blob: dcb19ff25cd6f7a5d25bed5b8cb6c57a060a490c [file] [log] [blame]
Keerthy947d9282016-09-30 09:34:03 +05301/*
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
19DECLARE_GLOBAL_DATA_PTR;
20
21static const char lp873x_buck_ctrl[LP873X_BUCK_NUM] = {0x2, 0x4};
22static const char lp873x_buck_volt[LP873X_BUCK_NUM] = {0x6, 0x7};
23static const char lp873x_ldo_ctrl[LP873X_LDO_NUM] = {0x8, 0x9};
24static const char lp873x_ldo_volt[LP873X_LDO_NUM] = {0xA, 0xB};
25
26static 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
61static 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
75static 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
89static 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
128static 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
164static 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
172static 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
183static 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
223static 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
242static 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
254static int ldo_set_value(struct udevice *dev, int uV)
255{
256 return lp873x_ldo_val(dev, PMIC_OP_SET, &uV);
257}
258
259static 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
271static int ldo_set_enable(struct udevice *dev, bool enable)
272{
273 return lp873x_ldo_enable(dev, PMIC_OP_SET, &enable);
274}
275
276static 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
296static 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
308static int buck_set_value(struct udevice *dev, int uV)
309{
310 return lp873x_buck_val(dev, PMIC_OP_SET, &uV);
311}
312
313static 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
326static int buck_set_enable(struct udevice *dev, bool enable)
327{
328 return lp873x_buck_enable(dev, PMIC_OP_SET, &enable);
329}
330
331static 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
338U_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
345static 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
352U_BOOT_DRIVER(lp873x_buck) = {
353 .name = LP873X_BUCK_DRIVER,
354 .id = UCLASS_REGULATOR,
355 .ops = &lp873x_buck_ops,
356 .probe = lp873x_buck_probe,
357};