xref: /freebsd/sys/riscv/starfive/jh7110_gpio.c (revision c063fb7accae4cbe5e0fb808a1382600dc1b4249)
15bae2aceSJari Sihvola /*
25bae2aceSJari Sihvola  * SPDX-License-Identifier: BSD-2-Clause
35bae2aceSJari Sihvola  *
45bae2aceSJari Sihvola  * Copyright (c) 2023 Jari Sihvola <jsihv@gmx.com>
55bae2aceSJari Sihvola  */
65bae2aceSJari Sihvola 
75bae2aceSJari Sihvola #include <sys/cdefs.h>
85bae2aceSJari Sihvola 
95bae2aceSJari Sihvola #include <sys/param.h>
105bae2aceSJari Sihvola #include <sys/systm.h>
115bae2aceSJari Sihvola #include <sys/bus.h>
125bae2aceSJari Sihvola 
135bae2aceSJari Sihvola #include <sys/gpio.h>
145bae2aceSJari Sihvola #include <sys/kernel.h>
155bae2aceSJari Sihvola #include <sys/lock.h>
165bae2aceSJari Sihvola #include <sys/module.h>
175bae2aceSJari Sihvola #include <sys/mutex.h>
185bae2aceSJari Sihvola #include <sys/rman.h>
195bae2aceSJari Sihvola 
205bae2aceSJari Sihvola #include <machine/bus.h>
215bae2aceSJari Sihvola #include <machine/intr.h>
225bae2aceSJari Sihvola #include <machine/resource.h>
235bae2aceSJari Sihvola 
245bae2aceSJari Sihvola #include <dev/clk/clk.h>
255bae2aceSJari Sihvola #include <dev/gpio/gpiobusvar.h>
265bae2aceSJari Sihvola #include <dev/ofw/ofw_bus.h>
275bae2aceSJari Sihvola #include <dev/ofw/ofw_bus_subr.h>
285bae2aceSJari Sihvola 
295bae2aceSJari Sihvola #include "gpio_if.h"
305bae2aceSJari Sihvola 
315bae2aceSJari Sihvola #define GPIO_PINS		64
325bae2aceSJari Sihvola #define GPIO_REGS		2
335bae2aceSJari Sihvola 
345bae2aceSJari Sihvola #define GP0_DOEN_CFG		0x0
355bae2aceSJari Sihvola #define GP0_DOUT_CFG		0x40
365bae2aceSJari Sihvola #define GPIOEN			0xdc
375bae2aceSJari Sihvola #define GPIOE_0			0x100
385bae2aceSJari Sihvola #define GPIOE_1			0x104
395bae2aceSJari Sihvola #define GPIO_DIN_LOW		0x118
405bae2aceSJari Sihvola #define GPIO_DIN_HIGH		0x11c
415bae2aceSJari Sihvola #define IOMUX_SYSCFG_288	0x120
425bae2aceSJari Sihvola 
435bae2aceSJari Sihvola #define PAD_INPUT_EN		(1 << 0)
445bae2aceSJari Sihvola #define PAD_PULLUP		(1 << 3)
455bae2aceSJari Sihvola #define PAD_PULLDOWN		(1 << 4)
465bae2aceSJari Sihvola #define PAD_HYST		(1 << 6)
475bae2aceSJari Sihvola 
485bae2aceSJari Sihvola #define ENABLE_MASK		0x3f
495bae2aceSJari Sihvola #define DATA_OUT_MASK		0x7f
505bae2aceSJari Sihvola #define DIROUT_DISABLE		1
515bae2aceSJari Sihvola 
525bae2aceSJari Sihvola struct jh7110_gpio_softc {
535bae2aceSJari Sihvola 	device_t		dev;
545bae2aceSJari Sihvola 	device_t		busdev;
555bae2aceSJari Sihvola 	struct mtx		mtx;
565bae2aceSJari Sihvola 	struct resource		*res;
575bae2aceSJari Sihvola 	clk_t			clk;
585bae2aceSJari Sihvola };
595bae2aceSJari Sihvola 
605bae2aceSJari Sihvola static struct ofw_compat_data compat_data[] = {
615bae2aceSJari Sihvola 	{"starfive,jh7110-sys-pinctrl", 1},
625bae2aceSJari Sihvola 	{NULL,				0}
635bae2aceSJari Sihvola };
645bae2aceSJari Sihvola 
655bae2aceSJari Sihvola static struct resource_spec jh7110_gpio_spec[] = {
665bae2aceSJari Sihvola 	{ SYS_RES_MEMORY, 0, RF_ACTIVE },
675bae2aceSJari Sihvola 	{ -1, 0 }
685bae2aceSJari Sihvola };
695bae2aceSJari Sihvola 
705bae2aceSJari Sihvola #define GPIO_RW_OFFSET(_val)		(_val & ~3)
715bae2aceSJari Sihvola #define GPIO_SHIFT(_val)		((_val & 3) * 8)
725bae2aceSJari Sihvola #define PAD_OFFSET(_val)		(_val * 4)
735bae2aceSJari Sihvola 
745bae2aceSJari Sihvola #define JH7110_GPIO_LOCK(_sc)		mtx_lock(&(_sc)->mtx)
755bae2aceSJari Sihvola #define JH7110_GPIO_UNLOCK(_sc)		mtx_unlock(&(_sc)->mtx)
765bae2aceSJari Sihvola 
775bae2aceSJari Sihvola #define JH7110_GPIO_READ(sc, reg)	bus_read_4((sc)->res, (reg))
785bae2aceSJari Sihvola #define JH7110_GPIO_WRITE(sc, reg, val) bus_write_4((sc)->res, (reg), (val))
795bae2aceSJari Sihvola 
805bae2aceSJari Sihvola static device_t
jh7110_gpio_get_bus(device_t dev)815bae2aceSJari Sihvola jh7110_gpio_get_bus(device_t dev)
825bae2aceSJari Sihvola {
835bae2aceSJari Sihvola 	struct jh7110_gpio_softc *sc;
845bae2aceSJari Sihvola 
855bae2aceSJari Sihvola 	sc = device_get_softc(dev);
865bae2aceSJari Sihvola 
875bae2aceSJari Sihvola 	return (sc->busdev);
885bae2aceSJari Sihvola }
895bae2aceSJari Sihvola 
905bae2aceSJari Sihvola static int
jh7110_gpio_pin_max(device_t dev,int * maxpin)915bae2aceSJari Sihvola jh7110_gpio_pin_max(device_t dev, int *maxpin)
925bae2aceSJari Sihvola {
935bae2aceSJari Sihvola 	*maxpin = GPIO_PINS - 1;
945bae2aceSJari Sihvola 
955bae2aceSJari Sihvola 	return (0);
965bae2aceSJari Sihvola }
975bae2aceSJari Sihvola 
985bae2aceSJari Sihvola static int
jh7110_gpio_pin_get(device_t dev,uint32_t pin,unsigned int * val)995bae2aceSJari Sihvola jh7110_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
1005bae2aceSJari Sihvola {
1015bae2aceSJari Sihvola 	struct jh7110_gpio_softc *sc;
1025bae2aceSJari Sihvola 	uint32_t reg;
1035bae2aceSJari Sihvola 
1045bae2aceSJari Sihvola 	sc = device_get_softc(dev);
1055bae2aceSJari Sihvola 
1065bae2aceSJari Sihvola 	if (pin >= GPIO_PINS)
1075bae2aceSJari Sihvola 		return (EINVAL);
1085bae2aceSJari Sihvola 
1095bae2aceSJari Sihvola 	JH7110_GPIO_LOCK(sc);
1105bae2aceSJari Sihvola 	if (pin < GPIO_PINS / GPIO_REGS) {
1115bae2aceSJari Sihvola 		reg = JH7110_GPIO_READ(sc, GPIO_DIN_LOW);
1125bae2aceSJari Sihvola 		*val = (reg >> pin) & 0x1;
1135bae2aceSJari Sihvola 	} else {
1145bae2aceSJari Sihvola 		reg = JH7110_GPIO_READ(sc, GPIO_DIN_HIGH);
1155bae2aceSJari Sihvola 		*val = (reg >> (pin - GPIO_PINS / GPIO_REGS)) & 0x1;
1165bae2aceSJari Sihvola 	}
1175bae2aceSJari Sihvola 	JH7110_GPIO_UNLOCK(sc);
1185bae2aceSJari Sihvola 
1195bae2aceSJari Sihvola 	return (0);
1205bae2aceSJari Sihvola }
1215bae2aceSJari Sihvola 
1225bae2aceSJari Sihvola static int
jh7110_gpio_pin_set(device_t dev,uint32_t pin,unsigned int value)1235bae2aceSJari Sihvola jh7110_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
1245bae2aceSJari Sihvola {
1255bae2aceSJari Sihvola 	struct jh7110_gpio_softc *sc;
1265bae2aceSJari Sihvola 	uint32_t reg;
1275bae2aceSJari Sihvola 
1285bae2aceSJari Sihvola 	sc = device_get_softc(dev);
1295bae2aceSJari Sihvola 
1305bae2aceSJari Sihvola 	if (pin >= GPIO_PINS)
1315bae2aceSJari Sihvola 		return (EINVAL);
1325bae2aceSJari Sihvola 
1335bae2aceSJari Sihvola 	JH7110_GPIO_LOCK(sc);
1345bae2aceSJari Sihvola 	reg = JH7110_GPIO_READ(sc, GP0_DOUT_CFG + GPIO_RW_OFFSET(pin));
1355bae2aceSJari Sihvola 	reg &= ~(DATA_OUT_MASK << GPIO_SHIFT(pin));
1365bae2aceSJari Sihvola 	if (value)
1375bae2aceSJari Sihvola 		reg |= 0x1 << GPIO_SHIFT(pin);
1385bae2aceSJari Sihvola 	JH7110_GPIO_WRITE(sc, GP0_DOUT_CFG + GPIO_RW_OFFSET(pin), reg);
1395bae2aceSJari Sihvola 	JH7110_GPIO_UNLOCK(sc);
1405bae2aceSJari Sihvola 
1415bae2aceSJari Sihvola 	return (0);
1425bae2aceSJari Sihvola }
1435bae2aceSJari Sihvola 
1445bae2aceSJari Sihvola static int
jh7110_gpio_pin_toggle(device_t dev,uint32_t pin)1455bae2aceSJari Sihvola jh7110_gpio_pin_toggle(device_t dev, uint32_t pin)
1465bae2aceSJari Sihvola {
1475bae2aceSJari Sihvola 	struct jh7110_gpio_softc *sc;
1485bae2aceSJari Sihvola 	uint32_t reg;
1495bae2aceSJari Sihvola 
1505bae2aceSJari Sihvola 	sc = device_get_softc(dev);
1515bae2aceSJari Sihvola 
1525bae2aceSJari Sihvola 	if (pin >= GPIO_PINS)
1535bae2aceSJari Sihvola 		return (EINVAL);
1545bae2aceSJari Sihvola 
1555bae2aceSJari Sihvola 	JH7110_GPIO_LOCK(sc);
1565bae2aceSJari Sihvola 	reg = JH7110_GPIO_READ(sc, GP0_DOUT_CFG + GPIO_RW_OFFSET(pin));
1575bae2aceSJari Sihvola 	if (reg & 0x1 << GPIO_SHIFT(pin)) {
1585bae2aceSJari Sihvola 		reg &= ~(DATA_OUT_MASK << GPIO_SHIFT(pin));
1595bae2aceSJari Sihvola 	} else {
1605bae2aceSJari Sihvola 		reg &= ~(DATA_OUT_MASK << GPIO_SHIFT(pin));
1615bae2aceSJari Sihvola 		reg |= 0x1 << GPIO_SHIFT(pin);
1625bae2aceSJari Sihvola 	}
1635bae2aceSJari Sihvola 	JH7110_GPIO_WRITE(sc, GP0_DOUT_CFG + GPIO_RW_OFFSET(pin), reg);
1645bae2aceSJari Sihvola 	JH7110_GPIO_UNLOCK(sc);
1655bae2aceSJari Sihvola 
1665bae2aceSJari Sihvola 	return (0);
1675bae2aceSJari Sihvola }
1685bae2aceSJari Sihvola 
1695bae2aceSJari Sihvola static int
jh7110_gpio_pin_getcaps(device_t dev,uint32_t pin,uint32_t * caps)1705bae2aceSJari Sihvola jh7110_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
1715bae2aceSJari Sihvola {
1725bae2aceSJari Sihvola 	if (pin >= GPIO_PINS)
1735bae2aceSJari Sihvola 		return (EINVAL);
1745bae2aceSJari Sihvola 
1755bae2aceSJari Sihvola 	*caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT);
1765bae2aceSJari Sihvola 
1775bae2aceSJari Sihvola 	return (0);
1785bae2aceSJari Sihvola }
1795bae2aceSJari Sihvola 
1805bae2aceSJari Sihvola static int
jh7110_gpio_pin_getname(device_t dev,uint32_t pin,char * name)1815bae2aceSJari Sihvola jh7110_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
1825bae2aceSJari Sihvola {
1835bae2aceSJari Sihvola 	if (pin >= GPIO_PINS)
1845bae2aceSJari Sihvola 		return (EINVAL);
1855bae2aceSJari Sihvola 
1865bae2aceSJari Sihvola 	snprintf(name, GPIOMAXNAME, "GPIO%d", pin);
1875bae2aceSJari Sihvola 
1885bae2aceSJari Sihvola 	return (0);
1895bae2aceSJari Sihvola }
1905bae2aceSJari Sihvola 
1915bae2aceSJari Sihvola static int
jh7110_gpio_pin_getflags(device_t dev,uint32_t pin,uint32_t * flags)1925bae2aceSJari Sihvola jh7110_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
1935bae2aceSJari Sihvola {
1945bae2aceSJari Sihvola 	struct jh7110_gpio_softc *sc;
1955bae2aceSJari Sihvola 	uint32_t reg;
1965bae2aceSJari Sihvola 
1975bae2aceSJari Sihvola 	sc = device_get_softc(dev);
1985bae2aceSJari Sihvola 
1995bae2aceSJari Sihvola 	if (pin >= GPIO_PINS)
2005bae2aceSJari Sihvola 		return (EINVAL);
2015bae2aceSJari Sihvola 
2025bae2aceSJari Sihvola 	/* Reading the direction */
2035bae2aceSJari Sihvola 	JH7110_GPIO_LOCK(sc);
2045bae2aceSJari Sihvola 	reg = JH7110_GPIO_READ(sc, GP0_DOEN_CFG + GPIO_RW_OFFSET(pin));
2055bae2aceSJari Sihvola 	if ((reg & ENABLE_MASK << GPIO_SHIFT(pin)) == 0)
2065bae2aceSJari Sihvola 		*flags |= GPIO_PIN_OUTPUT;
2075bae2aceSJari Sihvola 	else
2085bae2aceSJari Sihvola 		*flags |= GPIO_PIN_INPUT;
2095bae2aceSJari Sihvola 	JH7110_GPIO_UNLOCK(sc);
2105bae2aceSJari Sihvola 
2115bae2aceSJari Sihvola 	return (0);
2125bae2aceSJari Sihvola }
2135bae2aceSJari Sihvola 
2145bae2aceSJari Sihvola static int
jh7110_gpio_pin_setflags(device_t dev,uint32_t pin,uint32_t flags)2155bae2aceSJari Sihvola jh7110_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
2165bae2aceSJari Sihvola {
2175bae2aceSJari Sihvola 	struct jh7110_gpio_softc *sc;
2185bae2aceSJari Sihvola 	uint32_t reg;
2195bae2aceSJari Sihvola 
2205bae2aceSJari Sihvola 	sc = device_get_softc(dev);
2215bae2aceSJari Sihvola 
2225bae2aceSJari Sihvola 	if (pin >= GPIO_PINS)
2235bae2aceSJari Sihvola 		return (EINVAL);
2245bae2aceSJari Sihvola 
2255bae2aceSJari Sihvola 	/* Setting the direction, enable or disable output, configuring pads */
2265bae2aceSJari Sihvola 
2275bae2aceSJari Sihvola 	JH7110_GPIO_LOCK(sc);
2285bae2aceSJari Sihvola 
2295bae2aceSJari Sihvola 	if (flags & GPIO_PIN_INPUT) {
2305bae2aceSJari Sihvola 		reg = JH7110_GPIO_READ(sc, IOMUX_SYSCFG_288 + PAD_OFFSET(pin));
2315bae2aceSJari Sihvola 		reg |= (PAD_INPUT_EN | PAD_HYST);
2325bae2aceSJari Sihvola 		JH7110_GPIO_WRITE(sc, IOMUX_SYSCFG_288 + PAD_OFFSET(pin), reg);
2335bae2aceSJari Sihvola 	}
2345bae2aceSJari Sihvola 
2355bae2aceSJari Sihvola 	reg = JH7110_GPIO_READ(sc, GP0_DOEN_CFG + GPIO_RW_OFFSET(pin));
2365bae2aceSJari Sihvola 	reg &= ~(ENABLE_MASK << GPIO_SHIFT(pin));
2375bae2aceSJari Sihvola 	if (flags & GPIO_PIN_INPUT) {
2385bae2aceSJari Sihvola 		reg |= DIROUT_DISABLE << GPIO_SHIFT(pin);
2395bae2aceSJari Sihvola 	}
2405bae2aceSJari Sihvola 	JH7110_GPIO_WRITE(sc, GP0_DOEN_CFG + GPIO_RW_OFFSET(pin), reg);
2415bae2aceSJari Sihvola 
2425bae2aceSJari Sihvola 	if (flags & GPIO_PIN_OUTPUT) {
2435bae2aceSJari Sihvola 		reg = JH7110_GPIO_READ(sc, GP0_DOUT_CFG + GPIO_RW_OFFSET(pin));
2445bae2aceSJari Sihvola 		reg &= ~(ENABLE_MASK << GPIO_SHIFT(pin));
2455bae2aceSJari Sihvola 		reg |= 0x1 << GPIO_SHIFT(pin);
2465bae2aceSJari Sihvola 		JH7110_GPIO_WRITE(sc, GP0_DOUT_CFG + GPIO_RW_OFFSET(pin), reg);
2475bae2aceSJari Sihvola 
2485bae2aceSJari Sihvola 		reg = JH7110_GPIO_READ(sc, IOMUX_SYSCFG_288 + PAD_OFFSET(pin));
2495bae2aceSJari Sihvola 		reg &= ~(PAD_INPUT_EN | PAD_PULLUP | PAD_PULLDOWN | PAD_HYST);
2505bae2aceSJari Sihvola 		JH7110_GPIO_WRITE(sc, IOMUX_SYSCFG_288 + PAD_OFFSET(pin), reg);
2515bae2aceSJari Sihvola 	}
2525bae2aceSJari Sihvola 
2535bae2aceSJari Sihvola 	JH7110_GPIO_UNLOCK(sc);
2545bae2aceSJari Sihvola 
2555bae2aceSJari Sihvola 	return (0);
2565bae2aceSJari Sihvola }
2575bae2aceSJari Sihvola 
2585bae2aceSJari Sihvola static int
jh7110_gpio_probe(device_t dev)2595bae2aceSJari Sihvola jh7110_gpio_probe(device_t dev)
2605bae2aceSJari Sihvola {
2615bae2aceSJari Sihvola 	if (!ofw_bus_status_okay(dev))
2625bae2aceSJari Sihvola 		return (ENXIO);
2635bae2aceSJari Sihvola 
2645bae2aceSJari Sihvola 	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
2655bae2aceSJari Sihvola 		return (ENXIO);
2665bae2aceSJari Sihvola 
2675bae2aceSJari Sihvola 	device_set_desc(dev, "StarFive JH7110 GPIO controller");
2685bae2aceSJari Sihvola 
2695bae2aceSJari Sihvola 	return (BUS_PROBE_DEFAULT);
2705bae2aceSJari Sihvola }
2715bae2aceSJari Sihvola 
2725bae2aceSJari Sihvola static int
jh7110_gpio_detach(device_t dev)2735bae2aceSJari Sihvola jh7110_gpio_detach(device_t dev)
2745bae2aceSJari Sihvola {
2755bae2aceSJari Sihvola 	struct jh7110_gpio_softc *sc;
2765bae2aceSJari Sihvola 
2775bae2aceSJari Sihvola 	sc = device_get_softc(dev);
2785bae2aceSJari Sihvola 
2795bae2aceSJari Sihvola 	bus_release_resources(dev, jh7110_gpio_spec, &sc->res);
2805bae2aceSJari Sihvola 	if (sc->busdev != NULL)
2815bae2aceSJari Sihvola 		gpiobus_detach_bus(dev);
2825bae2aceSJari Sihvola 	if (sc->clk != NULL)
2835bae2aceSJari Sihvola 		clk_release(sc->clk);
2845bae2aceSJari Sihvola 	mtx_destroy(&sc->mtx);
2855bae2aceSJari Sihvola 
2865bae2aceSJari Sihvola 	return (0);
2875bae2aceSJari Sihvola }
2885bae2aceSJari Sihvola 
2895bae2aceSJari Sihvola static int
jh7110_gpio_attach(device_t dev)2905bae2aceSJari Sihvola jh7110_gpio_attach(device_t dev)
2915bae2aceSJari Sihvola {
2925bae2aceSJari Sihvola 	struct jh7110_gpio_softc *sc;
2935bae2aceSJari Sihvola 
2945bae2aceSJari Sihvola 	sc = device_get_softc(dev);
2955bae2aceSJari Sihvola 	sc->dev = dev;
2965bae2aceSJari Sihvola 
2975bae2aceSJari Sihvola 	mtx_init(&sc->mtx, device_get_nameunit(sc->dev), NULL, MTX_DEF);
2985bae2aceSJari Sihvola 
2995bae2aceSJari Sihvola 	if (bus_alloc_resources(dev, jh7110_gpio_spec, &sc->res) != 0) {
3005bae2aceSJari Sihvola 		device_printf(dev, "Could not allocate resources\n");
3015bae2aceSJari Sihvola 		bus_release_resources(dev, jh7110_gpio_spec, &sc->res);
3025bae2aceSJari Sihvola 		mtx_destroy(&sc->mtx);
3035bae2aceSJari Sihvola 		return (ENXIO);
3045bae2aceSJari Sihvola 	}
3055bae2aceSJari Sihvola 
3065bae2aceSJari Sihvola 	if (clk_get_by_ofw_index(dev, 0, 0, &sc->clk) != 0) {
3075bae2aceSJari Sihvola 		device_printf(dev, "Cannot get clock\n");
3085bae2aceSJari Sihvola 		jh7110_gpio_detach(dev);
3095bae2aceSJari Sihvola 		return (ENXIO);
3105bae2aceSJari Sihvola 	}
3115bae2aceSJari Sihvola 
3125bae2aceSJari Sihvola 	if (clk_enable(sc->clk) != 0) {
3135bae2aceSJari Sihvola 		device_printf(dev, "Could not enable clock %s\n",
3145bae2aceSJari Sihvola 		    clk_get_name(sc->clk));
3155bae2aceSJari Sihvola 		jh7110_gpio_detach(dev);
3165bae2aceSJari Sihvola 		return (ENXIO);
3175bae2aceSJari Sihvola 	}
3185bae2aceSJari Sihvola 
3195bae2aceSJari Sihvola 	/* Reseting GPIO interrupts */
3205bae2aceSJari Sihvola 	JH7110_GPIO_WRITE(sc, GPIOE_0, 0);
3215bae2aceSJari Sihvola 	JH7110_GPIO_WRITE(sc, GPIOE_1, 0);
3225bae2aceSJari Sihvola 	JH7110_GPIO_WRITE(sc, GPIOEN, 1);
3235bae2aceSJari Sihvola 
324*c063fb7aSAhmad Khalifa 	sc->busdev = gpiobus_add_bus(dev);
3255bae2aceSJari Sihvola 	if (sc->busdev == NULL) {
3265bae2aceSJari Sihvola 		device_printf(dev, "Cannot attach gpiobus\n");
3275bae2aceSJari Sihvola 		jh7110_gpio_detach(dev);
3285bae2aceSJari Sihvola 		return (ENXIO);
3295bae2aceSJari Sihvola 	}
3305bae2aceSJari Sihvola 
331*c063fb7aSAhmad Khalifa 	bus_attach_children(dev);
3325bae2aceSJari Sihvola 	return (0);
3335bae2aceSJari Sihvola }
3345bae2aceSJari Sihvola 
3355bae2aceSJari Sihvola static phandle_t
jh7110_gpio_get_node(device_t bus,device_t dev)3365bae2aceSJari Sihvola jh7110_gpio_get_node(device_t bus, device_t dev)
3375bae2aceSJari Sihvola {
3385bae2aceSJari Sihvola 	return (ofw_bus_get_node(bus));
3395bae2aceSJari Sihvola }
3405bae2aceSJari Sihvola 
3415bae2aceSJari Sihvola static device_method_t jh7110_gpio_methods[] = {
3425bae2aceSJari Sihvola 	/* Device interface */
3435bae2aceSJari Sihvola 	DEVMETHOD(device_probe,		jh7110_gpio_probe),
3445bae2aceSJari Sihvola 	DEVMETHOD(device_attach,	jh7110_gpio_attach),
3455bae2aceSJari Sihvola 	DEVMETHOD(device_detach,	jh7110_gpio_detach),
3465bae2aceSJari Sihvola 
3475bae2aceSJari Sihvola 	/* GPIO protocol */
3485bae2aceSJari Sihvola 	DEVMETHOD(gpio_get_bus,		jh7110_gpio_get_bus),
3495bae2aceSJari Sihvola 	DEVMETHOD(gpio_pin_max,		jh7110_gpio_pin_max),
3505bae2aceSJari Sihvola 	DEVMETHOD(gpio_pin_get,		jh7110_gpio_pin_get),
3515bae2aceSJari Sihvola 	DEVMETHOD(gpio_pin_set,		jh7110_gpio_pin_set),
3525bae2aceSJari Sihvola 	DEVMETHOD(gpio_pin_toggle,	jh7110_gpio_pin_toggle),
3535bae2aceSJari Sihvola 	DEVMETHOD(gpio_pin_getflags,	jh7110_gpio_pin_getflags),
3545bae2aceSJari Sihvola 	DEVMETHOD(gpio_pin_setflags,	jh7110_gpio_pin_setflags),
3555bae2aceSJari Sihvola 	DEVMETHOD(gpio_pin_getcaps,	jh7110_gpio_pin_getcaps),
3565bae2aceSJari Sihvola 	DEVMETHOD(gpio_pin_getname,	jh7110_gpio_pin_getname),
3575bae2aceSJari Sihvola 
3585bae2aceSJari Sihvola 	/* ofw_bus interface */
3595bae2aceSJari Sihvola 	DEVMETHOD(ofw_bus_get_node,	jh7110_gpio_get_node),
3605bae2aceSJari Sihvola 
3615bae2aceSJari Sihvola 	DEVMETHOD_END
3625bae2aceSJari Sihvola };
3635bae2aceSJari Sihvola 
3645bae2aceSJari Sihvola DEFINE_CLASS_0(gpio, jh7110_gpio_driver, jh7110_gpio_methods,
3655bae2aceSJari Sihvola     sizeof(struct jh7110_gpio_softc));
3665bae2aceSJari Sihvola EARLY_DRIVER_MODULE(jh7110_gpio, simplebus, jh7110_gpio_driver, 0, 0,
3675bae2aceSJari Sihvola     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
3685bae2aceSJari Sihvola MODULE_DEPEND(jh7110_gpio, gpiobus, 1, 1, 1);
369