aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
authorKeerthy <j-keerthy@ti.com>2014-02-06 00:50:13 -0500
committerMark Brown <broonie@linaro.org>2014-02-14 15:20:35 -0500
commit90e7d52627960e751da4fb2076ce79c51da82163 (patch)
tree2653e59275fe2c727b042592bb985c8bbc58156a /drivers/regulator
parent38dbfb59d1175ef458d006556061adeaa8751b72 (diff)
regulator: tps65218: Add Regulator driver for TPS65218 PMIC
This patch adds support for TPS65218 PMIC regulators. The regulators set consists of 6 DCDCs and 1 LDO. The output voltages are configurable and are meant to supply power to the main processor and other components. Signed-off-by: Keerthy <j-keerthy@ti.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/Kconfig9
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/tps65218-regulator.c304
3 files changed, 314 insertions, 0 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 6a7932822e37..b05da8803bd1 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -513,6 +513,15 @@ config REGULATOR_TPS65217
513 voltage regulators. It supports software based voltage control 513 voltage regulators. It supports software based voltage control
514 for different voltage domains 514 for different voltage domains
515 515
516config REGULATOR_TPS65218
517 tristate "TI TPS65218 Power regulators"
518 depends on MFD_TPS65218
519 help
520 This driver supports TPS65218 voltage regulator chips. TPS65218
521 provides six step-down converters and one general-purpose LDO
522 voltage regulators. It supports software based voltage control
523 for different voltage domains
524
516config REGULATOR_TPS6524X 525config REGULATOR_TPS6524X
517 tristate "TI TPS6524X Power regulators" 526 tristate "TI TPS6524X Power regulators"
518 depends on SPI 527 depends on SPI
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 979f9ddcf259..ba801a5081b6 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
67obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o 67obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
68obj-$(CONFIG_REGULATOR_TPS65090) += tps65090-regulator.o 68obj-$(CONFIG_REGULATOR_TPS65090) += tps65090-regulator.o
69obj-$(CONFIG_REGULATOR_TPS65217) += tps65217-regulator.o 69obj-$(CONFIG_REGULATOR_TPS65217) += tps65217-regulator.o
70obj-$(CONFIG_REGULATOR_TPS65218) += tps65218-regulator.o
70obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o 71obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
71obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o 72obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
72obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o 73obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c
new file mode 100644
index 000000000000..958276c891a4
--- /dev/null
+++ b/drivers/regulator/tps65218-regulator.c
@@ -0,0 +1,304 @@
1/*
2 * tps65218-regulator.c
3 *
4 * Regulator driver for TPS65218 PMIC
5 *
6 * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
13 * kind, whether expressed or implied; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License version 2 for more details.
16 */
17
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/device.h>
21#include <linux/init.h>
22#include <linux/err.h>
23#include <linux/platform_device.h>
24#include <linux/of_device.h>
25#include <linux/regulator/of_regulator.h>
26#include <linux/regulator/driver.h>
27#include <linux/regulator/machine.h>
28#include <linux/mfd/tps65218.h>
29
30static unsigned int tps65218_ramp_delay = 4000;
31
32enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4, DCDC5, DCDC6, LDO1 };
33
34#define TPS65218_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _er, _em, _t, \
35 _lr, _nlr) \
36 { \
37 .name = _name, \
38 .id = _id, \
39 .ops = &_ops, \
40 .n_voltages = _n, \
41 .type = REGULATOR_VOLTAGE, \
42 .owner = THIS_MODULE, \
43 .vsel_reg = _vr, \
44 .vsel_mask = _vm, \
45 .enable_reg = _er, \
46 .enable_mask = _em, \
47 .volt_table = _t, \
48 .linear_ranges = _lr, \
49 .n_linear_ranges = _nlr, \
50 } \
51
52#define TPS65218_INFO(_id, _nm, _min, _max) \
53 { \
54 .id = _id, \
55 .name = _nm, \
56 .min_uV = _min, \
57 .max_uV = _max, \
58 }
59
60static const struct regulator_linear_range dcdc1_dcdc2_ranges[] = {
61 REGULATOR_LINEAR_RANGE(850000, 0x0, 0x32, 10000),
62 REGULATOR_LINEAR_RANGE(1375000, 0x33, 0x3f, 25000),
63};
64
65static const struct regulator_linear_range ldo1_dcdc3_ranges[] = {
66 REGULATOR_LINEAR_RANGE(900000, 0x0, 0x1a, 25000),
67 REGULATOR_LINEAR_RANGE(1600000, 0x1b, 0x3f, 50000),
68};
69
70static const struct regulator_linear_range dcdc4_ranges[] = {
71 REGULATOR_LINEAR_RANGE(1175000, 0x0, 0xf, 25000),
72 REGULATOR_LINEAR_RANGE(1550000, 0x10, 0x34, 50000),
73};
74
75static struct tps_info tps65218_pmic_regs[] = {
76 TPS65218_INFO(0, "DCDC1", 850000, 167500),
77 TPS65218_INFO(1, "DCDC2", 850000, 1675000),
78 TPS65218_INFO(2, "DCDC3", 900000, 3400000),
79 TPS65218_INFO(3, "DCDC4", 1175000, 3400000),
80 TPS65218_INFO(4, "DCDC5", 1000000, 1000000),
81 TPS65218_INFO(5, "DCDC6", 1800000, 1800000),
82 TPS65218_INFO(6, "LDO1", 900000, 3400000),
83};
84
85#define TPS65218_OF_MATCH(comp, label) \
86 { \
87 .compatible = comp, \
88 .data = &label, \
89 }
90
91static const struct of_device_id tps65218_of_match[] = {
92 TPS65218_OF_MATCH("ti,tps65218-dcdc1", tps65218_pmic_regs[DCDC1]),
93 TPS65218_OF_MATCH("ti,tps65218-dcdc2", tps65218_pmic_regs[DCDC2]),
94 TPS65218_OF_MATCH("ti,tps65218-dcdc3", tps65218_pmic_regs[DCDC3]),
95 TPS65218_OF_MATCH("ti,tps65218-dcdc4", tps65218_pmic_regs[DCDC4]),
96 TPS65218_OF_MATCH("ti,tps65218-dcdc5", tps65218_pmic_regs[DCDC5]),
97 TPS65218_OF_MATCH("ti,tps65218-dcdc6", tps65218_pmic_regs[DCDC6]),
98 TPS65218_OF_MATCH("ti,tps65218-ldo1", tps65218_pmic_regs[LDO1]),
99};
100MODULE_DEVICE_TABLE(of, tps65218_of_match);
101
102static int tps65218_pmic_set_voltage_sel(struct regulator_dev *dev,
103 unsigned selector)
104{
105 int ret;
106 struct tps65218 *tps = rdev_get_drvdata(dev);
107 unsigned int rid = rdev_get_id(dev);
108
109 /* Set the voltage based on vsel value and write protect level is 2 */
110 ret = tps65218_set_bits(tps, dev->desc->vsel_reg, dev->desc->vsel_mask,
111 selector, TPS65218_PROTECT_L1);
112
113 /* Set GO bit for DCDC1/2 to initiate voltage transistion */
114 switch (rid) {
115 case TPS65218_DCDC_1:
116 case TPS65218_DCDC_2:
117 ret = tps65218_set_bits(tps, TPS65218_REG_CONTRL_SLEW_RATE,
118 TPS65218_SLEW_RATE_GO,
119 TPS65218_SLEW_RATE_GO,
120 TPS65218_PROTECT_L1);
121 break;
122 }
123
124 return ret;
125}
126
127static int tps65218_pmic_enable(struct regulator_dev *dev)
128{
129 struct tps65218 *tps = rdev_get_drvdata(dev);
130 unsigned int rid = rdev_get_id(dev);
131
132 if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1)
133 return -EINVAL;
134
135 /* Enable the regulator and password protection is level 1 */
136 return tps65218_set_bits(tps, dev->desc->enable_reg,
137 dev->desc->enable_mask, dev->desc->enable_mask,
138 TPS65218_PROTECT_L1);
139}
140
141static int tps65218_pmic_disable(struct regulator_dev *dev)
142{
143 struct tps65218 *tps = rdev_get_drvdata(dev);
144 unsigned int rid = rdev_get_id(dev);
145
146 if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1)
147 return -EINVAL;
148
149 /* Disable the regulator and password protection is level 1 */
150 return tps65218_clear_bits(tps, dev->desc->enable_reg,
151 dev->desc->enable_mask, TPS65218_PROTECT_L1);
152}
153
154static int tps65218_set_voltage_time_sel(struct regulator_dev *rdev,
155 unsigned int old_selector, unsigned int new_selector)
156{
157 int old_uv, new_uv;
158
159 old_uv = regulator_list_voltage_linear_range(rdev, old_selector);
160 if (old_uv < 0)
161 return old_uv;
162
163 new_uv = regulator_list_voltage_linear_range(rdev, new_selector);
164 if (new_uv < 0)
165 return new_uv;
166
167 return DIV_ROUND_UP(abs(old_uv - new_uv), tps65218_ramp_delay);
168}
169
170/* Operations permitted on DCDC1, DCDC2 */
171static struct regulator_ops tps65218_dcdc12_ops = {
172 .is_enabled = regulator_is_enabled_regmap,
173 .enable = tps65218_pmic_enable,
174 .disable = tps65218_pmic_disable,
175 .get_voltage_sel = regulator_get_voltage_sel_regmap,
176 .set_voltage_sel = tps65218_pmic_set_voltage_sel,
177 .list_voltage = regulator_list_voltage_linear_range,
178 .map_voltage = regulator_map_voltage_linear_range,
179 .set_voltage_time_sel = tps65218_set_voltage_time_sel,
180};
181
182/* Operations permitted on DCDC3, DCDC4 and LDO1 */
183static struct regulator_ops tps65218_ldo1_dcdc34_ops = {
184 .is_enabled = regulator_is_enabled_regmap,
185 .enable = tps65218_pmic_enable,
186 .disable = tps65218_pmic_disable,
187 .get_voltage_sel = regulator_get_voltage_sel_regmap,
188 .set_voltage_sel = tps65218_pmic_set_voltage_sel,
189 .list_voltage = regulator_list_voltage_linear_range,
190 .map_voltage = regulator_map_voltage_linear_range,
191};
192
193/* Operations permitted on DCDC5, DCDC6 */
194static struct regulator_ops tps65218_dcdc56_pmic_ops = {
195 .is_enabled = regulator_is_enabled_regmap,
196 .enable = tps65218_pmic_enable,
197 .disable = tps65218_pmic_disable,
198};
199
200static const struct regulator_desc regulators[] = {
201 TPS65218_REGULATOR("DCDC1", TPS65218_DCDC_1, tps65218_dcdc12_ops, 64,
202 TPS65218_REG_CONTROL_DCDC1,
203 TPS65218_CONTROL_DCDC1_MASK,
204 TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC1_EN, NULL,
205 dcdc1_dcdc2_ranges, 2),
206 TPS65218_REGULATOR("DCDC2", TPS65218_DCDC_2, tps65218_dcdc12_ops, 64,
207 TPS65218_REG_CONTROL_DCDC2,
208 TPS65218_CONTROL_DCDC2_MASK,
209 TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC2_EN, NULL,
210 dcdc1_dcdc2_ranges, 2),
211 TPS65218_REGULATOR("DCDC3", TPS65218_DCDC_3, tps65218_ldo1_dcdc34_ops,
212 64, TPS65218_REG_CONTROL_DCDC3,
213 TPS65218_CONTROL_DCDC3_MASK, TPS65218_REG_ENABLE1,
214 TPS65218_ENABLE1_DC3_EN, NULL,
215 ldo1_dcdc3_ranges, 2),
216 TPS65218_REGULATOR("DCDC4", TPS65218_DCDC_4, tps65218_ldo1_dcdc34_ops,
217 53, TPS65218_REG_CONTROL_DCDC4,
218 TPS65218_CONTROL_DCDC4_MASK,
219 TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC4_EN, NULL,
220 dcdc4_ranges, 2),
221 TPS65218_REGULATOR("DCDC5", TPS65218_DCDC_5, tps65218_dcdc56_pmic_ops,
222 1, -1, -1, TPS65218_REG_ENABLE1,
223 TPS65218_ENABLE1_DC5_EN, NULL, NULL, 0),
224 TPS65218_REGULATOR("DCDC6", TPS65218_DCDC_6, tps65218_dcdc56_pmic_ops,
225 1, -1, -1, TPS65218_REG_ENABLE1,
226 TPS65218_ENABLE1_DC6_EN, NULL, NULL, 0),
227 TPS65218_REGULATOR("LDO1", TPS65218_LDO_1, tps65218_ldo1_dcdc34_ops, 64,
228 TPS65218_REG_CONTROL_DCDC4,
229 TPS65218_CONTROL_LDO1_MASK, TPS65218_REG_ENABLE2,
230 TPS65218_ENABLE2_LDO1_EN, NULL, ldo1_dcdc3_ranges,
231 2),
232};
233
234static int tps65218_regulator_probe(struct platform_device *pdev)
235{
236 struct tps65218 *tps = dev_get_drvdata(pdev->dev.parent);
237 struct regulator_init_data *init_data;
238 const struct tps_info *template;
239 struct regulator_dev *rdev;
240 const struct of_device_id *match;
241 struct regulator_config config = { };
242 int id;
243
244 match = of_match_device(tps65218_of_match, &pdev->dev);
245 if (match) {
246 template = match->data;
247 id = template->id;
248 init_data = of_get_regulator_init_data(&pdev->dev,
249 pdev->dev.of_node);
250 } else {
251 return -ENODEV;
252 }
253
254 platform_set_drvdata(pdev, tps);
255
256 tps->info[id] = &tps65218_pmic_regs[id];
257 config.dev = &pdev->dev;
258 config.init_data = init_data;
259 config.driver_data = tps;
260 config.regmap = tps->regmap;
261
262 rdev = devm_regulator_register(&pdev->dev, &regulators[id], &config);
263 if (IS_ERR(rdev)) {
264 dev_err(tps->dev, "failed to register %s regulator\n",
265 pdev->name);
266 return PTR_ERR(rdev);
267 }
268
269 /* Save regulator */
270 tps->rdev[id] = rdev;
271
272 return 0;
273}
274
275static int tps65218_regulator_remove(struct platform_device *pdev)
276{
277 struct tps65218 *tps = platform_get_drvdata(pdev);
278 const struct of_device_id *match;
279 const struct tps_info *template;
280
281 match = of_match_device(tps65218_of_match, &pdev->dev);
282 template = match->data;
283 regulator_unregister(tps->rdev[template->id]);
284 platform_set_drvdata(pdev, NULL);
285
286 return 0;
287}
288
289static struct platform_driver tps65218_regulator_driver = {
290 .driver = {
291 .name = "tps65218-pmic",
292 .owner = THIS_MODULE,
293 .of_match_table = of_match_ptr(tps65218_of_match),
294 },
295 .probe = tps65218_regulator_probe,
296 .remove = tps65218_regulator_remove,
297};
298
299module_platform_driver(tps65218_regulator_driver);
300
301MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
302MODULE_DESCRIPTION("TPS65218 voltage regulator driver");
303MODULE_ALIAS("platform:tps65218-pmic");
304MODULE_LICENSE("GPL v2");