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