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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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