new libunwind, updated to netbsd b1f513eedd
[minix3.git] / drivers / ti1225 / ti1225.c
blob7dd8ec4c00b8703a991ae499595904c16a08cdf5
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 <machine/vmparam.h>
12 #include <sys/mman.h>
14 #include "ti1225.h"
15 #include "i82365.h"
17 /* The use of interrupts is not yet ready for prime time */
18 #define USE_INTS 0
20 static struct port
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;
32 static int instance;
33 static int debug;
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);
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);
43 /*===========================================================================*
44 * main *
45 *===========================================================================*/
46 int main(int argc, char *argv[])
48 int r;
49 message m;
50 int ipc_status;
52 /* SEF local startup. */
53 env_setargs(argc, argv);
54 sef_local_startup();
56 for (;;)
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);
64 return 0;
67 /*===========================================================================*
68 * sef_local_startup *
69 *===========================================================================*/
70 static void sef_local_startup()
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);
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);
81 /* Let SEF perform startup. */
82 sef_startup();
85 /*===========================================================================*
86 * sef_cb_init_fresh *
87 *===========================================================================*/
88 static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
90 /* Initialize the ti1225 driver. */
91 int r, devind;
92 long v;
94 if((r=tsc_calibrate()) != OK)
95 panic("tsc_calibrate failed: %d", r);
97 v = 0;
98 (void) env_parse("instance", "d", 0, &v, 0, 255);
99 instance = (int) v;
101 v = 0;
102 (void) env_parse("debug", "d", 0, &v, 0, 1);
103 debug = (int) v;
105 devind = hw_probe(instance);
107 if (devind < 0)
108 return(ENODEV);
110 hw_init(&port, devind);
112 return(OK);
115 /*===========================================================================*
116 * hw_probe *
117 *===========================================================================*/
118 static int hw_probe(int skip)
120 u16_t vid, did;
121 int devind;
123 pci_init();
125 if (pci_first_dev(&devind, &vid, &did) != 1)
126 return(-1);
128 while (skip--)
129 if (pci_next_dev(&devind, &vid, &did) != 1)
130 return(-1);
132 pci_reserve(devind);
134 if (debug)
135 printf("ti1225: found device %04x/%04x\n", vid, did);
137 return(devind);
140 /*===========================================================================*
141 * hw_init *
142 *===========================================================================*/
143 static void hw_init(struct port *pp, int devind)
145 u8_t v8;
146 u16_t v16;
147 u32_t v32;
148 #if USE_INTS
149 int r, irq;
150 #endif
152 pp->p_devind= devind;
153 if (debug)
154 printf("hw_init: devind = %d\n", devind);
156 if (debug)
158 v16= pci_attr_r16(devind, PCI_CR);
159 printf("ti1225: command register 0x%x\n", v16);
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 */
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");
172 if (debug)
174 v8= pci_attr_r8(devind, TI_PCI_BUS_NR);
175 printf("ti1225: PCI bus number %d\n", v8);
177 v8= pci_attr_r8(devind, TI_CB_BUS_NR);
178 pp->p_cb_busnr= v8;
179 if (debug)
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);
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
192 v32= pci_attr_r32(devind, TI_LEGACY_BA);
193 v32 &= ~1;
194 if (debug)
196 printf("ti1225: PC Card 16-bit legacy-mode base address 0x%x\n",
197 v32);
200 if (v32 == 0)
201 panic("bad legacy-mode base address: %d", v32);
202 pp->p_exca_port= v32;
204 if (debug)
206 v32= pci_attr_r32(devind, TI_MF_ROUTE);
207 printf("ti1225: Multifunction routing 0x%08x\n", v32);
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
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);
224 if (debug)
226 v32= pci_attr_r32(devind, TI_SYSCTRL);
227 printf("ti1225: System Control Register 0x%08x\n", v32);
229 v8= pci_attr_r8(devind, TI_CARD_CTRL);
230 printf("ti1225: Card Control 0x%02x\n", v8);
232 v8= pci_attr_r8(devind, TI_DEV_CTRL);
233 printf("ti1225: Device Control 0x%02x\n", v8);
236 /* Enable socket interrupts */
237 pp->csr_ptr->csr_mask |= CM_PWRMASK | CM_CDMASK | CM_CSTSMASK;
239 do_int(pp);
241 #if USE_INTS
242 r= sys_irqenable(&pp->p_hook);
243 if (r != OK)
244 panic("unable enable interrupts: %d", r);
245 #endif
248 /*===========================================================================*
249 * do_int *
250 *===========================================================================*/
251 static void do_int(struct port *pp)
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
263 devind= pp->p_devind;
264 v8= pci_attr_r8(devind, TI_CARD_CTRL);
265 if (v8 & TI_CCR_IFG)
267 printf("ti1225: got functional interrupt\n");
268 pci_attr_w8(devind, TI_CARD_CTRL, v8);
271 if (debug)
273 printf("Socket event: 0x%x\n", pp->csr_ptr->csr_event);
274 printf("Socket mask: 0x%x\n", pp->csr_ptr->csr_mask);
277 csr_present= pp->csr_ptr->csr_present;
278 csr_control= pp->csr_ptr->csr_control;
280 if ((csr_present & (CP_CDETECT1|CP_CDETECT2)) != 0)
282 if (debug)
283 printf("do_int: no card present\n");
284 return;
286 if (csr_present & CP_BADVCCREQ)
288 printf("do_int: Bad Vcc request\n");
289 /* return; */
291 if (csr_present & CP_DATALOST)
293 /* Do we care? */
294 if (debug)
295 printf("do_int: Data lost\n");
296 /* return; */
298 if (csr_present & CP_NOTACARD)
300 printf("do_int: Not a card\n");
301 return;
303 if (debug)
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");
310 if (csr_present & CP_PWRCYCLE)
312 if (debug)
313 printf("do_int: powered up\n");
314 return;
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)
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" : "");
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)
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" : "");
336 if (vcc_5v && socket_5v)
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");
343 else if (vcc_3v && socket_3v)
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");
350 else if (vcc_Xv && socket_Xv)
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");
356 else if (vcc_Yv && socket_Yv)
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");
362 else
364 printf("do_int: socket and card are not compatible\n");
365 return;
368 csr_event= pp->csr_ptr->csr_event;
369 if (csr_event)
371 if (debug)
372 printf("clearing socket event\n");
373 pp->csr_ptr->csr_event= csr_event;
374 if (debug)
376 printf("Socket event (cleared): 0x%x\n",
377 pp->csr_ptr->csr_event);
381 devind= pp->p_devind;
382 v8= pci_attr_r8(devind, TI_CARD_CTRL);
383 if (v8 & TI_CCR_IFG)
385 printf("ti1225: got functional interrupt\n");
386 pci_attr_w8(devind, TI_CARD_CTRL, v8);
389 if (debug)
391 v8= pci_attr_r8(devind, TI_CARD_CTRL);
392 printf("TI_CARD_CTRL: 0x%02x\n", v8);
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));
402 if (!(csr_present & CP_PWRCYCLE))
404 printf("do_int: not powered up?\n");
405 return;
408 /* Reset device */
409 v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
410 v16 |= CBB_BC_CRST;
411 pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
413 /* Wait one microsecond. Is this correct? What are the specs? */
414 micro_delay(1);
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);
421 /* Wait one microsecond after clearing the reset line. Is this
422 * correct? What are the specs?
424 micro_delay(1);
426 pci_rescan_bus(pp->p_cb_busnr);
428 #if USE_INTS
429 r= sys_irqenable(&pp->p_hook);
430 if (r != OK)
431 panic("unable enable interrupts: %d", r);
432 #endif