blob: f87d07e61fbff09f55ef7cac8da2c562e94e4e8a [file] [log] [blame]
Neil Armstrong5fc0a862022-04-27 13:28:10 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2022 BayLibre, SAS
4 * Author: Neil Armstrong <narmstrong@baylibre.com>
5 *
6 */
7
8#include <common.h>
9#include <fdtdec.h>
10#include <errno.h>
11#include <dm.h>
Neil Armstrong5fc0a862022-04-27 13:28:10 +020012#include <log.h>
13#include <linux/delay.h>
14#include <power/pmic.h>
15#include <power/regulator.h>
16#include <power/tps65219.h>
17
18static const unsigned int tps65219_buck_vout[TPS65219_BUCK_NUM] = {
19 [0] = TPS65219_BUCK1_VOUT_REG,
20 [1] = TPS65219_BUCK2_VOUT_REG,
21 [2] = TPS65219_BUCK3_VOUT_REG
22};
23
24static const unsigned int tps65219_ldo_vout[TPS65219_LDO_NUM] = {
25 [0] = TPS65219_LDO1_VOUT_REG,
26 [1] = TPS65219_LDO2_VOUT_REG,
27 [2] = TPS65219_LDO3_VOUT_REG,
28 [3] = TPS65219_LDO4_VOUT_REG,
29};
30
31static int tps65219_reg_enable(struct udevice *dev, unsigned int adr, int idx,
32 int op, bool *enable)
33{
34 int ret;
35
36 ret = pmic_reg_read(dev->parent, adr);
37 if (ret < 0)
38 return ret;
39
40 if (op == PMIC_OP_GET) {
41 if (ret & BIT(idx))
42 *enable = true;
43 else
44 *enable = false;
45
46 return 0;
47 } else if (op == PMIC_OP_SET) {
48 if (*enable)
49 ret |= BIT(idx);
50 else
51 ret &= ~BIT(idx);
52
53 ret = pmic_reg_write(dev->parent, adr, ret);
54 if (ret)
55 return ret;
56 }
57
58 return 0;
59}
60
61static int tps65219_buck_enable(struct udevice *dev, int op, bool *enable)
62{
63 unsigned int adr;
64 struct dm_regulator_uclass_plat *uc_pdata;
65 int idx;
66
67 idx = dev->driver_data - 1;
68 uc_pdata = dev_get_uclass_plat(dev);
69 adr = uc_pdata->ctrl_reg;
70
71 return tps65219_reg_enable(dev, adr, idx, op, enable);
72}
73
74static int tps65219_buck_volt2val(int uV)
75{
76 if (uV > TPS65219_BUCK_VOLT_MAX)
77 return -EINVAL;
78 else if (uV >= 1400000)
79 return (uV - 1400000) / 100000 + 0x20;
80 else if (uV >= 600000)
81 return (uV - 600000) / 25000 + 0x00;
82 else
83 return -EINVAL;
84}
85
86static int tps65219_buck_val2volt(int val)
87{
88 if (val > TPS65219_VOLT_MASK)
89 return -EINVAL;
90 else if (val > 0x34)
91 return TPS65219_BUCK_VOLT_MAX;
92 else if (val > 0x20)
93 return 1400000 + (val - 0x20) * 100000;
94 else if (val >= 0)
95 return 600000 + val * 25000;
96 else
97 return -EINVAL;
98}
99
100static int tps65219_buck_val(struct udevice *dev, int op, int *uV)
101{
102 unsigned int adr;
103 int ret, val;
104 struct dm_regulator_uclass_plat *uc_pdata;
105
106 uc_pdata = dev_get_uclass_plat(dev);
107 adr = uc_pdata->volt_reg;
108
109 ret = pmic_reg_read(dev->parent, adr);
110 if (ret < 0)
111 return ret;
112
113 if (op == PMIC_OP_GET) {
114 *uV = 0;
115
116 ret &= TPS65219_VOLT_MASK;
117 ret = tps65219_buck_val2volt(ret);
118 if (ret < 0)
119 return ret;
120
121 *uV = ret;
122 return 0;
123 }
124
125 val = tps65219_buck_volt2val(*uV);
126 if (val < 0)
127 return val;
128
129 ret &= ~TPS65219_VOLT_MASK;
130 ret |= val;
131
132 ret = pmic_reg_write(dev->parent, adr, ret);
133
134 udelay(100);
135
136 return ret;
137}
138
139static int tps65219_ldo_enable(struct udevice *dev, int op, bool *enable)
140{
141 unsigned int adr;
142 struct dm_regulator_uclass_plat *uc_pdata;
143 int idx;
144
145 idx = TPS65219_BUCK_NUM + (dev->driver_data - 1);
146 uc_pdata = dev_get_uclass_plat(dev);
147 adr = uc_pdata->ctrl_reg;
148
149 return tps65219_reg_enable(dev, adr, idx, op, enable);
150}
151
152static int tps65219_ldo_volt2val(int idx, int uV)
153{
154 int base = TPS65219_LDO12_VOLT_MIN;
155 int max = TPS65219_LDO12_VOLT_MAX;
156
157 if (idx > 1) {
158 base = TPS65219_LDO34_VOLT_MIN;
159 max = TPS65219_LDO34_VOLT_MAX;
160 }
161
162 if (uV > max)
163 return -EINVAL;
164 else if (uV >= base)
165 return (uV - TPS65219_LDO12_VOLT_MIN) / 50000;
166 else
167 return -EINVAL;
168}
169
170static int tps65219_ldo_val2volt(int idx, int val)
171{
172 int reg_base = TPS65219_LDO12_VOLT_REG_MIN;
173 int reg_max = TPS65219_LDO12_VOLT_REG_MAX;
174 int base = TPS65219_LDO12_VOLT_MIN;
175 int max = TPS65219_LDO12_VOLT_MAX;
176
177 if (idx > 1) {
178 base = TPS65219_LDO34_VOLT_MIN;
179 max = TPS65219_LDO34_VOLT_MAX;
180 reg_base = TPS65219_LDO34_VOLT_REG_MIN;
181 reg_max = TPS65219_LDO34_VOLT_REG_MAX;
182 }
183
184 if (val > TPS65219_VOLT_MASK || val < 0)
185 return -EINVAL;
186 else if (val >= reg_max)
187 return max;
188 else if (val <= reg_base)
189 return base;
190 else if (val >= 0)
191 return TPS65219_LDO12_VOLT_MIN + (50000 * val);
192 else
193 return -EINVAL;
194}
195
196static int tps65219_ldo_val(struct udevice *dev, int op, int *uV)
197{
198 unsigned int adr;
199 int ret, val;
200 struct dm_regulator_uclass_plat *uc_pdata;
201 int idx;
202
203 idx = dev->driver_data - 1;
204 uc_pdata = dev_get_uclass_plat(dev);
205 adr = uc_pdata->volt_reg;
206
207 ret = pmic_reg_read(dev->parent, adr);
208 if (ret < 0)
209 return ret;
210
211 if (op == PMIC_OP_GET) {
212 *uV = 0;
213
214 ret &= TPS65219_VOLT_MASK;
215 ret = tps65219_ldo_val2volt(idx, ret);
216 if (ret < 0)
217 return ret;
218
219 *uV = ret;
220 return 0;
221 }
222
223 /* LDO1 & LDO2 in BYPASS mode only supports 1.5V max */
224 if (idx < 2 &&
225 (ret & BIT(TPS65219_LDO12_BYP_CONFIG)) &&
226 *uV < TPS65219_LDO12_VOLT_BYP_MIN)
227 return -EINVAL;
228
229 val = tps65219_ldo_volt2val(idx, *uV);
230 if (val < 0)
231 return val;
232
233 ret &= ~TPS65219_VOLT_MASK;
234 ret |= val;
235
236 ret = pmic_reg_write(dev->parent, adr, ret);
237
238 udelay(100);
239
240 return ret;
241}
242
243static int tps65219_ldo_probe(struct udevice *dev)
244{
245 struct dm_regulator_uclass_plat *uc_pdata;
246 int idx;
247
248 uc_pdata = dev_get_uclass_plat(dev);
249 uc_pdata->type = REGULATOR_TYPE_LDO;
250
251 /* idx must be in 1..TPS65219_LDO_NUM */
252 idx = dev->driver_data;
253 if (idx < 1 || idx > TPS65219_LDO_NUM) {
254 printf("Wrong ID for regulator\n");
255 return -EINVAL;
256 }
257
258 uc_pdata->ctrl_reg = TPS65219_ENABLE_CTRL_REG;
259 uc_pdata->volt_reg = tps65219_ldo_vout[idx - 1];
260
261 return 0;
262}
263
264static int tps65219_buck_probe(struct udevice *dev)
265{
266 struct dm_regulator_uclass_plat *uc_pdata;
267 int idx;
268
269 uc_pdata = dev_get_uclass_plat(dev);
270 uc_pdata->type = REGULATOR_TYPE_BUCK;
271
272 /* idx must be in 1..TPS65219_BUCK_NUM */
273 idx = dev->driver_data;
274 if (idx < 1 || idx > TPS65219_BUCK_NUM) {
275 printf("Wrong ID for regulator\n");
276 return -EINVAL;
277 }
278
279 uc_pdata->ctrl_reg = TPS65219_ENABLE_CTRL_REG;
280 uc_pdata->volt_reg = tps65219_buck_vout[idx - 1];
281
282 return 0;
283}
284
285static int ldo_get_value(struct udevice *dev)
286{
287 int uV;
288 int ret;
289
290 ret = tps65219_ldo_val(dev, PMIC_OP_GET, &uV);
291 if (ret)
292 return ret;
293
294 return uV;
295}
296
297static int ldo_set_value(struct udevice *dev, int uV)
298{
299 return tps65219_ldo_val(dev, PMIC_OP_SET, &uV);
300}
301
302static int ldo_get_enable(struct udevice *dev)
303{
304 bool enable = false;
305 int ret;
306
307 ret = tps65219_ldo_enable(dev, PMIC_OP_GET, &enable);
308 if (ret)
309 return ret;
310
311 return enable;
312}
313
314static int ldo_set_enable(struct udevice *dev, bool enable)
315{
316 return tps65219_ldo_enable(dev, PMIC_OP_SET, &enable);
317}
318
319static int buck_get_value(struct udevice *dev)
320{
321 int uV;
322 int ret;
323
324 ret = tps65219_buck_val(dev, PMIC_OP_GET, &uV);
325 if (ret)
326 return ret;
327
328 return uV;
329}
330
331static int buck_set_value(struct udevice *dev, int uV)
332{
333 return tps65219_buck_val(dev, PMIC_OP_SET, &uV);
334}
335
336static int buck_get_enable(struct udevice *dev)
337{
338 bool enable = false;
339 int ret;
340
341 ret = tps65219_buck_enable(dev, PMIC_OP_GET, &enable);
342 if (ret)
343 return ret;
344
345 return enable;
346}
347
348static int buck_set_enable(struct udevice *dev, bool enable)
349{
350 return tps65219_buck_enable(dev, PMIC_OP_SET, &enable);
351}
352
353static const struct dm_regulator_ops tps65219_ldo_ops = {
354 .get_value = ldo_get_value,
355 .set_value = ldo_set_value,
356 .get_enable = ldo_get_enable,
357 .set_enable = ldo_set_enable,
358};
359
360U_BOOT_DRIVER(tps65219_ldo) = {
361 .name = TPS65219_LDO_DRIVER,
362 .id = UCLASS_REGULATOR,
363 .ops = &tps65219_ldo_ops,
364 .probe = tps65219_ldo_probe,
365};
366
367static const struct dm_regulator_ops tps65219_buck_ops = {
368 .get_value = buck_get_value,
369 .set_value = buck_set_value,
370 .get_enable = buck_get_enable,
371 .set_enable = buck_set_enable,
372};
373
374U_BOOT_DRIVER(tps65219_buck) = {
375 .name = TPS65219_BUCK_DRIVER,
376 .id = UCLASS_REGULATOR,
377 .ops = &tps65219_buck_ops,
378 .probe = tps65219_buck_probe,
379};