diff options
author | manu <manu@FreeBSD.org> | 2016-09-05 20:07:03 +0000 |
---|---|---|
committer | manu <manu@FreeBSD.org> | 2016-09-05 20:07:03 +0000 |
commit | 587595800a40be2a71341039df8aa65b5a3cb0c7 (patch) | |
tree | b940c9765cd96f18553ff0b1c6bd852faa645330 | |
parent | 3b33ca08743db03bde702396083b670015dff9c9 (diff) | |
download | FreeBSD-src-587595800a40be2a71341039df8aa65b5a3cb0c7.zip FreeBSD-src-587595800a40be2a71341039df8aa65b5a3cb0c7.tar.gz |
MFC r302470
Check that the pin function exists before setting it.
This is needed for Allwinner A13 which has gpio pins with only "out" function.
-rw-r--r-- | sys/arm/allwinner/a10_gpio.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/sys/arm/allwinner/a10_gpio.c b/sys/arm/allwinner/a10_gpio.c index fe9a050..b2c8874 100644 --- a/sys/arm/allwinner/a10_gpio.c +++ b/sys/arm/allwinner/a10_gpio.c @@ -198,11 +198,15 @@ a10_gpio_get_function(struct a10_gpio_softc *sc, uint32_t pin) return (0); } -static void +static int a10_gpio_set_function(struct a10_gpio_softc *sc, uint32_t pin, uint32_t f) { uint32_t bank, data, offset; + /* Check if the function exists in the padconf data */ + if (sc->padconf->pins[pin].functions[f] == NULL) + return (EINVAL); + /* Must be called with lock held. */ A10_GPIO_LOCK_ASSERT(sc); @@ -214,6 +218,8 @@ a10_gpio_set_function(struct a10_gpio_softc *sc, uint32_t pin, uint32_t f) data &= ~(7 << offset); data |= (f << offset); A10_GPIO_WRITE(sc, A10_GPIO_GP_CFG(bank, pin >> 3), data); + + return (0); } static uint32_t @@ -275,9 +281,10 @@ a10_gpio_set_drv(struct a10_gpio_softc *sc, uint32_t pin, uint32_t drive) A10_GPIO_WRITE(sc, A10_GPIO_GP_DRV(bank, pin >> 4), val); } -static void +static int a10_gpio_pin_configure(struct a10_gpio_softc *sc, uint32_t pin, uint32_t flags) { + int err = 0; /* Must be called with lock held. */ A10_GPIO_LOCK_ASSERT(sc); @@ -285,11 +292,14 @@ a10_gpio_pin_configure(struct a10_gpio_softc *sc, uint32_t pin, uint32_t flags) /* Manage input/output. */ if (flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) { if (flags & GPIO_PIN_OUTPUT) - a10_gpio_set_function(sc, pin, A10_GPIO_OUTPUT); + err = a10_gpio_set_function(sc, pin, A10_GPIO_OUTPUT); else - a10_gpio_set_function(sc, pin, A10_GPIO_INPUT); + err = a10_gpio_set_function(sc, pin, A10_GPIO_INPUT); } + if (err) + return (err); + /* Manage Pull-up/pull-down. */ if (flags & (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)) { if (flags & GPIO_PIN_PULLUP) @@ -298,6 +308,8 @@ a10_gpio_pin_configure(struct a10_gpio_softc *sc, uint32_t pin, uint32_t flags) a10_gpio_set_pud(sc, pin, A10_GPIO_PULLDOWN); } else a10_gpio_set_pud(sc, pin, A10_GPIO_NONE); + + return (0); } static device_t @@ -372,16 +384,17 @@ static int a10_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) { struct a10_gpio_softc *sc; + int err; sc = device_get_softc(dev); if (pin > sc->padconf->npins) return (EINVAL); A10_GPIO_LOCK(sc); - a10_gpio_pin_configure(sc, pin, flags); + err = a10_gpio_pin_configure(sc, pin, flags); A10_GPIO_UNLOCK(sc); - return (0); + return (err); } static int |