Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm64/nvidia/tegra210/max77620_regulators.c
48262 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright 2020 Michal Meloun <[email protected]>
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
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
887