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