[BACK]Return to pxa2x0_gpio.c CVS log [TXT][DIR] Up to [local] / sys / arch / arm / xscale

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