aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChris Zhong <zyw@rock-chips.com>2014-09-27 22:28:53 -0400
committerMark Brown <broonie@kernel.org>2014-09-28 06:35:53 -0400
commitaa66cc6630a4088e84b64992aa5f137711ae45fa (patch)
treece2c2439297c720528c8e3aeeca6c6673f483aa0 /drivers
parent7d1311b93e58ed55f3a31cc8f94c4b8fe988a2b9 (diff)
regulator: pwm-regulator: get voltage and duty table from dts
rename st-pwm to pwm-regulator. And support getting voltage & duty table from device tree, other platforms can also use this driver without any modify. Signed-off-by: Chris Zhong <zyw@rock-chips.com> Reviewed-by: Doug Anderson <dianders@chromium.org> Tested-by: Doug Anderson <dianders@chromium.org> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/regulator/Kconfig13
-rw-r--r--drivers/regulator/Makefile2
-rw-r--r--drivers/regulator/pwm-regulator.c197
-rw-r--r--drivers/regulator/st-pwm.c190
4 files changed, 205 insertions, 197 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 2dc8289e5dba..b0ff94a6e45d 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -449,6 +449,13 @@ config REGULATOR_PFUZE100
449 Say y here to support the regulators found on the Freescale 449 Say y here to support the regulators found on the Freescale
450 PFUZE100/PFUZE200 PMIC. 450 PFUZE100/PFUZE200 PMIC.
451 451
452config REGULATOR_PWM
453 tristate "PWM voltage regulator"
454 depends on PWM
455 help
456 This driver supports PWM controlled voltage regulators. PWM
457 duty cycle can increase or decrease the voltage.
458
452config REGULATOR_RC5T583 459config REGULATOR_RC5T583
453 tristate "RICOH RC5T583 Power regulators" 460 tristate "RICOH RC5T583 Power regulators"
454 depends on MFD_RC5T583 461 depends on MFD_RC5T583
@@ -483,12 +490,6 @@ config REGULATOR_S5M8767
483 via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and 490 via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and
484 supports DVS mode with 8bits of output voltage control. 491 supports DVS mode with 8bits of output voltage control.
485 492
486config REGULATOR_ST_PWM
487 tristate "STMicroelectronics PWM voltage regulator"
488 depends on ARCH_STI
489 help
490 This driver supports ST's PWM controlled voltage regulators.
491
492config REGULATOR_TI_ABB 493config REGULATOR_TI_ABB
493 tristate "TI Adaptive Body Bias on-chip LDO" 494 tristate "TI Adaptive Body Bias on-chip LDO"
494 depends on ARCH_OMAP 495 depends on ARCH_OMAP
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index aa4a6aa7b558..516c36b67c59 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -57,6 +57,7 @@ obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
57obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o 57obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
58obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o 58obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
59obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o 59obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o
60obj-$(CONFIG_REGULATOR_PWM) += pwm-regulator.o
60obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o 61obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
61obj-$(CONFIG_REGULATOR_PBIAS) += pbias-regulator.o 62obj-$(CONFIG_REGULATOR_PBIAS) += pbias-regulator.o
62obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o 63obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
@@ -65,7 +66,6 @@ obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
65obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o 66obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
66obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o 67obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
67obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o 68obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
68obj-$(CONFIG_REGULATOR_ST_PWM) += st-pwm.o
69obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o 69obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
70obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o 70obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
71obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o 71obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c
new file mode 100644
index 000000000000..d3f55eaea058
--- /dev/null
+++ b/drivers/regulator/pwm-regulator.c
@@ -0,0 +1,197 @@
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/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>
19#include <linux/of.h>
20#include <linux/of_device.h>
21#include <linux/pwm.h>
22
23struct pwm_regulator_data {
24 struct regulator_desc desc;
25 struct pwm_voltages *duty_cycle_table;
26 struct pwm_device *pwm;
27 bool enabled;
28 int state;
29};
30
31struct pwm_voltages {
32 unsigned int uV;
33 unsigned int dutycycle;
34};
35
36static int pwm_regulator_get_voltage_sel(struct regulator_dev *dev)
37{
38 struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
39
40 return drvdata->state;
41}
42
43static int pwm_regulator_set_voltage_sel(struct regulator_dev *dev,
44 unsigned selector)
45{
46 struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
47 unsigned int pwm_reg_period;
48 int dutycycle;
49 int ret;
50
51 pwm_reg_period = pwm_get_period(drvdata->pwm);
52
53 dutycycle = (pwm_reg_period *
54 drvdata->duty_cycle_table[selector].dutycycle) / 100;
55
56 ret = pwm_config(drvdata->pwm, dutycycle, pwm_reg_period);
57 if (ret) {
58 dev_err(&dev->dev, "Failed to configure PWM\n");
59 return ret;
60 }
61
62 drvdata->state = selector;
63
64 if (!drvdata->enabled) {
65 ret = pwm_enable(drvdata->pwm);
66 if (ret) {
67 dev_err(&dev->dev, "Failed to enable PWM\n");
68 return ret;
69 }
70 drvdata->enabled = true;
71 }
72
73 return 0;
74}
75
76static int pwm_regulator_list_voltage(struct regulator_dev *dev,
77 unsigned selector)
78{
79 struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
80
81 if (selector >= drvdata->desc.n_voltages)
82 return -EINVAL;
83
84 return drvdata->duty_cycle_table[selector].uV;
85}
86
87static struct regulator_ops pwm_regulator_voltage_ops = {
88 .set_voltage_sel = pwm_regulator_set_voltage_sel,
89 .get_voltage_sel = pwm_regulator_get_voltage_sel,
90 .list_voltage = pwm_regulator_list_voltage,
91 .map_voltage = regulator_map_voltage_iterate,
92};
93
94static const struct regulator_desc pwm_regulator_desc = {
95 .name = "pwm-regulator",
96 .ops = &pwm_regulator_voltage_ops,
97 .type = REGULATOR_VOLTAGE,
98 .owner = THIS_MODULE,
99 .supply_name = "pwm",
100};
101
102static int pwm_regulator_probe(struct platform_device *pdev)
103{
104 struct pwm_regulator_data *drvdata;
105 struct property *prop;
106 struct regulator_dev *regulator;
107 struct regulator_config config = { };
108 struct device_node *np = pdev->dev.of_node;
109 int length, ret;
110
111 if (!np) {
112 dev_err(&pdev->dev, "Device Tree node missing\n");
113 return -EINVAL;
114 }
115
116 drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
117 if (!drvdata)
118 return -ENOMEM;
119
120 memcpy(&drvdata->desc, &pwm_regulator_desc, sizeof(pwm_regulator_desc));
121
122 /* determine the number of voltage-table */
123 prop = of_find_property(np, "voltage-table", &length);
124 if (!prop) {
125 dev_err(&pdev->dev, "No voltage-table\n");
126 return -EINVAL;
127 }
128
129 if ((length < sizeof(*drvdata->duty_cycle_table)) ||
130 (length % sizeof(*drvdata->duty_cycle_table))) {
131 dev_err(&pdev->dev, "voltage-table length(%d) is invalid\n",
132 length);
133 return -EINVAL;
134 }
135
136 drvdata->desc.n_voltages = length / sizeof(*drvdata->duty_cycle_table);
137
138 drvdata->duty_cycle_table = devm_kzalloc(&pdev->dev,
139 length, GFP_KERNEL);
140 if (!drvdata->duty_cycle_table)
141 return -ENOMEM;
142
143 /* read voltage table from DT property */
144 ret = of_property_read_u32_array(np, "voltage-table",
145 (u32 *)drvdata->duty_cycle_table,
146 length / sizeof(u32));
147 if (ret < 0) {
148 dev_err(&pdev->dev, "read voltage-table failed\n");
149 return ret;
150 }
151
152 config.init_data = of_get_regulator_init_data(&pdev->dev, np);
153 if (!config.init_data)
154 return -ENOMEM;
155
156 config.of_node = np;
157 config.dev = &pdev->dev;
158 config.driver_data = drvdata;
159
160 drvdata->pwm = devm_pwm_get(&pdev->dev, NULL);
161 if (IS_ERR(drvdata->pwm)) {
162 dev_err(&pdev->dev, "Failed to get PWM\n");
163 return PTR_ERR(drvdata->pwm);
164 }
165
166 regulator = devm_regulator_register(&pdev->dev,
167 &drvdata->desc, &config);
168 if (IS_ERR(regulator)) {
169 dev_err(&pdev->dev, "Failed to register regulator %s\n",
170 drvdata->desc.name);
171 return PTR_ERR(regulator);
172 }
173
174 return 0;
175}
176
177static const struct of_device_id pwm_of_match[] = {
178 { .compatible = "pwm-regulator" },
179 { },
180};
181MODULE_DEVICE_TABLE(of, pwm_of_match);
182
183static struct platform_driver pwm_regulator_driver = {
184 .driver = {
185 .name = "pwm-regulator",
186 .owner = THIS_MODULE,
187 .of_match_table = of_match_ptr(pwm_of_match),
188 },
189 .probe = pwm_regulator_probe,
190};
191
192module_platform_driver(pwm_regulator_driver);
193
194MODULE_LICENSE("GPL");
195MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>");
196MODULE_DESCRIPTION("PWM Regulator Driver");
197MODULE_ALIAS("platform:pwm-regulator");
diff --git a/drivers/regulator/st-pwm.c b/drivers/regulator/st-pwm.c
deleted file mode 100644
index 5ea78df449f8..000000000000
--- a/drivers/regulator/st-pwm.c
+++ /dev/null
@@ -1,190 +0,0 @@
1/*
2 * Regulator driver for ST's 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/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>
19#include <linux/of.h>
20#include <linux/of_device.h>
21#include <linux/pwm.h>
22
23#define ST_PWM_REG_PERIOD 8448
24
25struct st_pwm_regulator_pdata {
26 const struct regulator_desc *desc;
27 struct st_pwm_voltages *duty_cycle_table;
28};
29
30struct st_pwm_regulator_data {
31 const struct st_pwm_regulator_pdata *pdata;
32 struct pwm_device *pwm;
33 bool enabled;
34 int state;
35};
36
37struct st_pwm_voltages {
38 unsigned int uV;
39 unsigned int dutycycle;
40};
41
42static int st_pwm_regulator_get_voltage_sel(struct regulator_dev *dev)
43{
44 struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
45
46 return drvdata->state;
47}
48
49static int st_pwm_regulator_set_voltage_sel(struct regulator_dev *dev,
50 unsigned selector)
51{
52 struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
53 int dutycycle;
54 int ret;
55
56 dutycycle = (ST_PWM_REG_PERIOD / 100) *
57 drvdata->pdata->duty_cycle_table[selector].dutycycle;
58
59 ret = pwm_config(drvdata->pwm, dutycycle, ST_PWM_REG_PERIOD);
60 if (ret) {
61 dev_err(&dev->dev, "Failed to configure PWM\n");
62 return ret;
63 }
64
65 drvdata->state = selector;
66
67 if (!drvdata->enabled) {
68 ret = pwm_enable(drvdata->pwm);
69 if (ret) {
70 dev_err(&dev->dev, "Failed to enable PWM\n");
71 return ret;
72 }
73 drvdata->enabled = true;
74 }
75
76 return 0;
77}
78
79static int st_pwm_regulator_list_voltage(struct regulator_dev *dev,
80 unsigned selector)
81{
82 struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
83
84 if (selector >= dev->desc->n_voltages)
85 return -EINVAL;
86
87 return drvdata->pdata->duty_cycle_table[selector].uV;
88}
89
90static struct regulator_ops st_pwm_regulator_voltage_ops = {
91 .set_voltage_sel = st_pwm_regulator_set_voltage_sel,
92 .get_voltage_sel = st_pwm_regulator_get_voltage_sel,
93 .list_voltage = st_pwm_regulator_list_voltage,
94 .map_voltage = regulator_map_voltage_iterate,
95};
96
97static struct st_pwm_voltages b2105_duty_cycle_table[] = {
98 { .uV = 1114000, .dutycycle = 0, },
99 { .uV = 1095000, .dutycycle = 10, },
100 { .uV = 1076000, .dutycycle = 20, },
101 { .uV = 1056000, .dutycycle = 30, },
102 { .uV = 1036000, .dutycycle = 40, },
103 { .uV = 1016000, .dutycycle = 50, },
104 /* WARNING: Values above 50% duty-cycle cause boot failures. */
105};
106
107static const struct regulator_desc b2105_desc = {
108 .name = "b2105-pwm-regulator",
109 .ops = &st_pwm_regulator_voltage_ops,
110 .type = REGULATOR_VOLTAGE,
111 .owner = THIS_MODULE,
112 .n_voltages = ARRAY_SIZE(b2105_duty_cycle_table),
113 .supply_name = "pwm",
114};
115
116static const struct st_pwm_regulator_pdata b2105_info = {
117 .desc = &b2105_desc,
118 .duty_cycle_table = b2105_duty_cycle_table,
119};
120
121static const struct of_device_id st_pwm_of_match[] = {
122 { .compatible = "st,b2105-pwm-regulator", .data = &b2105_info, },
123 { },
124};
125MODULE_DEVICE_TABLE(of, st_pwm_of_match);
126
127static int st_pwm_regulator_probe(struct platform_device *pdev)
128{
129 struct st_pwm_regulator_data *drvdata;
130 struct regulator_dev *regulator;
131 struct regulator_config config = { };
132 struct device_node *np = pdev->dev.of_node;
133 const struct of_device_id *of_match;
134
135 if (!np) {
136 dev_err(&pdev->dev, "Device Tree node missing\n");
137 return -EINVAL;
138 }
139
140 drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
141 if (!drvdata)
142 return -ENOMEM;
143
144 of_match = of_match_device(st_pwm_of_match, &pdev->dev);
145 if (!of_match) {
146 dev_err(&pdev->dev, "failed to match of device\n");
147 return -ENODEV;
148 }
149 drvdata->pdata = of_match->data;
150
151 config.init_data = of_get_regulator_init_data(&pdev->dev, np);
152 if (!config.init_data)
153 return -ENOMEM;
154
155 config.of_node = np;
156 config.dev = &pdev->dev;
157 config.driver_data = drvdata;
158
159 drvdata->pwm = devm_pwm_get(&pdev->dev, NULL);
160 if (IS_ERR(drvdata->pwm)) {
161 dev_err(&pdev->dev, "Failed to get PWM\n");
162 return PTR_ERR(drvdata->pwm);
163 }
164
165 regulator = devm_regulator_register(&pdev->dev,
166 drvdata->pdata->desc, &config);
167 if (IS_ERR(regulator)) {
168 dev_err(&pdev->dev, "Failed to register regulator %s\n",
169 drvdata->pdata->desc->name);
170 return PTR_ERR(regulator);
171 }
172
173 return 0;
174}
175
176static struct platform_driver st_pwm_regulator_driver = {
177 .driver = {
178 .name = "st-pwm-regulator",
179 .owner = THIS_MODULE,
180 .of_match_table = of_match_ptr(st_pwm_of_match),
181 },
182 .probe = st_pwm_regulator_probe,
183};
184
185module_platform_driver(st_pwm_regulator_driver);
186
187MODULE_LICENSE("GPL");
188MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>");
189MODULE_DESCRIPTION("ST PWM Regulator Driver");
190MODULE_ALIAS("platform:st_pwm-regulator");