xref: /minix/minix/drivers/bus/ti1225/ti1225.c (revision 433d6423)
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