2 * Regulator driver for PWM Regulators
4 * Copyright (C) 2014 - STMicroelectronics Inc.
6 * Author: Lee Jones <lee.jones@linaro.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 #include <linux/delay.h>
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/err.h>
17 #include <linux/regulator/driver.h>
18 #include <linux/regulator/machine.h>
19 #include <linux/regulator/of_regulator.h>
21 #include <linux/of_device.h>
22 #include <linux/pwm.h>
23 #include <linux/gpio/consumer.h>
25 struct pwm_regulator_data
{
27 struct pwm_device
*pwm
;
30 struct pwm_voltages
*duty_cycle_table
;
32 /* regulator descriptor */
33 struct regulator_desc desc
;
36 struct regulator_ops ops
;
40 /* Continuous voltage */
44 struct gpio_desc
*enb_gpio
;
49 unsigned int dutycycle
;
53 * Voltage table call-backs
55 static int pwm_regulator_get_voltage_sel(struct regulator_dev
*rdev
)
57 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
59 return drvdata
->state
;
62 static int pwm_regulator_set_voltage_sel(struct regulator_dev
*rdev
,
65 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
66 struct pwm_args pargs
;
70 pwm_get_args(drvdata
->pwm
, &pargs
);
72 dutycycle
= (pargs
.period
*
73 drvdata
->duty_cycle_table
[selector
].dutycycle
) / 100;
75 ret
= pwm_config(drvdata
->pwm
, dutycycle
, pargs
.period
);
77 dev_err(&rdev
->dev
, "Failed to configure PWM: %d\n", ret
);
81 drvdata
->state
= selector
;
86 static int pwm_regulator_list_voltage(struct regulator_dev
*rdev
,
89 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
91 if (selector
>= rdev
->desc
->n_voltages
)
94 return drvdata
->duty_cycle_table
[selector
].uV
;
97 static int pwm_regulator_enable(struct regulator_dev
*dev
)
99 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(dev
);
101 if (drvdata
->enb_gpio
)
102 gpiod_set_value_cansleep(drvdata
->enb_gpio
, 1);
104 return pwm_enable(drvdata
->pwm
);
107 static int pwm_regulator_disable(struct regulator_dev
*dev
)
109 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(dev
);
111 pwm_disable(drvdata
->pwm
);
113 if (drvdata
->enb_gpio
)
114 gpiod_set_value_cansleep(drvdata
->enb_gpio
, 0);
119 static int pwm_regulator_is_enabled(struct regulator_dev
*dev
)
121 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(dev
);
123 if (drvdata
->enb_gpio
&& !gpiod_get_value_cansleep(drvdata
->enb_gpio
))
126 return pwm_is_enabled(drvdata
->pwm
);
129 static int pwm_regulator_get_voltage(struct regulator_dev
*rdev
)
131 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
133 return drvdata
->volt_uV
;
136 static int pwm_regulator_set_voltage(struct regulator_dev
*rdev
,
137 int min_uV
, int max_uV
,
140 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
141 unsigned int ramp_delay
= rdev
->constraints
->ramp_delay
;
142 struct pwm_args pargs
;
143 unsigned int req_diff
= min_uV
- rdev
->constraints
->min_uV
;
145 unsigned int duty_pulse
;
148 int old_uV
= pwm_regulator_get_voltage(rdev
);
151 pwm_get_args(drvdata
->pwm
, &pargs
);
152 diff
= rdev
->constraints
->max_uV
- rdev
->constraints
->min_uV
;
154 /* First try to find out if we get the iduty cycle time which is
155 * factor of PWM period time. If (request_diff_to_min * pwm_period)
156 * is perfect divided by voltage_range_diff then it is possible to
157 * get duty cycle time which is factor of PWM period. This will help
158 * to get output voltage nearer to requested value as there is no
161 req_period
= req_diff
* pargs
.period
;
162 div_u64_rem(req_period
, diff
, &rem
);
164 do_div(req_period
, diff
);
165 duty_pulse
= (unsigned int)req_period
;
167 duty_pulse
= (pargs
.period
/ 100) * ((req_diff
* 100) / diff
);
170 ret
= pwm_config(drvdata
->pwm
, duty_pulse
, pargs
.period
);
172 dev_err(&rdev
->dev
, "Failed to configure PWM: %d\n", ret
);
176 drvdata
->volt_uV
= min_uV
;
178 if ((ramp_delay
== 0) || !pwm_regulator_is_enabled(rdev
))
181 /* Ramp delay is in uV/uS. Adjust to uS and delay */
182 ramp_delay
= DIV_ROUND_UP(abs(min_uV
- old_uV
), ramp_delay
);
183 usleep_range(ramp_delay
, ramp_delay
+ DIV_ROUND_UP(ramp_delay
, 10));
188 static struct regulator_ops pwm_regulator_voltage_table_ops
= {
189 .set_voltage_sel
= pwm_regulator_set_voltage_sel
,
190 .get_voltage_sel
= pwm_regulator_get_voltage_sel
,
191 .list_voltage
= pwm_regulator_list_voltage
,
192 .map_voltage
= regulator_map_voltage_iterate
,
193 .enable
= pwm_regulator_enable
,
194 .disable
= pwm_regulator_disable
,
195 .is_enabled
= pwm_regulator_is_enabled
,
198 static struct regulator_ops pwm_regulator_voltage_continuous_ops
= {
199 .get_voltage
= pwm_regulator_get_voltage
,
200 .set_voltage
= pwm_regulator_set_voltage
,
201 .enable
= pwm_regulator_enable
,
202 .disable
= pwm_regulator_disable
,
203 .is_enabled
= pwm_regulator_is_enabled
,
206 static struct regulator_desc pwm_regulator_desc
= {
207 .name
= "pwm-regulator",
208 .type
= REGULATOR_VOLTAGE
,
209 .owner
= THIS_MODULE
,
210 .supply_name
= "pwm",
213 static int pwm_regulator_init_table(struct platform_device
*pdev
,
214 struct pwm_regulator_data
*drvdata
)
216 struct device_node
*np
= pdev
->dev
.of_node
;
217 struct pwm_voltages
*duty_cycle_table
;
218 unsigned int length
= 0;
221 of_find_property(np
, "voltage-table", &length
);
223 if ((length
< sizeof(*duty_cycle_table
)) ||
224 (length
% sizeof(*duty_cycle_table
))) {
225 dev_err(&pdev
->dev
, "voltage-table length(%d) is invalid\n",
230 duty_cycle_table
= devm_kzalloc(&pdev
->dev
, length
, GFP_KERNEL
);
231 if (!duty_cycle_table
)
234 ret
= of_property_read_u32_array(np
, "voltage-table",
235 (u32
*)duty_cycle_table
,
236 length
/ sizeof(u32
));
238 dev_err(&pdev
->dev
, "Failed to read voltage-table: %d\n", ret
);
242 drvdata
->duty_cycle_table
= duty_cycle_table
;
243 memcpy(&drvdata
->ops
, &pwm_regulator_voltage_table_ops
,
244 sizeof(drvdata
->ops
));
245 drvdata
->desc
.ops
= &drvdata
->ops
;
246 drvdata
->desc
.n_voltages
= length
/ sizeof(*duty_cycle_table
);
251 static int pwm_regulator_init_continuous(struct platform_device
*pdev
,
252 struct pwm_regulator_data
*drvdata
)
254 memcpy(&drvdata
->ops
, &pwm_regulator_voltage_continuous_ops
,
255 sizeof(drvdata
->ops
));
256 drvdata
->desc
.ops
= &drvdata
->ops
;
257 drvdata
->desc
.continuous_voltage_range
= true;
262 static int pwm_regulator_probe(struct platform_device
*pdev
)
264 const struct regulator_init_data
*init_data
;
265 struct pwm_regulator_data
*drvdata
;
266 struct regulator_dev
*regulator
;
267 struct regulator_config config
= { };
268 struct device_node
*np
= pdev
->dev
.of_node
;
269 enum gpiod_flags gpio_flags
;
273 dev_err(&pdev
->dev
, "Device Tree node missing\n");
277 drvdata
= devm_kzalloc(&pdev
->dev
, sizeof(*drvdata
), GFP_KERNEL
);
281 memcpy(&drvdata
->desc
, &pwm_regulator_desc
, sizeof(drvdata
->desc
));
283 if (of_find_property(np
, "voltage-table", NULL
))
284 ret
= pwm_regulator_init_table(pdev
, drvdata
);
286 ret
= pwm_regulator_init_continuous(pdev
, drvdata
);
290 init_data
= of_get_regulator_init_data(&pdev
->dev
, np
,
296 config
.dev
= &pdev
->dev
;
297 config
.driver_data
= drvdata
;
298 config
.init_data
= init_data
;
300 drvdata
->pwm
= devm_pwm_get(&pdev
->dev
, NULL
);
301 if (IS_ERR(drvdata
->pwm
)) {
302 ret
= PTR_ERR(drvdata
->pwm
);
303 dev_err(&pdev
->dev
, "Failed to get PWM: %d\n", ret
);
307 if (init_data
->constraints
.boot_on
|| init_data
->constraints
.always_on
)
308 gpio_flags
= GPIOD_OUT_HIGH
;
310 gpio_flags
= GPIOD_OUT_LOW
;
311 drvdata
->enb_gpio
= devm_gpiod_get_optional(&pdev
->dev
, "enable",
313 if (IS_ERR(drvdata
->enb_gpio
)) {
314 ret
= PTR_ERR(drvdata
->enb_gpio
);
315 dev_err(&pdev
->dev
, "Failed to get enable GPIO: %d\n", ret
);
320 * FIXME: pwm_apply_args() should be removed when switching to the
323 pwm_apply_args(drvdata
->pwm
);
325 regulator
= devm_regulator_register(&pdev
->dev
,
326 &drvdata
->desc
, &config
);
327 if (IS_ERR(regulator
)) {
328 ret
= PTR_ERR(regulator
);
329 dev_err(&pdev
->dev
, "Failed to register regulator %s: %d\n",
330 drvdata
->desc
.name
, ret
);
337 static const struct of_device_id pwm_of_match
[] = {
338 { .compatible
= "pwm-regulator" },
341 MODULE_DEVICE_TABLE(of
, pwm_of_match
);
343 static struct platform_driver pwm_regulator_driver
= {
345 .name
= "pwm-regulator",
346 .of_match_table
= of_match_ptr(pwm_of_match
),
348 .probe
= pwm_regulator_probe
,
351 module_platform_driver(pwm_regulator_driver
);
353 MODULE_LICENSE("GPL");
354 MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>");
355 MODULE_DESCRIPTION("PWM Regulator Driver");
356 MODULE_ALIAS("platform:pwm-regulator");