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/lp873x.h>
18 
19 static const char lp873x_buck_ctrl[LP873X_BUCK_NUM] = {0x2, 0x4};
20 static const char lp873x_buck_volt[LP873X_BUCK_NUM] = {0x6, 0x7};
21 static const char lp873x_ldo_ctrl[LP873X_LDO_NUM] = {0x8, 0x9};
22 static const char lp873x_ldo_volt[LP873X_LDO_NUM] = {0xA, 0xB};
23 
24 static int lp873x_buck_enable(struct udevice *dev, int op, bool *enable)
25 {
26 	int ret;
27 	unsigned int adr;
28 	struct dm_regulator_uclass_platdata *uc_pdata;
29 
30 	uc_pdata = dev_get_uclass_platdata(dev);
31 	adr = uc_pdata->ctrl_reg;
32 
33 	ret = pmic_reg_read(dev->parent, adr);
34 	if (ret < 0)
35 		return ret;
36 
37 	if (op == PMIC_OP_GET) {
38 		ret &= LP873X_BUCK_MODE_MASK;
39 
40 		if (ret)
41 			*enable = true;
42 		else
43 			*enable = false;
44 
45 		return 0;
46 	} else if (op == PMIC_OP_SET) {
47 		if (*enable)
48 			ret |= LP873X_BUCK_MODE_MASK;
49 		else
50 			ret &= ~(LP873X_BUCK_MODE_MASK);
51 		ret = pmic_reg_write(dev->parent, adr, ret);
52 		if (ret)
53 			return ret;
54 	}
55 
56 	return 0;
57 }
58 
59 static int lp873x_buck_volt2hex(int uV)
60 {
61 	if (uV > LP873X_BUCK_VOLT_MAX)
62 		return -EINVAL;
63 	else if (uV > 1400000)
64 		return (uV - 1420000) / 20000 + 0x9E;
65 	else if (uV > 730000)
66 		return (uV - 735000) / 5000 + 0x18;
67 	else if (uV >= 700000)
68 		return (uV - 700000) / 10000 + 0x1;
69 	else
70 		return -EINVAL;
71 }
72 
73 static int lp873x_buck_hex2volt(int hex)
74 {
75 	if (hex > LP873X_BUCK_VOLT_MAX_HEX)
76 		return -EINVAL;
77 	else if (hex > 0x9D)
78 		return 1400000 + (hex - 0x9D) * 20000;
79 	else if (hex > 0x17)
80 		return 730000 + (hex - 0x17) * 5000;
81 	else if (hex >= 0x14)
82 		return 700000 + (hex - 0x14) * 10000;
83 	else
84 		return -EINVAL;
85 }
86 
87 static int lp873x_buck_val(struct udevice *dev, int op, int *uV)
88 {
89 	unsigned int hex, adr;
90 	int ret;
91 	struct dm_regulator_uclass_platdata *uc_pdata;
92 
93 	uc_pdata = dev_get_uclass_platdata(dev);
94 
95 	if (op == PMIC_OP_GET)
96 		*uV = 0;
97 
98 	adr = uc_pdata->volt_reg;
99 
100 	ret = pmic_reg_read(dev->parent, adr);
101 	if (ret < 0)
102 		return ret;
103 
104 	if (op == PMIC_OP_GET) {
105 		ret &= LP873X_BUCK_VOLT_MASK;
106 		ret = lp873x_buck_hex2volt(ret);
107 		if (ret < 0)
108 			return ret;
109 		*uV = ret;
110 
111 		return 0;
112 	}
113 
114 	hex = lp873x_buck_volt2hex(*uV);
115 	if (hex < 0)
116 		return hex;
117 
118 	ret &= 0x0;
119 	ret |= hex;
120 
121 	ret = pmic_reg_write(dev->parent, adr, ret);
122 
123 	return ret;
124 }
125 
126 static int lp873x_ldo_enable(struct udevice *dev, int op, bool *enable)
127 {
128 	int ret;
129 	unsigned int adr;
130 	struct dm_regulator_uclass_platdata *uc_pdata;
131 
132 	uc_pdata = dev_get_uclass_platdata(dev);
133 	adr = uc_pdata->ctrl_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 		ret &= LP873X_LDO_MODE_MASK;
141 
142 		if (ret)
143 			*enable = true;
144 		else
145 			*enable = false;
146 
147 		return 0;
148 	} else if (op == PMIC_OP_SET) {
149 		if (*enable)
150 			ret |= LP873X_LDO_MODE_MASK;
151 		else
152 			ret &= ~(LP873X_LDO_MODE_MASK);
153 
154 		ret = pmic_reg_write(dev->parent, adr, ret);
155 		if (ret)
156 			return ret;
157 	}
158 
159 	return 0;
160 }
161 
162 static int lp873x_ldo_volt2hex(int uV)
163 {
164 	if (uV > LP873X_LDO_VOLT_MAX)
165 		return -EINVAL;
166 
167 	return (uV - 800000) / 100000;
168 }
169 
170 static int lp873x_ldo_hex2volt(int hex)
171 {
172 	if (hex > LP873X_LDO_VOLT_MAX_HEX)
173 		return -EINVAL;
174 
175 	if (!hex)
176 		return 0;
177 
178 	return (hex * 100000) + 800000;
179 }
180 
181 static int lp873x_ldo_val(struct udevice *dev, int op, int *uV)
182 {
183 	unsigned int hex, adr;
184 	int ret;
185 
186 	struct dm_regulator_uclass_platdata *uc_pdata;
187 
188 	if (op == PMIC_OP_GET)
189 		*uV = 0;
190 
191 	uc_pdata = dev_get_uclass_platdata(dev);
192 
193 	adr = uc_pdata->volt_reg;
194 
195 	ret = pmic_reg_read(dev->parent, adr);
196 	if (ret < 0)
197 		return ret;
198 
199 	if (op == PMIC_OP_GET) {
200 		ret &= LP873X_LDO_VOLT_MASK;
201 		ret = lp873x_ldo_hex2volt(ret);
202 		if (ret < 0)
203 			return ret;
204 		*uV = ret;
205 		return 0;
206 	}
207 
208 	hex = lp873x_ldo_volt2hex(*uV);
209 	if (hex < 0)
210 		return hex;
211 
212 	ret &= ~LP873X_LDO_VOLT_MASK;
213 	ret |= hex;
214 	if (*uV > 1650000)
215 		ret |= 0x80;
216 	ret = pmic_reg_write(dev->parent, adr, ret);
217 
218 	return ret;
219 }
220 
221 static int lp873x_ldo_probe(struct udevice *dev)
222 {
223 	struct dm_regulator_uclass_platdata *uc_pdata;
224 
225 	uc_pdata = dev_get_uclass_platdata(dev);
226 	uc_pdata->type = REGULATOR_TYPE_LDO;
227 
228 	int idx = dev->driver_data;
229 	if (idx >= LP873X_LDO_NUM) {
230 		printf("Wrong ID for regulator\n");
231 		return -1;
232 	}
233 
234 	uc_pdata->ctrl_reg = lp873x_ldo_ctrl[idx];
235 	uc_pdata->volt_reg = lp873x_ldo_volt[idx];
236 
237 	return 0;
238 }
239 
240 static int ldo_get_value(struct udevice *dev)
241 {
242 	int uV;
243 	int ret;
244 
245 	ret = lp873x_ldo_val(dev, PMIC_OP_GET, &uV);
246 	if (ret)
247 		return ret;
248 
249 	return uV;
250 }
251 
252 static int ldo_set_value(struct udevice *dev, int uV)
253 {
254 	return lp873x_ldo_val(dev, PMIC_OP_SET, &uV);
255 }
256 
257 static int ldo_get_enable(struct udevice *dev)
258 {
259 	bool enable = false;
260 	int ret;
261 
262 	ret = lp873x_ldo_enable(dev, PMIC_OP_GET, &enable);
263 	if (ret)
264 		return ret;
265 
266 	return enable;
267 }
268 
269 static int ldo_set_enable(struct udevice *dev, bool enable)
270 {
271 	return lp873x_ldo_enable(dev, PMIC_OP_SET, &enable);
272 }
273 
274 static int lp873x_buck_probe(struct udevice *dev)
275 {
276 	struct dm_regulator_uclass_platdata *uc_pdata;
277 	int idx;
278 
279 	uc_pdata = dev_get_uclass_platdata(dev);
280 	uc_pdata->type = REGULATOR_TYPE_BUCK;
281 
282 	idx = dev->driver_data;
283 	if (idx >= LP873X_BUCK_NUM) {
284 		printf("Wrong ID for regulator\n");
285 		return -1;
286 	}
287 
288 	uc_pdata->ctrl_reg = lp873x_buck_ctrl[idx];
289 	uc_pdata->volt_reg = lp873x_buck_volt[idx];
290 
291 	return 0;
292 }
293 
294 static int buck_get_value(struct udevice *dev)
295 {
296 	int uV;
297 	int ret;
298 
299 	ret = lp873x_buck_val(dev, PMIC_OP_GET, &uV);
300 	if (ret)
301 		return ret;
302 
303 	return uV;
304 }
305 
306 static int buck_set_value(struct udevice *dev, int uV)
307 {
308 	return lp873x_buck_val(dev, PMIC_OP_SET, &uV);
309 }
310 
311 static int buck_get_enable(struct udevice *dev)
312 {
313 	bool enable = false;
314 	int ret;
315 
316 
317 	ret = lp873x_buck_enable(dev, PMIC_OP_GET, &enable);
318 	if (ret)
319 		return ret;
320 
321 	return enable;
322 }
323 
324 static int buck_set_enable(struct udevice *dev, bool enable)
325 {
326 	return lp873x_buck_enable(dev, PMIC_OP_SET, &enable);
327 }
328 
329 static const struct dm_regulator_ops lp873x_ldo_ops = {
330 	.get_value  = ldo_get_value,
331 	.set_value  = ldo_set_value,
332 	.get_enable = ldo_get_enable,
333 	.set_enable = ldo_set_enable,
334 };
335 
336 U_BOOT_DRIVER(lp873x_ldo) = {
337 	.name = LP873X_LDO_DRIVER,
338 	.id = UCLASS_REGULATOR,
339 	.ops = &lp873x_ldo_ops,
340 	.probe = lp873x_ldo_probe,
341 };
342 
343 static const struct dm_regulator_ops lp873x_buck_ops = {
344 	.get_value  = buck_get_value,
345 	.set_value  = buck_set_value,
346 	.get_enable = buck_get_enable,
347 	.set_enable = buck_set_enable,
348 };
349 
350 U_BOOT_DRIVER(lp873x_buck) = {
351 	.name = LP873X_BUCK_DRIVER,
352 	.id = UCLASS_REGULATOR,
353 	.ops = &lp873x_buck_ops,
354 	.probe = lp873x_buck_probe,
355 };
356