• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2019 ROHM Semiconductors
4  *
5  * ROHM BD71837 regulator driver
6  */
7 
8 #include <common.h>
9 #include <dm.h>
10 #include <power/bd71837.h>
11 #include <power/pmic.h>
12 #include <power/regulator.h>
13 
14 #define HW_STATE_CONTROL 0
15 #define DEBUG
16 
17 /**
18  * struct bd71837_vrange - describe linear range of voltages
19  *
20  * @min_volt:	smallest voltage in range
21  * @step:	how much voltage changes at each selector step
22  * @min_sel:	smallest selector in the range
23  * @max_sel:	maximum selector in the range
24  * @rangeval:	register value used to select this range if selectible
25  *		ranges are supported
26  */
27 struct bd71837_vrange {
28 	unsigned int	min_volt;
29 	unsigned int	step;
30 	u8		min_sel;
31 	u8		max_sel;
32 	u8		rangeval;
33 };
34 
35 /**
36  * struct bd71837_platdata - describe regulator control registers
37  *
38  * @name:	name of the regulator. Used for matching the dt-entry
39  * @enable_reg:	register address used to enable/disable regulator
40  * @enablemask:	register mask used to enable/disable regulator
41  * @volt_reg:	register address used to configure regulator voltage
42  * @volt_mask:	register mask used to configure regulator voltage
43  * @ranges:	pointer to ranges of regulator voltages and matching register
44  *		values
45  * @numranges:	number of voltage ranges pointed by ranges
46  * @rangemask:	mask for selecting used ranges if multiple ranges are supported
47  * @sel_mask:	bit to toggle in order to transfer the register control to SW
48  * @dvs:	whether the voltage can be changed when regulator is enabled
49  */
50 struct bd71837_platdata {
51 	const char		*name;
52 	u8			enable_reg;
53 	u8			enablemask;
54 	u8			volt_reg;
55 	u8			volt_mask;
56 	struct bd71837_vrange	*ranges;
57 	unsigned int		numranges;
58 	u8			rangemask;
59 	u8			sel_mask;
60 	bool			dvs;
61 };
62 
63 #define BD_RANGE(_min, _vstep, _sel_low, _sel_hi, _range_sel) \
64 { \
65 	.min_volt = (_min), .step = (_vstep), .min_sel = (_sel_low), \
66 	.max_sel = (_sel_hi), .rangeval = (_range_sel) \
67 }
68 
69 #define BD_DATA(_name, enreg, enmask, vreg, vmask, _range, rmask, _dvs, sel) \
70 { \
71 	.name = (_name), .enable_reg = (enreg), .enablemask = (enmask), \
72 	.volt_reg = (vreg), .volt_mask = (vmask), .ranges = (_range), \
73 	.numranges = ARRAY_SIZE(_range), .rangemask = (rmask), .dvs = (_dvs), \
74 	.sel_mask = (sel) \
75 }
76 
77 static struct bd71837_vrange dvs_buck_vranges[] = {
78 	BD_RANGE(700000, 10000, 0, 0x3c, 0),
79 	BD_RANGE(1300000, 0, 0x3d, 0x3f, 0),
80 };
81 
82 static struct bd71837_vrange bd71847_buck3_vranges[] = {
83 	BD_RANGE(700000, 100000, 0x00, 0x03, 0),
84 	BD_RANGE(1050000, 50000, 0x04, 0x05, 0),
85 	BD_RANGE(1200000, 150000, 0x06, 0x07, 0),
86 	BD_RANGE(550000, 50000, 0x0, 0x7, 0x40),
87 	BD_RANGE(675000, 100000, 0x0, 0x3, 0x80),
88 	BD_RANGE(1025000, 50000, 0x4, 0x5, 0x80),
89 	BD_RANGE(1175000, 150000, 0x6, 0x7, 0x80),
90 };
91 
92 static struct bd71837_vrange bd71847_buck4_vranges[] = {
93 	BD_RANGE(3000000, 100000, 0x00, 0x03, 0),
94 	BD_RANGE(2600000, 100000, 0x00, 0x03, 40),
95 };
96 
97 static struct bd71837_vrange bd71837_buck5_vranges[] = {
98 	BD_RANGE(700000, 100000, 0, 0x3, 0),
99 	BD_RANGE(1050000, 50000, 0x04, 0x05, 0),
100 	BD_RANGE(1200000, 150000, 0x06, 0x07, 0),
101 	BD_RANGE(675000, 100000, 0x0, 0x3, 0x80),
102 	BD_RANGE(1025000, 50000, 0x04, 0x05, 0x80),
103 	BD_RANGE(1175000, 150000, 0x06, 0x07, 0x80),
104 };
105 
106 static struct bd71837_vrange bd71837_buck6_vranges[] = {
107 	BD_RANGE(3000000, 100000, 0x00, 0x03, 0),
108 };
109 
110 static struct bd71837_vrange nodvs_buck3_vranges[] = {
111 	BD_RANGE(1605000, 90000, 0, 1, 0),
112 	BD_RANGE(1755000, 45000, 2, 4, 0),
113 	BD_RANGE(1905000, 45000, 5, 7, 0),
114 };
115 
116 static struct bd71837_vrange nodvs_buck4_vranges[] = {
117 	BD_RANGE(800000, 10000, 0x00, 0x3C, 0),
118 };
119 
120 static struct bd71837_vrange ldo1_vranges[] = {
121 	BD_RANGE(3000000, 100000, 0x00, 0x03, 0),
122 	BD_RANGE(1600000, 100000, 0x00, 0x03, 0x20),
123 };
124 
125 static struct bd71837_vrange ldo2_vranges[] = {
126 	BD_RANGE(900000, 0, 0, 0, 0),
127 	BD_RANGE(800000, 0, 1, 1, 0),
128 };
129 
130 static struct bd71837_vrange ldo3_vranges[] = {
131 	BD_RANGE(1800000, 100000, 0x00, 0x0f, 0),
132 };
133 
134 static struct bd71837_vrange ldo4_vranges[] = {
135 	BD_RANGE(900000, 100000, 0x00, 0x09, 0),
136 };
137 
138 static struct bd71837_vrange bd71837_ldo5_vranges[] = {
139 	BD_RANGE(1800000, 100000, 0x00, 0x0f, 0),
140 };
141 
142 static struct bd71837_vrange bd71847_ldo5_vranges[] = {
143 	BD_RANGE(1800000, 100000, 0x00, 0x0f, 0),
144 	BD_RANGE(800000, 100000, 0x00, 0x0f, 0x20),
145 };
146 
147 static struct bd71837_vrange ldo6_vranges[] = {
148 	BD_RANGE(900000, 100000, 0x00, 0x09, 0),
149 };
150 
151 static struct bd71837_vrange ldo7_vranges[] = {
152 	BD_RANGE(1800000, 100000, 0x00, 0x0f, 0),
153 };
154 
155 /*
156  * We use enable mask 'HW_STATE_CONTROL' to indicate that this regulator
157  * must not be enabled or disabled by SW. The typical use-case for BD71837
158  * is powering NXP i.MX8. In this use-case we (for now) only allow control
159  * for BUCK3 and BUCK4 which are not boot critical.
160  */
161 static struct bd71837_platdata bd71837_reg_data[] = {
162 /* Bucks 1-4 which support dynamic voltage scaling */
163 	BD_DATA("BUCK1", BD718XX_BUCK1_CTRL, HW_STATE_CONTROL,
164 		BD718XX_BUCK1_VOLT_RUN, DVS_BUCK_RUN_MASK, dvs_buck_vranges, 0,
165 		true, BD718XX_BUCK_SEL),
166 	BD_DATA("BUCK2", BD718XX_BUCK2_CTRL, HW_STATE_CONTROL,
167 		BD718XX_BUCK2_VOLT_RUN, DVS_BUCK_RUN_MASK, dvs_buck_vranges, 0,
168 		true, BD718XX_BUCK_SEL),
169 	BD_DATA("BUCK3", BD71837_BUCK3_CTRL, BD718XX_BUCK_EN,
170 		BD71837_BUCK3_VOLT_RUN, DVS_BUCK_RUN_MASK, dvs_buck_vranges, 0,
171 		true, BD718XX_BUCK_SEL),
172 	BD_DATA("BUCK4", BD71837_BUCK4_CTRL, BD718XX_BUCK_EN,
173 		BD71837_BUCK4_VOLT_RUN, DVS_BUCK_RUN_MASK, dvs_buck_vranges, 0,
174 		true, BD718XX_BUCK_SEL),
175 /* Bucks 5-8 which do not support dynamic voltage scaling */
176 	BD_DATA("BUCK5", BD718XX_1ST_NODVS_BUCK_CTRL, HW_STATE_CONTROL,
177 		BD718XX_1ST_NODVS_BUCK_VOLT, BD718XX_1ST_NODVS_BUCK_MASK,
178 		bd71837_buck5_vranges, 0x80, false, BD718XX_BUCK_SEL),
179 	BD_DATA("BUCK6", BD718XX_2ND_NODVS_BUCK_CTRL, HW_STATE_CONTROL,
180 		BD718XX_2ND_NODVS_BUCK_VOLT, BD71837_BUCK6_MASK,
181 		bd71837_buck6_vranges, 0, false, BD718XX_BUCK_SEL),
182 	BD_DATA("BUCK7", BD718XX_3RD_NODVS_BUCK_CTRL, HW_STATE_CONTROL,
183 		BD718XX_3RD_NODVS_BUCK_VOLT, BD718XX_3RD_NODVS_BUCK_MASK,
184 		nodvs_buck3_vranges, 0, false, BD718XX_BUCK_SEL),
185 	BD_DATA("BUCK8", BD718XX_4TH_NODVS_BUCK_CTRL, HW_STATE_CONTROL,
186 		BD718XX_4TH_NODVS_BUCK_VOLT, BD718XX_4TH_NODVS_BUCK_MASK,
187 		nodvs_buck4_vranges, 0, false, BD718XX_BUCK_SEL),
188 /* LDOs */
189 	BD_DATA("LDO1", BD718XX_LDO1_VOLT, HW_STATE_CONTROL, BD718XX_LDO1_VOLT,
190 		BD718XX_LDO1_MASK, ldo1_vranges, 0x20, false, BD718XX_LDO_SEL),
191 	BD_DATA("LDO2", BD718XX_LDO2_VOLT, HW_STATE_CONTROL, BD718XX_LDO2_VOLT,
192 		BD718XX_LDO2_MASK, ldo2_vranges, 0, false, BD718XX_LDO_SEL),
193 	BD_DATA("LDO3", BD718XX_LDO3_VOLT, HW_STATE_CONTROL, BD718XX_LDO3_VOLT,
194 		BD718XX_LDO3_MASK, ldo3_vranges, 0, false, BD718XX_LDO_SEL),
195 	BD_DATA("LDO4", BD718XX_LDO4_VOLT, HW_STATE_CONTROL, BD718XX_LDO4_VOLT,
196 		BD718XX_LDO4_MASK, ldo4_vranges, 0, false, BD718XX_LDO_SEL),
197 	BD_DATA("LDO5", BD718XX_LDO5_VOLT, HW_STATE_CONTROL, BD718XX_LDO5_VOLT,
198 		BD71837_LDO5_MASK, bd71837_ldo5_vranges, 0, false,
199 		BD718XX_LDO_SEL),
200 	BD_DATA("LDO6", BD718XX_LDO6_VOLT, HW_STATE_CONTROL, BD718XX_LDO6_VOLT,
201 		BD718XX_LDO6_MASK, ldo6_vranges, 0, false, BD718XX_LDO_SEL),
202 	BD_DATA("LDO7", BD71837_LDO7_VOLT, HW_STATE_CONTROL, BD71837_LDO7_VOLT,
203 		BD71837_LDO7_MASK, ldo7_vranges, 0, false, BD718XX_LDO_SEL),
204 };
205 
206 static struct bd71837_platdata bd71847_reg_data[] = {
207 /* Bucks 1 and 2 which support dynamic voltage scaling */
208 	BD_DATA("BUCK1", BD718XX_BUCK1_CTRL, HW_STATE_CONTROL,
209 		BD718XX_BUCK1_VOLT_RUN, DVS_BUCK_RUN_MASK, dvs_buck_vranges, 0,
210 		true, BD718XX_BUCK_SEL),
211 	BD_DATA("BUCK2", BD718XX_BUCK2_CTRL, HW_STATE_CONTROL,
212 		BD718XX_BUCK2_VOLT_RUN, DVS_BUCK_RUN_MASK, dvs_buck_vranges, 0,
213 		true, BD718XX_BUCK_SEL),
214 /* Bucks 3-6 which do not support dynamic voltage scaling */
215 	BD_DATA("BUCK3", BD718XX_1ST_NODVS_BUCK_CTRL, HW_STATE_CONTROL,
216 		BD718XX_1ST_NODVS_BUCK_VOLT, BD718XX_1ST_NODVS_BUCK_MASK,
217 		bd71847_buck3_vranges, 0xc0, false, BD718XX_BUCK_SEL),
218 	BD_DATA("BUCK4", BD718XX_2ND_NODVS_BUCK_CTRL, HW_STATE_CONTROL,
219 		BD718XX_2ND_NODVS_BUCK_VOLT, BD71837_BUCK6_MASK,
220 		bd71847_buck4_vranges, 0x40, false, BD718XX_BUCK_SEL),
221 	BD_DATA("BUCK5", BD718XX_3RD_NODVS_BUCK_CTRL, HW_STATE_CONTROL,
222 		BD718XX_3RD_NODVS_BUCK_VOLT, BD718XX_3RD_NODVS_BUCK_MASK,
223 		nodvs_buck3_vranges, 0, false, BD718XX_BUCK_SEL),
224 	BD_DATA("BUCK6", BD718XX_4TH_NODVS_BUCK_CTRL, HW_STATE_CONTROL,
225 		BD718XX_4TH_NODVS_BUCK_VOLT, BD718XX_4TH_NODVS_BUCK_MASK,
226 		nodvs_buck4_vranges, 0, false, BD718XX_BUCK_SEL),
227 /* LDOs */
228 	BD_DATA("LDO1", BD718XX_LDO1_VOLT, HW_STATE_CONTROL, BD718XX_LDO1_VOLT,
229 		BD718XX_LDO1_MASK, ldo1_vranges, 0x20, false, BD718XX_LDO_SEL),
230 	BD_DATA("LDO2", BD718XX_LDO2_VOLT, HW_STATE_CONTROL, BD718XX_LDO2_VOLT,
231 		BD718XX_LDO2_MASK, ldo2_vranges, 0, false, BD718XX_LDO_SEL),
232 	BD_DATA("LDO3", BD718XX_LDO3_VOLT, HW_STATE_CONTROL, BD718XX_LDO3_VOLT,
233 		BD718XX_LDO3_MASK, ldo3_vranges, 0, false, BD718XX_LDO_SEL),
234 	BD_DATA("LDO4", BD718XX_LDO4_VOLT, HW_STATE_CONTROL, BD718XX_LDO4_VOLT,
235 		BD718XX_LDO4_MASK, ldo4_vranges, 0, false, BD718XX_LDO_SEL),
236 	BD_DATA("LDO5", BD718XX_LDO5_VOLT, HW_STATE_CONTROL, BD718XX_LDO5_VOLT,
237 		BD71847_LDO5_MASK, bd71847_ldo5_vranges, 0x20, false,
238 		BD718XX_LDO_SEL),
239 	BD_DATA("LDO6", BD718XX_LDO6_VOLT, HW_STATE_CONTROL, BD718XX_LDO6_VOLT,
240 		BD718XX_LDO6_MASK, ldo6_vranges, 0, false, BD718XX_LDO_SEL),
241 };
242 
vrange_find_value(struct bd71837_vrange * r,unsigned int sel,unsigned int * val)243 static int vrange_find_value(struct bd71837_vrange *r, unsigned int sel,
244 			     unsigned int *val)
245 {
246 	if (!val || sel < r->min_sel || sel > r->max_sel)
247 		return -EINVAL;
248 
249 	*val = r->min_volt + r->step * (sel - r->min_sel);
250 	return 0;
251 }
252 
vrange_find_selector(struct bd71837_vrange * r,int val,unsigned int * sel)253 static int vrange_find_selector(struct bd71837_vrange *r, int val,
254 				unsigned int *sel)
255 {
256 	int ret = -EINVAL;
257 	int num_vals = r->max_sel - r->min_sel + 1;
258 
259 	if (val >= r->min_volt &&
260 	    val <= r->min_volt + r->step * (num_vals - 1)) {
261 		if (r->step) {
262 			*sel = r->min_sel + ((val - r->min_volt) / r->step);
263 			ret = 0;
264 		} else {
265 			*sel = r->min_sel;
266 			ret = 0;
267 		}
268 	}
269 	return ret;
270 }
271 
bd71837_get_enable(struct udevice * dev)272 static int bd71837_get_enable(struct udevice *dev)
273 {
274 	int val;
275 	struct bd71837_platdata *plat = dev_get_platdata(dev);
276 
277 	/*
278 	 * boot critical regulators on bd71837 must not be controlled by sw
279 	 * due to the 'feature' which leaves power rails down if bd71837 is
280 	 * reseted to snvs state. hence we can't get the state here.
281 	 *
282 	 * if we are alive it means we probably are on run state and
283 	 * if the regulator can't be controlled we can assume it is
284 	 * enabled.
285 	 */
286 	if (plat->enablemask == HW_STATE_CONTROL)
287 		return 1;
288 
289 	val = pmic_reg_read(dev->parent, plat->enable_reg);
290 	if (val < 0)
291 		return val;
292 
293 	return (val & plat->enablemask);
294 }
295 
bd71837_set_enable(struct udevice * dev,bool enable)296 static int bd71837_set_enable(struct udevice *dev, bool enable)
297 {
298 	int val = 0;
299 	struct bd71837_platdata *plat = dev_get_platdata(dev);
300 
301 	/*
302 	 * boot critical regulators on bd71837 must not be controlled by sw
303 	 * due to the 'feature' which leaves power rails down if bd71837 is
304 	 * reseted to snvs state. Hence we can't set the state here.
305 	 */
306 	if (plat->enablemask == HW_STATE_CONTROL)
307 		return -EINVAL;
308 
309 	if (enable)
310 		val = plat->enablemask;
311 
312 	return pmic_clrsetbits(dev->parent, plat->enable_reg, plat->enablemask,
313 			       val);
314 }
315 
bd71837_set_value(struct udevice * dev,int uvolt)316 static int bd71837_set_value(struct udevice *dev, int uvolt)
317 {
318 	unsigned int sel;
319 	unsigned int range;
320 	int i;
321 	int found = 0;
322 	struct bd71837_platdata *plat = dev_get_platdata(dev);
323 
324 	/*
325 	 * An under/overshooting may occur if voltage is changed for other
326 	 * regulators but buck 1,2,3 or 4 when regulator is enabled. Prevent
327 	 * change to protect the HW
328 	 */
329 	if (!plat->dvs)
330 		if (bd71837_get_enable(dev)) {
331 			pr_err("Only DVS bucks can be changed when enabled\n");
332 			return -EINVAL;
333 		}
334 
335 	for (i = 0; i < plat->numranges; i++) {
336 		struct bd71837_vrange *r = &plat->ranges[i];
337 
338 		found = !vrange_find_selector(r, uvolt, &sel);
339 		if (found) {
340 			unsigned int tmp;
341 
342 			/*
343 			 * We require exactly the requested value to be
344 			 * supported - this can be changed later if needed
345 			 */
346 			range = r->rangeval;
347 			found = !vrange_find_value(r, sel, &tmp);
348 			if (found && tmp == uvolt)
349 				break;
350 			found = 0;
351 		}
352 	}
353 
354 	if (!found)
355 		return -EINVAL;
356 
357 	sel <<= ffs(plat->volt_mask) - 1;
358 
359 	if (plat->rangemask)
360 		sel |= range;
361 
362 	return pmic_clrsetbits(dev->parent, plat->volt_reg, plat->volt_mask |
363 			       plat->rangemask, sel);
364 }
365 
bd71837_get_value(struct udevice * dev)366 static int bd71837_get_value(struct udevice *dev)
367 {
368 	unsigned int reg, range;
369 	unsigned int tmp;
370 	struct bd71837_platdata *plat = dev_get_platdata(dev);
371 	int i;
372 
373 	reg = pmic_reg_read(dev->parent, plat->volt_reg);
374 	if (((int)reg) < 0)
375 		return reg;
376 
377 	range = reg & plat->rangemask;
378 
379 	reg &= plat->volt_mask;
380 	reg >>= ffs(plat->volt_mask) - 1;
381 
382 	for (i = 0; i < plat->numranges; i++) {
383 		struct bd71837_vrange *r = &plat->ranges[i];
384 
385 		if (plat->rangemask && ((plat->rangemask & range) !=
386 		    r->rangeval))
387 			continue;
388 
389 		if (!vrange_find_value(r, reg, &tmp))
390 			return tmp;
391 	}
392 
393 	pr_err("Unknown voltage value read from pmic\n");
394 
395 	return -EINVAL;
396 }
397 
bd71837_regulator_probe(struct udevice * dev)398 static int bd71837_regulator_probe(struct udevice *dev)
399 {
400 	struct bd71837_platdata *plat = dev_get_platdata(dev);
401 	int i, ret;
402 	struct dm_regulator_uclass_platdata *uc_pdata;
403 	int type;
404 	struct bd71837_platdata *init_data;
405 	int data_amnt;
406 
407 	type = dev_get_driver_data(dev_get_parent(dev));
408 
409 	switch (type) {
410 	case ROHM_CHIP_TYPE_BD71837:
411 		init_data = bd71837_reg_data;
412 		data_amnt = ARRAY_SIZE(bd71837_reg_data);
413 		break;
414 	case ROHM_CHIP_TYPE_BD71847:
415 		init_data = bd71847_reg_data;
416 		data_amnt = ARRAY_SIZE(bd71847_reg_data);
417 		break;
418 	default:
419 		debug("Unknown PMIC type\n");
420 		init_data = NULL;
421 		data_amnt = 0;
422 		break;
423 	}
424 
425 	for (i = 0; i < data_amnt; i++) {
426 		if (!strcmp(dev->name, init_data[i].name)) {
427 			*plat = init_data[i];
428 			if (plat->enablemask != HW_STATE_CONTROL) {
429 				/*
430 				 * Take the regulator under SW control. Ensure
431 				 * the initial state matches dt flags and then
432 				 * write the SEL bit
433 				 */
434 				uc_pdata = dev_get_uclass_platdata(dev);
435 				ret = bd71837_set_enable(dev,
436 							 !!(uc_pdata->boot_on ||
437 							 uc_pdata->always_on));
438 				if (ret)
439 					return ret;
440 
441 				return pmic_clrsetbits(dev->parent,
442 						      plat->enable_reg,
443 						      plat->sel_mask,
444 						      plat->sel_mask);
445 			}
446 			return 0;
447 		}
448 	}
449 
450 	pr_err("Unknown regulator '%s'\n", dev->name);
451 
452 	return -ENOENT;
453 }
454 
455 static const struct dm_regulator_ops bd71837_regulator_ops = {
456 	.get_value  = bd71837_get_value,
457 	.set_value  = bd71837_set_value,
458 	.get_enable = bd71837_get_enable,
459 	.set_enable = bd71837_set_enable,
460 };
461 
462 U_BOOT_DRIVER(bd71837_regulator) = {
463 	.name = BD718XX_REGULATOR_DRIVER,
464 	.id = UCLASS_REGULATOR,
465 	.ops = &bd71837_regulator_ops,
466 	.probe = bd71837_regulator_probe,
467 	.platdata_auto_alloc_size = sizeof(struct bd71837_platdata),
468 };
469