Annotation of sys/arch/arm/xscale/pxa2x0_gpio.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: pxa2x0_gpio.c,v 1.18 2005/06/16 21:57:29 drahn Exp $ */
2: /* $NetBSD: pxa2x0_gpio.c,v 1.2 2003/07/15 00:24:55 lukem Exp $ */
3:
4: /*
5: * Copyright 2003 Wasabi Systems, Inc.
6: * All rights reserved.
7: *
8: * Written by Steve C. Woodford for Wasabi Systems, Inc.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed for the NetBSD Project by
21: * Wasabi Systems, Inc.
22: * 4. The name of Wasabi Systems, Inc. may not be used to endorse
23: * or promote products derived from this software without specific prior
24: * written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: * POSSIBILITY OF SUCH DAMAGE.
37: */
38:
39: #include <sys/cdefs.h>
40: /*
41: __KERNEL_RCSID(0, "$NetBSD: pxa2x0_gpio.c,v 1.2 2003/07/15 00:24:55 lukem Exp $");
42: */
43:
44: #include <sys/param.h>
45: #include <sys/systm.h>
46: #include <sys/device.h>
47: #include <sys/malloc.h>
48: #include <sys/evcount.h>
49:
50: #include <machine/intr.h>
51: #include <machine/bus.h>
52:
53: #include <arm/cpufunc.h>
54:
55: #include <arm/xscale/pxa2x0reg.h>
56: #include <arm/xscale/pxa2x0var.h>
57: #include <arm/xscale/pxa2x0_gpio.h>
58:
59: struct gpio_irq_handler {
60: struct gpio_irq_handler *gh_next;
61: int (*gh_func)(void *);
62: void *gh_arg;
63: int gh_spl;
64: u_int gh_gpio;
65: int gh_level;
66: int gh_irq;
67: struct evcount gh_count;
68: };
69:
70: struct pxagpio_softc {
71: struct device sc_dev;
72: bus_space_tag_t sc_bust;
73: bus_space_handle_t sc_bush;
74: void *sc_irqcookie[4];
75: u_int32_t sc_mask[3];
76: #ifdef PXAGPIO_HAS_GPION_INTRS
77: struct gpio_irq_handler *sc_handlers[GPIO_NPINS];
78: int sc_minipl;
79: int sc_maxipl;
80: #else
81: struct gpio_irq_handler *sc_handlers[2];
82: #endif
83: int npins;
84: int pxa27x_pins;
85: };
86:
87: int pxagpio_match(struct device *, void *, void *);
88: void pxagpio_attach(struct device *, struct device *, void *);
89:
90: #ifdef __NetBSD__
91: CFATTACH_DECL(pxagpio, sizeof(struct pxagpio_softc),
92: pxagpio_match, pxagpio_attach, NULL, NULL);
93: #else
94: struct cfattach pxagpio_ca = {
95: sizeof (struct pxagpio_softc), pxagpio_match, pxagpio_attach
96: };
97:
98: struct cfdriver pxagpio_cd = {
99: NULL, "pxagpio", DV_DULL
100: };
101:
102: #endif
103:
104: static struct pxagpio_softc *pxagpio_softc;
105: static vaddr_t pxagpio_regs;
106: #define GPIO_BOOTSTRAP_REG(reg) \
107: (*((volatile u_int32_t *)(pxagpio_regs + (reg))))
108:
109: void pxa2x0_gpio_set_intr_level(u_int, int);
110: int pxagpio_intr0(void *);
111: int pxagpio_intr1(void *);
112: #ifdef PXAGPIO_HAS_GPION_INTRS
113: int pxagpio_dispatch(struct pxagpio_softc *, int);
114: int pxagpio_intrN(void *);
115: int pxagpio_intrlow(void *);
116: void pxa2x0_gpio_intr_fixup(int minipl, int maxipl);
117: #endif
118: u_int32_t pxagpio_reg_read(struct pxagpio_softc *sc, int reg);
119: void pxagpio_reg_write(struct pxagpio_softc *sc, int reg, u_int32_t val);
120:
121: u_int32_t
122: pxagpio_reg_read(struct pxagpio_softc *sc, int reg)
123: {
124: if (__predict_true(sc != NULL))
125: return (bus_space_read_4(sc->sc_bust, sc->sc_bush, reg));
126: else
127: if (pxagpio_regs)
128: return (GPIO_BOOTSTRAP_REG(reg));
129: panic("pxagpio_reg_read: not bootstrapped");
130: }
131:
132: void
133: pxagpio_reg_write(struct pxagpio_softc *sc, int reg, u_int32_t val)
134: {
135: if (__predict_true(sc != NULL))
136: bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, val);
137: else
138: if (pxagpio_regs)
139: GPIO_BOOTSTRAP_REG(reg) = val;
140: else
141: panic("pxagpio_reg_write: not bootstrapped");
142: return;
143: }
144:
145: int
146: pxagpio_match(struct device *parent, void *cf, void *aux)
147: {
148: struct pxaip_attach_args *pxa = aux;
149:
150: if (pxagpio_softc != NULL || pxa->pxa_addr != PXA2X0_GPIO_BASE)
151: return (0);
152:
153: pxa->pxa_size = PXA2X0_GPIO_SIZE;
154:
155: return (1);
156: }
157:
158: void
159: pxagpio_attach(struct device *parent, struct device *self, void *aux)
160: {
161: struct pxagpio_softc *sc = (struct pxagpio_softc *)self;
162: struct pxaip_attach_args *pxa = aux;
163:
164: sc->sc_bust = pxa->pxa_iot;
165:
166: printf(": GPIO Controller\n");
167:
168: if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X) {
169: sc->npins = GPIO_NPINS;
170: sc->pxa27x_pins = 1;
171: } else {
172: sc->npins = GPIO_NPINS_25x;
173: sc->pxa27x_pins = 0;
174: }
175:
176: if (bus_space_map(sc->sc_bust, pxa->pxa_addr, pxa->pxa_size, 0,
177: &sc->sc_bush)) {
178: printf("%s: Can't map registers!\n", sc->sc_dev.dv_xname);
179: return;
180: }
181:
182: memset(sc->sc_handlers, 0, sizeof(sc->sc_handlers));
183:
184: /*
185: * Disable all GPIO interrupts
186: */
187: pxagpio_reg_write(sc, GPIO_GRER0, 0);
188: pxagpio_reg_write(sc, GPIO_GRER1, 0);
189: pxagpio_reg_write(sc, GPIO_GRER2, 0);
190: pxagpio_reg_write(sc, GPIO_GRER3, 0);
191: pxagpio_reg_write(sc, GPIO_GFER0, 0);
192: pxagpio_reg_write(sc, GPIO_GFER1, 0);
193: pxagpio_reg_write(sc, GPIO_GFER2, 0);
194: pxagpio_reg_write(sc, GPIO_GFER3, 0);
195: pxagpio_reg_write(sc, GPIO_GEDR0, ~0);
196: pxagpio_reg_write(sc, GPIO_GEDR1, ~0);
197: pxagpio_reg_write(sc, GPIO_GEDR2, ~0);
198: pxagpio_reg_write(sc, GPIO_GEDR3, ~0);
199:
200: #ifdef PXAGPIO_HAS_GPION_INTRS
201: sc->sc_minipl = IPL_NONE;
202: sc->sc_maxipl = IPL_NONE;
203: #endif
204:
205: sc->sc_irqcookie[0] = sc->sc_irqcookie[1] = NULL;
206:
207: pxagpio_softc = sc;
208: }
209:
210: void
211: pxa2x0_gpio_bootstrap(vaddr_t gpio_regs)
212: {
213:
214: pxagpio_regs = gpio_regs;
215: }
216:
217: void *
218: pxa2x0_gpio_intr_establish(u_int gpio, int level, int spl, int (*func)(void *),
219: void *arg, char *name)
220: {
221: struct pxagpio_softc *sc = pxagpio_softc;
222: struct gpio_irq_handler *gh;
223: u_int32_t bit;
224:
225: #ifdef DEBUG
226: #ifdef PXAGPIO_HAS_GPION_INTRS
227: if (gpio >= sc->npins)
228: panic("pxa2x0_gpio_intr_establish: bad pin number: %d", gpio);
229: #else
230: if (gpio > 1)
231: panic("pxa2x0_gpio_intr_establish: bad pin number: %d", gpio);
232: #endif
233: #endif
234:
235: if (GPIO_FN_IS_OUT(pxa2x0_gpio_get_function(gpio)) != GPIO_IN)
236: panic("pxa2x0_gpio_intr_establish: Pin %d not GPIO_IN", gpio);
237:
238: MALLOC(gh, struct gpio_irq_handler *, sizeof(struct gpio_irq_handler),
239: M_DEVBUF, M_NOWAIT);
240:
241: gh->gh_func = func;
242: gh->gh_arg = arg;
243: gh->gh_spl = spl;
244: gh->gh_gpio = gpio;
245: gh->gh_irq = gpio+32;
246: gh->gh_level = level;
247: evcount_attach(&gh->gh_count, name, (void *)&gh->gh_irq, &evcount_intr);
248:
249: gh->gh_next = sc->sc_handlers[gpio];
250: sc->sc_handlers[gpio] = gh;
251:
252: if (gpio == 0) {
253: KDASSERT(sc->sc_irqcookie[0] == NULL);
254: sc->sc_irqcookie[0] = pxa2x0_intr_establish(PXA2X0_INT_GPIO0,
255: spl, pxagpio_intr0, sc, NULL);
256: KDASSERT(sc->sc_irqcookie[0]);
257: } else if (gpio == 1) {
258: KDASSERT(sc->sc_irqcookie[1] == NULL);
259: sc->sc_irqcookie[1] = pxa2x0_intr_establish(PXA2X0_INT_GPIO1,
260: spl, pxagpio_intr1, sc, NULL);
261: KDASSERT(sc->sc_irqcookie[1]);
262: } else {
263: #ifdef PXAGPIO_HAS_GPION_INTRS
264: int minipl, maxipl;
265:
266: if (sc->sc_maxipl == IPL_NONE || spl > sc->sc_maxipl) {
267: maxipl = spl;
268: } else {
269: maxipl = sc->sc_maxipl;
270: }
271:
272:
273: if (sc->sc_minipl == IPL_NONE || spl < sc->sc_minipl) {
274: minipl = spl;
275: } else {
276: minipl = sc->sc_minipl;
277: }
278: pxa2x0_gpio_intr_fixup(minipl, maxipl);
279: #endif
280: }
281:
282: bit = GPIO_BIT(gpio);
283: sc->sc_mask[GPIO_BANK(gpio)] |= bit;
284:
285: pxa2x0_gpio_set_intr_level(gpio, gh->gh_level);
286:
287: return (gh);
288: }
289:
290: void
291: pxa2x0_gpio_intr_disestablish(void *cookie)
292: {
293: struct pxagpio_softc *sc = pxagpio_softc;
294: struct gpio_irq_handler *gh = cookie;
295: u_int32_t bit, reg;
296:
297: evcount_detach(&gh->gh_count);
298:
299: bit = GPIO_BIT(gh->gh_gpio);
300:
301: reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GFER0, gh->gh_gpio));
302: reg &= ~bit;
303: pxagpio_reg_write(sc, GPIO_REG(GPIO_GFER0, gh->gh_gpio), reg);
304: reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GRER0, gh->gh_gpio));
305: reg &= ~bit;
306: pxagpio_reg_write(sc, GPIO_REG(GPIO_GRER0, gh->gh_gpio), reg);
307:
308: pxagpio_reg_write(sc, GPIO_REG(GPIO_GEDR0, gh->gh_gpio), bit);
309:
310: sc->sc_mask[GPIO_BANK(gh->gh_gpio)] &= ~bit;
311: sc->sc_handlers[gh->gh_gpio] = NULL;
312:
313: if (gh->gh_gpio == 0) {
314: pxa2x0_intr_disestablish(sc->sc_irqcookie[0]);
315: sc->sc_irqcookie[0] = NULL;
316: } else if (gh->gh_gpio == 1) {
317: pxa2x0_intr_disestablish(sc->sc_irqcookie[1]);
318: sc->sc_irqcookie[1] = NULL;
319: } else {
320: #ifdef PXAGPIO_HAS_GPION_INTRS
321: int i, minipl, maxipl, ipl;
322: minipl = IPL_HIGH;
323: maxipl = IPL_NONE;
324: for (i = 2; i < sc->npins; i++) {
325: if (sc->sc_handlers[i] != NULL) {
326: ipl = sc->sc_handlers[i]->gh_spl;
327: if (minipl > ipl)
328: minipl = ipl;
329:
330: if (maxipl < ipl)
331: maxipl = ipl;
332: }
333: }
334: pxa2x0_gpio_intr_fixup(minipl, maxipl);
335: #endif /* PXAGPIO_HAS_GPION_INTRS */
336: }
337:
338: FREE(gh, M_DEVBUF);
339: }
340:
341: #ifdef PXAGPIO_HAS_GPION_INTRS
342: void
343: pxa2x0_gpio_intr_fixup(int minipl, int maxipl)
344: {
345: struct pxagpio_softc *sc = pxagpio_softc;
346: int save = disable_interrupts(I32_bit);
347:
348: if (maxipl == IPL_NONE && minipl == IPL_HIGH) {
349: /* no remaining interrupts */
350: if (sc->sc_irqcookie[2])
351: pxa2x0_intr_disestablish(sc->sc_irqcookie[2]);
352: sc->sc_irqcookie[2] = NULL;
353: if (sc->sc_irqcookie[3])
354: pxa2x0_intr_disestablish(sc->sc_irqcookie[3]);
355: sc->sc_irqcookie[3] = NULL;
356: sc->sc_minipl = IPL_NONE;
357: sc->sc_maxipl = IPL_NONE;
358: restore_interrupts(save);
359: return;
360: }
361:
362: if (sc->sc_maxipl == IPL_NONE || maxipl > sc->sc_maxipl) {
363: if (sc->sc_irqcookie[2])
364: pxa2x0_intr_disestablish(sc->sc_irqcookie[2]);
365:
366: sc->sc_maxipl = maxipl;
367: sc->sc_irqcookie[2] =
368: pxa2x0_intr_establish(PXA2X0_INT_GPION,
369: maxipl, pxagpio_intrN, sc, NULL);
370:
371: if (sc->sc_irqcookie[2] == NULL) {
372: printf("%s: failed to hook main "
373: "GPIO interrupt\n",
374: sc->sc_dev.dv_xname);
375: /* XXX - panic? */
376: }
377: }
378: if (sc->sc_minipl == IPL_NONE || minipl < sc->sc_minipl) {
379: if (sc->sc_irqcookie[3])
380: pxa2x0_intr_disestablish(sc->sc_irqcookie[3]);
381:
382: sc->sc_minipl = minipl;
383: sc->sc_irqcookie[3] =
384: pxa2x0_intr_establish(PXA2X0_INT_GPION,
385: sc->sc_minipl, pxagpio_intrlow, sc, NULL);
386:
387: if (sc->sc_irqcookie[3] == NULL) {
388: printf("%s: failed to hook main "
389: "GPIO interrupt\n",
390: sc->sc_dev.dv_xname);
391: /* XXX - panic? */
392: }
393: }
394: restore_interrupts(save);
395: }
396: #endif /* PXAGPIO_HAS_GPION_INTRS */
397:
398: const char *
399: pxa2x0_gpio_intr_string(void *cookie)
400: {
401: static char irqstr[32];
402: struct gpio_irq_handler *gh = cookie;
403:
404: if (gh == NULL)
405: snprintf(irqstr, sizeof irqstr, "couldn't establish interrupt");
406: else
407: snprintf(irqstr, sizeof irqstr, "irq %ld", gh->gh_irq);
408: return(irqstr);
409: }
410:
411:
412: int
413: pxagpio_intr0(void *arg)
414: {
415: struct pxagpio_softc *sc = arg;
416: int ret;
417:
418: #ifdef DIAGNOSTIC
419: if (sc->sc_handlers[0] == NULL) {
420: printf("%s: stray GPIO#0 edge interrupt\n",
421: sc->sc_dev.dv_xname);
422: return (0);
423: }
424: #endif
425:
426: bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_REG(GPIO_GEDR0, 0),
427: GPIO_BIT(0));
428:
429: ret = (sc->sc_handlers[0]->gh_func)(sc->sc_handlers[0]->gh_arg);
430: if (ret != 0)
431: sc->sc_handlers[0]->gh_count.ec_count++;
432: return ret;
433: }
434:
435: int
436: pxagpio_intr1(void *arg)
437: {
438: struct pxagpio_softc *sc = arg;
439: int ret;
440:
441: #ifdef DIAGNOSTIC
442: if (sc->sc_handlers[1] == NULL) {
443: printf("%s: stray GPIO#1 edge interrupt\n",
444: sc->sc_dev.dv_xname);
445: return (0);
446: }
447: #endif
448:
449: bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_REG(GPIO_GEDR0, 1),
450: GPIO_BIT(1));
451:
452: ret = (sc->sc_handlers[1]->gh_func)(sc->sc_handlers[1]->gh_arg);
453: if (ret != 0)
454: sc->sc_handlers[1]->gh_count.ec_count++;
455: return ret;
456: }
457:
458: #ifdef PXAGPIO_HAS_GPION_INTRS
459: int
460: pxagpio_dispatch(struct pxagpio_softc *sc, int gpio_base)
461: {
462: struct gpio_irq_handler **ghp, *gh;
463: int i, s, nhandled, handled, pins;
464: u_int32_t gedr, mask;
465: int bank;
466:
467: /* Fetch bitmap of pending interrupts on this GPIO bank */
468: gedr = pxagpio_reg_read(sc, GPIO_REG(GPIO_GEDR0, gpio_base));
469:
470: /* Don't handle GPIO 0/1 here */
471: if (gpio_base == 0)
472: gedr &= ~(GPIO_BIT(0) | GPIO_BIT(1));
473:
474: /* Bail early if there are no pending interrupts in this bank */
475: if (gedr == 0)
476: return (0);
477:
478: /* Acknowledge pending interrupts. */
479: pxagpio_reg_write(sc, GPIO_REG(GPIO_GEDR0, gpio_base), gedr);
480:
481: bank = GPIO_BANK(gpio_base);
482:
483: /*
484: * We're only interested in those for which we have a handler
485: * registered
486: */
487: #ifdef DEBUG
488: if ((gedr & sc->sc_mask[bank]) == 0) {
489: printf("%s: stray GPIO interrupt. Bank %d, GEDR 0x%08x, mask 0x%08x\n",
490: sc->sc_dev.dv_xname, bank, gedr, sc->sc_mask[bank]);
491: return (1); /* XXX: Pretend we dealt with it */
492: }
493: #endif
494:
495: gedr &= sc->sc_mask[bank];
496: ghp = &sc->sc_handlers[gpio_base];
497: if (sc->pxa27x_pins == 1)
498: pins = (gpio_base < 96) ? 32 : 25;
499: else
500: pins = (gpio_base < 64) ? 32 : 17;
501: handled = 0;
502:
503: for (i = 0, mask = 1; i < pins && gedr; i++, ghp++, mask <<= 1) {
504: if ((gedr & mask) == 0)
505: continue;
506: gedr &= ~mask;
507:
508: if ((gh = *ghp) == NULL) {
509: printf("%s: unhandled GPIO interrupt. GPIO#%d\n",
510: sc->sc_dev.dv_xname, gpio_base + i);
511: continue;
512: }
513:
514: s = _splraise(gh->gh_spl);
515: do {
516: nhandled = (gh->gh_func)(gh->gh_arg);
517: if (nhandled != 0)
518: gh->gh_count.ec_count++;
519: handled |= nhandled;
520: gh = gh->gh_next;
521: } while (gh != NULL);
522: splx(s);
523: }
524:
525: return (handled);
526: }
527:
528: int
529: pxagpio_intrN(void *arg)
530: {
531: struct pxagpio_softc *sc = arg;
532: int handled;
533:
534: handled = pxagpio_dispatch(sc, 0);
535: handled |= pxagpio_dispatch(sc, 32);
536: handled |= pxagpio_dispatch(sc, 64);
537: handled |= pxagpio_dispatch(sc, 96);
538:
539: return (handled);
540: }
541:
542: int
543: pxagpio_intrlow(void *arg)
544: {
545: /* dummy */
546: return 0;
547: }
548: #endif /* PXAGPIO_HAS_GPION_INTRS */
549:
550: u_int
551: pxa2x0_gpio_get_function(u_int gpio)
552: {
553: struct pxagpio_softc *sc = pxagpio_softc;
554: u_int32_t rv, io;
555:
556: if (__predict_true(sc != NULL))
557: KDASSERT(gpio < sc->npins);
558:
559: rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) >> GPIO_FN_SHIFT(gpio);
560: rv = GPIO_FN(rv);
561:
562: io = pxagpio_reg_read(sc, GPIO_REG(GPIO_GPDR0, gpio));
563: if (io & GPIO_BIT(gpio))
564: rv |= GPIO_OUT;
565:
566: io = pxagpio_reg_read(sc, GPIO_REG(GPIO_GPLR0, gpio));
567: if (io & GPIO_BIT(gpio))
568: rv |= GPIO_SET;
569:
570: return (rv);
571: }
572:
573: u_int
574: pxa2x0_gpio_set_function(u_int gpio, u_int fn)
575: {
576: struct pxagpio_softc *sc = pxagpio_softc;
577: u_int32_t rv, bit;
578: u_int oldfn;
579:
580: if (__predict_true(sc != NULL))
581: KDASSERT(gpio < sc->npins);
582:
583: oldfn = pxa2x0_gpio_get_function(gpio);
584:
585: if (GPIO_FN(fn) == GPIO_FN(oldfn) &&
586: GPIO_FN_IS_OUT(fn) == GPIO_FN_IS_OUT(oldfn)) {
587: /*
588: * The pin's function is not changing.
589: * For Alternate Functions and GPIO input, we can just
590: * return now.
591: * For GPIO output pins, check the initial state is
592: * the same.
593: *
594: * Return 'fn' instead of 'oldfn' so the caller can
595: * reliably detect that we didn't change anything.
596: * (The initial state might be different for non-
597: * GPIO output pins).
598: */
599: if (!GPIO_IS_GPIO_OUT(fn) ||
600: GPIO_FN_IS_SET(fn) == GPIO_FN_IS_SET(oldfn))
601: return (fn);
602: }
603:
604: /*
605: * See section 4.1.3.7 of the PXA2x0 Developer's Manual for
606: * the correct procedure for changing GPIO pin functions.
607: */
608:
609: bit = GPIO_BIT(gpio);
610:
611: /*
612: * 1. Configure the correct set/clear state of the pin
613: */
614: if (GPIO_FN_IS_SET(fn))
615: pxagpio_reg_write(sc, GPIO_REG(GPIO_GPSR0, gpio), bit);
616: else
617: pxagpio_reg_write(sc, GPIO_REG(GPIO_GPCR0, gpio), bit);
618:
619: /*
620: * 2. Configure the pin as an input or output as appropriate
621: */
622: rv = pxagpio_reg_read(sc, GPIO_REG(GPIO_GPDR0, gpio)) & ~bit;
623: if (GPIO_FN_IS_OUT(fn))
624: rv |= bit;
625: pxagpio_reg_write(sc, GPIO_REG(GPIO_GPDR0, gpio), rv);
626:
627: /*
628: * 3. Configure the pin's function
629: */
630: bit = GPIO_FN_MASK << GPIO_FN_SHIFT(gpio);
631: fn = GPIO_FN(fn) << GPIO_FN_SHIFT(gpio);
632: rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) & ~bit;
633: pxagpio_reg_write(sc, GPIO_FN_REG(gpio), rv | fn);
634:
635: return (oldfn);
636: }
637:
638: /*
639: * Quick function to read pin value
640: */
641: int
642: pxa2x0_gpio_get_bit(u_int gpio)
643: {
644: struct pxagpio_softc *sc = pxagpio_softc;
645: int bit;
646:
647: bit = GPIO_BIT(gpio);
648: if (pxagpio_reg_read(sc, GPIO_REG(GPIO_GPLR0, gpio)) & bit)
649: return 1;
650: else
651: return 0;
652: }
653:
654: /*
655: * Quick function to set pin to 1
656: */
657: void
658: pxa2x0_gpio_set_bit(u_int gpio)
659: {
660: struct pxagpio_softc *sc = pxagpio_softc;
661: int bit;
662:
663: bit = GPIO_BIT(gpio);
664: pxagpio_reg_write(sc, GPIO_REG(GPIO_GPSR0, gpio), bit);
665: }
666:
667: /*
668: * Quick function to set pin to 0
669: */
670: void
671: pxa2x0_gpio_clear_bit(u_int gpio)
672: {
673: struct pxagpio_softc *sc = pxagpio_softc;
674: int bit;
675:
676: bit = GPIO_BIT(gpio);
677: pxagpio_reg_write(sc, GPIO_REG(GPIO_GPCR0, gpio), bit);
678: }
679:
680: /*
681: * Quick function to change pin direction
682: */
683: void
684: pxa2x0_gpio_set_dir(u_int gpio, int dir)
685: {
686: struct pxagpio_softc *sc = pxagpio_softc;
687: int bit;
688: u_int32_t reg;
689:
690: bit = GPIO_BIT(gpio);
691:
692: reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GPDR0, gpio)) & ~bit;
693: if (GPIO_FN_IS_OUT(dir))
694: reg |= bit;
695: pxagpio_reg_write(sc, GPIO_REG(GPIO_GPDR0, gpio), reg);
696: }
697:
698: /*
699: * Quick function to clear interrupt status on a pin
700: * GPIO pins may be toggle in an interrupt and we dont want
701: * extra spurious interrupts to occur.
702: * Suppose this causes a slight race if a key is pressed while
703: * the interrupt handler is running. (yes this is for the keyboard driver)
704: */
705: void
706: pxa2x0_gpio_clear_intr(u_int gpio)
707: {
708: struct pxagpio_softc *sc = pxagpio_softc;
709: int bit;
710:
711: bit = GPIO_BIT(gpio);
712: pxagpio_reg_write(sc, GPIO_REG(GPIO_GEDR0, gpio), bit);
713: }
714:
715: /*
716: * Quick function to mask (disable) a GPIO interrupt
717: */
718: void
719: pxa2x0_gpio_intr_mask(void *v)
720: {
721: struct gpio_irq_handler *gh = v;
722:
723: pxa2x0_gpio_set_intr_level(gh->gh_gpio, IPL_NONE);
724: }
725:
726: /*
727: * Quick function to unmask (enable) a GPIO interrupt
728: */
729: void
730: pxa2x0_gpio_intr_unmask(void *v)
731: {
732: struct gpio_irq_handler *gh = v;
733:
734: pxa2x0_gpio_set_intr_level(gh->gh_gpio, gh->gh_level);
735: }
736:
737: /*
738: * Configure the edge sensitivity of interrupt pins
739: */
740: void
741: pxa2x0_gpio_set_intr_level(u_int gpio, int level)
742: {
743: struct pxagpio_softc *sc = pxagpio_softc;
744: u_int32_t bit;
745: u_int32_t gfer;
746: u_int32_t grer;
747: int s;
748:
749: s = splhigh();
750:
751: bit = GPIO_BIT(gpio);
752: gfer = pxagpio_reg_read(sc, GPIO_REG(GPIO_GFER0, gpio));
753: grer = pxagpio_reg_read(sc, GPIO_REG(GPIO_GRER0, gpio));
754:
755: switch (level) {
756: case IST_NONE:
757: gfer &= ~bit;
758: grer &= ~bit;
759: break;
760: case IST_EDGE_FALLING:
761: gfer |= bit;
762: grer &= ~bit;
763: break;
764: case IST_EDGE_RISING:
765: gfer &= ~bit;
766: grer |= bit;
767: break;
768: case IST_EDGE_BOTH:
769: gfer |= bit;
770: grer |= bit;
771: break;
772: default:
773: panic("pxa2x0_gpio_set_intr_level: bad level: %d", level);
774: break;
775: }
776:
777: pxagpio_reg_write(sc, GPIO_REG(GPIO_GFER0, gpio), gfer);
778: pxagpio_reg_write(sc, GPIO_REG(GPIO_GRER0, gpio), grer);
779:
780: splx(s);
781: }
CVSweb