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