diff options
author | Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> | 2018-05-30 04:43:43 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2018-05-30 06:31:22 -0400 |
commit | ba08799e90b5935a3df20766a73b5841046f6832 (patch) | |
tree | fb98a693669022c8011e71a78f8555195eabeda1 | |
parent | 196c813570afd0d52d453ef3b77c4c15ca760327 (diff) |
regulator: bd71837: BD71837 PMIC regulator driver
Support for controlling the 8 bucks and 7 LDOs the PMIC contains.
Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | drivers/regulator/Kconfig | 11 | ||||
-rw-r--r-- | drivers/regulator/Makefile | 1 | ||||
-rw-r--r-- | drivers/regulator/bd71837-regulator.c | 640 |
3 files changed, 652 insertions, 0 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 4efae3b7e746..5dbccf5f3037 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -180,6 +180,17 @@ config REGULATOR_BCM590XX | |||
180 | BCM590xx PMUs. This will enable support for the software | 180 | BCM590xx PMUs. This will enable support for the software |
181 | controllable LDO/Switching regulators. | 181 | controllable LDO/Switching regulators. |
182 | 182 | ||
183 | config REGULATOR_BD71837 | ||
184 | tristate "ROHM BD71837 Power Regulator" | ||
185 | depends on MFD_BD71837 | ||
186 | help | ||
187 | This driver supports voltage regulators on ROHM BD71837 PMIC. | ||
188 | This will enable support for the software controllable buck | ||
189 | and LDO regulators. | ||
190 | |||
191 | This driver can also be built as a module. If so, the module | ||
192 | will be called bd71837-regulator. | ||
193 | |||
183 | config REGULATOR_BD9571MWV | 194 | config REGULATOR_BD9571MWV |
184 | tristate "ROHM BD9571MWV Regulators" | 195 | tristate "ROHM BD9571MWV Regulators" |
185 | depends on MFD_BD9571MWV | 196 | depends on MFD_BD9571MWV |
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index d81fb02bd6e9..bd818ceb7c72 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
@@ -27,6 +27,7 @@ obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o | |||
27 | obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o | 27 | obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o |
28 | obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o | 28 | obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o |
29 | obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o | 29 | obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o |
30 | obj-$(CONFIG_REGULATOR_BD71837) += bd71837-regulator.o | ||
30 | obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o | 31 | obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o |
31 | obj-$(CONFIG_REGULATOR_DA903X) += da903x.o | 32 | obj-$(CONFIG_REGULATOR_DA903X) += da903x.o |
32 | obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o | 33 | obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o |
diff --git a/drivers/regulator/bd71837-regulator.c b/drivers/regulator/bd71837-regulator.c new file mode 100644 index 000000000000..6eae4d0432a2 --- /dev/null +++ b/drivers/regulator/bd71837-regulator.c | |||
@@ -0,0 +1,640 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // Copyright (C) 2018 ROHM Semiconductors | ||
3 | // bd71837-regulator.c ROHM BD71837MWV regulator driver | ||
4 | |||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/module.h> | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/err.h> | ||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/platform_device.h> | ||
11 | #include <linux/regulator/driver.h> | ||
12 | #include <linux/regulator/machine.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/gpio.h> | ||
16 | #include <linux/mfd/bd71837.h> | ||
17 | #include <linux/regulator/of_regulator.h> | ||
18 | |||
19 | struct bd71837_pmic { | ||
20 | struct regulator_desc descs[BD71837_REGULATOR_CNT]; | ||
21 | struct bd71837 *mfd; | ||
22 | struct platform_device *pdev; | ||
23 | struct regulator_dev *rdev[BD71837_REGULATOR_CNT]; | ||
24 | }; | ||
25 | |||
26 | /* | ||
27 | * BUCK1/2/3/4 | ||
28 | * BUCK1RAMPRATE[1:0] BUCK1 DVS ramp rate setting | ||
29 | * 00: 10.00mV/usec 10mV 1uS | ||
30 | * 01: 5.00mV/usec 10mV 2uS | ||
31 | * 10: 2.50mV/usec 10mV 4uS | ||
32 | * 11: 1.25mV/usec 10mV 8uS | ||
33 | */ | ||
34 | static int bd71837_buck1234_set_ramp_delay(struct regulator_dev *rdev, | ||
35 | int ramp_delay) | ||
36 | { | ||
37 | struct bd71837_pmic *pmic = rdev_get_drvdata(rdev); | ||
38 | struct bd71837 *mfd = pmic->mfd; | ||
39 | int id = rdev->desc->id; | ||
40 | unsigned int ramp_value = BUCK_RAMPRATE_10P00MV; | ||
41 | |||
42 | dev_dbg(&(pmic->pdev->dev), "Buck[%d] Set Ramp = %d\n", id + 1, | ||
43 | ramp_delay); | ||
44 | switch (ramp_delay) { | ||
45 | case 1 ... 1250: | ||
46 | ramp_value = BUCK_RAMPRATE_1P25MV; | ||
47 | break; | ||
48 | case 1251 ... 2500: | ||
49 | ramp_value = BUCK_RAMPRATE_2P50MV; | ||
50 | break; | ||
51 | case 2501 ... 5000: | ||
52 | ramp_value = BUCK_RAMPRATE_5P00MV; | ||
53 | break; | ||
54 | case 5001 ... 10000: | ||
55 | ramp_value = BUCK_RAMPRATE_10P00MV; | ||
56 | break; | ||
57 | default: | ||
58 | ramp_value = BUCK_RAMPRATE_10P00MV; | ||
59 | dev_err(&pmic->pdev->dev, | ||
60 | "%s: ramp_delay: %d not supported, setting 10000mV//us\n", | ||
61 | rdev->desc->name, ramp_delay); | ||
62 | } | ||
63 | |||
64 | return regmap_update_bits(mfd->regmap, BD71837_REG_BUCK1_CTRL + id, | ||
65 | BUCK_RAMPRATE_MASK, ramp_value << 6); | ||
66 | } | ||
67 | |||
68 | /* Bucks 1 to 4 support DVS. PWM mode is used when voltage is changed. | ||
69 | * Bucks 5 to 8 and LDOs can use PFM and must be disabled when voltage | ||
70 | * is changed. Hence we return -EBUSY for these if voltage is changed | ||
71 | * when BUCK/LDO is enabled. | ||
72 | */ | ||
73 | static int bd71837_set_voltage_sel_restricted(struct regulator_dev *rdev, | ||
74 | unsigned int sel) | ||
75 | { | ||
76 | int ret; | ||
77 | |||
78 | ret = regulator_is_enabled_regmap(rdev); | ||
79 | if (!ret) | ||
80 | ret = regulator_set_voltage_sel_regmap(rdev, sel); | ||
81 | else if (ret == 1) | ||
82 | ret = -EBUSY; | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | static struct regulator_ops bd71837_ldo_regulator_ops = { | ||
87 | .enable = regulator_enable_regmap, | ||
88 | .disable = regulator_disable_regmap, | ||
89 | .is_enabled = regulator_is_enabled_regmap, | ||
90 | .list_voltage = regulator_list_voltage_linear_range, | ||
91 | .set_voltage_sel = bd71837_set_voltage_sel_restricted, | ||
92 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
93 | }; | ||
94 | |||
95 | static struct regulator_ops bd71837_ldo_regulator_nolinear_ops = { | ||
96 | .enable = regulator_enable_regmap, | ||
97 | .disable = regulator_disable_regmap, | ||
98 | .is_enabled = regulator_is_enabled_regmap, | ||
99 | .list_voltage = regulator_list_voltage_table, | ||
100 | .set_voltage_sel = bd71837_set_voltage_sel_restricted, | ||
101 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
102 | }; | ||
103 | |||
104 | static struct regulator_ops bd71837_buck_regulator_ops = { | ||
105 | .enable = regulator_enable_regmap, | ||
106 | .disable = regulator_disable_regmap, | ||
107 | .is_enabled = regulator_is_enabled_regmap, | ||
108 | .list_voltage = regulator_list_voltage_linear_range, | ||
109 | .set_voltage_sel = bd71837_set_voltage_sel_restricted, | ||
110 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
111 | .set_voltage_time_sel = regulator_set_voltage_time_sel, | ||
112 | }; | ||
113 | |||
114 | static struct regulator_ops bd71837_buck_regulator_nolinear_ops = { | ||
115 | .enable = regulator_enable_regmap, | ||
116 | .disable = regulator_disable_regmap, | ||
117 | .is_enabled = regulator_is_enabled_regmap, | ||
118 | .list_voltage = regulator_list_voltage_table, | ||
119 | .set_voltage_sel = bd71837_set_voltage_sel_restricted, | ||
120 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
121 | .set_voltage_time_sel = regulator_set_voltage_time_sel, | ||
122 | }; | ||
123 | |||
124 | static struct regulator_ops bd71837_buck1234_regulator_ops = { | ||
125 | .enable = regulator_enable_regmap, | ||
126 | .disable = regulator_disable_regmap, | ||
127 | .is_enabled = regulator_is_enabled_regmap, | ||
128 | .list_voltage = regulator_list_voltage_linear_range, | ||
129 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
130 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
131 | .set_voltage_time_sel = regulator_set_voltage_time_sel, | ||
132 | .set_ramp_delay = bd71837_buck1234_set_ramp_delay, | ||
133 | }; | ||
134 | |||
135 | /* | ||
136 | * BUCK1/2/3/4 | ||
137 | * 0.70 to 1.30V (10mV step) | ||
138 | */ | ||
139 | static const struct regulator_linear_range bd71837_buck1234_voltage_ranges[] = { | ||
140 | REGULATOR_LINEAR_RANGE(700000, 0x00, 0x3C, 10000), | ||
141 | REGULATOR_LINEAR_RANGE(1300000, 0x3D, 0x3F, 0), | ||
142 | }; | ||
143 | |||
144 | /* | ||
145 | * BUCK5 | ||
146 | * 0.9V to 1.35V () | ||
147 | */ | ||
148 | static const struct regulator_linear_range bd71837_buck5_voltage_ranges[] = { | ||
149 | REGULATOR_LINEAR_RANGE(700000, 0x00, 0x03, 100000), | ||
150 | REGULATOR_LINEAR_RANGE(1050000, 0x04, 0x05, 50000), | ||
151 | REGULATOR_LINEAR_RANGE(1200000, 0x06, 0x07, 150000), | ||
152 | }; | ||
153 | |||
154 | /* | ||
155 | * BUCK6 | ||
156 | * 3.0V to 3.3V (step 100mV) | ||
157 | */ | ||
158 | static const struct regulator_linear_range bd71837_buck6_voltage_ranges[] = { | ||
159 | REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000), | ||
160 | }; | ||
161 | |||
162 | /* | ||
163 | * BUCK7 | ||
164 | * 000 = 1.605V | ||
165 | * 001 = 1.695V | ||
166 | * 010 = 1.755V | ||
167 | * 011 = 1.8V (Initial) | ||
168 | * 100 = 1.845V | ||
169 | * 101 = 1.905V | ||
170 | * 110 = 1.95V | ||
171 | * 111 = 1.995V | ||
172 | */ | ||
173 | static const unsigned int buck_7_volts[] = { | ||
174 | 1605000, 1695000, 1755000, 1800000, 1845000, 1905000, 1950000, 1995000 | ||
175 | }; | ||
176 | |||
177 | /* | ||
178 | * BUCK8 | ||
179 | * 0.8V to 1.40V (step 10mV) | ||
180 | */ | ||
181 | static const struct regulator_linear_range bd71837_buck8_voltage_ranges[] = { | ||
182 | REGULATOR_LINEAR_RANGE(800000, 0x00, 0x3C, 10000), | ||
183 | REGULATOR_LINEAR_RANGE(1400000, 0x3D, 0x3F, 0), | ||
184 | }; | ||
185 | |||
186 | /* | ||
187 | * LDO1 | ||
188 | * 3.0 to 3.3V (100mV step) | ||
189 | */ | ||
190 | static const struct regulator_linear_range bd71837_ldo1_voltage_ranges[] = { | ||
191 | REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000), | ||
192 | }; | ||
193 | |||
194 | /* | ||
195 | * LDO2 | ||
196 | * 0.8 or 0.9V | ||
197 | */ | ||
198 | const unsigned int ldo_2_volts[] = { | ||
199 | 900000, 800000 | ||
200 | }; | ||
201 | |||
202 | /* | ||
203 | * LDO3 | ||
204 | * 1.8 to 3.3V (100mV step) | ||
205 | */ | ||
206 | static const struct regulator_linear_range bd71837_ldo3_voltage_ranges[] = { | ||
207 | REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000), | ||
208 | }; | ||
209 | |||
210 | /* | ||
211 | * LDO4 | ||
212 | * 0.9 to 1.8V (100mV step) | ||
213 | */ | ||
214 | static const struct regulator_linear_range bd71837_ldo4_voltage_ranges[] = { | ||
215 | REGULATOR_LINEAR_RANGE(900000, 0x00, 0x09, 100000), | ||
216 | REGULATOR_LINEAR_RANGE(1800000, 0x0A, 0x0F, 0), | ||
217 | }; | ||
218 | |||
219 | /* | ||
220 | * LDO5 | ||
221 | * 1.8 to 3.3V (100mV step) | ||
222 | */ | ||
223 | static const struct regulator_linear_range bd71837_ldo5_voltage_ranges[] = { | ||
224 | REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000), | ||
225 | }; | ||
226 | |||
227 | /* | ||
228 | * LDO6 | ||
229 | * 0.9 to 1.8V (100mV step) | ||
230 | */ | ||
231 | static const struct regulator_linear_range bd71837_ldo6_voltage_ranges[] = { | ||
232 | REGULATOR_LINEAR_RANGE(900000, 0x00, 0x09, 100000), | ||
233 | REGULATOR_LINEAR_RANGE(1800000, 0x0A, 0x0F, 0), | ||
234 | }; | ||
235 | |||
236 | /* | ||
237 | * LDO7 | ||
238 | * 1.8 to 3.3V (100mV step) | ||
239 | */ | ||
240 | static const struct regulator_linear_range bd71837_ldo7_voltage_ranges[] = { | ||
241 | REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000), | ||
242 | }; | ||
243 | |||
244 | static const struct regulator_desc bd71837_regulators[] = { | ||
245 | { | ||
246 | .name = "buck1", | ||
247 | .of_match = of_match_ptr("BUCK1"), | ||
248 | .regulators_node = of_match_ptr("regulators"), | ||
249 | .id = BD71837_BUCK1, | ||
250 | .ops = &bd71837_buck1234_regulator_ops, | ||
251 | .type = REGULATOR_VOLTAGE, | ||
252 | .n_voltages = BD71837_BUCK1_VOLTAGE_NUM, | ||
253 | .linear_ranges = bd71837_buck1234_voltage_ranges, | ||
254 | .n_linear_ranges = ARRAY_SIZE(bd71837_buck1234_voltage_ranges), | ||
255 | .vsel_reg = BD71837_REG_BUCK1_VOLT_RUN, | ||
256 | .vsel_mask = BUCK1_RUN_MASK, | ||
257 | .enable_reg = BD71837_REG_BUCK1_CTRL, | ||
258 | .enable_mask = BD71837_BUCK_EN, | ||
259 | .owner = THIS_MODULE, | ||
260 | }, | ||
261 | { | ||
262 | .name = "buck2", | ||
263 | .of_match = of_match_ptr("BUCK2"), | ||
264 | .regulators_node = of_match_ptr("regulators"), | ||
265 | .id = BD71837_BUCK2, | ||
266 | .ops = &bd71837_buck1234_regulator_ops, | ||
267 | .type = REGULATOR_VOLTAGE, | ||
268 | .n_voltages = BD71837_BUCK2_VOLTAGE_NUM, | ||
269 | .linear_ranges = bd71837_buck1234_voltage_ranges, | ||
270 | .n_linear_ranges = ARRAY_SIZE(bd71837_buck1234_voltage_ranges), | ||
271 | .vsel_reg = BD71837_REG_BUCK2_VOLT_RUN, | ||
272 | .vsel_mask = BUCK2_RUN_MASK, | ||
273 | .enable_reg = BD71837_REG_BUCK2_CTRL, | ||
274 | .enable_mask = BD71837_BUCK_EN, | ||
275 | .owner = THIS_MODULE, | ||
276 | }, | ||
277 | { | ||
278 | .name = "buck3", | ||
279 | .of_match = of_match_ptr("BUCK3"), | ||
280 | .regulators_node = of_match_ptr("regulators"), | ||
281 | .id = BD71837_BUCK3, | ||
282 | .ops = &bd71837_buck1234_regulator_ops, | ||
283 | .type = REGULATOR_VOLTAGE, | ||
284 | .n_voltages = BD71837_BUCK3_VOLTAGE_NUM, | ||
285 | .linear_ranges = bd71837_buck1234_voltage_ranges, | ||
286 | .n_linear_ranges = ARRAY_SIZE(bd71837_buck1234_voltage_ranges), | ||
287 | .vsel_reg = BD71837_REG_BUCK3_VOLT_RUN, | ||
288 | .vsel_mask = BUCK3_RUN_MASK, | ||
289 | .enable_reg = BD71837_REG_BUCK3_CTRL, | ||
290 | .enable_mask = BD71837_BUCK_EN, | ||
291 | .owner = THIS_MODULE, | ||
292 | }, | ||
293 | { | ||
294 | .name = "buck4", | ||
295 | .of_match = of_match_ptr("BUCK4"), | ||
296 | .regulators_node = of_match_ptr("regulators"), | ||
297 | .id = BD71837_BUCK4, | ||
298 | .ops = &bd71837_buck1234_regulator_ops, | ||
299 | .type = REGULATOR_VOLTAGE, | ||
300 | .n_voltages = BD71837_BUCK4_VOLTAGE_NUM, | ||
301 | .linear_ranges = bd71837_buck1234_voltage_ranges, | ||
302 | .n_linear_ranges = ARRAY_SIZE(bd71837_buck1234_voltage_ranges), | ||
303 | .vsel_reg = BD71837_REG_BUCK4_VOLT_RUN, | ||
304 | .vsel_mask = BUCK4_RUN_MASK, | ||
305 | .enable_reg = BD71837_REG_BUCK4_CTRL, | ||
306 | .enable_mask = BD71837_BUCK_EN, | ||
307 | .owner = THIS_MODULE, | ||
308 | }, | ||
309 | { | ||
310 | .name = "buck5", | ||
311 | .of_match = of_match_ptr("BUCK5"), | ||
312 | .regulators_node = of_match_ptr("regulators"), | ||
313 | .id = BD71837_BUCK5, | ||
314 | .ops = &bd71837_buck_regulator_ops, | ||
315 | .type = REGULATOR_VOLTAGE, | ||
316 | .n_voltages = BD71837_BUCK5_VOLTAGE_NUM, | ||
317 | .linear_ranges = bd71837_buck5_voltage_ranges, | ||
318 | .n_linear_ranges = ARRAY_SIZE(bd71837_buck5_voltage_ranges), | ||
319 | .vsel_reg = BD71837_REG_BUCK5_VOLT, | ||
320 | .vsel_mask = BUCK5_MASK, | ||
321 | .enable_reg = BD71837_REG_BUCK5_CTRL, | ||
322 | .enable_mask = BD71837_BUCK_EN, | ||
323 | .owner = THIS_MODULE, | ||
324 | }, | ||
325 | { | ||
326 | .name = "buck6", | ||
327 | .of_match = of_match_ptr("BUCK6"), | ||
328 | .regulators_node = of_match_ptr("regulators"), | ||
329 | .id = BD71837_BUCK6, | ||
330 | .ops = &bd71837_buck_regulator_ops, | ||
331 | .type = REGULATOR_VOLTAGE, | ||
332 | .n_voltages = BD71837_BUCK6_VOLTAGE_NUM, | ||
333 | .linear_ranges = bd71837_buck6_voltage_ranges, | ||
334 | .n_linear_ranges = ARRAY_SIZE(bd71837_buck6_voltage_ranges), | ||
335 | .vsel_reg = BD71837_REG_BUCK6_VOLT, | ||
336 | .vsel_mask = BUCK6_MASK, | ||
337 | .enable_reg = BD71837_REG_BUCK6_CTRL, | ||
338 | .enable_mask = BD71837_BUCK_EN, | ||
339 | .owner = THIS_MODULE, | ||
340 | }, | ||
341 | { | ||
342 | .name = "buck7", | ||
343 | .of_match = of_match_ptr("BUCK7"), | ||
344 | .regulators_node = of_match_ptr("regulators"), | ||
345 | .id = BD71837_BUCK7, | ||
346 | .ops = &bd71837_buck_regulator_nolinear_ops, | ||
347 | .type = REGULATOR_VOLTAGE, | ||
348 | .volt_table = &buck_7_volts[0], | ||
349 | .n_voltages = ARRAY_SIZE(buck_7_volts), | ||
350 | .vsel_reg = BD71837_REG_BUCK7_VOLT, | ||
351 | .vsel_mask = BUCK7_MASK, | ||
352 | .enable_reg = BD71837_REG_BUCK7_CTRL, | ||
353 | .enable_mask = BD71837_BUCK_EN, | ||
354 | .owner = THIS_MODULE, | ||
355 | }, | ||
356 | { | ||
357 | .name = "buck8", | ||
358 | .of_match = of_match_ptr("BUCK8"), | ||
359 | .regulators_node = of_match_ptr("regulators"), | ||
360 | .id = BD71837_BUCK8, | ||
361 | .ops = &bd71837_buck_regulator_ops, | ||
362 | .type = REGULATOR_VOLTAGE, | ||
363 | .n_voltages = BD71837_BUCK8_VOLTAGE_NUM, | ||
364 | .linear_ranges = bd71837_buck8_voltage_ranges, | ||
365 | .n_linear_ranges = ARRAY_SIZE(bd71837_buck8_voltage_ranges), | ||
366 | .vsel_reg = BD71837_REG_BUCK8_VOLT, | ||
367 | .vsel_mask = BUCK8_MASK, | ||
368 | .enable_reg = BD71837_REG_BUCK8_CTRL, | ||
369 | .enable_mask = BD71837_BUCK_EN, | ||
370 | .owner = THIS_MODULE, | ||
371 | }, | ||
372 | { | ||
373 | .name = "ldo1", | ||
374 | .of_match = of_match_ptr("LDO1"), | ||
375 | .regulators_node = of_match_ptr("regulators"), | ||
376 | .id = BD71837_LDO1, | ||
377 | .ops = &bd71837_ldo_regulator_ops, | ||
378 | .type = REGULATOR_VOLTAGE, | ||
379 | .n_voltages = BD71837_LDO1_VOLTAGE_NUM, | ||
380 | .linear_ranges = bd71837_ldo1_voltage_ranges, | ||
381 | .n_linear_ranges = ARRAY_SIZE(bd71837_ldo1_voltage_ranges), | ||
382 | .vsel_reg = BD71837_REG_LDO1_VOLT, | ||
383 | .vsel_mask = LDO1_MASK, | ||
384 | .enable_reg = BD71837_REG_LDO1_VOLT, | ||
385 | .enable_mask = BD71837_LDO_EN, | ||
386 | .owner = THIS_MODULE, | ||
387 | }, | ||
388 | { | ||
389 | .name = "ldo2", | ||
390 | .of_match = of_match_ptr("LDO2"), | ||
391 | .regulators_node = of_match_ptr("regulators"), | ||
392 | .id = BD71837_LDO2, | ||
393 | .ops = &bd71837_ldo_regulator_nolinear_ops, | ||
394 | .type = REGULATOR_VOLTAGE, | ||
395 | .volt_table = &ldo_2_volts[0], | ||
396 | .vsel_reg = BD71837_REG_LDO2_VOLT, | ||
397 | .vsel_mask = LDO2_MASK, | ||
398 | .n_voltages = ARRAY_SIZE(ldo_2_volts), | ||
399 | .n_voltages = BD71837_LDO2_VOLTAGE_NUM, | ||
400 | .enable_reg = BD71837_REG_LDO2_VOLT, | ||
401 | .enable_mask = BD71837_LDO_EN, | ||
402 | .owner = THIS_MODULE, | ||
403 | }, | ||
404 | { | ||
405 | .name = "ldo3", | ||
406 | .of_match = of_match_ptr("LDO3"), | ||
407 | .regulators_node = of_match_ptr("regulators"), | ||
408 | .id = BD71837_LDO3, | ||
409 | .ops = &bd71837_ldo_regulator_ops, | ||
410 | .type = REGULATOR_VOLTAGE, | ||
411 | .n_voltages = BD71837_LDO3_VOLTAGE_NUM, | ||
412 | .linear_ranges = bd71837_ldo3_voltage_ranges, | ||
413 | .n_linear_ranges = ARRAY_SIZE(bd71837_ldo3_voltage_ranges), | ||
414 | .vsel_reg = BD71837_REG_LDO3_VOLT, | ||
415 | .vsel_mask = LDO3_MASK, | ||
416 | .enable_reg = BD71837_REG_LDO3_VOLT, | ||
417 | .enable_mask = BD71837_LDO_EN, | ||
418 | .owner = THIS_MODULE, | ||
419 | }, | ||
420 | { | ||
421 | .name = "ldo4", | ||
422 | .of_match = of_match_ptr("LDO4"), | ||
423 | .regulators_node = of_match_ptr("regulators"), | ||
424 | .id = BD71837_LDO4, | ||
425 | .ops = &bd71837_ldo_regulator_ops, | ||
426 | .type = REGULATOR_VOLTAGE, | ||
427 | .n_voltages = BD71837_LDO4_VOLTAGE_NUM, | ||
428 | .linear_ranges = bd71837_ldo4_voltage_ranges, | ||
429 | .n_linear_ranges = ARRAY_SIZE(bd71837_ldo4_voltage_ranges), | ||
430 | .vsel_reg = BD71837_REG_LDO4_VOLT, | ||
431 | .vsel_mask = LDO4_MASK, | ||
432 | .enable_reg = BD71837_REG_LDO4_VOLT, | ||
433 | .enable_mask = BD71837_LDO_EN, | ||
434 | .owner = THIS_MODULE, | ||
435 | }, | ||
436 | { | ||
437 | .name = "ldo5", | ||
438 | .of_match = of_match_ptr("LDO5"), | ||
439 | .regulators_node = of_match_ptr("regulators"), | ||
440 | .id = BD71837_LDO5, | ||
441 | .ops = &bd71837_ldo_regulator_ops, | ||
442 | .type = REGULATOR_VOLTAGE, | ||
443 | .n_voltages = BD71837_LDO5_VOLTAGE_NUM, | ||
444 | .linear_ranges = bd71837_ldo5_voltage_ranges, | ||
445 | .n_linear_ranges = ARRAY_SIZE(bd71837_ldo5_voltage_ranges), | ||
446 | /* LDO5 is supplied by buck6 */ | ||
447 | .supply_name = "buck6", | ||
448 | .vsel_reg = BD71837_REG_LDO5_VOLT, | ||
449 | .vsel_mask = LDO5_MASK, | ||
450 | .enable_reg = BD71837_REG_LDO5_VOLT, | ||
451 | .enable_mask = BD71837_LDO_EN, | ||
452 | .owner = THIS_MODULE, | ||
453 | }, | ||
454 | { | ||
455 | .name = "ldo6", | ||
456 | .of_match = of_match_ptr("LDO6"), | ||
457 | .regulators_node = of_match_ptr("regulators"), | ||
458 | .id = BD71837_LDO6, | ||
459 | .ops = &bd71837_ldo_regulator_ops, | ||
460 | .type = REGULATOR_VOLTAGE, | ||
461 | .n_voltages = BD71837_LDO6_VOLTAGE_NUM, | ||
462 | .linear_ranges = bd71837_ldo6_voltage_ranges, | ||
463 | .n_linear_ranges = ARRAY_SIZE(bd71837_ldo6_voltage_ranges), | ||
464 | /* LDO6 is supplied by buck7 */ | ||
465 | .supply_name = "buck7", | ||
466 | .vsel_reg = BD71837_REG_LDO6_VOLT, | ||
467 | .vsel_mask = LDO6_MASK, | ||
468 | .enable_reg = BD71837_REG_LDO6_VOLT, | ||
469 | .enable_mask = BD71837_LDO_EN, | ||
470 | .owner = THIS_MODULE, | ||
471 | }, | ||
472 | { | ||
473 | .name = "ldo7", | ||
474 | .of_match = of_match_ptr("LDO7"), | ||
475 | .regulators_node = of_match_ptr("regulators"), | ||
476 | .id = BD71837_LDO7, | ||
477 | .ops = &bd71837_ldo_regulator_ops, | ||
478 | .type = REGULATOR_VOLTAGE, | ||
479 | .n_voltages = BD71837_LDO7_VOLTAGE_NUM, | ||
480 | .linear_ranges = bd71837_ldo7_voltage_ranges, | ||
481 | .n_linear_ranges = ARRAY_SIZE(bd71837_ldo7_voltage_ranges), | ||
482 | .vsel_reg = BD71837_REG_LDO7_VOLT, | ||
483 | .vsel_mask = LDO7_MASK, | ||
484 | .enable_reg = BD71837_REG_LDO7_VOLT, | ||
485 | .enable_mask = BD71837_LDO_EN, | ||
486 | .owner = THIS_MODULE, | ||
487 | }, | ||
488 | }; | ||
489 | |||
490 | struct reg_init { | ||
491 | unsigned int reg; | ||
492 | unsigned int mask; | ||
493 | }; | ||
494 | |||
495 | static int bd71837_probe(struct platform_device *pdev) | ||
496 | { | ||
497 | struct bd71837_pmic *pmic; | ||
498 | struct bd71837_board *pdata; | ||
499 | struct regulator_config config = { 0 }; | ||
500 | struct reg_init pmic_regulator_inits[] = { | ||
501 | { | ||
502 | .reg = BD71837_REG_BUCK1_CTRL, | ||
503 | .mask = BD71837_BUCK_SEL, | ||
504 | }, { | ||
505 | .reg = BD71837_REG_BUCK2_CTRL, | ||
506 | .mask = BD71837_BUCK_SEL, | ||
507 | }, { | ||
508 | .reg = BD71837_REG_BUCK3_CTRL, | ||
509 | .mask = BD71837_BUCK_SEL, | ||
510 | }, { | ||
511 | .reg = BD71837_REG_BUCK4_CTRL, | ||
512 | .mask = BD71837_BUCK_SEL, | ||
513 | }, { | ||
514 | .reg = BD71837_REG_BUCK5_CTRL, | ||
515 | .mask = BD71837_BUCK_SEL, | ||
516 | }, { | ||
517 | .reg = BD71837_REG_BUCK6_CTRL, | ||
518 | .mask = BD71837_BUCK_SEL, | ||
519 | }, { | ||
520 | .reg = BD71837_REG_BUCK7_CTRL, | ||
521 | .mask = BD71837_BUCK_SEL, | ||
522 | }, { | ||
523 | .reg = BD71837_REG_BUCK8_CTRL, | ||
524 | .mask = BD71837_BUCK_SEL, | ||
525 | }, { | ||
526 | .reg = BD71837_REG_LDO1_VOLT, | ||
527 | .mask = BD71837_LDO_SEL, | ||
528 | }, { | ||
529 | .reg = BD71837_REG_LDO2_VOLT, | ||
530 | .mask = BD71837_LDO_SEL, | ||
531 | }, { | ||
532 | .reg = BD71837_REG_LDO3_VOLT, | ||
533 | .mask = BD71837_LDO_SEL, | ||
534 | }, { | ||
535 | .reg = BD71837_REG_LDO4_VOLT, | ||
536 | .mask = BD71837_LDO_SEL, | ||
537 | }, { | ||
538 | .reg = BD71837_REG_LDO5_VOLT, | ||
539 | .mask = BD71837_LDO_SEL, | ||
540 | }, { | ||
541 | .reg = BD71837_REG_LDO6_VOLT, | ||
542 | .mask = BD71837_LDO_SEL, | ||
543 | }, { | ||
544 | .reg = BD71837_REG_LDO7_VOLT, | ||
545 | .mask = BD71837_LDO_SEL, | ||
546 | } | ||
547 | }; | ||
548 | |||
549 | int i, err; | ||
550 | |||
551 | pmic = devm_kzalloc(&pdev->dev, sizeof(struct bd71837_pmic), | ||
552 | GFP_KERNEL); | ||
553 | if (!pmic) | ||
554 | return -ENOMEM; | ||
555 | |||
556 | memcpy(pmic->descs, bd71837_regulators, sizeof(pmic->descs)); | ||
557 | |||
558 | pmic->pdev = pdev; | ||
559 | pmic->mfd = dev_get_drvdata(pdev->dev.parent); | ||
560 | |||
561 | if (!pmic->mfd) { | ||
562 | dev_err(&pdev->dev, "No MFD driver data\n"); | ||
563 | err = -EINVAL; | ||
564 | goto err; | ||
565 | } | ||
566 | platform_set_drvdata(pdev, pmic); | ||
567 | pdata = dev_get_platdata(pmic->mfd->dev); | ||
568 | |||
569 | /* Register LOCK release */ | ||
570 | err = regmap_update_bits(pmic->mfd->regmap, BD71837_REG_REGLOCK, | ||
571 | (REGLOCK_PWRSEQ | REGLOCK_VREG), 0); | ||
572 | if (err) { | ||
573 | dev_err(&pmic->pdev->dev, "Failed to unlock PMIC (%d)\n", err); | ||
574 | goto err; | ||
575 | } else { | ||
576 | dev_dbg(&pmic->pdev->dev, "%s: Unlocked lock register 0x%x\n", | ||
577 | __func__, BD71837_REG_REGLOCK); | ||
578 | } | ||
579 | |||
580 | for (i = 0; i < ARRAY_SIZE(pmic_regulator_inits); i++) { | ||
581 | |||
582 | struct regulator_desc *desc; | ||
583 | struct regulator_dev *rdev; | ||
584 | |||
585 | desc = &pmic->descs[i]; | ||
586 | |||
587 | if (pdata) | ||
588 | config.init_data = pdata->init_data[i]; | ||
589 | |||
590 | config.dev = pdev->dev.parent; | ||
591 | config.driver_data = pmic; | ||
592 | config.regmap = pmic->mfd->regmap; | ||
593 | |||
594 | rdev = devm_regulator_register(&pdev->dev, desc, &config); | ||
595 | if (IS_ERR(rdev)) { | ||
596 | dev_err(pmic->mfd->dev, | ||
597 | "failed to register %s regulator\n", | ||
598 | desc->name); | ||
599 | err = PTR_ERR(rdev); | ||
600 | goto err; | ||
601 | } | ||
602 | /* Regulator register gets the regulator constraints and | ||
603 | * applies them (set_machine_constraints). This should have | ||
604 | * turned the control register(s) to correct values and we | ||
605 | * can now switch the control from PMIC state machine to the | ||
606 | * register interface | ||
607 | */ | ||
608 | err = regmap_update_bits(pmic->mfd->regmap, | ||
609 | pmic_regulator_inits[i].reg, | ||
610 | pmic_regulator_inits[i].mask, | ||
611 | 0xFFFFFFFF); | ||
612 | if (err) { | ||
613 | dev_err(&pmic->pdev->dev, | ||
614 | "Failed to write BUCK/LDO SEL bit for (%s)\n", | ||
615 | desc->name); | ||
616 | goto err; | ||
617 | } | ||
618 | |||
619 | pmic->rdev[i] = rdev; | ||
620 | } | ||
621 | |||
622 | return 0; | ||
623 | |||
624 | err: | ||
625 | return err; | ||
626 | } | ||
627 | |||
628 | static struct platform_driver bd71837_regulator = { | ||
629 | .driver = { | ||
630 | .name = "bd71837-pmic", | ||
631 | .owner = THIS_MODULE, | ||
632 | }, | ||
633 | .probe = bd71837_probe, | ||
634 | }; | ||
635 | |||
636 | module_platform_driver(bd71837_regulator); | ||
637 | |||
638 | MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); | ||
639 | MODULE_DESCRIPTION("BD71837 voltage regulator driver"); | ||
640 | MODULE_LICENSE("GPL"); | ||