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>
23 struct pwm_regulator_data
{
24 struct pwm_voltages
*duty_cycle_table
;
25 struct pwm_device
*pwm
;
31 unsigned int dutycycle
;
34 static int pwm_regulator_get_voltage_sel(struct regulator_dev
*rdev
)
36 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
38 return drvdata
->state
;
41 static int pwm_regulator_set_voltage_sel(struct regulator_dev
*rdev
,
44 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
45 unsigned int pwm_reg_period
;
49 pwm_reg_period
= pwm_get_period(drvdata
->pwm
);
51 dutycycle
= (pwm_reg_period
*
52 drvdata
->duty_cycle_table
[selector
].dutycycle
) / 100;
54 ret
= pwm_config(drvdata
->pwm
, dutycycle
, pwm_reg_period
);
56 dev_err(&rdev
->dev
, "Failed to configure PWM\n");
60 drvdata
->state
= selector
;
62 ret
= pwm_enable(drvdata
->pwm
);
64 dev_err(&rdev
->dev
, "Failed to enable PWM\n");
71 static int pwm_regulator_list_voltage(struct regulator_dev
*rdev
,
74 struct pwm_regulator_data
*drvdata
= rdev_get_drvdata(rdev
);
76 if (selector
>= rdev
->desc
->n_voltages
)
79 return drvdata
->duty_cycle_table
[selector
].uV
;
82 static struct regulator_ops pwm_regulator_voltage_ops
= {
83 .set_voltage_sel
= pwm_regulator_set_voltage_sel
,
84 .get_voltage_sel
= pwm_regulator_get_voltage_sel
,
85 .list_voltage
= pwm_regulator_list_voltage
,
86 .map_voltage
= regulator_map_voltage_iterate
,
89 static struct regulator_desc pwm_regulator_desc
= {
90 .name
= "pwm-regulator",
91 .ops
= &pwm_regulator_voltage_ops
,
92 .type
= REGULATOR_VOLTAGE
,
97 static int pwm_regulator_probe(struct platform_device
*pdev
)
99 struct pwm_regulator_data
*drvdata
;
100 struct property
*prop
;
101 struct regulator_dev
*regulator
;
102 struct regulator_config config
= { };
103 struct device_node
*np
= pdev
->dev
.of_node
;
107 dev_err(&pdev
->dev
, "Device Tree node missing\n");
111 drvdata
= devm_kzalloc(&pdev
->dev
, sizeof(*drvdata
), GFP_KERNEL
);
115 /* determine the number of voltage-table */
116 prop
= of_find_property(np
, "voltage-table", &length
);
118 dev_err(&pdev
->dev
, "No voltage-table\n");
122 if ((length
< sizeof(*drvdata
->duty_cycle_table
)) ||
123 (length
% sizeof(*drvdata
->duty_cycle_table
))) {
124 dev_err(&pdev
->dev
, "voltage-table length(%d) is invalid\n",
129 pwm_regulator_desc
.n_voltages
= length
/ sizeof(*drvdata
->duty_cycle_table
);
131 drvdata
->duty_cycle_table
= devm_kzalloc(&pdev
->dev
,
133 if (!drvdata
->duty_cycle_table
)
136 /* read voltage table from DT property */
137 ret
= of_property_read_u32_array(np
, "voltage-table",
138 (u32
*)drvdata
->duty_cycle_table
,
139 length
/ sizeof(u32
));
141 dev_err(&pdev
->dev
, "read voltage-table failed\n");
145 config
.init_data
= of_get_regulator_init_data(&pdev
->dev
, np
,
146 &pwm_regulator_desc
);
147 if (!config
.init_data
)
151 config
.dev
= &pdev
->dev
;
152 config
.driver_data
= drvdata
;
154 drvdata
->pwm
= devm_pwm_get(&pdev
->dev
, NULL
);
155 if (IS_ERR(drvdata
->pwm
)) {
156 dev_err(&pdev
->dev
, "Failed to get PWM\n");
157 return PTR_ERR(drvdata
->pwm
);
160 regulator
= devm_regulator_register(&pdev
->dev
,
161 &pwm_regulator_desc
, &config
);
162 if (IS_ERR(regulator
)) {
163 dev_err(&pdev
->dev
, "Failed to register regulator %s\n",
164 pwm_regulator_desc
.name
);
165 return PTR_ERR(regulator
);
171 static const struct of_device_id pwm_of_match
[] = {
172 { .compatible
= "pwm-regulator" },
175 MODULE_DEVICE_TABLE(of
, pwm_of_match
);
177 static struct platform_driver pwm_regulator_driver
= {
179 .name
= "pwm-regulator",
180 .of_match_table
= of_match_ptr(pwm_of_match
),
182 .probe
= pwm_regulator_probe
,
185 module_platform_driver(pwm_regulator_driver
);
187 MODULE_LICENSE("GPL");
188 MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>");
189 MODULE_DESCRIPTION("PWM Regulator Driver");
190 MODULE_ALIAS("platform:pwm-regulator");