diff options
author | manu <manu@FreeBSD.org> | 2016-09-05 20:34:15 +0000 |
---|---|---|
committer | manu <manu@FreeBSD.org> | 2016-09-05 20:34:15 +0000 |
commit | 421fb9c725e2dfab993ceddacd2d9e2b8dc14c83 (patch) | |
tree | 37beaaf269fce495e6e55d20f215e1b6fd7c4836 | |
parent | 9ea41c0da4cd11f09fb086590d8773f104f27c03 (diff) | |
download | FreeBSD-src-421fb9c725e2dfab993ceddacd2d9e2b8dc14c83.zip FreeBSD-src-421fb9c725e2dfab993ceddacd2d9e2b8dc14c83.tar.gz |
MFC r304289
a10_gpio_get_function now returns the whole function not only
GPIO_INPUT/GPIO_OUTPUT.
a10_gpio_get_pud now returns the whole pud not only PULLDOWN/PULLUP.
Add a10_gpio_get_drv to get the current drive strenght.
During fdt pin configure, avoid setting function/drive/pud if it's already in
the correct value.
Tested on Allwinner H3 and A20
-rw-r--r-- | sys/arm/allwinner/a10_gpio.c | 72 |
1 files changed, 53 insertions, 19 deletions
diff --git a/sys/arm/allwinner/a10_gpio.c b/sys/arm/allwinner/a10_gpio.c index 557b0fc..176cbf6 100644 --- a/sys/arm/allwinner/a10_gpio.c +++ b/sys/arm/allwinner/a10_gpio.c @@ -196,14 +196,8 @@ a10_gpio_get_function(struct a10_gpio_softc *sc, uint32_t pin) offset = ((pin & 0x07) << 2); func = A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, pin >> 3)); - switch ((func >> offset) & 0x7) { - case A10_GPIO_INPUT: - return (GPIO_PIN_INPUT); - case A10_GPIO_OUTPUT: - return (GPIO_PIN_OUTPUT); - } - return (0); + return ((func >> offset) & 0x7); } static int @@ -243,14 +237,8 @@ a10_gpio_get_pud(struct a10_gpio_softc *sc, uint32_t pin) offset = ((pin & 0x0f) << 1); val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pin >> 4)); - switch ((val >> offset) & 0x3) { - case A10_GPIO_PULLDOWN: - return (GPIO_PIN_PULLDOWN); - case A10_GPIO_PULLUP: - return (GPIO_PIN_PULLUP); - } - return (0); + return ((val >> offset) & AW_GPIO_PUD_MASK); } static void @@ -271,6 +259,23 @@ a10_gpio_set_pud(struct a10_gpio_softc *sc, uint32_t pin, uint32_t state) A10_GPIO_WRITE(sc, A10_GPIO_GP_PUL(bank, pin >> 4), val); } +static uint32_t +a10_gpio_get_drv(struct a10_gpio_softc *sc, uint32_t pin) +{ + uint32_t bank, offset, val; + + /* Must be called with lock held. */ + A10_GPIO_LOCK_ASSERT(sc); + + bank = sc->padconf->pins[pin].port; + pin = sc->padconf->pins[pin].pin; + offset = ((pin & 0x0f) << 1); + + val = A10_GPIO_READ(sc, A10_GPIO_GP_DRV(bank, pin >> 4)); + + return ((val >> offset) & AW_GPIO_DRV_MASK); +} + static void a10_gpio_set_drv(struct a10_gpio_softc *sc, uint32_t pin, uint32_t drive) { @@ -359,14 +364,39 @@ static int a10_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) { struct a10_gpio_softc *sc; + uint32_t func; + uint32_t pud; sc = device_get_softc(dev); if (pin >= sc->padconf->npins) return (EINVAL); A10_GPIO_LOCK(sc); - *flags = a10_gpio_get_function(sc, pin); - *flags |= a10_gpio_get_pud(sc, pin); + func = a10_gpio_get_function(sc, pin); + switch (func) { + case A10_GPIO_INPUT: + *flags = GPIO_PIN_INPUT; + break; + case A10_GPIO_OUTPUT: + *flags = GPIO_PIN_OUTPUT; + break; + default: + *flags = 0; + break; + } + + pud = a10_gpio_get_pud(sc, pin); + switch (pud) { + case A10_GPIO_PULLDOWN: + *flags |= GPIO_PIN_PULLDOWN; + break; + case A10_GPIO_PULLUP: + *flags |= GPIO_PIN_PULLUP; + break; + default: + break; + } + A10_GPIO_UNLOCK(sc); return (0); @@ -550,9 +580,13 @@ aw_fdt_configure_pins(device_t dev, phandle_t cfgxref) } A10_GPIO_LOCK(sc); - a10_gpio_set_function(sc, pin_num, pin_func); - a10_gpio_set_drv(sc, pin_num, pin_drive); - a10_gpio_set_pud(sc, pin_num, pin_pull); + + if (a10_gpio_get_function(sc, pin_num) != pin_func) + a10_gpio_set_function(sc, pin_num, pin_func); + if (a10_gpio_get_drv(sc, pin_num) != pin_drive) + a10_gpio_set_drv(sc, pin_num, pin_drive); + if (a10_gpio_get_pud(sc, pin_num) != pin_pull) + a10_gpio_set_pud(sc, pin_num, pin_pull); A10_GPIO_UNLOCK(sc); } |