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