xref: /freebsd/sys/dev/gpio/gpioregulator.c (revision e6bfd18d21b225af6a0ed67ceeaf1293b7b9eba5)
1 /*-
2  * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
20  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
21  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  * $FreeBSD$
26  */
27 
28 /*
29  * GPIO controlled regulators
30  */
31 
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/bus.h>
38 #include <sys/rman.h>
39 #include <sys/kernel.h>
40 #include <sys/module.h>
41 #include <sys/gpio.h>
42 
43 #include <dev/ofw/ofw_bus.h>
44 #include <dev/ofw/ofw_bus_subr.h>
45 
46 #include <dev/gpio/gpiobusvar.h>
47 
48 #include <dev/extres/regulator/regulator.h>
49 
50 #include "regdev_if.h"
51 
52 struct gpioregulator_state {
53 	int			val;
54 	uint32_t		mask;
55 };
56 
57 struct gpioregulator_init_def {
58 	struct regnode_init_def		reg_init_def;
59 	struct gpiobus_pin		*enable_pin;
60 	int				enable_pin_valid;
61 	int				startup_delay_us;
62 	int				nstates;
63 	struct gpioregulator_state	*states;
64 	int				npins;
65 	struct gpiobus_pin		**pins;
66 };
67 
68 struct gpioregulator_reg_sc {
69 	struct regnode			*regnode;
70 	device_t			base_dev;
71 	struct regnode_std_param	*param;
72 	struct gpioregulator_init_def	*def;
73 };
74 
75 struct gpioregulator_softc {
76 	device_t			dev;
77 	struct gpioregulator_reg_sc	*reg_sc;
78 	struct gpioregulator_init_def	init_def;
79 };
80 
81 static int
82 gpioregulator_regnode_init(struct regnode *regnode)
83 {
84 	struct gpioregulator_reg_sc *sc;
85 	int error, n;
86 
87 	sc = regnode_get_softc(regnode);
88 
89 	if (sc->def->enable_pin_valid == 1) {
90 		error = gpio_pin_setflags(sc->def->enable_pin, GPIO_PIN_OUTPUT);
91 		if (error != 0)
92 			return (error);
93 	}
94 
95 	for (n = 0; n < sc->def->npins; n++) {
96 		error = gpio_pin_setflags(sc->def->pins[n], GPIO_PIN_OUTPUT);
97 		if (error != 0)
98 			return (error);
99 	}
100 
101 	return (0);
102 }
103 
104 static int
105 gpioregulator_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
106 {
107 	struct gpioregulator_reg_sc *sc;
108 	bool active;
109 	int error;
110 
111 	sc = regnode_get_softc(regnode);
112 
113 	if (sc->def->enable_pin_valid == 1) {
114 		active = enable;
115 		if (!sc->param->enable_active_high)
116 			active = !active;
117 		error = gpio_pin_set_active(sc->def->enable_pin, active);
118 		if (error != 0)
119 			return (error);
120 	}
121 
122 	*udelay = sc->def->startup_delay_us;
123 
124 	return (0);
125 }
126 
127 static int
128 gpioregulator_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
129     int max_uvolt, int *udelay)
130 {
131 	struct gpioregulator_reg_sc *sc;
132 	const struct gpioregulator_state *state;
133 	int error, n;
134 
135 	sc = regnode_get_softc(regnode);
136 	state = NULL;
137 
138 	for (n = 0; n < sc->def->nstates; n++) {
139 		if (sc->def->states[n].val >= min_uvolt &&
140 		    sc->def->states[n].val <= max_uvolt) {
141 			state = &sc->def->states[n];
142 			break;
143 		}
144 	}
145 	if (state == NULL)
146 		return (EINVAL);
147 
148 	for (n = 0; n < sc->def->npins; n++) {
149 		error = gpio_pin_set_active(sc->def->pins[n],
150 		    (state->mask >> n) & 1);
151 		if (error != 0)
152 			return (error);
153 	}
154 
155 	*udelay = sc->def->startup_delay_us;
156 
157 	return (0);
158 }
159 
160 static int
161 gpioregulator_regnode_get_voltage(struct regnode *regnode, int *uvolt)
162 {
163 	struct gpioregulator_reg_sc *sc;
164 	uint32_t mask;
165 	int error, n;
166 	bool active;
167 
168 	sc = regnode_get_softc(regnode);
169 	mask = 0;
170 
171 	for (n = 0; n < sc->def->npins; n++) {
172 		error = gpio_pin_is_active(sc->def->pins[n], &active);
173 		if (error != 0)
174 			return (error);
175 		mask |= (active << n);
176 	}
177 
178 	for (n = 0; n < sc->def->nstates; n++) {
179 		if (sc->def->states[n].mask == mask) {
180 			*uvolt = sc->def->states[n].val;
181 			return (0);
182 		}
183 	}
184 
185 	return (EIO);
186 }
187 
188 static regnode_method_t gpioregulator_regnode_methods[] = {
189 	/* Regulator interface */
190 	REGNODEMETHOD(regnode_init,	gpioregulator_regnode_init),
191 	REGNODEMETHOD(regnode_enable,	gpioregulator_regnode_enable),
192 	REGNODEMETHOD(regnode_set_voltage, gpioregulator_regnode_set_voltage),
193 	REGNODEMETHOD(regnode_get_voltage, gpioregulator_regnode_get_voltage),
194 	REGNODEMETHOD_END
195 };
196 DEFINE_CLASS_1(gpioregulator_regnode, gpioregulator_regnode_class,
197     gpioregulator_regnode_methods, sizeof(struct gpioregulator_reg_sc),
198     regnode_class);
199 
200 static int
201 gpioregulator_parse_fdt(struct gpioregulator_softc *sc)
202 {
203 	uint32_t *pstates, mask;
204 	phandle_t node;
205 	ssize_t len;
206 	int error, n;
207 
208 	node = ofw_bus_get_node(sc->dev);
209 	pstates = NULL;
210 	mask = 0;
211 
212 	error = regulator_parse_ofw_stdparam(sc->dev, node,
213 	    &sc->init_def.reg_init_def);
214 	if (error != 0)
215 		return (error);
216 
217 	/* "states" property (required) */
218 	len = OF_getencprop_alloc_multi(node, "states", sizeof(*pstates),
219 	    (void **)&pstates);
220 	if (len < 2) {
221 		device_printf(sc->dev, "invalid 'states' property\n");
222 		error = EINVAL;
223 		goto done;
224 	}
225 	sc->init_def.nstates = len / 2;
226 	sc->init_def.states = malloc(sc->init_def.nstates *
227 	    sizeof(*sc->init_def.states), M_DEVBUF, M_WAITOK);
228 	for (n = 0; n < sc->init_def.nstates; n++) {
229 		sc->init_def.states[n].val = pstates[n * 2 + 0];
230 		sc->init_def.states[n].mask = pstates[n * 2 + 1];
231 		mask |= sc->init_def.states[n].mask;
232 	}
233 
234 	/* "startup-delay-us" property (optional) */
235 	len = OF_getencprop(node, "startup-delay-us",
236 	    &sc->init_def.startup_delay_us,
237 	    sizeof(sc->init_def.startup_delay_us));
238 	if (len <= 0)
239 		sc->init_def.startup_delay_us = 0;
240 
241 	/* "enable-gpio" property (optional) */
242 	error = gpio_pin_get_by_ofw_property(sc->dev, node, "enable-gpio",
243 	    &sc->init_def.enable_pin);
244 	if (error == 0)
245 		sc->init_def.enable_pin_valid = 1;
246 
247 	/* "gpios" property */
248 	sc->init_def.npins = 32 - __builtin_clz(mask);
249 	sc->init_def.pins = malloc(sc->init_def.npins *
250 	    sizeof(sc->init_def.pins), M_DEVBUF, M_WAITOK | M_ZERO);
251 	for (n = 0; n < sc->init_def.npins; n++) {
252 		error = gpio_pin_get_by_ofw_idx(sc->dev, node, n,
253 		    &sc->init_def.pins[n]);
254 		if (error != 0) {
255 			device_printf(sc->dev, "cannot get pin %d\n", n);
256 			goto done;
257 		}
258 	}
259 
260 done:
261 	if (error != 0) {
262 		for (n = 0; n < sc->init_def.npins; n++) {
263 			if (sc->init_def.pins[n] != NULL)
264 				gpio_pin_release(sc->init_def.pins[n]);
265 		}
266 
267 		free(sc->init_def.states, M_DEVBUF);
268 		free(sc->init_def.pins, M_DEVBUF);
269 
270 	}
271 	OF_prop_free(pstates);
272 
273 	return (error);
274 }
275 
276 static int
277 gpioregulator_probe(device_t dev)
278 {
279 
280 	if (!ofw_bus_is_compatible(dev, "regulator-gpio"))
281 		return (ENXIO);
282 
283 	device_set_desc(dev, "GPIO controlled regulator");
284 	return (BUS_PROBE_GENERIC);
285 }
286 
287 static int
288 gpioregulator_attach(device_t dev)
289 {
290 	struct gpioregulator_softc *sc;
291 	struct regnode *regnode;
292 	phandle_t node;
293 	int error;
294 
295 	sc = device_get_softc(dev);
296 	sc->dev = dev;
297 	node = ofw_bus_get_node(dev);
298 
299 	error = gpioregulator_parse_fdt(sc);
300 	if (error != 0) {
301 		device_printf(dev, "cannot parse parameters\n");
302 		return (ENXIO);
303 	}
304 	sc->init_def.reg_init_def.id = 1;
305 	sc->init_def.reg_init_def.ofw_node = node;
306 
307 	regnode = regnode_create(dev, &gpioregulator_regnode_class,
308 	    &sc->init_def.reg_init_def);
309 	if (regnode == NULL) {
310 		device_printf(dev, "cannot create regulator\n");
311 		return (ENXIO);
312 	}
313 
314 	sc->reg_sc = regnode_get_softc(regnode);
315 	sc->reg_sc->regnode = regnode;
316 	sc->reg_sc->base_dev = dev;
317 	sc->reg_sc->param = regnode_get_stdparam(regnode);
318 	sc->reg_sc->def = &sc->init_def;
319 
320 	regnode_register(regnode);
321 
322 	return (0);
323 }
324 
325 
326 static device_method_t gpioregulator_methods[] = {
327 	/* Device interface */
328 	DEVMETHOD(device_probe,		gpioregulator_probe),
329 	DEVMETHOD(device_attach,	gpioregulator_attach),
330 
331 	/* Regdev interface */
332 	DEVMETHOD(regdev_map,		regdev_default_ofw_map),
333 
334 	DEVMETHOD_END
335 };
336 
337 static driver_t gpioregulator_driver = {
338 	"gpioregulator",
339 	gpioregulator_methods,
340 	sizeof(struct gpioregulator_softc),
341 };
342 
343 EARLY_DRIVER_MODULE(gpioregulator, simplebus, gpioregulator_driver, 0, 0,
344     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST);
345 MODULE_VERSION(gpioregulator, 1);
346