regulator: Remove unused i2c variable in s5m8767_pmic_probe
[linux-2.6.git] / drivers / regulator / s5m8767.c
1 /*
2  * s5m8767.c
3  *
4  * Copyright (c) 2011 Samsung Electronics Co., Ltd
5  *              http://www.samsung.com
6  *
7  *  This program is free software; you can redistribute  it and/or modify it
8  *  under  the terms of  the GNU General  Public License as published by the
9  *  Free Software Foundation;  either version 2 of the  License, or (at your
10  *  option) any later version.
11  *
12  */
13
14 #include <linux/bug.h>
15 #include <linux/delay.h>
16 #include <linux/err.h>
17 #include <linux/gpio.h>
18 #include <linux/slab.h>
19 #include <linux/module.h>
20 #include <linux/platform_device.h>
21 #include <linux/regulator/driver.h>
22 #include <linux/regulator/machine.h>
23 #include <linux/mfd/s5m87xx/s5m-core.h>
24 #include <linux/mfd/s5m87xx/s5m-pmic.h>
25
26 struct s5m8767_info {
27         struct device *dev;
28         struct s5m87xx_dev *iodev;
29         int num_regulators;
30         struct regulator_dev **rdev;
31
32         int ramp_delay;
33         bool buck2_ramp;
34         bool buck3_ramp;
35         bool buck4_ramp;
36
37         bool buck2_gpiodvs;
38         bool buck3_gpiodvs;
39         bool buck4_gpiodvs;
40         u8 buck2_vol[8];
41         u8 buck3_vol[8];
42         u8 buck4_vol[8];
43         int buck_gpios[3];
44         int buck_gpioindex;
45 };
46
47 struct s5m_voltage_desc {
48         int max;
49         int min;
50         int step;
51 };
52
53 static const struct s5m_voltage_desc buck_voltage_val1 = {
54         .max = 2225000,
55         .min =  650000,
56         .step =   6250,
57 };
58
59 static const struct s5m_voltage_desc buck_voltage_val2 = {
60         .max = 1600000,
61         .min =  600000,
62         .step =   6250,
63 };
64
65 static const struct s5m_voltage_desc buck_voltage_val3 = {
66         .max = 3000000,
67         .min =  750000,
68         .step =  12500,
69 };
70
71 static const struct s5m_voltage_desc ldo_voltage_val1 = {
72         .max = 3950000,
73         .min =  800000,
74         .step =  50000,
75 };
76
77 static const struct s5m_voltage_desc ldo_voltage_val2 = {
78         .max = 2375000,
79         .min =  800000,
80         .step =  25000,
81 };
82
83 static const struct s5m_voltage_desc *reg_voltage_map[] = {
84         [S5M8767_LDO1] = &ldo_voltage_val2,
85         [S5M8767_LDO2] = &ldo_voltage_val2,
86         [S5M8767_LDO3] = &ldo_voltage_val1,
87         [S5M8767_LDO4] = &ldo_voltage_val1,
88         [S5M8767_LDO5] = &ldo_voltage_val1,
89         [S5M8767_LDO6] = &ldo_voltage_val2,
90         [S5M8767_LDO7] = &ldo_voltage_val2,
91         [S5M8767_LDO8] = &ldo_voltage_val2,
92         [S5M8767_LDO9] = &ldo_voltage_val1,
93         [S5M8767_LDO10] = &ldo_voltage_val1,
94         [S5M8767_LDO11] = &ldo_voltage_val1,
95         [S5M8767_LDO12] = &ldo_voltage_val1,
96         [S5M8767_LDO13] = &ldo_voltage_val1,
97         [S5M8767_LDO14] = &ldo_voltage_val1,
98         [S5M8767_LDO15] = &ldo_voltage_val2,
99         [S5M8767_LDO16] = &ldo_voltage_val1,
100         [S5M8767_LDO17] = &ldo_voltage_val1,
101         [S5M8767_LDO18] = &ldo_voltage_val1,
102         [S5M8767_LDO19] = &ldo_voltage_val1,
103         [S5M8767_LDO20] = &ldo_voltage_val1,
104         [S5M8767_LDO21] = &ldo_voltage_val1,
105         [S5M8767_LDO22] = &ldo_voltage_val1,
106         [S5M8767_LDO23] = &ldo_voltage_val1,
107         [S5M8767_LDO24] = &ldo_voltage_val1,
108         [S5M8767_LDO25] = &ldo_voltage_val1,
109         [S5M8767_LDO26] = &ldo_voltage_val1,
110         [S5M8767_LDO27] = &ldo_voltage_val1,
111         [S5M8767_LDO28] = &ldo_voltage_val1,
112         [S5M8767_BUCK1] = &buck_voltage_val1,
113         [S5M8767_BUCK2] = &buck_voltage_val2,
114         [S5M8767_BUCK3] = &buck_voltage_val2,
115         [S5M8767_BUCK4] = &buck_voltage_val2,
116         [S5M8767_BUCK5] = &buck_voltage_val1,
117         [S5M8767_BUCK6] = &buck_voltage_val1,
118         [S5M8767_BUCK7] = NULL,
119         [S5M8767_BUCK8] = NULL,
120         [S5M8767_BUCK9] = &buck_voltage_val3,
121 };
122
123 static int s5m8767_list_voltage(struct regulator_dev *rdev,
124                                 unsigned int selector)
125 {
126         const struct s5m_voltage_desc *desc;
127         int reg_id = rdev_get_id(rdev);
128         int val;
129
130         if (reg_id >= ARRAY_SIZE(reg_voltage_map) || reg_id < 0)
131                 return -EINVAL;
132
133         desc = reg_voltage_map[reg_id];
134         if (desc == NULL)
135                 return -EINVAL;
136
137         val = desc->min + desc->step * selector;
138         if (val > desc->max)
139                 return -EINVAL;
140
141         return val;
142 }
143
144 static int s5m8767_get_register(struct regulator_dev *rdev, int *reg)
145 {
146         int reg_id = rdev_get_id(rdev);
147
148         switch (reg_id) {
149         case S5M8767_LDO1 ... S5M8767_LDO2:
150                 *reg = S5M8767_REG_LDO1CTRL + (reg_id - S5M8767_LDO1);
151                 break;
152         case S5M8767_LDO3 ... S5M8767_LDO28:
153                 *reg = S5M8767_REG_LDO3CTRL + (reg_id - S5M8767_LDO3);
154                 break;
155         case S5M8767_BUCK1:
156                 *reg = S5M8767_REG_BUCK1CTRL1;
157                 break;
158         case S5M8767_BUCK2 ... S5M8767_BUCK4:
159                 *reg = S5M8767_REG_BUCK2CTRL + (reg_id - S5M8767_BUCK2) * 9;
160                 break;
161         case S5M8767_BUCK5:
162                 *reg = S5M8767_REG_BUCK5CTRL1;
163                 break;
164         case S5M8767_BUCK6 ... S5M8767_BUCK9:
165                 *reg = S5M8767_REG_BUCK6CTRL1 + (reg_id - S5M8767_BUCK6) * 2;
166                 break;
167         default:
168                 return -EINVAL;
169         }
170
171         return 0;
172 }
173
174 static int s5m8767_reg_is_enabled(struct regulator_dev *rdev)
175 {
176         struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
177         int ret, reg;
178         int mask = 0xc0, pattern = 0xc0;
179         u8 val;
180
181         ret = s5m8767_get_register(rdev, &reg);
182         if (ret == -EINVAL)
183                 return 1;
184         else if (ret)
185                 return ret;
186
187         ret = s5m_reg_read(s5m8767->iodev, reg, &val);
188         if (ret)
189                 return ret;
190
191         return (val & mask) == pattern;
192 }
193
194 static int s5m8767_reg_enable(struct regulator_dev *rdev)
195 {
196         struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
197         int ret, reg;
198         int mask = 0xc0, pattern = 0xc0;
199
200         ret = s5m8767_get_register(rdev, &reg);
201         if (ret)
202                 return ret;
203
204         return s5m_reg_update(s5m8767->iodev, reg, pattern, mask);
205 }
206
207 static int s5m8767_reg_disable(struct regulator_dev *rdev)
208 {
209         struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
210         int ret, reg;
211         int  mask = 0xc0, pattern = 0xc0;
212
213         ret = s5m8767_get_register(rdev, &reg);
214         if (ret)
215                 return ret;
216
217         return s5m_reg_update(s5m8767->iodev, reg, ~pattern, mask);
218 }
219
220 static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg)
221 {
222         int reg_id = rdev_get_id(rdev);
223         int reg;
224
225         switch (reg_id) {
226         case S5M8767_LDO1 ... S5M8767_LDO2:
227                 reg = S5M8767_REG_LDO1CTRL + (reg_id - S5M8767_LDO1);
228                 break;
229         case S5M8767_LDO3 ... S5M8767_LDO28:
230                 reg = S5M8767_REG_LDO3CTRL + (reg_id - S5M8767_LDO3);
231                 break;
232         case S5M8767_BUCK1:
233                 reg = S5M8767_REG_BUCK1CTRL2;
234                 break;
235         case S5M8767_BUCK2:
236                 reg = S5M8767_REG_BUCK2DVS1;
237                 break;
238         case S5M8767_BUCK3:
239                 reg = S5M8767_REG_BUCK3DVS1;
240                 break;
241         case S5M8767_BUCK4:
242                 reg = S5M8767_REG_BUCK4DVS1;
243                 break;
244         case S5M8767_BUCK5:
245                 reg = S5M8767_REG_BUCK5CTRL2;
246                 break;
247         case S5M8767_BUCK6 ... S5M8767_BUCK9:
248                 reg = S5M8767_REG_BUCK6CTRL2 + (reg_id - S5M8767_BUCK6) * 2;
249                 break;
250         default:
251                 return -EINVAL;
252         }
253
254         *_reg = reg;
255
256         return 0;
257 }
258
259 static int s5m8767_get_voltage_sel(struct regulator_dev *rdev)
260 {
261         struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
262         int reg, mask = 0xff, ret;
263         int reg_id = rdev_get_id(rdev);
264         u8 val;
265
266         ret = s5m8767_get_voltage_register(rdev, &reg);
267         if (ret)
268                 return ret;
269
270         switch (reg_id) {
271         case S5M8767_LDO1 ... S5M8767_LDO28:
272                 mask = 0x3f;
273                 break;
274         case S5M8767_BUCK2:
275                 if (s5m8767->buck2_gpiodvs)
276                         reg += s5m8767->buck_gpioindex;
277                 break;
278         case S5M8767_BUCK3:
279                 if (s5m8767->buck3_gpiodvs)
280                         reg += s5m8767->buck_gpioindex;
281                 break;
282         case S5M8767_BUCK4:
283                 if (s5m8767->buck4_gpiodvs)
284                         reg += s5m8767->buck_gpioindex;
285                 break;
286         }
287
288         ret = s5m_reg_read(s5m8767->iodev, reg, &val);
289         if (ret)
290                 return ret;
291
292         val &= mask;
293
294         return val;
295 }
296
297 static inline int s5m8767_convert_voltage(
298                 const struct s5m_voltage_desc *desc,
299                 int min_vol, int max_vol)
300 {
301         int out_vol = 0;
302
303         if (desc == NULL)
304                 return -EINVAL;
305
306         if (max_vol < desc->min || min_vol > desc->max)
307                 return -EINVAL;
308
309         out_vol = (min_vol - desc->min) / desc->step;
310
311         if (desc->min + desc->step * out_vol > max_vol)
312                 return -EINVAL;
313
314         return out_vol;
315 }
316
317 static int s5m8767_set_voltage(struct regulator_dev *rdev,
318                                 int min_uV, int max_uV, unsigned *selector)
319 {
320         struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
321         int min_vol = min_uV, max_vol = max_uV;
322         const struct s5m_voltage_desc *desc;
323         int reg_id = rdev_get_id(rdev);
324         int reg, mask, ret;
325         int i;
326         u8 val;
327
328         switch (reg_id) {
329         case S5M8767_LDO1 ... S5M8767_LDO28:
330                 mask = 0x3f;
331                 break;
332         case S5M8767_BUCK1 ... S5M8767_BUCK6:
333                 mask = 0xff;
334                 break;
335         case S5M8767_BUCK7 ... S5M8767_BUCK8:
336                 return -EINVAL;
337         case S5M8767_BUCK9:
338                 mask = 0xff;
339                 break;
340         default:
341                 return -EINVAL;
342         }
343
344         desc = reg_voltage_map[reg_id];
345
346         i = s5m8767_convert_voltage(desc, min_vol, max_vol);
347         if (i < 0)
348                 return i;
349
350         ret = s5m8767_get_voltage_register(rdev, &reg);
351         if (ret)
352                 return ret;
353
354         s5m_reg_read(s5m8767->iodev, reg, &val);
355         val = val & mask;
356
357         ret = s5m_reg_write(s5m8767->iodev, reg, val);
358         *selector = i;
359
360         return ret;
361 }
362
363 static inline void s5m8767_set_high(struct s5m8767_info *s5m8767)
364 {
365         int temp_index = s5m8767->buck_gpioindex;
366
367         gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
368         gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
369         gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
370 }
371
372 static inline void s5m8767_set_low(struct s5m8767_info *s5m8767)
373 {
374         int temp_index = s5m8767->buck_gpioindex;
375
376         gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
377         gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
378         gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
379 }
380
381 static int s5m8767_set_voltage_buck(struct regulator_dev *rdev,
382                                     int min_uV, int max_uV, unsigned *selector)
383 {
384         struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
385         int reg_id = rdev_get_id(rdev);
386         const struct s5m_voltage_desc *desc;
387         int new_val, old_val, i = 0;
388         int min_vol = min_uV, max_vol = max_uV;
389
390         if (reg_id < S5M8767_BUCK1 || reg_id > S5M8767_BUCK6)
391                 return -EINVAL;
392
393         switch (reg_id) {
394         case S5M8767_BUCK1:
395                 return s5m8767_set_voltage(rdev, min_uV, max_uV, selector);
396         case S5M8767_BUCK2 ... S5M8767_BUCK4:
397                 break;
398         case S5M8767_BUCK5 ... S5M8767_BUCK6:
399                 return s5m8767_set_voltage(rdev, min_uV, max_uV, selector);
400         case S5M8767_BUCK9:
401                 return s5m8767_set_voltage(rdev, min_uV, max_uV, selector);
402         }
403
404         desc = reg_voltage_map[reg_id];
405         new_val = s5m8767_convert_voltage(desc, min_vol, max_vol);
406         if (new_val < 0)
407                 return new_val;
408
409         switch (reg_id) {
410         case S5M8767_BUCK2:
411                 if (s5m8767->buck2_gpiodvs) {
412                         while (s5m8767->buck2_vol[i] != new_val)
413                                 i++;
414                 } else
415                         return s5m8767_set_voltage(rdev, min_uV,
416                                                    max_uV, selector);
417                 break;
418         case S5M8767_BUCK3:
419                 if (s5m8767->buck3_gpiodvs) {
420                         while (s5m8767->buck3_vol[i] != new_val)
421                                 i++;
422                 } else
423                         return s5m8767_set_voltage(rdev, min_uV,
424                                                    max_uV, selector);
425                 break;
426         case S5M8767_BUCK4:
427                 if (s5m8767->buck3_gpiodvs) {
428                         while (s5m8767->buck4_vol[i] != new_val)
429                                 i++;
430                 } else
431                         return s5m8767_set_voltage(rdev, min_uV,
432                                                    max_uV, selector);
433                 break;
434         }
435
436         old_val = s5m8767->buck_gpioindex;
437         s5m8767->buck_gpioindex = i;
438
439         if (i > old_val)
440                 s5m8767_set_high(s5m8767);
441         else
442                 s5m8767_set_low(s5m8767);
443
444         *selector = new_val;
445         return 0;
446 }
447
448 static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,
449                                              unsigned int old_sel,
450                                              unsigned int new_sel)
451 {
452         struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
453         const struct s5m_voltage_desc *desc;
454         int reg_id = rdev_get_id(rdev);
455
456         desc = reg_voltage_map[reg_id];
457
458         if (old_sel < new_sel)
459                 return DIV_ROUND_UP(desc->step * (new_sel - old_sel),
460                                         s5m8767->ramp_delay);
461         return 0;
462 }
463
464 static struct regulator_ops s5m8767_ldo_ops = {
465         .list_voltage           = s5m8767_list_voltage,
466         .is_enabled             = s5m8767_reg_is_enabled,
467         .enable                 = s5m8767_reg_enable,
468         .disable                = s5m8767_reg_disable,
469         .get_voltage_sel        = s5m8767_get_voltage_sel,
470         .set_voltage            = s5m8767_set_voltage,
471         .set_voltage_time_sel   = s5m8767_set_voltage_time_sel,
472 };
473
474 static struct regulator_ops s5m8767_buck_ops = {
475         .list_voltage           = s5m8767_list_voltage,
476         .is_enabled             = s5m8767_reg_is_enabled,
477         .enable                 = s5m8767_reg_enable,
478         .disable                = s5m8767_reg_disable,
479         .get_voltage_sel        = s5m8767_get_voltage_sel,
480         .set_voltage            = s5m8767_set_voltage_buck,
481         .set_voltage_time_sel   = s5m8767_set_voltage_time_sel,
482 };
483
484 #define regulator_desc_ldo(num)         {       \
485         .name           = "LDO"#num,            \
486         .id             = S5M8767_LDO##num,     \
487         .ops            = &s5m8767_ldo_ops,     \
488         .type           = REGULATOR_VOLTAGE,    \
489         .owner          = THIS_MODULE,          \
490 }
491 #define regulator_desc_buck(num)        {       \
492         .name           = "BUCK"#num,           \
493         .id             = S5M8767_BUCK##num,    \
494         .ops            = &s5m8767_buck_ops,    \
495         .type           = REGULATOR_VOLTAGE,    \
496         .owner          = THIS_MODULE,          \
497 }
498
499 static struct regulator_desc regulators[] = {
500         regulator_desc_ldo(1),
501         regulator_desc_ldo(2),
502         regulator_desc_ldo(3),
503         regulator_desc_ldo(4),
504         regulator_desc_ldo(5),
505         regulator_desc_ldo(6),
506         regulator_desc_ldo(7),
507         regulator_desc_ldo(8),
508         regulator_desc_ldo(9),
509         regulator_desc_ldo(10),
510         regulator_desc_ldo(11),
511         regulator_desc_ldo(12),
512         regulator_desc_ldo(13),
513         regulator_desc_ldo(14),
514         regulator_desc_ldo(15),
515         regulator_desc_ldo(16),
516         regulator_desc_ldo(17),
517         regulator_desc_ldo(18),
518         regulator_desc_ldo(19),
519         regulator_desc_ldo(20),
520         regulator_desc_ldo(21),
521         regulator_desc_ldo(22),
522         regulator_desc_ldo(23),
523         regulator_desc_ldo(24),
524         regulator_desc_ldo(25),
525         regulator_desc_ldo(26),
526         regulator_desc_ldo(27),
527         regulator_desc_ldo(28),
528         regulator_desc_buck(1),
529         regulator_desc_buck(2),
530         regulator_desc_buck(3),
531         regulator_desc_buck(4),
532         regulator_desc_buck(5),
533         regulator_desc_buck(6),
534         regulator_desc_buck(7),
535         regulator_desc_buck(8),
536         regulator_desc_buck(9),
537 };
538
539 static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
540 {
541         struct s5m87xx_dev *iodev = dev_get_drvdata(pdev->dev.parent);
542         struct s5m_platform_data *pdata = dev_get_platdata(iodev->dev);
543         struct regulator_dev **rdev;
544         struct s5m8767_info *s5m8767;
545         int i, ret, size;
546
547         if (!pdata) {
548                 dev_err(pdev->dev.parent, "Platform data not supplied\n");
549                 return -ENODEV;
550         }
551
552         s5m8767 = devm_kzalloc(&pdev->dev, sizeof(struct s5m8767_info),
553                                 GFP_KERNEL);
554         if (!s5m8767)
555                 return -ENOMEM;
556
557         size = sizeof(struct regulator_dev *) * (S5M8767_REG_MAX - 2);
558         s5m8767->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
559         if (!s5m8767->rdev)
560                 return -ENOMEM;
561
562         rdev = s5m8767->rdev;
563         s5m8767->dev = &pdev->dev;
564         s5m8767->iodev = iodev;
565         s5m8767->num_regulators = S5M8767_REG_MAX - 2;
566         platform_set_drvdata(pdev, s5m8767);
567
568         s5m8767->buck_gpioindex = pdata->buck_default_idx;
569         s5m8767->buck2_gpiodvs = pdata->buck2_gpiodvs;
570         s5m8767->buck3_gpiodvs = pdata->buck3_gpiodvs;
571         s5m8767->buck4_gpiodvs = pdata->buck4_gpiodvs;
572         s5m8767->buck_gpios[0] = pdata->buck_gpios[0];
573         s5m8767->buck_gpios[1] = pdata->buck_gpios[1];
574         s5m8767->buck_gpios[2] = pdata->buck_gpios[2];
575         s5m8767->ramp_delay = pdata->buck_ramp_delay;
576         s5m8767->buck2_ramp = pdata->buck2_ramp_enable;
577         s5m8767->buck3_ramp = pdata->buck3_ramp_enable;
578         s5m8767->buck4_ramp = pdata->buck4_ramp_enable;
579
580         for (i = 0; i < 8; i++) {
581                 if (s5m8767->buck2_gpiodvs) {
582                         s5m8767->buck2_vol[i] =
583                                 s5m8767_convert_voltage(
584                                                 &buck_voltage_val2,
585                                                 pdata->buck2_voltage[i],
586                                                 pdata->buck2_voltage[i] +
587                                                 buck_voltage_val2.step);
588                 }
589
590                 if (s5m8767->buck3_gpiodvs) {
591                         s5m8767->buck3_vol[i] =
592                                 s5m8767_convert_voltage(
593                                                 &buck_voltage_val2,
594                                                 pdata->buck3_voltage[i],
595                                                 pdata->buck3_voltage[i] +
596                                                 buck_voltage_val2.step);
597                 }
598
599                 if (s5m8767->buck4_gpiodvs) {
600                         s5m8767->buck4_vol[i] =
601                                 s5m8767_convert_voltage(
602                                                 &buck_voltage_val2,
603                                                 pdata->buck4_voltage[i],
604                                                 pdata->buck4_voltage[i] +
605                                                 buck_voltage_val2.step);
606                 }
607         }
608
609         if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
610                 pdata->buck4_gpiodvs) {
611                 if (gpio_is_valid(pdata->buck_gpios[0]) &&
612                         gpio_is_valid(pdata->buck_gpios[1]) &&
613                         gpio_is_valid(pdata->buck_gpios[2])) {
614                         ret = gpio_request(pdata->buck_gpios[0],
615                                                 "S5M8767 SET1");
616                         if (ret == -EBUSY)
617                                 dev_warn(&pdev->dev, "Duplicated gpio request for SET1\n");
618
619                         ret = gpio_request(pdata->buck_gpios[1],
620                                            "S5M8767 SET2");
621                         if (ret == -EBUSY)
622                                 dev_warn(&pdev->dev, "Duplicated gpio request for SET2\n");
623
624                         ret = gpio_request(pdata->buck_gpios[2],
625                                            "S5M8767 SET3");
626                         if (ret == -EBUSY)
627                                 dev_warn(&pdev->dev, "Duplicated gpio request for SET3\n");
628                         /* SET1 GPIO */
629                         gpio_direction_output(pdata->buck_gpios[0],
630                                         (s5m8767->buck_gpioindex >> 2) & 0x1);
631                         /* SET2 GPIO */
632                         gpio_direction_output(pdata->buck_gpios[1],
633                                         (s5m8767->buck_gpioindex >> 1) & 0x1);
634                         /* SET3 GPIO */
635                         gpio_direction_output(pdata->buck_gpios[2],
636                                         (s5m8767->buck_gpioindex >> 0) & 0x1);
637                         ret = 0;
638                 } else {
639                         dev_err(&pdev->dev, "GPIO NOT VALID\n");
640                         ret = -EINVAL;
641                         return ret;
642                 }
643         }
644
645         if (pdata->buck2_gpiodvs) {
646                 if (pdata->buck3_gpiodvs || pdata->buck4_gpiodvs) {
647                         dev_err(&pdev->dev, "S5M8767 GPIO DVS NOT VALID\n");
648                         ret = -EINVAL;
649                         return ret;
650                 }
651         }
652
653         if (pdata->buck3_gpiodvs) {
654                 if (pdata->buck2_gpiodvs || pdata->buck4_gpiodvs) {
655                         dev_err(&pdev->dev, "S5M8767 GPIO DVS NOT VALID\n");
656                         ret = -EINVAL;
657                         return ret;
658                 }
659         }
660
661         if (pdata->buck4_gpiodvs) {
662                 if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs) {
663                         dev_err(&pdev->dev, "S5M8767 GPIO DVS NOT VALID\n");
664                         ret = -EINVAL;
665                         return ret;
666                 }
667         }
668
669         s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL,
670                         (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
671         s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL,
672                         (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
673         s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL,
674                         (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
675
676         /* Initialize GPIO DVS registers */
677         for (i = 0; i < 8; i++) {
678                 if (s5m8767->buck2_gpiodvs) {
679                         s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK2DVS1 + i,
680                                            s5m8767->buck2_vol[i]);
681                 }
682
683                 if (s5m8767->buck3_gpiodvs) {
684                         s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK3DVS1 + i,
685                                            s5m8767->buck3_vol[i]);
686                 }
687
688                 if (s5m8767->buck4_gpiodvs) {
689                         s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK4DVS1 + i,
690                                            s5m8767->buck4_vol[i]);
691                 }
692         }
693         s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL, 0x78, 0xff);
694         s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL, 0x58, 0xff);
695         s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL, 0x78, 0xff);
696
697         if (s5m8767->buck2_ramp)
698                 s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x08, 0x08);
699
700         if (s5m8767->buck3_ramp)
701                 s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x04, 0x04);
702
703         if (s5m8767->buck4_ramp)
704                 s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x02, 0x02);
705
706         if (s5m8767->buck2_ramp || s5m8767->buck3_ramp
707                 || s5m8767->buck4_ramp) {
708                 switch (s5m8767->ramp_delay) {
709                 case 15:
710                         s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
711                                         0xc0, 0xf0);
712                         break;
713                 case 25:
714                         s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
715                                         0xd0, 0xf0);
716                         break;
717                 case 50:
718                         s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
719                                         0xe0, 0xf0);
720                         break;
721                 case 100:
722                         s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
723                                         0xf0, 0xf0);
724                         break;
725                 default:
726                         s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
727                                         0x90, 0xf0);
728                 }
729         }
730
731         for (i = 0; i < pdata->num_regulators; i++) {
732                 const struct s5m_voltage_desc *desc;
733                 int id = pdata->regulators[i].id;
734
735                 desc = reg_voltage_map[id];
736                 if (desc)
737                         regulators[id].n_voltages =
738                                 (desc->max - desc->min) / desc->step + 1;
739
740                 rdev[i] = regulator_register(&regulators[id], s5m8767->dev,
741                                 pdata->regulators[i].initdata, s5m8767, NULL);
742                 if (IS_ERR(rdev[i])) {
743                         ret = PTR_ERR(rdev[i]);
744                         dev_err(s5m8767->dev, "regulator init failed for %d\n",
745                                         id);
746                         rdev[i] = NULL;
747                         goto err;
748                 }
749         }
750
751         return 0;
752 err:
753         for (i = 0; i < s5m8767->num_regulators; i++)
754                 if (rdev[i])
755                         regulator_unregister(rdev[i]);
756
757         return ret;
758 }
759
760 static int __devexit s5m8767_pmic_remove(struct platform_device *pdev)
761 {
762         struct s5m8767_info *s5m8767 = platform_get_drvdata(pdev);
763         struct regulator_dev **rdev = s5m8767->rdev;
764         int i;
765
766         for (i = 0; i < s5m8767->num_regulators; i++)
767                 if (rdev[i])
768                         regulator_unregister(rdev[i]);
769
770         return 0;
771 }
772
773 static const struct platform_device_id s5m8767_pmic_id[] = {
774         { "s5m8767-pmic", 0},
775         { },
776 };
777 MODULE_DEVICE_TABLE(platform, s5m8767_pmic_id);
778
779 static struct platform_driver s5m8767_pmic_driver = {
780         .driver = {
781                 .name = "s5m8767-pmic",
782                 .owner = THIS_MODULE,
783         },
784         .probe = s5m8767_pmic_probe,
785         .remove = __devexit_p(s5m8767_pmic_remove),
786         .id_table = s5m8767_pmic_id,
787 };
788
789 static int __init s5m8767_pmic_init(void)
790 {
791         return platform_driver_register(&s5m8767_pmic_driver);
792 }
793 subsys_initcall(s5m8767_pmic_init);
794
795 static void __exit s5m8767_pmic_exit(void)
796 {
797         platform_driver_unregister(&s5m8767_pmic_driver);
798 }
799 module_exit(s5m8767_pmic_exit);
800
801 /* Module information */
802 MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
803 MODULE_DESCRIPTION("SAMSUNG S5M8767 Regulator Driver");
804 MODULE_LICENSE("GPL");