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 }
Cache object: 689633f137c52ef9247c64e414551dbf
|