b49c9693628d8f351e98e1db2b8735e1c61075ea
[openwrt/svn-archive/archive.git] / target / linux / sunxi / patches-4.1 / 101-regulator-axp20x-prep-support-for-multiple-axp-families.patch
1 From f95b73ba272eac5495e69e12795d5ea8bc81d2cd Mon Sep 17 00:00:00 2001
2 From: Boris BREZILLON <boris.brezillon@free-electrons.com>
3 Date: Fri, 10 Apr 2015 12:09:03 +0800
4 Subject: [PATCH] regulator: axp20x: Prepare support for multiple AXP chip
5 families
6
7 Rework the AXP20X_ macros and probe function to support the several chip
8 families, so that each family can define it's own set of regulators.
9
10 Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
11 [wens@csie.org: Support different DC-DC work frequency ranges]
12 Signed-off-by: Chen-Yu Tsai <wens@csie.org>
13 Reviewed-by: Mark Brown <broonie@kernel.org>
14 Signed-off-by: Lee Jones <lee.jones@linaro.org>
15 ---
16 drivers/regulator/axp20x-regulator.c | 143 +++++++++++++++++++++++------------
17 1 file changed, 94 insertions(+), 49 deletions(-)
18
19 diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
20 index e4331f5..50ae0b5 100644
21 --- a/drivers/regulator/axp20x-regulator.c
22 +++ b/drivers/regulator/axp20x-regulator.c
23 @@ -32,15 +32,15 @@
24
25 #define AXP20X_FREQ_DCDC_MASK 0x0f
26
27 -#define AXP20X_DESC_IO(_id, _match, _supply, _min, _max, _step, _vreg, _vmask, \
28 - _ereg, _emask, _enable_val, _disable_val) \
29 - [AXP20X_##_id] = { \
30 +#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
31 + _vmask, _ereg, _emask, _enable_val, _disable_val) \
32 + [_family##_##_id] = { \
33 .name = #_id, \
34 .supply_name = (_supply), \
35 .of_match = of_match_ptr(_match), \
36 .regulators_node = of_match_ptr("regulators"), \
37 .type = REGULATOR_VOLTAGE, \
38 - .id = AXP20X_##_id, \
39 + .id = _family##_##_id, \
40 .n_voltages = (((_max) - (_min)) / (_step) + 1), \
41 .owner = THIS_MODULE, \
42 .min_uV = (_min) * 1000, \
43 @@ -54,15 +54,15 @@
44 .ops = &axp20x_ops, \
45 }
46
47 -#define AXP20X_DESC(_id, _match, _supply, _min, _max, _step, _vreg, _vmask, \
48 - _ereg, _emask) \
49 - [AXP20X_##_id] = { \
50 +#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
51 + _vmask, _ereg, _emask) \
52 + [_family##_##_id] = { \
53 .name = #_id, \
54 .supply_name = (_supply), \
55 .of_match = of_match_ptr(_match), \
56 .regulators_node = of_match_ptr("regulators"), \
57 .type = REGULATOR_VOLTAGE, \
58 - .id = AXP20X_##_id, \
59 + .id = _family##_##_id, \
60 .n_voltages = (((_max) - (_min)) / (_step) + 1), \
61 .owner = THIS_MODULE, \
62 .min_uV = (_min) * 1000, \
63 @@ -74,29 +74,29 @@
64 .ops = &axp20x_ops, \
65 }
66
67 -#define AXP20X_DESC_FIXED(_id, _match, _supply, _volt) \
68 - [AXP20X_##_id] = { \
69 +#define AXP_DESC_FIXED(_family, _id, _match, _supply, _volt) \
70 + [_family##_##_id] = { \
71 .name = #_id, \
72 .supply_name = (_supply), \
73 .of_match = of_match_ptr(_match), \
74 .regulators_node = of_match_ptr("regulators"), \
75 .type = REGULATOR_VOLTAGE, \
76 - .id = AXP20X_##_id, \
77 + .id = _family##_##_id, \
78 .n_voltages = 1, \
79 .owner = THIS_MODULE, \
80 .min_uV = (_volt) * 1000, \
81 .ops = &axp20x_ops_fixed \
82 }
83
84 -#define AXP20X_DESC_TABLE(_id, _match, _supply, _table, _vreg, _vmask, _ereg, \
85 - _emask) \
86 - [AXP20X_##_id] = { \
87 +#define AXP_DESC_TABLE(_family, _id, _match, _supply, _table, _vreg, _vmask, \
88 + _ereg, _emask) \
89 + [_family##_##_id] = { \
90 .name = #_id, \
91 .supply_name = (_supply), \
92 .of_match = of_match_ptr(_match), \
93 .regulators_node = of_match_ptr("regulators"), \
94 .type = REGULATOR_VOLTAGE, \
95 - .id = AXP20X_##_id, \
96 + .id = _family##_##_id, \
97 .n_voltages = ARRAY_SIZE(_table), \
98 .owner = THIS_MODULE, \
99 .vsel_reg = (_vreg), \
100 @@ -136,37 +136,57 @@ static struct regulator_ops axp20x_ops = {
101 };
102
103 static const struct regulator_desc axp20x_regulators[] = {
104 - AXP20X_DESC(DCDC2, "dcdc2", "vin2", 700, 2275, 25, AXP20X_DCDC2_V_OUT,
105 - 0x3f, AXP20X_PWR_OUT_CTRL, 0x10),
106 - AXP20X_DESC(DCDC3, "dcdc3", "vin3", 700, 3500, 25, AXP20X_DCDC3_V_OUT,
107 - 0x7f, AXP20X_PWR_OUT_CTRL, 0x02),
108 - AXP20X_DESC_FIXED(LDO1, "ldo1", "acin", 1300),
109 - AXP20X_DESC(LDO2, "ldo2", "ldo24in", 1800, 3300, 100,
110 - AXP20X_LDO24_V_OUT, 0xf0, AXP20X_PWR_OUT_CTRL, 0x04),
111 - AXP20X_DESC(LDO3, "ldo3", "ldo3in", 700, 3500, 25, AXP20X_LDO3_V_OUT,
112 - 0x7f, AXP20X_PWR_OUT_CTRL, 0x40),
113 - AXP20X_DESC_TABLE(LDO4, "ldo4", "ldo24in", axp20x_ldo4_data,
114 - AXP20X_LDO24_V_OUT, 0x0f, AXP20X_PWR_OUT_CTRL, 0x08),
115 - AXP20X_DESC_IO(LDO5, "ldo5", "ldo5in", 1800, 3300, 100,
116 - AXP20X_LDO5_V_OUT, 0xf0, AXP20X_GPIO0_CTRL, 0x07,
117 - AXP20X_IO_ENABLED, AXP20X_IO_DISABLED),
118 + AXP_DESC(AXP20X, DCDC2, "dcdc2", "vin2", 700, 2275, 25,
119 + AXP20X_DCDC2_V_OUT, 0x3f, AXP20X_PWR_OUT_CTRL, 0x10),
120 + AXP_DESC(AXP20X, DCDC3, "dcdc3", "vin3", 700, 3500, 25,
121 + AXP20X_DCDC3_V_OUT, 0x7f, AXP20X_PWR_OUT_CTRL, 0x02),
122 + AXP_DESC_FIXED(AXP20X, LDO1, "ldo1", "acin", 1300),
123 + AXP_DESC(AXP20X, LDO2, "ldo2", "ldo24in", 1800, 3300, 100,
124 + AXP20X_LDO24_V_OUT, 0xf0, AXP20X_PWR_OUT_CTRL, 0x04),
125 + AXP_DESC(AXP20X, LDO3, "ldo3", "ldo3in", 700, 3500, 25,
126 + AXP20X_LDO3_V_OUT, 0x7f, AXP20X_PWR_OUT_CTRL, 0x40),
127 + AXP_DESC_TABLE(AXP20X, LDO4, "ldo4", "ldo24in", axp20x_ldo4_data,
128 + AXP20X_LDO24_V_OUT, 0x0f, AXP20X_PWR_OUT_CTRL, 0x08),
129 + AXP_DESC_IO(AXP20X, LDO5, "ldo5", "ldo5in", 1800, 3300, 100,
130 + AXP20X_LDO5_V_OUT, 0xf0, AXP20X_GPIO0_CTRL, 0x07,
131 + AXP20X_IO_ENABLED, AXP20X_IO_DISABLED),
132 };
133
134 static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
135 {
136 struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
137 + u32 min, max, def, step;
138 +
139 + switch (axp20x->variant) {
140 + case AXP202_ID:
141 + case AXP209_ID:
142 + min = 750;
143 + max = 1875;
144 + def = 1500;
145 + step = 75;
146 + break;
147 + default:
148 + dev_err(&pdev->dev,
149 + "Setting DCDC frequency for unsupported AXP variant\n");
150 + return -EINVAL;
151 + }
152 +
153 + if (dcdcfreq == 0)
154 + dcdcfreq = def;
155
156 - if (dcdcfreq < 750) {
157 - dcdcfreq = 750;
158 - dev_warn(&pdev->dev, "DCDC frequency too low. Set to 750kHz\n");
159 + if (dcdcfreq < min) {
160 + dcdcfreq = min;
161 + dev_warn(&pdev->dev, "DCDC frequency too low. Set to %ukHz\n",
162 + min);
163 }
164
165 - if (dcdcfreq > 1875) {
166 - dcdcfreq = 1875;
167 - dev_warn(&pdev->dev, "DCDC frequency too high. Set to 1875kHz\n");
168 + if (dcdcfreq > max) {
169 + dcdcfreq = max;
170 + dev_warn(&pdev->dev, "DCDC frequency too high. Set to %ukHz\n",
171 + max);
172 }
173
174 - dcdcfreq = (dcdcfreq - 750) / 75;
175 + dcdcfreq = (dcdcfreq - min) / step;
176
177 return regmap_update_bits(axp20x->regmap, AXP20X_DCDC_FREQ,
178 AXP20X_FREQ_DCDC_MASK, dcdcfreq);
179 @@ -176,7 +196,7 @@ static int axp20x_regulator_parse_dt(struct platform_device *pdev)
180 {
181 struct device_node *np, *regulators;
182 int ret;
183 - u32 dcdcfreq;
184 + u32 dcdcfreq = 0;
185
186 np = of_node_get(pdev->dev.parent->of_node);
187 if (!np)
188 @@ -186,7 +206,6 @@ static int axp20x_regulator_parse_dt(struct platform_device *pdev)
189 if (!regulators) {
190 dev_warn(&pdev->dev, "regulators node not found\n");
191 } else {
192 - dcdcfreq = 1500;
193 of_property_read_u32(regulators, "x-powers,dcdc-freq", &dcdcfreq);
194 ret = axp20x_set_dcdc_freq(pdev, dcdcfreq);
195 if (ret < 0) {
196 @@ -202,15 +221,27 @@ static int axp20x_regulator_parse_dt(struct platform_device *pdev)
197
198 static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode)
199 {
200 - unsigned int mask = AXP20X_WORKMODE_DCDC2_MASK;
201 + struct axp20x_dev *axp20x = rdev_get_drvdata(rdev);
202 + unsigned int mask;
203
204 - if ((id != AXP20X_DCDC2) && (id != AXP20X_DCDC3))
205 - return -EINVAL;
206 + switch (axp20x->variant) {
207 + case AXP202_ID:
208 + case AXP209_ID:
209 + if ((id != AXP20X_DCDC2) && (id != AXP20X_DCDC3))
210 + return -EINVAL;
211 +
212 + mask = AXP20X_WORKMODE_DCDC2_MASK;
213 + if (id == AXP20X_DCDC3)
214 + mask = AXP20X_WORKMODE_DCDC3_MASK;
215
216 - if (id == AXP20X_DCDC3)
217 - mask = AXP20X_WORKMODE_DCDC3_MASK;
218 + workmode <<= ffs(mask) - 1;
219 + break;
220
221 - workmode <<= ffs(mask) - 1;
222 + default:
223 + /* should not happen */
224 + WARN_ON(1);
225 + return -EINVAL;
226 + }
227
228 return regmap_update_bits(rdev->regmap, AXP20X_DCDC_MODE, mask, workmode);
229 }
230 @@ -219,22 +250,36 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
231 {
232 struct regulator_dev *rdev;
233 struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
234 + const struct regulator_desc *regulators;
235 struct regulator_config config = {
236 .dev = pdev->dev.parent,
237 .regmap = axp20x->regmap,
238 + .driver_data = axp20x,
239 };
240 - int ret, i;
241 + int ret, i, nregulators;
242 u32 workmode;
243
244 + switch (axp20x->variant) {
245 + case AXP202_ID:
246 + case AXP209_ID:
247 + regulators = axp20x_regulators;
248 + nregulators = AXP20X_REG_ID_MAX;
249 + break;
250 + default:
251 + dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
252 + axp20x->variant);
253 + return -EINVAL;
254 + }
255 +
256 /* This only sets the dcdc freq. Ignore any errors */
257 axp20x_regulator_parse_dt(pdev);
258
259 - for (i = 0; i < AXP20X_REG_ID_MAX; i++) {
260 - rdev = devm_regulator_register(&pdev->dev, &axp20x_regulators[i],
261 + for (i = 0; i < nregulators; i++) {
262 + rdev = devm_regulator_register(&pdev->dev, &regulators[i],
263 &config);
264 if (IS_ERR(rdev)) {
265 dev_err(&pdev->dev, "Failed to register %s\n",
266 - axp20x_regulators[i].name);
267 + regulators[i].name);
268
269 return PTR_ERR(rdev);
270 }
271 @@ -245,7 +290,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
272 if (!ret) {
273 if (axp20x_set_dcdc_workmode(rdev, i, workmode))
274 dev_err(&pdev->dev, "Failed to set workmode on %s\n",
275 - axp20x_regulators[i].name);
276 + rdev->desc->name);
277 }
278 }
279