[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     ! 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