Page MenuHomeFreeBSD
Paste P663

WIP JH7110 GPIO improvements
ActivePublic

Authored by mhorne on Jul 11 2025, 6:38 PM.
Tags
None
Referenced Files
F123163857: WIP JH7110 GPIO improvements
Jul 11 2025, 6:38 PM
Subscribers
None
commit f0ae126708edb44ac3956cef4b8b87eb28f9482f
Author: Mitchell Horne <mhorne@FreeBSD.org>
Date: Tue Dec 10 16:38:14 2024 -0400
WIP: JH7110 GPIO updates/improvements
diff --git a/sys/riscv/starfive/files.starfive b/sys/riscv/starfive/files.starfive
index 043421f37e2c..5da00b9acbef 100644
--- a/sys/riscv/starfive/files.starfive
+++ b/sys/riscv/starfive/files.starfive
@@ -2,7 +2,7 @@ dev/clk/starfive/jh7110_clk.c standard
dev/clk/starfive/jh7110_clk_aon.c standard
dev/clk/starfive/jh7110_clk_pll.c standard
dev/clk/starfive/jh7110_clk_sys.c standard
-dev/clk/starfive/jh7110_gpio.c optional gpio fdt
+dev/clk/starfive/jh7110_clk_stg.c standard
dev/mmc/host/dwmmc_starfive.c optional dwmmc_starfive fdt
dev/usb/controller/cdns3/cdns3_starfive.c standard
@@ -10,4 +10,5 @@ dev/eqos/if_eqos.c optional eqos
dev/eqos/if_eqos_if.m optional eqos
dev/eqos/if_eqos_starfive.c optional eqos
+riscv/starfive/jh7110_gpio.c optional gpio fdt
riscv/starfive/starfive_syscon.c standard
diff --git a/sys/riscv/starfive/jh7110_gpio.c b/sys/riscv/starfive/jh7110_gpio.c
index a71e45687d4d..9be0ee3704f5 100644
--- a/sys/riscv/starfive/jh7110_gpio.c
+++ b/sys/riscv/starfive/jh7110_gpio.c
@@ -45,6 +45,7 @@ struct jh7110_gpio_softc {
struct mtx mtx;
struct resource *res;
clk_t clk;
+ struct gpio_pin gpio_pins[JH7110_GPIO_PINS];
};
static struct ofw_compat_data compat_data[] = {
@@ -129,24 +130,52 @@ jh7110_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
return (0);
}
+static int
+jh7110_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+ struct jh7110_gpio_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (pin >= JH7110_GPIO_PINS)
+ return (EINVAL);
+
+ JH7110_GPIO_LOCK(sc);
+ *caps = sc->gpio_pins[pin].gp_caps;
+ JH7110_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
static int
jh7110_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
{
struct jh7110_gpio_softc *sc;
- uint32_t reg;
sc = device_get_softc(dev);
if (pin >= JH7110_GPIO_PINS)
return (EINVAL);
- /* Reading the direction */
JH7110_GPIO_LOCK(sc);
- reg = JH7110_GPIO_READ(sc, GP0_DOEN_CFG + ALIGN_4(pin));
- if ((reg & ENABLE_MASK << MOD_4(pin) * 8) == 0)
- *flags |= GPIO_PIN_OUTPUT;
- else
- *flags |= GPIO_PIN_INPUT;
+ *flags = sc->gpio_pins[pin].gp_flags;
+ JH7110_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+jh7110_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+ struct jh7110_gpio_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (pin >= JH7110_GPIO_PINS)
+ return (EINVAL);
+
+ JH7110_GPIO_LOCK(sc);
+ memcpy(name, sc->gpio_pins[pin].gp_name, GPIOMAXNAME);
JH7110_GPIO_UNLOCK(sc);
return (0);
@@ -166,16 +195,22 @@ jh7110_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
/* Setting the direction, enable or disable output */
JH7110_GPIO_LOCK(sc);
- if (flags & GPIO_PIN_INPUT) {
+ if ((flags & GPIO_PIN_INPUT) != 0) {
reg = JH7110_GPIO_READ(sc, GP0_DOUT_CFG + ALIGN_4(pin));
reg &= ~(ENABLE_MASK << MOD_4(pin) * 8);
reg |= 1 << MOD_4(pin) * 8;
JH7110_GPIO_WRITE(sc, GP0_DOUT_CFG + ALIGN_4(pin), reg);
- } else if (flags & GPIO_PIN_OUTPUT) {
+
+ sc->gpio_pins[pin].gp_flags &= ~GPIO_PIN_OUTPUT;
+ sc->gpio_pins[pin].gp_flags |= GPIO_PIN_INPUT;
+ } else if ((flags & GPIO_PIN_OUTPUT) != 0) {
reg = JH7110_GPIO_READ(sc, GP0_DOUT_CFG + ALIGN_4(pin));
reg &= ~(ENABLE_MASK << MOD_4(pin) * 8);
reg |= 0 << MOD_4(pin) * 8;
JH7110_GPIO_WRITE(sc, GP0_DOUT_CFG + ALIGN_4(pin), reg);
+
+ sc->gpio_pins[pin].gp_flags &= ~GPIO_PIN_INPUT;
+ sc->gpio_pins[pin].gp_flags |= GPIO_PIN_OUTPUT;
}
JH7110_GPIO_UNLOCK(sc);
@@ -203,8 +238,11 @@ jh7110_gpio_detach(device_t dev)
sc = device_get_softc(dev);
- bus_release_resources(dev, jh7110_gpio_spec, &sc->res);
gpiobus_detach_bus(dev);
+ if (sc->clk != NULL) {
+ clk_release(sc->clk);
+ }
+ bus_release_resources(dev, jh7110_gpio_spec, &sc->res);
mtx_destroy(&sc->mtx);
return (0);
@@ -214,16 +252,15 @@ static int
jh7110_gpio_attach(device_t dev)
{
struct jh7110_gpio_softc *sc;
- int err;
+ uint32_t reg;
sc = device_get_softc(dev);
sc->dev = dev;
mtx_init(&sc->mtx, device_get_nameunit(sc->dev), NULL, MTX_DEF);
- if (bus_alloc_resources(dev, jh7110_gpio_spec, &sc->res)) {
+ if (bus_alloc_resources(dev, jh7110_gpio_spec, &sc->res) != 0) {
device_printf(dev, "Could not allocate resources\n");
- bus_release_resources(dev, jh7110_gpio_spec, &sc->res);
mtx_destroy(&sc->mtx);
return (ENXIO);
}
@@ -234,8 +271,7 @@ jh7110_gpio_attach(device_t dev)
return (ENXIO);
}
- err = clk_enable(sc->clk);
- if (err != 0) {
+ if (clk_enable(sc->clk) != 0) {
device_printf(dev, "Could not enable clock %s\n",
clk_get_name(sc->clk));
jh7110_gpio_detach(dev);
@@ -249,7 +285,19 @@ jh7110_gpio_attach(device_t dev)
return (ENXIO);
}
- /* Reseting GPIO interrupts */
+ for (int i = 0; i < JH7110_GPIO_PINS; i++) {
+ reg = JH7110_GPIO_READ(sc, GP0_DOEN_CFG + ALIGN_4(i));
+
+ sc->gpio_pins[i].gp_pin = i;
+ sc->gpio_pins[i].gp_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
+ sc->gpio_pins[i].gp_flags =
+ ((reg & ENABLE_MASK << MOD_4(i) * 8) == 0) ?
+ GPIO_PIN_INPUT : GPIO_PIN_OUTPUT;
+
+ snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME, "GPIO %d", i);
+ }
+
+ /* Disable all GPIO interrupts. */
JH7110_GPIO_WRITE(sc, GPIOE_0, 0);
JH7110_GPIO_WRITE(sc, GPIOE_1, 0);
JH7110_GPIO_WRITE(sc, GPIOEN, 1);
@@ -272,8 +320,10 @@ static device_method_t jh7110_gpio_methods[] = {
/* GPIO protocol */
DEVMETHOD(gpio_get_bus, jh7110_gpio_get_bus),
DEVMETHOD(gpio_pin_max, jh7110_gpio_pin_max),
+ DEVMETHOD(gpio_pin_getcaps, jh7110_gpio_pin_getcaps),
DEVMETHOD(gpio_pin_getflags, jh7110_gpio_pin_getflags),
DEVMETHOD(gpio_pin_setflags, jh7110_gpio_pin_setflags),
+ DEVMETHOD(gpio_pin_getname, jh7110_gpio_pin_getname),
DEVMETHOD(gpio_pin_get, jh7110_gpio_pin_get),
DEVMETHOD(gpio_pin_set, jh7110_gpio_pin_set),