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
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
max77620_get_sel(struct max77620_reg_sc * sc,uint8_t * sel)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
max77620_set_sel(struct max77620_reg_sc * sc,uint8_t sel)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
max77620_get_fps_src(struct max77620_reg_sc * sc,uint8_t * fps_src)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
max77620_set_fps_src(struct max77620_reg_sc * sc,uint8_t fps_src)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
max77620_set_fps_slots(struct max77620_reg_sc * sc,bool suspend)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
max77620_get_pwr_mode(struct max77620_reg_sc * sc,uint8_t * pwr_mode)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
max77620_set_pwr_mode(struct max77620_reg_sc * sc,uint8_t pwr_mode)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
max77620_get_pwr_ramp_delay(struct max77620_reg_sc * sc,int * rate)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
max77620_set_pwr_ramp_delay(struct max77620_reg_sc * sc,int rate)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
max77620_regnode_init(struct regnode * regnode)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
max77620_fdt_parse(struct max77620_softc * sc,phandle_t node,struct reg_def * def,struct max77620_regnode_init_def * init_def)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 *
max77620_attach(struct max77620_softc * sc,phandle_t node,struct reg_def * def)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
max77620_regulator_attach(struct max77620_softc * sc,phandle_t node)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
max77620_regulator_map(device_t dev,phandle_t xref,int ncells,pcell_t * cells,intptr_t * num)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
max77620_regnode_enable(struct regnode * regnode,bool val,int * udelay)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
max77620_regnode_set_volt(struct regnode * regnode,int min_uvolt,int max_uvolt,int * udelay)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
max77620_regnode_get_volt(struct regnode * regnode,int * uvolt)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