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