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