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