Author: loos
Date: Mon Jul 13 18:19:26 2015
New Revision: 285484
URL: https://svnweb.freebsd.org/changeset/base/285484

Log:
  Bring a few simplifications to a10_gpio:
  
   o Return the real hardware state in gpio_pin_getflags() instead of keep
     the last state in an internal table.  Now the driver returns the real
     state of pins (input/output and pull-up/pull-down) at all times.
   o Use a spin mutex.  This is required by interrupts and the 1-wire code.
   o Use better variable names and place parentheses around them in MACROS.
   o Do not lock the driver when returning static data.
  
  Tested with gpioled(4) and DS1820 (1-wire) sensors on banana pi.

Modified:
  head/sys/arm/allwinner/a10_gpio.c

Modified: head/sys/arm/allwinner/a10_gpio.c
==============================================================================
--- head/sys/arm/allwinner/a10_gpio.c   Mon Jul 13 17:45:22 2015        
(r285483)
+++ head/sys/arm/allwinner/a10_gpio.c   Mon Jul 13 18:19:26 2015        
(r285484)
@@ -82,18 +82,16 @@ struct a10_gpio_softc {
        bus_space_tag_t         sc_bst;
        bus_space_handle_t      sc_bsh;
        void *                  sc_intrhand;
-       int                     sc_gpio_npins;
-       struct gpio_pin         sc_gpio_pins[A10_GPIO_PINS];
 };
 
-#define        A10_GPIO_LOCK(_sc)              mtx_lock(&_sc->sc_mtx)
-#define        A10_GPIO_UNLOCK(_sc)            mtx_unlock(&_sc->sc_mtx)
-#define        A10_GPIO_LOCK_ASSERT(_sc)       mtx_assert(&_sc->sc_mtx, 
MA_OWNED)
+#define        A10_GPIO_LOCK(_sc)              mtx_lock_spin(&(_sc)->sc_mtx)
+#define        A10_GPIO_UNLOCK(_sc)            mtx_unlock_spin(&(_sc)->sc_mtx)
+#define        A10_GPIO_LOCK_ASSERT(_sc)       mtx_assert(&(_sc)->sc_mtx, 
MA_OWNED)
 
-#define        A10_GPIO_GP_CFG(_bank, _pin)    0x00 + ((_bank) * 0x24) + 
((_pin)<<2)
+#define        A10_GPIO_GP_CFG(_bank, _idx)    0x00 + ((_bank) * 0x24) + 
((_idx) << 2)
 #define        A10_GPIO_GP_DAT(_bank)          0x10 + ((_bank) * 0x24)
-#define        A10_GPIO_GP_DRV(_bank, _pin)    0x14 + ((_bank) * 0x24) + 
((_pin)<<2)
-#define        A10_GPIO_GP_PUL(_bank, _pin)    0x1c + ((_bank) * 0x24) + 
((_pin)<<2)
+#define        A10_GPIO_GP_DRV(_bank, _idx)    0x14 + ((_bank) * 0x24) + 
((_idx) << 2)
+#define        A10_GPIO_GP_PUL(_bank, _idx)    0x1c + ((_bank) * 0x24) + 
((_idx) << 2)
 
 #define        A10_GPIO_GP_INT_CFG0            0x200
 #define        A10_GPIO_GP_INT_CFG1            0x204
@@ -116,106 +114,106 @@ a10_gpio_get_function(struct a10_gpio_so
 {
        uint32_t bank, func, offset;
 
+       /* Must be called with lock held. */
+       A10_GPIO_LOCK_ASSERT(sc);
+
        bank = pin / 32;
-       pin = pin - 32 * bank;
-       func = pin >> 3;
+       pin = pin % 32;
        offset = ((pin & 0x07) << 2);
 
-       A10_GPIO_LOCK(sc);
-       func = (A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, func)) >> offset) & 7;
-       A10_GPIO_UNLOCK(sc);
-
-       return (func);
-}
-
-static uint32_t
-a10_gpio_func_flag(uint32_t nfunc)
-{
-
-       switch (nfunc) {
+       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);
 }
 
 static void
 a10_gpio_set_function(struct a10_gpio_softc *sc, uint32_t pin, uint32_t f)
 {
-       uint32_t bank, func, data, offset;
+       uint32_t bank, data, offset;
 
        /* Must be called with lock held. */
        A10_GPIO_LOCK_ASSERT(sc);
 
        bank = pin / 32;
-       pin = pin - 32 * bank;
-       func = pin >> 3;
+       pin = pin % 32;
        offset = ((pin & 0x07) << 2);
 
-       data = A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, func));
+       data = A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, pin >> 3));
        data &= ~(7 << offset);
        data |= (f << offset);
-       A10_GPIO_WRITE(sc, A10_GPIO_GP_CFG(bank, func), data);
+       A10_GPIO_WRITE(sc, A10_GPIO_GP_CFG(bank, pin >> 3), data);
+}
+
+static uint32_t
+a10_gpio_get_pud(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 = pin / 32;
+       pin = pin % 32;
+       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);
 }
 
 static void
 a10_gpio_set_pud(struct a10_gpio_softc *sc, uint32_t pin, uint32_t state)
 {
-       uint32_t bank, offset, pull, val;
+       uint32_t bank, offset, val;
 
        /* Must be called with lock held. */
        A10_GPIO_LOCK_ASSERT(sc);
 
        bank = pin / 32;
-       pin = pin - 32 * bank;
-       pull = pin >> 4;
+       pin = pin % 32;
        offset = ((pin & 0x0f) << 1);
 
-       val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pull));
+       val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pin >> 4));
        val &= ~(0x03 << offset);
        val |= (state << offset);
-       A10_GPIO_WRITE(sc, A10_GPIO_GP_PUL(bank, pull), val);
+       A10_GPIO_WRITE(sc, A10_GPIO_GP_PUL(bank, pin >> 4), val);
 }
 
 static void
-a10_gpio_pin_configure(struct a10_gpio_softc *sc, struct gpio_pin *pin,
-    unsigned int flags)
+a10_gpio_pin_configure(struct a10_gpio_softc *sc, uint32_t pin, uint32_t flags)
 {
 
-       A10_GPIO_LOCK(sc);
+       /* Must be called with lock held. */
+       A10_GPIO_LOCK_ASSERT(sc);
 
-       /*
-        * Manage input/output.
-        */
-       if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
-               pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
-               if (flags & GPIO_PIN_OUTPUT) {
-                       pin->gp_flags |= GPIO_PIN_OUTPUT;
-                       a10_gpio_set_function(sc, pin->gp_pin,
-                           A10_GPIO_OUTPUT);
-               } else {
-                       pin->gp_flags |= GPIO_PIN_INPUT;
-                       a10_gpio_set_function(sc, pin->gp_pin,
-                           A10_GPIO_INPUT);
-               }
+       /* 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);
+               else
+                       a10_gpio_set_function(sc, pin, A10_GPIO_INPUT);
        }
 
        /* 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;
-                       a10_gpio_set_pud(sc, pin->gp_pin, A10_GPIO_PULLUP);
-               } else {
-                       pin->gp_flags |= GPIO_PIN_PULLDOWN;
-                       a10_gpio_set_pud(sc, pin->gp_pin, A10_GPIO_PULLDOWN);
-               }
+       if (flags & (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)) {
+               if (flags & GPIO_PIN_PULLUP)
+                       a10_gpio_set_pud(sc, pin, A10_GPIO_PULLUP);
+               else
+                       a10_gpio_set_pud(sc, pin, A10_GPIO_PULLDOWN);
        } else 
-               a10_gpio_set_pud(sc, pin->gp_pin, A10_GPIO_NONE);
-
-       A10_GPIO_UNLOCK(sc);
+               a10_gpio_set_pud(sc, pin, A10_GPIO_NONE);
 }
 
 static device_t
@@ -239,20 +237,11 @@ a10_gpio_pin_max(device_t dev, int *maxp
 static int
 a10_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
 {
-       struct a10_gpio_softc *sc = device_get_softc(dev);
-       int i;
 
-       for (i = 0; i < sc->sc_gpio_npins; i++) {
-               if (sc->sc_gpio_pins[i].gp_pin == pin)
-                       break;
-       }
-
-       if (i >= sc->sc_gpio_npins)
+       if (pin >= A10_GPIO_PINS)
                return (EINVAL);
 
-       A10_GPIO_LOCK(sc);
-       *caps = sc->sc_gpio_pins[i].gp_caps;
-       A10_GPIO_UNLOCK(sc);
+       *caps = A10_GPIO_DEFAULT_CAPS;
 
        return (0);
 }
@@ -260,19 +249,15 @@ a10_gpio_pin_getcaps(device_t dev, uint3
 static int
 a10_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
 {
-       struct a10_gpio_softc *sc = device_get_softc(dev);
-       int i;
-
-       for (i = 0; i < sc->sc_gpio_npins; i++) {
-               if (sc->sc_gpio_pins[i].gp_pin == pin)
-                       break;
-       }
+       struct a10_gpio_softc *sc;
 
-       if (i >= sc->sc_gpio_npins)
+       if (pin >= A10_GPIO_PINS)
                return (EINVAL);
 
+       sc = device_get_softc(dev);
        A10_GPIO_LOCK(sc);
-       *flags = sc->sc_gpio_pins[i].gp_flags;
+       *flags = a10_gpio_get_function(sc, pin);
+       *flags |= a10_gpio_get_pud(sc, pin);
        A10_GPIO_UNLOCK(sc);
 
        return (0);
@@ -281,20 +266,15 @@ a10_gpio_pin_getflags(device_t dev, uint
 static int
 a10_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
 {
-       struct a10_gpio_softc *sc = device_get_softc(dev);
-       int i;
+       uint32_t bank;
 
-       for (i = 0; i < sc->sc_gpio_npins; i++) {
-               if (sc->sc_gpio_pins[i].gp_pin == pin)
-                       break;
-       }
-
-       if (i >= sc->sc_gpio_npins)
+       if (pin >= A10_GPIO_PINS)
                return (EINVAL);
 
-       A10_GPIO_LOCK(sc);
-       memcpy(name, sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME);
-       A10_GPIO_UNLOCK(sc);
+       bank = pin / 32;
+       snprintf(name, GPIOMAXNAME - 1, "pin %d (P%c%d)",
+           pin, bank + 'A', pin % 32);
+       name[GPIOMAXNAME - 1] = '\0';
 
        return (0);
 }
@@ -302,18 +282,15 @@ a10_gpio_pin_getname(device_t dev, uint3
 static int
 a10_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
 {
-       struct a10_gpio_softc *sc = device_get_softc(dev);
-       int i;
-
-       for (i = 0; i < sc->sc_gpio_npins; i++) {
-               if (sc->sc_gpio_pins[i].gp_pin == pin)
-                       break;
-       }
+       struct a10_gpio_softc *sc;
 
-       if (i >= sc->sc_gpio_npins)
+       if (pin >= A10_GPIO_PINS)
                return (EINVAL);
 
-       a10_gpio_pin_configure(sc, &sc->sc_gpio_pins[i], flags);
+       sc = device_get_softc(dev);
+       A10_GPIO_LOCK(sc);
+       a10_gpio_pin_configure(sc, pin, flags);
+       A10_GPIO_UNLOCK(sc);
 
        return (0);
 }
@@ -321,28 +298,22 @@ a10_gpio_pin_setflags(device_t dev, uint
 static int
 a10_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
 {
-       struct a10_gpio_softc *sc = device_get_softc(dev);
-       uint32_t bank, offset, data;
-       int i;
-
-       for (i = 0; i < sc->sc_gpio_npins; i++) {
-               if (sc->sc_gpio_pins[i].gp_pin == pin)
-                       break;
-       }
+       struct a10_gpio_softc *sc;
+       uint32_t bank, data;
 
-       if (i >= sc->sc_gpio_npins)
+       if (pin >= A10_GPIO_PINS)
                return (EINVAL);
 
        bank = pin / 32;
-       pin = pin - 32 * bank;
-       offset = pin & 0x1f;
+       pin = pin % 32;
 
+       sc = device_get_softc(dev);
        A10_GPIO_LOCK(sc);
        data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
        if (value)
-               data |= (1 << offset);
+               data |= (1 << pin);
        else
-               data &= ~(1 << offset);
+               data &= ~(1 << pin);
        A10_GPIO_WRITE(sc, A10_GPIO_GP_DAT(bank), data);
        A10_GPIO_UNLOCK(sc);
 
@@ -352,26 +323,20 @@ a10_gpio_pin_set(device_t dev, uint32_t 
 static int
 a10_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
 {
-       struct a10_gpio_softc *sc = device_get_softc(dev);
-       uint32_t bank, offset, reg_data;
-       int i;
-
-       for (i = 0; i < sc->sc_gpio_npins; i++) {
-               if (sc->sc_gpio_pins[i].gp_pin == pin)
-                       break;
-       }
+       struct a10_gpio_softc *sc;
+       uint32_t bank, reg_data;
 
-       if (i >= sc->sc_gpio_npins)
+       if (pin >= A10_GPIO_PINS)
                return (EINVAL);
 
        bank = pin / 32;
-       pin = pin - 32 * bank;
-       offset = pin & 0x1f;
+       pin = pin % 32;
 
+       sc = device_get_softc(dev);
        A10_GPIO_LOCK(sc);
        reg_data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
        A10_GPIO_UNLOCK(sc);
-       *val = (reg_data & (1 << offset)) ? 1 : 0;
+       *val = (reg_data & (1 << pin)) ? 1 : 0;
 
        return (0);
 }
@@ -379,28 +344,22 @@ a10_gpio_pin_get(device_t dev, uint32_t 
 static int
 a10_gpio_pin_toggle(device_t dev, uint32_t pin)
 {
-       struct a10_gpio_softc *sc = device_get_softc(dev);
-       uint32_t bank, data, offset;
-       int i;
-
-       for (i = 0; i < sc->sc_gpio_npins; i++) {
-               if (sc->sc_gpio_pins[i].gp_pin == pin)
-                       break;
-       }
+       struct a10_gpio_softc *sc;
+       uint32_t bank, data;
 
-       if (i >= sc->sc_gpio_npins)
+       if (pin >= A10_GPIO_PINS)
                return (EINVAL);
 
        bank = pin / 32;
-       pin = pin - 32 * bank;
-       offset = pin & 0x1f;
+       pin = pin % 32;
 
+       sc = device_get_softc(dev);
        A10_GPIO_LOCK(sc);
        data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
-       if (data & (1 << offset))
-               data &= ~(1 << offset);
+       if (data & (1 << pin))
+               data &= ~(1 << pin);
        else
-               data |= (1 << offset);
+               data |= (1 << pin);
        A10_GPIO_WRITE(sc, A10_GPIO_GP_DAT(bank), data);
        A10_GPIO_UNLOCK(sc);
 
@@ -424,14 +383,14 @@ a10_gpio_probe(device_t dev)
 static int
 a10_gpio_attach(device_t dev)
 {
-       struct a10_gpio_softc *sc = device_get_softc(dev);
-       uint32_t func;
-       int i, rid;
+       int rid;
        phandle_t gpio;
+       struct a10_gpio_softc *sc;
 
+       sc = device_get_softc(dev);
        sc->sc_dev = dev;
 
-       mtx_init(&sc->sc_mtx, "a10 gpio", "gpio", MTX_DEF);
+       mtx_init(&sc->sc_mtx, "a10 gpio", "gpio", MTX_SPIN);
 
        rid = 0;
        sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
@@ -454,21 +413,10 @@ a10_gpio_attach(device_t dev)
 
        /* Find our node. */
        gpio = ofw_bus_get_node(sc->sc_dev);
-
        if (!OF_hasprop(gpio, "gpio-controller"))
                /* Node is not a GPIO controller. */
                goto fail;
 
-       /* Initialize the software controlled pins. */
-       for (i = 0; i < A10_GPIO_PINS; i++) {
-               snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME,
-                   "pin %d", i);
-               func = a10_gpio_get_function(sc, i);
-               sc->sc_gpio_pins[i].gp_pin = i;
-               sc->sc_gpio_pins[i].gp_caps = A10_GPIO_DEFAULT_CAPS;
-               sc->sc_gpio_pins[i].gp_flags = a10_gpio_func_flag(func);
-       }
-       sc->sc_gpio_npins = i;
        a10_gpio_sc = sc;
        sc->sc_busdev = gpiobus_attach_bus(dev);
        if (sc->sc_busdev == NULL)
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to