summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormanu <manu@FreeBSD.org>2016-09-05 20:34:15 +0000
committermanu <manu@FreeBSD.org>2016-09-05 20:34:15 +0000
commit421fb9c725e2dfab993ceddacd2d9e2b8dc14c83 (patch)
tree37beaaf269fce495e6e55d20f215e1b6fd7c4836
parent9ea41c0da4cd11f09fb086590d8773f104f27c03 (diff)
downloadFreeBSD-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.c72
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);
}
OpenPOWER on IntegriCloud