xref: /freebsd/sys/dev/iicbus/pmic/act8846_regulator.c (revision 55141f2c8991b2a6adbf30bb0fe3e6cbc303f06d)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2019 Michal Meloun <mmel@FreeBSD.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/bus.h>
32 #include <sys/kernel.h>
33 #include <sys/module.h>
34 #include <sys/mutex.h>
35 #include <sys/rman.h>
36 #include <machine/bus.h>
37 
38 #include <dev/iicbus/iiconf.h>
39 #include <dev/iicbus/iicbus.h>
40 
41 #include <dev/ofw/ofw_bus.h>
42 #include <dev/ofw/ofw_bus_subr.h>
43 
44 #include <dev/extres/regulator/regulator.h>
45 
46 #include <dev/iicbus/pmic/act8846.h>
47 
48 #include "regdev_if.h"
49 
50 MALLOC_DEFINE(M_ACT8846_REG, "ACT8846 regulator", "ACT8846 power regulator");
51 
52 #if 0
53 #define	dprintf(sc, format, arg...)
54 	device_printf(sc->base_sc->dev, "%s: " format, __func__, arg) */
55 #else
56 #define	dprintf(sc, format, arg...)
57 #endif
58 
59 enum act8846_reg_id {
60 	ACT8846_REG_ID_REG1,
61 	ACT8846_REG_ID_REG2,
62 	ACT8846_REG_ID_REG3,
63 	ACT8846_REG_ID_REG4,
64 	ACT8846_REG_ID_REG5,
65 	ACT8846_REG_ID_REG6,
66 	ACT8846_REG_ID_REG7,
67 	ACT8846_REG_ID_REG8,
68 	ACT8846_REG_ID_REG9,
69 	ACT8846_REG_ID_REG10,
70 	ACT8846_REG_ID_REG11,
71 	ACT8846_REG_ID_REG12,
72 	ACT8846_REG_ID_REG13,
73 };
74 
75 struct act8846_regdef {
76 	intptr_t		id;		/* ID */
77 	char			*name;		/* Regulator name */
78 	char			*supply_name;	/* Source property name */
79 	uint8_t			enable_reg;
80 	uint8_t			enable_mask;
81 	uint8_t			voltage_reg;
82 	uint8_t			voltage_mask;
83 	struct regulator_range	*ranges;
84 	int			nranges;
85 };
86 struct act8846_softc;
87 
88 struct act8846_reg_sc {
89 	struct regnode		*regnode;
90 	struct act8846_softc	*base_sc;
91 	struct act8846_regdef	*def;
92 	phandle_t		xref;
93 	struct regnode_std_param *param;
94 };
95 
96 
97 static struct regulator_range act8846_ranges[] = {
98 	REG_RANGE_INIT(  0, 23,  600000, 25000),
99 	REG_RANGE_INIT( 24, 47, 1200000, 50000),
100 	REG_RANGE_INIT( 48, 64, 2400000, 100000),
101 };
102 
103 static struct act8846_regdef act8846_regdefs[] = {
104 	{
105 		.id = ACT8846_REG_ID_REG1,
106 		.name = "REG1",
107 		.supply_name = "vp1",
108 		.enable_reg = ACT8846_REG1_CTRL,
109 		.enable_mask = ACT8846_CTRL_ENA,
110 	},
111 	{
112 		.id = ACT8846_REG_ID_REG2,
113 		.name = "REG2",
114 		.supply_name = "vp2",
115 		.enable_reg = ACT8846_REG2_CTRL,
116 		.enable_mask = ACT8846_CTRL_ENA,
117 		.voltage_reg = ACT8846_REG2_VSET0,
118 		.voltage_mask = ACT8846_VSEL_MASK,
119 		.ranges = act8846_ranges,
120 		.nranges = nitems(act8846_ranges),
121 	},
122 	{
123 		.id = ACT8846_REG_ID_REG3,
124 		.name = "REG3",
125 		.supply_name = "vp3",
126 		.enable_reg = ACT8846_REG3_CTRL,
127 		.enable_mask = ACT8846_CTRL_ENA,
128 		.voltage_reg = ACT8846_REG3_VSET0,
129 		.voltage_mask = ACT8846_VSEL_MASK,
130 		.ranges = act8846_ranges,
131 		.nranges = nitems(act8846_ranges),
132 	},
133 	{
134 		.id = ACT8846_REG_ID_REG4,
135 		.name = "REG4",
136 		.supply_name = "vp4",
137 		.enable_reg = ACT8846_REG4_CTRL,
138 		.enable_mask = ACT8846_CTRL_ENA,
139 		.voltage_reg = ACT8846_REG4_VSET0,
140 		.voltage_mask = ACT8846_VSEL_MASK,
141 		.ranges = act8846_ranges,
142 		.nranges = nitems(act8846_ranges),
143 	},
144 	{
145 		.id = ACT8846_REG_ID_REG5,
146 		.name = "REG5",
147 		.supply_name = "inl1",
148 		.enable_reg = ACT8846_REG5_CTRL,
149 		.enable_mask = ACT8846_CTRL_ENA,
150 		.voltage_reg = ACT8846_REG5_VSET,
151 		.voltage_mask = ACT8846_VSEL_MASK,
152 		.ranges = act8846_ranges,
153 		.nranges = nitems(act8846_ranges),
154 	},
155 	{
156 		.id = ACT8846_REG_ID_REG6,
157 		.name = "REG6",
158 		.supply_name = "inl1",
159 		.enable_reg = ACT8846_REG6_CTRL,
160 		.enable_mask = ACT8846_CTRL_ENA,
161 		.voltage_reg = ACT8846_REG6_VSET,
162 		.voltage_mask = ACT8846_VSEL_MASK,
163 		.ranges = act8846_ranges,
164 		.nranges = nitems(act8846_ranges),
165 	},
166 	{
167 		.id = ACT8846_REG_ID_REG7,
168 		.name = "REG7",
169 		.supply_name = "inl1",
170 		.enable_reg = ACT8846_REG7_CTRL,
171 		.enable_mask = ACT8846_CTRL_ENA,
172 		.voltage_reg = ACT8846_REG7_VSET,
173 		.voltage_mask = ACT8846_VSEL_MASK,
174 		.ranges = act8846_ranges,
175 		.nranges = nitems(act8846_ranges),
176 	},
177 	{
178 		.id = ACT8846_REG_ID_REG8,
179 		.name = "REG8",
180 		.supply_name = "inl2",
181 		.enable_reg = ACT8846_REG8_CTRL,
182 		.enable_mask = ACT8846_CTRL_ENA,
183 		.voltage_reg = ACT8846_REG8_VSET,
184 		.voltage_mask = ACT8846_VSEL_MASK,
185 		.ranges = act8846_ranges,
186 		.nranges = nitems(act8846_ranges),
187 	},
188 	{
189 		.id = ACT8846_REG_ID_REG9,
190 		.name = "REG9",
191 		.supply_name = "inl2",
192 		.enable_reg = ACT8846_REG9_CTRL,
193 		.enable_mask = ACT8846_CTRL_ENA,
194 		.voltage_reg = ACT8846_REG9_VSET,
195 		.voltage_mask = ACT8846_VSEL_MASK,
196 		.ranges = act8846_ranges,
197 		.nranges = nitems(act8846_ranges),
198 	},
199 	{
200 		.id = ACT8846_REG_ID_REG10,
201 		.name = "REG10",
202 		.supply_name = "inl3",
203 		.enable_reg = ACT8846_REG10_CTRL,
204 		.enable_mask = ACT8846_CTRL_ENA,
205 		.voltage_reg = ACT8846_REG10_VSET,
206 		.voltage_mask = ACT8846_VSEL_MASK,
207 		.ranges = act8846_ranges,
208 		.nranges = nitems(act8846_ranges),
209 	},
210 	{
211 		.id = ACT8846_REG_ID_REG11,
212 		.name = "REG11",
213 		.supply_name = "inl3",
214 		.enable_reg = ACT8846_REG11_CTRL,
215 		.enable_mask = ACT8846_CTRL_ENA,
216 		.voltage_reg = ACT8846_REG11_VSET,
217 		.voltage_mask = ACT8846_VSEL_MASK,
218 		.ranges = act8846_ranges,
219 		.nranges = nitems(act8846_ranges),
220 	},
221 	{
222 		.id = ACT8846_REG_ID_REG12,
223 		.name = "REG12",
224 		.supply_name = "inl3",
225 		.enable_reg = ACT8846_REG12_CTRL,
226 		.enable_mask = ACT8846_CTRL_ENA,
227 		.voltage_reg = ACT8846_REG12_VSET,
228 		.voltage_mask = ACT8846_VSEL_MASK,
229 		.ranges = act8846_ranges,
230 		.nranges = nitems(act8846_ranges),
231 	},
232 	{
233 		.id = ACT8846_REG_ID_REG13,
234 		.name = "REG13",
235 		.supply_name = "inl1",
236 		.enable_reg = ACT8846_REG13_CTRL,
237 		.enable_mask = ACT8846_CTRL_ENA,
238 	},
239 };
240 
241 static int
242 act8846_read_sel(struct act8846_reg_sc *sc, uint8_t *sel)
243 {
244 	int rv;
245 
246 	rv = RD1(sc->base_sc, sc->def->voltage_reg, sel);
247 	if (rv != 0)
248 		return (rv);
249 	*sel &= sc->def->voltage_mask;
250 	*sel >>= ffs(sc->def->voltage_mask) - 1;
251 	return (0);
252 }
253 
254 static int
255 act8846_write_sel(struct act8846_reg_sc *sc, uint8_t sel)
256 {
257 	int rv;
258 
259 	sel <<= ffs(sc->def->voltage_mask) - 1;
260 	sel &= sc->def->voltage_mask;
261 
262 	rv = RM1(sc->base_sc, sc->def->voltage_reg,
263 	    sc->def->voltage_mask, sel);
264 	if (rv != 0)
265 		return (rv);
266 	return (rv);
267 }
268 
269 static int
270 act8846_regnode_init(struct regnode *regnode)
271 {
272 	return (0);
273 }
274 
275 static int
276 act8846_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
277 {
278 	struct act8846_reg_sc *sc;
279 	int rv;
280 
281 	sc = regnode_get_softc(regnode);
282 
283 	dprintf(sc, "%sabling regulator %s\n",
284 	    enable ? "En" : "Dis",
285 	    sc->def->name);
286 	rv = RM1(sc->base_sc, sc->def->enable_reg,
287 	    sc->def->enable_mask, enable ? sc->def->enable_mask: 0);
288 	*udelay = sc->param->enable_delay;
289 
290 	return (rv);
291 }
292 
293 static int
294 act8846_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
295     int max_uvolt, int *udelay)
296 {
297 	struct act8846_reg_sc *sc;
298 	uint8_t sel;
299 	int uvolt, rv;
300 
301 	sc = regnode_get_softc(regnode);
302 
303 	if (sc->def->ranges == NULL)
304 		return (ENXIO);
305 
306 	dprintf(sc, "Setting %s to %d<->%d uvolts\n",
307 	    sc->def->name,
308 	    min_uvolt,
309 	    max_uvolt);
310 	rv = regulator_range_volt_to_sel8(sc->def->ranges, sc->def->nranges,
311 	    min_uvolt, max_uvolt, &sel);
312 	if (rv != 0)
313 		return (rv);
314 	*udelay = sc->param->ramp_delay;
315 	rv = act8846_write_sel(sc, sel);
316 
317 	act8846_read_sel(sc, &sel);
318 	regulator_range_sel8_to_volt(sc->def->ranges, sc->def->nranges,
319 	    sel, &uvolt);
320 	dprintf(sc, "Regulator %s set to %d uvolt\n", sc->def->name,
321 	    uvolt);
322 
323 	return (rv);
324 }
325 
326 static int
327 act8846_regnode_get_voltage(struct regnode *regnode, int *uvolt)
328 {
329 	struct act8846_reg_sc *sc;
330 	uint8_t sel;
331 	int rv;
332 
333 	sc = regnode_get_softc(regnode);
334 
335 	if (sc->def->ranges == NULL) {
336 		if (sc->def->id == ACT8846_REG_ID_REG13) {
337 			*uvolt = 1800000;
338 			return (0);
339 		}
340 		return (ENXIO);
341 	}
342 
343 	rv = act8846_read_sel(sc, &sel);
344 	if (rv != 0)
345 		return (rv);
346 	rv = regulator_range_sel8_to_volt(sc->def->ranges, sc->def->nranges,
347 	    sel, uvolt);
348 	dprintf(sc, "Regulator %s is at %d uvolt\n", sc->def->name,
349 	    *uvolt);
350 
351 	return (rv);
352 }
353 
354 static regnode_method_t act8846_regnode_methods[] = {
355 	/* Regulator interface */
356 	REGNODEMETHOD(regnode_init,		act8846_regnode_init),
357 	REGNODEMETHOD(regnode_enable,		act8846_regnode_enable),
358 	REGNODEMETHOD(regnode_set_voltage,	act8846_regnode_set_voltage),
359 	REGNODEMETHOD(regnode_get_voltage,	act8846_regnode_get_voltage),
360 	REGNODEMETHOD_END
361 };
362 DEFINE_CLASS_1(act8846_regnode, act8846_regnode_class, act8846_regnode_methods,
363     sizeof(struct act8846_reg_sc), regnode_class);
364 
365 static int
366 act8846_fdt_parse(struct act8846_softc *sc, phandle_t pnode, phandle_t node,
367     struct act8846_regdef *def, struct regnode_init_def *init_def)
368 {
369 	int rv;
370 	phandle_t supply_node;
371 	char prop_name[64]; /* Maximum OFW property name length. */
372 
373 	rv = regulator_parse_ofw_stdparam(sc->dev, node, init_def);
374 
375 	/* Get parent supply. */
376 	if (def->supply_name == NULL)
377 		 return (0);
378 
379 	snprintf(prop_name, sizeof(prop_name), "%s-supply",
380 	    def->supply_name);
381 	rv = OF_getencprop(pnode, prop_name, &supply_node,
382 	    sizeof(supply_node));
383 	if (rv <= 0)
384 		return (rv);
385 	supply_node = OF_node_from_xref(supply_node);
386 	rv = OF_getprop_alloc(supply_node, "regulator-name",
387 	    (void **)&init_def->parent_name);
388 	if (rv <= 0)
389 		init_def->parent_name = NULL;
390 	return (0);
391 }
392 
393 static struct act8846_reg_sc *
394 act8846_attach(struct act8846_softc *sc, phandle_t pnode, phandle_t node,
395     struct act8846_regdef *def)
396 {
397 	struct act8846_reg_sc *reg_sc;
398 	struct regnode_init_def initdef;
399 	struct regnode *regnode;
400 
401 	memset(&initdef, 0, sizeof(initdef));
402 	if (act8846_fdt_parse(sc, pnode, node, def, &initdef) != 0) {
403 		device_printf(sc->dev, "cannot parse FDT data for regulator\n");
404 		return (NULL);
405 	}
406 	initdef.id = def->id;
407 	initdef.ofw_node = node;
408 
409 	regnode = regnode_create(sc->dev, &act8846_regnode_class, &initdef);
410 	if (regnode == NULL) {
411 		device_printf(sc->dev, "cannot create regulator\n");
412 		return (NULL);
413 	}
414 
415 	reg_sc = regnode_get_softc(regnode);
416 	reg_sc->base_sc = sc;
417 	reg_sc->def = def;
418 	reg_sc->xref = OF_xref_from_node(node);
419 	reg_sc->param = regnode_get_stdparam(regnode);
420 
421 	regnode_register(regnode);
422 
423 	if (bootverbose) {
424 		int volt, rv;
425 		regnode_topo_slock();
426 		rv = regnode_get_voltage(regnode, &volt);
427 		if (rv == ENODEV) {
428 			device_printf(sc->dev,
429 			   " Regulator %s: parent doesn't exist yet.\n",
430 			   regnode_get_name(regnode));
431 		} else if (rv != 0) {
432 			device_printf(sc->dev,
433 			   " Regulator %s: voltage: INVALID!!!\n",
434 			   regnode_get_name(regnode));
435 		} else {
436 			device_printf(sc->dev,
437 			    " Regulator %s: voltage: %d uV\n",
438 			    regnode_get_name(regnode), volt);
439 		}
440 		regnode_topo_unlock();
441 	}
442 
443 	return (reg_sc);
444 }
445 
446 
447 int
448 act8846_regulator_attach(struct act8846_softc *sc, phandle_t node)
449 {
450 	struct act8846_reg_sc *reg;
451 	phandle_t child, rnode;
452 	int i;
453 
454 	rnode = ofw_bus_find_child(node, "regulators");
455 	if (rnode <= 0) {
456 		device_printf(sc->dev, " Cannot find regulators subnode\n");
457 		return (ENXIO);
458 	}
459 
460 	/* ACT8846 specific definitio. */
461 	sc->nregs = nitems(act8846_regdefs);
462 	sc->regs = malloc(sizeof(struct act8846_reg_sc *) * sc->nregs,
463 	    M_ACT8846_REG, M_WAITOK | M_ZERO);
464 
465 
466 	/* Attach all known regulators if exist in DT. */
467 	for (i = 0; i < sc->nregs; i++) {
468 		child = ofw_bus_find_child(rnode, act8846_regdefs[i].name);
469 		if (child == 0) {
470 			if (bootverbose)
471 				device_printf(sc->dev,
472 				    "Regulator %s missing in DT\n",
473 				    act8846_regdefs[i].name);
474 			continue;
475 		}
476 		reg = act8846_attach(sc, node, child, act8846_regdefs + i);
477 		if (reg == NULL) {
478 			device_printf(sc->dev, "Cannot attach regulator: %s\n",
479 			    act8846_regdefs[i].name);
480 			return (ENXIO);
481 		}
482 		sc->regs[i] = reg;
483 	}
484 	return (0);
485 }
486 
487 int
488 act8846_regulator_map(device_t dev, phandle_t xref, int ncells,
489     pcell_t *cells, int *num)
490 {
491 	struct act8846_softc *sc;
492 	int i;
493 
494 	sc = device_get_softc(dev);
495 	for (i = 0; i < sc->nregs; i++) {
496 		if (sc->regs[i] == NULL)
497 			continue;
498 		if (sc->regs[i]->xref == xref) {
499 			*num = sc->regs[i]->def->id;
500 			return (0);
501 		}
502 	}
503 	return (ENXIO);
504 }
505