• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Regulator driver for PWM Regulators
3  *
4  * Copyright (C) 2014 - STMicroelectronics Inc.
5  *
6  * Author: Lee Jones <lee.jones@linaro.org>
7  *
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.
11  */
12 
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>
20 #include <linux/of.h>
21 #include <linux/of_device.h>
22 #include <linux/pwm.h>
23 
24 struct pwm_regulator_data {
25 	/*  Shared */
26 	struct pwm_device *pwm;
27 
28 	/* Voltage table */
29 	struct pwm_voltages *duty_cycle_table;
30 	int state;
31 
32 	/* Continuous voltage */
33 	int volt_uV;
34 };
35 
36 struct pwm_voltages {
37 	unsigned int uV;
38 	unsigned int dutycycle;
39 };
40 
41 /**
42  * Voltage table call-backs
43  */
pwm_regulator_get_voltage_sel(struct regulator_dev * rdev)44 static int pwm_regulator_get_voltage_sel(struct regulator_dev *rdev)
45 {
46 	struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
47 
48 	return drvdata->state;
49 }
50 
pwm_regulator_set_voltage_sel(struct regulator_dev * rdev,unsigned selector)51 static int pwm_regulator_set_voltage_sel(struct regulator_dev *rdev,
52 					 unsigned selector)
53 {
54 	struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
55 	unsigned int pwm_reg_period;
56 	int dutycycle;
57 	int ret;
58 
59 	pwm_reg_period = pwm_get_period(drvdata->pwm);
60 
61 	dutycycle = (pwm_reg_period *
62 		    drvdata->duty_cycle_table[selector].dutycycle) / 100;
63 
64 	ret = pwm_config(drvdata->pwm, dutycycle, pwm_reg_period);
65 	if (ret) {
66 		dev_err(&rdev->dev, "Failed to configure PWM\n");
67 		return ret;
68 	}
69 
70 	drvdata->state = selector;
71 
72 	return 0;
73 }
74 
pwm_regulator_list_voltage(struct regulator_dev * rdev,unsigned selector)75 static int pwm_regulator_list_voltage(struct regulator_dev *rdev,
76 				      unsigned selector)
77 {
78 	struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
79 
80 	if (selector >= rdev->desc->n_voltages)
81 		return -EINVAL;
82 
83 	return drvdata->duty_cycle_table[selector].uV;
84 }
85 
pwm_regulator_enable(struct regulator_dev * dev)86 static int pwm_regulator_enable(struct regulator_dev *dev)
87 {
88 	struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
89 
90 	return pwm_enable(drvdata->pwm);
91 }
92 
pwm_regulator_disable(struct regulator_dev * dev)93 static int pwm_regulator_disable(struct regulator_dev *dev)
94 {
95 	struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
96 
97 	pwm_disable(drvdata->pwm);
98 
99 	return 0;
100 }
101 
pwm_regulator_is_enabled(struct regulator_dev * dev)102 static int pwm_regulator_is_enabled(struct regulator_dev *dev)
103 {
104 	struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
105 
106 	return pwm_is_enabled(drvdata->pwm);
107 }
108 
109 /**
110  * Continuous voltage call-backs
111  */
pwm_voltage_to_duty_cycle_percentage(struct regulator_dev * rdev,int req_uV)112 static int pwm_voltage_to_duty_cycle_percentage(struct regulator_dev *rdev, int req_uV)
113 {
114 	int min_uV = rdev->constraints->min_uV;
115 	int max_uV = rdev->constraints->max_uV;
116 	int diff = max_uV - min_uV;
117 
118 	return 100 - (((req_uV * 100) - (min_uV * 100)) / diff);
119 }
120 
pwm_regulator_get_voltage(struct regulator_dev * rdev)121 static int pwm_regulator_get_voltage(struct regulator_dev *rdev)
122 {
123 	struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
124 
125 	return drvdata->volt_uV;
126 }
127 
pwm_regulator_set_voltage(struct regulator_dev * rdev,int min_uV,int max_uV,unsigned * selector)128 static int pwm_regulator_set_voltage(struct regulator_dev *rdev,
129 					int min_uV, int max_uV,
130 					unsigned *selector)
131 {
132 	struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
133 	unsigned int ramp_delay = rdev->constraints->ramp_delay;
134 	unsigned int period = pwm_get_period(drvdata->pwm);
135 	int duty_cycle;
136 	int ret;
137 
138 	duty_cycle = pwm_voltage_to_duty_cycle_percentage(rdev, min_uV);
139 
140 	ret = pwm_config(drvdata->pwm, (period / 100) * duty_cycle, period);
141 	if (ret) {
142 		dev_err(&rdev->dev, "Failed to configure PWM\n");
143 		return ret;
144 	}
145 
146 	ret = pwm_enable(drvdata->pwm);
147 	if (ret) {
148 		dev_err(&rdev->dev, "Failed to enable PWM\n");
149 		return ret;
150 	}
151 	drvdata->volt_uV = min_uV;
152 
153 	/* Delay required by PWM regulator to settle to the new voltage */
154 	usleep_range(ramp_delay, ramp_delay + 1000);
155 
156 	return 0;
157 }
158 
159 static struct regulator_ops pwm_regulator_voltage_table_ops = {
160 	.set_voltage_sel = pwm_regulator_set_voltage_sel,
161 	.get_voltage_sel = pwm_regulator_get_voltage_sel,
162 	.list_voltage    = pwm_regulator_list_voltage,
163 	.map_voltage     = regulator_map_voltage_iterate,
164 	.enable          = pwm_regulator_enable,
165 	.disable         = pwm_regulator_disable,
166 	.is_enabled      = pwm_regulator_is_enabled,
167 };
168 
169 static struct regulator_ops pwm_regulator_voltage_continuous_ops = {
170 	.get_voltage = pwm_regulator_get_voltage,
171 	.set_voltage = pwm_regulator_set_voltage,
172 	.enable          = pwm_regulator_enable,
173 	.disable         = pwm_regulator_disable,
174 	.is_enabled      = pwm_regulator_is_enabled,
175 };
176 
177 static struct regulator_desc pwm_regulator_desc = {
178 	.name		= "pwm-regulator",
179 	.type		= REGULATOR_VOLTAGE,
180 	.owner		= THIS_MODULE,
181 	.supply_name    = "pwm",
182 };
183 
pwm_regulator_init_table(struct platform_device * pdev,struct pwm_regulator_data * drvdata)184 static int pwm_regulator_init_table(struct platform_device *pdev,
185 				    struct pwm_regulator_data *drvdata)
186 {
187 	struct device_node *np = pdev->dev.of_node;
188 	struct pwm_voltages *duty_cycle_table;
189 	unsigned int length = 0;
190 	int ret;
191 
192 	of_find_property(np, "voltage-table", &length);
193 
194 	if ((length < sizeof(*duty_cycle_table)) ||
195 	    (length % sizeof(*duty_cycle_table))) {
196 		dev_err(&pdev->dev,
197 			"voltage-table length(%d) is invalid\n",
198 			length);
199 		return -EINVAL;
200 	}
201 
202 	duty_cycle_table = devm_kzalloc(&pdev->dev, length, GFP_KERNEL);
203 	if (!duty_cycle_table)
204 		return -ENOMEM;
205 
206 	ret = of_property_read_u32_array(np, "voltage-table",
207 					 (u32 *)duty_cycle_table,
208 					 length / sizeof(u32));
209 	if (ret) {
210 		dev_err(&pdev->dev, "Failed to read voltage-table\n");
211 		return ret;
212 	}
213 
214 	drvdata->duty_cycle_table	= duty_cycle_table;
215 	pwm_regulator_desc.ops		= &pwm_regulator_voltage_table_ops;
216 	pwm_regulator_desc.n_voltages	= length / sizeof(*duty_cycle_table);
217 
218 	return 0;
219 }
220 
pwm_regulator_init_continuous(struct platform_device * pdev,struct pwm_regulator_data * drvdata)221 static int pwm_regulator_init_continuous(struct platform_device *pdev,
222 					 struct pwm_regulator_data *drvdata)
223 {
224 	pwm_regulator_desc.ops = &pwm_regulator_voltage_continuous_ops;
225 	pwm_regulator_desc.continuous_voltage_range = true;
226 
227 	return 0;
228 }
229 
pwm_regulator_probe(struct platform_device * pdev)230 static int pwm_regulator_probe(struct platform_device *pdev)
231 {
232 	const struct regulator_init_data *init_data;
233 	struct pwm_regulator_data *drvdata;
234 	struct regulator_dev *regulator;
235 	struct regulator_config config = { };
236 	struct device_node *np = pdev->dev.of_node;
237 	int ret;
238 
239 	if (!np) {
240 		dev_err(&pdev->dev, "Device Tree node missing\n");
241 		return -EINVAL;
242 	}
243 
244 	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
245 	if (!drvdata)
246 		return -ENOMEM;
247 
248 	if (of_find_property(np, "voltage-table", NULL))
249 		ret = pwm_regulator_init_table(pdev, drvdata);
250 	else
251 		ret = pwm_regulator_init_continuous(pdev, drvdata);
252 	if (ret)
253 		return ret;
254 
255 	init_data = of_get_regulator_init_data(&pdev->dev, np,
256 					       &pwm_regulator_desc);
257 	if (!init_data)
258 		return -ENOMEM;
259 
260 	config.of_node = np;
261 	config.dev = &pdev->dev;
262 	config.driver_data = drvdata;
263 	config.init_data = init_data;
264 
265 	drvdata->pwm = devm_pwm_get(&pdev->dev, NULL);
266 	if (IS_ERR(drvdata->pwm)) {
267 		dev_err(&pdev->dev, "Failed to get PWM\n");
268 		return PTR_ERR(drvdata->pwm);
269 	}
270 
271 	regulator = devm_regulator_register(&pdev->dev,
272 					    &pwm_regulator_desc, &config);
273 	if (IS_ERR(regulator)) {
274 		dev_err(&pdev->dev, "Failed to register regulator %s\n",
275 			pwm_regulator_desc.name);
276 		return PTR_ERR(regulator);
277 	}
278 
279 	return 0;
280 }
281 
282 static const struct of_device_id pwm_of_match[] = {
283 	{ .compatible = "pwm-regulator" },
284 	{ },
285 };
286 MODULE_DEVICE_TABLE(of, pwm_of_match);
287 
288 static struct platform_driver pwm_regulator_driver = {
289 	.driver = {
290 		.name		= "pwm-regulator",
291 		.of_match_table = of_match_ptr(pwm_of_match),
292 	},
293 	.probe = pwm_regulator_probe,
294 };
295 
296 module_platform_driver(pwm_regulator_driver);
297 
298 MODULE_LICENSE("GPL");
299 MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>");
300 MODULE_DESCRIPTION("PWM Regulator Driver");
301 MODULE_ALIAS("platform:pwm-regulator");
302