Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch Finish off GPIO handler. Add hook for other driver...



details:   https://anonhg.NetBSD.org/src/rev/69175340b846
branches:  trunk
changeset: 789782:69175340b846
user:      matt <matt%NetBSD.org@localhost>
date:      Sat Sep 07 19:47:28 2013 +0000

description:
Finish off GPIO handler.  Add hook for other driver to access a named gpio.
Add two input gpio's for usb0.

diffstat:

 sys/arch/arm/allwinner/awin_gpio.c    |  332 +++++++++++++++++++++++++++++++--
 sys/arch/arm/allwinner/awin_reg.h     |  236 +++++++++++++-----------
 sys/arch/arm/allwinner/awin_var.h     |   17 +-
 sys/arch/evbarm/cubie/cubie_machdep.c |   22 +-
 4 files changed, 464 insertions(+), 143 deletions(-)

diffs (truncated from 832 to 300 lines):

diff -r 33c36baa1749 -r 69175340b846 sys/arch/arm/allwinner/awin_gpio.c
--- a/sys/arch/arm/allwinner/awin_gpio.c        Sat Sep 07 19:06:29 2013 +0000
+++ b/sys/arch/arm/allwinner/awin_gpio.c        Sat Sep 07 19:47:28 2013 +0000
@@ -28,15 +28,17 @@
  */
 
 #include "locators.h"
+#include "gpio.h"
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: awin_gpio.c,v 1.3 2013/09/07 02:09:23 matt Exp $");
+__KERNEL_RCSID(1, "$NetBSD: awin_gpio.c,v 1.4 2013/09/07 19:47:28 matt Exp $");
 
 #include <sys/bus.h>
 #include <sys/device.h>
 #include <sys/intr.h>
 #include <sys/systm.h>
+#include <sys/kmem.h>
 
 #include <sys/gpio.h>
 
@@ -48,6 +50,10 @@
 static int awin_gpio_match(device_t, cfdata_t, void *);
 static void awin_gpio_attach(device_t, device_t, void *);
 
+static int awin_gpio_pin_read(void *, int);
+static void awin_gpio_pin_write(void *, int, int);
+static void awin_gpio_pin_ctl(void *, int, int);
+
 static const int ist_maps[] = {
        [IST_LEVEL_LOW] =       AWIN_PIO_EINT_LOW_LEVEL,
        [IST_LEVEL_HIGH] =      AWIN_PIO_EINT_HIGH_LEVEL,
@@ -57,7 +63,9 @@
 };
 
 struct awin_gpio_pin_cfg {
-       uint32_t val[4];
+       uint32_t cfg[4];
+       uint32_t drv[2];
+       uint32_t pul[2];
 };
 
 static struct awin_gpio_pin_group {
@@ -65,21 +73,101 @@
        uint32_t grp_pin_inuse_mask;
        bus_space_handle_t grp_bsh;
        struct awin_gpio_pin_cfg grp_cfg;
+       struct gpio_chipset_tag grp_gc_tag;
+       const char grp_nc_name[6];
 } pin_groups[] = {
-       [0] = { .grp_pin_mask = __BIT(AWIN_PIO_PA_PINS) - 1 },
-       [1] = { .grp_pin_mask = __BIT(AWIN_PIO_PB_PINS) - 1 },
-       [2] = { .grp_pin_mask = __BIT(AWIN_PIO_PC_PINS) - 1 },
-       [3] = { .grp_pin_mask = __BIT(AWIN_PIO_PD_PINS) - 1 },
-       [4] = { .grp_pin_mask = __BIT(AWIN_PIO_PE_PINS) - 1 },
-       [5] = { .grp_pin_mask = __BIT(AWIN_PIO_PF_PINS) - 1 },
-       [6] = { .grp_pin_mask = __BIT(AWIN_PIO_PG_PINS) - 1 },
-       [7] = { .grp_pin_mask = __BIT(AWIN_PIO_PH_PINS) - 1 },
-       [8] = { .grp_pin_mask = __BIT(AWIN_PIO_PI_PINS) - 1 },
+       [0] = {
+               .grp_pin_mask = __BIT(AWIN_PIO_PA_PINS) - 1,
+               .grp_gc_tag = {
+                       .gp_cookie = &pin_groups[0],
+                       .gp_pin_read = awin_gpio_pin_read,
+                       .gp_pin_write = awin_gpio_pin_write,
+                       .gp_pin_ctl = awin_gpio_pin_ctl,
+               },
+               .grp_nc_name = "nc-pa",
+       },
+       [1] = {
+               .grp_pin_mask = __BIT(AWIN_PIO_PB_PINS) - 1,
+               .grp_gc_tag = {
+                       .gp_cookie = &pin_groups[1],
+                       .gp_pin_read = awin_gpio_pin_read,
+                       .gp_pin_write = awin_gpio_pin_write,
+                       .gp_pin_ctl = awin_gpio_pin_ctl,
+               },
+               .grp_nc_name = "nc-pb",
+       },
+       [2] = {
+               .grp_pin_mask = __BIT(AWIN_PIO_PC_PINS) - 1,
+               .grp_gc_tag = {
+                       .gp_cookie = &pin_groups[2],
+                       .gp_pin_read = awin_gpio_pin_read,
+                       .gp_pin_write = awin_gpio_pin_write,
+                       .gp_pin_ctl = awin_gpio_pin_ctl,
+               },
+               .grp_nc_name = "nc-pc",
+       },
+       [3] = {
+               .grp_pin_mask = __BIT(AWIN_PIO_PD_PINS) - 1,
+               .grp_gc_tag = {
+                       .gp_cookie = &pin_groups[3],
+                       .gp_pin_read = awin_gpio_pin_read,
+                       .gp_pin_write = awin_gpio_pin_write,
+                       .gp_pin_ctl = awin_gpio_pin_ctl,
+               },
+               .grp_nc_name = "nc-pd",
+       },
+       [4] = {
+               .grp_pin_mask = __BIT(AWIN_PIO_PE_PINS) - 1,
+               .grp_gc_tag = {
+                       .gp_cookie = &pin_groups[4],
+                       .gp_pin_read = awin_gpio_pin_read,
+                       .gp_pin_write = awin_gpio_pin_write,
+                       .gp_pin_ctl = awin_gpio_pin_ctl,
+               },
+               .grp_nc_name = "nc-pe",
+       },
+       [5] = {
+               .grp_pin_mask = __BIT(AWIN_PIO_PF_PINS) - 1,
+               .grp_gc_tag = {
+                       .gp_cookie = &pin_groups[5],
+                       .gp_pin_read = awin_gpio_pin_read,
+                       .gp_pin_write = awin_gpio_pin_write,
+                       .gp_pin_ctl = awin_gpio_pin_ctl,
+               },
+               .grp_nc_name = "nc-pf",
+       },
+       [6] = {
+               .grp_pin_mask = __BIT(AWIN_PIO_PG_PINS) - 1,
+               .grp_gc_tag = {
+                       .gp_cookie = &pin_groups[6],
+                       .gp_pin_read = awin_gpio_pin_read,
+                       .gp_pin_write = awin_gpio_pin_write,
+                       .gp_pin_ctl = awin_gpio_pin_ctl,
+               },
+               .grp_nc_name = "nc-pg",
+       },
+       [7] = {
+               .grp_pin_mask = __BIT(AWIN_PIO_PH_PINS) - 1,
+               .grp_gc_tag = {
+                       .gp_cookie = &pin_groups[7],
+                       .gp_pin_read = awin_gpio_pin_read,
+                       .gp_pin_write = awin_gpio_pin_write,
+                       .gp_pin_ctl = awin_gpio_pin_ctl,
+               },
+               .grp_nc_name = "nc-ph",
+       },
+       [8] = {
+               .grp_pin_mask = __BIT(AWIN_PIO_PI_PINS) - 1,
+               .grp_gc_tag = {
+                       .gp_cookie = &pin_groups[8],
+                       .gp_pin_read = awin_gpio_pin_read,
+                       .gp_pin_write = awin_gpio_pin_write,
+                       .gp_pin_ctl = awin_gpio_pin_ctl,
+               },
+               .grp_nc_name = "nc-pi",
+       },
 };
 
-struct awin_eint_info {
-       uint32_t grp_pin ;
-};
 
 static struct awin_gpio_softc {
        device_t sc_dev;
@@ -108,12 +196,74 @@
        return 1;
 }
 
+#if NGPIO > 0
+static void
+awin_gpio_config_pins(device_t self)
+{
+       struct awin_gpio_softc * const sc = &awin_gpio_sc;
+
+       /*
+        * First find out how many pins we can offer.
+        */
+       size_t pin_count = 0;
+       for (u_int i = 0; i < __arraycount(pin_groups); i++) {
+               struct awin_gpio_pin_group * const grp = &pin_groups[i];
+
+               pin_count +=
+                   popcount32(grp->grp_pin_mask & ~grp->grp_pin_inuse_mask);
+       }
+
+       /*
+        * Allocate the pin data.
+        */
+       gpio_pin_t * const pins = kmem_zalloc(sizeof(gpio_pin_t) * pin_count,
+           KM_SLEEP);
+       KASSERT(pins != NULL);
+
+       const int pincaps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT
+               | GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN;
+
+       gpio_pin_t *pin = pins;
+       for (u_int i = 0; i < __arraycount(pin_groups); i++) {
+               struct awin_gpio_pin_group * const grp = &pin_groups[i];
+               uint32_t mask = grp->grp_pin_mask & ~grp->grp_pin_inuse_mask;
+
+               /* 
+                * If this group has no bits to provide, skip it.
+                */
+               if (mask == 0)
+                       continue;
+
+               struct gpiobus_attach_args gba = {
+                       .gba_gc = &grp->grp_gc_tag,
+                       .gba_pins = pin,
+               };
+
+               uint32_t data = bus_space_read_4(sc->sc_bst, grp->grp_bsh,
+                   AWIN_PIO_DAT_REG);
+               for (int num = 0; mask != 0; mask >>= 1, data >>= 1, num++) {
+                       if (mask & 1) {
+                               pin->pin_num = num + (i << 5);
+                               pin->pin_caps = pincaps;
+                               pin->pin_flags = pincaps;
+                               pin->pin_state = (data & 1) != 0;
+                               pin++;
+                       }
+               }
+
+               gba.gba_npins = pin - gba.gba_pins;
+               config_found_ia(self, "gpiobus", &gba, gpiobus_print);
+       }
+}
+#endif /* NGPIO > 0 */
+
 static void
 awin_gpio_attach(device_t parent, device_t self, void *aux)
 {
        struct awin_gpio_softc * const sc = &awin_gpio_sc;
        struct awinio_attach_args * const aio = aux;
        const struct awin_locators * const loc = &aio->aio_loc;
+       prop_dictionary_t dict = device_properties(self);
 
        sc->sc_dev = self;
 
@@ -123,24 +273,54 @@
 
        aprint_naive("\n");
        aprint_normal("\n");
+
+       for (u_int i = 0; i < __arraycount(pin_groups); i++) {
+               struct awin_gpio_pin_group * const grp = &pin_groups[i];
+
+               /*
+                * See if this group has any unconnected pins and make sure
+                * we won't use them.
+                */
+               uint32_t nc;
+               if (prop_dictionary_get_uint32(dict, grp->grp_nc_name, &nc)) {
+                       KASSERT((~grp->grp_pin_mask & nc) == 0);
+                       KASSERT((grp->grp_pin_inuse_mask & ~nc) == 0);
+                       grp->grp_pin_mask &= ~nc;
+               }
+       }
+
+#if NGPIO > 0
+       config_defer(self, awin_gpio_config_pins);
+#endif
 }
 
 static u_int
 awin_gpio_get_pin_func(const struct awin_gpio_pin_cfg *cfg, u_int pin)
 {
        const u_int shift = (pin & 7) << 2;
-       const u_int i = pin >> 3;
-       return (cfg->val[i] >> shift) & 0x0f;
+       const u_int i = (pin >> 3) & 3;
+
+       return (cfg->cfg[i] >> shift) & 0x0f;
 }
 
 static void
 awin_gpio_set_pin_func(struct awin_gpio_pin_cfg *cfg, u_int pin, u_int func)
 {
        const u_int shift = (pin & 7) << 2;
-       const u_int i = pin >> 3;
+       const u_int i = (pin >> 3) & 3;
        
-       cfg->val[i] &= ~(0x0f << shift);
-       cfg->val[i] |= func << shift;
+       cfg->cfg[i] &= ~(0x0f << shift);
+       cfg->cfg[i] |= func << shift;
+}
+
+static void
+awin_gpio_set_pin_pull(struct awin_gpio_pin_cfg *cfg, u_int pin, u_int pull)
+{
+       const u_int shift = (pin & 15) << 1;
+       const u_int i = (pin >> 4) & 1;
+       
+       cfg->pul[i] &= ~(0x03 << shift);
+       cfg->pul[i] |= pull << shift;
 }
 
 static void
@@ -148,10 +328,22 @@
     const struct awin_gpio_pin_cfg *ncfg)
 {
        for (u_int i = 0; i < 4; i++) {
-               if (grp->grp_cfg.val[i] != ncfg->val[i]) {
+               if (grp->grp_cfg.cfg[i] != ncfg->cfg[i]) {
                        bus_space_write_4(bst, grp->grp_bsh,



Home | Main Index | Thread Index | Old Index