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