Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch Attach gpio(4) to sunxigpio
details: https://anonhg.NetBSD.org/src/rev/026d79e331ba
branches: trunk
changeset: 354964:026d79e331ba
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Thu Jul 06 10:44:19 2017 +0000
description:
Attach gpio(4) to sunxigpio
diffstat:
sys/arch/arm/sunxi/sunxi_gpio.c | 121 +++++++++++++++++++++++++++++++++++++++-
sys/arch/evbarm/conf/SUNXI | 4 +-
2 files changed, 120 insertions(+), 5 deletions(-)
diffs (258 lines):
diff -r 25fa8649e612 -r 026d79e331ba sys/arch/arm/sunxi/sunxi_gpio.c
--- a/sys/arch/arm/sunxi/sunxi_gpio.c Thu Jul 06 10:43:06 2017 +0000
+++ b/sys/arch/arm/sunxi/sunxi_gpio.c Thu Jul 06 10:44:19 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_gpio.c,v 1.4 2017/07/02 21:13:06 jmcneill Exp $ */
+/* $NetBSD: sunxi_gpio.c,v 1.5 2017/07/06 10:44:19 jmcneill Exp $ */
/*-
* Copyright (c) 2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
#include "opt_soc.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_gpio.c,v 1.4 2017/07/02 21:13:06 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_gpio.c,v 1.5 2017/07/06 10:44:19 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -41,6 +41,7 @@
#include <sys/gpio.h>
#include <dev/fdt/fdtvar.h>
+#include <dev/gpio/gpiovar.h>
#include <arm/sunxi/sunxi_gpio.h>
@@ -73,6 +74,11 @@
bus_space_tag_t sc_bst;
bus_space_handle_t sc_bsh;
const struct sunxi_gpio_padconf *sc_padconf;
+ kmutex_t sc_lock;
+
+ struct gpio_chipset_tag sc_gp;
+ gpio_pin_t *sc_pins;
+ device_t sc_gpiodev;
};
struct sunxi_gpio_pin {
@@ -130,6 +136,8 @@
uint32_t cfg;
u_int n;
+ KASSERT(mutex_owned(&sc->sc_lock));
+
const bus_size_t cfg_reg = SUNXI_GPIO_CFG(pin_def->port, pin_def->pin);
const uint32_t cfg_mask = SUNXI_GPIO_CFG_PINMASK(pin_def->pin);
@@ -162,6 +170,8 @@
{
uint32_t pull;
+ KASSERT(mutex_owned(&sc->sc_lock));
+
const bus_size_t pull_reg = SUNXI_GPIO_PULL(pin_def->port, pin_def->pin);
const uint32_t pull_mask = SUNXI_GPIO_PULL_PINMASK(pin_def->pin);
@@ -188,6 +198,8 @@
{
uint32_t drv;
+ KASSERT(mutex_owned(&sc->sc_lock));
+
if (drive_strength < 10 || drive_strength > 40)
return EINVAL;
@@ -210,6 +222,8 @@
sunxi_gpio_ctl(struct sunxi_gpio_softc *sc, const struct sunxi_gpio_pins *pin_def,
int flags)
{
+ KASSERT(mutex_owned(&sc->sc_lock));
+
if (flags & GPIO_PIN_INPUT)
return sunxi_gpio_setfunc(sc, pin_def, "gpio_in");
if (flags & GPIO_PIN_OUTPUT)
@@ -238,7 +252,10 @@
if (pin_def == NULL)
return NULL;
+ mutex_enter(&sc->sc_lock);
error = sunxi_gpio_ctl(sc, pin_def, flags);
+ mutex_exit(&sc->sc_lock);
+
if (error != 0)
return NULL;
@@ -275,6 +292,7 @@
const bus_size_t data_reg = SUNXI_GPIO_DATA(pin_def->port);
const uint32_t data_mask = __BIT(pin_def->pin);
+ /* No lock required for reads */
data = GPIO_READ(sc, data_reg);
val = __SHIFTOUT(data, data_mask);
if (!raw && pin->pin_actlo)
@@ -305,7 +323,7 @@
if (!raw && pin->pin_actlo)
val = !val;
- /* XXX locking */
+ mutex_enter(&sc->sc_lock);
data = GPIO_READ(sc, data_reg);
data &= ~data_mask;
data |= __SHIFTIN(val, data_mask);
@@ -314,6 +332,7 @@
pin_def->port + 'A', pin_def->pin, GPIO_READ(sc, data_reg), data);
#endif
GPIO_WRITE(sc, data_reg, data_mask);
+ mutex_exit(&sc->sc_lock);
}
static struct fdtbus_gpio_controller_func sunxi_gpio_funcs = {
@@ -348,6 +367,8 @@
return -1;
const char *pins = fdtbus_get_string(phandle, "pins");
+ mutex_enter(&sc->sc_lock);
+
for (pins = fdtbus_get_string(phandle, "pins");
pins_len > 0;
pins_len -= strlen(pins) + 1, pins += strlen(pins) + 1) {
@@ -370,6 +391,8 @@
sunxi_gpio_setdrv(sc, pin_def, drive_strength);
}
+ mutex_exit(&sc->sc_lock);
+
return 0;
}
@@ -378,6 +401,95 @@
};
static int
+sunxi_gpio_pin_read(void *priv, int pin)
+{
+ struct sunxi_gpio_softc * const sc = priv;
+ const struct sunxi_gpio_pins *pin_def = &sc->sc_padconf->pins[pin];
+ uint32_t data;
+ int val;
+
+ KASSERT(pin < sc->sc_padconf->npins);
+
+ const bus_size_t data_reg = SUNXI_GPIO_DATA(pin_def->port);
+ const uint32_t data_mask = __BIT(pin_def->pin);
+
+ /* No lock required for reads */
+ data = GPIO_READ(sc, data_reg);
+ val = __SHIFTOUT(data, data_mask);
+
+ return val;
+}
+
+static void
+sunxi_gpio_pin_write(void *priv, int pin, int val)
+{
+ struct sunxi_gpio_softc * const sc = priv;
+ const struct sunxi_gpio_pins *pin_def = &sc->sc_padconf->pins[pin];
+ uint32_t data;
+
+ KASSERT(pin < sc->sc_padconf->npins);
+
+ const bus_size_t data_reg = SUNXI_GPIO_DATA(pin_def->port);
+ const uint32_t data_mask = __BIT(pin_def->pin);
+
+ mutex_enter(&sc->sc_lock);
+ data = GPIO_READ(sc, data_reg);
+ if (val)
+ data |= data_mask;
+ else
+ data &= ~data_mask;
+ GPIO_WRITE(sc, data_reg, data);
+ mutex_exit(&sc->sc_lock);
+}
+
+static void
+sunxi_gpio_pin_ctl(void *priv, int pin, int flags)
+{
+ struct sunxi_gpio_softc * const sc = priv;
+ const struct sunxi_gpio_pins *pin_def = &sc->sc_padconf->pins[pin];
+
+ KASSERT(pin < sc->sc_padconf->npins);
+
+ mutex_enter(&sc->sc_lock);
+ sunxi_gpio_ctl(sc, pin_def, flags);
+ sunxi_gpio_setpull(sc, pin_def, flags);
+ mutex_exit(&sc->sc_lock);
+}
+
+static void
+sunxi_gpio_attach_ports(struct sunxi_gpio_softc *sc)
+{
+ const struct sunxi_gpio_pins *pin_def;
+ struct gpio_chipset_tag *gp = &sc->sc_gp;
+ struct gpiobus_attach_args gba;
+ u_int pin;
+
+ gp->gp_cookie = sc;
+ gp->gp_pin_read = sunxi_gpio_pin_read;
+ gp->gp_pin_write = sunxi_gpio_pin_write;
+ gp->gp_pin_ctl = sunxi_gpio_pin_ctl;
+
+ const u_int npins = sc->sc_padconf->npins;
+ sc->sc_pins = kmem_zalloc(sizeof(*sc->sc_pins) * npins, KM_SLEEP);
+
+ for (pin = 0; pin < sc->sc_padconf->npins; pin++) {
+ pin_def = &sc->sc_padconf->pins[pin];
+ sc->sc_pins[pin].pin_num = pin;
+ sc->sc_pins[pin].pin_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |
+ GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN;
+ sc->sc_pins[pin].pin_state = sunxi_gpio_pin_read(sc, pin);
+ strlcpy(sc->sc_pins[pin].pin_defname, pin_def->name,
+ sizeof(sc->sc_pins[pin].pin_defname));
+ }
+
+ memset(&gba, 0, sizeof(gba));
+ gba.gba_gc = gp;
+ gba.gba_pins = sc->sc_pins;
+ gba.gba_npins = npins;
+ sc->sc_gpiodev = config_found_ia(sc->sc_dev, "gpiobus", &gba, NULL);
+}
+
+static int
sunxi_gpio_match(device_t parent, cfdata_t cf, void *aux)
{
struct fdt_attach_args * const faa = aux;
@@ -406,6 +518,7 @@
aprint_error(": couldn't map registers\n");
return;
}
+ mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
sc->sc_padconf = (void *)of_search_compatible(phandle, compat_data)->data;
aprint_naive("\n");
@@ -420,4 +533,6 @@
}
fdtbus_pinctrl_configure();
+
+ sunxi_gpio_attach_ports(sc);
}
diff -r 25fa8649e612 -r 026d79e331ba sys/arch/evbarm/conf/SUNXI
--- a/sys/arch/evbarm/conf/SUNXI Thu Jul 06 10:43:06 2017 +0000
+++ b/sys/arch/evbarm/conf/SUNXI Thu Jul 06 10:44:19 2017 +0000
@@ -1,5 +1,5 @@
#
-# $NetBSD: SUNXI,v 1.10 2017/07/02 18:06:45 jmcneill Exp $
+# $NetBSD: SUNXI,v 1.11 2017/07/06 10:44:19 jmcneill Exp $
#
# Allwinner sunxi family
#
@@ -83,7 +83,7 @@
# GPIO controller
sunxigpio* at fdt? pass 2 # GPIO
-#gpio* at gpiobus?
+gpio* at gpiobus?
# Ethernet
sunxiemac* at fdt? # Allwinner Gigabit Ethernet
Home |
Main Index |
Thread Index |
Old Index