blob: 75cdbca30f621166b9d31791b4ab0c0642796e30 [file] [log] [blame]
Samuel Holland8de2c0c2023-01-21 17:13:05 -06001// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2/*
3 * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
4 * Copyright (c) 2018-2023 Samuel Holland <samuel@sholland.org>
5 */
6
7#include <axp_pmic.h>
8#include <dm.h>
9#include <errno.h>
10#include <dm/device-internal.h>
11#include <power/pmic.h>
12#include <power/regulator.h>
13
14#define NA 0xff
15
16struct axp_regulator_plat {
17 const char *name;
18 u8 enable_reg;
19 u8 enable_mask;
20 u8 volt_reg;
21 u8 volt_mask;
22 u16 min_mV;
23 u16 max_mV;
24 u8 step_mV;
25 u8 split;
26 const u16 *table;
27};
28
29static int axp_regulator_get_value(struct udevice *dev)
30{
31 const struct axp_regulator_plat *plat = dev_get_plat(dev);
32 int mV, sel;
33
34 if (plat->volt_reg == NA)
35 return -EINVAL;
36
37 sel = pmic_reg_read(dev->parent, plat->volt_reg);
38 if (sel < 0)
39 return sel;
40
41 sel &= plat->volt_mask;
42 sel >>= ffs(plat->volt_mask) - 1;
43
44 if (plat->table) {
45 mV = plat->table[sel];
46 } else {
47 if (sel > plat->split)
48 sel = plat->split + (sel - plat->split) * 2;
49 mV = plat->min_mV + sel * plat->step_mV;
50 }
51
52 return mV * 1000;
53}
54
55static int axp_regulator_set_value(struct udevice *dev, int uV)
56{
57 const struct axp_regulator_plat *plat = dev_get_plat(dev);
58 int mV = uV / 1000;
59 uint sel, shift;
60
61 if (plat->volt_reg == NA)
62 return -EINVAL;
63 if (mV < plat->min_mV || mV > plat->max_mV)
64 return -EINVAL;
65
66 shift = ffs(plat->volt_mask) - 1;
67
68 if (plat->table) {
69 /*
70 * The table must be monotonically increasing and
71 * have an entry for each possible field value.
72 */
73 sel = plat->volt_mask >> shift;
74 while (sel && plat->table[sel] > mV)
75 sel--;
76 } else {
77 sel = (mV - plat->min_mV) / plat->step_mV;
78 if (sel > plat->split)
79 sel = plat->split + (sel - plat->split) / 2;
80 }
81
82 return pmic_clrsetbits(dev->parent, plat->volt_reg,
83 plat->volt_mask, sel << shift);
84}
85
86static int axp_regulator_get_enable(struct udevice *dev)
87{
88 const struct axp_regulator_plat *plat = dev_get_plat(dev);
89 int reg;
90
91 reg = pmic_reg_read(dev->parent, plat->enable_reg);
92 if (reg < 0)
93 return reg;
94
95 return (reg & plat->enable_mask) == plat->enable_mask;
96}
97
98static int axp_regulator_set_enable(struct udevice *dev, bool enable)
99{
100 const struct axp_regulator_plat *plat = dev_get_plat(dev);
101
102 return pmic_clrsetbits(dev->parent, plat->enable_reg,
103 plat->enable_mask,
104 enable ? plat->enable_mask : 0);
105}
106
107static const struct dm_regulator_ops axp_regulator_ops = {
108 .get_value = axp_regulator_get_value,
109 .set_value = axp_regulator_set_value,
110 .get_enable = axp_regulator_get_enable,
111 .set_enable = axp_regulator_set_enable,
112};
113
114static const u16 axp152_dcdc1_table[] = {
115 1700, 1800, 1900, 2000, 2100, 2400, 2500, 2600,
116 2700, 2800, 3000, 3100, 3200, 3300, 3400, 3500,
117};
118
119static const u16 axp152_aldo12_table[] = {
120 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900,
121 2000, 2500, 2700, 2800, 3000, 3100, 3200, 3300,
122};
123
124static const u16 axp152_ldo0_table[] = {
125 5000, 3300, 2800, 2500,
126};
127
128static const struct axp_regulator_plat axp152_regulators[] = {
129 { "dcdc1", 0x12, BIT(7), 0x26, 0x0f, .table = axp152_dcdc1_table },
130 { "dcdc2", 0x12, BIT(6), 0x23, 0x3f, 700, 2275, 25, NA },
131 { "dcdc3", 0x12, BIT(5), 0x27, 0x3f, 700, 3500, 50, NA },
132 { "dcdc4", 0x12, BIT(4), 0x2b, 0x7f, 700, 3500, 25, NA },
133 { "aldo1", 0x12, BIT(3), 0x28, 0xf0, .table = axp152_aldo12_table },
134 { "aldo2", 0x12, BIT(2), 0x28, 0x0f, .table = axp152_aldo12_table },
135 { "dldo1", 0x12, BIT(1), 0x29, 0x1f, 700, 3500, 100, NA },
136 { "dldo2", 0x12, BIT(0), 0x2a, 0x1f, 700, 3500, 100, NA },
137 { "ldo0", 0x15, BIT(7), 0x15, 0x30, .table = axp152_ldo0_table },
138 { }
139};
140
141static const u16 axp20x_ldo4_table[] = {
142 1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900,
143 2000, 2500, 2700, 2800, 3000, 3100, 3200, 3300,
144};
145
146static const struct axp_regulator_plat axp20x_regulators[] = {
147 { "dcdc2", 0x12, BIT(4), 0x23, 0x3f, 700, 2275, 25, NA },
148 { "dcdc3", 0x12, BIT(1), 0x27, 0x7f, 700, 3500, 25, NA },
149 { "ldo2", 0x12, BIT(2), 0x28, 0xf0, 1800, 3300, 100, NA },
150 { "ldo3", 0x12, BIT(6), 0x29, 0x7f, 700, 2275, 25, NA },
151 { "ldo4", 0x12, BIT(3), 0x28, 0x0f, .table = axp20x_ldo4_table },
152 { }
153};
154
155static const struct axp_regulator_plat axp22x_regulators[] = {
156 {"dc5ldo", 0x10, BIT(0), 0x1c, 0x07, 700, 1400, 100, NA },
157 { "dcdc1", 0x10, BIT(1), 0x21, 0x1f, 1600, 3400, 100, NA },
158 { "dcdc2", 0x10, BIT(2), 0x22, 0x3f, 600, 1540, 20, NA },
159 { "dcdc3", 0x10, BIT(3), 0x23, 0x3f, 600, 1860, 20, NA },
160 { "dcdc4", 0x10, BIT(4), 0x24, 0x3f, 600, 1540, 20, NA },
161 { "dcdc5", 0x10, BIT(5), 0x25, 0x1f, 1000, 2550, 50, NA },
162 { "aldo1", 0x10, BIT(6), 0x28, 0x1f, 700, 3300, 100, NA },
163 { "aldo2", 0x10, BIT(7), 0x29, 0x1f, 700, 3300, 100, NA },
164 { "aldo3", 0x13, BIT(7), 0x2a, 0x1f, 700, 3300, 100, NA },
165 { "dldo1", 0x12, BIT(3), 0x15, 0x1f, 700, 3300, 100, NA },
166 { "dldo2", 0x12, BIT(4), 0x16, 0x1f, 700, 3300, 100, NA },
167 { "dldo3", 0x12, BIT(5), 0x17, 0x1f, 700, 3300, 100, NA },
168 { "dldo4", 0x12, BIT(6), 0x18, 0x1f, 700, 3300, 100, NA },
169 { "eldo1", 0x12, BIT(0), 0x19, 0x1f, 700, 3300, 100, NA },
170 { "eldo2", 0x12, BIT(1), 0x1a, 0x1f, 700, 3300, 100, NA },
171 { "eldo3", 0x12, BIT(2), 0x1b, 0x1f, 700, 3300, 100, NA },
172 { "dc1sw", 0x12, BIT(7), NA, NA, NA, NA, NA, NA },
173 { }
174};
175
Andre Przywara943afa72023-10-17 14:12:44 +0100176/*
177 * The "dcdc1" regulator has another range, beyond 1.54V up to 3.4V, in
178 * steps of 100mV. We cannot model this easily, but also don't need that,
179 * since it's typically only used for ~1.1V anyway, so just ignore it.
180 * Also the DCDC3 regulator is described wrongly in the (available) manual,
181 * experiments show that the split point is at 1200mV, as for DCDC1/2.
182 */
183static const struct axp_regulator_plat axp313_regulators[] = {
184 { "dcdc1", 0x10, BIT(0), 0x13, 0x7f, 500, 1540, 10, 70 },
185 { "dcdc2", 0x10, BIT(1), 0x14, 0x7f, 500, 1540, 10, 70 },
186 { "dcdc3", 0x10, BIT(2), 0x15, 0x7f, 500, 1840, 10, 70 },
187 { "aldo1", 0x10, BIT(3), 0x16, 0x1f, 500, 3500, 100, NA },
188 { "dldo1", 0x10, BIT(4), 0x17, 0x1f, 500, 3500, 100, NA },
189 { }
190};
191
Andre Przywaracaf9f722024-05-10 00:43:19 +0100192/*
193 * The "dcdc2" regulator has another range, beyond 1.54V up to 3.4V, in
194 * steps of 100mV. We cannot model this easily, but also don't need that,
195 * since it's typically only used for lower voltages anyway, so just ignore it.
196 */
197static const struct axp_regulator_plat axp717_regulators[] = {
198 { "dcdc1", 0x80, BIT(0), 0x83, 0x7f, 500, 1540, 10, 70 },
199 { "dcdc2", 0x80, BIT(1), 0x84, 0x7f, 500, 1540, 10, 70 },
200 { "dcdc3", 0x80, BIT(2), 0x85, 0x7f, 500, 1840, 10, 70 },
201 { "dcdc4", 0x80, BIT(3), 0x86, 0x7f, 1000, 3700, 100, NA },
202 { "aldo1", 0x90, BIT(0), 0x93, 0x1f, 500, 3500, 100, NA },
203 { "aldo2", 0x90, BIT(1), 0x94, 0x1f, 500, 3500, 100, NA },
204 { "aldo3", 0x90, BIT(2), 0x95, 0x1f, 500, 3500, 100, NA },
205 { "aldo4", 0x90, BIT(3), 0x96, 0x1f, 500, 3500, 100, NA },
206 { "bldo1", 0x90, BIT(4), 0x97, 0x1f, 500, 3500, 100, NA },
207 { "bldo2", 0x90, BIT(5), 0x98, 0x1f, 500, 3500, 100, NA },
208 { "bldo3", 0x90, BIT(6), 0x99, 0x1f, 500, 3500, 100, NA },
209 { "bldo4", 0x90, BIT(7), 0x9a, 0x1f, 500, 3500, 100, NA },
210 { "cldo1", 0x91, BIT(0), 0x9b, 0x1f, 500, 3500, 100, NA },
211 { "cldo2", 0x91, BIT(1), 0x9c, 0x1f, 500, 3500, 100, NA },
212 { "cldo3", 0x91, BIT(2), 0x9d, 0x1f, 500, 3500, 100, NA },
213 { "cldo4", 0x91, BIT(3), 0x9e, 0x1f, 500, 3500, 100, NA },
214 {"cpusldo",0x91, BIT(4), 0x9f, 0x1f, 500, 1400, 50, NA },
215 {" boost", 0x19, BIT(4), 0x1e, 0xf0, 4550, 5510, 64, NA },
216 { }
217};
218
Samuel Holland8de2c0c2023-01-21 17:13:05 -0600219static const struct axp_regulator_plat axp803_regulators[] = {
220 { "dcdc1", 0x10, BIT(0), 0x20, 0x1f, 1600, 3400, 100, NA },
221 { "dcdc2", 0x10, BIT(1), 0x21, 0x7f, 500, 1300, 10, 70 },
222 { "dcdc3", 0x10, BIT(2), 0x22, 0x7f, 500, 1300, 10, 70 },
223 { "dcdc4", 0x10, BIT(3), 0x23, 0x7f, 500, 1300, 10, 70 },
224 { "dcdc5", 0x10, BIT(4), 0x24, 0x7f, 800, 1840, 10, 32 },
225 { "dcdc6", 0x10, BIT(5), 0x25, 0x7f, 600, 1520, 10, 50 },
226 { "aldo1", 0x13, BIT(5), 0x28, 0x1f, 700, 3300, 100, NA },
227 { "aldo2", 0x13, BIT(6), 0x29, 0x1f, 700, 3300, 100, NA },
228 { "aldo3", 0x13, BIT(7), 0x2a, 0x1f, 700, 3300, 100, NA },
229 { "dldo1", 0x12, BIT(3), 0x15, 0x1f, 700, 3300, 100, NA },
230 { "dldo2", 0x12, BIT(4), 0x16, 0x1f, 700, 4200, 100, 27 },
231 { "dldo3", 0x12, BIT(5), 0x17, 0x1f, 700, 3300, 100, NA },
232 { "dldo4", 0x12, BIT(6), 0x18, 0x1f, 700, 3300, 100, NA },
233 { "eldo1", 0x12, BIT(0), 0x19, 0x1f, 700, 1900, 50, NA },
234 { "eldo2", 0x12, BIT(1), 0x1a, 0x1f, 700, 1900, 50, NA },
235 { "eldo3", 0x12, BIT(2), 0x1b, 0x1f, 700, 1900, 50, NA },
236 { "fldo1", 0x13, BIT(2), 0x1c, 0x0f, 700, 1450, 50, NA },
237 { "fldo2", 0x13, BIT(3), 0x1d, 0x0f, 700, 1450, 50, NA },
238 { "dc1sw", 0x12, BIT(7), NA, NA, NA, NA, NA, NA },
239 { }
240};
241
242/*
243 * The "dcdcd" split changes the step size by a factor of 5, not 2;
244 * disallow values above the split to maintain accuracy.
245 */
246static const struct axp_regulator_plat axp806_regulators[] = {
247 { "dcdca", 0x10, BIT(0), 0x12, 0x7f, 600, 1520, 10, 50 },
248 { "dcdcb", 0x10, BIT(1), 0x13, 0x1f, 1000, 2550, 50, NA },
249 { "dcdcc", 0x10, BIT(2), 0x14, 0x7f, 600, 1520, 10, 50 },
250 { "dcdcd", 0x10, BIT(3), 0x15, 0x3f, 600, 1500, 20, NA },
251 { "dcdce", 0x10, BIT(4), 0x16, 0x1f, 1100, 3400, 100, NA },
252 { "aldo1", 0x10, BIT(5), 0x17, 0x1f, 700, 3300, 100, NA },
253 { "aldo2", 0x10, BIT(6), 0x18, 0x1f, 700, 3300, 100, NA },
254 { "aldo3", 0x10, BIT(7), 0x19, 0x1f, 700, 3300, 100, NA },
255 { "bldo1", 0x11, BIT(0), 0x20, 0x0f, 700, 1900, 100, NA },
256 { "bldo2", 0x11, BIT(1), 0x21, 0x0f, 700, 1900, 100, NA },
257 { "bldo3", 0x11, BIT(2), 0x22, 0x0f, 700, 1900, 100, NA },
258 { "bldo4", 0x11, BIT(3), 0x23, 0x0f, 700, 1900, 100, NA },
259 { "cldo1", 0x11, BIT(4), 0x24, 0x1f, 700, 3300, 100, NA },
260 { "cldo2", 0x11, BIT(5), 0x25, 0x1f, 700, 4200, 100, 27 },
261 { "cldo3", 0x11, BIT(6), 0x26, 0x1f, 700, 3300, 100, NA },
262 { "sw", 0x11, BIT(7), NA, NA, NA, NA, NA, NA },
263 { }
264};
265
266/*
267 * The "dcdc4" split changes the step size by a factor of 5, not 2;
268 * disallow values above the split to maintain accuracy.
269 */
270static const struct axp_regulator_plat axp809_regulators[] = {
271 {"dc5ldo", 0x10, BIT(0), 0x1c, 0x07, 700, 1400, 100, NA },
272 { "dcdc1", 0x10, BIT(1), 0x21, 0x1f, 1600, 3400, 100, NA },
273 { "dcdc2", 0x10, BIT(2), 0x22, 0x3f, 600, 1540, 20, NA },
274 { "dcdc3", 0x10, BIT(3), 0x23, 0x3f, 600, 1860, 20, NA },
275 { "dcdc4", 0x10, BIT(4), 0x24, 0x3f, 600, 1540, 20, NA },
276 { "dcdc5", 0x10, BIT(5), 0x25, 0x1f, 1000, 2550, 50, NA },
277 { "aldo1", 0x10, BIT(6), 0x28, 0x1f, 700, 3300, 100, NA },
278 { "aldo2", 0x10, BIT(7), 0x29, 0x1f, 700, 3300, 100, NA },
279 { "aldo3", 0x12, BIT(5), 0x2a, 0x1f, 700, 3300, 100, NA },
280 { "dldo1", 0x12, BIT(3), 0x15, 0x1f, 700, 3300, 100, NA },
281 { "dldo2", 0x12, BIT(4), 0x16, 0x1f, 700, 3300, 100, NA },
282 { "eldo1", 0x12, BIT(0), 0x19, 0x1f, 700, 3300, 100, NA },
283 { "eldo2", 0x12, BIT(1), 0x1a, 0x1f, 700, 3300, 100, NA },
284 { "eldo3", 0x12, BIT(2), 0x1b, 0x1f, 700, 3300, 100, NA },
285 { "sw", 0x12, BIT(6), NA, NA, NA, NA, NA, NA },
286 { "dc1sw", 0x12, BIT(7), NA, NA, NA, NA, NA, NA },
287 { }
288};
289
290static const struct axp_regulator_plat axp813_regulators[] = {
291 { "dcdc1", 0x10, BIT(0), 0x20, 0x1f, 1600, 3400, 100, NA },
292 { "dcdc2", 0x10, BIT(1), 0x21, 0x7f, 500, 1300, 10, 70 },
293 { "dcdc3", 0x10, BIT(2), 0x22, 0x7f, 500, 1300, 10, 70 },
294 { "dcdc4", 0x10, BIT(3), 0x23, 0x7f, 500, 1300, 10, 70 },
295 { "dcdc5", 0x10, BIT(4), 0x24, 0x7f, 800, 1840, 10, 32 },
296 { "dcdc6", 0x10, BIT(5), 0x25, 0x7f, 600, 1520, 10, 50 },
297 { "dcdc7", 0x10, BIT(6), 0x26, 0x7f, 600, 1520, 10, 50 },
298 { "aldo1", 0x13, BIT(5), 0x28, 0x1f, 700, 3300, 100, NA },
299 { "aldo2", 0x13, BIT(6), 0x29, 0x1f, 700, 3300, 100, NA },
300 { "aldo3", 0x13, BIT(7), 0x2a, 0x1f, 700, 3300, 100, NA },
301 { "dldo1", 0x12, BIT(3), 0x15, 0x1f, 700, 3300, 100, NA },
302 { "dldo2", 0x12, BIT(4), 0x16, 0x1f, 700, 4200, 100, 27 },
303 { "dldo3", 0x12, BIT(5), 0x17, 0x1f, 700, 3300, 100, NA },
304 { "dldo4", 0x12, BIT(6), 0x18, 0x1f, 700, 3300, 100, NA },
305 { "eldo1", 0x12, BIT(0), 0x19, 0x1f, 700, 1900, 50, NA },
306 { "eldo2", 0x12, BIT(1), 0x1a, 0x1f, 700, 1900, 50, NA },
307 { "eldo3", 0x12, BIT(2), 0x1b, 0x1f, 700, 1900, 50, NA },
308 { "fldo1", 0x13, BIT(2), 0x1c, 0x0f, 700, 1450, 50, NA },
309 { "fldo2", 0x13, BIT(3), 0x1d, 0x0f, 700, 1450, 50, NA },
310 { "fldo3", 0x13, BIT(4), NA, NA, NA, NA, NA, NA },
311 { }
312};
313
314static const struct axp_regulator_plat *const axp_regulators[] = {
315 [AXP152_ID] = axp152_regulators,
316 [AXP202_ID] = axp20x_regulators,
317 [AXP209_ID] = axp20x_regulators,
318 [AXP221_ID] = axp22x_regulators,
319 [AXP223_ID] = axp22x_regulators,
Andre Przywara943afa72023-10-17 14:12:44 +0100320 [AXP313_ID] = axp313_regulators,
Andre Przywaracaf9f722024-05-10 00:43:19 +0100321 [AXP717_ID] = axp717_regulators,
Samuel Holland8de2c0c2023-01-21 17:13:05 -0600322 [AXP803_ID] = axp803_regulators,
323 [AXP806_ID] = axp806_regulators,
324 [AXP809_ID] = axp809_regulators,
325 [AXP813_ID] = axp813_regulators,
326};
327
328static int axp_regulator_bind(struct udevice *dev)
329{
330 struct dm_regulator_uclass_plat *uc_plat = dev_get_uclass_plat(dev);
331 ulong id = dev_get_driver_data(dev->parent);
332 const struct axp_regulator_plat *plat;
333
334 for (plat = axp_regulators[id]; plat && plat->name; plat++)
335 if (!strcmp(plat->name, dev->name))
336 break;
337 if (!plat || !plat->name)
338 return -ENODEV;
339
340 dev_set_plat(dev, (void *)plat);
341
342 if (plat->volt_reg == NA)
343 uc_plat->type = REGULATOR_TYPE_FIXED;
344 else if (!strncmp(plat->name, "dcdc", strlen("dcdc")))
345 uc_plat->type = REGULATOR_TYPE_BUCK;
346 else
347 uc_plat->type = REGULATOR_TYPE_LDO;
348
349 return 0;
350}
351
352U_BOOT_DRIVER(axp_regulator) = {
353 .name = "axp_regulator",
354 .id = UCLASS_REGULATOR,
355 .bind = axp_regulator_bind,
356 .ops = &axp_regulator_ops,
357};