1 // SPDX-License-Identifier: GPL-2.0-only
3 * Regulator driver for PWM Regulators
5 * Copyright (C) 2014 - STMicroelectronics Inc.
7 * Author: Lee Jones <lee.jones@linaro.org>
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/err.h>
13 #include <linux/regulator/driver.h>
14 #include <linux/regulator/machine.h>
15 #include <linux/regulator/of_regulator.h>
17 #include <linux/of_device.h>
18 #include <linux/pwm.h>
19 #include <linux/gpio/consumer.h>
21 struct pwm_continuous_reg_data
{
22 unsigned int min_uV_dutycycle
;
23 unsigned int max_uV_dutycycle
;
24 unsigned int dutycycle_unit
;
27 struct pwm_regulator_data
{
29 struct pwm_device
*pwm
;
32 struct pwm_voltages
*duty_cycle_table
;
34 /* Continuous mode info */
35 struct pwm_continuous_reg_data continuous
;
37 /* regulator descriptor */
38 struct regulator_desc desc
;
43 struct gpio_desc
*enb_gpio
;
48 unsigned int dutycycle
;
52 * Voltage table call-backs
54 static void pwm_regulator_init_state(struct regulator_dev
*rdev
)
56 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
57 struct pwm_state pwm_state
;
58 unsigned int dutycycle
;
61 pwm_get_state(drvdata
->pwm
, &pwm_state
);
62 dutycycle
= pwm_get_relative_duty_cycle(&pwm_state
, 100);
64 for (i
= 0; i
< rdev
->desc
->n_voltages
; i
++) {
65 if (dutycycle
== drvdata
->duty_cycle_table
[i
].dutycycle
) {
72 static int pwm_regulator_get_voltage_sel(struct regulator_dev
*rdev
)
74 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
76 if (drvdata
->state
< 0)
77 pwm_regulator_init_state(rdev
);
79 return drvdata
->state
;
82 static int pwm_regulator_set_voltage_sel(struct regulator_dev
*rdev
,
85 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
86 struct pwm_state pstate
;
89 pwm_init_state(drvdata
->pwm
, &pstate
);
90 pwm_set_relative_duty_cycle(&pstate
,
91 drvdata
->duty_cycle_table
[selector
].dutycycle
, 100);
93 ret
= pwm_apply_state(drvdata
->pwm
, &pstate
);
95 dev_err(&rdev
->dev
, "Failed to configure PWM: %d\n", ret
);
99 drvdata
->state
= selector
;
104 static int pwm_regulator_list_voltage(struct regulator_dev
*rdev
,
107 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
109 if (selector
>= rdev
->desc
->n_voltages
)
112 return drvdata
->duty_cycle_table
[selector
].uV
;
115 static int pwm_regulator_enable(struct regulator_dev
*dev
)
117 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(dev
);
119 gpiod_set_value_cansleep(drvdata
->enb_gpio
, 1);
121 return pwm_enable(drvdata
->pwm
);
124 static int pwm_regulator_disable(struct regulator_dev
*dev
)
126 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(dev
);
128 pwm_disable(drvdata
->pwm
);
130 gpiod_set_value_cansleep(drvdata
->enb_gpio
, 0);
135 static int pwm_regulator_is_enabled(struct regulator_dev
*dev
)
137 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(dev
);
139 if (drvdata
->enb_gpio
&& !gpiod_get_value_cansleep(drvdata
->enb_gpio
))
142 return pwm_is_enabled(drvdata
->pwm
);
145 static int pwm_regulator_get_voltage(struct regulator_dev
*rdev
)
147 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
148 unsigned int min_uV_duty
= drvdata
->continuous
.min_uV_dutycycle
;
149 unsigned int max_uV_duty
= drvdata
->continuous
.max_uV_dutycycle
;
150 unsigned int duty_unit
= drvdata
->continuous
.dutycycle_unit
;
151 int min_uV
= rdev
->constraints
->min_uV
;
152 int max_uV
= rdev
->constraints
->max_uV
;
153 int diff_uV
= max_uV
- min_uV
;
154 struct pwm_state pstate
;
155 unsigned int diff_duty
;
156 unsigned int voltage
;
158 pwm_get_state(drvdata
->pwm
, &pstate
);
160 voltage
= pwm_get_relative_duty_cycle(&pstate
, duty_unit
);
163 * The dutycycle for min_uV might be greater than the one for max_uV.
164 * This is happening when the user needs an inversed polarity, but the
165 * PWM device does not support inversing it in hardware.
167 if (max_uV_duty
< min_uV_duty
) {
168 voltage
= min_uV_duty
- voltage
;
169 diff_duty
= min_uV_duty
- max_uV_duty
;
171 voltage
= voltage
- min_uV_duty
;
172 diff_duty
= max_uV_duty
- min_uV_duty
;
175 voltage
= DIV_ROUND_CLOSEST_ULL((u64
)voltage
* diff_uV
, diff_duty
);
177 return voltage
+ min_uV
;
180 static int pwm_regulator_set_voltage(struct regulator_dev
*rdev
,
181 int req_min_uV
, int req_max_uV
,
182 unsigned int *selector
)
184 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
185 unsigned int min_uV_duty
= drvdata
->continuous
.min_uV_dutycycle
;
186 unsigned int max_uV_duty
= drvdata
->continuous
.max_uV_dutycycle
;
187 unsigned int duty_unit
= drvdata
->continuous
.dutycycle_unit
;
188 int min_uV
= rdev
->constraints
->min_uV
;
189 int max_uV
= rdev
->constraints
->max_uV
;
190 int diff_uV
= max_uV
- min_uV
;
191 struct pwm_state pstate
;
192 unsigned int diff_duty
;
193 unsigned int dutycycle
;
196 pwm_init_state(drvdata
->pwm
, &pstate
);
199 * The dutycycle for min_uV might be greater than the one for max_uV.
200 * This is happening when the user needs an inversed polarity, but the
201 * PWM device does not support inversing it in hardware.
203 if (max_uV_duty
< min_uV_duty
)
204 diff_duty
= min_uV_duty
- max_uV_duty
;
206 diff_duty
= max_uV_duty
- min_uV_duty
;
208 dutycycle
= DIV_ROUND_CLOSEST_ULL((u64
)(req_min_uV
- min_uV
) *
212 if (max_uV_duty
< min_uV_duty
)
213 dutycycle
= min_uV_duty
- dutycycle
;
215 dutycycle
= min_uV_duty
+ dutycycle
;
217 pwm_set_relative_duty_cycle(&pstate
, dutycycle
, duty_unit
);
219 ret
= pwm_apply_state(drvdata
->pwm
, &pstate
);
221 dev_err(&rdev
->dev
, "Failed to configure PWM: %d\n", ret
);
228 static const struct regulator_ops pwm_regulator_voltage_table_ops
= {
229 .set_voltage_sel
= pwm_regulator_set_voltage_sel
,
230 .get_voltage_sel
= pwm_regulator_get_voltage_sel
,
231 .list_voltage
= pwm_regulator_list_voltage
,
232 .map_voltage
= regulator_map_voltage_iterate
,
233 .enable
= pwm_regulator_enable
,
234 .disable
= pwm_regulator_disable
,
235 .is_enabled
= pwm_regulator_is_enabled
,
238 static const struct regulator_ops pwm_regulator_voltage_continuous_ops
= {
239 .get_voltage
= pwm_regulator_get_voltage
,
240 .set_voltage
= pwm_regulator_set_voltage
,
241 .enable
= pwm_regulator_enable
,
242 .disable
= pwm_regulator_disable
,
243 .is_enabled
= pwm_regulator_is_enabled
,
246 static const struct regulator_desc pwm_regulator_desc
= {
247 .name
= "pwm-regulator",
248 .type
= REGULATOR_VOLTAGE
,
249 .owner
= THIS_MODULE
,
250 .supply_name
= "pwm",
253 static int pwm_regulator_init_table(struct platform_device
*pdev
,
254 struct pwm_regulator_data
*drvdata
)
256 struct device_node
*np
= pdev
->dev
.of_node
;
257 struct pwm_voltages
*duty_cycle_table
;
258 unsigned int length
= 0;
261 of_find_property(np
, "voltage-table", &length
);
263 if ((length
< sizeof(*duty_cycle_table
)) ||
264 (length
% sizeof(*duty_cycle_table
))) {
265 dev_err(&pdev
->dev
, "voltage-table length(%d) is invalid\n",
270 duty_cycle_table
= devm_kzalloc(&pdev
->dev
, length
, GFP_KERNEL
);
271 if (!duty_cycle_table
)
274 ret
= of_property_read_u32_array(np
, "voltage-table",
275 (u32
*)duty_cycle_table
,
276 length
/ sizeof(u32
));
278 dev_err(&pdev
->dev
, "Failed to read voltage-table: %d\n", ret
);
282 drvdata
->state
= -ENOTRECOVERABLE
;
283 drvdata
->duty_cycle_table
= duty_cycle_table
;
284 drvdata
->desc
.ops
= &pwm_regulator_voltage_table_ops
;
285 drvdata
->desc
.n_voltages
= length
/ sizeof(*duty_cycle_table
);
290 static int pwm_regulator_init_continuous(struct platform_device
*pdev
,
291 struct pwm_regulator_data
*drvdata
)
293 u32 dutycycle_range
[2] = { 0, 100 };
294 u32 dutycycle_unit
= 100;
296 drvdata
->desc
.ops
= &pwm_regulator_voltage_continuous_ops
;
297 drvdata
->desc
.continuous_voltage_range
= true;
299 of_property_read_u32_array(pdev
->dev
.of_node
,
300 "pwm-dutycycle-range",
302 of_property_read_u32(pdev
->dev
.of_node
, "pwm-dutycycle-unit",
305 if (dutycycle_range
[0] > dutycycle_unit
||
306 dutycycle_range
[1] > dutycycle_unit
)
309 drvdata
->continuous
.dutycycle_unit
= dutycycle_unit
;
310 drvdata
->continuous
.min_uV_dutycycle
= dutycycle_range
[0];
311 drvdata
->continuous
.max_uV_dutycycle
= dutycycle_range
[1];
316 static int pwm_regulator_probe(struct platform_device
*pdev
)
318 const struct regulator_init_data
*init_data
;
319 struct pwm_regulator_data
*drvdata
;
320 struct regulator_dev
*regulator
;
321 struct regulator_config config
= { };
322 struct device_node
*np
= pdev
->dev
.of_node
;
323 enum gpiod_flags gpio_flags
;
327 dev_err(&pdev
->dev
, "Device Tree node missing\n");
331 drvdata
= devm_kzalloc(&pdev
->dev
, sizeof(*drvdata
), GFP_KERNEL
);
335 memcpy(&drvdata
->desc
, &pwm_regulator_desc
, sizeof(drvdata
->desc
));
337 if (of_find_property(np
, "voltage-table", NULL
))
338 ret
= pwm_regulator_init_table(pdev
, drvdata
);
340 ret
= pwm_regulator_init_continuous(pdev
, drvdata
);
344 init_data
= of_get_regulator_init_data(&pdev
->dev
, np
,
350 config
.dev
= &pdev
->dev
;
351 config
.driver_data
= drvdata
;
352 config
.init_data
= init_data
;
354 drvdata
->pwm
= devm_pwm_get(&pdev
->dev
, NULL
);
355 if (IS_ERR(drvdata
->pwm
)) {
356 ret
= PTR_ERR(drvdata
->pwm
);
357 if (ret
== -EPROBE_DEFER
)
359 "Failed to get PWM, deferring probe\n");
361 dev_err(&pdev
->dev
, "Failed to get PWM: %d\n", ret
);
365 if (init_data
->constraints
.boot_on
|| init_data
->constraints
.always_on
)
366 gpio_flags
= GPIOD_OUT_HIGH
;
368 gpio_flags
= GPIOD_OUT_LOW
;
369 drvdata
->enb_gpio
= devm_gpiod_get_optional(&pdev
->dev
, "enable",
371 if (IS_ERR(drvdata
->enb_gpio
)) {
372 ret
= PTR_ERR(drvdata
->enb_gpio
);
373 dev_err(&pdev
->dev
, "Failed to get enable GPIO: %d\n", ret
);
377 ret
= pwm_adjust_config(drvdata
->pwm
);
381 regulator
= devm_regulator_register(&pdev
->dev
,
382 &drvdata
->desc
, &config
);
383 if (IS_ERR(regulator
)) {
384 ret
= PTR_ERR(regulator
);
385 dev_err(&pdev
->dev
, "Failed to register regulator %s: %d\n",
386 drvdata
->desc
.name
, ret
);
393 static const struct of_device_id __maybe_unused pwm_of_match
[] = {
394 { .compatible
= "pwm-regulator" },
397 MODULE_DEVICE_TABLE(of
, pwm_of_match
);
399 static struct platform_driver pwm_regulator_driver
= {
401 .name
= "pwm-regulator",
402 .of_match_table
= of_match_ptr(pwm_of_match
),
404 .probe
= pwm_regulator_probe
,
407 module_platform_driver(pwm_regulator_driver
);
409 MODULE_LICENSE("GPL");
410 MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>");
411 MODULE_DESCRIPTION("PWM Regulator Driver");
412 MODULE_ALIAS("platform:pwm-regulator");