blob: 0ed4952a1e0fa5f6cd7187c12b1692e848da7f7a [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Felix Brack9493f0e2017-11-30 13:52:37 +01002/*
3 * Copyright (C) EETS GmbH, 2017, Felix Brack <f.brack@eets.ch>
Felix Brack9493f0e2017-11-30 13:52:37 +01004 */
5
6#include <common.h>
7#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -06008#include <log.h>
Felix Brack9493f0e2017-11-30 13:52:37 +01009#include <power/pmic.h>
10#include <power/regulator.h>
11#include <power/tps65910_pmic.h>
12
13#define VOUT_CHOICE_COUNT 4
14
15/*
16 * struct regulator_props - Properties of a LDO and VIO SMPS regulator
17 *
18 * All of these regulators allow setting one out of four output voltages.
19 * These output voltages are only achievable when supplying the regulator
20 * with a minimum input voltage.
21 *
22 * @vin_min[]: minimum supply input voltage in uV required to achieve the
23 * corresponding vout[] voltage
24 * @vout[]: regulator output voltage in uV
25 * @reg: I2C register used to set regulator voltage
26 */
27struct regulator_props {
28 int vin_min[VOUT_CHOICE_COUNT];
29 int vout[VOUT_CHOICE_COUNT];
30 int reg;
31};
32
33static const struct regulator_props ldo_props_vdig1 = {
34 .vin_min = { 1700000, 2100000, 2700000, 3200000 },
35 .vout = { 1200000, 1500000, 1800000, 2700000 },
36 .reg = TPS65910_REG_VDIG1
37};
38
39static const struct regulator_props ldo_props_vdig2 = {
40 .vin_min = { 1700000, 1700000, 1700000, 2700000 },
41 .vout = { 1000000, 1100000, 1200000, 1800000 },
42 .reg = TPS65910_REG_VDIG2
43};
44
45static const struct regulator_props ldo_props_vpll = {
46 .vin_min = { 2700000, 2700000, 2700000, 3000000 },
47 .vout = { 1000000, 1100000, 1800000, 2500000 },
48 .reg = TPS65910_REG_VPLL
49};
50
51static const struct regulator_props ldo_props_vdac = {
52 .vin_min = { 2700000, 3000000, 3200000, 3200000 },
53 .vout = { 1800000, 2600000, 2800000, 2850000 },
54 .reg = TPS65910_REG_VDAC
55};
56
57static const struct regulator_props ldo_props_vaux1 = {
58 .vin_min = { 2700000, 3200000, 3200000, 3200000 },
59 .vout = { 1800000, 2500000, 2800000, 2850000 },
60 .reg = TPS65910_REG_VAUX1
61};
62
63static const struct regulator_props ldo_props_vaux2 = {
64 .vin_min = { 2700000, 3200000, 3200000, 3600000 },
65 .vout = { 1800000, 2800000, 2900000, 3300000 },
66 .reg = TPS65910_REG_VAUX2
67};
68
69static const struct regulator_props ldo_props_vaux33 = {
70 .vin_min = { 2700000, 2700000, 3200000, 3600000 },
71 .vout = { 1800000, 2000000, 2800000, 3300000 },
72 .reg = TPS65910_REG_VAUX33
73};
74
75static const struct regulator_props ldo_props_vmmc = {
76 .vin_min = { 2700000, 3200000, 3200000, 3600000 },
77 .vout = { 1800000, 2800000, 3000000, 3300000 },
78 .reg = TPS65910_REG_VMMC
79};
80
81static const struct regulator_props smps_props_vio = {
82 .vin_min = { 3200000, 3200000, 4000000, 4400000 },
83 .vout = { 1500000, 1800000, 2500000, 3300000 },
84 .reg = TPS65910_REG_VIO
85};
86
87/* lookup table of control registers indexed by regulator unit number */
88static const int ctrl_regs[] = {
89 TPS65910_REG_VRTC,
90 TPS65910_REG_VIO,
91 TPS65910_REG_VDD1,
92 TPS65910_REG_VDD2,
93 TPS65910_REG_VDD3,
94 TPS65910_REG_VDIG1,
95 TPS65910_REG_VDIG2,
96 TPS65910_REG_VPLL,
97 TPS65910_REG_VDAC,
98 TPS65910_REG_VAUX1,
99 TPS65910_REG_VAUX2,
100 TPS65910_REG_VAUX33,
101 TPS65910_REG_VMMC
102};
103
104/* supply names as used in DT */
105static const char * const supply_names[] = {
106 "vccio-supply",
107 "vcc1-supply",
108 "vcc2-supply",
109 "vcc3-supply",
110 "vcc4-supply",
111 "vcc5-supply",
112 "vcc6-supply",
113 "vcc7-supply"
114};
115
116/* lookup table of regulator supplies indexed by regulator unit number */
117static const int regulator_supplies[] = {
118 TPS65910_SUPPLY_VCC7,
119 TPS65910_SUPPLY_VCCIO,
120 TPS65910_SUPPLY_VCC1,
121 TPS65910_SUPPLY_VCC2,
122 TPS65910_SUPPLY_VCC7,
123 TPS65910_SUPPLY_VCC6,
124 TPS65910_SUPPLY_VCC6,
125 TPS65910_SUPPLY_VCC5,
126 TPS65910_SUPPLY_VCC5,
127 TPS65910_SUPPLY_VCC4,
128 TPS65910_SUPPLY_VCC4,
129 TPS65910_SUPPLY_VCC3,
130 TPS65910_SUPPLY_VCC3
131};
132
133static int get_ctrl_reg_from_unit_addr(const uint unit_addr)
134{
135 if (unit_addr < ARRAY_SIZE(ctrl_regs))
136 return ctrl_regs[unit_addr];
137 return -ENXIO;
138}
139
140static int tps65910_regulator_get_value(struct udevice *dev,
141 const struct regulator_props *rgp)
142{
143 int sel, val, vout;
Simon Glassfa20e932020-12-03 16:55:20 -0700144 struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
Felix Brack9493f0e2017-11-30 13:52:37 +0100145 int vin = pdata->supply;
146
147 val = pmic_reg_read(dev->parent, rgp->reg);
148 if (val < 0)
149 return val;
150 sel = (val & TPS65910_SEL_MASK) >> 2;
151 vout = (vin >= *(rgp->vin_min + sel)) ? *(rgp->vout + sel) : 0;
152 vout = ((val & TPS65910_SUPPLY_STATE_MASK) == 1) ? vout : 0;
153
154 return vout;
155}
156
157static int tps65910_ldo_get_value(struct udevice *dev)
158{
Simon Glassfa20e932020-12-03 16:55:20 -0700159 struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
Felix Brack9493f0e2017-11-30 13:52:37 +0100160 int vin;
161
162 if (!pdata)
163 return 0;
164 vin = pdata->supply;
165
166 switch (pdata->unit) {
167 case TPS65910_UNIT_VRTC:
168 /* VRTC is fixed and can't be turned off */
169 return (vin >= 2500000) ? 1830000 : 0;
170 case TPS65910_UNIT_VDIG1:
171 return tps65910_regulator_get_value(dev, &ldo_props_vdig1);
172 case TPS65910_UNIT_VDIG2:
173 return tps65910_regulator_get_value(dev, &ldo_props_vdig2);
174 case TPS65910_UNIT_VPLL:
175 return tps65910_regulator_get_value(dev, &ldo_props_vpll);
176 case TPS65910_UNIT_VDAC:
177 return tps65910_regulator_get_value(dev, &ldo_props_vdac);
178 case TPS65910_UNIT_VAUX1:
179 return tps65910_regulator_get_value(dev, &ldo_props_vaux1);
180 case TPS65910_UNIT_VAUX2:
181 return tps65910_regulator_get_value(dev, &ldo_props_vaux2);
182 case TPS65910_UNIT_VAUX33:
183 return tps65910_regulator_get_value(dev, &ldo_props_vaux33);
184 case TPS65910_UNIT_VMMC:
185 return tps65910_regulator_get_value(dev, &ldo_props_vmmc);
186 default:
187 return 0;
188 }
189}
190
191static int tps65910_regulator_set_value(struct udevice *dev,
192 const struct regulator_props *ldo,
193 int uV)
194{
195 int val;
196 int sel = 0;
Simon Glassfa20e932020-12-03 16:55:20 -0700197 struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
Felix Brack9493f0e2017-11-30 13:52:37 +0100198
199 do {
200 /* we only allow exact voltage matches */
201 if (uV == *(ldo->vout + sel))
202 break;
203 } while (++sel < VOUT_CHOICE_COUNT);
204 if (sel == VOUT_CHOICE_COUNT)
205 return -EINVAL;
206 if (pdata->supply < *(ldo->vin_min + sel))
207 return -EINVAL;
208
209 val = pmic_reg_read(dev->parent, ldo->reg);
210 if (val < 0)
211 return val;
212 val &= ~TPS65910_SEL_MASK;
213 val |= sel << 2;
214 return pmic_reg_write(dev->parent, ldo->reg, val);
215}
216
217static int tps65910_ldo_set_value(struct udevice *dev, int uV)
218{
Simon Glassfa20e932020-12-03 16:55:20 -0700219 struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
Felix Brack9493f0e2017-11-30 13:52:37 +0100220 int vin = pdata->supply;
221
222 switch (pdata->unit) {
223 case TPS65910_UNIT_VRTC:
224 /* VRTC is fixed to 1.83V and can't be turned off */
225 if (vin < 2500000)
226 return -EINVAL;
227 return 0;
228 case TPS65910_UNIT_VDIG1:
229 return tps65910_regulator_set_value(dev, &ldo_props_vdig1, uV);
230 case TPS65910_UNIT_VDIG2:
231 return tps65910_regulator_set_value(dev, &ldo_props_vdig2, uV);
232 case TPS65910_UNIT_VPLL:
233 return tps65910_regulator_set_value(dev, &ldo_props_vpll, uV);
234 case TPS65910_UNIT_VDAC:
235 return tps65910_regulator_set_value(dev, &ldo_props_vdac, uV);
236 case TPS65910_UNIT_VAUX1:
237 return tps65910_regulator_set_value(dev, &ldo_props_vaux1, uV);
238 case TPS65910_UNIT_VAUX2:
239 return tps65910_regulator_set_value(dev, &ldo_props_vaux2, uV);
240 case TPS65910_UNIT_VAUX33:
241 return tps65910_regulator_set_value(dev, &ldo_props_vaux33, uV);
242 case TPS65910_UNIT_VMMC:
243 return tps65910_regulator_set_value(dev, &ldo_props_vmmc, uV);
244 default:
245 return 0;
246 }
247}
248
249static int tps65910_get_enable(struct udevice *dev)
250{
251 int reg, val;
Simon Glassfa20e932020-12-03 16:55:20 -0700252 struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
Felix Brack9493f0e2017-11-30 13:52:37 +0100253
254 reg = get_ctrl_reg_from_unit_addr(pdata->unit);
255 if (reg < 0)
256 return reg;
257
258 val = pmic_reg_read(dev->parent, reg);
259 if (val < 0)
260 return val;
261
262 /* bits 1:0 of regulator control register define state */
263 return ((val & TPS65910_SUPPLY_STATE_MASK) == 1);
264}
265
266static int tps65910_set_enable(struct udevice *dev, bool enable)
267{
268 int reg;
269 uint clr, set;
Simon Glassfa20e932020-12-03 16:55:20 -0700270 struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
Felix Brack9493f0e2017-11-30 13:52:37 +0100271
272 reg = get_ctrl_reg_from_unit_addr(pdata->unit);
273 if (reg < 0)
274 return reg;
275
276 if (enable) {
277 clr = TPS65910_SUPPLY_STATE_MASK & ~TPS65910_SUPPLY_STATE_ON;
278 set = TPS65910_SUPPLY_STATE_MASK & TPS65910_SUPPLY_STATE_ON;
279 } else {
280 clr = TPS65910_SUPPLY_STATE_MASK & ~TPS65910_SUPPLY_STATE_OFF;
281 set = TPS65910_SUPPLY_STATE_MASK & TPS65910_SUPPLY_STATE_OFF;
282 }
283 return pmic_clrsetbits(dev->parent, reg, clr, set);
284}
285
286static int buck_get_vdd1_vdd2_value(struct udevice *dev, int reg_vdd)
287{
288 int gain;
289 int val = pmic_reg_read(dev, reg_vdd);
290
291 if (val < 0)
292 return val;
293 gain = (val & TPS65910_GAIN_SEL_MASK) >> 6;
294 gain = (gain == 0) ? 1 : gain;
295 val = pmic_reg_read(dev, reg_vdd + 1);
296 if (val < 0)
297 return val;
298 if (val & TPS65910_VDD_SR_MASK)
299 /* use smart reflex value instead */
300 val = pmic_reg_read(dev, reg_vdd + 2);
301 if (val < 0)
302 return val;
303 return (562500 + (val & TPS65910_VDD_SEL_MASK) * 12500) * gain;
304}
305
306static int tps65910_buck_get_value(struct udevice *dev)
307{
Simon Glassfa20e932020-12-03 16:55:20 -0700308 struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
Felix Brack9493f0e2017-11-30 13:52:37 +0100309
310 switch (pdata->unit) {
311 case TPS65910_UNIT_VIO:
312 return tps65910_regulator_get_value(dev, &smps_props_vio);
313 case TPS65910_UNIT_VDD1:
314 return buck_get_vdd1_vdd2_value(dev->parent, TPS65910_REG_VDD1);
315 case TPS65910_UNIT_VDD2:
316 return buck_get_vdd1_vdd2_value(dev->parent, TPS65910_REG_VDD2);
317 default:
318 return 0;
319 }
320}
321
322static int buck_set_vdd1_vdd2_value(struct udevice *dev, int uV)
323{
324 int ret, reg_vdd, gain;
325 int val;
Simon Glass71fa5b42020-12-03 16:55:18 -0700326 struct dm_regulator_uclass_plat *uc_pdata;
Simon Glassfa20e932020-12-03 16:55:20 -0700327 struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
Felix Brack9493f0e2017-11-30 13:52:37 +0100328
329 switch (pdata->unit) {
330 case TPS65910_UNIT_VDD1:
331 reg_vdd = TPS65910_REG_VDD1;
332 break;
333 case TPS65910_UNIT_VDD2:
334 reg_vdd = TPS65910_REG_VDD2;
335 break;
336 default:
337 return -EINVAL;
338 }
Simon Glass71fa5b42020-12-03 16:55:18 -0700339 uc_pdata = dev_get_uclass_plat(dev);
Felix Brack9493f0e2017-11-30 13:52:37 +0100340
341 /* check setpoint is within limits */
342 if (uV < uc_pdata->min_uV) {
Felix Brackabdd51d2017-12-18 15:38:28 +0100343 pr_err("voltage %duV for %s too low\n", uV, dev->name);
Felix Brack9493f0e2017-11-30 13:52:37 +0100344 return -EINVAL;
345 }
346 if (uV > uc_pdata->max_uV) {
Felix Brackabdd51d2017-12-18 15:38:28 +0100347 pr_err("voltage %duV for %s too high\n", uV, dev->name);
Felix Brack9493f0e2017-11-30 13:52:37 +0100348 return -EINVAL;
349 }
350
351 val = pmic_reg_read(dev->parent, reg_vdd);
352 if (val < 0)
353 return val;
354 gain = (val & TPS65910_GAIN_SEL_MASK) >> 6;
355 gain = (gain == 0) ? 1 : gain;
356 val = ((uV / gain) - 562500) / 12500;
357 if (val < TPS65910_VDD_SEL_MIN || val > TPS65910_VDD_SEL_MAX)
358 /*
359 * Neither do we change the gain, nor do we allow shutdown or
360 * any approximate value (for now)
361 */
362 return -EPERM;
363 val &= TPS65910_VDD_SEL_MASK;
364 ret = pmic_reg_write(dev->parent, reg_vdd + 1, val);
365 if (ret)
366 return ret;
367 return 0;
368}
369
370static int tps65910_buck_set_value(struct udevice *dev, int uV)
371{
Simon Glassfa20e932020-12-03 16:55:20 -0700372 struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
Felix Brack9493f0e2017-11-30 13:52:37 +0100373
374 if (pdata->unit == TPS65910_UNIT_VIO)
375 return tps65910_regulator_set_value(dev, &smps_props_vio, uV);
376
377 return buck_set_vdd1_vdd2_value(dev, uV);
378}
379
380static int tps65910_boost_get_value(struct udevice *dev)
381{
382 int vout;
Simon Glassfa20e932020-12-03 16:55:20 -0700383 struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
Felix Brack9493f0e2017-11-30 13:52:37 +0100384
385 vout = (pdata->supply >= 3000000) ? 5000000 : 0;
386 return vout;
387}
388
Simon Glassaad29ae2020-12-03 16:55:21 -0700389static int tps65910_regulator_of_to_plat(struct udevice *dev)
Felix Brack9493f0e2017-11-30 13:52:37 +0100390{
391 struct udevice *supply;
392 int ret;
393 const char *supply_name;
Simon Glassfa20e932020-12-03 16:55:20 -0700394 struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
Felix Brack9493f0e2017-11-30 13:52:37 +0100395
396 pdata->unit = dev_get_driver_data(dev);
397 if (pdata->unit > TPS65910_UNIT_VMMC)
398 return -EINVAL;
399 supply_name = supply_names[regulator_supplies[pdata->unit]];
400
401 debug("Looking up supply power %s\n", supply_name);
402 ret = device_get_supply_regulator(dev->parent, supply_name, &supply);
403 if (ret) {
404 debug(" missing supply power %s\n", supply_name);
405 return ret;
406 }
407 pdata->supply = regulator_get_value(supply);
408 if (pdata->supply < 0) {
409 debug(" invalid supply voltage for regulator %s\n",
410 supply->name);
411 return -EINVAL;
412 }
413
414 return 0;
415}
416
417static const struct dm_regulator_ops tps65910_boost_ops = {
418 .get_value = tps65910_boost_get_value,
419 .get_enable = tps65910_get_enable,
420 .set_enable = tps65910_set_enable,
421};
422
423U_BOOT_DRIVER(tps65910_boost) = {
424 .name = TPS65910_BOOST_DRIVER,
425 .id = UCLASS_REGULATOR,
426 .ops = &tps65910_boost_ops,
Simon Glass71fa5b42020-12-03 16:55:18 -0700427 .plat_auto = sizeof(struct tps65910_regulator_pdata),
Simon Glassaad29ae2020-12-03 16:55:21 -0700428 .of_to_plat = tps65910_regulator_of_to_plat,
Felix Brack9493f0e2017-11-30 13:52:37 +0100429};
430
431static const struct dm_regulator_ops tps65910_buck_ops = {
432 .get_value = tps65910_buck_get_value,
433 .set_value = tps65910_buck_set_value,
434 .get_enable = tps65910_get_enable,
435 .set_enable = tps65910_set_enable,
436};
437
438U_BOOT_DRIVER(tps65910_buck) = {
439 .name = TPS65910_BUCK_DRIVER,
440 .id = UCLASS_REGULATOR,
441 .ops = &tps65910_buck_ops,
Simon Glass71fa5b42020-12-03 16:55:18 -0700442 .plat_auto = sizeof(struct tps65910_regulator_pdata),
Simon Glassaad29ae2020-12-03 16:55:21 -0700443 .of_to_plat = tps65910_regulator_of_to_plat,
Felix Brack9493f0e2017-11-30 13:52:37 +0100444};
445
446static const struct dm_regulator_ops tps65910_ldo_ops = {
447 .get_value = tps65910_ldo_get_value,
448 .set_value = tps65910_ldo_set_value,
449 .get_enable = tps65910_get_enable,
450 .set_enable = tps65910_set_enable,
451};
452
453U_BOOT_DRIVER(tps65910_ldo) = {
454 .name = TPS65910_LDO_DRIVER,
455 .id = UCLASS_REGULATOR,
456 .ops = &tps65910_ldo_ops,
Simon Glass71fa5b42020-12-03 16:55:18 -0700457 .plat_auto = sizeof(struct tps65910_regulator_pdata),
Simon Glassaad29ae2020-12-03 16:55:21 -0700458 .of_to_plat = tps65910_regulator_of_to_plat,
Felix Brack9493f0e2017-11-30 13:52:37 +0100459};