]> git.sur5r.net Git - u-boot/blob - drivers/power/regulator/palmas_regulator.c
Merge branch 'master' of git://git.denx.de/u-boot-sunxi
[u-boot] / drivers / power / regulator / palmas_regulator.c
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/palmas.h>
17
18 #define REGULATOR_ON            0x1
19 #define REGULATOR_OFF           0x0
20
21 #define SMPS_MODE_MASK          0x3
22 #define SMPS_MODE_SHIFT         0x0
23 #define LDO_MODE_MASK           0x1
24 #define LDO_MODE_SHIFT          0x0
25
26 static const char palmas_smps_ctrl[][PALMAS_SMPS_NUM] = {
27         {0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c},
28         {0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38},
29         {0x20, 0x24, 0x2c, 0x30, 0x38},
30 };
31
32 static const char palmas_smps_volt[][PALMAS_SMPS_NUM] = {
33         {0x23, 0x27, 0x2b, 0x2f, 0x33, 0x37, 0x3b, 0x3c},
34         {0x23, 0x27, 0x2b, 0x2f, 0x33, 0x37, 0x3b},
35         {0x23, 0x27, 0x2f, 0x33, 0x3B}
36 };
37
38 static const char palmas_ldo_ctrl[][PALMAS_LDO_NUM] = {
39         {0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x62, 0x64},
40         {0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x62, 0x64},
41         {0x50, 0x52, 0x54, 0x5e, 0x62}
42 };
43
44 static const char palmas_ldo_volt[][PALMAS_LDO_NUM] = {
45         {0x51, 0x53, 0x55, 0x57, 0x59, 0x5b, 0x5d, 0x5f, 0x61, 0x63, 0x65},
46         {0x51, 0x53, 0x55, 0x57, 0x59, 0x5b, 0x5d, 0x5f, 0x61, 0x63, 0x65},
47         {0x51, 0x53, 0x55, 0x5f, 0x63}
48 };
49
50 static int palmas_smps_enable(struct udevice *dev, int op, bool *enable)
51 {
52         int ret;
53         unsigned int adr;
54         struct dm_regulator_uclass_platdata *uc_pdata;
55
56         uc_pdata = dev_get_uclass_platdata(dev);
57         adr = uc_pdata->ctrl_reg;
58
59         ret = pmic_reg_read(dev->parent, adr);
60                 if (ret < 0)
61                         return ret;
62
63         if (op == PMIC_OP_GET) {
64                 ret &= PALMAS_SMPS_STATUS_MASK;
65
66                 if (ret)
67                         *enable = true;
68                 else
69                         *enable = false;
70
71                 return 0;
72         } else if (op == PMIC_OP_SET) {
73                 if (*enable)
74                         ret |= PALMAS_SMPS_MODE_MASK;
75                 else
76                         ret &= ~(PALMAS_SMPS_MODE_MASK);
77
78                 ret = pmic_reg_write(dev->parent, adr, ret);
79                 if (ret)
80                         return ret;
81         }
82
83         return 0;
84 }
85
86 static int palmas_smps_volt2hex(int uV)
87 {
88         if (uV > PALMAS_LDO_VOLT_MAX)
89                 return -EINVAL;
90
91         if (uV > 1650000)
92                 return (uV - 1000000) / 20000 + 0x6;
93
94         if (uV == 500000)
95                 return 0x6;
96         else
97                 return 0x6 + ((uV - 500000) / 10000);
98 }
99
100 static int palmas_smps_hex2volt(int hex, bool range)
101 {
102         unsigned int uV = 0;
103
104         if (hex > PALMAS_SMPS_VOLT_MAX_HEX)
105                 return -EINVAL;
106
107         if (hex < 0x7)
108                 uV = 500000;
109         else
110                 uV = 500000 + (hex - 0x6) * 10000;
111
112         if (range)
113                 uV *= 2;
114
115         return uV;
116 }
117
118 static int palmas_smps_val(struct udevice *dev, int op, int *uV)
119 {
120         unsigned int hex, adr;
121         int ret;
122         bool range;
123         struct dm_regulator_uclass_platdata *uc_pdata;
124
125         uc_pdata = dev_get_uclass_platdata(dev);
126
127         if (op == PMIC_OP_GET)
128                 *uV = 0;
129
130         adr = uc_pdata->volt_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                 if (ret & PALMAS_SMPS_RANGE_MASK)
138                         range =  true;
139                 else
140                         range = false;
141
142                 ret &= PALMAS_SMPS_VOLT_MASK;
143                 ret = palmas_smps_hex2volt(ret, range);
144                 if (ret < 0)
145                         return ret;
146                 *uV = ret;
147
148                 return 0;
149         }
150
151         hex = palmas_smps_volt2hex(*uV);
152         if (hex < 0)
153                 return hex;
154
155         ret &= ~PALMAS_SMPS_VOLT_MASK;
156         ret |= hex;
157         if (*uV > 1650000)
158                 ret |= PALMAS_SMPS_RANGE_MASK;
159
160         return pmic_reg_write(dev->parent, adr, ret);
161 }
162
163 static int palmas_ldo_bypass_enable(struct udevice *dev, bool enabled)
164 {
165         int type = dev_get_driver_data(dev_get_parent(dev));
166         struct dm_regulator_uclass_platdata *p;
167         unsigned int adr;
168         int reg;
169
170         if (type == TPS65917) {
171                 /* bypass available only on LDO1 and LDO2 */
172                 if (dev->driver_data > 2)
173                         return -ENOTSUPP;
174         } else if (type == TPS659038) {
175                 /* bypass available only on LDO9 */
176                 if (dev->driver_data != 9)
177                         return -ENOTSUPP;
178         }
179
180         p = dev_get_uclass_platdata(dev);
181         adr = p->ctrl_reg;
182
183         reg = pmic_reg_read(dev->parent, adr);
184         if (reg < 0)
185                 return reg;
186
187         if (enabled)
188                 reg |= PALMAS_LDO_BYPASS_EN;
189         else
190                 reg &= ~PALMAS_LDO_BYPASS_EN;
191
192         return pmic_reg_write(dev->parent, adr, reg);
193 }
194
195 static int palmas_ldo_enable(struct udevice *dev, int op, bool *enable)
196 {
197         int ret;
198         unsigned int adr;
199         struct dm_regulator_uclass_platdata *uc_pdata;
200
201         uc_pdata = dev_get_uclass_platdata(dev);
202         adr = uc_pdata->ctrl_reg;
203
204         ret = pmic_reg_read(dev->parent, adr);
205                 if (ret < 0)
206                         return ret;
207
208         if (op == PMIC_OP_GET) {
209                 ret &= PALMAS_LDO_STATUS_MASK;
210
211                 if (ret)
212                         *enable = true;
213                 else
214                         *enable = false;
215
216                 return 0;
217         } else if (op == PMIC_OP_SET) {
218                 if (*enable)
219                         ret |= PALMAS_LDO_MODE_MASK;
220                 else
221                         ret &= ~(PALMAS_LDO_MODE_MASK);
222
223                 ret = pmic_reg_write(dev->parent, adr, ret);
224                 if (ret)
225                         return ret;
226
227                 ret = palmas_ldo_bypass_enable(dev, false);
228                 if (ret && (ret != -ENOTSUPP))
229                         return ret;
230         }
231
232         return 0;
233 }
234
235 static int palmas_ldo_volt2hex(int uV)
236 {
237         if (uV > PALMAS_LDO_VOLT_MAX)
238                 return -EINVAL;
239
240         return (uV - 850000) / 50000;
241 }
242
243 static int palmas_ldo_hex2volt(int hex)
244 {
245         if (hex > PALMAS_LDO_VOLT_MAX_HEX)
246                 return -EINVAL;
247
248         if (!hex)
249                 return 0;
250
251         return (hex * 50000) + 850000;
252 }
253
254 static int palmas_ldo_val(struct udevice *dev, int op, int *uV)
255 {
256         unsigned int hex, adr;
257         int ret;
258
259         struct dm_regulator_uclass_platdata *uc_pdata;
260
261         if (op == PMIC_OP_GET)
262                 *uV = 0;
263
264         uc_pdata = dev_get_uclass_platdata(dev);
265
266         adr = uc_pdata->volt_reg;
267
268         ret = pmic_reg_read(dev->parent, adr);
269         if (ret < 0)
270                 return ret;
271
272         if (op == PMIC_OP_GET) {
273                 ret &= PALMAS_LDO_VOLT_MASK;
274                 ret = palmas_ldo_hex2volt(ret);
275                 if (ret < 0)
276                         return ret;
277                 *uV = ret;
278                 return 0;
279         }
280
281         hex = palmas_ldo_volt2hex(*uV);
282         if (hex < 0)
283                 return hex;
284
285         ret &= ~PALMAS_LDO_VOLT_MASK;
286         ret |= hex;
287         if (*uV > 1650000)
288                 ret |= 0x80;
289
290         return pmic_reg_write(dev->parent, adr, ret);
291 }
292
293 static int palmas_ldo_probe(struct udevice *dev)
294 {
295         struct dm_regulator_uclass_platdata *uc_pdata;
296         struct udevice *parent;
297
298         uc_pdata = dev_get_uclass_platdata(dev);
299
300         parent = dev_get_parent(dev);
301         int type = dev_get_driver_data(parent);
302
303         uc_pdata->type = REGULATOR_TYPE_LDO;
304
305         if (dev->driver_data) {
306                 u8 idx = dev->driver_data - 1;
307                 uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][idx];
308                 uc_pdata->volt_reg = palmas_ldo_volt[type][idx];
309         } else {
310                 /* check for ldoln and ldousb cases */
311                 if (!strcmp("ldoln", dev->name)) {
312                         uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][9];
313                         uc_pdata->volt_reg = palmas_ldo_volt[type][9];
314                 } else if (!strcmp("ldousb", dev->name)) {
315                         uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][10];
316                         uc_pdata->volt_reg = palmas_ldo_volt[type][10];
317                 }
318         }
319
320         return 0;
321 }
322
323 static int ldo_get_value(struct udevice *dev)
324 {
325         int uV;
326         int ret;
327
328         ret = palmas_ldo_val(dev, PMIC_OP_GET, &uV);
329         if (ret)
330                 return ret;
331
332         return uV;
333 }
334
335 static int ldo_set_value(struct udevice *dev, int uV)
336 {
337         return palmas_ldo_val(dev, PMIC_OP_SET, &uV);
338 }
339
340 static int ldo_get_enable(struct udevice *dev)
341 {
342         bool enable = false;
343         int ret;
344
345         ret = palmas_ldo_enable(dev, PMIC_OP_GET, &enable);
346         if (ret)
347                 return ret;
348
349         return enable;
350 }
351
352 static int ldo_set_enable(struct udevice *dev, bool enable)
353 {
354         return palmas_ldo_enable(dev, PMIC_OP_SET, &enable);
355 }
356
357 static int palmas_smps_probe(struct udevice *dev)
358 {
359         struct dm_regulator_uclass_platdata *uc_pdata;
360         struct udevice *parent;
361         int idx;
362
363         uc_pdata = dev_get_uclass_platdata(dev);
364
365         parent = dev_get_parent(dev);
366         int type = dev_get_driver_data(parent);
367
368         uc_pdata->type = REGULATOR_TYPE_BUCK;
369
370         switch (type) {
371         case PALMAS:
372         case TPS659038:
373                 switch (dev->driver_data) {
374                 case 123:
375                 case 12:
376                         uc_pdata->ctrl_reg = palmas_smps_ctrl[type][0];
377                         uc_pdata->volt_reg = palmas_smps_volt[type][0];
378                         break;
379                 case 3:
380                         uc_pdata->ctrl_reg = palmas_smps_ctrl[type][1];
381                         uc_pdata->volt_reg = palmas_smps_volt[type][1];
382                         break;
383                 case 45:
384                         uc_pdata->ctrl_reg = palmas_smps_ctrl[type][2];
385                         uc_pdata->volt_reg = palmas_smps_volt[type][2];
386                         break;
387                 case 6:
388                 case 7:
389                 case 8:
390                 case 9:
391                 case 10:
392                         idx = dev->driver_data - 3;
393                         uc_pdata->ctrl_reg = palmas_smps_ctrl[type][idx];
394                         uc_pdata->volt_reg = palmas_smps_volt[type][idx];
395                         break;
396
397                 default:
398                         printf("Wrong ID for regulator\n");
399                 }
400                 break;
401
402         case TPS65917:
403                 switch (dev->driver_data) {
404                 case 1:
405                 case 2:
406                 case 3:
407                 case 4:
408                 case 5:
409                         idx = dev->driver_data - 1;
410                         uc_pdata->ctrl_reg = palmas_smps_ctrl[type][idx];
411                         uc_pdata->volt_reg = palmas_smps_volt[type][idx];
412                         break;
413                 case 12:
414                         idx = 0;
415                         uc_pdata->ctrl_reg = palmas_smps_ctrl[type][idx];
416                         uc_pdata->volt_reg = palmas_smps_volt[type][idx];
417                         break;
418                 default:
419                         printf("Wrong ID for regulator\n");
420                 }
421                 break;
422
423         default:
424                         printf("Invalid PMIC ID\n");
425         }
426
427         return 0;
428 }
429
430 static int smps_get_value(struct udevice *dev)
431 {
432         int uV;
433         int ret;
434
435         ret = palmas_smps_val(dev, PMIC_OP_GET, &uV);
436         if (ret)
437                 return ret;
438
439         return uV;
440 }
441
442 static int smps_set_value(struct udevice *dev, int uV)
443 {
444         return palmas_smps_val(dev, PMIC_OP_SET, &uV);
445 }
446
447 static int smps_get_enable(struct udevice *dev)
448 {
449         bool enable = false;
450         int ret;
451
452         ret = palmas_smps_enable(dev, PMIC_OP_GET, &enable);
453         if (ret)
454                 return ret;
455
456         return enable;
457 }
458
459 static int smps_set_enable(struct udevice *dev, bool enable)
460 {
461         return palmas_smps_enable(dev, PMIC_OP_SET, &enable);
462 }
463
464 static const struct dm_regulator_ops palmas_ldo_ops = {
465         .get_value  = ldo_get_value,
466         .set_value  = ldo_set_value,
467         .get_enable = ldo_get_enable,
468         .set_enable = ldo_set_enable,
469 };
470
471 U_BOOT_DRIVER(palmas_ldo) = {
472         .name = PALMAS_LDO_DRIVER,
473         .id = UCLASS_REGULATOR,
474         .ops = &palmas_ldo_ops,
475         .probe = palmas_ldo_probe,
476 };
477
478 static const struct dm_regulator_ops palmas_smps_ops = {
479         .get_value  = smps_get_value,
480         .set_value  = smps_set_value,
481         .get_enable = smps_get_enable,
482         .set_enable = smps_set_enable,
483 };
484
485 U_BOOT_DRIVER(palmas_smps) = {
486         .name = PALMAS_SMPS_DRIVER,
487         .id = UCLASS_REGULATOR,
488         .ops = &palmas_smps_ops,
489         .probe = palmas_smps_probe,
490 };