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