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 <log.h>
9#include <linux/printk.h>
10#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;
145	struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
146	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{
160	struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
161	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;
198	struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
199
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{
220	struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
221	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;
253	struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
254
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;
271	struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
272
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{
309	struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
310
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;
327	struct dm_regulator_uclass_plat *uc_pdata;
328	struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
329
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	}
340	uc_pdata = dev_get_uclass_plat(dev);
341
342	/* check setpoint is within limits */
343	if (uV < uc_pdata->min_uV) {
344		pr_err("voltage %duV for %s too low\n", uV, dev->name);
345		return -EINVAL;
346	}
347	if (uV > uc_pdata->max_uV) {
348		pr_err("voltage %duV for %s too high\n", uV, dev->name);
349		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{
373	struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
374
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;
384	struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
385
386	vout = (pdata->supply >= 3000000) ? 5000000 : 0;
387	return vout;
388}
389
390static int tps65910_regulator_of_to_plat(struct udevice *dev)
391{
392	struct udevice *supply;
393	int ret;
394	const char *supply_name;
395	struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
396
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,
428	.plat_auto	= sizeof(struct tps65910_regulator_pdata),
429	.of_to_plat = tps65910_regulator_of_to_plat,
430};
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,
443	.plat_auto	= sizeof(struct tps65910_regulator_pdata),
444	.of_to_plat = tps65910_regulator_of_to_plat,
445};
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,
458	.plat_auto	= sizeof(struct tps65910_regulator_pdata),
459	.of_to_plat = tps65910_regulator_of_to_plat,
460};
461