xref: /freebsd/sys/arm64/nvidia/tegra210/max77620_regulators.c (revision 02e9120893770924227138ba49df1edb3896112a)
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/extres/regulator/regulator.h>
41 #include <dev/gpio/gpiobusvar.h>
42 
43 #include <dt-bindings/mfd/max77620.h>
44 
45 #include "max77620.h"
46 
47 MALLOC_DEFINE(M_MAX77620_REG, "MAX77620 regulator", "MAX77620 power regulator");
48 
49 #define	DIV_ROUND_UP(n,d) howmany(n, d)
50 
51 enum 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. */
68 struct 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. */
80 struct 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 
96 struct 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 
120 static struct regulator_range max77620_sd0_ranges[] = {
121 	REG_RANGE_INIT(0, 64, 600000, 12500),  /* 0.6V - 1.4V / 12.5mV */
122 };
123 
124 static struct regulator_range max77620_sd1_ranges[] = {
125 	REG_RANGE_INIT(0, 76, 600000, 12500),  /* 0.6V - 1.55V / 12.5mV */
126 };
127 
128 static struct regulator_range max77620_sdx_ranges[] = {
129 	REG_RANGE_INIT(0, 255, 600000, 12500),  /* 0.6V - 3.7875V / 12.5mV */
130 };
131 
132 static struct regulator_range max77620_ldo0_1_ranges[] = {
133 	REG_RANGE_INIT(0, 63, 800000, 25000),  /* 0.8V - 2.375V / 25mV */
134 };
135 
136 static struct regulator_range max77620_ldo4_ranges[] = {
137 	REG_RANGE_INIT(0, 63, 800000, 12500),  /* 0.8V - 1.5875V / 12.5mV */
138 };
139 
140 static struct regulator_range max77620_ldox_ranges[] = {
141 	REG_RANGE_INIT(0, 63, 800000, 50000),  /* 0.8V - 3.95V / 50mV */
142 };
143 
144 static 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 
343 static int max77620_regnode_init(struct regnode *regnode);
344 static int max77620_regnode_enable(struct regnode *regnode, bool enable,
345     int *udelay);
346 static int max77620_regnode_set_volt(struct regnode *regnode, int min_uvolt,
347     int max_uvolt, int *udelay);
348 static int max77620_regnode_get_volt(struct regnode *regnode, int *uvolt);
349 static 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 };
357 DEFINE_CLASS_1(max77620_regnode, max77620_regnode_class, max77620_regnode_methods,
358    sizeof(struct max77620_reg_sc), regnode_class);
359 
360 static int
361 max77620_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 
376 static int
377 max77620_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 
394 static int
395 max77620_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 
408 static int
409 max77620_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 
421 static int
422 max77620_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 
454 static int
455 max77620_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 
468 static int
469 max77620_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 
481 static int
482 max77620_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 
513 static int
514 max77620_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 
544 static int
545 max77620_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 {
556 uint8_t val1, val2, val3;
557 RD1(sc->base_sc, sc->def->volt_reg, &val1);
558 RD1(sc->base_sc, sc->def->cfg_reg, &val2);
559 RD1(sc->base_sc, sc->def->fps_reg, &val3);
560 printf("%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 
631 static void
632 max77620_fdt_parse(struct max77620_softc *sc, phandle_t node, struct reg_def *def,
633 struct 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 
695 static struct max77620_reg_sc *
696 max77620_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 
757 int
758 max77620_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 
798 int
799 max77620_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 
818 static int
819 max77620_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 
849 static int
850 max77620_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 
868 static int
869 max77620_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