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