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