1// SPDX-License-Identifier: GPL-2.0+
2/*
3 *  Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
4 */
5
6#include <dm.h>
7#include <power/pmic.h>
8#include <power/regulator.h>
9#include <power/tps65910_pmic.h>
10
11/* fist row is control registers, second is voltage registers */
12static const char tps65911_vdd_reg[][TPS65911_VDD_NUM] = {
13	{ TPS65911_REG_VDD1, TPS65911_REG_VDD2,
14	  TPS65911_REG_VDDCTRL, TPS65911_REG_VIO },
15	{ TPS65911_REG_VDD1_OP, TPS65911_REG_VDD2_OP,
16	  TPS65911_REG_VDDCTRL_OP, 0x00 },
17};
18
19static const char tps65911_ldo_reg[TPS65911_LDO_NUM] = {
20	TPS65911_REG_LDO1, TPS65911_REG_LDO2, TPS65911_REG_LDO3,
21	TPS65911_REG_LDO4, TPS65911_REG_LDO5, TPS65911_REG_LDO6,
22	TPS65911_REG_LDO7, TPS65911_REG_LDO8
23};
24
25static int tps65911_regulator_enable(struct udevice *dev, int op, bool *enable)
26{
27	struct dm_regulator_uclass_plat *uc_pdata =
28					dev_get_uclass_plat(dev);
29	u32 adr = uc_pdata->ctrl_reg;
30	int val, ret;
31
32	val = pmic_reg_read(dev->parent, adr);
33	if (val < 0)
34		return val;
35
36	if (op == PMIC_OP_GET) {
37		if (val & TPS65910_SUPPLY_STATE_ON)
38			*enable = true;
39		else
40			*enable = false;
41
42		return 0;
43	} else if (op == PMIC_OP_SET) {
44		val &= ~TPS65910_SUPPLY_STATE_MASK;
45
46		if (*enable)
47			val |= TPS65910_SUPPLY_STATE_ON;
48
49		ret = pmic_reg_write(dev->parent, adr, val);
50		if (ret)
51			return ret;
52	}
53
54	return 0;
55}
56
57static int tps65911_get_enable(struct udevice *dev)
58{
59	bool enable = false;
60	int ret;
61
62	ret = tps65911_regulator_enable(dev, PMIC_OP_GET, &enable);
63	if (ret)
64		return ret;
65
66	return enable;
67}
68
69static int tps65911_set_enable(struct udevice *dev, bool enable)
70{
71	return tps65911_regulator_enable(dev, PMIC_OP_SET, &enable);
72}
73
74/**
75 * tps65911_vdd_volt2hex() - convert voltage in uV into
76 *			     applicable to register hex value
77 *
78 * @uV:		voltage in uV
79 *
80 * Return: voltage in hex on success, -ve on failure
81 */
82static int tps65911_vdd_volt2hex(int uV)
83{
84	if (uV > TPS65911_VDD_VOLT_MAX)
85		return -EINVAL;
86
87	if (uV < TPS65911_VDD_VOLT_MIN)
88		uV = TPS65911_VDD_VOLT_MIN;
89
90	return (uV - TPS65911_VDD_VOLT_BASE) / 12500;
91}
92
93/**
94 * tps65911_vdd_hex2volt() - convert register hex value into
95 *			     actual voltage in uV
96 *
97 * @hex:	hex value of register
98 *
99 * Return: voltage in uV on success, -ve on failure
100 */
101static int tps65911_vdd_hex2volt(int hex)
102{
103	if (hex > TPS65910_VDD_SEL_MAX)
104		return -EINVAL;
105
106	if (hex < TPS65910_VDD_SEL_MIN)
107		hex = TPS65910_VDD_SEL_MIN;
108
109	return TPS65911_VDD_VOLT_BASE + hex * 12500;
110}
111
112static int tps65911_vio_range[4] = {
113	1500000, 1800000, 2500000, 3300000
114};
115
116static int tps65911_vio_val(struct udevice *dev, int op, int *uV)
117{
118	struct dm_regulator_uclass_plat *uc_pdata =
119					dev_get_uclass_plat(dev);
120	u32 adr = uc_pdata->volt_reg;
121	int i, val;
122
123	val = pmic_reg_read(dev->parent, adr);
124	if (val < 0)
125		return val;
126
127	if (op == PMIC_OP_GET) {
128		*uV = 0;
129
130		val &= TPS65910_SEL_MASK;
131
132		*uV = tps65911_vio_range[val >> 2];
133
134		return 0;
135	}
136
137	val &= ~TPS65910_SEL_MASK;
138
139	for (i = 0; i < ARRAY_SIZE(tps65911_vio_range); i++)
140		if (*uV <= tps65911_vio_range[i])
141			break;
142
143	return pmic_reg_write(dev->parent, adr, val | i << 2);
144}
145
146static int tps65911_vdd_val(struct udevice *dev, int op, int *uV)
147{
148	struct dm_regulator_uclass_plat *uc_pdata =
149					dev_get_uclass_plat(dev);
150	u32 adr = uc_pdata->volt_reg;
151	int val, ret;
152
153	/* in case vdd is vio */
154	if (!adr)
155		return tps65911_vio_val(dev, op, uV);
156
157	val = pmic_reg_read(dev->parent, adr);
158	if (val < 0)
159		return val;
160
161	if (op == PMIC_OP_GET) {
162		*uV = 0;
163
164		ret = tps65911_vdd_hex2volt(val);
165		if (ret < 0)
166			return ret;
167
168		*uV = ret;
169		return 0;
170	}
171
172	val = tps65911_vdd_volt2hex(*uV);
173	if (val < 0)
174		return val;
175
176	return pmic_reg_write(dev->parent, adr, val);
177}
178
179static int tps65911_vdd_probe(struct udevice *dev)
180{
181	struct dm_regulator_uclass_plat *uc_pdata =
182					dev_get_uclass_plat(dev);
183
184	uc_pdata->type = REGULATOR_TYPE_BUCK;
185
186	/* check for vddctrl and vddio cases */
187	if (!strcmp("vddctrl", dev->name)) {
188		uc_pdata->ctrl_reg = tps65911_vdd_reg[0][2];
189		uc_pdata->volt_reg = tps65911_vdd_reg[1][2];
190		return 0;
191	}
192
193	if (!strcmp("vddio", dev->name)) {
194		uc_pdata->ctrl_reg = tps65911_vdd_reg[0][3];
195		uc_pdata->volt_reg = tps65911_vdd_reg[1][3];
196		return 0;
197	}
198
199	if (dev->driver_data > 0) {
200		u8 idx = dev->driver_data - 1;
201
202		uc_pdata->ctrl_reg = tps65911_vdd_reg[0][idx];
203		uc_pdata->volt_reg = tps65911_vdd_reg[1][idx];
204	}
205
206	return 0;
207}
208
209static int vdd_get_value(struct udevice *dev)
210{
211	int uV;
212	int ret;
213
214	ret = tps65911_vdd_val(dev, PMIC_OP_GET, &uV);
215	if (ret)
216		return ret;
217
218	return uV;
219}
220
221static int vdd_set_value(struct udevice *dev, int uV)
222{
223	return tps65911_vdd_val(dev, PMIC_OP_SET, &uV);
224}
225
226static const struct dm_regulator_ops tps65911_vdd_ops = {
227	.get_value  = vdd_get_value,
228	.set_value  = vdd_set_value,
229	.get_enable = tps65911_get_enable,
230	.set_enable = tps65911_set_enable,
231};
232
233U_BOOT_DRIVER(tps65911_vdd) = {
234	.name = TPS65911_VDD_DRIVER,
235	.id = UCLASS_REGULATOR,
236	.ops = &tps65911_vdd_ops,
237	.probe = tps65911_vdd_probe,
238};
239
240/**
241 * tps65911_ldo_volt2hex() - convert voltage in uV into
242 *			     applicable to register hex value
243 *
244 * @idx:	regulator index
245 * @uV:		voltage in uV
246 *
247 * Return: voltage in hex on success, -ve on failure
248 */
249static int tps65911_ldo_volt2hex(int idx, int uV)
250{
251	int step;
252
253	if (uV > TPS65911_LDO_VOLT_MAX)
254		return -EINVAL;
255
256	if (uV < TPS65911_LDO_VOLT_BASE)
257		uV = TPS65911_LDO_VOLT_BASE;
258
259	switch (idx) {
260	case 1:
261	case 2:
262	case 4:
263		step = TPS65911_LDO124_VOLT_STEP;
264		break;
265	case 3:
266	case 5:
267	case 6:
268	case 7:
269	case 8:
270		step = TPS65911_LDO358_VOLT_STEP;
271		break;
272	default:
273		return -EINVAL;
274	};
275
276	return ((uV - TPS65911_LDO_VOLT_BASE) / step) << 2;
277}
278
279/**
280 * tps65911_ldo_hex2volt() - convert register hex value into
281 *			     actual voltage in uV
282 *
283 * @idx:	regulator index
284 * @hex:	hex value of register
285 *
286 * Return: voltage in uV on success, -ve on failure
287 */
288static int tps65911_ldo_hex2volt(int idx, int hex)
289{
290	int step;
291
292	switch (idx) {
293	case 1:
294	case 2:
295	case 4:
296		if (hex > TPS65911_LDO124_VOLT_MAX_HEX)
297			return -EINVAL;
298
299		step = TPS65911_LDO124_VOLT_STEP;
300		break;
301	case 3:
302	case 5:
303	case 6:
304	case 7:
305	case 8:
306		if (hex > TPS65911_LDO358_VOLT_MAX_HEX)
307			return -EINVAL;
308
309		if (hex < TPS65911_LDO358_VOLT_MIN_HEX)
310			hex = TPS65911_LDO358_VOLT_MIN_HEX;
311
312		step = TPS65911_LDO358_VOLT_STEP;
313		break;
314	default:
315		return -EINVAL;
316	};
317
318	return TPS65911_LDO_VOLT_BASE + hex * step;
319}
320
321static int tps65911_ldo_val(struct udevice *dev, int op, int *uV)
322{
323	struct dm_regulator_uclass_plat *uc_pdata =
324					dev_get_uclass_plat(dev);
325	u32 adr = uc_pdata->ctrl_reg;
326	int idx = dev->driver_data;
327	int val, hex, ret;
328
329	val = pmic_reg_read(dev->parent, adr);
330	if (val < 0)
331		return val;
332
333	if (op == PMIC_OP_GET) {
334		*uV = 0;
335		val &= TPS65911_LDO_SEL_MASK;
336
337		ret = tps65911_ldo_hex2volt(idx, val >> 2);
338		if (ret < 0)
339			return ret;
340
341		*uV = ret;
342		return 0;
343	}
344
345	hex = tps65911_ldo_volt2hex(idx, *uV);
346	if (hex < 0)
347		return hex;
348
349	val &= ~TPS65911_LDO_SEL_MASK;
350
351	return pmic_reg_write(dev->parent, adr, val | hex);
352}
353
354static int tps65911_ldo_probe(struct udevice *dev)
355{
356	struct dm_regulator_uclass_plat *uc_pdata =
357					dev_get_uclass_plat(dev);
358	u8 idx = dev->driver_data - 1;
359
360	uc_pdata->type = REGULATOR_TYPE_LDO;
361	uc_pdata->ctrl_reg = tps65911_ldo_reg[idx];
362
363	return 0;
364}
365
366static int ldo_get_value(struct udevice *dev)
367{
368	int uV;
369	int ret;
370
371	ret = tps65911_ldo_val(dev, PMIC_OP_GET, &uV);
372	if (ret)
373		return ret;
374
375	return uV;
376}
377
378static int ldo_set_value(struct udevice *dev, int uV)
379{
380	return tps65911_ldo_val(dev, PMIC_OP_SET, &uV);
381}
382
383static const struct dm_regulator_ops tps65911_ldo_ops = {
384	.get_value  = ldo_get_value,
385	.set_value  = ldo_set_value,
386	.get_enable = tps65911_get_enable,
387	.set_enable = tps65911_set_enable,
388};
389
390U_BOOT_DRIVER(tps65911_ldo) = {
391	.name = TPS65911_LDO_DRIVER,
392	.id = UCLASS_REGULATOR,
393	.ops = &tps65911_ldo_ops,
394	.probe = tps65911_ldo_probe,
395};
396