blob: a00ef58129cf188975d47e073aea8654e03d3d3e [file] [log] [blame]
Keerthy4a030002019-10-24 15:00:51 +05301// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2019
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/tps65941.h>
17
18static const char tps65941_buck_ctrl[TPS65941_BUCK_NUM] = {0x4, 0x6, 0x8, 0xA,
19 0xC};
20static const char tps65941_buck_vout[TPS65941_BUCK_NUM] = {0xE, 0x10, 0x12,
21 0x14, 0x16};
22static const char tps65941_ldo_ctrl[TPS65941_BUCK_NUM] = {0x1D, 0x1E, 0x1F,
23 0x20};
24static const char tps65941_ldo_vout[TPS65941_BUCK_NUM] = {0x23, 0x24, 0x25,
25 0x26};
26
27static int tps65941_buck_enable(struct udevice *dev, int op, bool *enable)
28{
29 int ret;
30 unsigned int adr;
31 struct dm_regulator_uclass_platdata *uc_pdata;
32
33 uc_pdata = dev_get_uclass_platdata(dev);
34 adr = uc_pdata->ctrl_reg;
35
36 ret = pmic_reg_read(dev->parent, adr);
37 if (ret < 0)
38 return ret;
39
40 if (op == PMIC_OP_GET) {
41 ret &= TPS65941_BUCK_MODE_MASK;
42
43 if (ret)
44 *enable = true;
45 else
46 *enable = false;
47
48 return 0;
49 } else if (op == PMIC_OP_SET) {
50 if (*enable)
51 ret |= TPS65941_BUCK_MODE_MASK;
52 else
53 ret &= ~TPS65941_BUCK_MODE_MASK;
54 ret = pmic_reg_write(dev->parent, adr, ret);
55 if (ret)
56 return ret;
57 }
58
59 return 0;
60}
61
62static int tps65941_buck_volt2val(int uV)
63{
64 if (uV > TPS65941_BUCK_VOLT_MAX)
65 return -EINVAL;
66 else if (uV > 1650000)
67 return (uV - 1660000) / 20000 + 0xAB;
68 else if (uV > 1110000)
69 return (uV - 1110000) / 10000 + 0x73;
70 else if (uV > 600000)
71 return (uV - 600000) / 5000 + 0x0F;
72 else if (uV >= 300000)
73 return (uV - 300000) / 20000 + 0x00;
74 else
75 return -EINVAL;
76}
77
78static int tps65941_buck_val2volt(int val)
79{
80 if (val > TPS65941_BUCK_VOLT_MAX_HEX)
81 return -EINVAL;
82 else if (val > 0xAB)
83 return 1660000 + (val - 0xAB) * 20000;
84 else if (val > 0x73)
85 return 1100000 + (val - 0x73) * 10000;
86 else if (val > 0xF)
87 return 600000 + (val - 0xF) * 5000;
88 else if (val >= 0x0)
89 return 300000 + val * 5000;
90 else
91 return -EINVAL;
92}
93
94int tps65941_lookup_slew(int id)
95{
96 switch (id) {
97 case 0:
98 return 33000;
99 case 1:
100 return 20000;
101 case 2:
102 return 10000;
103 case 3:
104 return 5000;
105 case 4:
106 return 2500;
107 case 5:
108 return 1300;
109 case 6:
110 return 630;
111 case 7:
112 return 310;
113 default:
114 return -1;
115 }
116}
117
118static int tps65941_buck_val(struct udevice *dev, int op, int *uV)
119{
120 unsigned int hex, adr;
121 int ret, delta, uwait, slew;
122 struct dm_regulator_uclass_platdata *uc_pdata;
123
124 uc_pdata = dev_get_uclass_platdata(dev);
125
126 if (op == PMIC_OP_GET)
127 *uV = 0;
128
129 adr = uc_pdata->volt_reg;
130
131 ret = pmic_reg_read(dev->parent, adr);
132 if (ret < 0)
133 return ret;
134
135 ret &= TPS65941_BUCK_VOLT_MASK;
136 ret = tps65941_buck_val2volt(ret);
137 if (ret < 0)
138 return ret;
139
140 if (op == PMIC_OP_GET) {
141 *uV = ret;
142 return 0;
143 }
144
145 /*
146 * Compute the delta voltage, find the slew rate and wait
147 * for the appropriate amount of time after voltage switch
148 */
149 if (*uV > ret)
150 delta = *uV - ret;
151 else
152 delta = ret - *uV;
153
154 slew = pmic_reg_read(dev->parent, uc_pdata->ctrl_reg + 1);
155 if (slew < 0)
156 return ret;
157
158 slew &= TP65941_BUCK_CONF_SLEW_MASK;
159 slew = tps65941_lookup_slew(slew);
160 if (slew <= 0)
161 return ret;
162
163 uwait = delta / slew;
164
165 hex = tps65941_buck_volt2val(*uV);
166 if (hex < 0)
167 return hex;
168
169 ret &= 0x0;
170 ret = hex;
171
172 ret = pmic_reg_write(dev->parent, adr, ret);
173
174 udelay(uwait);
175
176 return ret;
177}
178
179static int tps65941_ldo_enable(struct udevice *dev, int op, bool *enable)
180{
181 int ret;
182 unsigned int adr;
183 struct dm_regulator_uclass_platdata *uc_pdata;
184
185 uc_pdata = dev_get_uclass_platdata(dev);
186 adr = uc_pdata->ctrl_reg;
187
188 ret = pmic_reg_read(dev->parent, adr);
189 if (ret < 0)
190 return ret;
191
192 if (op == PMIC_OP_GET) {
193 ret &= TPS65941_LDO_MODE_MASK;
194
195 if (ret)
196 *enable = true;
197 else
198 *enable = false;
199
200 return 0;
201 } else if (op == PMIC_OP_SET) {
202 if (*enable)
203 ret |= TPS65941_LDO_MODE_MASK;
204 else
205 ret &= ~TPS65941_LDO_MODE_MASK;
206 ret = pmic_reg_write(dev->parent, adr, ret);
207 if (ret)
208 return ret;
209 }
210
211 return 0;
212}
213
214static int tps65941_ldo_val2volt(int val)
215{
216 if (val > TPS65941_LDO_VOLT_MAX_HEX || val < TPS65941_LDO_VOLT_MIN_HEX)
217 return -EINVAL;
218 else if (val >= TPS65941_LDO_VOLT_MIN_HEX)
219 return 600000 + (val - TPS65941_LDO_VOLT_MIN_HEX) * 50000;
220 else
221 return -EINVAL;
222}
223
224static int tps65941_ldo_val(struct udevice *dev, int op, int *uV)
225{
226 unsigned int hex, adr;
227 int ret;
228 struct dm_regulator_uclass_platdata *uc_pdata;
229
230 uc_pdata = dev_get_uclass_platdata(dev);
231
232 if (op == PMIC_OP_GET)
233 *uV = 0;
234
235 adr = uc_pdata->volt_reg;
236
237 ret = pmic_reg_read(dev->parent, adr);
238 if (ret < 0)
239 return ret;
240
241 ret &= TPS65941_LDO_VOLT_MASK;
242 ret = tps65941_ldo_val2volt(ret);
243 if (ret < 0)
244 return ret;
245
246 if (op == PMIC_OP_GET) {
247 *uV = ret;
248 return 0;
249 }
250
251 hex = tps65941_buck_volt2val(*uV);
252 if (hex < 0)
253 return hex;
254
255 ret &= 0x0;
256 ret = hex;
257
258 ret = pmic_reg_write(dev->parent, adr, ret);
259
260 return ret;
261}
262
263static int tps65941_ldo_probe(struct udevice *dev)
264{
265 struct dm_regulator_uclass_platdata *uc_pdata;
266 int idx;
267
268 uc_pdata = dev_get_uclass_platdata(dev);
269 uc_pdata->type = REGULATOR_TYPE_LDO;
270
271 idx = dev->driver_data;
272 if (idx == 1 || idx == 2 || idx == 3 || idx == 4) {
273 debug("Single phase regulator\n");
274 } else {
275 printf("Wrong ID for regulator\n");
276 return -EINVAL;
277 }
278
279 uc_pdata->ctrl_reg = tps65941_ldo_ctrl[idx - 1];
280 uc_pdata->volt_reg = tps65941_ldo_vout[idx - 1];
281
282 return 0;
283}
284
285static int tps65941_buck_probe(struct udevice *dev)
286{
287 struct dm_regulator_uclass_platdata *uc_pdata;
288 int idx;
289
290 uc_pdata = dev_get_uclass_platdata(dev);
291 uc_pdata->type = REGULATOR_TYPE_BUCK;
292
293 idx = dev->driver_data;
294 if (idx == 1 || idx == 2 || idx == 3 || idx == 4 || idx == 5) {
295 debug("Single phase regulator\n");
296 } else if (idx == 12) {
297 idx = 1;
298 } else if (idx == 34) {
299 idx = 3;
300 } else if (idx == 1234) {
301 idx = 1;
302 } else {
303 printf("Wrong ID for regulator\n");
304 return -EINVAL;
305 }
306
307 uc_pdata->ctrl_reg = tps65941_buck_ctrl[idx - 1];
308 uc_pdata->volt_reg = tps65941_buck_vout[idx - 1];
309
310 return 0;
311}
312
313static int ldo_get_value(struct udevice *dev)
314{
315 int uV;
316 int ret;
317
318 ret = tps65941_ldo_val(dev, PMIC_OP_GET, &uV);
319 if (ret)
320 return ret;
321
322 return uV;
323}
324
325static int ldo_set_value(struct udevice *dev, int uV)
326{
327 return tps65941_ldo_val(dev, PMIC_OP_SET, &uV);
328}
329
330static int ldo_get_enable(struct udevice *dev)
331{
332 bool enable = false;
333 int ret;
334
335 ret = tps65941_ldo_enable(dev, PMIC_OP_GET, &enable);
336 if (ret)
337 return ret;
338
339 return enable;
340}
341
342static int ldo_set_enable(struct udevice *dev, bool enable)
343{
344 return tps65941_ldo_enable(dev, PMIC_OP_SET, &enable);
345}
346
347static int buck_get_value(struct udevice *dev)
348{
349 int uV;
350 int ret;
351
352 ret = tps65941_buck_val(dev, PMIC_OP_GET, &uV);
353 if (ret)
354 return ret;
355
356 return uV;
357}
358
359static int buck_set_value(struct udevice *dev, int uV)
360{
361 return tps65941_buck_val(dev, PMIC_OP_SET, &uV);
362}
363
364static int buck_get_enable(struct udevice *dev)
365{
366 bool enable = false;
367 int ret;
368
369 ret = tps65941_buck_enable(dev, PMIC_OP_GET, &enable);
370 if (ret)
371 return ret;
372
373 return enable;
374}
375
376static int buck_set_enable(struct udevice *dev, bool enable)
377{
378 return tps65941_buck_enable(dev, PMIC_OP_SET, &enable);
379}
380
381static const struct dm_regulator_ops tps65941_ldo_ops = {
382 .get_value = ldo_get_value,
383 .set_value = ldo_set_value,
384 .get_enable = ldo_get_enable,
385 .set_enable = ldo_set_enable,
386};
387
388U_BOOT_DRIVER(tps65941_ldo) = {
389 .name = TPS65941_LDO_DRIVER,
390 .id = UCLASS_REGULATOR,
391 .ops = &tps65941_ldo_ops,
392 .probe = tps65941_ldo_probe,
393};
394
395static const struct dm_regulator_ops tps65941_buck_ops = {
396 .get_value = buck_get_value,
397 .set_value = buck_set_value,
398 .get_enable = buck_get_enable,
399 .set_enable = buck_set_enable,
400};
401
402U_BOOT_DRIVER(tps65941_buck) = {
403 .name = TPS65941_BUCK_DRIVER,
404 .id = UCLASS_REGULATOR,
405 .ops = &tps65941_buck_ops,
406 .probe = tps65941_buck_probe,
407};