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/tps80031.h>
10 
11 static const char tps80031_smps_reg[][TPS80031_SMPS_NUM] = {
12 	{   0x54,   0x5a,   0x66,   0x42,   0x48 },
13 	{   0x56,   0x5c,   0x68,   0x44,   0x4a },
14 	{ BIT(3), BIT(4), BIT(6), BIT(0), BIT(1) },
15 };
16 
17 static const char tps80031_ldo_reg[][TPS80031_LDO_NUM] = {
18 	{ 0x9e, 0x86, 0x8e, 0x8a, 0x9a, 0x92, 0xa6, 0x96, 0xa2 },
19 	{ 0x9f, 0x87, 0x8f, 0x8b, 0x9b, 0x93, 0xa7, 0x97, 0xa3 },
20 };
21 
tps80031_regulator_enable(struct udevice * dev,int op,bool * enable)22 static int tps80031_regulator_enable(struct udevice *dev, int op, bool *enable)
23 {
24 	struct dm_regulator_uclass_plat *uc_pdata =
25 					dev_get_uclass_plat(dev);
26 	u32 adr = uc_pdata->ctrl_reg;
27 	int val, ret;
28 
29 	val = pmic_reg_read(dev->parent, adr);
30 	if (val < 0)
31 		return val;
32 
33 	if (op == PMIC_OP_GET) {
34 		if (val & REGULATOR_MODE_ON)
35 			*enable = true;
36 		else
37 			*enable = false;
38 
39 		return 0;
40 	} else if (op == PMIC_OP_SET) {
41 		val &= ~REGULATOR_STATUS_MASK;
42 
43 		if (*enable)
44 			val |= REGULATOR_MODE_ON;
45 
46 		ret = pmic_reg_write(dev->parent, adr, val);
47 		if (ret)
48 			return ret;
49 	}
50 
51 	return 0;
52 }
53 
tps80031_get_enable(struct udevice * dev)54 static int tps80031_get_enable(struct udevice *dev)
55 {
56 	bool enable = false;
57 	int ret;
58 
59 	ret = tps80031_regulator_enable(dev, PMIC_OP_GET, &enable);
60 	if (ret)
61 		return ret;
62 
63 	return enable;
64 }
65 
tps80031_set_enable(struct udevice * dev,bool enable)66 static int tps80031_set_enable(struct udevice *dev, bool enable)
67 {
68 	return tps80031_regulator_enable(dev, PMIC_OP_SET, &enable);
69 }
70 
71 /**
72  * tps80031_ldo_volt2hex() - convert voltage in uV into
73  *			     applicable to register hex value
74  *
75  * @uV:		voltage in uV
76  *
77  * Return: voltage in hex on success, -ve on failure
78  */
tps80031_ldo_volt2hex(int uV)79 static int tps80031_ldo_volt2hex(int uV)
80 {
81 	if (uV > LDO_VOLT_MAX)
82 		return -EINVAL;
83 
84 	if (uV < LDO_VOLT_MIN)
85 		uV = LDO_VOLT_MIN;
86 
87 	return DIV_ROUND_UP(uV - LDO_VOLT_BASE, 102000);
88 }
89 
90 /**
91  * tps80031_ldo_hex2volt() - convert register hex value into
92  *			     actual voltage in uV
93  *
94  * @hex:	hex value of register
95  *
96  * Return: voltage in uV on success, -ve on failure
97  */
tps80031_ldo_hex2volt(int hex)98 static int tps80031_ldo_hex2volt(int hex)
99 {
100 	if (hex > LDO_VOLT_MAX_HEX)
101 		return -EINVAL;
102 
103 	if (hex < LDO_VOLT_MIN_HEX)
104 		hex = LDO_VOLT_MIN_HEX;
105 
106 	return LDO_VOLT_BASE + hex * 102000;
107 }
108 
tps80031_ldo_val(struct udevice * dev,int op,int * uV)109 static int tps80031_ldo_val(struct udevice *dev, int op, int *uV)
110 {
111 	struct dm_regulator_uclass_plat *uc_pdata =
112 					dev_get_uclass_plat(dev);
113 	u32 adr = uc_pdata->volt_reg;
114 	int val, hex, ret;
115 
116 	val = pmic_reg_read(dev->parent, adr);
117 	if (val < 0)
118 		return val;
119 
120 	if (op == PMIC_OP_GET) {
121 		*uV = 0;
122 
123 		ret = tps80031_ldo_hex2volt(val & LDO_VOLT_MASK);
124 		if (ret < 0)
125 			return ret;
126 
127 		*uV = ret;
128 		return 0;
129 	}
130 
131 	hex = tps80031_ldo_volt2hex(*uV);
132 	if (hex < 0)
133 		return hex;
134 
135 	val &= ~LDO_VOLT_MASK;
136 
137 	return pmic_reg_write(dev->parent, adr, val | hex);
138 }
139 
tps80031_ldo_probe(struct udevice * dev)140 static int tps80031_ldo_probe(struct udevice *dev)
141 {
142 	struct dm_regulator_uclass_plat *uc_pdata =
143 					dev_get_uclass_plat(dev);
144 
145 	uc_pdata->type = REGULATOR_TYPE_LDO;
146 
147 	/* check for ldoln and ldousb cases */
148 	if (!strcmp("ldoln", dev->name)) {
149 		uc_pdata->ctrl_reg = tps80031_ldo_reg[CTRL][7];
150 		uc_pdata->volt_reg = tps80031_ldo_reg[VOLT][7];
151 		return 0;
152 	}
153 
154 	if (!strcmp("ldousb", dev->name)) {
155 		uc_pdata->ctrl_reg = tps80031_ldo_reg[CTRL][8];
156 		uc_pdata->volt_reg = tps80031_ldo_reg[VOLT][8];
157 		return 0;
158 	}
159 
160 	if (dev->driver_data > 0) {
161 		u8 idx = dev->driver_data - 1;
162 
163 		uc_pdata->ctrl_reg = tps80031_ldo_reg[CTRL][idx];
164 		uc_pdata->volt_reg = tps80031_ldo_reg[VOLT][idx];
165 	}
166 
167 	return 0;
168 }
169 
ldo_get_value(struct udevice * dev)170 static int ldo_get_value(struct udevice *dev)
171 {
172 	int uV;
173 	int ret;
174 
175 	ret = tps80031_ldo_val(dev, PMIC_OP_GET, &uV);
176 	if (ret)
177 		return ret;
178 
179 	return uV;
180 }
181 
ldo_set_value(struct udevice * dev,int uV)182 static int ldo_set_value(struct udevice *dev, int uV)
183 {
184 	return tps80031_ldo_val(dev, PMIC_OP_SET, &uV);
185 }
186 
187 static const struct dm_regulator_ops tps80031_ldo_ops = {
188 	.get_value  = ldo_get_value,
189 	.set_value  = ldo_set_value,
190 	.get_enable = tps80031_get_enable,
191 	.set_enable = tps80031_set_enable,
192 };
193 
194 U_BOOT_DRIVER(tps80031_ldo) = {
195 	.name = TPS80031_LDO_DRIVER,
196 	.id = UCLASS_REGULATOR,
197 	.ops = &tps80031_ldo_ops,
198 	.probe = tps80031_ldo_probe,
199 };
200 
201 struct tps80031_smps_priv {
202 	int flags;
203 };
204 
205 /* DCDC voltages for the selector of 0x39 to 0x3F */
206 static int tps80031_dcdc_voltages[5] = {
207 	1350000, 1500000, 1800000, 1900000, 2100000
208 };
209 
210 /**
211  * tps80031_smps_volt2hex() - convert voltage in uV into
212  *			      applicable to register hex value
213  *
214  * @base:	base voltage in uV
215  * @uV:		voltage in uV
216  *
217  * Return: voltage in hex on success, -ve on failure
218  */
tps80031_smps_volt2hex(u32 base,int uV)219 static int tps80031_smps_volt2hex(u32 base, int uV)
220 {
221 	int i;
222 
223 	if (uV < base)
224 		return 1;
225 
226 	if (uV > SMPS_VOLT_LINEAR) {
227 		for (i = 0; i < ARRAY_SIZE(tps80031_dcdc_voltages); i++)
228 			if (uV <= tps80031_dcdc_voltages[i])
229 				break;
230 
231 		return SMPS_VOLT_NLINEAR_HEX + i;
232 	}
233 
234 	return DIV_ROUND_UP(uV - base, 12500);
235 }
236 
237 /**
238  * tps80031_smps_hex2volt() - convert register hex value into
239  *			      actual voltage in uV
240  *
241  * @base:	base voltage in uV
242  * @hex:	hex value of register
243  *
244  * Return: voltage in uV on success, -ve on failure
245  */
tps80031_smps_hex2volt(u32 base,int hex)246 static int tps80031_smps_hex2volt(u32 base, int hex)
247 {
248 	if (!hex)
249 		return 0;
250 
251 	/* if reg value exceeds linear scale use table */
252 	if (hex > SMPS_VOLT_LINEAR_HEX)
253 		return tps80031_dcdc_voltages[hex - SMPS_VOLT_LINEAR_HEX];
254 	else
255 		return base + hex * 12500;
256 }
257 
tps80031_smps_val(struct udevice * dev,int op,int * uV)258 static int tps80031_smps_val(struct udevice *dev, int op, int *uV)
259 {
260 	struct dm_regulator_uclass_plat *uc_pdata =
261 					dev_get_uclass_plat(dev);
262 	struct tps80031_smps_priv *priv = dev_get_priv(dev);
263 	u32 adr = uc_pdata->volt_reg;
264 	int base, val, hex, ret;
265 
266 	/* If offset flag was set then base voltage is higher */
267 	if (priv->flags & TPS80031_OFFSET_FLAG)
268 		base = SMPS_VOLT_BASE_OFFSET;
269 	else
270 		base = SMPS_VOLT_BASE;
271 
272 	val = pmic_reg_read(dev->parent, adr);
273 	if (val < 0)
274 		return val;
275 
276 	if (op == PMIC_OP_GET) {
277 		*uV = 0;
278 
279 		ret = tps80031_smps_hex2volt(base, val & SMPS_VOLT_MASK);
280 		if (ret < 0)
281 			return ret;
282 
283 		*uV = ret;
284 		return 0;
285 	}
286 
287 	hex = tps80031_smps_volt2hex(base, *uV);
288 	if (hex < 0)
289 		return hex;
290 
291 	val &= ~SMPS_VOLT_MASK;
292 
293 	return pmic_reg_write(dev->parent, adr, val | hex);
294 }
295 
tps80031_smps_probe(struct udevice * dev)296 static int tps80031_smps_probe(struct udevice *dev)
297 {
298 	struct dm_regulator_uclass_plat *uc_pdata =
299 					dev_get_uclass_plat(dev);
300 	struct tps80031_smps_priv *priv = dev_get_priv(dev);
301 	int idx = dev->driver_data - 1;
302 	int val;
303 
304 	uc_pdata->type = REGULATOR_TYPE_BUCK;
305 
306 	uc_pdata->ctrl_reg = tps80031_smps_reg[CTRL][idx];
307 	uc_pdata->volt_reg = tps80031_smps_reg[VOLT][idx];
308 
309 	/* Determine if smps regulator uses higher voltage */
310 	val = pmic_reg_read(dev->parent, TPS80031_SMPS_OFFSET);
311 	if (val & tps80031_smps_reg[OFFSET][idx])
312 		priv->flags |= TPS80031_OFFSET_FLAG;
313 
314 	return 0;
315 }
316 
smps_get_value(struct udevice * dev)317 static int smps_get_value(struct udevice *dev)
318 {
319 	int uV;
320 	int ret;
321 
322 	ret = tps80031_smps_val(dev, PMIC_OP_GET, &uV);
323 	if (ret)
324 		return ret;
325 
326 	return uV;
327 }
328 
smps_set_value(struct udevice * dev,int uV)329 static int smps_set_value(struct udevice *dev, int uV)
330 {
331 	return tps80031_smps_val(dev, PMIC_OP_SET, &uV);
332 }
333 
334 static const struct dm_regulator_ops tps80031_smps_ops = {
335 	.get_value  = smps_get_value,
336 	.set_value  = smps_set_value,
337 	.get_enable = tps80031_get_enable,
338 	.set_enable = tps80031_set_enable,
339 };
340 
341 U_BOOT_DRIVER(tps80031_smps) = {
342 	.name = TPS80031_SMPS_DRIVER,
343 	.id = UCLASS_REGULATOR,
344 	.ops = &tps80031_smps_ops,
345 	.probe = tps80031_smps_probe,
346 	.priv_auto = sizeof(struct tps80031_smps_priv),
347 };
348