1 /* 2 ti1225.c 3 4 Created: Dec 2005 by Philip Homburg 5 */ 6 7 #include <minix/drivers.h> 8 #include <minix/driver.h> 9 #include <machine/pci.h> 10 #include <machine/vm.h> 11 #include <machine/vmparam.h> 12 #include <sys/mman.h> 13 14 #include "ti1225.h" 15 #include "i82365.h" 16 17 /* The use of interrupts is not yet ready for prime time */ 18 #define USE_INTS 0 19 20 static struct port 21 { 22 int p_devind; 23 u8_t p_cb_busnr; 24 u16_t p_exca_port; 25 #if USE_INTS 26 int p_irq; 27 int p_hook; 28 #endif 29 volatile struct csr *csr_ptr; 30 } port; 31 32 static int instance; 33 static int debug; 34 35 static int hw_probe(int skip); 36 static void hw_init(struct port *pp, int devind); 37 static void do_int(struct port *pp); 38 39 /* SEF functions and variables. */ 40 static void sef_local_startup(void); 41 static int sef_cb_init_fresh(int type, sef_init_info_t *info); 42 43 /*===========================================================================* 44 * main * 45 *===========================================================================*/ 46 int main(int argc, char *argv[]) 47 { 48 int r; 49 message m; 50 int ipc_status; 51 52 /* SEF local startup. */ 53 env_setargs(argc, argv); 54 sef_local_startup(); 55 56 for (;;) 57 { 58 r= driver_receive(ANY, &m, &ipc_status); 59 if (r != OK) 60 panic("driver_receive failed: %d", r); 61 printf("ti1225: got message %u from %d\n", 62 m.m_type, m.m_source); 63 } 64 return 0; 65 } 66 67 /*===========================================================================* 68 * sef_local_startup * 69 *===========================================================================*/ 70 static void sef_local_startup() 71 { 72 /* Register init callbacks. */ 73 sef_setcb_init_fresh(sef_cb_init_fresh); 74 sef_setcb_init_lu(sef_cb_init_fresh); 75 sef_setcb_init_restart(sef_cb_init_fresh); 76 77 /* Register live update callbacks. */ 78 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready); 79 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard); 80 81 /* Let SEF perform startup. */ 82 sef_startup(); 83 } 84 85 /*===========================================================================* 86 * sef_cb_init_fresh * 87 *===========================================================================*/ 88 static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) 89 { 90 /* Initialize the ti1225 driver. */ 91 int r, devind; 92 long v; 93 94 if((r=tsc_calibrate()) != OK) 95 panic("tsc_calibrate failed: %d", r); 96 97 v = 0; 98 (void) env_parse("instance", "d", 0, &v, 0, 255); 99 instance = (int) v; 100 101 v = 0; 102 (void) env_parse("debug", "d", 0, &v, 0, 1); 103 debug = (int) v; 104 105 devind = hw_probe(instance); 106 107 if (devind < 0) 108 return(ENODEV); 109 110 hw_init(&port, devind); 111 112 return(OK); 113 } 114 115 /*===========================================================================* 116 * hw_probe * 117 *===========================================================================*/ 118 static int hw_probe(int skip) 119 { 120 u16_t vid, did; 121 int devind; 122 123 pci_init(); 124 125 if (pci_first_dev(&devind, &vid, &did) != 1) 126 return(-1); 127 128 while (skip--) 129 if (pci_next_dev(&devind, &vid, &did) != 1) 130 return(-1); 131 132 pci_reserve(devind); 133 134 if (debug) 135 printf("ti1225: found device %04x/%04x\n", vid, did); 136 137 return(devind); 138 } 139 140 /*===========================================================================* 141 * hw_init * 142 *===========================================================================*/ 143 static void hw_init(struct port *pp, int devind) 144 { 145 u8_t v8; 146 u16_t v16; 147 u32_t v32; 148 #if USE_INTS 149 int r, irq; 150 #endif 151 152 pp->p_devind= devind; 153 if (debug) 154 printf("hw_init: devind = %d\n", devind); 155 156 if (debug) 157 { 158 v16= pci_attr_r16(devind, PCI_CR); 159 printf("ti1225: command register 0x%x\n", v16); 160 } 161 162 v32= pci_attr_r32(devind, TI_CB_BASEADDR); 163 if (debug) 164 printf("ti1225: Cardbus/ExCA base address 0x%x\n", v32); 165 v32 &= PCI_BAR_MEM_MASK; /* Clear low order bits in base */ 166 167 pp->csr_ptr= 168 (struct csr *) vm_map_phys(SELF, (void *) v32, PAGE_SIZE); 169 if (pp->csr_ptr == MAP_FAILED) 170 panic("hw_init: vm_map_phys failed"); 171 172 if (debug) 173 { 174 v8= pci_attr_r8(devind, TI_PCI_BUS_NR); 175 printf("ti1225: PCI bus number %d\n", v8); 176 } 177 v8= pci_attr_r8(devind, TI_CB_BUS_NR); 178 pp->p_cb_busnr= v8; 179 if (debug) 180 { 181 printf("ti1225: CardBus bus number %d\n", v8); 182 v8= pci_attr_r8(devind, TI_SO_BUS_NR); 183 printf("ti1225: Subordinate bus number %d\n", v8); 184 } 185 186 #if USE_INTS 187 irq= pci_attr_r8(devind, PCI_ILR); 188 pp->p_irq= irq; 189 printf("ti1225 using IRQ %d\n", irq); 190 #endif 191 192 v32= pci_attr_r32(devind, TI_LEGACY_BA); 193 v32 &= ~1; 194 if (debug) 195 { 196 printf("ti1225: PC Card 16-bit legacy-mode base address 0x%x\n", 197 v32); 198 } 199 200 if (v32 == 0) 201 panic("bad legacy-mode base address: %d", v32); 202 pp->p_exca_port= v32; 203 204 if (debug) 205 { 206 v32= pci_attr_r32(devind, TI_MF_ROUTE); 207 printf("ti1225: Multifunction routing 0x%08x\n", v32); 208 } 209 210 #if USE_INTS 211 pp->p_hook = pp->p_irq; 212 r= sys_irqsetpolicy(pp->p_irq, 0, &pp->p_hook); 213 if (r != OK) 214 panic("sys_irqsetpolicy failed: %d", r); 215 #endif 216 217 /* Clear CBB_BC_INTEXCA */ 218 v16= pci_attr_r16(devind, CBB_BRIDGECTRL); 219 if (debug) 220 printf("ti1225: Bridge control 0x%04x\n", v16); 221 v16 &= ~CBB_BC_INTEXCA; 222 pci_attr_w16(devind, CBB_BRIDGECTRL, v16); 223 224 if (debug) 225 { 226 v32= pci_attr_r32(devind, TI_SYSCTRL); 227 printf("ti1225: System Control Register 0x%08x\n", v32); 228 229 v8= pci_attr_r8(devind, TI_CARD_CTRL); 230 printf("ti1225: Card Control 0x%02x\n", v8); 231 232 v8= pci_attr_r8(devind, TI_DEV_CTRL); 233 printf("ti1225: Device Control 0x%02x\n", v8); 234 } 235 236 /* Enable socket interrupts */ 237 pp->csr_ptr->csr_mask |= CM_PWRMASK | CM_CDMASK | CM_CSTSMASK; 238 239 do_int(pp); 240 241 #if USE_INTS 242 r= sys_irqenable(&pp->p_hook); 243 if (r != OK) 244 panic("unable enable interrupts: %d", r); 245 #endif 246 } 247 248 /*===========================================================================* 249 * do_int * 250 *===========================================================================*/ 251 static void do_int(struct port *pp) 252 { 253 int devind, vcc_5v, vcc_3v, vcc_Xv, vcc_Yv, 254 socket_5v, socket_3v, socket_Xv, socket_Yv; 255 spin_t spin; 256 u32_t csr_event, csr_present, csr_control; 257 u8_t v8; 258 u16_t v16; 259 #if USE_INTS 260 int r; 261 #endif 262 263 devind= pp->p_devind; 264 v8= pci_attr_r8(devind, TI_CARD_CTRL); 265 if (v8 & TI_CCR_IFG) 266 { 267 printf("ti1225: got functional interrupt\n"); 268 pci_attr_w8(devind, TI_CARD_CTRL, v8); 269 } 270 271 if (debug) 272 { 273 printf("Socket event: 0x%x\n", pp->csr_ptr->csr_event); 274 printf("Socket mask: 0x%x\n", pp->csr_ptr->csr_mask); 275 } 276 277 csr_present= pp->csr_ptr->csr_present; 278 csr_control= pp->csr_ptr->csr_control; 279 280 if ((csr_present & (CP_CDETECT1|CP_CDETECT2)) != 0) 281 { 282 if (debug) 283 printf("do_int: no card present\n"); 284 return; 285 } 286 if (csr_present & CP_BADVCCREQ) 287 { 288 printf("do_int: Bad Vcc request\n"); 289 /* return; */ 290 } 291 if (csr_present & CP_DATALOST) 292 { 293 /* Do we care? */ 294 if (debug) 295 printf("do_int: Data lost\n"); 296 /* return; */ 297 } 298 if (csr_present & CP_NOTACARD) 299 { 300 printf("do_int: Not a card\n"); 301 return; 302 } 303 if (debug) 304 { 305 if (csr_present & CP_CBCARD) 306 printf("do_int: Cardbus card detected\n"); 307 if (csr_present & CP_16BITCARD) 308 printf("do_int: 16-bit card detected\n"); 309 } 310 if (csr_present & CP_PWRCYCLE) 311 { 312 if (debug) 313 printf("do_int: powered up\n"); 314 return; 315 } 316 vcc_5v= !!(csr_present & CP_5VCARD); 317 vcc_3v= !!(csr_present & CP_3VCARD); 318 vcc_Xv= !!(csr_present & CP_XVCARD); 319 vcc_Yv= !!(csr_present & CP_YVCARD); 320 if (debug) 321 { 322 printf("do_int: card supports:%s%s%s%s\n", 323 vcc_5v ? " 5V" : "", vcc_3v ? " 3V" : "", 324 vcc_Xv ? " X.X V" : "", vcc_Yv ? " Y.Y V" : ""); 325 } 326 socket_5v= !!(csr_present & CP_5VSOCKET); 327 socket_3v= !!(csr_present & CP_3VSOCKET); 328 socket_Xv= !!(csr_present & CP_XVSOCKET); 329 socket_Yv= !!(csr_present & CP_YVSOCKET); 330 if (debug) 331 { 332 printf("do_int: socket supports:%s%s%s%s\n", 333 socket_5v ? " 5V" : "", socket_3v ? " 3V" : "", 334 socket_Xv ? " X.X V" : "", socket_Yv ? " Y.Y V" : ""); 335 } 336 if (vcc_5v && socket_5v) 337 { 338 csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_5V; 339 pp->csr_ptr->csr_control= csr_control; 340 if (debug) 341 printf("do_int: applying 5V\n"); 342 } 343 else if (vcc_3v && socket_3v) 344 { 345 csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_3V; 346 pp->csr_ptr->csr_control= csr_control; 347 if (debug) 348 printf("do_int: applying 3V\n"); 349 } 350 else if (vcc_Xv && socket_Xv) 351 { 352 csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_XV; 353 pp->csr_ptr->csr_control= csr_control; 354 printf("do_int: applying X.X V\n"); 355 } 356 else if (vcc_Yv && socket_Yv) 357 { 358 csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_YV; 359 pp->csr_ptr->csr_control= csr_control; 360 printf("do_int: applying Y.Y V\n"); 361 } 362 else 363 { 364 printf("do_int: socket and card are not compatible\n"); 365 return; 366 } 367 368 csr_event= pp->csr_ptr->csr_event; 369 if (csr_event) 370 { 371 if (debug) 372 printf("clearing socket event\n"); 373 pp->csr_ptr->csr_event= csr_event; 374 if (debug) 375 { 376 printf("Socket event (cleared): 0x%x\n", 377 pp->csr_ptr->csr_event); 378 } 379 } 380 381 devind= pp->p_devind; 382 v8= pci_attr_r8(devind, TI_CARD_CTRL); 383 if (v8 & TI_CCR_IFG) 384 { 385 printf("ti1225: got functional interrupt\n"); 386 pci_attr_w8(devind, TI_CARD_CTRL, v8); 387 } 388 389 if (debug) 390 { 391 v8= pci_attr_r8(devind, TI_CARD_CTRL); 392 printf("TI_CARD_CTRL: 0x%02x\n", v8); 393 } 394 395 spin_init(&spin, 100000); 396 do { 397 csr_present= pp->csr_ptr->csr_present; 398 if (csr_present & CP_PWRCYCLE) 399 break; 400 } while (spin_check(&spin)); 401 402 if (!(csr_present & CP_PWRCYCLE)) 403 { 404 printf("do_int: not powered up?\n"); 405 return; 406 } 407 408 /* Reset device */ 409 v16= pci_attr_r16(devind, CBB_BRIDGECTRL); 410 v16 |= CBB_BC_CRST; 411 pci_attr_w16(devind, CBB_BRIDGECTRL, v16); 412 413 /* Wait one microsecond. Is this correct? What are the specs? */ 414 micro_delay(1); 415 416 /* Clear CBB_BC_CRST */ 417 v16= pci_attr_r16(devind, CBB_BRIDGECTRL); 418 v16 &= ~CBB_BC_CRST; 419 pci_attr_w16(devind, CBB_BRIDGECTRL, v16); 420 421 /* Wait one microsecond after clearing the reset line. Is this 422 * correct? What are the specs? 423 */ 424 micro_delay(1); 425 426 pci_rescan_bus(pp->p_cb_busnr); 427 428 #if USE_INTS 429 r= sys_irqenable(&pp->p_hook); 430 if (r != OK) 431 panic("unable enable interrupts: %d", r); 432 #endif 433 434 } 435 436