1 // SPDX-License-Identifier: GPL-2.0-only
3 * Driver for voltage controller regulators
5 * Copyright (C) 2017 Google, Inc.
8 #include <linux/delay.h>
10 #include <linux/init.h>
11 #include <linux/module.h>
13 #include <linux/of_device.h>
14 #include <linux/regulator/driver.h>
15 #include <linux/regulator/of_regulator.h>
16 #include <linux/sort.h>
18 struct vctrl_voltage_range
{
23 struct vctrl_voltage_ranges
{
24 struct vctrl_voltage_range ctrl
;
25 struct vctrl_voltage_range out
;
28 struct vctrl_voltage_table
{
35 struct regulator_dev
*rdev
;
36 struct regulator_desc desc
;
37 struct regulator
*ctrl_reg
;
39 unsigned int min_slew_down_rate
;
40 unsigned int ovp_threshold
;
41 struct vctrl_voltage_ranges vrange
;
42 struct vctrl_voltage_table
*vtable
;
46 static int vctrl_calc_ctrl_voltage(struct vctrl_data
*vctrl
, int out_uV
)
48 struct vctrl_voltage_range
*ctrl
= &vctrl
->vrange
.ctrl
;
49 struct vctrl_voltage_range
*out
= &vctrl
->vrange
.out
;
52 DIV_ROUND_CLOSEST_ULL((s64
)(out_uV
- out
->min_uV
) *
53 (ctrl
->max_uV
- ctrl
->min_uV
),
54 out
->max_uV
- out
->min_uV
);
57 static int vctrl_calc_output_voltage(struct vctrl_data
*vctrl
, int ctrl_uV
)
59 struct vctrl_voltage_range
*ctrl
= &vctrl
->vrange
.ctrl
;
60 struct vctrl_voltage_range
*out
= &vctrl
->vrange
.out
;
63 pr_err("vctrl: failed to get control voltage\n");
67 if (ctrl_uV
< ctrl
->min_uV
)
70 if (ctrl_uV
> ctrl
->max_uV
)
74 DIV_ROUND_CLOSEST_ULL((s64
)(ctrl_uV
- ctrl
->min_uV
) *
75 (out
->max_uV
- out
->min_uV
),
76 ctrl
->max_uV
- ctrl
->min_uV
);
79 static int vctrl_get_voltage(struct regulator_dev
*rdev
)
81 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
82 int ctrl_uV
= regulator_get_voltage(vctrl
->ctrl_reg
);
84 return vctrl_calc_output_voltage(vctrl
, ctrl_uV
);
87 static int vctrl_set_voltage(struct regulator_dev
*rdev
,
88 int req_min_uV
, int req_max_uV
,
89 unsigned int *selector
)
91 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
92 struct regulator
*ctrl_reg
= vctrl
->ctrl_reg
;
93 int orig_ctrl_uV
= regulator_get_voltage(ctrl_reg
);
94 int uV
= vctrl_calc_output_voltage(vctrl
, orig_ctrl_uV
);
97 if (req_min_uV
>= uV
|| !vctrl
->ovp_threshold
)
98 /* voltage rising or no OVP */
99 return regulator_set_voltage(
101 vctrl_calc_ctrl_voltage(vctrl
, req_min_uV
),
102 vctrl_calc_ctrl_voltage(vctrl
, req_max_uV
));
104 while (uV
> req_min_uV
) {
105 int max_drop_uV
= (uV
* vctrl
->ovp_threshold
) / 100;
110 /* Make sure no infinite loop even in crazy cases */
111 if (max_drop_uV
== 0)
114 next_uV
= max_t(int, req_min_uV
, uV
- max_drop_uV
);
115 next_ctrl_uV
= vctrl_calc_ctrl_voltage(vctrl
, next_uV
);
117 ret
= regulator_set_voltage(ctrl_reg
,
123 delay
= DIV_ROUND_UP(uV
- next_uV
, vctrl
->min_slew_down_rate
);
124 usleep_range(delay
, delay
+ DIV_ROUND_UP(delay
, 10));
132 /* Try to go back to original voltage */
133 regulator_set_voltage(ctrl_reg
, orig_ctrl_uV
, orig_ctrl_uV
);
138 static int vctrl_get_voltage_sel(struct regulator_dev
*rdev
)
140 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
145 static int vctrl_set_voltage_sel(struct regulator_dev
*rdev
,
146 unsigned int selector
)
148 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
149 struct regulator
*ctrl_reg
= vctrl
->ctrl_reg
;
150 unsigned int orig_sel
= vctrl
->sel
;
153 if (selector
>= rdev
->desc
->n_voltages
)
156 if (selector
>= vctrl
->sel
|| !vctrl
->ovp_threshold
) {
157 /* voltage rising or no OVP */
158 ret
= regulator_set_voltage(ctrl_reg
,
159 vctrl
->vtable
[selector
].ctrl
,
160 vctrl
->vtable
[selector
].ctrl
);
162 vctrl
->sel
= selector
;
167 while (vctrl
->sel
!= selector
) {
168 unsigned int next_sel
;
171 if (selector
>= vctrl
->vtable
[vctrl
->sel
].ovp_min_sel
)
174 next_sel
= vctrl
->vtable
[vctrl
->sel
].ovp_min_sel
;
176 ret
= regulator_set_voltage(ctrl_reg
,
177 vctrl
->vtable
[next_sel
].ctrl
,
178 vctrl
->vtable
[next_sel
].ctrl
);
181 "failed to set control voltage to %duV\n",
182 vctrl
->vtable
[next_sel
].ctrl
);
185 vctrl
->sel
= next_sel
;
187 delay
= DIV_ROUND_UP(vctrl
->vtable
[vctrl
->sel
].out
-
188 vctrl
->vtable
[next_sel
].out
,
189 vctrl
->min_slew_down_rate
);
190 usleep_range(delay
, delay
+ DIV_ROUND_UP(delay
, 10));
196 if (vctrl
->sel
!= orig_sel
) {
197 /* Try to go back to original voltage */
198 if (!regulator_set_voltage(ctrl_reg
,
199 vctrl
->vtable
[orig_sel
].ctrl
,
200 vctrl
->vtable
[orig_sel
].ctrl
))
201 vctrl
->sel
= orig_sel
;
204 "failed to restore original voltage\n");
210 static int vctrl_list_voltage(struct regulator_dev
*rdev
,
211 unsigned int selector
)
213 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
215 if (selector
>= rdev
->desc
->n_voltages
)
218 return vctrl
->vtable
[selector
].out
;
221 static int vctrl_parse_dt(struct platform_device
*pdev
,
222 struct vctrl_data
*vctrl
)
225 struct device_node
*np
= pdev
->dev
.of_node
;
229 vctrl
->ctrl_reg
= devm_regulator_get(&pdev
->dev
, "ctrl");
230 if (IS_ERR(vctrl
->ctrl_reg
))
231 return PTR_ERR(vctrl
->ctrl_reg
);
233 ret
= of_property_read_u32(np
, "ovp-threshold-percent", &pval
);
235 vctrl
->ovp_threshold
= pval
;
236 if (vctrl
->ovp_threshold
> 100) {
238 "ovp-threshold-percent (%u) > 100\n",
239 vctrl
->ovp_threshold
);
244 ret
= of_property_read_u32(np
, "min-slew-down-rate", &pval
);
246 vctrl
->min_slew_down_rate
= pval
;
248 /* We use the value as int and as divider; sanity check */
249 if (vctrl
->min_slew_down_rate
== 0) {
251 "min-slew-down-rate must not be 0\n");
253 } else if (vctrl
->min_slew_down_rate
> INT_MAX
) {
254 dev_err(&pdev
->dev
, "min-slew-down-rate (%u) too big\n",
255 vctrl
->min_slew_down_rate
);
260 if (vctrl
->ovp_threshold
&& !vctrl
->min_slew_down_rate
) {
262 "ovp-threshold-percent requires min-slew-down-rate\n");
266 ret
= of_property_read_u32(np
, "regulator-min-microvolt", &pval
);
269 "failed to read regulator-min-microvolt: %d\n", ret
);
272 vctrl
->vrange
.out
.min_uV
= pval
;
274 ret
= of_property_read_u32(np
, "regulator-max-microvolt", &pval
);
277 "failed to read regulator-max-microvolt: %d\n", ret
);
280 vctrl
->vrange
.out
.max_uV
= pval
;
282 ret
= of_property_read_u32_array(np
, "ctrl-voltage-range", vrange_ctrl
,
285 dev_err(&pdev
->dev
, "failed to read ctrl-voltage-range: %d\n",
290 if (vrange_ctrl
[0] >= vrange_ctrl
[1]) {
291 dev_err(&pdev
->dev
, "ctrl-voltage-range is invalid: %d-%d\n",
292 vrange_ctrl
[0], vrange_ctrl
[1]);
296 vctrl
->vrange
.ctrl
.min_uV
= vrange_ctrl
[0];
297 vctrl
->vrange
.ctrl
.max_uV
= vrange_ctrl
[1];
302 static int vctrl_cmp_ctrl_uV(const void *a
, const void *b
)
304 const struct vctrl_voltage_table
*at
= a
;
305 const struct vctrl_voltage_table
*bt
= b
;
307 return at
->ctrl
- bt
->ctrl
;
310 static int vctrl_init_vtable(struct platform_device
*pdev
)
312 struct vctrl_data
*vctrl
= platform_get_drvdata(pdev
);
313 struct regulator_desc
*rdesc
= &vctrl
->desc
;
314 struct regulator
*ctrl_reg
= vctrl
->ctrl_reg
;
315 struct vctrl_voltage_range
*vrange_ctrl
= &vctrl
->vrange
.ctrl
;
320 n_voltages
= regulator_count_voltages(ctrl_reg
);
322 rdesc
->n_voltages
= n_voltages
;
324 /* determine number of steps within the range of the vctrl regulator */
325 for (i
= 0; i
< n_voltages
; i
++) {
326 ctrl_uV
= regulator_list_voltage(ctrl_reg
, i
);
328 if (ctrl_uV
< vrange_ctrl
->min_uV
||
329 ctrl_uV
> vrange_ctrl
->max_uV
)
333 if (rdesc
->n_voltages
== 0) {
334 dev_err(&pdev
->dev
, "invalid configuration\n");
338 vctrl
->vtable
= devm_kcalloc(&pdev
->dev
, rdesc
->n_voltages
,
339 sizeof(struct vctrl_voltage_table
),
344 /* create mapping control <=> output voltage */
345 for (i
= 0, idx_vt
= 0; i
< n_voltages
; i
++) {
346 ctrl_uV
= regulator_list_voltage(ctrl_reg
, i
);
348 if (ctrl_uV
< vrange_ctrl
->min_uV
||
349 ctrl_uV
> vrange_ctrl
->max_uV
)
352 vctrl
->vtable
[idx_vt
].ctrl
= ctrl_uV
;
353 vctrl
->vtable
[idx_vt
].out
=
354 vctrl_calc_output_voltage(vctrl
, ctrl_uV
);
358 /* we rely on the table to be ordered by ascending voltage */
359 sort(vctrl
->vtable
, rdesc
->n_voltages
,
360 sizeof(struct vctrl_voltage_table
), vctrl_cmp_ctrl_uV
,
363 /* pre-calculate OVP-safe downward transitions */
364 for (i
= rdesc
->n_voltages
- 1; i
> 0; i
--) {
366 int ovp_min_uV
= (vctrl
->vtable
[i
].out
*
367 (100 - vctrl
->ovp_threshold
)) / 100;
369 for (j
= 0; j
< i
; j
++) {
370 if (vctrl
->vtable
[j
].out
>= ovp_min_uV
) {
371 vctrl
->vtable
[i
].ovp_min_sel
= j
;
377 dev_warn(&pdev
->dev
, "switching down from %duV may cause OVP shutdown\n",
378 vctrl
->vtable
[i
].out
);
379 /* use next lowest voltage */
380 vctrl
->vtable
[i
].ovp_min_sel
= i
- 1;
387 static int vctrl_enable(struct regulator_dev
*rdev
)
389 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
390 int ret
= regulator_enable(vctrl
->ctrl_reg
);
393 vctrl
->enabled
= true;
398 static int vctrl_disable(struct regulator_dev
*rdev
)
400 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
401 int ret
= regulator_disable(vctrl
->ctrl_reg
);
404 vctrl
->enabled
= false;
409 static int vctrl_is_enabled(struct regulator_dev
*rdev
)
411 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
413 return vctrl
->enabled
;
416 static const struct regulator_ops vctrl_ops_cont
= {
417 .enable
= vctrl_enable
,
418 .disable
= vctrl_disable
,
419 .is_enabled
= vctrl_is_enabled
,
420 .get_voltage
= vctrl_get_voltage
,
421 .set_voltage
= vctrl_set_voltage
,
424 static const struct regulator_ops vctrl_ops_non_cont
= {
425 .enable
= vctrl_enable
,
426 .disable
= vctrl_disable
,
427 .is_enabled
= vctrl_is_enabled
,
428 .set_voltage_sel
= vctrl_set_voltage_sel
,
429 .get_voltage_sel
= vctrl_get_voltage_sel
,
430 .list_voltage
= vctrl_list_voltage
,
431 .map_voltage
= regulator_map_voltage_iterate
,
434 static int vctrl_probe(struct platform_device
*pdev
)
436 struct device_node
*np
= pdev
->dev
.of_node
;
437 struct vctrl_data
*vctrl
;
438 const struct regulator_init_data
*init_data
;
439 struct regulator_desc
*rdesc
;
440 struct regulator_config cfg
= { };
441 struct vctrl_voltage_range
*vrange_ctrl
;
445 vctrl
= devm_kzalloc(&pdev
->dev
, sizeof(struct vctrl_data
),
450 platform_set_drvdata(pdev
, vctrl
);
452 ret
= vctrl_parse_dt(pdev
, vctrl
);
456 vrange_ctrl
= &vctrl
->vrange
.ctrl
;
458 rdesc
= &vctrl
->desc
;
459 rdesc
->name
= "vctrl";
460 rdesc
->type
= REGULATOR_VOLTAGE
;
461 rdesc
->owner
= THIS_MODULE
;
463 if ((regulator_get_linear_step(vctrl
->ctrl_reg
) == 1) ||
464 (regulator_count_voltages(vctrl
->ctrl_reg
) == -EINVAL
)) {
465 rdesc
->continuous_voltage_range
= true;
466 rdesc
->ops
= &vctrl_ops_cont
;
468 rdesc
->ops
= &vctrl_ops_non_cont
;
471 init_data
= of_get_regulator_init_data(&pdev
->dev
, np
, rdesc
);
476 cfg
.dev
= &pdev
->dev
;
477 cfg
.driver_data
= vctrl
;
478 cfg
.init_data
= init_data
;
480 if (!rdesc
->continuous_voltage_range
) {
481 ret
= vctrl_init_vtable(pdev
);
485 ctrl_uV
= regulator_get_voltage(vctrl
->ctrl_reg
);
487 dev_err(&pdev
->dev
, "failed to get control voltage\n");
491 /* determine current voltage selector from control voltage */
492 if (ctrl_uV
< vrange_ctrl
->min_uV
) {
494 } else if (ctrl_uV
> vrange_ctrl
->max_uV
) {
495 vctrl
->sel
= rdesc
->n_voltages
- 1;
499 for (i
= 0; i
< rdesc
->n_voltages
; i
++) {
500 if (ctrl_uV
== vctrl
->vtable
[i
].ctrl
) {
508 vctrl
->rdev
= devm_regulator_register(&pdev
->dev
, rdesc
, &cfg
);
509 if (IS_ERR(vctrl
->rdev
)) {
510 ret
= PTR_ERR(vctrl
->rdev
);
511 dev_err(&pdev
->dev
, "failed to register regulator: %d\n", ret
);
518 static const struct of_device_id vctrl_of_match
[] = {
519 { .compatible
= "vctrl-regulator", },
522 MODULE_DEVICE_TABLE(of
, vctrl_of_match
);
524 static struct platform_driver vctrl_driver
= {
525 .probe
= vctrl_probe
,
527 .name
= "vctrl-regulator",
528 .of_match_table
= of_match_ptr(vctrl_of_match
),
532 module_platform_driver(vctrl_driver
);
534 MODULE_DESCRIPTION("Voltage Controlled Regulator Driver");
535 MODULE_AUTHOR("Matthias Kaehlcke <mka@chromium.org>");
536 MODULE_LICENSE("GPL v2");