1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright 2020 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/gpio.h>
32#include <sys/kernel.h>
33#include <sys/module.h>
34#include <sys/malloc.h>
35#include <sys/rman.h>
36#include <sys/sx.h>
37
38#include <machine/bus.h>
39
40#include <dev/regulator/regulator.h>
41#include <dev/gpio/gpiobusvar.h>
42
43#include <dt-bindings/mfd/max77620.h>
44
45#include "max77620.h"
46
47MALLOC_DEFINE(M_MAX77620_REG, "MAX77620 regulator", "MAX77620 power regulator");
48
49#define	DIV_ROUND_UP(n,d) howmany(n, d)
50
51enum max77620_reg_id {
52	MAX77620_REG_ID_SD0,
53	MAX77620_REG_ID_SD1,
54	MAX77620_REG_ID_SD2,
55	MAX77620_REG_ID_SD3,
56	MAX77620_REG_ID_LDO0,
57	MAX77620_REG_ID_LDO1,
58	MAX77620_REG_ID_LDO2,
59	MAX77620_REG_ID_LDO3,
60	MAX77620_REG_ID_LDO4,
61	MAX77620_REG_ID_LDO5,
62	MAX77620_REG_ID_LDO6,
63	MAX77620_REG_ID_LDO7,
64	MAX77620_REG_ID_LDO8,
65};
66
67/* Initial configuration. */
68struct max77620_regnode_init_def {
69	struct regnode_init_def	reg_init_def;
70	int active_fps_src;
71	int active_fps_pu_slot;
72	int active_fps_pd_slot;
73	int suspend_fps_src;
74	int suspend_fps_pu_slot;
75	int suspend_fps_pd_slot;
76	int ramp_rate_setting;
77};
78
79/* Regulator HW definition. */
80struct reg_def {
81	intptr_t		id;		/* ID */
82	char			*name;		/* Regulator name */
83	char			*supply_name;	/* Source property name */
84	bool 			is_sd_reg; 	/* SD or LDO regulator? */
85	uint8_t			volt_reg;
86	uint8_t			volt_vsel_mask;
87	uint8_t			cfg_reg;
88	uint8_t			fps_reg;
89	uint8_t			pwr_mode_reg;
90	uint8_t			pwr_mode_mask;
91	uint8_t			pwr_mode_shift;
92	struct regulator_range	*ranges;
93	int			nranges;
94};
95
96struct max77620_reg_sc {
97	struct regnode		*regnode;
98	struct max77620_softc	*base_sc;
99	struct reg_def		*def;
100	phandle_t		xref;
101
102	struct regnode_std_param *param;
103	/* Configured values */
104	int			active_fps_src;
105	int			active_fps_pu_slot;
106	int			active_fps_pd_slot;
107	int			suspend_fps_src;
108	int			suspend_fps_pu_slot;
109	int			suspend_fps_pd_slot;
110	int			ramp_rate_setting;
111	int			enable_usec;
112	uint8_t			enable_pwr_mode;
113
114	/* Cached values */
115	uint8_t			fps_src;
116	uint8_t			pwr_mode;
117	int			pwr_ramp_delay;
118};
119
120static struct regulator_range max77620_sd0_ranges[] = {
121	REG_RANGE_INIT(0, 64, 600000, 12500),  /* 0.6V - 1.4V / 12.5mV */
122};
123
124static struct regulator_range max77620_sd1_ranges[] = {
125	REG_RANGE_INIT(0, 76, 600000, 12500),  /* 0.6V - 1.55V / 12.5mV */
126};
127
128static struct regulator_range max77620_sdx_ranges[] = {
129	REG_RANGE_INIT(0, 255, 600000, 12500),  /* 0.6V - 3.7875V / 12.5mV */
130};
131
132static struct regulator_range max77620_ldo0_1_ranges[] = {
133	REG_RANGE_INIT(0, 63, 800000, 25000),  /* 0.8V - 2.375V / 25mV */
134};
135
136static struct regulator_range max77620_ldo4_ranges[] = {
137	REG_RANGE_INIT(0, 63, 800000, 12500),  /* 0.8V - 1.5875V / 12.5mV */
138};
139
140static struct regulator_range max77620_ldox_ranges[] = {
141	REG_RANGE_INIT(0, 63, 800000, 50000),  /* 0.8V - 3.95V / 50mV */
142};
143
144static struct reg_def max77620s_def[] = {
145	{
146		.id = MAX77620_REG_ID_SD0,
147		.name = "sd0",
148		.supply_name = "in-sd0",
149		.is_sd_reg = true,
150		.volt_reg = MAX77620_REG_SD0,
151		.volt_vsel_mask = MAX77620_SD0_VSEL_MASK,
152		.cfg_reg = MAX77620_REG_CFG_SD0,
153		.fps_reg = MAX77620_REG_FPS_SD0,
154		.pwr_mode_reg = MAX77620_REG_CFG_SD0,
155		.pwr_mode_mask = MAX77620_SD_POWER_MODE_MASK,
156		.pwr_mode_shift = MAX77620_SD_POWER_MODE_SHIFT,
157		.ranges = max77620_sd0_ranges,
158		.nranges = nitems(max77620_sd0_ranges),
159	},
160	{
161		.id = MAX77620_REG_ID_SD1,
162		.name = "sd1",
163		.supply_name = "in-sd1",
164		.is_sd_reg = true,
165		.volt_reg = MAX77620_REG_SD1,
166		.volt_vsel_mask = MAX77620_SD1_VSEL_MASK,
167		.cfg_reg = MAX77620_REG_CFG_SD1,
168		.fps_reg = MAX77620_REG_FPS_SD1,
169		.pwr_mode_reg = MAX77620_REG_CFG_SD1,
170		.pwr_mode_mask = MAX77620_SD_POWER_MODE_MASK,
171		.pwr_mode_shift = MAX77620_SD_POWER_MODE_SHIFT,
172		.ranges = max77620_sd1_ranges,
173		.nranges = nitems(max77620_sd1_ranges),
174	},
175	{
176		.id = MAX77620_REG_ID_SD2,
177		.name = "sd2",
178		.supply_name = "in-sd2",
179		.is_sd_reg = true,
180		.volt_reg = MAX77620_REG_SD2,
181		.volt_vsel_mask = MAX77620_SDX_VSEL_MASK,
182		.cfg_reg = MAX77620_REG_CFG_SD2,
183		.fps_reg = MAX77620_REG_FPS_SD2,
184		.pwr_mode_reg = MAX77620_REG_CFG_SD2,
185		.pwr_mode_mask = MAX77620_SD_POWER_MODE_MASK,
186		.pwr_mode_shift = MAX77620_SD_POWER_MODE_SHIFT,
187		.ranges = max77620_sdx_ranges,
188		.nranges = nitems(max77620_sdx_ranges),
189	},
190	{
191		.id = MAX77620_REG_ID_SD3,
192		.name = "sd3",
193		.supply_name = "in-sd3",
194		.is_sd_reg = true,
195		.volt_reg = MAX77620_REG_SD3,
196		.volt_vsel_mask = MAX77620_SDX_VSEL_MASK,
197		.cfg_reg = MAX77620_REG_CFG_SD3,
198		.fps_reg = MAX77620_REG_FPS_SD3,
199		.pwr_mode_reg = MAX77620_REG_CFG_SD3,
200		.pwr_mode_mask = MAX77620_SD_POWER_MODE_MASK,
201		.pwr_mode_shift = MAX77620_SD_POWER_MODE_SHIFT,
202		.ranges = max77620_sdx_ranges,
203		.nranges = nitems(max77620_sdx_ranges),
204	},
205	{
206		.id = MAX77620_REG_ID_LDO0,
207		.name = "ldo0",
208		.supply_name = "vin-ldo0-1",
209		.volt_reg = MAX77620_REG_CFG_LDO0,
210		.volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
211		.is_sd_reg = false,
212		.cfg_reg = MAX77620_REG_CFG2_LDO0,
213		.fps_reg = MAX77620_REG_FPS_LDO0,
214		.pwr_mode_reg = MAX77620_REG_CFG_LDO0,
215		.pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
216		.pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
217		.ranges = max77620_ldo0_1_ranges,
218		.nranges = nitems(max77620_ldo0_1_ranges),
219	},
220	{
221		.id = MAX77620_REG_ID_LDO1,
222		.name = "ldo1",
223		.supply_name = "in-ldo0-1",
224		.is_sd_reg = false,
225		.volt_reg = MAX77620_REG_CFG_LDO1,
226		.volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
227		.cfg_reg = MAX77620_REG_CFG2_LDO1,
228		.fps_reg = MAX77620_REG_FPS_LDO1,
229		.pwr_mode_reg = MAX77620_REG_CFG_LDO1,
230		.pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
231		.pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
232		.ranges = max77620_ldo0_1_ranges,
233		.nranges = nitems(max77620_ldo0_1_ranges),
234	},
235	{
236		.id = MAX77620_REG_ID_LDO2,
237		.name = "ldo2",
238		.supply_name = "in-ldo2",
239		.is_sd_reg = false,
240		.volt_reg = MAX77620_REG_CFG_LDO2,
241		.volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
242		.cfg_reg = MAX77620_REG_CFG2_LDO2,
243		.fps_reg = MAX77620_REG_FPS_LDO2,
244		.pwr_mode_reg = MAX77620_REG_CFG_LDO2,
245		.pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
246		.pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
247		.ranges = max77620_ldox_ranges,
248		.nranges = nitems(max77620_ldox_ranges),
249	},
250	{
251		.id = MAX77620_REG_ID_LDO3,
252		.name = "ldo3",
253		.supply_name = "in-ldo3-5",
254		.is_sd_reg = false,
255		.volt_reg = MAX77620_REG_CFG_LDO3,
256		.volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
257		.cfg_reg = MAX77620_REG_CFG2_LDO3,
258		.fps_reg = MAX77620_REG_FPS_LDO3,
259		.pwr_mode_reg = MAX77620_REG_CFG_LDO3,
260		.pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
261		.pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
262		.ranges = max77620_ldox_ranges,
263		.nranges = nitems(max77620_ldox_ranges),
264	},
265	{
266		.id = MAX77620_REG_ID_LDO4,
267		.name = "ldo4",
268		.supply_name = "in-ldo4-6",
269		.is_sd_reg = false,
270		.volt_reg = MAX77620_REG_CFG_LDO4,
271		.volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
272		.cfg_reg = MAX77620_REG_CFG2_LDO4,
273		.fps_reg = MAX77620_REG_FPS_LDO4,
274		.pwr_mode_reg = MAX77620_REG_CFG_LDO4,
275		.pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
276		.pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
277		.ranges = max77620_ldo4_ranges,
278		.nranges = nitems(max77620_ldo4_ranges),
279	},
280	{
281		.id = MAX77620_REG_ID_LDO5,
282		.name = "ldo5",
283		.supply_name = "in-ldo3-5",
284		.is_sd_reg = false,
285		.volt_reg = MAX77620_REG_CFG_LDO5,
286		.volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
287		.cfg_reg = MAX77620_REG_CFG2_LDO5,
288		.fps_reg = MAX77620_REG_FPS_LDO5,
289		.pwr_mode_reg = MAX77620_REG_CFG_LDO5,
290		.pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
291		.pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
292		.ranges = max77620_ldox_ranges,
293		.nranges = nitems(max77620_ldox_ranges),
294	},
295	{
296		.id = MAX77620_REG_ID_LDO6,
297		.name = "ldo6",
298		.supply_name = "in-ldo4-6",
299		.is_sd_reg = false,
300		.volt_reg = MAX77620_REG_CFG_LDO6,
301		.volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
302		.cfg_reg = MAX77620_REG_CFG2_LDO6,
303		.fps_reg = MAX77620_REG_FPS_LDO6,
304		.pwr_mode_reg = MAX77620_REG_CFG_LDO6,
305		.pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
306		.pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
307		.ranges = max77620_ldox_ranges,
308		.nranges = nitems(max77620_ldox_ranges),
309	},
310	{
311		.id = MAX77620_REG_ID_LDO7,
312		.name = "ldo7",
313		.supply_name = "in-ldo7-8",
314		.is_sd_reg = false,
315		.volt_reg = MAX77620_REG_CFG_LDO7,
316		.volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
317		.cfg_reg = MAX77620_REG_CFG2_LDO7,
318		.fps_reg = MAX77620_REG_FPS_LDO7,
319		.pwr_mode_reg = MAX77620_REG_CFG_LDO7,
320		.pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
321		.pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
322		.ranges = max77620_ldox_ranges,
323		.nranges = nitems(max77620_ldox_ranges),
324	},
325	{
326		.id = MAX77620_REG_ID_LDO8,
327		.name = "ldo8",
328		.supply_name = "in-ldo7-8",
329		.is_sd_reg = false,
330		.volt_reg = MAX77620_REG_CFG_LDO8,
331		.volt_vsel_mask = MAX77620_LDO_VSEL_MASK,
332		.cfg_reg = MAX77620_REG_CFG2_LDO8,
333		.fps_reg = MAX77620_REG_FPS_LDO8,
334		.pwr_mode_reg = MAX77620_REG_CFG_LDO8,
335		.pwr_mode_mask = MAX77620_LDO_POWER_MODE_MASK,
336		.pwr_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,
337		.ranges = max77620_ldox_ranges,
338		.nranges = nitems(max77620_ldox_ranges),
339	},
340};
341
342
343static int max77620_regnode_init(struct regnode *regnode);
344static int max77620_regnode_enable(struct regnode *regnode, bool enable,
345    int *udelay);
346static int max77620_regnode_set_volt(struct regnode *regnode, int min_uvolt,
347    int max_uvolt, int *udelay);
348static int max77620_regnode_get_volt(struct regnode *regnode, int *uvolt);
349static regnode_method_t max77620_regnode_methods[] = {
350	/* Regulator interface */
351	REGNODEMETHOD(regnode_init,		max77620_regnode_init),
352	REGNODEMETHOD(regnode_enable,		max77620_regnode_enable),
353	REGNODEMETHOD(regnode_set_voltage,	max77620_regnode_set_volt),
354	REGNODEMETHOD(regnode_get_voltage,	max77620_regnode_get_volt),
355	REGNODEMETHOD_END
356};
357DEFINE_CLASS_1(max77620_regnode, max77620_regnode_class, max77620_regnode_methods,
358   sizeof(struct max77620_reg_sc), regnode_class);
359
360static int
361max77620_get_sel(struct max77620_reg_sc *sc, uint8_t *sel)
362{
363	int rv;
364
365	rv = RD1(sc->base_sc, sc->def->volt_reg, sel);
366	if (rv != 0) {
367		printf("%s: cannot read volatge selector: %d\n",
368		    regnode_get_name(sc->regnode), rv);
369		return (rv);
370	}
371	*sel &= sc->def->volt_vsel_mask;
372	*sel >>= ffs(sc->def->volt_vsel_mask) - 1;
373	return (0);
374}
375
376static int
377max77620_set_sel(struct max77620_reg_sc *sc, uint8_t sel)
378{
379	int rv;
380
381	sel <<= ffs(sc->def->volt_vsel_mask) - 1;
382	sel &= sc->def->volt_vsel_mask;
383
384	rv = RM1(sc->base_sc, sc->def->volt_reg,
385	    sc->def->volt_vsel_mask, sel);
386	if (rv != 0) {
387		printf("%s: cannot set volatge selector: %d\n",
388		    regnode_get_name(sc->regnode), rv);
389		return (rv);
390	}
391	return (rv);
392}
393
394static int
395max77620_get_fps_src(struct max77620_reg_sc *sc, uint8_t *fps_src)
396{
397	uint8_t val;
398	int rv;
399
400	rv = RD1(sc->base_sc, sc->def->fps_reg, &val);
401	if (rv != 0)
402		return (rv);
403
404	*fps_src  = (val & MAX77620_FPS_SRC_MASK) >> MAX77620_FPS_SRC_SHIFT;
405	return (0);
406}
407
408static int
409max77620_set_fps_src(struct max77620_reg_sc *sc, uint8_t fps_src)
410{
411	int rv;
412
413	rv = RM1(sc->base_sc, sc->def->fps_reg, MAX77620_FPS_SRC_MASK,
414	    fps_src << MAX77620_FPS_SRC_SHIFT);
415	if (rv != 0)
416		return (rv);
417	sc->fps_src = fps_src;
418	return (0);
419}
420
421static int
422max77620_set_fps_slots(struct max77620_reg_sc *sc, bool suspend)
423{
424	uint8_t mask, val;
425	int pu_slot, pd_slot, rv;
426
427	if (suspend) {
428		pu_slot = sc->suspend_fps_pu_slot;
429		pd_slot = sc->suspend_fps_pd_slot;
430	} else {
431		pu_slot = sc->active_fps_pu_slot;
432		pd_slot = sc->active_fps_pd_slot;
433	}
434
435	mask = 0;
436	val = 0;
437	if (pu_slot >= 0) {
438		mask |= MAX77620_FPS_PU_PERIOD_MASK;
439		val |= ((uint8_t)pu_slot << MAX77620_FPS_PU_PERIOD_SHIFT) &
440		    MAX77620_FPS_PU_PERIOD_MASK;
441	}
442	if (pd_slot >= 0) {
443		mask |= MAX77620_FPS_PD_PERIOD_MASK;
444		val |= ((uint8_t)pd_slot << MAX77620_FPS_PD_PERIOD_SHIFT) &
445		    MAX77620_FPS_PD_PERIOD_MASK;
446	}
447
448	rv = RM1(sc->base_sc, sc->def->fps_reg, mask, val);
449	if (rv != 0)
450		return (rv);
451	return (0);
452}
453
454static int
455max77620_get_pwr_mode(struct max77620_reg_sc *sc, uint8_t *pwr_mode)
456{
457	uint8_t val;
458	int rv;
459
460	rv = RD1(sc->base_sc, sc->def->pwr_mode_reg, &val);
461	if (rv != 0)
462		return (rv);
463
464	*pwr_mode  = (val & sc->def->pwr_mode_mask) >> sc->def->pwr_mode_shift;
465	return (0);
466}
467
468static int
469max77620_set_pwr_mode(struct max77620_reg_sc *sc, uint8_t pwr_mode)
470{
471	int rv;
472
473	rv = RM1(sc->base_sc, sc->def->pwr_mode_reg, sc->def->pwr_mode_shift,
474	    pwr_mode << sc->def->pwr_mode_shift);
475	if (rv != 0)
476		return (rv);
477	sc->pwr_mode = pwr_mode;
478	return (0);
479}
480
481static int
482max77620_get_pwr_ramp_delay(struct max77620_reg_sc *sc, int *rate)
483{
484	uint8_t val;
485	int rv;
486
487	rv = RD1(sc->base_sc, sc->def->cfg_reg, &val);
488	if (rv != 0)
489		return (rv);
490
491	if (sc->def->is_sd_reg) {
492		val = (val & MAX77620_SD_SR_MASK) >> MAX77620_SD_SR_SHIFT;
493		if (val == 0)
494			*rate = 13750;
495		else if (val == 1)
496			*rate = 27500;
497		else if (val == 2)
498			*rate = 55000;
499		else
500			*rate = 100000;
501	} else {
502		val = (val & MAX77620_LDO_SLEW_RATE_MASK) >>
503		    MAX77620_LDO_SLEW_RATE_SHIFT;
504		if (val == 0)
505			*rate = 100000;
506		else
507			*rate = 5000;
508	}
509	sc->pwr_ramp_delay = *rate;
510	return (0);
511}
512
513static int
514max77620_set_pwr_ramp_delay(struct max77620_reg_sc *sc, int rate)
515{
516	uint8_t val, mask;
517	int rv;
518
519	if (sc->def->is_sd_reg) {
520		if (rate <= 13750)
521			val = 0;
522		else if (rate <= 27500)
523			val = 1;
524		else if (rate <= 55000)
525			val = 2;
526		else
527			val = 3;
528		val <<= MAX77620_SD_SR_SHIFT;
529		mask = MAX77620_SD_SR_MASK;
530	} else {
531		if (rate <= 5000)
532			val = 1;
533		else
534			val = 0;
535		val <<= MAX77620_LDO_SLEW_RATE_SHIFT;
536		mask = MAX77620_LDO_SLEW_RATE_MASK;
537	}
538	rv = RM1(sc->base_sc, sc->def->cfg_reg, mask, val);
539	if (rv != 0)
540		return (rv);
541	return (0);
542}
543
544static int
545max77620_regnode_init(struct regnode *regnode)
546{
547	struct max77620_reg_sc *sc;
548	uint8_t val;
549	int intval, rv;
550
551	sc = regnode_get_softc(regnode);
552	sc->enable_usec = 500;
553	sc->enable_pwr_mode = MAX77620_POWER_MODE_NORMAL;
554#if 0
555{
556uint8_t val1, val2, val3;
557RD1(sc->base_sc, sc->def->volt_reg, &val1);
558RD1(sc->base_sc, sc->def->cfg_reg, &val2);
559RD1(sc->base_sc, sc->def->fps_reg, &val3);
560printf("%s: Volt: 0x%02X, CFG: 0x%02X, FPS: 0x%02X\n", regnode_get_name(sc->regnode), val1, val2, val3);
561}
562#endif
563	/* Get current power mode */
564	rv = max77620_get_pwr_mode(sc, &val);
565	if (rv != 0) {
566		printf("%s: cannot read current power mode: %d\n",
567		    regnode_get_name(sc->regnode), rv);
568		return (rv);
569	}
570	sc->pwr_mode = val;
571
572	/* Get current power ramp delay */
573	rv = max77620_get_pwr_ramp_delay(sc, &intval);
574	if (rv != 0) {
575		printf("%s: cannot read current power mode: %d\n",
576		    regnode_get_name(sc->regnode), rv);
577		return (rv);
578	}
579	sc->pwr_ramp_delay = intval;
580
581	/* Get FPS source if is not specified. */
582	if (sc->active_fps_src == -1) {
583		rv = max77620_get_fps_src(sc, &val);
584		if (rv != 0) {
585			printf("%s: cannot read current FPS source: %d\n",
586			    regnode_get_name(sc->regnode), rv);
587			return (rv);
588		}
589		sc->active_fps_src = val;
590	}
591
592	/* Configure power mode non-FPS controlled regulators. */
593	if (sc->active_fps_src != MAX77620_FPS_SRC_NONE ||
594	    (sc->pwr_mode != MAX77620_POWER_MODE_DISABLE &&
595	    sc->pwr_mode != sc->enable_pwr_mode)) {
596		rv = max77620_set_pwr_mode(sc, (uint8_t)sc->enable_pwr_mode);
597		if (rv != 0) {
598			printf("%s: cannot set power mode: %d\n",
599			    regnode_get_name(sc->regnode), rv);
600			return (rv);
601		}
602	}
603
604	/* Set FPS source. */
605	rv = max77620_set_fps_src(sc, sc->active_fps_src);
606	if (rv != 0) {
607		printf("%s: cannot setup FPS source: %d\n",
608		    regnode_get_name(sc->regnode), rv);
609		return (rv);
610	}
611	/* Set FPS slots. */
612	rv = max77620_set_fps_slots(sc, false);
613	if (rv != 0) {
614		printf("%s: cannot setup power slots: %d\n",
615		    regnode_get_name(sc->regnode), rv);
616		return (rv);
617	}
618	/* Setup power ramp . */
619	if (sc->ramp_rate_setting != -1) {
620		rv = max77620_set_pwr_ramp_delay(sc, sc->pwr_ramp_delay);
621		if (rv != 0) {
622			printf("%s: cannot set power ramp delay: %d\n",
623			    regnode_get_name(sc->regnode), rv);
624			return (rv);
625		}
626	}
627
628	return (0);
629}
630
631static void
632max77620_fdt_parse(struct max77620_softc *sc, phandle_t node, struct reg_def *def,
633struct max77620_regnode_init_def *init_def)
634{
635	int rv;
636	phandle_t parent, supply_node;
637	char prop_name[64]; /* Maximum OFW property name length. */
638
639	rv = regulator_parse_ofw_stdparam(sc->dev, node,
640	    &init_def->reg_init_def);
641
642	rv = OF_getencprop(node, "maxim,active-fps-source",
643	    &init_def->active_fps_src, sizeof(init_def->active_fps_src));
644	if (rv <= 0)
645		init_def->active_fps_src = MAX77620_FPS_SRC_DEF;
646
647	rv = OF_getencprop(node, "maxim,active-fps-power-up-slot",
648	    &init_def->active_fps_pu_slot, sizeof(init_def->active_fps_pu_slot));
649	if (rv <= 0)
650		init_def->active_fps_pu_slot = -1;
651
652	rv = OF_getencprop(node, "maxim,active-fps-power-down-slot",
653	    &init_def->active_fps_pd_slot, sizeof(init_def->active_fps_pd_slot));
654	if (rv <= 0)
655		init_def->active_fps_pd_slot = -1;
656
657	rv = OF_getencprop(node, "maxim,suspend-fps-source",
658	    &init_def->suspend_fps_src, sizeof(init_def->suspend_fps_src));
659	if (rv <= 0)
660		init_def->suspend_fps_src = -1;
661
662	rv = OF_getencprop(node, "maxim,suspend-fps-power-up-slot",
663	    &init_def->suspend_fps_pu_slot, sizeof(init_def->suspend_fps_pu_slot));
664	if (rv <= 0)
665		init_def->suspend_fps_pu_slot = -1;
666
667	rv = OF_getencprop(node, "maxim,suspend-fps-power-down-slot",
668	    &init_def->suspend_fps_pd_slot, sizeof(init_def->suspend_fps_pd_slot));
669	if (rv <= 0)
670		init_def->suspend_fps_pd_slot = -1;
671
672	rv = OF_getencprop(node, "maxim,ramp-rate-setting",
673	    &init_def->ramp_rate_setting, sizeof(init_def->ramp_rate_setting));
674	if (rv <= 0)
675		init_def->ramp_rate_setting = -1;
676
677	/* Get parent supply. */
678	if (def->supply_name == NULL)
679		 return;
680
681	parent = OF_parent(node);
682	snprintf(prop_name, sizeof(prop_name), "%s-supply",
683	    def->supply_name);
684	rv = OF_getencprop(parent, prop_name, &supply_node,
685	    sizeof(supply_node));
686	if (rv <= 0)
687		return;
688	supply_node = OF_node_from_xref(supply_node);
689	rv = OF_getprop_alloc(supply_node, "regulator-name",
690	    (void **)&init_def->reg_init_def.parent_name);
691	if (rv <= 0)
692		init_def->reg_init_def.parent_name = NULL;
693}
694
695static struct max77620_reg_sc *
696max77620_attach(struct max77620_softc *sc, phandle_t node, struct reg_def *def)
697{
698	struct max77620_reg_sc *reg_sc;
699	struct max77620_regnode_init_def init_def;
700	struct regnode *regnode;
701
702	bzero(&init_def, sizeof(init_def));
703
704	max77620_fdt_parse(sc, node, def, &init_def);
705	init_def.reg_init_def.id = def->id;
706	init_def.reg_init_def.ofw_node = node;
707	regnode = regnode_create(sc->dev, &max77620_regnode_class,
708	    &init_def.reg_init_def);
709	if (regnode == NULL) {
710		device_printf(sc->dev, "Cannot create regulator.\n");
711		return (NULL);
712	}
713	reg_sc = regnode_get_softc(regnode);
714
715	/* Init regulator softc. */
716	reg_sc->regnode = regnode;
717	reg_sc->base_sc = sc;
718	reg_sc->def = def;
719	reg_sc->xref = OF_xref_from_node(node);
720	reg_sc->param = regnode_get_stdparam(regnode);
721	reg_sc->active_fps_src = init_def.active_fps_src;
722	reg_sc->active_fps_pu_slot = init_def.active_fps_pu_slot;
723	reg_sc->active_fps_pd_slot = init_def.active_fps_pd_slot;
724	reg_sc->suspend_fps_src = init_def.suspend_fps_src;
725	reg_sc->suspend_fps_pu_slot = init_def.suspend_fps_pu_slot;
726	reg_sc->suspend_fps_pd_slot = init_def.suspend_fps_pd_slot;
727	reg_sc->ramp_rate_setting = init_def.ramp_rate_setting;
728
729	regnode_register(regnode);
730	if (bootverbose) {
731		int volt, rv;
732		regnode_topo_slock();
733		rv = regnode_get_voltage(regnode, &volt);
734		if (rv == ENODEV) {
735			device_printf(sc->dev,
736			   " Regulator %s: parent doesn't exist yet.\n",
737			   regnode_get_name(regnode));
738		} else if (rv != 0) {
739			device_printf(sc->dev,
740			   " Regulator %s: voltage: INVALID!!!\n",
741			   regnode_get_name(regnode));
742		} else {
743			device_printf(sc->dev,
744			    " Regulator %s: voltage: %d uV\n",
745			    regnode_get_name(regnode), volt);
746			device_printf(sc->dev,
747			    "  FPS source: %d, mode: %d, ramp delay: %d\n",
748			    reg_sc->fps_src, reg_sc->pwr_mode,
749			    reg_sc->pwr_ramp_delay);
750		}
751		regnode_topo_unlock();
752	}
753
754	return (reg_sc);
755}
756
757int
758max77620_regulator_attach(struct max77620_softc *sc, phandle_t node)
759{
760	struct max77620_reg_sc *reg;
761	phandle_t child, rnode;
762	int i;
763
764	rnode = ofw_bus_find_child(node, "regulators");
765	if (rnode <= 0) {
766		device_printf(sc->dev, " Cannot find regulators subnode\n");
767		return (ENXIO);
768	}
769
770	sc->nregs = nitems(max77620s_def);
771	sc->regs = malloc(sizeof(struct max77620_reg_sc *) * sc->nregs,
772	    M_MAX77620_REG, M_WAITOK | M_ZERO);
773
774
775	/* Attach all known regulators if exist in DT. */
776	for (i = 0; i < sc->nregs; i++) {
777		child = ofw_bus_find_child(rnode, max77620s_def[i].name);
778		if (child == 0) {
779			if (bootverbose)
780				device_printf(sc->dev,
781				    "Regulator %s missing in DT\n",
782				    max77620s_def[i].name);
783			continue;
784		}
785		if (ofw_bus_node_status_okay(child) == 0)
786			continue;
787		reg = max77620_attach(sc, child, max77620s_def + i);
788		if (reg == NULL) {
789			device_printf(sc->dev, "Cannot attach regulator: %s\n",
790			    max77620s_def[i].name);
791			return (ENXIO);
792		}
793		sc->regs[i] = reg;
794	}
795	return (0);
796}
797
798int
799max77620_regulator_map(device_t dev, phandle_t xref, int ncells,
800    pcell_t *cells, intptr_t *num)
801{
802	struct max77620_softc *sc;
803	int i;
804
805	sc = device_get_softc(dev);
806	for (i = 0; i < sc->nregs; i++) {
807		if (sc->regs[i] == NULL)
808			continue;
809		if (sc->regs[i]->xref == xref) {
810			*num = sc->regs[i]->def->id;
811			return (0);
812		}
813	}
814
815	return (ENXIO);
816}
817
818static int
819max77620_regnode_enable(struct regnode *regnode, bool val, int *udelay)
820{
821
822	struct max77620_reg_sc *sc;
823	uint8_t mode;
824	int rv;
825
826	sc = regnode_get_softc(regnode);
827
828	if (sc->active_fps_src != MAX77620_FPS_SRC_NONE) {
829		*udelay = 0;
830		return (0);
831	}
832
833	if (val)
834		mode = sc->enable_pwr_mode;
835	else
836		mode = MAX77620_POWER_MODE_DISABLE;
837
838	rv = max77620_set_pwr_mode(sc, mode);
839	if (rv != 0) {
840		printf("%s: cannot set power mode: %d\n",
841		    regnode_get_name(sc->regnode), rv);
842		return (rv);
843	}
844
845	*udelay = sc->enable_usec;
846	return (0);
847}
848
849static int
850max77620_regnode_set_volt(struct regnode *regnode, int min_uvolt, int max_uvolt,
851    int *udelay)
852{
853	struct max77620_reg_sc *sc;
854	uint8_t sel;
855	int rv;
856
857	sc = regnode_get_softc(regnode);
858
859	*udelay = 0;
860	rv = regulator_range_volt_to_sel8(sc->def->ranges, sc->def->nranges,
861	    min_uvolt, max_uvolt, &sel);
862	if (rv != 0)
863		return (rv);
864	rv = max77620_set_sel(sc, sel);
865	return (rv);
866}
867
868static int
869max77620_regnode_get_volt(struct regnode *regnode, int *uvolt)
870{
871
872	struct max77620_reg_sc *sc;
873	uint8_t sel;
874	int rv;
875
876	sc = regnode_get_softc(regnode);
877	rv = max77620_get_sel(sc, &sel);
878	if (rv != 0)
879		return (rv);
880
881	rv = regulator_range_sel8_to_volt(sc->def->ranges, sc->def->nranges,
882	    sel, uvolt);
883	return (rv);
884	return(0);
885}
886