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