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