diff options
author | Sachin Kamat <sachin.kamat@linaro.org> | 2014-03-14 07:51:58 -0400 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2014-03-18 06:56:30 -0400 |
commit | f18792714608a670c2762d22f695d77d02fc965e (patch) | |
tree | 37859d7ac890744f6b51d1b780452d47c6597c5f | |
parent | ce24991e1e4d7bee05bcc0e156b0b1c2ef791dd3 (diff) |
regulator: Add support for S2MPA01 regulator
Add support for S2MPA01 voltage and current regulator.
Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
Acked-by: Mark Brown <broonie@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r-- | drivers/regulator/Kconfig | 7 | ||||
-rw-r--r-- | drivers/regulator/Makefile | 1 | ||||
-rw-r--r-- | drivers/regulator/s2mpa01.c | 481 |
3 files changed, 489 insertions, 0 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 6a7932822e37..8f8e6710bb45 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -416,6 +416,13 @@ config REGULATOR_RC5T583 | |||
416 | through regulator interface. The device supports multiple DCDC/LDO | 416 | through regulator interface. The device supports multiple DCDC/LDO |
417 | outputs which can be controlled by i2c communication. | 417 | outputs which can be controlled by i2c communication. |
418 | 418 | ||
419 | config REGULATOR_S2MPA01 | ||
420 | tristate "Samsung S2MPA01 voltage regulator" | ||
421 | depends on MFD_SEC_CORE | ||
422 | help | ||
423 | This driver controls Samsung S2MPA01 voltage output regulator | ||
424 | via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs. | ||
425 | |||
419 | config REGULATOR_S2MPS11 | 426 | config REGULATOR_S2MPS11 |
420 | tristate "Samsung S2MPS11 voltage regulator" | 427 | tristate "Samsung S2MPS11 voltage regulator" |
421 | depends on MFD_SEC_CORE | 428 | depends on MFD_SEC_CORE |
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 979f9ddcf259..b3ece84289cf 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
@@ -57,6 +57,7 @@ obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o | |||
57 | obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o | 57 | obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o |
58 | obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o | 58 | obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o |
59 | obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o | 59 | obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o |
60 | obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o | ||
60 | obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o | 61 | obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o |
61 | obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o | 62 | obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o |
62 | obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o | 63 | obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o |
diff --git a/drivers/regulator/s2mpa01.c b/drivers/regulator/s2mpa01.c new file mode 100644 index 000000000000..808b3aa7a42c --- /dev/null +++ b/drivers/regulator/s2mpa01.c | |||
@@ -0,0 +1,481 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Samsung Electronics Co., Ltd | ||
3 | * http://www.samsung.com | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/bug.h> | ||
13 | #include <linux/err.h> | ||
14 | #include <linux/gpio.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/of.h> | ||
18 | #include <linux/regmap.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/regulator/driver.h> | ||
21 | #include <linux/regulator/machine.h> | ||
22 | #include <linux/regulator/of_regulator.h> | ||
23 | #include <linux/mfd/samsung/core.h> | ||
24 | #include <linux/mfd/samsung/s2mpa01.h> | ||
25 | |||
26 | #define S2MPA01_REGULATOR_CNT ARRAY_SIZE(regulators) | ||
27 | |||
28 | struct s2mpa01_info { | ||
29 | int ramp_delay24; | ||
30 | int ramp_delay3; | ||
31 | int ramp_delay5; | ||
32 | int ramp_delay16; | ||
33 | int ramp_delay7; | ||
34 | int ramp_delay8910; | ||
35 | }; | ||
36 | |||
37 | static int get_ramp_delay(int ramp_delay) | ||
38 | { | ||
39 | unsigned char cnt = 0; | ||
40 | |||
41 | ramp_delay /= 6250; | ||
42 | |||
43 | while (true) { | ||
44 | ramp_delay = ramp_delay >> 1; | ||
45 | if (ramp_delay == 0) | ||
46 | break; | ||
47 | cnt++; | ||
48 | } | ||
49 | |||
50 | if (cnt > 3) | ||
51 | cnt = 3; | ||
52 | |||
53 | return cnt; | ||
54 | } | ||
55 | |||
56 | static int s2mpa01_regulator_set_voltage_time_sel(struct regulator_dev *rdev, | ||
57 | unsigned int old_selector, | ||
58 | unsigned int new_selector) | ||
59 | { | ||
60 | struct s2mpa01_info *s2mpa01 = rdev_get_drvdata(rdev); | ||
61 | unsigned int ramp_delay = 0; | ||
62 | int old_volt, new_volt; | ||
63 | |||
64 | switch (rdev->desc->id) { | ||
65 | case S2MPA01_BUCK2: | ||
66 | case S2MPA01_BUCK4: | ||
67 | ramp_delay = s2mpa01->ramp_delay24; | ||
68 | break; | ||
69 | case S2MPA01_BUCK3: | ||
70 | ramp_delay = s2mpa01->ramp_delay3; | ||
71 | break; | ||
72 | case S2MPA01_BUCK5: | ||
73 | ramp_delay = s2mpa01->ramp_delay5; | ||
74 | break; | ||
75 | case S2MPA01_BUCK1: | ||
76 | case S2MPA01_BUCK6: | ||
77 | ramp_delay = s2mpa01->ramp_delay16; | ||
78 | break; | ||
79 | case S2MPA01_BUCK7: | ||
80 | ramp_delay = s2mpa01->ramp_delay7; | ||
81 | break; | ||
82 | case S2MPA01_BUCK8: | ||
83 | case S2MPA01_BUCK9: | ||
84 | case S2MPA01_BUCK10: | ||
85 | ramp_delay = s2mpa01->ramp_delay8910; | ||
86 | break; | ||
87 | } | ||
88 | |||
89 | if (ramp_delay == 0) | ||
90 | ramp_delay = rdev->desc->ramp_delay; | ||
91 | |||
92 | old_volt = rdev->desc->min_uV + (rdev->desc->uV_step * old_selector); | ||
93 | new_volt = rdev->desc->min_uV + (rdev->desc->uV_step * new_selector); | ||
94 | |||
95 | return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); | ||
96 | } | ||
97 | |||
98 | static int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) | ||
99 | { | ||
100 | struct s2mpa01_info *s2mpa01 = rdev_get_drvdata(rdev); | ||
101 | unsigned int ramp_val, ramp_shift, ramp_reg = S2MPA01_REG_RAMP2; | ||
102 | unsigned int ramp_enable = 1, enable_shift = 0; | ||
103 | int ret; | ||
104 | |||
105 | switch (rdev->desc->id) { | ||
106 | case S2MPA01_BUCK1: | ||
107 | enable_shift = S2MPA01_BUCK1_RAMP_EN_SHIFT; | ||
108 | if (!ramp_delay) { | ||
109 | ramp_enable = 0; | ||
110 | break; | ||
111 | } | ||
112 | |||
113 | if (ramp_delay > s2mpa01->ramp_delay16) | ||
114 | s2mpa01->ramp_delay16 = ramp_delay; | ||
115 | else | ||
116 | ramp_delay = s2mpa01->ramp_delay16; | ||
117 | |||
118 | ramp_shift = S2MPA01_BUCK16_RAMP_SHIFT; | ||
119 | ramp_reg = S2MPA01_REG_RAMP1; | ||
120 | break; | ||
121 | case S2MPA01_BUCK2: | ||
122 | enable_shift = S2MPA01_BUCK2_RAMP_EN_SHIFT; | ||
123 | if (!ramp_delay) { | ||
124 | ramp_enable = 0; | ||
125 | break; | ||
126 | } | ||
127 | |||
128 | if (ramp_delay > s2mpa01->ramp_delay24) | ||
129 | s2mpa01->ramp_delay24 = ramp_delay; | ||
130 | else | ||
131 | ramp_delay = s2mpa01->ramp_delay24; | ||
132 | |||
133 | ramp_shift = S2MPA01_BUCK24_RAMP_SHIFT; | ||
134 | ramp_reg = S2MPA01_REG_RAMP1; | ||
135 | break; | ||
136 | case S2MPA01_BUCK3: | ||
137 | enable_shift = S2MPA01_BUCK3_RAMP_EN_SHIFT; | ||
138 | if (!ramp_delay) { | ||
139 | ramp_enable = 0; | ||
140 | break; | ||
141 | } | ||
142 | |||
143 | s2mpa01->ramp_delay3 = ramp_delay; | ||
144 | ramp_shift = S2MPA01_BUCK3_RAMP_SHIFT; | ||
145 | ramp_reg = S2MPA01_REG_RAMP1; | ||
146 | break; | ||
147 | case S2MPA01_BUCK4: | ||
148 | enable_shift = S2MPA01_BUCK4_RAMP_EN_SHIFT; | ||
149 | if (!ramp_delay) { | ||
150 | ramp_enable = 0; | ||
151 | break; | ||
152 | } | ||
153 | |||
154 | if (ramp_delay > s2mpa01->ramp_delay24) | ||
155 | s2mpa01->ramp_delay24 = ramp_delay; | ||
156 | else | ||
157 | ramp_delay = s2mpa01->ramp_delay24; | ||
158 | |||
159 | ramp_shift = S2MPA01_BUCK24_RAMP_SHIFT; | ||
160 | ramp_reg = S2MPA01_REG_RAMP1; | ||
161 | break; | ||
162 | case S2MPA01_BUCK5: | ||
163 | s2mpa01->ramp_delay5 = ramp_delay; | ||
164 | ramp_shift = S2MPA01_BUCK5_RAMP_SHIFT; | ||
165 | break; | ||
166 | case S2MPA01_BUCK6: | ||
167 | if (ramp_delay > s2mpa01->ramp_delay16) | ||
168 | s2mpa01->ramp_delay16 = ramp_delay; | ||
169 | else | ||
170 | ramp_delay = s2mpa01->ramp_delay16; | ||
171 | |||
172 | ramp_shift = S2MPA01_BUCK16_RAMP_SHIFT; | ||
173 | break; | ||
174 | case S2MPA01_BUCK7: | ||
175 | s2mpa01->ramp_delay7 = ramp_delay; | ||
176 | ramp_shift = S2MPA01_BUCK7_RAMP_SHIFT; | ||
177 | break; | ||
178 | case S2MPA01_BUCK8: | ||
179 | case S2MPA01_BUCK9: | ||
180 | case S2MPA01_BUCK10: | ||
181 | if (ramp_delay > s2mpa01->ramp_delay8910) | ||
182 | s2mpa01->ramp_delay8910 = ramp_delay; | ||
183 | else | ||
184 | ramp_delay = s2mpa01->ramp_delay8910; | ||
185 | |||
186 | ramp_shift = S2MPA01_BUCK8910_RAMP_SHIFT; | ||
187 | break; | ||
188 | default: | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | if (!ramp_enable) | ||
193 | goto ramp_disable; | ||
194 | |||
195 | if (enable_shift) { | ||
196 | ret = regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1, | ||
197 | 1 << enable_shift, 1 << enable_shift); | ||
198 | if (ret) { | ||
199 | dev_err(&rdev->dev, "failed to enable ramp rate\n"); | ||
200 | return ret; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | ramp_val = get_ramp_delay(ramp_delay); | ||
205 | |||
206 | return regmap_update_bits(rdev->regmap, ramp_reg, 0x3 << ramp_shift, | ||
207 | ramp_val << ramp_shift); | ||
208 | |||
209 | ramp_disable: | ||
210 | return regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1, | ||
211 | 1 << enable_shift, 0); | ||
212 | } | ||
213 | |||
214 | static struct regulator_ops s2mpa01_ldo_ops = { | ||
215 | .list_voltage = regulator_list_voltage_linear, | ||
216 | .map_voltage = regulator_map_voltage_linear, | ||
217 | .is_enabled = regulator_is_enabled_regmap, | ||
218 | .enable = regulator_enable_regmap, | ||
219 | .disable = regulator_disable_regmap, | ||
220 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
221 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
222 | .set_voltage_time_sel = regulator_set_voltage_time_sel, | ||
223 | }; | ||
224 | |||
225 | static struct regulator_ops s2mpa01_buck_ops = { | ||
226 | .list_voltage = regulator_list_voltage_linear, | ||
227 | .map_voltage = regulator_map_voltage_linear, | ||
228 | .is_enabled = regulator_is_enabled_regmap, | ||
229 | .enable = regulator_enable_regmap, | ||
230 | .disable = regulator_disable_regmap, | ||
231 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
232 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
233 | .set_voltage_time_sel = s2mpa01_regulator_set_voltage_time_sel, | ||
234 | .set_ramp_delay = s2mpa01_set_ramp_delay, | ||
235 | }; | ||
236 | |||
237 | #define regulator_desc_ldo1(num) { \ | ||
238 | .name = "LDO"#num, \ | ||
239 | .id = S2MPA01_LDO##num, \ | ||
240 | .ops = &s2mpa01_ldo_ops, \ | ||
241 | .type = REGULATOR_VOLTAGE, \ | ||
242 | .owner = THIS_MODULE, \ | ||
243 | .min_uV = S2MPA01_LDO_MIN, \ | ||
244 | .uV_step = S2MPA01_LDO_STEP1, \ | ||
245 | .n_voltages = S2MPA01_LDO_N_VOLTAGES, \ | ||
246 | .vsel_reg = S2MPA01_REG_L1CTRL + num - 1, \ | ||
247 | .vsel_mask = S2MPA01_LDO_VSEL_MASK, \ | ||
248 | .enable_reg = S2MPA01_REG_L1CTRL + num - 1, \ | ||
249 | .enable_mask = S2MPA01_ENABLE_MASK \ | ||
250 | } | ||
251 | #define regulator_desc_ldo2(num) { \ | ||
252 | .name = "LDO"#num, \ | ||
253 | .id = S2MPA01_LDO##num, \ | ||
254 | .ops = &s2mpa01_ldo_ops, \ | ||
255 | .type = REGULATOR_VOLTAGE, \ | ||
256 | .owner = THIS_MODULE, \ | ||
257 | .min_uV = S2MPA01_LDO_MIN, \ | ||
258 | .uV_step = S2MPA01_LDO_STEP2, \ | ||
259 | .n_voltages = S2MPA01_LDO_N_VOLTAGES, \ | ||
260 | .vsel_reg = S2MPA01_REG_L1CTRL + num - 1, \ | ||
261 | .vsel_mask = S2MPA01_LDO_VSEL_MASK, \ | ||
262 | .enable_reg = S2MPA01_REG_L1CTRL + num - 1, \ | ||
263 | .enable_mask = S2MPA01_ENABLE_MASK \ | ||
264 | } | ||
265 | |||
266 | #define regulator_desc_buck1_4(num) { \ | ||
267 | .name = "BUCK"#num, \ | ||
268 | .id = S2MPA01_BUCK##num, \ | ||
269 | .ops = &s2mpa01_buck_ops, \ | ||
270 | .type = REGULATOR_VOLTAGE, \ | ||
271 | .owner = THIS_MODULE, \ | ||
272 | .min_uV = S2MPA01_BUCK_MIN1, \ | ||
273 | .uV_step = S2MPA01_BUCK_STEP1, \ | ||
274 | .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ | ||
275 | .ramp_delay = S2MPA01_RAMP_DELAY, \ | ||
276 | .vsel_reg = S2MPA01_REG_B1CTRL2 + (num - 1) * 2, \ | ||
277 | .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \ | ||
278 | .enable_reg = S2MPA01_REG_B1CTRL1 + (num - 1) * 2, \ | ||
279 | .enable_mask = S2MPA01_ENABLE_MASK \ | ||
280 | } | ||
281 | |||
282 | #define regulator_desc_buck5 { \ | ||
283 | .name = "BUCK5", \ | ||
284 | .id = S2MPA01_BUCK5, \ | ||
285 | .ops = &s2mpa01_buck_ops, \ | ||
286 | .type = REGULATOR_VOLTAGE, \ | ||
287 | .owner = THIS_MODULE, \ | ||
288 | .min_uV = S2MPA01_BUCK_MIN2, \ | ||
289 | .uV_step = S2MPA01_BUCK_STEP1, \ | ||
290 | .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ | ||
291 | .ramp_delay = S2MPA01_RAMP_DELAY, \ | ||
292 | .vsel_reg = S2MPA01_REG_B5CTRL2, \ | ||
293 | .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \ | ||
294 | .enable_reg = S2MPA01_REG_B5CTRL1, \ | ||
295 | .enable_mask = S2MPA01_ENABLE_MASK \ | ||
296 | } | ||
297 | |||
298 | #define regulator_desc_buck6_7(num) { \ | ||
299 | .name = "BUCK"#num, \ | ||
300 | .id = S2MPA01_BUCK##num, \ | ||
301 | .ops = &s2mpa01_buck_ops, \ | ||
302 | .type = REGULATOR_VOLTAGE, \ | ||
303 | .owner = THIS_MODULE, \ | ||
304 | .min_uV = S2MPA01_BUCK_MIN1, \ | ||
305 | .uV_step = S2MPA01_BUCK_STEP1, \ | ||
306 | .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ | ||
307 | .ramp_delay = S2MPA01_RAMP_DELAY, \ | ||
308 | .vsel_reg = S2MPA01_REG_B6CTRL2 + (num - 6) * 2, \ | ||
309 | .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \ | ||
310 | .enable_reg = S2MPA01_REG_B6CTRL1 + (num - 6) * 2, \ | ||
311 | .enable_mask = S2MPA01_ENABLE_MASK \ | ||
312 | } | ||
313 | |||
314 | #define regulator_desc_buck8 { \ | ||
315 | .name = "BUCK8", \ | ||
316 | .id = S2MPA01_BUCK8, \ | ||
317 | .ops = &s2mpa01_buck_ops, \ | ||
318 | .type = REGULATOR_VOLTAGE, \ | ||
319 | .owner = THIS_MODULE, \ | ||
320 | .min_uV = S2MPA01_BUCK_MIN2, \ | ||
321 | .uV_step = S2MPA01_BUCK_STEP2, \ | ||
322 | .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ | ||
323 | .ramp_delay = S2MPA01_RAMP_DELAY, \ | ||
324 | .vsel_reg = S2MPA01_REG_B8CTRL2, \ | ||
325 | .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \ | ||
326 | .enable_reg = S2MPA01_REG_B8CTRL1, \ | ||
327 | .enable_mask = S2MPA01_ENABLE_MASK \ | ||
328 | } | ||
329 | |||
330 | #define regulator_desc_buck9 { \ | ||
331 | .name = "BUCK9", \ | ||
332 | .id = S2MPA01_BUCK9, \ | ||
333 | .ops = &s2mpa01_buck_ops, \ | ||
334 | .type = REGULATOR_VOLTAGE, \ | ||
335 | .owner = THIS_MODULE, \ | ||
336 | .min_uV = S2MPA01_BUCK_MIN4, \ | ||
337 | .uV_step = S2MPA01_BUCK_STEP2, \ | ||
338 | .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ | ||
339 | .ramp_delay = S2MPA01_RAMP_DELAY, \ | ||
340 | .vsel_reg = S2MPA01_REG_B9CTRL2, \ | ||
341 | .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \ | ||
342 | .enable_reg = S2MPA01_REG_B9CTRL1, \ | ||
343 | .enable_mask = S2MPA01_ENABLE_MASK \ | ||
344 | } | ||
345 | |||
346 | #define regulator_desc_buck10 { \ | ||
347 | .name = "BUCK10", \ | ||
348 | .id = S2MPA01_BUCK10, \ | ||
349 | .ops = &s2mpa01_buck_ops, \ | ||
350 | .type = REGULATOR_VOLTAGE, \ | ||
351 | .owner = THIS_MODULE, \ | ||
352 | .min_uV = S2MPA01_BUCK_MIN3, \ | ||
353 | .uV_step = S2MPA01_BUCK_STEP2, \ | ||
354 | .n_voltages = S2MPA01_BUCK_N_VOLTAGES, \ | ||
355 | .ramp_delay = S2MPA01_RAMP_DELAY, \ | ||
356 | .vsel_reg = S2MPA01_REG_B10CTRL2, \ | ||
357 | .vsel_mask = S2MPA01_BUCK_VSEL_MASK, \ | ||
358 | .enable_reg = S2MPA01_REG_B10CTRL1, \ | ||
359 | .enable_mask = S2MPA01_ENABLE_MASK \ | ||
360 | } | ||
361 | |||
362 | static struct regulator_desc regulators[] = { | ||
363 | regulator_desc_ldo2(1), | ||
364 | regulator_desc_ldo1(2), | ||
365 | regulator_desc_ldo1(3), | ||
366 | regulator_desc_ldo1(4), | ||
367 | regulator_desc_ldo1(5), | ||
368 | regulator_desc_ldo2(6), | ||
369 | regulator_desc_ldo1(7), | ||
370 | regulator_desc_ldo1(8), | ||
371 | regulator_desc_ldo1(9), | ||
372 | regulator_desc_ldo1(10), | ||
373 | regulator_desc_ldo2(11), | ||
374 | regulator_desc_ldo1(12), | ||
375 | regulator_desc_ldo1(13), | ||
376 | regulator_desc_ldo1(14), | ||
377 | regulator_desc_ldo1(15), | ||
378 | regulator_desc_ldo1(16), | ||
379 | regulator_desc_ldo1(17), | ||
380 | regulator_desc_ldo1(18), | ||
381 | regulator_desc_ldo1(19), | ||
382 | regulator_desc_ldo1(20), | ||
383 | regulator_desc_ldo1(21), | ||
384 | regulator_desc_ldo2(22), | ||
385 | regulator_desc_ldo2(23), | ||
386 | regulator_desc_ldo1(24), | ||
387 | regulator_desc_ldo1(25), | ||
388 | regulator_desc_ldo1(26), | ||
389 | regulator_desc_buck1_4(1), | ||
390 | regulator_desc_buck1_4(2), | ||
391 | regulator_desc_buck1_4(3), | ||
392 | regulator_desc_buck1_4(4), | ||
393 | regulator_desc_buck5, | ||
394 | regulator_desc_buck6_7(6), | ||
395 | regulator_desc_buck6_7(7), | ||
396 | regulator_desc_buck8, | ||
397 | regulator_desc_buck9, | ||
398 | regulator_desc_buck10, | ||
399 | }; | ||
400 | |||
401 | static int s2mpa01_pmic_probe(struct platform_device *pdev) | ||
402 | { | ||
403 | struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); | ||
404 | struct sec_platform_data *pdata = dev_get_platdata(iodev->dev); | ||
405 | struct of_regulator_match rdata[S2MPA01_REGULATOR_MAX]; | ||
406 | struct device_node *reg_np = NULL; | ||
407 | struct regulator_config config = { }; | ||
408 | struct s2mpa01_info *s2mpa01; | ||
409 | int i; | ||
410 | |||
411 | s2mpa01 = devm_kzalloc(&pdev->dev, sizeof(*s2mpa01), GFP_KERNEL); | ||
412 | if (!s2mpa01) | ||
413 | return -ENOMEM; | ||
414 | |||
415 | for (i = 0; i < S2MPA01_REGULATOR_CNT; i++) | ||
416 | rdata[i].name = regulators[i].name; | ||
417 | |||
418 | if (iodev->dev->of_node) { | ||
419 | reg_np = of_get_child_by_name(iodev->dev->of_node, | ||
420 | "regulators"); | ||
421 | if (!reg_np) { | ||
422 | dev_err(&pdev->dev, | ||
423 | "could not find regulators sub-node\n"); | ||
424 | return -EINVAL; | ||
425 | } | ||
426 | |||
427 | of_regulator_match(&pdev->dev, reg_np, rdata, | ||
428 | S2MPA01_REGULATOR_MAX); | ||
429 | of_node_put(reg_np); | ||
430 | } | ||
431 | |||
432 | platform_set_drvdata(pdev, s2mpa01); | ||
433 | |||
434 | config.dev = &pdev->dev; | ||
435 | config.regmap = iodev->regmap_pmic; | ||
436 | config.driver_data = s2mpa01; | ||
437 | |||
438 | for (i = 0; i < S2MPA01_REGULATOR_MAX; i++) { | ||
439 | struct regulator_dev *rdev; | ||
440 | if (pdata) | ||
441 | config.init_data = pdata->regulators[i].initdata; | ||
442 | else | ||
443 | config.init_data = rdata[i].init_data; | ||
444 | |||
445 | if (reg_np) | ||
446 | config.of_node = rdata[i].of_node; | ||
447 | |||
448 | rdev = devm_regulator_register(&pdev->dev, | ||
449 | ®ulators[i], &config); | ||
450 | if (IS_ERR(rdev)) { | ||
451 | dev_err(&pdev->dev, "regulator init failed for %d\n", | ||
452 | i); | ||
453 | return PTR_ERR(rdev); | ||
454 | } | ||
455 | } | ||
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static const struct platform_device_id s2mpa01_pmic_id[] = { | ||
461 | { "s2mpa01-pmic", 0}, | ||
462 | { }, | ||
463 | }; | ||
464 | MODULE_DEVICE_TABLE(platform, s2mpa01_pmic_id); | ||
465 | |||
466 | static struct platform_driver s2mpa01_pmic_driver = { | ||
467 | .driver = { | ||
468 | .name = "s2mpa01-pmic", | ||
469 | .owner = THIS_MODULE, | ||
470 | }, | ||
471 | .probe = s2mpa01_pmic_probe, | ||
472 | .id_table = s2mpa01_pmic_id, | ||
473 | }; | ||
474 | |||
475 | module_platform_driver(s2mpa01_pmic_driver); | ||
476 | |||
477 | /* Module information */ | ||
478 | MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>"); | ||
479 | MODULE_AUTHOR("Sachin Kamat <sachin.kamat@samsung.com>"); | ||
480 | MODULE_DESCRIPTION("SAMSUNG S2MPA01 Regulator Driver"); | ||
481 | MODULE_LICENSE("GPL"); | ||