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/platform_device.h>
14 #include <linux/regulator/coupler.h>
15 #include <linux/regulator/driver.h>
16 #include <linux/regulator/of_regulator.h>
17 #include <linux/sort.h>
21 struct vctrl_voltage_range
{
26 struct vctrl_voltage_ranges
{
27 struct vctrl_voltage_range ctrl
;
28 struct vctrl_voltage_range out
;
31 struct vctrl_voltage_table
{
38 struct regulator_dev
*rdev
;
39 struct regulator_desc desc
;
41 unsigned int min_slew_down_rate
;
42 unsigned int ovp_threshold
;
43 struct vctrl_voltage_ranges vrange
;
44 struct vctrl_voltage_table
*vtable
;
48 static int vctrl_calc_ctrl_voltage(struct vctrl_data
*vctrl
, int out_uV
)
50 struct vctrl_voltage_range
*ctrl
= &vctrl
->vrange
.ctrl
;
51 struct vctrl_voltage_range
*out
= &vctrl
->vrange
.out
;
54 DIV_ROUND_CLOSEST_ULL((s64
)(out_uV
- out
->min_uV
) *
55 (ctrl
->max_uV
- ctrl
->min_uV
),
56 out
->max_uV
- out
->min_uV
);
59 static int vctrl_calc_output_voltage(struct vctrl_data
*vctrl
, int ctrl_uV
)
61 struct vctrl_voltage_range
*ctrl
= &vctrl
->vrange
.ctrl
;
62 struct vctrl_voltage_range
*out
= &vctrl
->vrange
.out
;
65 pr_err("vctrl: failed to get control voltage\n");
69 if (ctrl_uV
< ctrl
->min_uV
)
72 if (ctrl_uV
> ctrl
->max_uV
)
76 DIV_ROUND_CLOSEST_ULL((s64
)(ctrl_uV
- ctrl
->min_uV
) *
77 (out
->max_uV
- out
->min_uV
),
78 ctrl
->max_uV
- ctrl
->min_uV
);
81 static int vctrl_get_voltage(struct regulator_dev
*rdev
)
83 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
89 ctrl_uV
= regulator_get_voltage_rdev(rdev
->supply
->rdev
);
91 return vctrl_calc_output_voltage(vctrl
, ctrl_uV
);
94 static int vctrl_set_voltage(struct regulator_dev
*rdev
,
95 int req_min_uV
, int req_max_uV
,
96 unsigned int *selector
)
98 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
104 return -EPROBE_DEFER
;
106 orig_ctrl_uV
= regulator_get_voltage_rdev(rdev
->supply
->rdev
);
107 uV
= vctrl_calc_output_voltage(vctrl
, orig_ctrl_uV
);
109 if (req_min_uV
>= uV
|| !vctrl
->ovp_threshold
)
110 /* voltage rising or no OVP */
111 return regulator_set_voltage_rdev(rdev
->supply
->rdev
,
112 vctrl_calc_ctrl_voltage(vctrl
, req_min_uV
),
113 vctrl_calc_ctrl_voltage(vctrl
, req_max_uV
),
116 while (uV
> req_min_uV
) {
117 int max_drop_uV
= (uV
* vctrl
->ovp_threshold
) / 100;
122 /* Make sure no infinite loop even in crazy cases */
123 if (max_drop_uV
== 0)
126 next_uV
= max_t(int, req_min_uV
, uV
- max_drop_uV
);
127 next_ctrl_uV
= vctrl_calc_ctrl_voltage(vctrl
, next_uV
);
129 ret
= regulator_set_voltage_rdev(rdev
->supply
->rdev
,
136 delay
= DIV_ROUND_UP(uV
- next_uV
, vctrl
->min_slew_down_rate
);
137 usleep_range(delay
, delay
+ DIV_ROUND_UP(delay
, 10));
145 /* Try to go back to original voltage */
146 regulator_set_voltage_rdev(rdev
->supply
->rdev
, orig_ctrl_uV
, orig_ctrl_uV
,
152 static int vctrl_get_voltage_sel(struct regulator_dev
*rdev
)
154 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
159 static int vctrl_set_voltage_sel(struct regulator_dev
*rdev
,
160 unsigned int selector
)
162 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
163 unsigned int orig_sel
= vctrl
->sel
;
167 return -EPROBE_DEFER
;
169 if (selector
>= rdev
->desc
->n_voltages
)
172 if (selector
>= vctrl
->sel
|| !vctrl
->ovp_threshold
) {
173 /* voltage rising or no OVP */
174 ret
= regulator_set_voltage_rdev(rdev
->supply
->rdev
,
175 vctrl
->vtable
[selector
].ctrl
,
176 vctrl
->vtable
[selector
].ctrl
,
179 vctrl
->sel
= selector
;
184 while (vctrl
->sel
!= selector
) {
185 unsigned int next_sel
;
188 next_sel
= max_t(unsigned int, selector
, vctrl
->vtable
[vctrl
->sel
].ovp_min_sel
);
190 ret
= regulator_set_voltage_rdev(rdev
->supply
->rdev
,
191 vctrl
->vtable
[next_sel
].ctrl
,
192 vctrl
->vtable
[next_sel
].ctrl
,
196 "failed to set control voltage to %duV\n",
197 vctrl
->vtable
[next_sel
].ctrl
);
200 vctrl
->sel
= next_sel
;
202 delay
= DIV_ROUND_UP(vctrl
->vtable
[vctrl
->sel
].out
-
203 vctrl
->vtable
[next_sel
].out
,
204 vctrl
->min_slew_down_rate
);
205 usleep_range(delay
, delay
+ DIV_ROUND_UP(delay
, 10));
211 if (vctrl
->sel
!= orig_sel
) {
212 /* Try to go back to original voltage */
213 if (!regulator_set_voltage_rdev(rdev
->supply
->rdev
,
214 vctrl
->vtable
[orig_sel
].ctrl
,
215 vctrl
->vtable
[orig_sel
].ctrl
,
217 vctrl
->sel
= orig_sel
;
220 "failed to restore original voltage\n");
226 static int vctrl_list_voltage(struct regulator_dev
*rdev
,
227 unsigned int selector
)
229 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
231 if (selector
>= rdev
->desc
->n_voltages
)
234 return vctrl
->vtable
[selector
].out
;
237 static int vctrl_parse_dt(struct platform_device
*pdev
,
238 struct vctrl_data
*vctrl
)
241 struct device_node
*np
= pdev
->dev
.of_node
;
245 ret
= of_property_read_u32(np
, "ovp-threshold-percent", &pval
);
247 vctrl
->ovp_threshold
= pval
;
248 if (vctrl
->ovp_threshold
> 100) {
250 "ovp-threshold-percent (%u) > 100\n",
251 vctrl
->ovp_threshold
);
256 ret
= of_property_read_u32(np
, "min-slew-down-rate", &pval
);
258 vctrl
->min_slew_down_rate
= pval
;
260 /* We use the value as int and as divider; sanity check */
261 if (vctrl
->min_slew_down_rate
== 0) {
263 "min-slew-down-rate must not be 0\n");
265 } else if (vctrl
->min_slew_down_rate
> INT_MAX
) {
266 dev_err(&pdev
->dev
, "min-slew-down-rate (%u) too big\n",
267 vctrl
->min_slew_down_rate
);
272 if (vctrl
->ovp_threshold
&& !vctrl
->min_slew_down_rate
) {
274 "ovp-threshold-percent requires min-slew-down-rate\n");
278 ret
= of_property_read_u32(np
, "regulator-min-microvolt", &pval
);
281 "failed to read regulator-min-microvolt: %d\n", ret
);
284 vctrl
->vrange
.out
.min_uV
= pval
;
286 ret
= of_property_read_u32(np
, "regulator-max-microvolt", &pval
);
289 "failed to read regulator-max-microvolt: %d\n", ret
);
292 vctrl
->vrange
.out
.max_uV
= pval
;
294 ret
= of_property_read_u32_array(np
, "ctrl-voltage-range", vrange_ctrl
,
297 dev_err(&pdev
->dev
, "failed to read ctrl-voltage-range: %d\n",
302 if (vrange_ctrl
[0] >= vrange_ctrl
[1]) {
303 dev_err(&pdev
->dev
, "ctrl-voltage-range is invalid: %d-%d\n",
304 vrange_ctrl
[0], vrange_ctrl
[1]);
308 vctrl
->vrange
.ctrl
.min_uV
= vrange_ctrl
[0];
309 vctrl
->vrange
.ctrl
.max_uV
= vrange_ctrl
[1];
314 static int vctrl_cmp_ctrl_uV(const void *a
, const void *b
)
316 const struct vctrl_voltage_table
*at
= a
;
317 const struct vctrl_voltage_table
*bt
= b
;
319 return at
->ctrl
- bt
->ctrl
;
322 static int vctrl_init_vtable(struct platform_device
*pdev
,
323 struct regulator
*ctrl_reg
)
325 struct vctrl_data
*vctrl
= platform_get_drvdata(pdev
);
326 struct regulator_desc
*rdesc
= &vctrl
->desc
;
327 struct vctrl_voltage_range
*vrange_ctrl
= &vctrl
->vrange
.ctrl
;
332 n_voltages
= regulator_count_voltages(ctrl_reg
);
334 rdesc
->n_voltages
= n_voltages
;
336 /* determine number of steps within the range of the vctrl regulator */
337 for (i
= 0; i
< n_voltages
; i
++) {
338 ctrl_uV
= regulator_list_voltage(ctrl_reg
, i
);
340 if (ctrl_uV
< vrange_ctrl
->min_uV
||
341 ctrl_uV
> vrange_ctrl
->max_uV
)
345 if (rdesc
->n_voltages
== 0) {
346 dev_err(&pdev
->dev
, "invalid configuration\n");
350 vctrl
->vtable
= devm_kcalloc(&pdev
->dev
, rdesc
->n_voltages
,
351 sizeof(struct vctrl_voltage_table
),
356 /* create mapping control <=> output voltage */
357 for (i
= 0, idx_vt
= 0; i
< n_voltages
; i
++) {
358 ctrl_uV
= regulator_list_voltage(ctrl_reg
, i
);
360 if (ctrl_uV
< vrange_ctrl
->min_uV
||
361 ctrl_uV
> vrange_ctrl
->max_uV
)
364 vctrl
->vtable
[idx_vt
].ctrl
= ctrl_uV
;
365 vctrl
->vtable
[idx_vt
].out
=
366 vctrl_calc_output_voltage(vctrl
, ctrl_uV
);
370 /* we rely on the table to be ordered by ascending voltage */
371 sort(vctrl
->vtable
, rdesc
->n_voltages
,
372 sizeof(struct vctrl_voltage_table
), vctrl_cmp_ctrl_uV
,
375 /* pre-calculate OVP-safe downward transitions */
376 for (i
= rdesc
->n_voltages
- 1; i
> 0; i
--) {
378 int ovp_min_uV
= (vctrl
->vtable
[i
].out
*
379 (100 - vctrl
->ovp_threshold
)) / 100;
381 for (j
= 0; j
< i
; j
++) {
382 if (vctrl
->vtable
[j
].out
>= ovp_min_uV
) {
383 vctrl
->vtable
[i
].ovp_min_sel
= j
;
389 dev_warn(&pdev
->dev
, "switching down from %duV may cause OVP shutdown\n",
390 vctrl
->vtable
[i
].out
);
391 /* use next lowest voltage */
392 vctrl
->vtable
[i
].ovp_min_sel
= i
- 1;
399 static int vctrl_enable(struct regulator_dev
*rdev
)
401 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
403 vctrl
->enabled
= true;
408 static int vctrl_disable(struct regulator_dev
*rdev
)
410 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
412 vctrl
->enabled
= false;
417 static int vctrl_is_enabled(struct regulator_dev
*rdev
)
419 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
421 return vctrl
->enabled
;
424 static const struct regulator_ops vctrl_ops_cont
= {
425 .enable
= vctrl_enable
,
426 .disable
= vctrl_disable
,
427 .is_enabled
= vctrl_is_enabled
,
428 .get_voltage
= vctrl_get_voltage
,
429 .set_voltage
= vctrl_set_voltage
,
432 static const struct regulator_ops vctrl_ops_non_cont
= {
433 .enable
= vctrl_enable
,
434 .disable
= vctrl_disable
,
435 .is_enabled
= vctrl_is_enabled
,
436 .set_voltage_sel
= vctrl_set_voltage_sel
,
437 .get_voltage_sel
= vctrl_get_voltage_sel
,
438 .list_voltage
= vctrl_list_voltage
,
439 .map_voltage
= regulator_map_voltage_iterate
,
442 static int vctrl_probe(struct platform_device
*pdev
)
444 struct device_node
*np
= pdev
->dev
.of_node
;
445 struct vctrl_data
*vctrl
;
446 const struct regulator_init_data
*init_data
;
447 struct regulator_desc
*rdesc
;
448 struct regulator_config cfg
= { };
449 struct vctrl_voltage_range
*vrange_ctrl
;
450 struct regulator
*ctrl_reg
;
454 vctrl
= devm_kzalloc(&pdev
->dev
, sizeof(struct vctrl_data
),
459 platform_set_drvdata(pdev
, vctrl
);
461 ret
= vctrl_parse_dt(pdev
, vctrl
);
465 ctrl_reg
= devm_regulator_get(&pdev
->dev
, "ctrl");
466 if (IS_ERR(ctrl_reg
))
467 return PTR_ERR(ctrl_reg
);
469 vrange_ctrl
= &vctrl
->vrange
.ctrl
;
471 rdesc
= &vctrl
->desc
;
472 rdesc
->name
= "vctrl";
473 rdesc
->type
= REGULATOR_VOLTAGE
;
474 rdesc
->owner
= THIS_MODULE
;
475 rdesc
->supply_name
= "ctrl";
477 if ((regulator_get_linear_step(ctrl_reg
) == 1) ||
478 (regulator_count_voltages(ctrl_reg
) == -EINVAL
)) {
479 rdesc
->continuous_voltage_range
= true;
480 rdesc
->ops
= &vctrl_ops_cont
;
482 rdesc
->ops
= &vctrl_ops_non_cont
;
485 init_data
= of_get_regulator_init_data(&pdev
->dev
, np
, rdesc
);
490 cfg
.dev
= &pdev
->dev
;
491 cfg
.driver_data
= vctrl
;
492 cfg
.init_data
= init_data
;
494 if (!rdesc
->continuous_voltage_range
) {
495 ret
= vctrl_init_vtable(pdev
, ctrl_reg
);
499 /* Use locked consumer API when not in regulator framework */
500 ctrl_uV
= regulator_get_voltage(ctrl_reg
);
502 dev_err(&pdev
->dev
, "failed to get control voltage\n");
506 /* determine current voltage selector from control voltage */
507 if (ctrl_uV
< vrange_ctrl
->min_uV
) {
509 } else if (ctrl_uV
> vrange_ctrl
->max_uV
) {
510 vctrl
->sel
= rdesc
->n_voltages
- 1;
514 for (i
= 0; i
< rdesc
->n_voltages
; i
++) {
515 if (ctrl_uV
== vctrl
->vtable
[i
].ctrl
) {
523 /* Drop ctrl-supply here in favor of regulator core managed supply */
524 devm_regulator_put(ctrl_reg
);
526 vctrl
->rdev
= devm_regulator_register(&pdev
->dev
, rdesc
, &cfg
);
527 if (IS_ERR(vctrl
->rdev
)) {
528 ret
= PTR_ERR(vctrl
->rdev
);
529 dev_err(&pdev
->dev
, "failed to register regulator: %d\n", ret
);
536 static const struct of_device_id vctrl_of_match
[] = {
537 { .compatible
= "vctrl-regulator", },
540 MODULE_DEVICE_TABLE(of
, vctrl_of_match
);
542 static struct platform_driver vctrl_driver
= {
543 .probe
= vctrl_probe
,
545 .name
= "vctrl-regulator",
546 .probe_type
= PROBE_PREFER_ASYNCHRONOUS
,
547 .of_match_table
= of_match_ptr(vctrl_of_match
),
551 module_platform_driver(vctrl_driver
);
553 MODULE_DESCRIPTION("Voltage Controlled Regulator Driver");
554 MODULE_AUTHOR("Matthias Kaehlcke <mka@chromium.org>");
555 MODULE_LICENSE("GPL v2");