1 /*
2  * (C) Copyright 2016
3  * Texas Instruments Incorporated, <www.ti.com>
4  *
5  * Keerthy <j-keerthy@ti.com>
6  *
7  * SPDX-License-Identifier:	GPL-2.0+
8  */
9 
10 #include <common.h>
11 #include <fdtdec.h>
12 #include <errno.h>
13 #include <dm.h>
14 #include <i2c.h>
15 #include <power/pmic.h>
16 #include <power/regulator.h>
17 #include <power/palmas.h>
18 
19 DECLARE_GLOBAL_DATA_PTR;
20 
21 #define	REGULATOR_ON		0x1
22 #define	REGULATOR_OFF		0x0
23 
24 #define	SMPS_MODE_MASK		0x3
25 #define	SMPS_MODE_SHIFT		0x0
26 #define	LDO_MODE_MASK		0x1
27 #define	LDO_MODE_SHIFT		0x0
28 
29 static const char palmas_smps_ctrl[][PALMAS_SMPS_NUM] = {
30 	{0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c},
31 	{0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38},
32 	{0x20, 0x24, 0x2c, 0x30, 0x38},
33 };
34 
35 static const char palmas_smps_volt[][PALMAS_SMPS_NUM] = {
36 	{0x23, 0x27, 0x2b, 0x2f, 0x33, 0x37, 0x3b, 0x3c},
37 	{0x23, 0x27, 0x2b, 0x2f, 0x33, 0x37, 0x3b},
38 	{0x23, 0x27, 0x2f, 0x33, 0x3B}
39 };
40 
41 static const char palmas_ldo_ctrl[][PALMAS_LDO_NUM] = {
42 	{0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x62, 0x64},
43 	{0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x62, 0x64},
44 	{0x50, 0x52, 0x54, 0x5e, 0x62}
45 };
46 
47 static const char palmas_ldo_volt[][PALMAS_LDO_NUM] = {
48 	{0x51, 0x53, 0x55, 0x57, 0x59, 0x5b, 0x5d, 0x5f, 0x61, 0x63, 0x65},
49 	{0x51, 0x53, 0x55, 0x57, 0x59, 0x5b, 0x5d, 0x5f, 0x61, 0x63, 0x65},
50 	{0x51, 0x53, 0x55, 0x5f, 0x63}
51 };
52 
53 static int palmas_smps_enable(struct udevice *dev, int op, bool *enable)
54 {
55 	int ret;
56 	unsigned int adr;
57 	struct dm_regulator_uclass_platdata *uc_pdata;
58 
59 	uc_pdata = dev_get_uclass_platdata(dev);
60 	adr = uc_pdata->ctrl_reg;
61 
62 	ret = pmic_reg_read(dev->parent, adr);
63 		if (ret < 0)
64 			return ret;
65 
66 	if (op == PMIC_OP_GET) {
67 		ret &= PALMAS_SMPS_STATUS_MASK;
68 
69 		if (ret)
70 			*enable = true;
71 		else
72 			*enable = false;
73 
74 		return 0;
75 	} else if (op == PMIC_OP_SET) {
76 		if (*enable)
77 			ret |= PALMAS_SMPS_MODE_MASK;
78 		else
79 			ret &= ~(PALMAS_SMPS_MODE_MASK);
80 
81 		ret = pmic_reg_write(dev->parent, adr, ret);
82 		if (ret)
83 			return ret;
84 	}
85 
86 	return 0;
87 }
88 
89 static int palmas_smps_volt2hex(int uV)
90 {
91 	if (uV > PALMAS_LDO_VOLT_MAX)
92 		return -EINVAL;
93 
94 	if (uV > 1650000)
95 		return (uV - 1000000) / 20000 + 0x6;
96 
97 	if (uV == 500000)
98 		return 0x6;
99 	else
100 		return 0x6 + ((uV - 500000) / 10000);
101 }
102 
103 static int palmas_smps_hex2volt(int hex, bool range)
104 {
105 	unsigned int uV = 0;
106 
107 	if (hex > PALMAS_SMPS_VOLT_MAX_HEX)
108 		return -EINVAL;
109 
110 	if (hex < 0x7)
111 		uV = 500000;
112 	else
113 		uV = 500000 + (hex - 0x6) * 10000;
114 
115 	if (range)
116 		uV *= 2;
117 
118 	return uV;
119 }
120 
121 static int palmas_smps_val(struct udevice *dev, int op, int *uV)
122 {
123 	unsigned int hex, adr;
124 	int ret;
125 	bool range;
126 	struct dm_regulator_uclass_platdata *uc_pdata;
127 
128 	uc_pdata = dev_get_uclass_platdata(dev);
129 
130 	if (op == PMIC_OP_GET)
131 		*uV = 0;
132 
133 	adr = uc_pdata->volt_reg;
134 
135 	ret = pmic_reg_read(dev->parent, adr);
136 	if (ret < 0)
137 		return ret;
138 
139 	if (op == PMIC_OP_GET) {
140 		if (ret & PALMAS_SMPS_RANGE_MASK)
141 			range =  true;
142 		else
143 			range = false;
144 
145 		ret &= PALMAS_SMPS_VOLT_MASK;
146 		ret = palmas_smps_hex2volt(ret, range);
147 		if (ret < 0)
148 			return ret;
149 		*uV = ret;
150 
151 		return 0;
152 	}
153 
154 	hex = palmas_smps_volt2hex(*uV);
155 	if (hex < 0)
156 		return hex;
157 
158 	ret &= ~PALMAS_SMPS_VOLT_MASK;
159 	ret |= hex;
160 	if (*uV > 1650000)
161 		ret |= PALMAS_SMPS_RANGE_MASK;
162 
163 	return pmic_reg_write(dev->parent, adr, ret);
164 }
165 
166 static int palmas_ldo_enable(struct udevice *dev, int op, bool *enable)
167 {
168 	int ret;
169 	unsigned int adr;
170 	struct dm_regulator_uclass_platdata *uc_pdata;
171 
172 	uc_pdata = dev_get_uclass_platdata(dev);
173 	adr = uc_pdata->ctrl_reg;
174 
175 	ret = pmic_reg_read(dev->parent, adr);
176 		if (ret < 0)
177 			return ret;
178 
179 	if (op == PMIC_OP_GET) {
180 		ret &= PALMAS_LDO_STATUS_MASK;
181 
182 		if (ret)
183 			*enable = true;
184 		else
185 			*enable = false;
186 
187 		return 0;
188 	} else if (op == PMIC_OP_SET) {
189 		if (*enable)
190 			ret |= PALMAS_LDO_MODE_MASK;
191 		else
192 			ret &= ~(PALMAS_LDO_MODE_MASK);
193 
194 		ret = pmic_reg_write(dev->parent, adr, ret);
195 		if (ret)
196 			return ret;
197 	}
198 
199 	return 0;
200 }
201 
202 static int palmas_ldo_volt2hex(int uV)
203 {
204 	if (uV > PALMAS_LDO_VOLT_MAX)
205 		return -EINVAL;
206 
207 	return (uV - 850000) / 50000;
208 }
209 
210 static int palmas_ldo_hex2volt(int hex)
211 {
212 	if (hex > PALMAS_LDO_VOLT_MAX_HEX)
213 		return -EINVAL;
214 
215 	if (!hex)
216 		return 0;
217 
218 	return (hex * 50000) + 850000;
219 }
220 
221 static int palmas_ldo_val(struct udevice *dev, int op, int *uV)
222 {
223 	unsigned int hex, adr;
224 	int ret;
225 
226 	struct dm_regulator_uclass_platdata *uc_pdata;
227 
228 	if (op == PMIC_OP_GET)
229 		*uV = 0;
230 
231 	uc_pdata = dev_get_uclass_platdata(dev);
232 
233 	adr = uc_pdata->volt_reg;
234 
235 	ret = pmic_reg_read(dev->parent, adr);
236 	if (ret < 0)
237 		return ret;
238 
239 	if (op == PMIC_OP_GET) {
240 		ret &= PALMAS_LDO_VOLT_MASK;
241 		ret = palmas_ldo_hex2volt(ret);
242 		if (ret < 0)
243 			return ret;
244 		*uV = ret;
245 		return 0;
246 	}
247 
248 	hex = palmas_ldo_volt2hex(*uV);
249 	if (hex < 0)
250 		return hex;
251 
252 	ret &= ~PALMAS_LDO_VOLT_MASK;
253 	ret |= hex;
254 	if (*uV > 1650000)
255 		ret |= 0x80;
256 
257 	return pmic_reg_write(dev->parent, adr, ret);
258 }
259 
260 static int palmas_ldo_probe(struct udevice *dev)
261 {
262 	struct dm_regulator_uclass_platdata *uc_pdata;
263 	struct udevice *parent;
264 
265 	uc_pdata = dev_get_uclass_platdata(dev);
266 
267 	parent = dev_get_parent(dev);
268 	int type = dev_get_driver_data(parent);
269 
270 	uc_pdata->type = REGULATOR_TYPE_LDO;
271 
272 	if (dev->driver_data) {
273 		u8 idx = dev->driver_data - 1;
274 		uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][idx];
275 		uc_pdata->volt_reg = palmas_ldo_volt[type][idx];
276 	} else {
277 		/* check for ldoln and ldousb cases */
278 		if (!strcmp("ldoln", dev->name)) {
279 			uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][9];
280 			uc_pdata->volt_reg = palmas_ldo_volt[type][9];
281 		} else if (!strcmp("ldousb", dev->name)) {
282 			uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][10];
283 			uc_pdata->volt_reg = palmas_ldo_volt[type][10];
284 		}
285 	}
286 
287 	return 0;
288 }
289 
290 static int ldo_get_value(struct udevice *dev)
291 {
292 	int uV;
293 	int ret;
294 
295 	ret = palmas_ldo_val(dev, PMIC_OP_GET, &uV);
296 	if (ret)
297 		return ret;
298 
299 	return uV;
300 }
301 
302 static int ldo_set_value(struct udevice *dev, int uV)
303 {
304 	return palmas_ldo_val(dev, PMIC_OP_SET, &uV);
305 }
306 
307 static bool ldo_get_enable(struct udevice *dev)
308 {
309 	bool enable = false;
310 	int ret;
311 
312 	ret = palmas_ldo_enable(dev, PMIC_OP_GET, &enable);
313 	if (ret)
314 		return ret;
315 
316 	return enable;
317 }
318 
319 static int ldo_set_enable(struct udevice *dev, bool enable)
320 {
321 	return palmas_ldo_enable(dev, PMIC_OP_SET, &enable);
322 }
323 
324 static int palmas_smps_probe(struct udevice *dev)
325 {
326 	struct dm_regulator_uclass_platdata *uc_pdata;
327 	struct udevice *parent;
328 	int idx;
329 
330 	uc_pdata = dev_get_uclass_platdata(dev);
331 
332 	parent = dev_get_parent(dev);
333 	int type = dev_get_driver_data(parent);
334 
335 	uc_pdata->type = REGULATOR_TYPE_BUCK;
336 
337 	switch (type) {
338 	case PALMAS:
339 	case TPS659038:
340 		switch (dev->driver_data) {
341 		case 123:
342 		case 12:
343 			uc_pdata->ctrl_reg = palmas_smps_ctrl[type][0];
344 			uc_pdata->volt_reg = palmas_smps_volt[type][0];
345 			break;
346 		case 3:
347 			uc_pdata->ctrl_reg = palmas_smps_ctrl[type][1];
348 			uc_pdata->volt_reg = palmas_smps_volt[type][1];
349 			break;
350 		case 45:
351 			uc_pdata->ctrl_reg = palmas_smps_ctrl[type][2];
352 			uc_pdata->volt_reg = palmas_smps_volt[type][2];
353 			break;
354 		case 6:
355 		case 7:
356 		case 8:
357 		case 9:
358 		case 10:
359 			idx = dev->driver_data - 4;
360 			uc_pdata->ctrl_reg = palmas_smps_ctrl[type][idx];
361 			uc_pdata->volt_reg = palmas_smps_volt[type][idx];
362 			break;
363 
364 		default:
365 			printf("Wrong ID for regulator\n");
366 		}
367 		break;
368 
369 	case TPS65917:
370 		switch (dev->driver_data) {
371 		case 1:
372 		case 2:
373 		case 3:
374 		case 4:
375 		case 5:
376 			idx = dev->driver_data - 1;
377 			uc_pdata->ctrl_reg = palmas_smps_ctrl[type][idx];
378 			uc_pdata->volt_reg = palmas_smps_volt[type][idx];
379 			break;
380 
381 		default:
382 			printf("Wrong ID for regulator\n");
383 		}
384 		break;
385 
386 	default:
387 			printf("Invalid PMIC ID\n");
388 	}
389 
390 	return 0;
391 }
392 
393 static int smps_get_value(struct udevice *dev)
394 {
395 	int uV;
396 	int ret;
397 
398 	ret = palmas_smps_val(dev, PMIC_OP_GET, &uV);
399 	if (ret)
400 		return ret;
401 
402 	return uV;
403 }
404 
405 static int smps_set_value(struct udevice *dev, int uV)
406 {
407 	return palmas_smps_val(dev, PMIC_OP_SET, &uV);
408 }
409 
410 static bool smps_get_enable(struct udevice *dev)
411 {
412 	bool enable = false;
413 	int ret;
414 
415 	ret = palmas_smps_enable(dev, PMIC_OP_GET, &enable);
416 	if (ret)
417 		return ret;
418 
419 	return enable;
420 }
421 
422 static int smps_set_enable(struct udevice *dev, bool enable)
423 {
424 	return palmas_smps_enable(dev, PMIC_OP_SET, &enable);
425 }
426 
427 static const struct dm_regulator_ops palmas_ldo_ops = {
428 	.get_value  = ldo_get_value,
429 	.set_value  = ldo_set_value,
430 	.get_enable = ldo_get_enable,
431 	.set_enable = ldo_set_enable,
432 };
433 
434 U_BOOT_DRIVER(palmas_ldo) = {
435 	.name = PALMAS_LDO_DRIVER,
436 	.id = UCLASS_REGULATOR,
437 	.ops = &palmas_ldo_ops,
438 	.probe = palmas_ldo_probe,
439 };
440 
441 static const struct dm_regulator_ops palmas_smps_ops = {
442 	.get_value  = smps_get_value,
443 	.set_value  = smps_set_value,
444 	.get_enable = smps_get_enable,
445 	.set_enable = smps_set_enable,
446 };
447 
448 U_BOOT_DRIVER(palmas_smps) = {
449 	.name = PALMAS_SMPS_DRIVER,
450 	.id = UCLASS_REGULATOR,
451 	.ops = &palmas_smps_ops,
452 	.probe = palmas_smps_probe,
453 };
454