xref: /freebsd/sys/riscv/starfive/jh7110_gpio.c (revision 5bae2ace2e55de034cd62d3bae95a202de848eab)
1*5bae2aceSJari Sihvola /*
2*5bae2aceSJari Sihvola  * SPDX-License-Identifier: BSD-2-Clause
3*5bae2aceSJari Sihvola  *
4*5bae2aceSJari Sihvola  * Copyright (c) 2023 Jari Sihvola <jsihv@gmx.com>
5*5bae2aceSJari Sihvola  */
6*5bae2aceSJari Sihvola 
7*5bae2aceSJari Sihvola #include <sys/cdefs.h>
8*5bae2aceSJari Sihvola 
9*5bae2aceSJari Sihvola #include <sys/param.h>
10*5bae2aceSJari Sihvola #include <sys/systm.h>
11*5bae2aceSJari Sihvola #include <sys/bus.h>
12*5bae2aceSJari Sihvola 
13*5bae2aceSJari Sihvola #include <sys/gpio.h>
14*5bae2aceSJari Sihvola #include <sys/kernel.h>
15*5bae2aceSJari Sihvola #include <sys/lock.h>
16*5bae2aceSJari Sihvola #include <sys/module.h>
17*5bae2aceSJari Sihvola #include <sys/mutex.h>
18*5bae2aceSJari Sihvola #include <sys/rman.h>
19*5bae2aceSJari Sihvola 
20*5bae2aceSJari Sihvola #include <machine/bus.h>
21*5bae2aceSJari Sihvola #include <machine/intr.h>
22*5bae2aceSJari Sihvola #include <machine/resource.h>
23*5bae2aceSJari Sihvola 
24*5bae2aceSJari Sihvola #include <dev/clk/clk.h>
25*5bae2aceSJari Sihvola #include <dev/gpio/gpiobusvar.h>
26*5bae2aceSJari Sihvola #include <dev/ofw/ofw_bus.h>
27*5bae2aceSJari Sihvola #include <dev/ofw/ofw_bus_subr.h>
28*5bae2aceSJari Sihvola 
29*5bae2aceSJari Sihvola #include "gpio_if.h"
30*5bae2aceSJari Sihvola 
31*5bae2aceSJari Sihvola #define GPIO_PINS		64
32*5bae2aceSJari Sihvola #define GPIO_REGS		2
33*5bae2aceSJari Sihvola 
34*5bae2aceSJari Sihvola #define GP0_DOEN_CFG		0x0
35*5bae2aceSJari Sihvola #define GP0_DOUT_CFG		0x40
36*5bae2aceSJari Sihvola #define GPIOEN			0xdc
37*5bae2aceSJari Sihvola #define GPIOE_0			0x100
38*5bae2aceSJari Sihvola #define GPIOE_1			0x104
39*5bae2aceSJari Sihvola #define GPIO_DIN_LOW		0x118
40*5bae2aceSJari Sihvola #define GPIO_DIN_HIGH		0x11c
41*5bae2aceSJari Sihvola #define IOMUX_SYSCFG_288	0x120
42*5bae2aceSJari Sihvola 
43*5bae2aceSJari Sihvola #define PAD_INPUT_EN		(1 << 0)
44*5bae2aceSJari Sihvola #define PAD_PULLUP		(1 << 3)
45*5bae2aceSJari Sihvola #define PAD_PULLDOWN		(1 << 4)
46*5bae2aceSJari Sihvola #define PAD_HYST		(1 << 6)
47*5bae2aceSJari Sihvola 
48*5bae2aceSJari Sihvola #define ENABLE_MASK		0x3f
49*5bae2aceSJari Sihvola #define DATA_OUT_MASK		0x7f
50*5bae2aceSJari Sihvola #define DIROUT_DISABLE		1
51*5bae2aceSJari Sihvola 
52*5bae2aceSJari Sihvola struct jh7110_gpio_softc {
53*5bae2aceSJari Sihvola 	device_t		dev;
54*5bae2aceSJari Sihvola 	device_t		busdev;
55*5bae2aceSJari Sihvola 	struct mtx		mtx;
56*5bae2aceSJari Sihvola 	struct resource		*res;
57*5bae2aceSJari Sihvola 	clk_t			clk;
58*5bae2aceSJari Sihvola };
59*5bae2aceSJari Sihvola 
60*5bae2aceSJari Sihvola static struct ofw_compat_data compat_data[] = {
61*5bae2aceSJari Sihvola 	{"starfive,jh7110-sys-pinctrl", 1},
62*5bae2aceSJari Sihvola 	{NULL,				0}
63*5bae2aceSJari Sihvola };
64*5bae2aceSJari Sihvola 
65*5bae2aceSJari Sihvola static struct resource_spec jh7110_gpio_spec[] = {
66*5bae2aceSJari Sihvola 	{ SYS_RES_MEMORY, 0, RF_ACTIVE },
67*5bae2aceSJari Sihvola 	{ -1, 0 }
68*5bae2aceSJari Sihvola };
69*5bae2aceSJari Sihvola 
70*5bae2aceSJari Sihvola #define GPIO_RW_OFFSET(_val)		(_val & ~3)
71*5bae2aceSJari Sihvola #define GPIO_SHIFT(_val)		((_val & 3) * 8)
72*5bae2aceSJari Sihvola #define PAD_OFFSET(_val)		(_val * 4)
73*5bae2aceSJari Sihvola 
74*5bae2aceSJari Sihvola #define JH7110_GPIO_LOCK(_sc)		mtx_lock(&(_sc)->mtx)
75*5bae2aceSJari Sihvola #define JH7110_GPIO_UNLOCK(_sc)		mtx_unlock(&(_sc)->mtx)
76*5bae2aceSJari Sihvola 
77*5bae2aceSJari Sihvola #define JH7110_GPIO_READ(sc, reg)	bus_read_4((sc)->res, (reg))
78*5bae2aceSJari Sihvola #define JH7110_GPIO_WRITE(sc, reg, val) bus_write_4((sc)->res, (reg), (val))
79*5bae2aceSJari Sihvola 
80*5bae2aceSJari Sihvola static device_t
81*5bae2aceSJari Sihvola jh7110_gpio_get_bus(device_t dev)
82*5bae2aceSJari Sihvola {
83*5bae2aceSJari Sihvola 	struct jh7110_gpio_softc *sc;
84*5bae2aceSJari Sihvola 
85*5bae2aceSJari Sihvola 	sc = device_get_softc(dev);
86*5bae2aceSJari Sihvola 
87*5bae2aceSJari Sihvola 	return (sc->busdev);
88*5bae2aceSJari Sihvola }
89*5bae2aceSJari Sihvola 
90*5bae2aceSJari Sihvola static int
91*5bae2aceSJari Sihvola jh7110_gpio_pin_max(device_t dev, int *maxpin)
92*5bae2aceSJari Sihvola {
93*5bae2aceSJari Sihvola 	*maxpin = GPIO_PINS - 1;
94*5bae2aceSJari Sihvola 
95*5bae2aceSJari Sihvola 	return (0);
96*5bae2aceSJari Sihvola }
97*5bae2aceSJari Sihvola 
98*5bae2aceSJari Sihvola static int
99*5bae2aceSJari Sihvola jh7110_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
100*5bae2aceSJari Sihvola {
101*5bae2aceSJari Sihvola 	struct jh7110_gpio_softc *sc;
102*5bae2aceSJari Sihvola 	uint32_t reg;
103*5bae2aceSJari Sihvola 
104*5bae2aceSJari Sihvola 	sc = device_get_softc(dev);
105*5bae2aceSJari Sihvola 
106*5bae2aceSJari Sihvola 	if (pin >= GPIO_PINS)
107*5bae2aceSJari Sihvola 		return (EINVAL);
108*5bae2aceSJari Sihvola 
109*5bae2aceSJari Sihvola 	JH7110_GPIO_LOCK(sc);
110*5bae2aceSJari Sihvola 	if (pin < GPIO_PINS / GPIO_REGS) {
111*5bae2aceSJari Sihvola 		reg = JH7110_GPIO_READ(sc, GPIO_DIN_LOW);
112*5bae2aceSJari Sihvola 		*val = (reg >> pin) & 0x1;
113*5bae2aceSJari Sihvola 	} else {
114*5bae2aceSJari Sihvola 		reg = JH7110_GPIO_READ(sc, GPIO_DIN_HIGH);
115*5bae2aceSJari Sihvola 		*val = (reg >> (pin - GPIO_PINS / GPIO_REGS)) & 0x1;
116*5bae2aceSJari Sihvola 	}
117*5bae2aceSJari Sihvola 	JH7110_GPIO_UNLOCK(sc);
118*5bae2aceSJari Sihvola 
119*5bae2aceSJari Sihvola 	return (0);
120*5bae2aceSJari Sihvola }
121*5bae2aceSJari Sihvola 
122*5bae2aceSJari Sihvola static int
123*5bae2aceSJari Sihvola jh7110_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
124*5bae2aceSJari Sihvola {
125*5bae2aceSJari Sihvola 	struct jh7110_gpio_softc *sc;
126*5bae2aceSJari Sihvola 	uint32_t reg;
127*5bae2aceSJari Sihvola 
128*5bae2aceSJari Sihvola 	sc = device_get_softc(dev);
129*5bae2aceSJari Sihvola 
130*5bae2aceSJari Sihvola 	if (pin >= GPIO_PINS)
131*5bae2aceSJari Sihvola 		return (EINVAL);
132*5bae2aceSJari Sihvola 
133*5bae2aceSJari Sihvola 	JH7110_GPIO_LOCK(sc);
134*5bae2aceSJari Sihvola 	reg = JH7110_GPIO_READ(sc, GP0_DOUT_CFG + GPIO_RW_OFFSET(pin));
135*5bae2aceSJari Sihvola 	reg &= ~(DATA_OUT_MASK << GPIO_SHIFT(pin));
136*5bae2aceSJari Sihvola 	if (value)
137*5bae2aceSJari Sihvola 		reg |= 0x1 << GPIO_SHIFT(pin);
138*5bae2aceSJari Sihvola 	JH7110_GPIO_WRITE(sc, GP0_DOUT_CFG + GPIO_RW_OFFSET(pin), reg);
139*5bae2aceSJari Sihvola 	JH7110_GPIO_UNLOCK(sc);
140*5bae2aceSJari Sihvola 
141*5bae2aceSJari Sihvola 	return (0);
142*5bae2aceSJari Sihvola }
143*5bae2aceSJari Sihvola 
144*5bae2aceSJari Sihvola static int
145*5bae2aceSJari Sihvola jh7110_gpio_pin_toggle(device_t dev, uint32_t pin)
146*5bae2aceSJari Sihvola {
147*5bae2aceSJari Sihvola 	struct jh7110_gpio_softc *sc;
148*5bae2aceSJari Sihvola 	uint32_t reg;
149*5bae2aceSJari Sihvola 
150*5bae2aceSJari Sihvola 	sc = device_get_softc(dev);
151*5bae2aceSJari Sihvola 
152*5bae2aceSJari Sihvola 	if (pin >= GPIO_PINS)
153*5bae2aceSJari Sihvola 		return (EINVAL);
154*5bae2aceSJari Sihvola 
155*5bae2aceSJari Sihvola 	JH7110_GPIO_LOCK(sc);
156*5bae2aceSJari Sihvola 	reg = JH7110_GPIO_READ(sc, GP0_DOUT_CFG + GPIO_RW_OFFSET(pin));
157*5bae2aceSJari Sihvola 	if (reg & 0x1 << GPIO_SHIFT(pin)) {
158*5bae2aceSJari Sihvola 		reg &= ~(DATA_OUT_MASK << GPIO_SHIFT(pin));
159*5bae2aceSJari Sihvola 	} else {
160*5bae2aceSJari Sihvola 		reg &= ~(DATA_OUT_MASK << GPIO_SHIFT(pin));
161*5bae2aceSJari Sihvola 		reg |= 0x1 << GPIO_SHIFT(pin);
162*5bae2aceSJari Sihvola 	}
163*5bae2aceSJari Sihvola 	JH7110_GPIO_WRITE(sc, GP0_DOUT_CFG + GPIO_RW_OFFSET(pin), reg);
164*5bae2aceSJari Sihvola 	JH7110_GPIO_UNLOCK(sc);
165*5bae2aceSJari Sihvola 
166*5bae2aceSJari Sihvola 	return (0);
167*5bae2aceSJari Sihvola }
168*5bae2aceSJari Sihvola 
169*5bae2aceSJari Sihvola static int
170*5bae2aceSJari Sihvola jh7110_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
171*5bae2aceSJari Sihvola {
172*5bae2aceSJari Sihvola 	if (pin >= GPIO_PINS)
173*5bae2aceSJari Sihvola 		return (EINVAL);
174*5bae2aceSJari Sihvola 
175*5bae2aceSJari Sihvola 	*caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT);
176*5bae2aceSJari Sihvola 
177*5bae2aceSJari Sihvola 	return (0);
178*5bae2aceSJari Sihvola }
179*5bae2aceSJari Sihvola 
180*5bae2aceSJari Sihvola static int
181*5bae2aceSJari Sihvola jh7110_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
182*5bae2aceSJari Sihvola {
183*5bae2aceSJari Sihvola 	if (pin >= GPIO_PINS)
184*5bae2aceSJari Sihvola 		return (EINVAL);
185*5bae2aceSJari Sihvola 
186*5bae2aceSJari Sihvola 	snprintf(name, GPIOMAXNAME, "GPIO%d", pin);
187*5bae2aceSJari Sihvola 
188*5bae2aceSJari Sihvola 	return (0);
189*5bae2aceSJari Sihvola }
190*5bae2aceSJari Sihvola 
191*5bae2aceSJari Sihvola static int
192*5bae2aceSJari Sihvola jh7110_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
193*5bae2aceSJari Sihvola {
194*5bae2aceSJari Sihvola 	struct jh7110_gpio_softc *sc;
195*5bae2aceSJari Sihvola 	uint32_t reg;
196*5bae2aceSJari Sihvola 
197*5bae2aceSJari Sihvola 	sc = device_get_softc(dev);
198*5bae2aceSJari Sihvola 
199*5bae2aceSJari Sihvola 	if (pin >= GPIO_PINS)
200*5bae2aceSJari Sihvola 		return (EINVAL);
201*5bae2aceSJari Sihvola 
202*5bae2aceSJari Sihvola 	/* Reading the direction */
203*5bae2aceSJari Sihvola 	JH7110_GPIO_LOCK(sc);
204*5bae2aceSJari Sihvola 	reg = JH7110_GPIO_READ(sc, GP0_DOEN_CFG + GPIO_RW_OFFSET(pin));
205*5bae2aceSJari Sihvola 	if ((reg & ENABLE_MASK << GPIO_SHIFT(pin)) == 0)
206*5bae2aceSJari Sihvola 		*flags |= GPIO_PIN_OUTPUT;
207*5bae2aceSJari Sihvola 	else
208*5bae2aceSJari Sihvola 		*flags |= GPIO_PIN_INPUT;
209*5bae2aceSJari Sihvola 	JH7110_GPIO_UNLOCK(sc);
210*5bae2aceSJari Sihvola 
211*5bae2aceSJari Sihvola 	return (0);
212*5bae2aceSJari Sihvola }
213*5bae2aceSJari Sihvola 
214*5bae2aceSJari Sihvola static int
215*5bae2aceSJari Sihvola jh7110_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
216*5bae2aceSJari Sihvola {
217*5bae2aceSJari Sihvola 	struct jh7110_gpio_softc *sc;
218*5bae2aceSJari Sihvola 	uint32_t reg;
219*5bae2aceSJari Sihvola 
220*5bae2aceSJari Sihvola 	sc = device_get_softc(dev);
221*5bae2aceSJari Sihvola 
222*5bae2aceSJari Sihvola 	if (pin >= GPIO_PINS)
223*5bae2aceSJari Sihvola 		return (EINVAL);
224*5bae2aceSJari Sihvola 
225*5bae2aceSJari Sihvola 	/* Setting the direction, enable or disable output, configuring pads */
226*5bae2aceSJari Sihvola 
227*5bae2aceSJari Sihvola 	JH7110_GPIO_LOCK(sc);
228*5bae2aceSJari Sihvola 
229*5bae2aceSJari Sihvola 	if (flags & GPIO_PIN_INPUT) {
230*5bae2aceSJari Sihvola 		reg = JH7110_GPIO_READ(sc, IOMUX_SYSCFG_288 + PAD_OFFSET(pin));
231*5bae2aceSJari Sihvola 		reg |= (PAD_INPUT_EN | PAD_HYST);
232*5bae2aceSJari Sihvola 		JH7110_GPIO_WRITE(sc, IOMUX_SYSCFG_288 + PAD_OFFSET(pin), reg);
233*5bae2aceSJari Sihvola 	}
234*5bae2aceSJari Sihvola 
235*5bae2aceSJari Sihvola 	reg = JH7110_GPIO_READ(sc, GP0_DOEN_CFG + GPIO_RW_OFFSET(pin));
236*5bae2aceSJari Sihvola 	reg &= ~(ENABLE_MASK << GPIO_SHIFT(pin));
237*5bae2aceSJari Sihvola 	if (flags & GPIO_PIN_INPUT) {
238*5bae2aceSJari Sihvola 		reg |= DIROUT_DISABLE << GPIO_SHIFT(pin);
239*5bae2aceSJari Sihvola 	}
240*5bae2aceSJari Sihvola 	JH7110_GPIO_WRITE(sc, GP0_DOEN_CFG + GPIO_RW_OFFSET(pin), reg);
241*5bae2aceSJari Sihvola 
242*5bae2aceSJari Sihvola 	if (flags & GPIO_PIN_OUTPUT) {
243*5bae2aceSJari Sihvola 		reg = JH7110_GPIO_READ(sc, GP0_DOUT_CFG + GPIO_RW_OFFSET(pin));
244*5bae2aceSJari Sihvola 		reg &= ~(ENABLE_MASK << GPIO_SHIFT(pin));
245*5bae2aceSJari Sihvola 		reg |= 0x1 << GPIO_SHIFT(pin);
246*5bae2aceSJari Sihvola 		JH7110_GPIO_WRITE(sc, GP0_DOUT_CFG + GPIO_RW_OFFSET(pin), reg);
247*5bae2aceSJari Sihvola 
248*5bae2aceSJari Sihvola 		reg = JH7110_GPIO_READ(sc, IOMUX_SYSCFG_288 + PAD_OFFSET(pin));
249*5bae2aceSJari Sihvola 		reg &= ~(PAD_INPUT_EN | PAD_PULLUP | PAD_PULLDOWN | PAD_HYST);
250*5bae2aceSJari Sihvola 		JH7110_GPIO_WRITE(sc, IOMUX_SYSCFG_288 + PAD_OFFSET(pin), reg);
251*5bae2aceSJari Sihvola 	}
252*5bae2aceSJari Sihvola 
253*5bae2aceSJari Sihvola 	JH7110_GPIO_UNLOCK(sc);
254*5bae2aceSJari Sihvola 
255*5bae2aceSJari Sihvola 	return (0);
256*5bae2aceSJari Sihvola }
257*5bae2aceSJari Sihvola 
258*5bae2aceSJari Sihvola static int
259*5bae2aceSJari Sihvola jh7110_gpio_probe(device_t dev)
260*5bae2aceSJari Sihvola {
261*5bae2aceSJari Sihvola 	if (!ofw_bus_status_okay(dev))
262*5bae2aceSJari Sihvola 		return (ENXIO);
263*5bae2aceSJari Sihvola 
264*5bae2aceSJari Sihvola 	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
265*5bae2aceSJari Sihvola 		return (ENXIO);
266*5bae2aceSJari Sihvola 
267*5bae2aceSJari Sihvola 	device_set_desc(dev, "StarFive JH7110 GPIO controller");
268*5bae2aceSJari Sihvola 
269*5bae2aceSJari Sihvola 	return (BUS_PROBE_DEFAULT);
270*5bae2aceSJari Sihvola }
271*5bae2aceSJari Sihvola 
272*5bae2aceSJari Sihvola static int
273*5bae2aceSJari Sihvola jh7110_gpio_detach(device_t dev)
274*5bae2aceSJari Sihvola {
275*5bae2aceSJari Sihvola 	struct jh7110_gpio_softc *sc;
276*5bae2aceSJari Sihvola 
277*5bae2aceSJari Sihvola 	sc = device_get_softc(dev);
278*5bae2aceSJari Sihvola 
279*5bae2aceSJari Sihvola 	bus_release_resources(dev, jh7110_gpio_spec, &sc->res);
280*5bae2aceSJari Sihvola 	if (sc->busdev != NULL)
281*5bae2aceSJari Sihvola 		gpiobus_detach_bus(dev);
282*5bae2aceSJari Sihvola 	if (sc->clk != NULL)
283*5bae2aceSJari Sihvola 		clk_release(sc->clk);
284*5bae2aceSJari Sihvola 	mtx_destroy(&sc->mtx);
285*5bae2aceSJari Sihvola 
286*5bae2aceSJari Sihvola 	return (0);
287*5bae2aceSJari Sihvola }
288*5bae2aceSJari Sihvola 
289*5bae2aceSJari Sihvola static int
290*5bae2aceSJari Sihvola jh7110_gpio_attach(device_t dev)
291*5bae2aceSJari Sihvola {
292*5bae2aceSJari Sihvola 	struct jh7110_gpio_softc *sc;
293*5bae2aceSJari Sihvola 
294*5bae2aceSJari Sihvola 	sc = device_get_softc(dev);
295*5bae2aceSJari Sihvola 	sc->dev = dev;
296*5bae2aceSJari Sihvola 
297*5bae2aceSJari Sihvola 	mtx_init(&sc->mtx, device_get_nameunit(sc->dev), NULL, MTX_DEF);
298*5bae2aceSJari Sihvola 
299*5bae2aceSJari Sihvola 	if (bus_alloc_resources(dev, jh7110_gpio_spec, &sc->res) != 0) {
300*5bae2aceSJari Sihvola 		device_printf(dev, "Could not allocate resources\n");
301*5bae2aceSJari Sihvola 		bus_release_resources(dev, jh7110_gpio_spec, &sc->res);
302*5bae2aceSJari Sihvola 		mtx_destroy(&sc->mtx);
303*5bae2aceSJari Sihvola 		return (ENXIO);
304*5bae2aceSJari Sihvola 	}
305*5bae2aceSJari Sihvola 
306*5bae2aceSJari Sihvola 	if (clk_get_by_ofw_index(dev, 0, 0, &sc->clk) != 0) {
307*5bae2aceSJari Sihvola 		device_printf(dev, "Cannot get clock\n");
308*5bae2aceSJari Sihvola 		jh7110_gpio_detach(dev);
309*5bae2aceSJari Sihvola 		return (ENXIO);
310*5bae2aceSJari Sihvola 	}
311*5bae2aceSJari Sihvola 
312*5bae2aceSJari Sihvola 	if (clk_enable(sc->clk) != 0) {
313*5bae2aceSJari Sihvola 		device_printf(dev, "Could not enable clock %s\n",
314*5bae2aceSJari Sihvola 		    clk_get_name(sc->clk));
315*5bae2aceSJari Sihvola 		jh7110_gpio_detach(dev);
316*5bae2aceSJari Sihvola 		return (ENXIO);
317*5bae2aceSJari Sihvola 	}
318*5bae2aceSJari Sihvola 
319*5bae2aceSJari Sihvola 	/* Reseting GPIO interrupts */
320*5bae2aceSJari Sihvola 	JH7110_GPIO_WRITE(sc, GPIOE_0, 0);
321*5bae2aceSJari Sihvola 	JH7110_GPIO_WRITE(sc, GPIOE_1, 0);
322*5bae2aceSJari Sihvola 	JH7110_GPIO_WRITE(sc, GPIOEN, 1);
323*5bae2aceSJari Sihvola 
324*5bae2aceSJari Sihvola 	sc->busdev = gpiobus_attach_bus(dev);
325*5bae2aceSJari Sihvola 	if (sc->busdev == NULL) {
326*5bae2aceSJari Sihvola 		device_printf(dev, "Cannot attach gpiobus\n");
327*5bae2aceSJari Sihvola 		jh7110_gpio_detach(dev);
328*5bae2aceSJari Sihvola 		return (ENXIO);
329*5bae2aceSJari Sihvola 	}
330*5bae2aceSJari Sihvola 
331*5bae2aceSJari Sihvola 	return (0);
332*5bae2aceSJari Sihvola }
333*5bae2aceSJari Sihvola 
334*5bae2aceSJari Sihvola static phandle_t
335*5bae2aceSJari Sihvola jh7110_gpio_get_node(device_t bus, device_t dev)
336*5bae2aceSJari Sihvola {
337*5bae2aceSJari Sihvola 	return (ofw_bus_get_node(bus));
338*5bae2aceSJari Sihvola }
339*5bae2aceSJari Sihvola 
340*5bae2aceSJari Sihvola static device_method_t jh7110_gpio_methods[] = {
341*5bae2aceSJari Sihvola 	/* Device interface */
342*5bae2aceSJari Sihvola 	DEVMETHOD(device_probe,		jh7110_gpio_probe),
343*5bae2aceSJari Sihvola 	DEVMETHOD(device_attach,	jh7110_gpio_attach),
344*5bae2aceSJari Sihvola 	DEVMETHOD(device_detach,	jh7110_gpio_detach),
345*5bae2aceSJari Sihvola 
346*5bae2aceSJari Sihvola 	/* GPIO protocol */
347*5bae2aceSJari Sihvola 	DEVMETHOD(gpio_get_bus,		jh7110_gpio_get_bus),
348*5bae2aceSJari Sihvola 	DEVMETHOD(gpio_pin_max,		jh7110_gpio_pin_max),
349*5bae2aceSJari Sihvola 	DEVMETHOD(gpio_pin_get,		jh7110_gpio_pin_get),
350*5bae2aceSJari Sihvola 	DEVMETHOD(gpio_pin_set,		jh7110_gpio_pin_set),
351*5bae2aceSJari Sihvola 	DEVMETHOD(gpio_pin_toggle,	jh7110_gpio_pin_toggle),
352*5bae2aceSJari Sihvola 	DEVMETHOD(gpio_pin_getflags,	jh7110_gpio_pin_getflags),
353*5bae2aceSJari Sihvola 	DEVMETHOD(gpio_pin_setflags,	jh7110_gpio_pin_setflags),
354*5bae2aceSJari Sihvola 	DEVMETHOD(gpio_pin_getcaps,	jh7110_gpio_pin_getcaps),
355*5bae2aceSJari Sihvola 	DEVMETHOD(gpio_pin_getname,	jh7110_gpio_pin_getname),
356*5bae2aceSJari Sihvola 
357*5bae2aceSJari Sihvola 	/* ofw_bus interface */
358*5bae2aceSJari Sihvola 	DEVMETHOD(ofw_bus_get_node,	jh7110_gpio_get_node),
359*5bae2aceSJari Sihvola 
360*5bae2aceSJari Sihvola 	DEVMETHOD_END
361*5bae2aceSJari Sihvola };
362*5bae2aceSJari Sihvola 
363*5bae2aceSJari Sihvola DEFINE_CLASS_0(gpio, jh7110_gpio_driver, jh7110_gpio_methods,
364*5bae2aceSJari Sihvola     sizeof(struct jh7110_gpio_softc));
365*5bae2aceSJari Sihvola EARLY_DRIVER_MODULE(jh7110_gpio, simplebus, jh7110_gpio_driver, 0, 0,
366*5bae2aceSJari Sihvola     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
367*5bae2aceSJari Sihvola MODULE_DEPEND(jh7110_gpio, gpiobus, 1, 1, 1);
368