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