aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
authorChris Zhong <zyw@rock-chips.com>2014-08-19 23:36:42 -0400
committerMark Brown <broonie@linaro.org>2014-08-20 12:28:15 -0400
commit2cd64ae3d57b80f6d93682b98a59ed4b124cf2ef (patch)
treeed5ea0a8d224c230f473fe6c6b691a1f1d8afcbb /drivers/regulator
parent7d1311b93e58ed55f3a31cc8f94c4b8fe988a2b9 (diff)
regulator: RK808: Add regulator driver for RK808
The regulator module consists of 4 DCDCs, 8 LDOs and 2 switches. The output voltages are configurable and are meant to supply power to the main processor and other components Signed-off-by: Chris Zhong <zyw@rock-chips.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/Kconfig10
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/rk808-regulator.c410
3 files changed, 421 insertions, 0 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 2dc8289e5dba..fb32babf756e 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -459,6 +459,16 @@ config REGULATOR_RC5T583
459 through regulator interface. The device supports multiple DCDC/LDO 459 through regulator interface. The device supports multiple DCDC/LDO
460 outputs which can be controlled by i2c communication. 460 outputs which can be controlled by i2c communication.
461 461
462config REGULATOR_RK808
463 tristate "Rockchip RK808 Power regulators"
464 depends on MFD_RK808
465 help
466 Select this option to enable the power regulator of ROCKCHIP
467 PMIC RK808.
468 This driver supports the control of different power rails of device
469 through regulator interface. The device supports multiple DCDC/LDO
470 outputs which can be controlled by i2c communication.
471
462config REGULATOR_S2MPA01 472config REGULATOR_S2MPA01
463 tristate "Samsung S2MPA01 voltage regulator" 473 tristate "Samsung S2MPA01 voltage regulator"
464 depends on MFD_SEC_CORE 474 depends on MFD_SEC_CORE
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index aa4a6aa7b558..236fdbb2b786 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_REGULATOR_PBIAS) += pbias-regulator.o
62obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o 62obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
63obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o 63obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
64obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o 64obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
65obj-$(CONFIG_REGULATOR_RK808) += rk808-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
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
new file mode 100644
index 000000000000..94753fd311c1
--- /dev/null
+++ b/drivers/regulator/rk808-regulator.c
@@ -0,0 +1,410 @@
1/*
2 * Regulator driver for Rockchip RK808
3 *
4 * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
5 *
6 * Author: Chris Zhong <zyw@rock-chips.com>
7 * Author: Zhang Qing <zhangqing@rock-chips.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms and conditions of the GNU General Public License,
11 * version 2, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 */
19
20#include <linux/module.h>
21#include <linux/init.h>
22#include <linux/i2c.h>
23#include <linux/err.h>
24#include <linux/platform_device.h>
25#include <linux/mfd/rk808.h>
26#include <linux/of.h>
27#include <linux/of_device.h>
28#include <linux/regulator/driver.h>
29#include <linux/regulator/of_regulator.h>
30#include <linux/regmap.h>
31#include <linux/slab.h>
32/*
33 * Field Definitions.
34 */
35#define RK808_BUCK_VSEL_MASK 0x3f
36#define RK808_BUCK4_VSEL_MASK 0xf
37#define RK808_LDO_VSEL_MASK 0x1f
38
39static const int buck_set_vol_base_addr[] = {
40 RK808_BUCK1_ON_VSEL_REG,
41 RK808_BUCK2_ON_VSEL_REG,
42 RK808_BUCK3_CONFIG_REG,
43 RK808_BUCK4_ON_VSEL_REG,
44};
45
46static const int buck_contr_base_addr[] = {
47 RK808_BUCK1_CONFIG_REG,
48 RK808_BUCK2_CONFIG_REG,
49 RK808_BUCK3_CONFIG_REG,
50 RK808_BUCK4_CONFIG_REG,
51};
52
53#define rk808_BUCK_SET_VOL_REG(x) (buck_set_vol_base_addr[x])
54#define rk808_BUCK_CONTR_REG(x) (buck_contr_base_addr[x])
55#define rk808_LDO_SET_VOL_REG(x) (ldo_set_vol_base_addr[x])
56
57static const int ldo_set_vol_base_addr[] = {
58 RK808_LDO1_ON_VSEL_REG,
59 RK808_LDO2_ON_VSEL_REG,
60 RK808_LDO3_ON_VSEL_REG,
61 RK808_LDO4_ON_VSEL_REG,
62 RK808_LDO5_ON_VSEL_REG,
63 RK808_LDO6_ON_VSEL_REG,
64 RK808_LDO7_ON_VSEL_REG,
65 RK808_LDO8_ON_VSEL_REG,
66};
67
68/*
69 * rk808 voltage number
70 */
71static const struct regulator_linear_range rk808_buck_voltage_ranges[] = {
72 REGULATOR_LINEAR_RANGE(700000, 0, 63, 12500),
73};
74
75static const struct regulator_linear_range rk808_buck4_voltage_ranges[] = {
76 REGULATOR_LINEAR_RANGE(1800000, 0, 15, 100000),
77};
78
79static const struct regulator_linear_range rk808_ldo_voltage_ranges[] = {
80 REGULATOR_LINEAR_RANGE(1800000, 0, 16, 100000),
81};
82
83static const struct regulator_linear_range rk808_ldo3_voltage_ranges[] = {
84 REGULATOR_LINEAR_RANGE(800000, 0, 13, 100000),
85 REGULATOR_LINEAR_RANGE(2500000, 15, 15, 0),
86};
87
88static const struct regulator_linear_range rk808_ldo6_voltage_ranges[] = {
89 REGULATOR_LINEAR_RANGE(800000, 0, 17, 100000),
90};
91
92static struct regulator_ops rk808_reg_ops = {
93 .list_voltage = regulator_list_voltage_linear_range,
94 .map_voltage = regulator_map_voltage_linear_range,
95 .get_voltage_sel = regulator_get_voltage_sel_regmap,
96 .set_voltage_sel = regulator_set_voltage_sel_regmap,
97 .enable = regulator_enable_regmap,
98 .disable = regulator_disable_regmap,
99 .is_enabled = regulator_is_enabled_regmap,
100};
101
102static struct regulator_ops rk808_switch_ops = {
103 .enable = regulator_enable_regmap,
104 .disable = regulator_disable_regmap,
105 .is_enabled = regulator_is_enabled_regmap,
106};
107
108static const struct regulator_desc rk808_reg[] = {
109 {
110 .name = "DCDC_REG1",
111 .id = RK808_ID_DCDC1,
112 .ops = &rk808_reg_ops,
113 .type = REGULATOR_VOLTAGE,
114 .n_voltages = 64,
115 .linear_ranges = rk808_buck_voltage_ranges,
116 .n_linear_ranges = ARRAY_SIZE(rk808_buck_voltage_ranges),
117 .vsel_reg = RK808_BUCK1_ON_VSEL_REG,
118 .vsel_mask = RK808_BUCK_VSEL_MASK,
119 .enable_reg = RK808_DCDC_EN_REG,
120 .enable_mask = BIT(0),
121 .owner = THIS_MODULE,
122 }, {
123 .name = "DCDC_REG2",
124 .id = RK808_ID_DCDC2,
125 .ops = &rk808_reg_ops,
126 .type = REGULATOR_VOLTAGE,
127 .n_voltages = 64,
128 .linear_ranges = rk808_buck_voltage_ranges,
129 .n_linear_ranges = ARRAY_SIZE(rk808_buck_voltage_ranges),
130 .vsel_reg = RK808_BUCK2_ON_VSEL_REG,
131 .vsel_mask = RK808_BUCK_VSEL_MASK,
132 .enable_reg = RK808_DCDC_EN_REG,
133 .enable_mask = BIT(1),
134 .owner = THIS_MODULE,
135 }, {
136 .name = "DCDC_REG3",
137 .id = RK808_ID_DCDC3,
138 .ops = &rk808_switch_ops,
139 .type = REGULATOR_VOLTAGE,
140 .n_voltages = 1,
141 .enable_reg = RK808_DCDC_EN_REG,
142 .enable_mask = BIT(2),
143 .owner = THIS_MODULE,
144 }, {
145 .name = "DCDC_REG4",
146 .id = RK808_ID_DCDC4,
147 .ops = &rk808_reg_ops,
148 .type = REGULATOR_VOLTAGE,
149 .n_voltages = 17,
150 .linear_ranges = rk808_buck4_voltage_ranges,
151 .n_linear_ranges = ARRAY_SIZE(rk808_buck4_voltage_ranges),
152 .vsel_reg = RK808_BUCK4_ON_VSEL_REG,
153 .vsel_mask = RK808_BUCK4_VSEL_MASK,
154 .enable_reg = RK808_DCDC_EN_REG,
155 .enable_mask = BIT(3),
156 .owner = THIS_MODULE,
157 }, {
158 .name = "LDO_REG1",
159 .id = RK808_ID_LDO1,
160 .ops = &rk808_reg_ops,
161 .type = REGULATOR_VOLTAGE,
162 .n_voltages = 17,
163 .linear_ranges = rk808_ldo_voltage_ranges,
164 .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges),
165 .vsel_reg = RK808_LDO1_ON_VSEL_REG,
166 .vsel_mask = RK808_LDO_VSEL_MASK,
167 .enable_reg = RK808_LDO_EN_REG,
168 .enable_mask = BIT(0),
169 .owner = THIS_MODULE,
170 }, {
171 .name = "LDO_REG2",
172 .id = RK808_ID_LDO2,
173 .ops = &rk808_reg_ops,
174 .type = REGULATOR_VOLTAGE,
175 .n_voltages = 17,
176 .linear_ranges = rk808_ldo_voltage_ranges,
177 .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges),
178 .vsel_reg = RK808_LDO2_ON_VSEL_REG,
179 .vsel_mask = RK808_LDO_VSEL_MASK,
180 .enable_reg = RK808_LDO_EN_REG,
181 .enable_mask = BIT(1),
182 .owner = THIS_MODULE,
183 }, {
184 .name = "LDO_REG3",
185 .id = RK808_ID_LDO3,
186 .ops = &rk808_reg_ops,
187 .type = REGULATOR_VOLTAGE,
188 .n_voltages = 16,
189 .linear_ranges = rk808_ldo3_voltage_ranges,
190 .n_linear_ranges = ARRAY_SIZE(rk808_ldo3_voltage_ranges),
191 .vsel_reg = RK808_LDO3_ON_VSEL_REG,
192 .vsel_mask = RK808_BUCK4_VSEL_MASK,
193 .enable_reg = RK808_LDO_EN_REG,
194 .enable_mask = BIT(2),
195 .owner = THIS_MODULE,
196 }, {
197 .name = "LDO_REG4",
198 .id = RK808_ID_LDO4,
199 .ops = &rk808_reg_ops,
200 .type = REGULATOR_VOLTAGE,
201 .n_voltages = 17,
202 .linear_ranges = rk808_ldo_voltage_ranges,
203 .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges),
204 .vsel_reg = RK808_LDO4_ON_VSEL_REG,
205 .vsel_mask = RK808_LDO_VSEL_MASK,
206 .enable_reg = RK808_LDO_EN_REG,
207 .enable_mask = BIT(3),
208 .owner = THIS_MODULE,
209 }, {
210 .name = "LDO_REG5",
211 .id = RK808_ID_LDO5,
212 .ops = &rk808_reg_ops,
213 .type = REGULATOR_VOLTAGE,
214 .n_voltages = 17,
215 .linear_ranges = rk808_ldo_voltage_ranges,
216 .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges),
217 .vsel_reg = RK808_LDO5_ON_VSEL_REG,
218 .vsel_mask = RK808_LDO_VSEL_MASK,
219 .enable_reg = RK808_LDO_EN_REG,
220 .enable_mask = BIT(4),
221 .owner = THIS_MODULE,
222 }, {
223 .name = "LDO_REG6",
224 .id = RK808_ID_LDO6,
225 .ops = &rk808_reg_ops,
226 .type = REGULATOR_VOLTAGE,
227 .n_voltages = 18,
228 .linear_ranges = rk808_ldo6_voltage_ranges,
229 .n_linear_ranges = ARRAY_SIZE(rk808_ldo6_voltage_ranges),
230 .vsel_reg = RK808_LDO6_ON_VSEL_REG,
231 .vsel_mask = RK808_LDO_VSEL_MASK,
232 .enable_reg = RK808_LDO_EN_REG,
233 .enable_mask = BIT(5),
234 .owner = THIS_MODULE,
235 }, {
236 .name = "LDO_REG7",
237 .id = RK808_ID_LDO7,
238 .ops = &rk808_reg_ops,
239 .type = REGULATOR_VOLTAGE,
240 .n_voltages = 18,
241 .linear_ranges = rk808_ldo6_voltage_ranges,
242 .n_linear_ranges = ARRAY_SIZE(rk808_ldo6_voltage_ranges),
243 .vsel_reg = RK808_LDO7_ON_VSEL_REG,
244 .vsel_mask = RK808_LDO_VSEL_MASK,
245 .enable_reg = RK808_LDO_EN_REG,
246 .enable_mask = BIT(6),
247 .owner = THIS_MODULE,
248 }, {
249 .name = "LDO_REG8",
250 .id = RK808_ID_LDO8,
251 .ops = &rk808_reg_ops,
252 .type = REGULATOR_VOLTAGE,
253 .n_voltages = 17,
254 .linear_ranges = rk808_ldo_voltage_ranges,
255 .n_linear_ranges = ARRAY_SIZE(rk808_ldo_voltage_ranges),
256 .vsel_reg = RK808_LDO8_ON_VSEL_REG,
257 .vsel_mask = RK808_LDO_VSEL_MASK,
258 .enable_reg = RK808_LDO_EN_REG,
259 .enable_mask = BIT(7),
260 .owner = THIS_MODULE,
261 }, {
262 .name = "SWITCH_REG1",
263 .id = RK808_ID_SWITCH1,
264 .ops = &rk808_switch_ops,
265 .type = REGULATOR_VOLTAGE,
266 .enable_reg = RK808_DCDC_EN_REG,
267 .enable_mask = BIT(5),
268 .owner = THIS_MODULE,
269 }, {
270 .name = "SWITCH_REG2",
271 .id = RK808_ID_SWITCH2,
272 .ops = &rk808_switch_ops,
273 .type = REGULATOR_VOLTAGE,
274 .enable_reg = RK808_DCDC_EN_REG,
275 .enable_mask = BIT(6),
276 .owner = THIS_MODULE,
277 },
278};
279
280static struct of_regulator_match rk808_reg_matches[] = {
281 [RK808_ID_DCDC1] = { .name = "DCDC_REG1" },
282 [RK808_ID_DCDC2] = { .name = "DCDC_REG2" },
283 [RK808_ID_DCDC3] = { .name = "DCDC_REG3" },
284 [RK808_ID_DCDC4] = { .name = "DCDC_REG4" },
285 [RK808_ID_LDO1] = { .name = "LDO_REG1" },
286 [RK808_ID_LDO2] = { .name = "LDO_REG2" },
287 [RK808_ID_LDO3] = { .name = "LDO_REG3" },
288 [RK808_ID_LDO4] = { .name = "LDO_REG4" },
289 [RK808_ID_LDO5] = { .name = "LDO_REG5" },
290 [RK808_ID_LDO6] = { .name = "LDO_REG6" },
291 [RK808_ID_LDO7] = { .name = "LDO_REG7" },
292 [RK808_ID_LDO8] = { .name = "LDO_REG8" },
293 [RK808_ID_SWITCH1] = { .name = "SWITCH_REG1" },
294 [RK808_ID_SWITCH2] = { .name = "SWITCH_REG2" },
295};
296
297static int rk808_regulator_dts(struct rk808 *rk808)
298{
299 struct rk808_board *pdata = rk808->pdata;
300 struct device_node *np, *reg_np;
301 int i, ret;
302
303 np = rk808->dev->of_node;
304 if (!np) {
305 dev_err(rk808->dev, "could not find pmic sub-node\n");
306 return -ENXIO;
307 }
308
309 reg_np = of_get_child_by_name(np, "regulators");
310 if (!reg_np)
311 return -ENXIO;
312
313 ret = of_regulator_match(rk808->dev, reg_np, rk808_reg_matches,
314 RK808_NUM_REGULATORS);
315 if (ret < 0) {
316 dev_err(rk808->dev,
317 "failed to parse regulator data: %d\n", ret);
318 return ret;
319 }
320
321 for (i = 0; i < RK808_NUM_REGULATORS; i++) {
322 if (!rk808_reg_matches[i].init_data ||
323 !rk808_reg_matches[i].of_node)
324 continue;
325
326 pdata->rk808_init_data[i] = rk808_reg_matches[i].init_data;
327 pdata->of_node[i] = rk808_reg_matches[i].of_node;
328 }
329
330 return 0;
331}
332
333static int rk808_regulator_probe(struct platform_device *pdev)
334{
335 struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
336 struct rk808_board *pdata;
337 struct regulator_config config;
338 struct regulator_dev *rk808_rdev;
339 struct regulator_init_data *reg_data;
340 int i = 0;
341 int ret = 0;
342
343 dev_dbg(rk808->dev, "%s\n", __func__);
344
345 if (!rk808) {
346 dev_err(rk808->dev, "%s no rk808\n", __func__);
347 return -ENODEV;
348 }
349
350 pdata = rk808->pdata;
351 if (!pdata) {
352 dev_warn(rk808->dev, "%s no pdata, create it\n", __func__);
353 pdata = devm_kzalloc(rk808->dev, sizeof(*pdata), GFP_KERNEL);
354 if (!pdata)
355 return -ENOMEM;
356 }
357
358 ret = rk808_regulator_dts(rk808);
359 if (ret)
360 return ret;
361
362 rk808->num_regulators = RK808_NUM_REGULATORS;
363 rk808->rdev = devm_kzalloc(&pdev->dev, RK808_NUM_REGULATORS *
364 sizeof(struct regulator_dev *), GFP_KERNEL);
365 if (!rk808->rdev)
366 return -ENOMEM;
367
368 /* Instantiate the regulators */
369 for (i = 0; i < RK808_NUM_REGULATORS; i++) {
370 reg_data = pdata->rk808_init_data[i];
371 if (!reg_data)
372 continue;
373
374 config.dev = rk808->dev;
375 config.driver_data = rk808;
376 config.regmap = rk808->regmap;
377
378 if (rk808->dev->of_node)
379 config.of_node = pdata->of_node[i];
380
381 reg_data->supply_regulator = rk808_reg[i].name;
382 config.init_data = reg_data;
383
384 rk808_rdev = devm_regulator_register(&pdev->dev,
385 &rk808_reg[i], &config);
386 if (IS_ERR(rk808_rdev)) {
387 dev_err(rk808->dev,
388 "failed to register %d regulator\n", i);
389 return PTR_ERR(rk808_rdev);
390 }
391 rk808->rdev[i] = rk808_rdev;
392 }
393 return 0;
394}
395
396static struct platform_driver rk808_regulator_driver = {
397 .probe = rk808_regulator_probe,
398 .driver = {
399 .name = "rk808-regulator",
400 .owner = THIS_MODULE,
401 },
402};
403
404module_platform_driver(rk808_regulator_driver);
405
406MODULE_DESCRIPTION("regulator driver for the rk808 series PMICs");
407MODULE_AUTHOR("Chris Zhong<zyw@rock-chips.com>");
408MODULE_AUTHOR("Zhang Qing<zhanqging@rock-chips.com>");
409MODULE_LICENSE("GPL");
410MODULE_ALIAS("platform:rk808-regulator");