1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2018 Flowbird
4 * Martin Fuzzey <martin.fuzzey@flowbird.group>
5 */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <linux/bitops.h>
10 #include <power/da9063_pmic.h>
11 #include <power/pmic.h>
12 #include <power/regulator.h>
13
14 #define DA9063_BUCK_EN 0x01
15 #define DA9063_LDO_EN 0x01
16 #define DA9063_VBUCK_MASK 0x7F
17 #define DA9063_BUCK_SL 0x80
18 #define DA9063_LDO_SL 0x80
19
20 #define DA9063_VLDO1_MASK 0x3F
21 #define DA9063_VLDO2_MASK 0x3F
22 #define DA9063_VLDO3_MASK 0x7F
23 #define DA9063_VLDO4_MASK 0x7F
24 #define DA9063_VLDO5_MASK 0x3F
25 #define DA9063_VLDO6_MASK 0x3F
26 #define DA9063_VLDO7_MASK 0x3F
27 #define DA9063_VLDO8_MASK 0x3F
28 #define DA9063_VLDO9_MASK 0x3F
29 #define DA9063_VLDO10_MASK 0x3F
30 #define DA9063_VLDO11_MASK 0x3F
31
32 #define DA9063_BUCK_MODE_MASK 0xC0
33 #define DA9063_BUCK_MODE_MANUAL 0x00
34 #define DA9063_BUCK_MODE_SLEEP 0x40
35 #define DA9063_BUCK_MODE_SYNC 0x80
36 #define DA9063_BUCK_MODE_AUTO 0xC0
37
38 #define DA9063_BIO_ILIM_MASK 0x0F
39 #define DA9063_BMEM_ILIM_MASK 0xF0
40 #define DA9063_BPRO_ILIM_MASK 0x0F
41 #define DA9063_BPERI_ILIM_MASK 0xF0
42 #define DA9063_BCORE1_ILIM_MASK 0x0F
43 #define DA9063_BCORE2_ILIM_MASK 0xF0
44
45 struct da9063_reg_info {
46 uint min_uV;
47 uint step_uV;
48 uint max_uV;
49 uint min_uA;
50 uint step_uA;
51 uint max_uA;
52 uint en_reg;
53 uint vsel_reg;
54 uint mode_reg;
55 uint ilim_reg;
56 u8 en_mask;
57 u8 vsel_mask;
58 u8 ilim_mask;
59 const char *dt_node_name;
60 const int *current_limits;
61 };
62
63 struct da9063_priv {
64 const struct da9063_reg_info *reg_info;
65 };
66
67 static struct dm_regulator_mode da9063_ldo_modes[] = {
68 { .id = DA9063_LDOMODE_SLEEP,
69 .register_value = DA9063_LDO_SL, .name = "SLEEP" },
70 { .id = DA9063_LDOMODE_NORMAL,
71 .register_value = 0, .name = "NORMAL" },
72 };
73
74 #define DA9063_LDO(regl_name, min_mV, step_mV, max_mV) \
75 .min_uV = (min_mV) * 1000, \
76 .step_uV = (step_mV) * 1000, \
77 .max_uV = (max_mV) * 1000, \
78 .en_reg = DA9063_REG_##regl_name##_CONT, \
79 .en_mask = DA9063_LDO_EN, \
80 .vsel_reg = DA9063_REG_V##regl_name##_A, \
81 .vsel_mask = DA9063_V##regl_name##_MASK, \
82 .mode_reg = DA9063_REG_V##regl_name##_A \
83
84 /* This array is directly indexed so must stay in numerical order */
85 static const struct da9063_reg_info da9063_ldo_info[] = {
86 { DA9063_LDO(LDO1, 600, 20, 1860) },
87 { DA9063_LDO(LDO2, 600, 20, 1860) },
88 { DA9063_LDO(LDO3, 900, 20, 3440) },
89 { DA9063_LDO(LDO4, 900, 20, 3440) },
90 { DA9063_LDO(LDO5, 900, 50, 3600) },
91 { DA9063_LDO(LDO6, 900, 50, 3600) },
92 { DA9063_LDO(LDO7, 900, 50, 3600) },
93 { DA9063_LDO(LDO8, 900, 50, 3600) },
94 { DA9063_LDO(LDO9, 950, 50, 3600) },
95 { DA9063_LDO(LDO10, 900, 50, 3600) },
96 { DA9063_LDO(LDO11, 900, 50, 3600) },
97 };
98
99 static struct dm_regulator_mode da9063_buck_modes[] = {
100 { .id = DA9063_BUCKMODE_SLEEP,
101 .register_value = DA9063_BUCK_MODE_SLEEP, .name = "SLEEP" },
102 { .id = DA9063_BUCKMODE_SYNC,
103 .register_value = DA9063_BUCK_MODE_SYNC, .name = "SYNC" },
104 { .id = DA9063_BUCKMODE_AUTO,
105 .register_value = DA9063_BUCK_MODE_AUTO, .name = "AUTO" },
106 };
107
108 #define DA9063_BUCK(regl_name, dt_name, \
109 min_mV, step_mV, max_mV, \
110 min_mA, step_mA, max_mA, _ilim_reg) \
111 .dt_node_name = dt_name, \
112 .min_uV = (min_mV) * 1000, \
113 .step_uV = (step_mV) * 1000, \
114 .max_uV = (max_mV) * 1000, \
115 .min_uA = (min_mA) * 1000, \
116 .step_uA = (step_mA) * 1000, \
117 .max_uA = (max_mA) * 1000, \
118 .en_reg = DA9063_REG_##regl_name##_CONT, \
119 .en_mask = DA9063_BUCK_EN, \
120 .vsel_reg = DA9063_REG_V##regl_name##_A, \
121 .vsel_mask = DA9063_VBUCK_MASK, \
122 .mode_reg = DA9063_REG_##regl_name##_CFG, \
123 .ilim_reg = DA9063_REG_BUCK_ILIM_##_ilim_reg, \
124 .ilim_mask = DA9063_##regl_name##_ILIM_MASK
125
126 static const struct da9063_reg_info da9063_buck_info[] = {
127 /* mV mA */
128 { DA9063_BUCK(BCORE1, "bcore1", 300, 10, 1570, 500, 100, 2000, C) },
129 { DA9063_BUCK(BCORE2, "bcore2", 300, 10, 1570, 500, 100, 2000, C) },
130 { DA9063_BUCK(BPRO, "bpro", 530, 10, 1800, 500, 100, 2000, B) },
131 { DA9063_BUCK(BMEM, "bmem", 800, 20, 3340, 1500, 100, 3000, A) },
132 { DA9063_BUCK(BIO, "bio", 800, 20, 3340, 1500, 100, 3000, A) },
133 { DA9063_BUCK(BPERI, "bperi", 800, 20, 3340, 1500, 100, 3000, B) },
134 };
135
da9063_get_enable(struct udevice * dev)136 static int da9063_get_enable(struct udevice *dev)
137 {
138 const struct da9063_priv *priv = dev_get_priv(dev);
139 const struct da9063_reg_info *info = priv->reg_info;
140 int ret;
141
142 ret = pmic_reg_read(dev->parent, info->en_reg);
143 if (ret < 0)
144 return ret;
145
146 return ret & info->en_mask ? true : false;
147 }
148
da9063_set_enable(struct udevice * dev,bool enable)149 static int da9063_set_enable(struct udevice *dev, bool enable)
150 {
151 const struct da9063_priv *priv = dev_get_priv(dev);
152 const struct da9063_reg_info *info = priv->reg_info;
153
154 return pmic_clrsetbits(dev->parent, info->en_reg,
155 info->en_mask, enable ? info->en_mask : 0);
156 }
157
da9063_get_voltage(struct udevice * dev)158 static int da9063_get_voltage(struct udevice *dev)
159 {
160 const struct da9063_priv *priv = dev_get_priv(dev);
161 const struct da9063_reg_info *info = priv->reg_info;
162 int ret;
163
164 ret = pmic_reg_read(dev->parent, info->vsel_reg);
165 if (ret < 0)
166 return ret;
167
168 return info->min_uV + (ret & info->vsel_mask) * info->step_uV;
169 }
170
da9063_set_voltage(struct udevice * dev,int uV)171 static int da9063_set_voltage(struct udevice *dev, int uV)
172 {
173 const struct da9063_priv *priv = dev_get_priv(dev);
174 const struct da9063_reg_info *info = priv->reg_info;
175 uint sel;
176
177 if (uV < info->min_uV || uV > info->max_uV)
178 return -EINVAL;
179
180 sel = (uV - info->min_uV) / info->step_uV;
181
182 return pmic_clrsetbits(dev->parent, info->vsel_reg,
183 info->vsel_mask, sel);
184 }
185
186 static const struct dm_regulator_mode
da9063_find_mode_by_id(int id,const struct dm_regulator_mode * modes,uint mode_count)187 *da9063_find_mode_by_id(int id,
188 const struct dm_regulator_mode *modes,
189 uint mode_count)
190 {
191 for (; mode_count; mode_count--) {
192 if (modes->id == id)
193 return modes;
194 modes++;
195 }
196 return NULL;
197 }
198
ldo_get_mode(struct udevice * dev)199 static int ldo_get_mode(struct udevice *dev)
200 {
201 const struct da9063_priv *priv = dev_get_priv(dev);
202 const struct da9063_reg_info *info = priv->reg_info;
203 int val;
204
205 val = pmic_reg_read(dev->parent, info->mode_reg);
206 if (val < 0)
207 return val;
208
209 if (val & DA9063_LDO_SL)
210 return DA9063_LDOMODE_SLEEP;
211 else
212 return DA9063_LDOMODE_NORMAL;
213 }
214
ldo_set_mode(struct udevice * dev,int mode_id)215 static int ldo_set_mode(struct udevice *dev, int mode_id)
216 {
217 const struct da9063_priv *priv = dev_get_priv(dev);
218 const struct da9063_reg_info *info = priv->reg_info;
219 const struct dm_regulator_mode *mode;
220
221 mode = da9063_find_mode_by_id(mode_id,
222 da9063_ldo_modes,
223 ARRAY_SIZE(da9063_ldo_modes));
224 if (!mode)
225 return -EINVAL;
226
227 return pmic_clrsetbits(dev->parent, info->mode_reg,
228 DA9063_LDO_SL, mode->register_value);
229 }
230
buck_get_mode(struct udevice * dev)231 static int buck_get_mode(struct udevice *dev)
232 {
233 const struct da9063_priv *priv = dev_get_priv(dev);
234 const struct da9063_reg_info *info = priv->reg_info;
235 int i;
236 int val;
237
238 val = pmic_reg_read(dev->parent, info->mode_reg);
239 if (val < 0)
240 return val;
241
242 val &= DA9063_BUCK_MODE_MASK;
243 if (val == DA9063_BUCK_MODE_MANUAL) {
244 val = pmic_reg_read(dev->parent, info->vsel_reg);
245 if (val < 0)
246 return val;
247
248 if (val & DA9063_BUCK_SL)
249 return DA9063_BUCKMODE_SLEEP;
250 else
251 return DA9063_BUCKMODE_SYNC;
252 }
253
254 for (i = 0; i < ARRAY_SIZE(da9063_buck_modes); i++) {
255 if (da9063_buck_modes[i].register_value == val)
256 return da9063_buck_modes[i].id;
257 }
258
259 return -EINVAL;
260 }
261
buck_set_mode(struct udevice * dev,int mode_id)262 static int buck_set_mode(struct udevice *dev, int mode_id)
263 {
264 const struct da9063_priv *priv = dev_get_priv(dev);
265 const struct da9063_reg_info *info = priv->reg_info;
266 const struct dm_regulator_mode *mode;
267
268 mode = da9063_find_mode_by_id(mode_id,
269 da9063_buck_modes,
270 ARRAY_SIZE(da9063_buck_modes));
271 if (!mode)
272 return -EINVAL;
273
274 return pmic_clrsetbits(dev->parent, info->mode_reg,
275 DA9063_BUCK_MODE_MASK, mode->register_value);
276 }
277
buck_get_current_limit(struct udevice * dev)278 static int buck_get_current_limit(struct udevice *dev)
279 {
280 const struct da9063_priv *priv = dev_get_priv(dev);
281 const struct da9063_reg_info *info = priv->reg_info;
282 int val;
283
284 val = pmic_reg_read(dev->parent, info->ilim_reg);
285 if (val < 0)
286 return val;
287
288 val &= info->ilim_mask;
289 val >>= (ffs(info->ilim_mask) - 1);
290
291 return info->min_uA + val * info->step_uA;
292 }
293
buck_set_current_limit(struct udevice * dev,int uA)294 static int buck_set_current_limit(struct udevice *dev, int uA)
295 {
296 const struct da9063_priv *priv = dev_get_priv(dev);
297 const struct da9063_reg_info *info = priv->reg_info;
298 int val;
299
300 if (uA < info->min_uA || uA > info->max_uA)
301 return -EINVAL;
302
303 val = (uA - info->min_uA) / info->step_uA;
304 val <<= (ffs(info->ilim_mask) - 1);
305
306 return pmic_clrsetbits(dev->parent, info->ilim_reg,
307 info->ilim_mask, val);
308 }
309
da9063_ldo_probe(struct udevice * dev)310 static int da9063_ldo_probe(struct udevice *dev)
311 {
312 struct dm_regulator_uclass_plat *uc_pdata;
313 struct da9063_priv *priv = dev_get_priv(dev);
314
315 /* LDOs are named numerically in DT so can directly index */
316 if (dev->driver_data < 1 ||
317 dev->driver_data > ARRAY_SIZE(da9063_ldo_info))
318 return -EINVAL;
319 priv->reg_info = &da9063_ldo_info[dev->driver_data - 1];
320
321 uc_pdata = dev_get_uclass_plat(dev);
322 uc_pdata->type = REGULATOR_TYPE_LDO;
323 uc_pdata->mode = da9063_ldo_modes;
324 uc_pdata->mode_count = ARRAY_SIZE(da9063_ldo_modes);
325
326 return 0;
327 }
328
da9063_buck_probe(struct udevice * dev)329 static int da9063_buck_probe(struct udevice *dev)
330 {
331 struct dm_regulator_uclass_plat *uc_pdata;
332 struct da9063_priv *priv = dev_get_priv(dev);
333 int i;
334
335 /* Bucks have names rather than numbers so need to match with DT */
336 for (i = 0; i < ARRAY_SIZE(da9063_buck_info); i++) {
337 const struct da9063_reg_info *info = &da9063_buck_info[i];
338
339 if (!strcmp(info->dt_node_name, dev->name)) {
340 priv->reg_info = info;
341 break;
342 }
343 }
344 if (!priv->reg_info)
345 return -ENODEV;
346
347 uc_pdata = dev_get_uclass_plat(dev);
348 uc_pdata->type = REGULATOR_TYPE_BUCK;
349 uc_pdata->mode = da9063_buck_modes;
350 uc_pdata->mode_count = ARRAY_SIZE(da9063_buck_modes);
351
352 return 0;
353 }
354
355 static const struct dm_regulator_ops da9063_ldo_ops = {
356 .get_value = da9063_get_voltage,
357 .set_value = da9063_set_voltage,
358 .get_enable = da9063_get_enable,
359 .set_enable = da9063_set_enable,
360 .get_mode = ldo_get_mode,
361 .set_mode = ldo_set_mode,
362 };
363
364 U_BOOT_DRIVER(da9063_ldo) = {
365 .name = DA9063_LDO_DRIVER,
366 .id = UCLASS_REGULATOR,
367 .ops = &da9063_ldo_ops,
368 .probe = da9063_ldo_probe,
369 .priv_auto = sizeof(struct da9063_priv),
370 };
371
372 static const struct dm_regulator_ops da9063_buck_ops = {
373 .get_value = da9063_get_voltage,
374 .set_value = da9063_set_voltage,
375 .get_enable = da9063_get_enable,
376 .set_enable = da9063_set_enable,
377 .get_mode = buck_get_mode,
378 .set_mode = buck_set_mode,
379 .get_current = buck_get_current_limit,
380 .set_current = buck_set_current_limit,
381 };
382
383 U_BOOT_DRIVER(da9063_buck) = {
384 .name = DA9063_BUCK_DRIVER,
385 .id = UCLASS_REGULATOR,
386 .ops = &da9063_buck_ops,
387 .probe = da9063_buck_probe,
388 .priv_auto = sizeof(struct da9063_priv),
389 };
390