blob: 2b5acdfcbb0d5eea2c72db0b73fea14105f28333 [file] [log] [blame]
Svyatoslav Ryheld10842a2023-10-27 11:26:15 +03001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
4 */
5
6#include <dm.h>
7#include <power/pmic.h>
8#include <power/regulator.h>
9#include <power/tps65910_pmic.h>
10
11/* fist row is control registers, second is voltage registers */
12static const char tps65911_vdd_reg[][TPS65911_VDD_NUM] = {
13 { TPS65911_REG_VDD1, TPS65911_REG_VDD2,
14 TPS65911_REG_VDDCTRL, TPS65911_REG_VIO },
15 { TPS65911_REG_VDD1_OP, TPS65911_REG_VDD2_OP,
16 TPS65911_REG_VDDCTRL_OP, 0x00 },
17};
18
19static const char tps65911_ldo_reg[TPS65911_LDO_NUM] = {
20 TPS65911_REG_LDO1, TPS65911_REG_LDO2, TPS65911_REG_LDO3,
21 TPS65911_REG_LDO4, TPS65911_REG_LDO5, TPS65911_REG_LDO6,
22 TPS65911_REG_LDO7, TPS65911_REG_LDO8
23};
24
25static int tps65911_regulator_enable(struct udevice *dev, int op, bool *enable)
26{
27 struct dm_regulator_uclass_plat *uc_pdata =
28 dev_get_uclass_plat(dev);
29 u32 adr = uc_pdata->ctrl_reg;
30 int val, ret;
31
32 val = pmic_reg_read(dev->parent, adr);
33 if (val < 0)
34 return val;
35
36 if (op == PMIC_OP_GET) {
37 if (val & TPS65910_SUPPLY_STATE_ON)
38 *enable = true;
39 else
40 *enable = false;
41
42 return 0;
43 } else if (op == PMIC_OP_SET) {
44 val &= ~TPS65910_SUPPLY_STATE_MASK;
45
46 if (*enable)
47 val |= TPS65910_SUPPLY_STATE_ON;
48
49 ret = pmic_reg_write(dev->parent, adr, val);
50 if (ret)
51 return ret;
52 }
53
54 return 0;
55}
56
57static int tps65911_get_enable(struct udevice *dev)
58{
59 bool enable = false;
60 int ret;
61
62 ret = tps65911_regulator_enable(dev, PMIC_OP_GET, &enable);
63 if (ret)
64 return ret;
65
66 return enable;
67}
68
69static int tps65911_set_enable(struct udevice *dev, bool enable)
70{
71 return tps65911_regulator_enable(dev, PMIC_OP_SET, &enable);
72}
73
74/**
75 * tps65911_vdd_volt2hex() - convert voltage in uV into
76 * applicable to register hex value
77 *
78 * @uV: voltage in uV
79 *
80 * Return: voltage in hex on success, -ve on failure
81 */
82static int tps65911_vdd_volt2hex(int uV)
83{
84 if (uV > TPS65911_VDD_VOLT_MAX)
85 return -EINVAL;
86
87 if (uV < TPS65911_VDD_VOLT_MIN)
88 uV = TPS65911_VDD_VOLT_MIN;
89
90 return (uV - TPS65911_VDD_VOLT_BASE) / 12500;
91}
92
93/**
94 * tps65911_vdd_hex2volt() - convert register hex value into
95 * actual voltage in uV
96 *
97 * @hex: hex value of register
98 *
99 * Return: voltage in uV on success, -ve on failure
100 */
101static int tps65911_vdd_hex2volt(int hex)
102{
103 if (hex > TPS65910_VDD_SEL_MAX)
104 return -EINVAL;
105
106 if (hex < TPS65910_VDD_SEL_MIN)
107 hex = TPS65910_VDD_SEL_MIN;
108
109 return TPS65911_VDD_VOLT_BASE + hex * 12500;
110}
111
112static int tps65911_vio_range[4] = {
113 1500000, 1800000, 2500000, 3300000
114};
115
116static int tps65911_vio_val(struct udevice *dev, int op, int *uV)
117{
118 struct dm_regulator_uclass_plat *uc_pdata =
119 dev_get_uclass_plat(dev);
120 u32 adr = uc_pdata->volt_reg;
121 int i, val;
122
123 val = pmic_reg_read(dev->parent, adr);
124 if (val < 0)
125 return val;
126
127 if (op == PMIC_OP_GET) {
128 *uV = 0;
129
130 val &= TPS65910_SEL_MASK;
131
132 *uV = tps65911_vio_range[val >> 2];
133
134 return 0;
135 }
136
137 val &= ~TPS65910_SEL_MASK;
138
139 for (i = 0; i < ARRAY_SIZE(tps65911_vio_range); i++)
140 if (*uV <= tps65911_vio_range[i])
141 break;
142
143 return pmic_reg_write(dev->parent, adr, val | i << 2);
144}
145
146static int tps65911_vdd_val(struct udevice *dev, int op, int *uV)
147{
148 struct dm_regulator_uclass_plat *uc_pdata =
149 dev_get_uclass_plat(dev);
150 u32 adr = uc_pdata->volt_reg;
151 int val, ret;
152
153 /* in case vdd is vio */
154 if (!adr)
155 return tps65911_vio_val(dev, op, uV);
156
157 val = pmic_reg_read(dev->parent, adr);
158 if (val < 0)
159 return val;
160
161 if (op == PMIC_OP_GET) {
162 *uV = 0;
163
164 ret = tps65911_vdd_hex2volt(val);
165 if (ret < 0)
166 return ret;
167
168 *uV = ret;
169 return 0;
170 }
171
172 val = tps65911_vdd_volt2hex(*uV);
173 if (val < 0)
174 return val;
175
176 return pmic_reg_write(dev->parent, adr, val);
177}
178
179static int tps65911_vdd_probe(struct udevice *dev)
180{
181 struct dm_regulator_uclass_plat *uc_pdata =
182 dev_get_uclass_plat(dev);
183
184 uc_pdata->type = REGULATOR_TYPE_BUCK;
185
186 /* check for vddctrl and vddio cases */
187 if (!strcmp("vddctrl", dev->name)) {
188 uc_pdata->ctrl_reg = tps65911_vdd_reg[0][2];
189 uc_pdata->volt_reg = tps65911_vdd_reg[1][2];
190 return 0;
191 }
192
193 if (!strcmp("vddio", dev->name)) {
194 uc_pdata->ctrl_reg = tps65911_vdd_reg[0][3];
195 uc_pdata->volt_reg = tps65911_vdd_reg[1][3];
196 return 0;
197 }
198
199 if (dev->driver_data > 0) {
200 u8 idx = dev->driver_data - 1;
201
202 uc_pdata->ctrl_reg = tps65911_vdd_reg[0][idx];
203 uc_pdata->volt_reg = tps65911_vdd_reg[1][idx];
204 }
205
206 return 0;
207}
208
209static int vdd_get_value(struct udevice *dev)
210{
211 int uV;
212 int ret;
213
214 ret = tps65911_vdd_val(dev, PMIC_OP_GET, &uV);
215 if (ret)
216 return ret;
217
218 return uV;
219}
220
221static int vdd_set_value(struct udevice *dev, int uV)
222{
223 return tps65911_vdd_val(dev, PMIC_OP_SET, &uV);
224}
225
226static const struct dm_regulator_ops tps65911_vdd_ops = {
227 .get_value = vdd_get_value,
228 .set_value = vdd_set_value,
229 .get_enable = tps65911_get_enable,
230 .set_enable = tps65911_set_enable,
231};
232
233U_BOOT_DRIVER(tps65911_vdd) = {
234 .name = TPS65911_VDD_DRIVER,
235 .id = UCLASS_REGULATOR,
236 .ops = &tps65911_vdd_ops,
237 .probe = tps65911_vdd_probe,
238};
239
240/**
241 * tps65911_ldo_volt2hex() - convert voltage in uV into
242 * applicable to register hex value
243 *
244 * @idx: regulator index
245 * @uV: voltage in uV
246 *
247 * Return: voltage in hex on success, -ve on failure
248 */
249static int tps65911_ldo_volt2hex(int idx, int uV)
250{
251 int step;
252
253 if (uV > TPS65911_LDO_VOLT_MAX)
254 return -EINVAL;
255
256 if (uV < TPS65911_LDO_VOLT_BASE)
257 uV = TPS65911_LDO_VOLT_BASE;
258
259 switch (idx) {
260 case 1:
261 case 2:
262 case 4:
263 step = TPS65911_LDO124_VOLT_STEP;
264 break;
265 case 3:
266 case 5:
267 case 6:
268 case 7:
269 case 8:
270 step = TPS65911_LDO358_VOLT_STEP;
271 break;
272 default:
273 return -EINVAL;
274 };
275
276 return ((uV - TPS65911_LDO_VOLT_BASE) / step) << 2;
277}
278
279/**
280 * tps65911_ldo_hex2volt() - convert register hex value into
281 * actual voltage in uV
282 *
283 * @idx: regulator index
284 * @hex: hex value of register
285 *
286 * Return: voltage in uV on success, -ve on failure
287 */
288static int tps65911_ldo_hex2volt(int idx, int hex)
289{
290 int step;
291
292 switch (idx) {
293 case 1:
294 case 2:
295 case 4:
296 if (hex > TPS65911_LDO124_VOLT_MAX_HEX)
297 return -EINVAL;
298
299 step = TPS65911_LDO124_VOLT_STEP;
300 break;
301 case 3:
302 case 5:
303 case 6:
304 case 7:
305 case 8:
306 if (hex > TPS65911_LDO358_VOLT_MAX_HEX)
307 return -EINVAL;
308
309 if (hex < TPS65911_LDO358_VOLT_MIN_HEX)
310 hex = TPS65911_LDO358_VOLT_MIN_HEX;
311
312 step = TPS65911_LDO358_VOLT_STEP;
313 break;
314 default:
315 return -EINVAL;
316 };
317
318 return TPS65911_LDO_VOLT_BASE + hex * step;
319}
320
321static int tps65911_ldo_val(struct udevice *dev, int op, int *uV)
322{
323 struct dm_regulator_uclass_plat *uc_pdata =
324 dev_get_uclass_plat(dev);
325 u32 adr = uc_pdata->ctrl_reg;
326 int idx = dev->driver_data;
327 int val, hex, ret;
328
329 val = pmic_reg_read(dev->parent, adr);
330 if (val < 0)
331 return val;
332
333 if (op == PMIC_OP_GET) {
334 *uV = 0;
335 val &= TPS65911_LDO_SEL_MASK;
336
337 ret = tps65911_ldo_hex2volt(idx, val >> 2);
338 if (ret < 0)
339 return ret;
340
341 *uV = ret;
342 return 0;
343 }
344
345 hex = tps65911_ldo_volt2hex(idx, *uV);
346 if (hex < 0)
347 return hex;
348
349 val &= ~TPS65911_LDO_SEL_MASK;
350
351 return pmic_reg_write(dev->parent, adr, val | hex);
352}
353
354static int tps65911_ldo_probe(struct udevice *dev)
355{
356 struct dm_regulator_uclass_plat *uc_pdata =
357 dev_get_uclass_plat(dev);
358 u8 idx = dev->driver_data - 1;
359
360 uc_pdata->type = REGULATOR_TYPE_LDO;
361 uc_pdata->ctrl_reg = tps65911_ldo_reg[idx];
362
363 return 0;
364}
365
366static int ldo_get_value(struct udevice *dev)
367{
368 int uV;
369 int ret;
370
371 ret = tps65911_ldo_val(dev, PMIC_OP_GET, &uV);
372 if (ret)
373 return ret;
374
375 return uV;
376}
377
378static int ldo_set_value(struct udevice *dev, int uV)
379{
380 return tps65911_ldo_val(dev, PMIC_OP_SET, &uV);
381}
382
383static const struct dm_regulator_ops tps65911_ldo_ops = {
384 .get_value = ldo_get_value,
385 .set_value = ldo_set_value,
386 .get_enable = tps65911_get_enable,
387 .set_enable = tps65911_set_enable,
388};
389
390U_BOOT_DRIVER(tps65911_ldo) = {
391 .name = TPS65911_LDO_DRIVER,
392 .id = UCLASS_REGULATOR,
393 .ops = &tps65911_ldo_ops,
394 .probe = tps65911_ldo_probe,
395};