Annotation of sys/arch/arm/sa11x0/sa11xx_pcic.c, Revision 1.2
1.2 ! nbrk 1: /* $Id: sa11xx_pcic.c,v 1.1.1.1 2008/03/04 16:05:17 nbrk Exp $ */
1.1 nbrk 2: /*
3: * Copyright (c) 2001 IWAMOTO Toshihiro. All rights reserved.
4: * Copyright (c) 1997 Marc Horowitz. All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: * 3. All advertising materials mentioning features or use of this software
15: * must display the following acknowledgement:
16: * This product includes software developed by Marc Horowitz.
17: * 4. The name of the author may not be used to endorse or promote products
18: * derived from this software without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30: */
31:
32: /*
33: * Common code for SA-11x0 based PCMCIA modules.
34: */
35:
36: #include <sys/cdefs.h>
37:
38: #include <sys/types.h>
39: #include <sys/param.h>
40: #include <sys/systm.h>
41: #include <sys/device.h>
1.2 ! nbrk 42: //#include <sys/callout.h>
1.1 nbrk 43: #include <sys/kernel.h>
44: #include <sys/kthread.h>
45: #include <sys/malloc.h>
1.2 ! nbrk 46:
! 47: #include <sys/mutex.h>
! 48: #include <machine/bus.h>
! 49: #include <machine/intr.h>
1.1 nbrk 50:
51: #include <uvm/uvm.h>
52:
53: #include <dev/pcmcia/pcmciareg.h>
54: #include <dev/pcmcia/pcmciavar.h>
55: #include <dev/pcmcia/pcmciachip.h>
56:
57: #include <arm/sa11x0/sa11x0_reg.h>
58: #include <arm/sa11x0/sa11x0_var.h>
59: #include <arm/sa11x0/sa11xx_pcicreg.h>
60: #include <arm/sa11x0/sa11xx_pcicvar.h>
61:
62: static int sapcic_mem_alloc(pcmcia_chipset_handle_t, bus_size_t,
63: struct pcmcia_mem_handle *);
64: static void sapcic_mem_free(pcmcia_chipset_handle_t,
65: struct pcmcia_mem_handle *);
66: static int sapcic_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t,
67: bus_size_t, struct pcmcia_mem_handle *,
68: bus_addr_t *, int *);
69: static void sapcic_mem_unmap(pcmcia_chipset_handle_t, int);
70: static int sapcic_io_alloc(pcmcia_chipset_handle_t, bus_addr_t,
71: bus_size_t, bus_size_t,
72: struct pcmcia_io_handle *);
73: static void sapcic_io_free(pcmcia_chipset_handle_t,
74: struct pcmcia_io_handle *);
75: static int sapcic_io_map(pcmcia_chipset_handle_t, int,
76: bus_addr_t, bus_size_t,
77: struct pcmcia_io_handle *, int *);
78: static void sapcic_io_unmap(pcmcia_chipset_handle_t, int);
79: static void *sapcic_intr_establish(pcmcia_chipset_handle_t,
80: struct pcmcia_function *, int,
1.2 ! nbrk 81: int (*)(void *), void *, char *);
1.1 nbrk 82: static void sapcic_intr_disestablish(pcmcia_chipset_handle_t,
83: void *);
84: static void sapcic_socket_enable(pcmcia_chipset_handle_t);
85: static void sapcic_socket_disable(pcmcia_chipset_handle_t);
1.2 ! nbrk 86: //static void sapcic_socket_settype(pcmcia_chipset_handle_t, int);
! 87: //int sapcic_socket_detect(pcmcia_chipset_handle_t);
! 88: const char *sapcic_intr_string(pcmcia_chipset_handle_t pch, void *ih);
! 89:
1.1 nbrk 90:
91: static void sapcic_event_thread(void *);
92:
93: static void sapcic_delay(int, const char *);
94:
1.2 ! nbrk 95: #if (defined DEBUG) || (defined PCMCIADEBUG)
1.1 nbrk 96: #define DPRINTF(arg) printf arg
97: #else
98: #define DPRINTF(arg)
99: #endif
100:
101: struct pcmcia_chip_functions sa11x0_pcmcia_functions = {
102: sapcic_mem_alloc,
103: sapcic_mem_free,
104: sapcic_mem_map,
105: sapcic_mem_unmap,
106:
107: sapcic_io_alloc,
108: sapcic_io_free,
109: sapcic_io_map,
110: sapcic_io_unmap,
111:
112: sapcic_intr_establish,
113: sapcic_intr_disestablish,
1.2 ! nbrk 114: sapcic_intr_string,
1.1 nbrk 115:
116: sapcic_socket_enable,
1.2 ! nbrk 117: sapcic_socket_disable
1.1 nbrk 118: };
119:
120:
121: void
122: sapcic_kthread_create(void *arg)
123: {
124: struct sapcic_socket *so = arg;
125:
126: /* XXX attach card if already present */
127:
1.2 ! nbrk 128: mtx_init(&so->sc->sc_lock, IPL_NONE);
1.1 nbrk 129:
130: so->laststatus = (so->pcictag->read)(so, SAPCIC_STATUS_CARD);
131: if (so->laststatus == SAPCIC_CARD_VALID) {
132: printf("%s: card present\n",
133: so->sc->sc_dev.dv_xname);
134:
135: pcmcia_card_attach(so->pcmcia);
136: }
137:
1.2 ! nbrk 138: #if 0
1.1 nbrk 139: if (kthread_create(PRI_NONE, 0, NULL, sapcic_event_thread, so,
140: &so->event_thread, "%s,%d", so->sc->sc_dev.dv_xname, so->socket)) {
141: printf("%s: unable to create event thread for socket %d\n",
142: so->sc->sc_dev.dv_xname, so->socket);
143: panic("sapcic_kthread_create");
144: }
1.2 ! nbrk 145: #endif
! 146:
! 147: kthread_create_deferred(sapcic_event_thread, so);
! 148:
1.1 nbrk 149: }
150:
151: static void
152: sapcic_event_thread(void *arg)
153: {
154: struct sapcic_socket *so = arg;
155: int newstatus, s;
156:
157: while (so->shutdown == 0) {
158: /*
159: * Serialize event processing on the PCIC. We may
160: * sleep while we hold this lock.
161: */
1.2 ! nbrk 162: mtx_enter(&so->sc->sc_lock);
1.1 nbrk 163:
164: /* sleep .25s to be enqueued chatterling interrupts */
165: (void) tsleep(sapcic_event_thread, PWAIT, "pcicss", hz / 4);
166:
167: s = splhigh();
168: so->event = 0;
169:
170: /* we don't rely on interrupt type */
171: newstatus = (so->pcictag->read)(so, SAPCIC_STATUS_CARD);
172: splx(s);
173:
174: if (so->laststatus == newstatus) {
175: /*
176: * No events to process; release the PCIC lock.
177: */
1.2 ! nbrk 178: mtx_leave(&so->sc->sc_lock);
1.1 nbrk 179: (void) tsleep(&so->event, PWAIT, "pcicev", hz);
180: continue;
181: }
182:
183: so->laststatus = newstatus;
184: switch (newstatus) {
185: case SAPCIC_CARD_VALID:
186: printf("%s: insertion event\n",
187: so->sc->sc_dev.dv_xname);
188:
189: pcmcia_card_attach(so->pcmcia);
190: break;
191:
192: case SAPCIC_CARD_INVALID:
193: printf("%s: removal event\n",
194: so->sc->sc_dev.dv_xname);
195:
196: pcmcia_card_detach(so->pcmcia, DETACH_FORCE);
197: break;
198:
199: default:
200: panic("sapcic_event_thread: unknown status %d",
201: newstatus);
202: }
203:
1.2 ! nbrk 204: mtx_leave(&so->sc->sc_lock);
1.1 nbrk 205: }
206:
1.2 ! nbrk 207: //so->event_thread = NULL;
1.1 nbrk 208:
209: /* In case parent is waiting for us to exit. */
210: wakeup(so->sc);
211:
212: kthread_exit(0);
213: }
214:
215: static void
216: sapcic_delay(int timo, const char *wmesg)
217: {
1.2 ! nbrk 218: // tsleep(sapcic_delay, PWAIT, wmesg, roundup(timo * hz, 1000) / 1000);
! 219: delay(timo * 10);
1.1 nbrk 220: }
221:
222: int
223: sapcic_intr(void *arg)
224: {
225: struct sapcic_socket *so = arg;
226:
227: so->event++;
228: (so->pcictag->clear_intr)(so->socket);
229: wakeup(&so->event);
230: return 1;
231: }
232:
233: static int
234: sapcic_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size,
235: struct pcmcia_mem_handle *pmh)
236: {
237: struct sapcic_socket *so = pch;
238:
239: /* All we need is bus space tag */
240: memset(pmh, 0, sizeof(*pmh));
241: pmh->memt = so->sc->sc_iot;
242: return 0;
243: }
244:
245:
246: static void
247: sapcic_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *pmh)
248: {
249: }
250:
251: static int
252: sapcic_mem_map(pcmcia_chipset_handle_t pch, int kind, bus_addr_t card_addr,
253: bus_size_t size, struct pcmcia_mem_handle *pmh, bus_addr_t *offsetp,
254: int *windowp)
255: {
256: struct sapcic_socket *so = pch;
257: int error;
258: bus_addr_t pa;
259:
260: pa = trunc_page(card_addr);
261: *offsetp = card_addr - pa;
262: size = round_page(card_addr + size) - pa;
263: pmh->realsize = size;
264:
265: pa += SAPCIC_BASE_OFFSET;
266: pa += SAPCIC_SOCKET_OFFSET * so->socket;
267:
268: switch (kind & ~PCMCIA_WIDTH_MEM_MASK) {
269: case PCMCIA_MEM_ATTR:
270: pa += SAPCIC_ATTR_OFFSET;
271: break;
272: case PCMCIA_MEM_COMMON:
273: pa += SAPCIC_COMMON_OFFSET;
274: break;
275: default:
276: panic("sapcic_mem_map: bogus kind");
277: }
278:
279: error = bus_space_map(so->sc->sc_iot, pa, size, 0, &pmh->memh);
280: if (!error)
281: *windowp = (int)pmh->memh;
282: return error;
283: }
284:
285: static void
286: sapcic_mem_unmap(pcmcia_chipset_handle_t pch, int window)
287: {
288: struct sapcic_socket *so = pch;
289:
290: bus_space_unmap(so->sc->sc_iot, (bus_addr_t)window, 4096); /* XXX */
291: }
292:
293: static int
294: sapcic_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start,
295: bus_size_t size, bus_size_t align, struct pcmcia_io_handle *pih)
296: {
297: struct sapcic_socket *so = pch;
298: int error;
299: bus_addr_t pa;
300:
301: memset(pih, 0, sizeof(*pih));
302: pih->iot = so->sc->sc_iot;
303: pih->addr = start;
304: pih->size = size;
305:
306: pa = pih->addr;
307: pa += SAPCIC_BASE_OFFSET;
308: pa += SAPCIC_SOCKET_OFFSET * so->socket;
309:
310: DPRINTF(("sapcic_io_alloc: %x %x\n", (unsigned int)pa,
311: (unsigned int)size));
312: /* XXX Are we ignoring alignment constraints? */
313: error = bus_space_map(so->sc->sc_iot, pa, size, 0, &pih->ioh);
314:
315: return error;
316: }
317:
318: static void
319: sapcic_io_free(pcmcia_chipset_handle_t pch, struct pcmcia_io_handle *pih)
320: {
321: struct sapcic_socket *so = pch;
322:
323: bus_space_unmap(so->sc->sc_iot, pih->ioh, pih->size);
324: }
325:
326: static int
327: sapcic_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset,
328: bus_size_t size, struct pcmcia_io_handle *pih, int *windowp)
329: {
330:
331: return 0;
332: }
333:
334: static void sapcic_io_unmap(pcmcia_chipset_handle_t pch, int window)
335: {
336: }
337:
338: static void *
339: sapcic_intr_establish(pcmcia_chipset_handle_t pch, struct pcmcia_function *pf,
1.2 ! nbrk 340: int ipl, int (*fct)(void *), void *arg, char *str)
1.1 nbrk 341: {
342: struct sapcic_socket *so = pch;
343:
344: /* XXX need to check if something should be done here */
345:
346: return (so->pcictag->intr_establish)(so, ipl, fct, arg);
347: }
348:
349: static void
350: sapcic_intr_disestablish(pcmcia_chipset_handle_t pch, void *ih)
351: {
352: struct sapcic_socket *so = pch;
353:
354: (so->pcictag->intr_disestablish)(so, ih);
355: }
356:
357: static void
358: sapcic_socket_enable(pcmcia_chipset_handle_t pch)
359: {
360: struct sapcic_socket *so = pch;
361: int i;
362:
363: #if defined(DIAGNOSTIC) && defined(notyet)
364: if (so->flags & PCIC_FLAG_ENABLED)
365: printf("sapcic_socket_enable: enabling twice\n");
366: #endif
367:
368: /* disable interrupts */
369:
370: /* power down the socket to reset it, clear the card reset pin */
371: (so->pcictag->set_power)(so, SAPCIC_POWER_OFF);
372:
373: /*
374: * wait 300ms until power fails (Tpf). Then, wait 100ms since
375: * we are changing Vcc (Toff).
376: */
377: sapcic_delay(300 + 100, "pccen0");
1.2 ! nbrk 378: printf("sapcic_socket_enable: sapcic_delay\n");
1.1 nbrk 379:
380: /* power up the socket */
381: /* XXX voltage selection should be done in PCMCIA code */
382: if (so->power_capability & SAPCIC_POWER_5V) {
383: (so->pcictag->set_power)(so, SAPCIC_POWER_5V);
384: (so->pcictag->write)(so, SAPCIC_CONTROL_POWERSELECT,
385: SAPCIC_POWER_5V);
386: } else {
387: (so->pcictag->set_power)(so, SAPCIC_POWER_3V);
388: (so->pcictag->write)(so, SAPCIC_CONTROL_POWERSELECT,
389: SAPCIC_POWER_3V);
390: }
391:
392: /* enable PCMCIA control lines */
393: (so->pcictag->write)(so, SAPCIC_CONTROL_LINEENABLE, 1);
394:
395: /*
396: * wait 100ms until power raise (Tpr) and 20ms to become
397: * stable (Tsu(Vcc)).
398: *
399: * some machines require some more time to be settled
400: * (300ms is added here).
401: */
402: sapcic_delay(100 + 20 + 300, "pccen1");
403:
404: /* honor nWAIT signal */
405: (so->pcictag->write)(so, SAPCIC_CONTROL_WAITENABLE, 1);
406: /* now make sure we have reset# active */
407: (so->pcictag->write)(so, SAPCIC_CONTROL_RESET, 1);
408:
409: /*
410: * hold RESET at least 10us, this is a min allow for slop in
411: * delay routine.
412: */
413: delay(20);
414:
415: /* clear the reset flag */
416: (so->pcictag->write)(so, SAPCIC_CONTROL_RESET, 0);
417:
418: /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
419: sapcic_delay(20, "pccen2");
420:
421: /* wait for the chip to finish initializing */
422: sapcic_delay(10, "pccen3");
423: for (i = 100; i; i--) {
424: if ((so->pcictag->read)(so, SAPCIC_STATUS_READY))
425: break;
426: sapcic_delay(100, "pccen4");
427: }
428: DPRINTF(("sapcic_socket_enable: wait ready %d\n", 100 - i));
429:
430: /* finally enable the interrupt */
431:
432: }
433:
434: static void
435: sapcic_socket_disable(pcmcia_chipset_handle_t pch)
436: {
437: struct sapcic_socket *so = pch;
438:
439: /* XXX mask card interrupts */
440:
441: /* power down the card */
442: (so->pcictag->set_power)(so, SAPCIC_POWER_OFF);
443:
444: /* float controller lines */
445: (so->pcictag->write)(so, SAPCIC_CONTROL_LINEENABLE, 0);
446: }
447:
1.2 ! nbrk 448: #if 0
1.1 nbrk 449: static void
450: sapcic_socket_settype(pcmcia_chipset_handle_t pch, int type)
451: {
452:
453: /* XXX nothing to do */
454: }
1.2 ! nbrk 455: #endif
! 456:
! 457: #if 0
! 458: int
! 459: sapcic_socket_detect(pcmcia_chipset_handle_t pch)
! 460: {
! 461: /* TODO */
! 462: return (0);
! 463: }
! 464: #endif
! 465:
! 466: const char *
! 467: sapcic_intr_string(pcmcia_chipset_handle_t pch, void *ih)
! 468: {
! 469: // return (sa11x0_gpio_intr_string(ih));
! 470: return ("(sapcic_intr_string)");
! 471: }
! 472:
! 473:
CVSweb