blob: cf54e30df5eb80502ccfc9481f2135aca5aa65a4 [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>
Simon Glass0f2af882020-05-10 11:40:05 -060013#include <log.h>
Simon Glassdbd79542020-05-10 11:40:11 -060014#include <linux/delay.h>
Keerthy4a030002019-10-24 15:00:51 +053015#include <power/pmic.h>
16#include <power/regulator.h>
17#include <power/tps65941.h>
18
Bhargav Raviprakash83491492024-04-22 09:48:53 +000019/* Single Phase Buck IDs */
20#define TPS65941_BUCK_ID_1 1
21#define TPS65941_BUCK_ID_2 2
22#define TPS65941_BUCK_ID_3 3
23#define TPS65941_BUCK_ID_4 4
24#define TPS65941_BUCK_ID_5 5
25
26/* Multi Phase Buck IDs */
27#define TPS65941_BUCK_ID_12 12
28#define TPS65941_BUCK_ID_34 34
29#define TPS65941_BUCK_ID_123 123
30#define TPS65941_BUCK_ID_1234 1234
31
32/* LDO IDs */
33#define TPS65941_LDO_ID_1 1
34#define TPS65941_LDO_ID_2 2
35#define TPS65941_LDO_ID_3 3
36#define TPS65941_LDO_ID_4 4
37
Keerthy4a030002019-10-24 15:00:51 +053038static const char tps65941_buck_ctrl[TPS65941_BUCK_NUM] = {0x4, 0x6, 0x8, 0xA,
39 0xC};
40static const char tps65941_buck_vout[TPS65941_BUCK_NUM] = {0xE, 0x10, 0x12,
41 0x14, 0x16};
42static const char tps65941_ldo_ctrl[TPS65941_BUCK_NUM] = {0x1D, 0x1E, 0x1F,
43 0x20};
44static const char tps65941_ldo_vout[TPS65941_BUCK_NUM] = {0x23, 0x24, 0x25,
45 0x26};
46
47static int tps65941_buck_enable(struct udevice *dev, int op, bool *enable)
48{
49 int ret;
50 unsigned int adr;
Simon Glass71fa5b42020-12-03 16:55:18 -070051 struct dm_regulator_uclass_plat *uc_pdata;
Keerthy4a030002019-10-24 15:00:51 +053052
Simon Glass71fa5b42020-12-03 16:55:18 -070053 uc_pdata = dev_get_uclass_plat(dev);
Keerthy4a030002019-10-24 15:00:51 +053054 adr = uc_pdata->ctrl_reg;
55
56 ret = pmic_reg_read(dev->parent, adr);
57 if (ret < 0)
58 return ret;
59
60 if (op == PMIC_OP_GET) {
61 ret &= TPS65941_BUCK_MODE_MASK;
62
63 if (ret)
64 *enable = true;
65 else
66 *enable = false;
67
68 return 0;
69 } else if (op == PMIC_OP_SET) {
70 if (*enable)
71 ret |= TPS65941_BUCK_MODE_MASK;
72 else
73 ret &= ~TPS65941_BUCK_MODE_MASK;
74 ret = pmic_reg_write(dev->parent, adr, ret);
75 if (ret)
76 return ret;
77 }
78
79 return 0;
80}
81
82static int tps65941_buck_volt2val(int uV)
83{
84 if (uV > TPS65941_BUCK_VOLT_MAX)
85 return -EINVAL;
86 else if (uV > 1650000)
87 return (uV - 1660000) / 20000 + 0xAB;
88 else if (uV > 1110000)
89 return (uV - 1110000) / 10000 + 0x73;
90 else if (uV > 600000)
91 return (uV - 600000) / 5000 + 0x0F;
92 else if (uV >= 300000)
93 return (uV - 300000) / 20000 + 0x00;
94 else
95 return -EINVAL;
96}
97
98static int tps65941_buck_val2volt(int val)
99{
100 if (val > TPS65941_BUCK_VOLT_MAX_HEX)
101 return -EINVAL;
102 else if (val > 0xAB)
103 return 1660000 + (val - 0xAB) * 20000;
104 else if (val > 0x73)
105 return 1100000 + (val - 0x73) * 10000;
106 else if (val > 0xF)
107 return 600000 + (val - 0xF) * 5000;
108 else if (val >= 0x0)
109 return 300000 + val * 5000;
110 else
111 return -EINVAL;
112}
113
114int tps65941_lookup_slew(int id)
115{
116 switch (id) {
117 case 0:
118 return 33000;
119 case 1:
120 return 20000;
121 case 2:
122 return 10000;
123 case 3:
124 return 5000;
125 case 4:
126 return 2500;
127 case 5:
128 return 1300;
129 case 6:
130 return 630;
131 case 7:
132 return 310;
133 default:
134 return -1;
135 }
136}
137
138static int tps65941_buck_val(struct udevice *dev, int op, int *uV)
139{
140 unsigned int hex, adr;
141 int ret, delta, uwait, slew;
Simon Glass71fa5b42020-12-03 16:55:18 -0700142 struct dm_regulator_uclass_plat *uc_pdata;
Keerthy4a030002019-10-24 15:00:51 +0530143
Simon Glass71fa5b42020-12-03 16:55:18 -0700144 uc_pdata = dev_get_uclass_plat(dev);
Keerthy4a030002019-10-24 15:00:51 +0530145
146 if (op == PMIC_OP_GET)
147 *uV = 0;
148
149 adr = uc_pdata->volt_reg;
150
151 ret = pmic_reg_read(dev->parent, adr);
152 if (ret < 0)
153 return ret;
154
155 ret &= TPS65941_BUCK_VOLT_MASK;
156 ret = tps65941_buck_val2volt(ret);
157 if (ret < 0)
158 return ret;
159
160 if (op == PMIC_OP_GET) {
161 *uV = ret;
162 return 0;
163 }
164
165 /*
166 * Compute the delta voltage, find the slew rate and wait
167 * for the appropriate amount of time after voltage switch
168 */
169 if (*uV > ret)
170 delta = *uV - ret;
171 else
172 delta = ret - *uV;
173
174 slew = pmic_reg_read(dev->parent, uc_pdata->ctrl_reg + 1);
175 if (slew < 0)
176 return ret;
177
178 slew &= TP65941_BUCK_CONF_SLEW_MASK;
179 slew = tps65941_lookup_slew(slew);
180 if (slew <= 0)
181 return ret;
182
183 uwait = delta / slew;
184
185 hex = tps65941_buck_volt2val(*uV);
186 if (hex < 0)
187 return hex;
188
189 ret &= 0x0;
190 ret = hex;
191
192 ret = pmic_reg_write(dev->parent, adr, ret);
193
194 udelay(uwait);
195
196 return ret;
197}
198
199static int tps65941_ldo_enable(struct udevice *dev, int op, bool *enable)
200{
201 int ret;
202 unsigned int adr;
Simon Glass71fa5b42020-12-03 16:55:18 -0700203 struct dm_regulator_uclass_plat *uc_pdata;
Keerthy4a030002019-10-24 15:00:51 +0530204
Simon Glass71fa5b42020-12-03 16:55:18 -0700205 uc_pdata = dev_get_uclass_plat(dev);
Keerthy4a030002019-10-24 15:00:51 +0530206 adr = uc_pdata->ctrl_reg;
207
208 ret = pmic_reg_read(dev->parent, adr);
209 if (ret < 0)
210 return ret;
211
212 if (op == PMIC_OP_GET) {
213 ret &= TPS65941_LDO_MODE_MASK;
214
215 if (ret)
216 *enable = true;
217 else
218 *enable = false;
219
220 return 0;
221 } else if (op == PMIC_OP_SET) {
222 if (*enable)
223 ret |= TPS65941_LDO_MODE_MASK;
224 else
225 ret &= ~TPS65941_LDO_MODE_MASK;
226 ret = pmic_reg_write(dev->parent, adr, ret);
227 if (ret)
228 return ret;
229 }
230
231 return 0;
232}
233
234static int tps65941_ldo_val2volt(int val)
235{
236 if (val > TPS65941_LDO_VOLT_MAX_HEX || val < TPS65941_LDO_VOLT_MIN_HEX)
237 return -EINVAL;
238 else if (val >= TPS65941_LDO_VOLT_MIN_HEX)
239 return 600000 + (val - TPS65941_LDO_VOLT_MIN_HEX) * 50000;
240 else
241 return -EINVAL;
242}
243
244static int tps65941_ldo_val(struct udevice *dev, int op, int *uV)
245{
246 unsigned int hex, adr;
247 int ret;
Simon Glass71fa5b42020-12-03 16:55:18 -0700248 struct dm_regulator_uclass_plat *uc_pdata;
Keerthy4a030002019-10-24 15:00:51 +0530249
Simon Glass71fa5b42020-12-03 16:55:18 -0700250 uc_pdata = dev_get_uclass_plat(dev);
Keerthy4a030002019-10-24 15:00:51 +0530251
252 if (op == PMIC_OP_GET)
253 *uV = 0;
254
255 adr = uc_pdata->volt_reg;
256
257 ret = pmic_reg_read(dev->parent, adr);
258 if (ret < 0)
259 return ret;
260
261 ret &= TPS65941_LDO_VOLT_MASK;
262 ret = tps65941_ldo_val2volt(ret);
263 if (ret < 0)
264 return ret;
265
266 if (op == PMIC_OP_GET) {
267 *uV = ret;
268 return 0;
269 }
270
271 hex = tps65941_buck_volt2val(*uV);
272 if (hex < 0)
273 return hex;
274
275 ret &= 0x0;
276 ret = hex;
277
278 ret = pmic_reg_write(dev->parent, adr, ret);
279
280 return ret;
281}
282
283static int tps65941_ldo_probe(struct udevice *dev)
284{
Simon Glass71fa5b42020-12-03 16:55:18 -0700285 struct dm_regulator_uclass_plat *uc_pdata;
Keerthy4a030002019-10-24 15:00:51 +0530286 int idx;
287
Simon Glass71fa5b42020-12-03 16:55:18 -0700288 uc_pdata = dev_get_uclass_plat(dev);
Keerthy4a030002019-10-24 15:00:51 +0530289 uc_pdata->type = REGULATOR_TYPE_LDO;
290
291 idx = dev->driver_data;
Bhargav Raviprakash83491492024-04-22 09:48:53 +0000292 switch (idx) {
293 case TPS65941_LDO_ID_1:
294 case TPS65941_LDO_ID_2:
295 case TPS65941_LDO_ID_3:
296 case TPS65941_LDO_ID_4:
Keerthy4a030002019-10-24 15:00:51 +0530297 debug("Single phase regulator\n");
Bhargav Raviprakash83491492024-04-22 09:48:53 +0000298 break;
299 default:
300 pr_err("Wrong ID for regulator\n");
Keerthy4a030002019-10-24 15:00:51 +0530301 return -EINVAL;
302 }
303
304 uc_pdata->ctrl_reg = tps65941_ldo_ctrl[idx - 1];
305 uc_pdata->volt_reg = tps65941_ldo_vout[idx - 1];
306
307 return 0;
308}
309
310static int tps65941_buck_probe(struct udevice *dev)
311{
Simon Glass71fa5b42020-12-03 16:55:18 -0700312 struct dm_regulator_uclass_plat *uc_pdata;
Keerthy4a030002019-10-24 15:00:51 +0530313 int idx;
314
Simon Glass71fa5b42020-12-03 16:55:18 -0700315 uc_pdata = dev_get_uclass_plat(dev);
Keerthy4a030002019-10-24 15:00:51 +0530316 uc_pdata->type = REGULATOR_TYPE_BUCK;
317
318 idx = dev->driver_data;
Bhargav Raviprakash83491492024-04-22 09:48:53 +0000319 switch (idx) {
320 case TPS65941_BUCK_ID_1:
321 case TPS65941_BUCK_ID_2:
322 case TPS65941_BUCK_ID_3:
323 case TPS65941_BUCK_ID_4:
324 case TPS65941_BUCK_ID_5:
Keerthy4a030002019-10-24 15:00:51 +0530325 debug("Single phase regulator\n");
Bhargav Raviprakash83491492024-04-22 09:48:53 +0000326 break;
327 case TPS65941_BUCK_ID_12:
328 case TPS65941_BUCK_ID_123:
329 case TPS65941_BUCK_ID_1234:
Keerthy4a030002019-10-24 15:00:51 +0530330 idx = 1;
Bhargav Raviprakash83491492024-04-22 09:48:53 +0000331 break;
332 case TPS65941_BUCK_ID_34:
Keerthy4a030002019-10-24 15:00:51 +0530333 idx = 3;
Bhargav Raviprakash83491492024-04-22 09:48:53 +0000334 break;
335 default:
336 pr_err("Wrong ID for regulator\n");
Keerthy4a030002019-10-24 15:00:51 +0530337 return -EINVAL;
338 }
339
340 uc_pdata->ctrl_reg = tps65941_buck_ctrl[idx - 1];
341 uc_pdata->volt_reg = tps65941_buck_vout[idx - 1];
342
343 return 0;
344}
345
346static int ldo_get_value(struct udevice *dev)
347{
348 int uV;
349 int ret;
350
351 ret = tps65941_ldo_val(dev, PMIC_OP_GET, &uV);
352 if (ret)
353 return ret;
354
355 return uV;
356}
357
358static int ldo_set_value(struct udevice *dev, int uV)
359{
360 return tps65941_ldo_val(dev, PMIC_OP_SET, &uV);
361}
362
363static int ldo_get_enable(struct udevice *dev)
364{
365 bool enable = false;
366 int ret;
367
368 ret = tps65941_ldo_enable(dev, PMIC_OP_GET, &enable);
369 if (ret)
370 return ret;
371
372 return enable;
373}
374
375static int ldo_set_enable(struct udevice *dev, bool enable)
376{
377 return tps65941_ldo_enable(dev, PMIC_OP_SET, &enable);
378}
379
380static int buck_get_value(struct udevice *dev)
381{
382 int uV;
383 int ret;
384
385 ret = tps65941_buck_val(dev, PMIC_OP_GET, &uV);
386 if (ret)
387 return ret;
388
389 return uV;
390}
391
392static int buck_set_value(struct udevice *dev, int uV)
393{
394 return tps65941_buck_val(dev, PMIC_OP_SET, &uV);
395}
396
397static int buck_get_enable(struct udevice *dev)
398{
399 bool enable = false;
400 int ret;
401
402 ret = tps65941_buck_enable(dev, PMIC_OP_GET, &enable);
403 if (ret)
404 return ret;
405
406 return enable;
407}
408
409static int buck_set_enable(struct udevice *dev, bool enable)
410{
411 return tps65941_buck_enable(dev, PMIC_OP_SET, &enable);
412}
413
414static const struct dm_regulator_ops tps65941_ldo_ops = {
415 .get_value = ldo_get_value,
416 .set_value = ldo_set_value,
417 .get_enable = ldo_get_enable,
418 .set_enable = ldo_set_enable,
419};
420
421U_BOOT_DRIVER(tps65941_ldo) = {
422 .name = TPS65941_LDO_DRIVER,
423 .id = UCLASS_REGULATOR,
424 .ops = &tps65941_ldo_ops,
425 .probe = tps65941_ldo_probe,
426};
427
428static const struct dm_regulator_ops tps65941_buck_ops = {
429 .get_value = buck_get_value,
430 .set_value = buck_set_value,
431 .get_enable = buck_get_enable,
432 .set_enable = buck_set_enable,
433};
434
435U_BOOT_DRIVER(tps65941_buck) = {
436 .name = TPS65941_BUCK_DRIVER,
437 .id = UCLASS_REGULATOR,
438 .ops = &tps65941_buck_ops,
439 .probe = tps65941_buck_probe,
440};