aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChen Feng <puck.chen@hisilicon.com>2016-02-14 01:29:22 -0500
committerMark Brown <broonie@kernel.org>2016-02-15 14:54:55 -0500
commit4618119b9be5f5075daf995b2ab807088b14961c (patch)
tree9569f586873911151583ef8faf3b1c0357527123
parent16dc661e0e4cba666a751f3f552f4e2de07a2397 (diff)
regulator: hi655x: enable regulator for hi655x PMIC
Add the regulator driver for hi655x PMIC. Signed-off-by: Chen Feng <puck.chen@hisilicon.com> Signed-off-by: Fei Wang <w.f@huawei.com> Signed-off-by: Xinwei Kong <kong.kongxinwei@hisilicon.com> Reviewed-by: Haojian Zhuang <haojian.zhuang@linaro.org> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/regulator/Kconfig8
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/hi655x-regulator.c227
3 files changed, 236 insertions, 0 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 8155e80dd3f8..cd8ce7e9d451 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -261,6 +261,14 @@ config REGULATOR_HI6421
261 21 general purpose LDOs, 3 dedicated LDOs, and 5 BUCKs. All 261 21 general purpose LDOs, 3 dedicated LDOs, and 5 BUCKs. All
262 of them come with support to either ECO (idle) or sleep mode. 262 of them come with support to either ECO (idle) or sleep mode.
263 263
264config REGULATOR_HI655X
265 tristate "Hisilicon HI655X PMIC regulators support"
266 depends on ARCH_HISI || COMPILE_TEST
267 depends on MFD_HI655X_PMIC && OF
268 help
269 This driver provides support for the voltage regulators of the
270 Hisilicon Hi655x PMIC device.
271
264config REGULATOR_ISL9305 272config REGULATOR_ISL9305
265 tristate "Intersil ISL9305 regulator" 273 tristate "Intersil ISL9305 regulator"
266 depends on I2C 274 depends on I2C
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 980b1943fa81..422786cc4b74 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
34obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o 34obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
35obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o 35obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
36obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o 36obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o
37obj-$(CONFIG_REGULATOR_HI655X) += hi655x-regulator.o
37obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o 38obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
38obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o 39obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o
39obj-$(CONFIG_REGULATOR_LM363X) += lm363x-regulator.o 40obj-$(CONFIG_REGULATOR_LM363X) += lm363x-regulator.o
diff --git a/drivers/regulator/hi655x-regulator.c b/drivers/regulator/hi655x-regulator.c
new file mode 100644
index 000000000000..aca18466f522
--- /dev/null
+++ b/drivers/regulator/hi655x-regulator.c
@@ -0,0 +1,227 @@
1/*
2 * Device driver for regulators in Hi655x IC
3 *
4 * Copyright (c) 2016 Hisilicon.
5 *
6 * Authors:
7 * Chen Feng <puck.chen@hisilicon.com>
8 * Fei Wang <w.f@huawei.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/bitops.h>
16#include <linux/device.h>
17#include <linux/err.h>
18#include <linux/module.h>
19#include <linux/io.h>
20#include <linux/of.h>
21#include <linux/platform_device.h>
22#include <linux/regmap.h>
23#include <linux/regulator/driver.h>
24#include <linux/regulator/machine.h>
25#include <linux/regulator/of_regulator.h>
26#include <linux/mfd/hi655x-pmic.h>
27
28struct hi655x_regulator {
29 unsigned int disable_reg;
30 unsigned int status_reg;
31 unsigned int ctrl_regs;
32 unsigned int ctrl_mask;
33 struct regulator_desc rdesc;
34};
35
36/* LDO7 & LDO10 */
37static const unsigned int ldo7_voltages[] = {
38 1800000, 1850000, 2850000, 2900000,
39 3000000, 3100000, 3200000, 3300000,
40};
41
42static const unsigned int ldo19_voltages[] = {
43 1800000, 1850000, 1900000, 1750000,
44 2800000, 2850000, 2900000, 3000000,
45};
46
47static const unsigned int ldo22_voltages[] = {
48 900000, 1000000, 1050000, 1100000,
49 1150000, 1175000, 1185000, 1200000,
50};
51
52enum hi655x_regulator_id {
53 HI655X_LDO0,
54 HI655X_LDO1,
55 HI655X_LDO2,
56 HI655X_LDO3,
57 HI655X_LDO4,
58 HI655X_LDO5,
59 HI655X_LDO6,
60 HI655X_LDO7,
61 HI655X_LDO8,
62 HI655X_LDO9,
63 HI655X_LDO10,
64 HI655X_LDO11,
65 HI655X_LDO12,
66 HI655X_LDO13,
67 HI655X_LDO14,
68 HI655X_LDO15,
69 HI655X_LDO16,
70 HI655X_LDO17,
71 HI655X_LDO18,
72 HI655X_LDO19,
73 HI655X_LDO20,
74 HI655X_LDO21,
75 HI655X_LDO22,
76};
77
78static int hi655x_is_enabled(struct regulator_dev *rdev)
79{
80 unsigned int value = 0;
81
82 struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);
83
84 regmap_read(rdev->regmap, regulator->status_reg, &value);
85 return (value & BIT(regulator->ctrl_mask));
86}
87
88static int hi655x_disable(struct regulator_dev *rdev)
89{
90 int ret = 0;
91
92 struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);
93
94 ret = regmap_write(rdev->regmap, regulator->disable_reg,
95 BIT(regulator->ctrl_mask));
96 return ret;
97}
98
99static struct regulator_ops hi655x_regulator_ops = {
100 .enable = regulator_enable_regmap,
101 .disable = hi655x_disable,
102 .is_enabled = hi655x_is_enabled,
103 .list_voltage = regulator_list_voltage_table,
104 .get_voltage_sel = regulator_get_voltage_sel_regmap,
105 .set_voltage_sel = regulator_set_voltage_sel_regmap,
106};
107
108static struct regulator_ops hi655x_ldo_linear_ops = {
109 .enable = regulator_enable_regmap,
110 .disable = hi655x_disable,
111 .is_enabled = hi655x_is_enabled,
112 .list_voltage = regulator_list_voltage_linear,
113 .get_voltage_sel = regulator_get_voltage_sel_regmap,
114 .set_voltage_sel = regulator_set_voltage_sel_regmap,
115};
116
117#define HI655X_LDO(_ID, vreg, vmask, ereg, dreg, \
118 sreg, cmask, vtable) { \
119 .rdesc = { \
120 .name = #_ID, \
121 .of_match = of_match_ptr(#_ID), \
122 .ops = &hi655x_regulator_ops, \
123 .regulators_node = of_match_ptr("regulators"), \
124 .type = REGULATOR_VOLTAGE, \
125 .id = HI655X_##_ID, \
126 .owner = THIS_MODULE, \
127 .n_voltages = ARRAY_SIZE(vtable), \
128 .volt_table = vtable, \
129 .vsel_reg = HI655X_BUS_ADDR(vreg), \
130 .vsel_mask = vmask, \
131 .enable_reg = HI655X_BUS_ADDR(ereg), \
132 .enable_mask = BIT(cmask), \
133 }, \
134 .disable_reg = HI655X_BUS_ADDR(dreg), \
135 .status_reg = HI655X_BUS_ADDR(sreg), \
136 .ctrl_mask = cmask, \
137}
138
139#define HI655X_LDO_LINEAR(_ID, vreg, vmask, ereg, dreg, \
140 sreg, cmask, minv, nvolt, vstep) { \
141 .rdesc = { \
142 .name = #_ID, \
143 .of_match = of_match_ptr(#_ID), \
144 .ops = &hi655x_ldo_linear_ops, \
145 .regulators_node = of_match_ptr("regulators"), \
146 .type = REGULATOR_VOLTAGE, \
147 .id = HI655X_##_ID, \
148 .owner = THIS_MODULE, \
149 .min_uV = minv, \
150 .n_voltages = nvolt, \
151 .uV_step = vstep, \
152 .vsel_reg = HI655X_BUS_ADDR(vreg), \
153 .vsel_mask = vmask, \
154 .enable_reg = HI655X_BUS_ADDR(ereg), \
155 .enable_mask = BIT(cmask), \
156 }, \
157 .disable_reg = HI655X_BUS_ADDR(dreg), \
158 .status_reg = HI655X_BUS_ADDR(sreg), \
159 .ctrl_mask = cmask, \
160}
161
162static struct hi655x_regulator regulators[] = {
163 HI655X_LDO_LINEAR(LDO2, 0x72, 0x07, 0x29, 0x2a, 0x2b, 0x01,
164 2500000, 8, 100000),
165 HI655X_LDO(LDO7, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x06, ldo7_voltages),
166 HI655X_LDO(LDO10, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x01, ldo7_voltages),
167 HI655X_LDO_LINEAR(LDO13, 0x7e, 0x07, 0x2c, 0x2d, 0x2e, 0x04,
168 1600000, 8, 50000),
169 HI655X_LDO_LINEAR(LDO14, 0x7f, 0x07, 0x2c, 0x2d, 0x2e, 0x05,
170 2500000, 8, 100000),
171 HI655X_LDO_LINEAR(LDO15, 0x80, 0x07, 0x2c, 0x2d, 0x2e, 0x06,
172 1600000, 8, 50000),
173 HI655X_LDO_LINEAR(LDO17, 0x82, 0x07, 0x2f, 0x30, 0x31, 0x00,
174 2500000, 8, 100000),
175 HI655X_LDO(LDO19, 0x84, 0x07, 0x2f, 0x30, 0x31, 0x02, ldo19_voltages),
176 HI655X_LDO_LINEAR(LDO21, 0x86, 0x07, 0x2f, 0x30, 0x31, 0x04,
177 1650000, 8, 50000),
178 HI655X_LDO(LDO22, 0x87, 0x07, 0x2f, 0x30, 0x31, 0x05, ldo22_voltages),
179};
180
181static int hi655x_regulator_probe(struct platform_device *pdev)
182{
183 unsigned int i;
184 struct hi655x_regulator *regulator;
185 struct hi655x_pmic *pmic;
186 struct regulator_config config = { };
187 struct regulator_dev *rdev;
188
189 pmic = dev_get_drvdata(pdev->dev.parent);
190 if (!pmic) {
191 dev_err(&pdev->dev, "no pmic in the regulator parent node\n");
192 return -ENODEV;
193 }
194
195 regulator = devm_kzalloc(&pdev->dev, sizeof(*regulator), GFP_KERNEL);
196 if (!regulator)
197 return -ENOMEM;
198
199 platform_set_drvdata(pdev, regulator);
200
201 config.dev = pdev->dev.parent;
202 config.regmap = pmic->regmap;
203 config.driver_data = regulator;
204 for (i = 0; i < ARRAY_SIZE(regulators); i++) {
205 rdev = devm_regulator_register(&pdev->dev,
206 &regulators[i].rdesc,
207 &config);
208 if (IS_ERR(rdev)) {
209 dev_err(&pdev->dev, "failed to register regulator %s\n",
210 regulator->rdesc.name);
211 return PTR_ERR(rdev);
212 }
213 }
214 return 0;
215}
216
217static struct platform_driver hi655x_regulator_driver = {
218 .driver = {
219 .name = "hi655x-regulator",
220 },
221 .probe = hi655x_regulator_probe,
222};
223module_platform_driver(hi655x_regulator_driver);
224
225MODULE_AUTHOR("Chen Feng <puck.chen@hisilicon.com>");
226MODULE_DESCRIPTION("Hisilicon Hi655x regulator driver");
227MODULE_LICENSE("GPL v2");