123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777 |
- /* $OpenBSD: pxa2x0_gpio.c,v 1.24 2014/07/12 18:44:41 tedu Exp $ */
- /* $NetBSD: pxa2x0_gpio.c,v 1.2 2003/07/15 00:24:55 lukem Exp $ */
- /*
- * Copyright 2003 Wasabi Systems, Inc.
- * All rights reserved.
- *
- * Written by Steve C. Woodford for Wasabi Systems, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed for the NetBSD Project by
- * Wasabi Systems, Inc.
- * 4. The name of Wasabi Systems, Inc. may not be used to endorse
- * or promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
- #include <sys/param.h>
- #include <sys/systm.h>
- #include <sys/device.h>
- #include <sys/malloc.h>
- #include <sys/evcount.h>
- #include <machine/intr.h>
- #include <machine/bus.h>
- #include <arm/cpufunc.h>
- #include <arm/xscale/pxa2x0reg.h>
- #include <arm/xscale/pxa2x0var.h>
- #include <arm/xscale/pxa2x0_gpio.h>
- struct gpio_irq_handler {
- struct gpio_irq_handler *gh_next;
- int (*gh_func)(void *);
- void *gh_arg;
- int gh_spl;
- u_int gh_gpio;
- int gh_level;
- int gh_irq;
- struct evcount gh_count;
- };
- struct pxagpio_softc {
- struct device sc_dev;
- bus_space_tag_t sc_bust;
- bus_space_handle_t sc_bush;
- void *sc_irqcookie[4];
- u_int32_t sc_mask[3];
- #ifdef PXAGPIO_HAS_GPION_INTRS
- struct gpio_irq_handler *sc_handlers[GPIO_NPINS];
- int sc_minipl;
- int sc_maxipl;
- #else
- struct gpio_irq_handler *sc_handlers[2];
- #endif
- int npins;
- int pxa27x_pins;
- };
- int pxagpio_match(struct device *, void *, void *);
- void pxagpio_attach(struct device *, struct device *, void *);
- #ifdef __NetBSD__
- CFATTACH_DECL(pxagpio, sizeof(struct pxagpio_softc),
- pxagpio_match, pxagpio_attach, NULL, NULL);
- #else
- struct cfattach pxagpio_ca = {
- sizeof (struct pxagpio_softc), pxagpio_match, pxagpio_attach
- };
-
- struct cfdriver pxagpio_cd = {
- NULL, "pxagpio", DV_DULL
- };
- #endif
- static struct pxagpio_softc *pxagpio_softc;
- static vaddr_t pxagpio_regs;
- #define GPIO_BOOTSTRAP_REG(reg) \
- (*((volatile u_int32_t *)(pxagpio_regs + (reg))))
- void pxa2x0_gpio_set_intr_level(u_int, int);
- int pxagpio_intr0(void *);
- int pxagpio_intr1(void *);
- #ifdef PXAGPIO_HAS_GPION_INTRS
- int pxagpio_dispatch(struct pxagpio_softc *, int);
- int pxagpio_intrN(void *);
- int pxagpio_intrlow(void *);
- void pxa2x0_gpio_intr_fixup(int minipl, int maxipl);
- #endif
- u_int32_t pxagpio_reg_read(struct pxagpio_softc *sc, int reg);
- void pxagpio_reg_write(struct pxagpio_softc *sc, int reg, u_int32_t val);
- u_int32_t
- pxagpio_reg_read(struct pxagpio_softc *sc, int reg)
- {
- if (__predict_true(sc != NULL))
- return (bus_space_read_4(sc->sc_bust, sc->sc_bush, reg));
- else
- if (pxagpio_regs)
- return (GPIO_BOOTSTRAP_REG(reg));
- panic("pxagpio_reg_read: not bootstrapped");
- }
- void
- pxagpio_reg_write(struct pxagpio_softc *sc, int reg, u_int32_t val)
- {
- if (__predict_true(sc != NULL))
- bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, val);
- else
- if (pxagpio_regs)
- GPIO_BOOTSTRAP_REG(reg) = val;
- else
- panic("pxagpio_reg_write: not bootstrapped");
- return;
- }
- int
- pxagpio_match(struct device *parent, void *cf, void *aux)
- {
- struct pxaip_attach_args *pxa = aux;
- if (pxagpio_softc != NULL || pxa->pxa_addr != PXA2X0_GPIO_BASE)
- return (0);
- pxa->pxa_size = PXA2X0_GPIO_SIZE;
- return (1);
- }
- void
- pxagpio_attach(struct device *parent, struct device *self, void *aux)
- {
- struct pxagpio_softc *sc = (struct pxagpio_softc *)self;
- struct pxaip_attach_args *pxa = aux;
- sc->sc_bust = pxa->pxa_iot;
- printf(": GPIO Controller\n");
- if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X) {
- sc->npins = GPIO_NPINS;
- sc->pxa27x_pins = 1;
- } else {
- sc->npins = GPIO_NPINS_25x;
- sc->pxa27x_pins = 0;
- }
- if (bus_space_map(sc->sc_bust, pxa->pxa_addr, pxa->pxa_size, 0,
- &sc->sc_bush)) {
- printf("%s: Can't map registers!\n", sc->sc_dev.dv_xname);
- return;
- }
- memset(sc->sc_handlers, 0, sizeof(sc->sc_handlers));
- /*
- * Disable all GPIO interrupts
- */
- pxagpio_reg_write(sc, GPIO_GRER0, 0);
- pxagpio_reg_write(sc, GPIO_GRER1, 0);
- pxagpio_reg_write(sc, GPIO_GRER2, 0);
- pxagpio_reg_write(sc, GPIO_GRER3, 0);
- pxagpio_reg_write(sc, GPIO_GFER0, 0);
- pxagpio_reg_write(sc, GPIO_GFER1, 0);
- pxagpio_reg_write(sc, GPIO_GFER2, 0);
- pxagpio_reg_write(sc, GPIO_GFER3, 0);
- pxagpio_reg_write(sc, GPIO_GEDR0, ~0);
- pxagpio_reg_write(sc, GPIO_GEDR1, ~0);
- pxagpio_reg_write(sc, GPIO_GEDR2, ~0);
- pxagpio_reg_write(sc, GPIO_GEDR3, ~0);
- #ifdef PXAGPIO_HAS_GPION_INTRS
- sc->sc_minipl = IPL_NONE;
- sc->sc_maxipl = IPL_NONE;
- #endif
- sc->sc_irqcookie[0] = sc->sc_irqcookie[1] = NULL;
- pxagpio_softc = sc;
- }
- void
- pxa2x0_gpio_bootstrap(vaddr_t gpio_regs)
- {
- pxagpio_regs = gpio_regs;
- }
- void *
- pxa2x0_gpio_intr_establish(u_int gpio, int level, int spl, int (*func)(void *),
- void *arg, const char *name)
- {
- struct pxagpio_softc *sc = pxagpio_softc;
- struct gpio_irq_handler *gh;
- u_int32_t bit;
- #ifdef DEBUG
- #ifdef PXAGPIO_HAS_GPION_INTRS
- if (gpio >= sc->npins)
- panic("pxa2x0_gpio_intr_establish: bad pin number: %d", gpio);
- #else
- if (gpio > 1)
- panic("pxa2x0_gpio_intr_establish: bad pin number: %d", gpio);
- #endif
- #endif
- if (GPIO_FN_IS_OUT(pxa2x0_gpio_get_function(gpio)) != GPIO_IN)
- panic("pxa2x0_gpio_intr_establish: Pin %d not GPIO_IN", gpio);
- gh = (struct gpio_irq_handler *)malloc(sizeof(struct gpio_irq_handler),
- M_DEVBUF, M_NOWAIT);
- gh->gh_func = func;
- gh->gh_arg = arg;
- gh->gh_spl = spl;
- gh->gh_gpio = gpio;
- gh->gh_irq = gpio+32;
- gh->gh_level = level;
- evcount_attach(&gh->gh_count, name, &gh->gh_irq);
- gh->gh_next = sc->sc_handlers[gpio];
- sc->sc_handlers[gpio] = gh;
- if (gpio == 0) {
- KDASSERT(sc->sc_irqcookie[0] == NULL);
- sc->sc_irqcookie[0] = pxa2x0_intr_establish(PXA2X0_INT_GPIO0,
- spl, pxagpio_intr0, sc, NULL);
- KDASSERT(sc->sc_irqcookie[0]);
- } else if (gpio == 1) {
- KDASSERT(sc->sc_irqcookie[1] == NULL);
- sc->sc_irqcookie[1] = pxa2x0_intr_establish(PXA2X0_INT_GPIO1,
- spl, pxagpio_intr1, sc, NULL);
- KDASSERT(sc->sc_irqcookie[1]);
- } else {
- #ifdef PXAGPIO_HAS_GPION_INTRS
- int minipl, maxipl;
-
- if (sc->sc_maxipl == IPL_NONE || spl > sc->sc_maxipl) {
- maxipl = spl;
- } else {
- maxipl = sc->sc_maxipl;
- }
-
- if (sc->sc_minipl == IPL_NONE || spl < sc->sc_minipl) {
- minipl = spl;
- } else {
- minipl = sc->sc_minipl;
- }
- pxa2x0_gpio_intr_fixup(minipl, maxipl);
- #endif
- }
- bit = GPIO_BIT(gpio);
- sc->sc_mask[GPIO_BANK(gpio)] |= bit;
- pxa2x0_gpio_set_intr_level(gpio, gh->gh_level);
- return (gh);
- }
- void
- pxa2x0_gpio_intr_disestablish(void *cookie)
- {
- struct pxagpio_softc *sc = pxagpio_softc;
- struct gpio_irq_handler *gh = cookie;
- u_int32_t bit, reg;
- evcount_detach(&gh->gh_count);
- bit = GPIO_BIT(gh->gh_gpio);
- reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GFER0, gh->gh_gpio));
- reg &= ~bit;
- pxagpio_reg_write(sc, GPIO_REG(GPIO_GFER0, gh->gh_gpio), reg);
- reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GRER0, gh->gh_gpio));
- reg &= ~bit;
- pxagpio_reg_write(sc, GPIO_REG(GPIO_GRER0, gh->gh_gpio), reg);
- pxagpio_reg_write(sc, GPIO_REG(GPIO_GEDR0, gh->gh_gpio), bit);
- sc->sc_mask[GPIO_BANK(gh->gh_gpio)] &= ~bit;
- sc->sc_handlers[gh->gh_gpio] = NULL;
- if (gh->gh_gpio == 0) {
- pxa2x0_intr_disestablish(sc->sc_irqcookie[0]);
- sc->sc_irqcookie[0] = NULL;
- } else if (gh->gh_gpio == 1) {
- pxa2x0_intr_disestablish(sc->sc_irqcookie[1]);
- sc->sc_irqcookie[1] = NULL;
- } else {
- #ifdef PXAGPIO_HAS_GPION_INTRS
- int i, minipl, maxipl, ipl;
- minipl = IPL_HIGH;
- maxipl = IPL_NONE;
- for (i = 2; i < sc->npins; i++) {
- if (sc->sc_handlers[i] != NULL) {
- ipl = sc->sc_handlers[i]->gh_spl;
- if (minipl > ipl)
- minipl = ipl;
- if (maxipl < ipl)
- maxipl = ipl;
- }
- }
- pxa2x0_gpio_intr_fixup(minipl, maxipl);
- #endif /* PXAGPIO_HAS_GPION_INTRS */
- }
- free(gh, M_DEVBUF, 0);
- }
- #ifdef PXAGPIO_HAS_GPION_INTRS
- void
- pxa2x0_gpio_intr_fixup(int minipl, int maxipl)
- {
- struct pxagpio_softc *sc = pxagpio_softc;
- int save = disable_interrupts(I32_bit);
- if (maxipl == IPL_NONE && minipl == IPL_HIGH) {
- /* no remaining interrupts */
- if (sc->sc_irqcookie[2])
- pxa2x0_intr_disestablish(sc->sc_irqcookie[2]);
- sc->sc_irqcookie[2] = NULL;
- if (sc->sc_irqcookie[3])
- pxa2x0_intr_disestablish(sc->sc_irqcookie[3]);
- sc->sc_irqcookie[3] = NULL;
- sc->sc_minipl = IPL_NONE;
- sc->sc_maxipl = IPL_NONE;
- restore_interrupts(save);
- return;
- }
-
- if (sc->sc_maxipl == IPL_NONE || maxipl > sc->sc_maxipl) {
- if (sc->sc_irqcookie[2])
- pxa2x0_intr_disestablish(sc->sc_irqcookie[2]);
- sc->sc_maxipl = maxipl;
- sc->sc_irqcookie[2] =
- pxa2x0_intr_establish(PXA2X0_INT_GPION,
- maxipl, pxagpio_intrN, sc, NULL);
- if (sc->sc_irqcookie[2] == NULL) {
- printf("%s: failed to hook main "
- "GPIO interrupt\n",
- sc->sc_dev.dv_xname);
- /* XXX - panic? */
- }
- }
- if (sc->sc_minipl == IPL_NONE || minipl < sc->sc_minipl) {
- if (sc->sc_irqcookie[3])
- pxa2x0_intr_disestablish(sc->sc_irqcookie[3]);
- sc->sc_minipl = minipl;
- sc->sc_irqcookie[3] =
- pxa2x0_intr_establish(PXA2X0_INT_GPION,
- sc->sc_minipl, pxagpio_intrlow, sc, NULL);
- if (sc->sc_irqcookie[3] == NULL) {
- printf("%s: failed to hook main "
- "GPIO interrupt\n",
- sc->sc_dev.dv_xname);
- /* XXX - panic? */
- }
- }
- restore_interrupts(save);
- }
- #endif /* PXAGPIO_HAS_GPION_INTRS */
- const char *
- pxa2x0_gpio_intr_string(void *cookie)
- {
- static char irqstr[32];
- struct gpio_irq_handler *gh = cookie;
- if (gh == NULL)
- snprintf(irqstr, sizeof irqstr, "couldn't establish interrupt");
- else
- snprintf(irqstr, sizeof irqstr, "irq %d", gh->gh_irq);
- return(irqstr);
- }
- int
- pxagpio_intr0(void *arg)
- {
- struct pxagpio_softc *sc = arg;
- int ret;
- #ifdef DIAGNOSTIC
- if (sc->sc_handlers[0] == NULL) {
- printf("%s: stray GPIO#0 edge interrupt\n",
- sc->sc_dev.dv_xname);
- return (0);
- }
- #endif
- bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_REG(GPIO_GEDR0, 0),
- GPIO_BIT(0));
- ret = (sc->sc_handlers[0]->gh_func)(sc->sc_handlers[0]->gh_arg);
- if (ret != 0)
- sc->sc_handlers[0]->gh_count.ec_count++;
- return ret;
- }
- int
- pxagpio_intr1(void *arg)
- {
- struct pxagpio_softc *sc = arg;
- int ret;
- #ifdef DIAGNOSTIC
- if (sc->sc_handlers[1] == NULL) {
- printf("%s: stray GPIO#1 edge interrupt\n",
- sc->sc_dev.dv_xname);
- return (0);
- }
- #endif
- bus_space_write_4(sc->sc_bust, sc->sc_bush, GPIO_REG(GPIO_GEDR0, 1),
- GPIO_BIT(1));
- ret = (sc->sc_handlers[1]->gh_func)(sc->sc_handlers[1]->gh_arg);
- if (ret != 0)
- sc->sc_handlers[1]->gh_count.ec_count++;
- return ret;
- }
- #ifdef PXAGPIO_HAS_GPION_INTRS
- int
- pxagpio_dispatch(struct pxagpio_softc *sc, int gpio_base)
- {
- struct gpio_irq_handler **ghp, *gh;
- int i, s, nhandled, handled, pins;
- u_int32_t gedr, mask;
- int bank;
- /* Fetch bitmap of pending interrupts on this GPIO bank */
- gedr = pxagpio_reg_read(sc, GPIO_REG(GPIO_GEDR0, gpio_base));
- /* Don't handle GPIO 0/1 here */
- if (gpio_base == 0)
- gedr &= ~(GPIO_BIT(0) | GPIO_BIT(1));
- /* Bail early if there are no pending interrupts in this bank */
- if (gedr == 0)
- return (0);
- /* Acknowledge pending interrupts. */
- pxagpio_reg_write(sc, GPIO_REG(GPIO_GEDR0, gpio_base), gedr);
- bank = GPIO_BANK(gpio_base);
- /*
- * We're only interested in those for which we have a handler
- * registered
- */
- #ifdef DEBUG
- if ((gedr & sc->sc_mask[bank]) == 0) {
- printf("%s: stray GPIO interrupt. Bank %d, GEDR 0x%08x, mask 0x%08x\n",
- sc->sc_dev.dv_xname, bank, gedr, sc->sc_mask[bank]);
- return (1); /* XXX: Pretend we dealt with it */
- }
- #endif
- gedr &= sc->sc_mask[bank];
- ghp = &sc->sc_handlers[gpio_base];
- if (sc->pxa27x_pins == 1)
- pins = (gpio_base < 96) ? 32 : 25;
- else
- pins = (gpio_base < 64) ? 32 : 17;
- handled = 0;
- for (i = 0, mask = 1; i < pins && gedr; i++, ghp++, mask <<= 1) {
- if ((gedr & mask) == 0)
- continue;
- gedr &= ~mask;
- if ((gh = *ghp) == NULL) {
- printf("%s: unhandled GPIO interrupt. GPIO#%d\n",
- sc->sc_dev.dv_xname, gpio_base + i);
- continue;
- }
- s = _splraise(gh->gh_spl);
- do {
- nhandled = (gh->gh_func)(gh->gh_arg);
- if (nhandled != 0)
- gh->gh_count.ec_count++;
- handled |= nhandled;
- gh = gh->gh_next;
- } while (gh != NULL);
- splx(s);
- }
- return (handled);
- }
- int
- pxagpio_intrN(void *arg)
- {
- struct pxagpio_softc *sc = arg;
- int handled;
- handled = pxagpio_dispatch(sc, 0);
- handled |= pxagpio_dispatch(sc, 32);
- handled |= pxagpio_dispatch(sc, 64);
- handled |= pxagpio_dispatch(sc, 96);
- return (handled);
- }
- int
- pxagpio_intrlow(void *arg)
- {
- /* dummy */
- return 0;
- }
- #endif /* PXAGPIO_HAS_GPION_INTRS */
- u_int
- pxa2x0_gpio_get_function(u_int gpio)
- {
- struct pxagpio_softc *sc = pxagpio_softc;
- u_int32_t rv, io;
- if (__predict_true(sc != NULL))
- KDASSERT(gpio < sc->npins);
- rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) >> GPIO_FN_SHIFT(gpio);
- rv = GPIO_FN(rv);
- io = pxagpio_reg_read(sc, GPIO_REG(GPIO_GPDR0, gpio));
- if (io & GPIO_BIT(gpio))
- rv |= GPIO_OUT;
- io = pxagpio_reg_read(sc, GPIO_REG(GPIO_GPLR0, gpio));
- if (io & GPIO_BIT(gpio))
- rv |= GPIO_SET;
- return (rv);
- }
- u_int
- pxa2x0_gpio_set_function(u_int gpio, u_int fn)
- {
- struct pxagpio_softc *sc = pxagpio_softc;
- u_int32_t rv, bit;
- u_int oldfn;
- if (__predict_true(sc != NULL))
- KDASSERT(gpio < sc->npins);
- oldfn = pxa2x0_gpio_get_function(gpio);
- if (GPIO_FN(fn) == GPIO_FN(oldfn) &&
- GPIO_FN_IS_OUT(fn) == GPIO_FN_IS_OUT(oldfn)) {
- /*
- * The pin's function is not changing.
- * For Alternate Functions and GPIO input, we can just
- * return now.
- * For GPIO output pins, check the initial state is
- * the same.
- *
- * Return 'fn' instead of 'oldfn' so the caller can
- * reliably detect that we didn't change anything.
- * (The initial state might be different for non-
- * GPIO output pins).
- */
- if (!GPIO_IS_GPIO_OUT(fn) ||
- GPIO_FN_IS_SET(fn) == GPIO_FN_IS_SET(oldfn))
- return (fn);
- }
- /*
- * See section 4.1.3.7 of the PXA2x0 Developer's Manual for
- * the correct procedure for changing GPIO pin functions.
- */
- bit = GPIO_BIT(gpio);
- /*
- * 1. Configure the correct set/clear state of the pin
- */
- if (GPIO_FN_IS_SET(fn))
- pxagpio_reg_write(sc, GPIO_REG(GPIO_GPSR0, gpio), bit);
- else
- pxagpio_reg_write(sc, GPIO_REG(GPIO_GPCR0, gpio), bit);
- /*
- * 2. Configure the pin as an input or output as appropriate
- */
- rv = pxagpio_reg_read(sc, GPIO_REG(GPIO_GPDR0, gpio)) & ~bit;
- if (GPIO_FN_IS_OUT(fn))
- rv |= bit;
- pxagpio_reg_write(sc, GPIO_REG(GPIO_GPDR0, gpio), rv);
- /*
- * 3. Configure the pin's function
- */
- bit = GPIO_FN_MASK << GPIO_FN_SHIFT(gpio);
- fn = GPIO_FN(fn) << GPIO_FN_SHIFT(gpio);
- rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) & ~bit;
- pxagpio_reg_write(sc, GPIO_FN_REG(gpio), rv | fn);
- return (oldfn);
- }
- /*
- * Quick function to read pin value
- */
- int
- pxa2x0_gpio_get_bit(u_int gpio)
- {
- struct pxagpio_softc *sc = pxagpio_softc;
- int bit;
- bit = GPIO_BIT(gpio);
- if (pxagpio_reg_read(sc, GPIO_REG(GPIO_GPLR0, gpio)) & bit)
- return 1;
- else
- return 0;
- }
- /*
- * Quick function to set pin to 1
- */
- void
- pxa2x0_gpio_set_bit(u_int gpio)
- {
- struct pxagpio_softc *sc = pxagpio_softc;
- int bit;
- bit = GPIO_BIT(gpio);
- pxagpio_reg_write(sc, GPIO_REG(GPIO_GPSR0, gpio), bit);
- }
- /*
- * Quick function to set pin to 0
- */
- void
- pxa2x0_gpio_clear_bit(u_int gpio)
- {
- struct pxagpio_softc *sc = pxagpio_softc;
- int bit;
- bit = GPIO_BIT(gpio);
- pxagpio_reg_write(sc, GPIO_REG(GPIO_GPCR0, gpio), bit);
- }
- /*
- * Quick function to change pin direction
- */
- void
- pxa2x0_gpio_set_dir(u_int gpio, int dir)
- {
- struct pxagpio_softc *sc = pxagpio_softc;
- int bit;
- u_int32_t reg;
- bit = GPIO_BIT(gpio);
- reg = pxagpio_reg_read(sc, GPIO_REG(GPIO_GPDR0, gpio)) & ~bit;
- if (GPIO_FN_IS_OUT(dir))
- reg |= bit;
- pxagpio_reg_write(sc, GPIO_REG(GPIO_GPDR0, gpio), reg);
- }
- /*
- * Quick function to clear interrupt status on a pin
- * GPIO pins may be toggle in an interrupt and we dont want
- * extra spurious interrupts to occur.
- * Suppose this causes a slight race if a key is pressed while
- * the interrupt handler is running. (yes this is for the keyboard driver)
- */
- void
- pxa2x0_gpio_clear_intr(u_int gpio)
- {
- struct pxagpio_softc *sc = pxagpio_softc;
- int bit;
- bit = GPIO_BIT(gpio);
- pxagpio_reg_write(sc, GPIO_REG(GPIO_GEDR0, gpio), bit);
- }
- /*
- * Quick function to mask (disable) a GPIO interrupt
- */
- void
- pxa2x0_gpio_intr_mask(void *v)
- {
- struct gpio_irq_handler *gh = v;
- pxa2x0_gpio_set_intr_level(gh->gh_gpio, IPL_NONE);
- }
- /*
- * Quick function to unmask (enable) a GPIO interrupt
- */
- void
- pxa2x0_gpio_intr_unmask(void *v)
- {
- struct gpio_irq_handler *gh = v;
- pxa2x0_gpio_set_intr_level(gh->gh_gpio, gh->gh_level);
- }
- /*
- * Configure the edge sensitivity of interrupt pins
- */
- void
- pxa2x0_gpio_set_intr_level(u_int gpio, int level)
- {
- struct pxagpio_softc *sc = pxagpio_softc;
- u_int32_t bit;
- u_int32_t gfer;
- u_int32_t grer;
- int s;
- s = splhigh();
- bit = GPIO_BIT(gpio);
- gfer = pxagpio_reg_read(sc, GPIO_REG(GPIO_GFER0, gpio));
- grer = pxagpio_reg_read(sc, GPIO_REG(GPIO_GRER0, gpio));
- switch (level) {
- case IST_NONE:
- gfer &= ~bit;
- grer &= ~bit;
- break;
- case IST_EDGE_FALLING:
- gfer |= bit;
- grer &= ~bit;
- break;
- case IST_EDGE_RISING:
- gfer &= ~bit;
- grer |= bit;
- break;
- case IST_EDGE_BOTH:
- gfer |= bit;
- grer |= bit;
- break;
- default:
- panic("pxa2x0_gpio_set_intr_level: bad level: %d", level);
- break;
- }
- pxagpio_reg_write(sc, GPIO_REG(GPIO_GFER0, gpio), gfer);
- pxagpio_reg_write(sc, GPIO_REG(GPIO_GRER0, gpio), grer);
- splx(s);
- }
|