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/module.h>
14 #include <linux/init.h>
15 #include <linux/err.h>
16 #include <linux/regulator/driver.h>
17 #include <linux/regulator/machine.h>
18 #include <linux/regulator/of_regulator.h>
20 #include <linux/of_device.h>
21 #include <linux/pwm.h>
22 #include <linux/gpio/consumer.h>
24 struct pwm_continuous_reg_data
{
25 unsigned int min_uV_dutycycle
;
26 unsigned int max_uV_dutycycle
;
27 unsigned int dutycycle_unit
;
30 struct pwm_regulator_data
{
32 struct pwm_device
*pwm
;
35 struct pwm_voltages
*duty_cycle_table
;
37 /* Continuous mode info */
38 struct pwm_continuous_reg_data continuous
;
40 /* regulator descriptor */
41 struct regulator_desc desc
;
44 struct regulator_ops ops
;
49 struct gpio_desc
*enb_gpio
;
54 unsigned int dutycycle
;
58 * Voltage table call-backs
60 static void pwm_regulator_init_state(struct regulator_dev
*rdev
)
62 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
63 struct pwm_state pwm_state
;
64 unsigned int dutycycle
;
67 pwm_get_state(drvdata
->pwm
, &pwm_state
);
68 dutycycle
= pwm_get_relative_duty_cycle(&pwm_state
, 100);
70 for (i
= 0; i
< rdev
->desc
->n_voltages
; i
++) {
71 if (dutycycle
== drvdata
->duty_cycle_table
[i
].dutycycle
) {
78 static int pwm_regulator_get_voltage_sel(struct regulator_dev
*rdev
)
80 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
82 if (drvdata
->state
< 0)
83 pwm_regulator_init_state(rdev
);
85 return drvdata
->state
;
88 static int pwm_regulator_set_voltage_sel(struct regulator_dev
*rdev
,
91 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
92 struct pwm_state pstate
;
95 pwm_init_state(drvdata
->pwm
, &pstate
);
96 pwm_set_relative_duty_cycle(&pstate
,
97 drvdata
->duty_cycle_table
[selector
].dutycycle
, 100);
99 ret
= pwm_apply_state(drvdata
->pwm
, &pstate
);
101 dev_err(&rdev
->dev
, "Failed to configure PWM: %d\n", ret
);
105 drvdata
->state
= selector
;
110 static int pwm_regulator_list_voltage(struct regulator_dev
*rdev
,
113 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
115 if (selector
>= rdev
->desc
->n_voltages
)
118 return drvdata
->duty_cycle_table
[selector
].uV
;
121 static int pwm_regulator_enable(struct regulator_dev
*dev
)
123 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(dev
);
125 gpiod_set_value_cansleep(drvdata
->enb_gpio
, 1);
127 return pwm_enable(drvdata
->pwm
);
130 static int pwm_regulator_disable(struct regulator_dev
*dev
)
132 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(dev
);
134 pwm_disable(drvdata
->pwm
);
136 gpiod_set_value_cansleep(drvdata
->enb_gpio
, 0);
141 static int pwm_regulator_is_enabled(struct regulator_dev
*dev
)
143 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(dev
);
145 if (drvdata
->enb_gpio
&& !gpiod_get_value_cansleep(drvdata
->enb_gpio
))
148 return pwm_is_enabled(drvdata
->pwm
);
151 static int pwm_regulator_get_voltage(struct regulator_dev
*rdev
)
153 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
154 unsigned int min_uV_duty
= drvdata
->continuous
.min_uV_dutycycle
;
155 unsigned int max_uV_duty
= drvdata
->continuous
.max_uV_dutycycle
;
156 unsigned int duty_unit
= drvdata
->continuous
.dutycycle_unit
;
157 int min_uV
= rdev
->constraints
->min_uV
;
158 int max_uV
= rdev
->constraints
->max_uV
;
159 int diff_uV
= max_uV
- min_uV
;
160 struct pwm_state pstate
;
161 unsigned int diff_duty
;
162 unsigned int voltage
;
164 pwm_get_state(drvdata
->pwm
, &pstate
);
166 voltage
= pwm_get_relative_duty_cycle(&pstate
, duty_unit
);
169 * The dutycycle for min_uV might be greater than the one for max_uV.
170 * This is happening when the user needs an inversed polarity, but the
171 * PWM device does not support inversing it in hardware.
173 if (max_uV_duty
< min_uV_duty
) {
174 voltage
= min_uV_duty
- voltage
;
175 diff_duty
= min_uV_duty
- max_uV_duty
;
177 voltage
= voltage
- min_uV_duty
;
178 diff_duty
= max_uV_duty
- min_uV_duty
;
181 voltage
= DIV_ROUND_CLOSEST_ULL((u64
)voltage
* diff_uV
, diff_duty
);
183 return voltage
+ min_uV
;
186 static int pwm_regulator_set_voltage(struct regulator_dev
*rdev
,
187 int req_min_uV
, int req_max_uV
,
188 unsigned int *selector
)
190 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
191 unsigned int min_uV_duty
= drvdata
->continuous
.min_uV_dutycycle
;
192 unsigned int max_uV_duty
= drvdata
->continuous
.max_uV_dutycycle
;
193 unsigned int duty_unit
= drvdata
->continuous
.dutycycle_unit
;
194 int min_uV
= rdev
->constraints
->min_uV
;
195 int max_uV
= rdev
->constraints
->max_uV
;
196 int diff_uV
= max_uV
- min_uV
;
197 struct pwm_state pstate
;
198 unsigned int diff_duty
;
199 unsigned int dutycycle
;
202 pwm_init_state(drvdata
->pwm
, &pstate
);
205 * The dutycycle for min_uV might be greater than the one for max_uV.
206 * This is happening when the user needs an inversed polarity, but the
207 * PWM device does not support inversing it in hardware.
209 if (max_uV_duty
< min_uV_duty
)
210 diff_duty
= min_uV_duty
- max_uV_duty
;
212 diff_duty
= max_uV_duty
- min_uV_duty
;
214 dutycycle
= DIV_ROUND_CLOSEST_ULL((u64
)(req_min_uV
- min_uV
) *
218 if (max_uV_duty
< min_uV_duty
)
219 dutycycle
= min_uV_duty
- dutycycle
;
221 dutycycle
= min_uV_duty
+ dutycycle
;
223 pwm_set_relative_duty_cycle(&pstate
, dutycycle
, duty_unit
);
225 ret
= pwm_apply_state(drvdata
->pwm
, &pstate
);
227 dev_err(&rdev
->dev
, "Failed to configure PWM: %d\n", ret
);
234 static struct regulator_ops pwm_regulator_voltage_table_ops
= {
235 .set_voltage_sel
= pwm_regulator_set_voltage_sel
,
236 .get_voltage_sel
= pwm_regulator_get_voltage_sel
,
237 .list_voltage
= pwm_regulator_list_voltage
,
238 .map_voltage
= regulator_map_voltage_iterate
,
239 .enable
= pwm_regulator_enable
,
240 .disable
= pwm_regulator_disable
,
241 .is_enabled
= pwm_regulator_is_enabled
,
244 static struct regulator_ops pwm_regulator_voltage_continuous_ops
= {
245 .get_voltage
= pwm_regulator_get_voltage
,
246 .set_voltage
= pwm_regulator_set_voltage
,
247 .enable
= pwm_regulator_enable
,
248 .disable
= pwm_regulator_disable
,
249 .is_enabled
= pwm_regulator_is_enabled
,
252 static struct regulator_desc pwm_regulator_desc
= {
253 .name
= "pwm-regulator",
254 .type
= REGULATOR_VOLTAGE
,
255 .owner
= THIS_MODULE
,
256 .supply_name
= "pwm",
259 static int pwm_regulator_init_table(struct platform_device
*pdev
,
260 struct pwm_regulator_data
*drvdata
)
262 struct device_node
*np
= pdev
->dev
.of_node
;
263 struct pwm_voltages
*duty_cycle_table
;
264 unsigned int length
= 0;
267 of_find_property(np
, "voltage-table", &length
);
269 if ((length
< sizeof(*duty_cycle_table
)) ||
270 (length
% sizeof(*duty_cycle_table
))) {
271 dev_err(&pdev
->dev
, "voltage-table length(%d) is invalid\n",
276 duty_cycle_table
= devm_kzalloc(&pdev
->dev
, length
, GFP_KERNEL
);
277 if (!duty_cycle_table
)
280 ret
= of_property_read_u32_array(np
, "voltage-table",
281 (u32
*)duty_cycle_table
,
282 length
/ sizeof(u32
));
284 dev_err(&pdev
->dev
, "Failed to read voltage-table: %d\n", ret
);
288 drvdata
->state
= -EINVAL
;
289 drvdata
->duty_cycle_table
= duty_cycle_table
;
290 memcpy(&drvdata
->ops
, &pwm_regulator_voltage_table_ops
,
291 sizeof(drvdata
->ops
));
292 drvdata
->desc
.ops
= &drvdata
->ops
;
293 drvdata
->desc
.n_voltages
= length
/ sizeof(*duty_cycle_table
);
298 static int pwm_regulator_init_continuous(struct platform_device
*pdev
,
299 struct pwm_regulator_data
*drvdata
)
301 u32 dutycycle_range
[2] = { 0, 100 };
302 u32 dutycycle_unit
= 100;
304 memcpy(&drvdata
->ops
, &pwm_regulator_voltage_continuous_ops
,
305 sizeof(drvdata
->ops
));
306 drvdata
->desc
.ops
= &drvdata
->ops
;
307 drvdata
->desc
.continuous_voltage_range
= true;
309 of_property_read_u32_array(pdev
->dev
.of_node
,
310 "pwm-dutycycle-range",
312 of_property_read_u32(pdev
->dev
.of_node
, "pwm-dutycycle-unit",
315 if (dutycycle_range
[0] > dutycycle_unit
||
316 dutycycle_range
[1] > dutycycle_unit
)
319 drvdata
->continuous
.dutycycle_unit
= dutycycle_unit
;
320 drvdata
->continuous
.min_uV_dutycycle
= dutycycle_range
[0];
321 drvdata
->continuous
.max_uV_dutycycle
= dutycycle_range
[1];
326 static int pwm_regulator_probe(struct platform_device
*pdev
)
328 const struct regulator_init_data
*init_data
;
329 struct pwm_regulator_data
*drvdata
;
330 struct regulator_dev
*regulator
;
331 struct regulator_config config
= { };
332 struct device_node
*np
= pdev
->dev
.of_node
;
333 enum gpiod_flags gpio_flags
;
337 dev_err(&pdev
->dev
, "Device Tree node missing\n");
341 drvdata
= devm_kzalloc(&pdev
->dev
, sizeof(*drvdata
), GFP_KERNEL
);
345 memcpy(&drvdata
->desc
, &pwm_regulator_desc
, sizeof(drvdata
->desc
));
347 if (of_find_property(np
, "voltage-table", NULL
))
348 ret
= pwm_regulator_init_table(pdev
, drvdata
);
350 ret
= pwm_regulator_init_continuous(pdev
, drvdata
);
354 init_data
= of_get_regulator_init_data(&pdev
->dev
, np
,
360 config
.dev
= &pdev
->dev
;
361 config
.driver_data
= drvdata
;
362 config
.init_data
= init_data
;
364 drvdata
->pwm
= devm_pwm_get(&pdev
->dev
, NULL
);
365 if (IS_ERR(drvdata
->pwm
)) {
366 ret
= PTR_ERR(drvdata
->pwm
);
367 dev_err(&pdev
->dev
, "Failed to get PWM: %d\n", ret
);
371 if (init_data
->constraints
.boot_on
|| init_data
->constraints
.always_on
)
372 gpio_flags
= GPIOD_OUT_HIGH
;
374 gpio_flags
= GPIOD_OUT_LOW
;
375 drvdata
->enb_gpio
= devm_gpiod_get_optional(&pdev
->dev
, "enable",
377 if (IS_ERR(drvdata
->enb_gpio
)) {
378 ret
= PTR_ERR(drvdata
->enb_gpio
);
379 dev_err(&pdev
->dev
, "Failed to get enable GPIO: %d\n", ret
);
383 ret
= pwm_adjust_config(drvdata
->pwm
);
387 regulator
= devm_regulator_register(&pdev
->dev
,
388 &drvdata
->desc
, &config
);
389 if (IS_ERR(regulator
)) {
390 ret
= PTR_ERR(regulator
);
391 dev_err(&pdev
->dev
, "Failed to register regulator %s: %d\n",
392 drvdata
->desc
.name
, ret
);
399 static const struct of_device_id pwm_of_match
[] = {
400 { .compatible
= "pwm-regulator" },
403 MODULE_DEVICE_TABLE(of
, pwm_of_match
);
405 static struct platform_driver pwm_regulator_driver
= {
407 .name
= "pwm-regulator",
408 .of_match_table
= of_match_ptr(pwm_of_match
),
410 .probe
= pwm_regulator_probe
,
413 module_platform_driver(pwm_regulator_driver
);
415 MODULE_LICENSE("GPL");
416 MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>");
417 MODULE_DESCRIPTION("PWM Regulator Driver");
418 MODULE_ALIAS("platform:pwm-regulator");