xref: /freebsd/sys/arm64/rockchip/rk_grf_gpio.c (revision 0832a409c21b45b2a31b90c50a005d9a4b1a5efd)
1 /*
2  * Copyright (c) 2025 Stephen Hurd <shurd@FreeBSD.org>
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  */
6 
7 #include <sys/param.h>
8 #include <sys/bus.h>
9 #include <sys/gpio.h>
10 #include <sys/kernel.h>
11 #include <sys/module.h>
12 
13 #include <dev/ofw/openfirm.h>
14 #include <dev/ofw/ofw_bus.h>
15 #include <dev/ofw/ofw_bus_subr.h>
16 
17 #include <dev/gpio/gpiobusvar.h>
18 #include <dev/syscon/syscon.h>
19 
20 #include "syscon_if.h"
21 
22 #define	GRF_SOC_CON10			0x0428
23 #define	 SOC_CON10_GPIOMUT		(1 << 1)
24 #define	 SOC_CON10_GPIOMUT_MASK		((1 << 1) << 16)
25 #define	 SOC_CON10_GPIOMUT_EN		(1 << 0)
26 #define	 SOC_CON10_GPIOMUT_EN_MASK	((1 << 0) << 16)
27 
28 struct rk_grf_gpio_softc {
29 	device_t		sc_dev;
30 	device_t		sc_busdev;
31 	struct syscon		*sc_grf;
32 	bool			active_high;
33 };
34 
35 static struct ofw_compat_data compat_data[] = {
36 	{"rockchip,rk3328-grf-gpio", 1},
37 	{NULL,             0}
38 };
39 
40 static device_t
rk_grf_gpio_get_bus(device_t dev)41 rk_grf_gpio_get_bus(device_t dev)
42 {
43 	struct rk_grf_gpio_softc *sc;
44 
45 	sc = device_get_softc(dev);
46 
47 	return (sc->sc_busdev);
48 }
49 
50 static int
rk_grf_gpio_pin_max(device_t dev,int * maxpin)51 rk_grf_gpio_pin_max(device_t dev, int *maxpin)
52 {
53 	*maxpin = 1;
54 	return (0);
55 }
56 
57 static int
rk_grf_gpio_pin_getname(device_t dev,uint32_t pin,char * name)58 rk_grf_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
59 {
60 	if (pin)
61 		return (EINVAL);
62 
63 	snprintf(name, GPIOMAXNAME, "GPIO_MUTE");
64 
65 	return (0);
66 }
67 
68 static int
rk_grf_gpio_pin_getflags(device_t dev,uint32_t pin,uint32_t * flags)69 rk_grf_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
70 {
71 	if (pin)
72 		return (EINVAL);
73 	*flags = GPIO_PIN_OUTPUT;
74 	return (0);
75 }
76 
77 static int
rk_grf_gpio_pin_setflags(device_t dev,uint32_t pin,uint32_t flags)78 rk_grf_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
79 {
80 	if (pin)
81 		return (EINVAL);
82 	if (flags != GPIO_PIN_OUTPUT)
83 		return (EINVAL);
84 
85 	return (0);
86 }
87 
88 static int
rk_grf_gpio_pin_getcaps(device_t dev,uint32_t pin,uint32_t * caps)89 rk_grf_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
90 {
91 	if (pin)
92 		return (EINVAL);
93 
94 	*caps = GPIO_PIN_OUTPUT;
95 	return (0);
96 }
97 
98 static int
rk_grf_gpio_pin_get(device_t dev,uint32_t pin,unsigned int * val)99 rk_grf_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
100 {
101 	struct rk_grf_gpio_softc *sc;
102 	uint32_t reg;
103 
104 	sc = device_get_softc(dev);
105 
106 	if (pin)
107 		return (EINVAL);
108 
109 	reg = SYSCON_READ_4(sc->sc_grf, GRF_SOC_CON10);
110 	if (reg & SOC_CON10_GPIOMUT)
111 		*val = 1;
112 	else
113 		*val = 0;
114 
115 	return (0);
116 }
117 
118 static int
rk_grf_gpio_pin_set(device_t dev,uint32_t pin,unsigned int value)119 rk_grf_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
120 {
121 	struct rk_grf_gpio_softc *sc;
122 	uint32_t val;
123 
124 	sc = device_get_softc(dev);
125 
126 	if (pin)
127 		return (EINVAL);
128 
129 	val = SOC_CON10_GPIOMUT_MASK;
130 	if (value)
131 		val |= SOC_CON10_GPIOMUT;
132 	SYSCON_WRITE_4(sc->sc_grf, GRF_SOC_CON10, val);
133 
134 	return (0);
135 }
136 
137 static int
rk_grf_gpio_map_gpios(device_t bus,phandle_t dev,phandle_t gparent,int gcells,pcell_t * gpios,uint32_t * pin,uint32_t * flags)138 rk_grf_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
139     pcell_t *gpios, uint32_t *pin, uint32_t *flags)
140 {
141 	if (gpios[0])
142 		return (EINVAL);
143 
144 	/* The gpios are mapped as <pin flags> */
145 	*pin = 0;
146 	/* TODO: The only valid flags are active low or active high */
147 	*flags = GPIO_PIN_OUTPUT;
148 	return (0);
149 }
150 
151 static int
rk_grf_gpio_probe(device_t dev)152 rk_grf_gpio_probe(device_t dev)
153 {
154 
155 	if (!ofw_bus_status_okay(dev))
156 		return (ENXIO);
157 	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
158 		return (ENXIO);
159 
160 	device_set_desc(dev, "RockChip General Register File GPIO (GPIO_MUTE)");
161 	return (BUS_PROBE_DEFAULT);
162 }
163 
164 static int
rk_grf_gpio_attach(device_t dev)165 rk_grf_gpio_attach(device_t dev)
166 {
167 	struct rk_grf_gpio_softc *sc;
168 	phandle_t parent_node, node;
169 	device_t pdev;
170 
171 	sc = device_get_softc(dev);
172 	sc->sc_dev = dev;
173 
174 	node = ofw_bus_get_node(sc->sc_dev);
175 	if (!OF_hasprop(node, "gpio-controller"))
176 		return (ENXIO);
177 	pdev = device_get_parent(dev);
178 	parent_node = ofw_bus_get_node(pdev);
179 	if (syscon_get_by_ofw_node(dev, parent_node, &sc->sc_grf) != 0) {
180 		device_printf(dev, "cannot get parent syscon handle\n");
181 		return (ENXIO);
182 	}
183 
184 	sc->sc_busdev = gpiobus_attach_bus(dev);
185 	if (sc->sc_busdev == NULL) {
186 		return (ENXIO);
187 	}
188 
189 	return (0);
190 }
191 
192 static int
rk_grf_gpio_detach(device_t dev)193 rk_grf_gpio_detach(device_t dev)
194 {
195 	struct rk_grf_gpio_softc *sc;
196 
197 	sc = device_get_softc(dev);
198 
199 	if (sc->sc_busdev)
200 		gpiobus_detach_bus(dev);
201 
202 	return(0);
203 }
204 
205 static device_method_t rk_grf_gpio_methods[] = {
206 	DEVMETHOD(device_probe, rk_grf_gpio_probe),
207 	DEVMETHOD(device_attach, rk_grf_gpio_attach),
208 	DEVMETHOD(device_detach, rk_grf_gpio_detach),
209 
210 	/* GPIO protocol */
211 	DEVMETHOD(gpio_get_bus,		rk_grf_gpio_get_bus),
212 	DEVMETHOD(gpio_pin_max,		rk_grf_gpio_pin_max),
213 	DEVMETHOD(gpio_pin_getname,	rk_grf_gpio_pin_getname),
214 	DEVMETHOD(gpio_pin_getflags,	rk_grf_gpio_pin_getflags),
215 	DEVMETHOD(gpio_pin_setflags,	rk_grf_gpio_pin_setflags),
216 	DEVMETHOD(gpio_pin_getcaps,	rk_grf_gpio_pin_getcaps),
217 	DEVMETHOD(gpio_pin_get,		rk_grf_gpio_pin_get),
218 	DEVMETHOD(gpio_pin_set,		rk_grf_gpio_pin_set),
219 	DEVMETHOD(gpio_map_gpios,	rk_grf_gpio_map_gpios),
220 
221 	DEVMETHOD_END
222 };
223 
224 static driver_t rk_grf_gpio_driver = {
225 	"gpio",
226 	rk_grf_gpio_methods,
227 	sizeof(struct rk_grf_gpio_softc),
228 };
229 
230 /*
231  * GPIO driver is always a child of rk_grf driver and should be probed
232  * and attached within rk_grf function. Due to this, bus pass order
233  * must be same as bus pass order of rk_grf driver.
234  */
235 EARLY_DRIVER_MODULE(rk_grf_gpio, simplebus, rk_grf_gpio_driver, 0, 0,
236     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
237