2 * Driver for voltage controller regulators
4 * Copyright (C) 2017 Google, Inc.
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <linux/delay.h>
17 #include <linux/err.h>
18 #include <linux/init.h>
19 #include <linux/module.h>
21 #include <linux/of_device.h>
22 #include <linux/regulator/driver.h>
23 #include <linux/regulator/of_regulator.h>
24 #include <linux/sort.h>
26 struct vctrl_voltage_range
{
31 struct vctrl_voltage_ranges
{
32 struct vctrl_voltage_range ctrl
;
33 struct vctrl_voltage_range out
;
36 struct vctrl_voltage_table
{
43 struct regulator_dev
*rdev
;
44 struct regulator_desc desc
;
45 struct regulator
*ctrl_reg
;
47 unsigned int min_slew_down_rate
;
48 unsigned int ovp_threshold
;
49 struct vctrl_voltage_ranges vrange
;
50 struct vctrl_voltage_table
*vtable
;
54 static int vctrl_calc_ctrl_voltage(struct vctrl_data
*vctrl
, int out_uV
)
56 struct vctrl_voltage_range
*ctrl
= &vctrl
->vrange
.ctrl
;
57 struct vctrl_voltage_range
*out
= &vctrl
->vrange
.out
;
60 DIV_ROUND_CLOSEST_ULL((s64
)(out_uV
- out
->min_uV
) *
61 (ctrl
->max_uV
- ctrl
->min_uV
),
62 out
->max_uV
- out
->min_uV
);
65 static int vctrl_calc_output_voltage(struct vctrl_data
*vctrl
, int ctrl_uV
)
67 struct vctrl_voltage_range
*ctrl
= &vctrl
->vrange
.ctrl
;
68 struct vctrl_voltage_range
*out
= &vctrl
->vrange
.out
;
71 pr_err("vctrl: failed to get control voltage\n");
75 if (ctrl_uV
< ctrl
->min_uV
)
78 if (ctrl_uV
> ctrl
->max_uV
)
82 DIV_ROUND_CLOSEST_ULL((s64
)(ctrl_uV
- ctrl
->min_uV
) *
83 (out
->max_uV
- out
->min_uV
),
84 ctrl
->max_uV
- ctrl
->min_uV
);
87 static int vctrl_get_voltage(struct regulator_dev
*rdev
)
89 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
90 int ctrl_uV
= regulator_get_voltage(vctrl
->ctrl_reg
);
92 return vctrl_calc_output_voltage(vctrl
, ctrl_uV
);
95 static int vctrl_set_voltage(struct regulator_dev
*rdev
,
96 int req_min_uV
, int req_max_uV
,
97 unsigned int *selector
)
99 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
100 struct regulator
*ctrl_reg
= vctrl
->ctrl_reg
;
101 int orig_ctrl_uV
= regulator_get_voltage(ctrl_reg
);
102 int uV
= vctrl_calc_output_voltage(vctrl
, orig_ctrl_uV
);
105 if (req_min_uV
>= uV
|| !vctrl
->ovp_threshold
)
106 /* voltage rising or no OVP */
107 return regulator_set_voltage(
109 vctrl_calc_ctrl_voltage(vctrl
, req_min_uV
),
110 vctrl_calc_ctrl_voltage(vctrl
, req_max_uV
));
112 while (uV
> req_min_uV
) {
113 int max_drop_uV
= (uV
* vctrl
->ovp_threshold
) / 100;
118 /* Make sure no infinite loop even in crazy cases */
119 if (max_drop_uV
== 0)
122 next_uV
= max_t(int, req_min_uV
, uV
- max_drop_uV
);
123 next_ctrl_uV
= vctrl_calc_ctrl_voltage(vctrl
, next_uV
);
125 ret
= regulator_set_voltage(ctrl_reg
,
131 delay
= DIV_ROUND_UP(uV
- next_uV
, vctrl
->min_slew_down_rate
);
132 usleep_range(delay
, delay
+ DIV_ROUND_UP(delay
, 10));
140 /* Try to go back to original voltage */
141 regulator_set_voltage(ctrl_reg
, orig_ctrl_uV
, orig_ctrl_uV
);
146 static int vctrl_get_voltage_sel(struct regulator_dev
*rdev
)
148 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
153 static int vctrl_set_voltage_sel(struct regulator_dev
*rdev
,
154 unsigned int selector
)
156 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
157 struct regulator
*ctrl_reg
= vctrl
->ctrl_reg
;
158 unsigned int orig_sel
= vctrl
->sel
;
161 if (selector
>= rdev
->desc
->n_voltages
)
164 if (selector
>= vctrl
->sel
|| !vctrl
->ovp_threshold
) {
165 /* voltage rising or no OVP */
166 ret
= regulator_set_voltage(ctrl_reg
,
167 vctrl
->vtable
[selector
].ctrl
,
168 vctrl
->vtable
[selector
].ctrl
);
170 vctrl
->sel
= selector
;
175 while (vctrl
->sel
!= selector
) {
176 unsigned int next_sel
;
179 if (selector
>= vctrl
->vtable
[vctrl
->sel
].ovp_min_sel
)
182 next_sel
= vctrl
->vtable
[vctrl
->sel
].ovp_min_sel
;
184 ret
= regulator_set_voltage(ctrl_reg
,
185 vctrl
->vtable
[next_sel
].ctrl
,
186 vctrl
->vtable
[next_sel
].ctrl
);
189 "failed to set control voltage to %duV\n",
190 vctrl
->vtable
[next_sel
].ctrl
);
193 vctrl
->sel
= next_sel
;
195 delay
= DIV_ROUND_UP(vctrl
->vtable
[vctrl
->sel
].out
-
196 vctrl
->vtable
[next_sel
].out
,
197 vctrl
->min_slew_down_rate
);
198 usleep_range(delay
, delay
+ DIV_ROUND_UP(delay
, 10));
204 if (vctrl
->sel
!= orig_sel
) {
205 /* Try to go back to original voltage */
206 if (!regulator_set_voltage(ctrl_reg
,
207 vctrl
->vtable
[orig_sel
].ctrl
,
208 vctrl
->vtable
[orig_sel
].ctrl
))
209 vctrl
->sel
= orig_sel
;
212 "failed to restore original voltage\n");
218 static int vctrl_list_voltage(struct regulator_dev
*rdev
,
219 unsigned int selector
)
221 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
223 if (selector
>= rdev
->desc
->n_voltages
)
226 return vctrl
->vtable
[selector
].out
;
229 static int vctrl_parse_dt(struct platform_device
*pdev
,
230 struct vctrl_data
*vctrl
)
233 struct device_node
*np
= pdev
->dev
.of_node
;
237 vctrl
->ctrl_reg
= devm_regulator_get(&pdev
->dev
, "ctrl");
238 if (IS_ERR(vctrl
->ctrl_reg
))
239 return PTR_ERR(vctrl
->ctrl_reg
);
241 ret
= of_property_read_u32(np
, "ovp-threshold-percent", &pval
);
243 vctrl
->ovp_threshold
= pval
;
244 if (vctrl
->ovp_threshold
> 100) {
246 "ovp-threshold-percent (%u) > 100\n",
247 vctrl
->ovp_threshold
);
252 ret
= of_property_read_u32(np
, "min-slew-down-rate", &pval
);
254 vctrl
->min_slew_down_rate
= pval
;
256 /* We use the value as int and as divider; sanity check */
257 if (vctrl
->min_slew_down_rate
== 0) {
259 "min-slew-down-rate must not be 0\n");
261 } else if (vctrl
->min_slew_down_rate
> INT_MAX
) {
262 dev_err(&pdev
->dev
, "min-slew-down-rate (%u) too big\n",
263 vctrl
->min_slew_down_rate
);
268 if (vctrl
->ovp_threshold
&& !vctrl
->min_slew_down_rate
) {
270 "ovp-threshold-percent requires min-slew-down-rate\n");
274 ret
= of_property_read_u32(np
, "regulator-min-microvolt", &pval
);
277 "failed to read regulator-min-microvolt: %d\n", ret
);
280 vctrl
->vrange
.out
.min_uV
= pval
;
282 ret
= of_property_read_u32(np
, "regulator-max-microvolt", &pval
);
285 "failed to read regulator-max-microvolt: %d\n", ret
);
288 vctrl
->vrange
.out
.max_uV
= pval
;
290 ret
= of_property_read_u32_array(np
, "ctrl-voltage-range", vrange_ctrl
,
293 dev_err(&pdev
->dev
, "failed to read ctrl-voltage-range: %d\n",
298 if (vrange_ctrl
[0] >= vrange_ctrl
[1]) {
299 dev_err(&pdev
->dev
, "ctrl-voltage-range is invalid: %d-%d\n",
300 vrange_ctrl
[0], vrange_ctrl
[1]);
304 vctrl
->vrange
.ctrl
.min_uV
= vrange_ctrl
[0];
305 vctrl
->vrange
.ctrl
.max_uV
= vrange_ctrl
[1];
310 static int vctrl_cmp_ctrl_uV(const void *a
, const void *b
)
312 const struct vctrl_voltage_table
*at
= a
;
313 const struct vctrl_voltage_table
*bt
= b
;
315 return at
->ctrl
- bt
->ctrl
;
318 static int vctrl_init_vtable(struct platform_device
*pdev
)
320 struct vctrl_data
*vctrl
= platform_get_drvdata(pdev
);
321 struct regulator_desc
*rdesc
= &vctrl
->desc
;
322 struct regulator
*ctrl_reg
= vctrl
->ctrl_reg
;
323 struct vctrl_voltage_range
*vrange_ctrl
= &vctrl
->vrange
.ctrl
;
328 n_voltages
= regulator_count_voltages(ctrl_reg
);
330 rdesc
->n_voltages
= n_voltages
;
332 /* determine number of steps within the range of the vctrl regulator */
333 for (i
= 0; i
< n_voltages
; i
++) {
334 ctrl_uV
= regulator_list_voltage(ctrl_reg
, i
);
336 if (ctrl_uV
< vrange_ctrl
->min_uV
||
337 ctrl_uV
> vrange_ctrl
->max_uV
) {
343 if (rdesc
->n_voltages
== 0) {
344 dev_err(&pdev
->dev
, "invalid configuration\n");
348 vctrl
->vtable
= devm_kcalloc(&pdev
->dev
, rdesc
->n_voltages
,
349 sizeof(struct vctrl_voltage_table
),
354 /* create mapping control <=> output voltage */
355 for (i
= 0, idx_vt
= 0; i
< n_voltages
; i
++) {
356 ctrl_uV
= regulator_list_voltage(ctrl_reg
, i
);
358 if (ctrl_uV
< vrange_ctrl
->min_uV
||
359 ctrl_uV
> vrange_ctrl
->max_uV
)
362 vctrl
->vtable
[idx_vt
].ctrl
= ctrl_uV
;
363 vctrl
->vtable
[idx_vt
].out
=
364 vctrl_calc_output_voltage(vctrl
, ctrl_uV
);
368 /* we rely on the table to be ordered by ascending voltage */
369 sort(vctrl
->vtable
, rdesc
->n_voltages
,
370 sizeof(struct vctrl_voltage_table
), vctrl_cmp_ctrl_uV
,
373 /* pre-calculate OVP-safe downward transitions */
374 for (i
= rdesc
->n_voltages
- 1; i
> 0; i
--) {
376 int ovp_min_uV
= (vctrl
->vtable
[i
].out
*
377 (100 - vctrl
->ovp_threshold
)) / 100;
379 for (j
= 0; j
< i
; j
++) {
380 if (vctrl
->vtable
[j
].out
>= ovp_min_uV
) {
381 vctrl
->vtable
[i
].ovp_min_sel
= j
;
387 dev_warn(&pdev
->dev
, "switching down from %duV may cause OVP shutdown\n",
388 vctrl
->vtable
[i
].out
);
389 /* use next lowest voltage */
390 vctrl
->vtable
[i
].ovp_min_sel
= i
- 1;
397 static int vctrl_enable(struct regulator_dev
*rdev
)
399 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
400 int ret
= regulator_enable(vctrl
->ctrl_reg
);
403 vctrl
->enabled
= true;
408 static int vctrl_disable(struct regulator_dev
*rdev
)
410 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
411 int ret
= regulator_disable(vctrl
->ctrl_reg
);
414 vctrl
->enabled
= false;
419 static int vctrl_is_enabled(struct regulator_dev
*rdev
)
421 struct vctrl_data
*vctrl
= rdev_get_drvdata(rdev
);
423 return vctrl
->enabled
;
426 static const struct regulator_ops vctrl_ops_cont
= {
427 .enable
= vctrl_enable
,
428 .disable
= vctrl_disable
,
429 .is_enabled
= vctrl_is_enabled
,
430 .get_voltage
= vctrl_get_voltage
,
431 .set_voltage
= vctrl_set_voltage
,
434 static const struct regulator_ops vctrl_ops_non_cont
= {
435 .enable
= vctrl_enable
,
436 .disable
= vctrl_disable
,
437 .is_enabled
= vctrl_is_enabled
,
438 .set_voltage_sel
= vctrl_set_voltage_sel
,
439 .get_voltage_sel
= vctrl_get_voltage_sel
,
440 .list_voltage
= vctrl_list_voltage
,
441 .map_voltage
= regulator_map_voltage_iterate
,
444 static int vctrl_probe(struct platform_device
*pdev
)
446 struct device_node
*np
= pdev
->dev
.of_node
;
447 struct vctrl_data
*vctrl
;
448 const struct regulator_init_data
*init_data
;
449 struct regulator_desc
*rdesc
;
450 struct regulator_config cfg
= { };
451 struct vctrl_voltage_range
*vrange_ctrl
;
455 vctrl
= devm_kzalloc(&pdev
->dev
, sizeof(struct vctrl_data
),
460 platform_set_drvdata(pdev
, vctrl
);
462 ret
= vctrl_parse_dt(pdev
, vctrl
);
466 vrange_ctrl
= &vctrl
->vrange
.ctrl
;
468 rdesc
= &vctrl
->desc
;
469 rdesc
->name
= "vctrl";
470 rdesc
->type
= REGULATOR_VOLTAGE
;
471 rdesc
->owner
= THIS_MODULE
;
473 if ((regulator_get_linear_step(vctrl
->ctrl_reg
) == 1) ||
474 (regulator_count_voltages(vctrl
->ctrl_reg
) == -EINVAL
)) {
475 rdesc
->continuous_voltage_range
= true;
476 rdesc
->ops
= &vctrl_ops_cont
;
478 rdesc
->ops
= &vctrl_ops_non_cont
;
481 init_data
= of_get_regulator_init_data(&pdev
->dev
, np
, rdesc
);
486 cfg
.dev
= &pdev
->dev
;
487 cfg
.driver_data
= vctrl
;
488 cfg
.init_data
= init_data
;
490 if (!rdesc
->continuous_voltage_range
) {
491 ret
= vctrl_init_vtable(pdev
);
495 ctrl_uV
= regulator_get_voltage(vctrl
->ctrl_reg
);
497 dev_err(&pdev
->dev
, "failed to get control voltage\n");
501 /* determine current voltage selector from control voltage */
502 if (ctrl_uV
< vrange_ctrl
->min_uV
) {
504 } else if (ctrl_uV
> vrange_ctrl
->max_uV
) {
505 vctrl
->sel
= rdesc
->n_voltages
- 1;
509 for (i
= 0; i
< rdesc
->n_voltages
; i
++) {
510 if (ctrl_uV
== vctrl
->vtable
[i
].ctrl
) {
518 vctrl
->rdev
= devm_regulator_register(&pdev
->dev
, rdesc
, &cfg
);
519 if (IS_ERR(vctrl
->rdev
)) {
520 ret
= PTR_ERR(vctrl
->rdev
);
521 dev_err(&pdev
->dev
, "failed to register regulator: %d\n", ret
);
528 static const struct of_device_id vctrl_of_match
[] = {
529 { .compatible
= "vctrl-regulator", },
532 MODULE_DEVICE_TABLE(of
, vctrl_of_match
);
534 static struct platform_driver vctrl_driver
= {
535 .probe
= vctrl_probe
,
537 .name
= "vctrl-regulator",
538 .of_match_table
= of_match_ptr(vctrl_of_match
),
542 module_platform_driver(vctrl_driver
);
544 MODULE_DESCRIPTION("Voltage Controlled Regulator Driver");
545 MODULE_AUTHOR("Matthias Kaehlcke <mka@chromium.org>");
546 MODULE_LICENSE("GPL v2");