diff options
author | loos <loos@FreeBSD.org> | 2015-01-07 19:15:11 +0000 |
---|---|---|
committer | loos <loos@FreeBSD.org> | 2015-01-07 19:15:11 +0000 |
commit | 173745533e391b9bdce26a35aa6462a80ce28c3b (patch) | |
tree | 807dbde92b154389d8d33379ae45837cad54cde7 /sys/arm | |
parent | 17b7ef10fda79e94515b2a9bc292f3efe4621111 (diff) | |
download | FreeBSD-src-173745533e391b9bdce26a35aa6462a80ce28c3b.zip FreeBSD-src-173745533e391b9bdce26a35aa6462a80ce28c3b.tar.gz |
Fix the handling of pull-up and pull-down for RK3188.
For this to work the driver needs to know the bank it has attached to since
the registers for the first 12 pins are at a different location.
Move the lock initialization to simplify the code.
Diffstat (limited to 'sys/arm')
-rw-r--r-- | sys/arm/rockchip/rk30xx_gpio.c | 70 |
1 files changed, 46 insertions, 24 deletions
diff --git a/sys/arm/rockchip/rk30xx_gpio.c b/sys/arm/rockchip/rk30xx_gpio.c index 21f5e09..6eb7db7 100644 --- a/sys/arm/rockchip/rk30xx_gpio.c +++ b/sys/arm/rockchip/rk30xx_gpio.c @@ -79,10 +79,14 @@ struct rk30_gpio_softc { bus_space_tag_t sc_bst; bus_space_handle_t sc_bsh; void * sc_intrhand; + int sc_bank; int sc_gpio_npins; struct gpio_pin sc_gpio_pins[RK30_GPIO_PINS]; }; +/* We use our base address to find out our bank number. */ +static unsigned long rk30_gpio_base_addr[4] = + { 0x2000a000, 0x2003c000, 0x2003e000, 0x20080000 }; static struct rk30_gpio_softc *rk30_gpio_sc = NULL; typedef int (*gpios_phandler_t)(phandle_t, pcell_t *, int); @@ -153,17 +157,28 @@ rk30_gpio_set_function(struct rk30_gpio_softc *sc, uint32_t pin, uint32_t func) static void rk30_gpio_set_pud(struct rk30_gpio_softc *sc, uint32_t pin, uint32_t state) { - uint32_t bank; - - bank = pin / 32; + uint32_t pud; /* Must be called with lock held. */ RK30_GPIO_LOCK_ASSERT(sc); - - if (bank == 0 && pin < 12) - rk30_pmu_gpio_pud(pin, state); + switch (state) { + case GPIO_PIN_PULLUP: + pud = RK30_GPIO_PULLUP; + break; + case GPIO_PIN_PULLDOWN: + pud = RK30_GPIO_PULLDOWN; + break; + default: + pud = RK30_GPIO_NONE; + } + /* + * The pull up/down registers for GPIO0A and half of GPIO0B + * (the first 12 pins on bank 0) are at a different location. + */ + if (sc->sc_bank == 0 && pin < 12) + rk30_pmu_gpio_pud(pin, pud); else - rk30_grf_gpio_pud(bank, pin, state); + rk30_grf_gpio_pud(sc->sc_bank, pin, pud); } static void @@ -183,22 +198,15 @@ rk30_gpio_pin_configure(struct rk30_gpio_softc *sc, struct gpio_pin *pin, pin->gp_flags |= GPIO_PIN_INPUT; rk30_gpio_set_function(sc, pin->gp_pin, pin->gp_flags); } - /* Manage Pull-up/pull-down. */ - pin->gp_flags &= ~(GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN); - if (flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) { - if (flags & GPIO_PIN_PULLUP) { + pin->gp_flags &= ~(GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN); + if (flags & (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)) { + if (flags & GPIO_PIN_PULLUP) pin->gp_flags |= GPIO_PIN_PULLUP; - rk30_gpio_set_pud(sc, pin->gp_pin, - RK30_GPIO_PULLUP); - } else { + else pin->gp_flags |= GPIO_PIN_PULLDOWN; - rk30_gpio_set_pud(sc, pin->gp_pin, - RK30_GPIO_PULLDOWN); - } - } else - rk30_gpio_set_pud(sc, pin->gp_pin, RK30_GPIO_NONE); - + } + rk30_gpio_set_pud(sc, pin->gp_pin, pin->gp_flags); RK30_GPIO_UNLOCK(sc); } @@ -386,14 +394,12 @@ rk30_gpio_attach(device_t dev) struct rk30_gpio_softc *sc = device_get_softc(dev); int i, rid; phandle_t gpio; + unsigned long start; if (rk30_gpio_sc) return (ENXIO); - sc->sc_dev = dev; - mtx_init(&sc->sc_mtx, "rk30 gpio", "gpio", MTX_DEF); - rid = 0; sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); @@ -401,9 +407,23 @@ rk30_gpio_attach(device_t dev) device_printf(dev, "cannot allocate memory window\n"); return (ENXIO); } - sc->sc_bst = rman_get_bustag(sc->sc_mem_res); sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res); + /* Check the unit we are attaching by our base address. */ + sc->sc_bank = -1; + start = rman_get_start(sc->sc_mem_res); + for (i = 0; i < nitems(rk30_gpio_base_addr); i++) { + if (rk30_gpio_base_addr[i] == start) { + sc->sc_bank = i; + break; + } + } + if (sc->sc_bank == -1) { + device_printf(dev, + "unsupported device unit (only GPIO0..3 are supported)\n"); + bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); + return (ENXIO); + } rid = 0; sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, @@ -421,6 +441,8 @@ rk30_gpio_attach(device_t dev) /* Node is not a GPIO controller. */ goto fail; + mtx_init(&sc->sc_mtx, "rk30 gpio", "gpio", MTX_DEF); + /* Initialize the software controlled pins. */ for (i = 0; i < RK30_GPIO_PINS; i++) { snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME, |