blob: 5dcdb0f3db7e908821745dff7ebcf3d8ca353f9d [file] [log] [blame]
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -04001/*
2 * Regulators driver for Marvell 88PM8607
3 *
4 * Copyright (C) 2009 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/err.h>
Haojian Zhuang53dbab72010-01-08 06:01:24 -050014#include <linux/i2c.h>
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -040015#include <linux/platform_device.h>
16#include <linux/regulator/driver.h>
17#include <linux/regulator/machine.h>
Haojian Zhuang53dbab72010-01-08 06:01:24 -050018#include <linux/mfd/88pm860x.h>
Paul Gortmaker65602c32011-07-17 16:28:23 -040019#include <linux/module.h>
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -040020
21struct pm8607_regulator_info {
22 struct regulator_desc desc;
Haojian Zhuang53dbab72010-01-08 06:01:24 -050023 struct pm860x_chip *chip;
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -040024 struct regulator_dev *regulator;
Haojian Zhuang53dbab72010-01-08 06:01:24 -050025 struct i2c_client *i2c;
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -040026
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -040027 unsigned int *vol_table;
28 unsigned int *vol_suspend;
29
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -040030 int vol_reg;
31 int vol_shift;
32 int vol_nbits;
33 int update_reg;
34 int update_bit;
35 int enable_reg;
36 int enable_bit;
37 int slope_double;
38};
39
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -040040static const unsigned int BUCK1_table[] = {
41 725000, 750000, 775000, 800000, 825000, 850000, 875000, 900000,
42 925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000,
43 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
44 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
45 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000,
46 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000,
47 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000,
48 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000,
49};
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -040050
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -040051static const unsigned int BUCK1_suspend_table[] = {
52 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000,
53 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000,
54 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000,
55 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000,
56 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000,
57 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
58 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000,
59 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000,
60};
61
62static const unsigned int BUCK2_table[] = {
63 0, 50000, 100000, 150000, 200000, 250000, 300000, 350000,
64 400000, 450000, 500000, 550000, 600000, 650000, 700000, 750000,
65 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000,
66 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000,
67 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000,
68 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000,
69 2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000,
70 2800000, 2850000, 2900000, 2950000, 3000000, 3000000, 3000000, 3000000,
71};
72
73static const unsigned int BUCK2_suspend_table[] = {
74 0, 50000, 100000, 150000, 200000, 250000, 300000, 350000,
75 400000, 450000, 500000, 550000, 600000, 650000, 700000, 750000,
76 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000,
77 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000,
78 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000,
79 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000,
80 2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000,
81 2800000, 2850000, 2900000, 2950000, 3000000, 3000000, 3000000, 3000000,
82};
83
84static const unsigned int BUCK3_table[] = {
85 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000,
86 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000,
87 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000,
88 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000,
89 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000,
90 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
91 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000,
92 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000,
93};
94
95static const unsigned int BUCK3_suspend_table[] = {
96 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000,
97 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000,
98 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000,
99 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000,
100 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000,
101 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
102 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000,
103 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000,
104};
105
106static const unsigned int LDO1_table[] = {
107 1800000, 1200000, 2800000, 0,
108};
109
110static const unsigned int LDO1_suspend_table[] = {
111 1800000, 1200000, 0, 0,
112};
113
114static const unsigned int LDO2_table[] = {
115 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
116};
117
118static const unsigned int LDO2_suspend_table[] = {
119 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
120};
121
122static const unsigned int LDO3_table[] = {
123 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
124};
125
126static const unsigned int LDO3_suspend_table[] = {
127 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
128};
129
130static const unsigned int LDO4_table[] = {
131 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2900000, 3300000,
132};
133
134static const unsigned int LDO4_suspend_table[] = {
135 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2900000, 2900000,
136};
137
138static const unsigned int LDO5_table[] = {
139 2900000, 3000000, 3100000, 3300000,
140};
141
142static const unsigned int LDO5_suspend_table[] = {
143 2900000, 0, 0, 0,
144};
145
146static const unsigned int LDO6_table[] = {
147 1800000, 1850000, 2600000, 2650000, 2700000, 2750000, 2800000, 3300000,
148};
149
150static const unsigned int LDO6_suspend_table[] = {
151 1800000, 1850000, 2600000, 2650000, 2700000, 2750000, 2800000, 2900000,
152};
153
154static const unsigned int LDO7_table[] = {
155 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
156};
157
158static const unsigned int LDO7_suspend_table[] = {
159 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
160};
161
162static const unsigned int LDO8_table[] = {
163 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
164};
165
166static const unsigned int LDO8_suspend_table[] = {
167 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
168};
169
170static const unsigned int LDO9_table[] = {
171 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
172};
173
174static const unsigned int LDO9_suspend_table[] = {
175 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
176};
177
178static const unsigned int LDO10_table[] = {
179 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
180 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
181};
182
183static const unsigned int LDO10_suspend_table[] = {
184 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
185 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
186};
187
188static const unsigned int LDO12_table[] = {
189 1800000, 1900000, 2700000, 2800000, 2900000, 3000000, 3100000, 3300000,
190 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
191};
192
193static const unsigned int LDO12_suspend_table[] = {
194 1800000, 1900000, 2700000, 2800000, 2900000, 2900000, 2900000, 2900000,
195 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
196};
197
198static const unsigned int LDO13_table[] = {
199 1300000, 1800000, 2000000, 2500000, 2800000, 3000000, 0, 0,
200};
201
202static const unsigned int LDO13_suspend_table[] = {
203 0,
204};
205
206static const unsigned int LDO14_table[] = {
207 1800000, 1850000, 2700000, 2750000, 2800000, 2850000, 2900000, 3300000,
208};
209
210static const unsigned int LDO14_suspend_table[] = {
211 1800000, 1850000, 2700000, 2750000, 2800000, 2850000, 2900000, 2900000,
212};
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400213
214static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
215{
216 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400217 int ret = -EINVAL;
218
Axel Lind06563c2010-09-04 23:10:48 +0800219 if (info->vol_table && (index < (1 << info->vol_nbits))) {
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -0400220 ret = info->vol_table[index];
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400221 if (info->slope_double)
222 ret <<= 1;
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400223 }
224 return ret;
225}
226
227static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
228{
229 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -0400230 int i, ret = -ENOENT;
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400231
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -0400232 if (info->slope_double) {
233 min_uV = min_uV >> 1;
234 max_uV = max_uV >> 1;
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400235 }
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -0400236 if (info->vol_table) {
Axel Lind06563c2010-09-04 23:10:48 +0800237 for (i = 0; i < (1 << info->vol_nbits); i++) {
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -0400238 if (!info->vol_table[i])
239 break;
240 if ((min_uV <= info->vol_table[i])
241 && (max_uV >= info->vol_table[i])) {
242 ret = i;
243 break;
244 }
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400245 }
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -0400246 }
247 if (ret < 0)
248 pr_err("invalid voltage range (%d %d) uV\n", min_uV, max_uV);
249 return ret;
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400250}
251
252static int pm8607_set_voltage(struct regulator_dev *rdev,
Mark Brown3a93f2a2010-11-10 14:38:29 +0000253 int min_uV, int max_uV, unsigned *selector)
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400254{
255 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400256 uint8_t val, mask;
257 int ret;
258
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -0400259 if (min_uV > max_uV) {
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400260 pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV);
261 return -EINVAL;
262 }
263
264 ret = choose_voltage(rdev, min_uV, max_uV);
265 if (ret < 0)
266 return -EINVAL;
Mark Brown3a93f2a2010-11-10 14:38:29 +0000267 *selector = ret;
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400268 val = (uint8_t)(ret << info->vol_shift);
269 mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
270
Haojian Zhuang53dbab72010-01-08 06:01:24 -0500271 ret = pm860x_set_bits(info->i2c, info->vol_reg, mask, val);
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400272 if (ret)
273 return ret;
274 switch (info->desc.id) {
275 case PM8607_ID_BUCK1:
276 case PM8607_ID_BUCK3:
Haojian Zhuang53dbab72010-01-08 06:01:24 -0500277 ret = pm860x_set_bits(info->i2c, info->update_reg,
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400278 1 << info->update_bit,
279 1 << info->update_bit);
280 break;
281 }
282 return ret;
283}
284
285static int pm8607_get_voltage(struct regulator_dev *rdev)
286{
287 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400288 uint8_t val, mask;
289 int ret;
290
Haojian Zhuang53dbab72010-01-08 06:01:24 -0500291 ret = pm860x_reg_read(info->i2c, info->vol_reg);
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400292 if (ret < 0)
293 return ret;
294
295 mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
296 val = ((unsigned char)ret & mask) >> info->vol_shift;
297
298 return pm8607_list_voltage(rdev, val);
299}
300
301static int pm8607_enable(struct regulator_dev *rdev)
302{
303 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400304
Haojian Zhuang53dbab72010-01-08 06:01:24 -0500305 return pm860x_set_bits(info->i2c, info->enable_reg,
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400306 1 << info->enable_bit,
307 1 << info->enable_bit);
308}
309
310static int pm8607_disable(struct regulator_dev *rdev)
311{
312 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400313
Haojian Zhuang53dbab72010-01-08 06:01:24 -0500314 return pm860x_set_bits(info->i2c, info->enable_reg,
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400315 1 << info->enable_bit, 0);
316}
317
318static int pm8607_is_enabled(struct regulator_dev *rdev)
319{
320 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400321 int ret;
322
Haojian Zhuang53dbab72010-01-08 06:01:24 -0500323 ret = pm860x_reg_read(info->i2c, info->enable_reg);
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400324 if (ret < 0)
325 return ret;
326
327 return !!((unsigned char)ret & (1 << info->enable_bit));
328}
329
330static struct regulator_ops pm8607_regulator_ops = {
331 .set_voltage = pm8607_set_voltage,
332 .get_voltage = pm8607_get_voltage,
333 .enable = pm8607_enable,
334 .disable = pm8607_disable,
335 .is_enabled = pm8607_is_enabled,
336};
337
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -0400338#define PM8607_DVC(vreg, nbits, ureg, ubit, ereg, ebit) \
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400339{ \
340 .desc = { \
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -0400341 .name = #vreg, \
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400342 .ops = &pm8607_regulator_ops, \
343 .type = REGULATOR_VOLTAGE, \
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -0400344 .id = PM8607_ID_##vreg, \
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400345 .owner = THIS_MODULE, \
346 }, \
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400347 .vol_reg = PM8607_##vreg, \
348 .vol_shift = (0), \
349 .vol_nbits = (nbits), \
350 .update_reg = PM8607_##ureg, \
351 .update_bit = (ubit), \
352 .enable_reg = PM8607_##ereg, \
353 .enable_bit = (ebit), \
354 .slope_double = (0), \
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -0400355 .vol_table = (unsigned int *)&vreg##_table, \
356 .vol_suspend = (unsigned int *)&vreg##_suspend_table, \
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400357}
358
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -0400359#define PM8607_LDO(_id, vreg, shift, nbits, ereg, ebit) \
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400360{ \
361 .desc = { \
362 .name = "LDO" #_id, \
363 .ops = &pm8607_regulator_ops, \
364 .type = REGULATOR_VOLTAGE, \
365 .id = PM8607_ID_LDO##_id, \
366 .owner = THIS_MODULE, \
367 }, \
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400368 .vol_reg = PM8607_##vreg, \
369 .vol_shift = (shift), \
370 .vol_nbits = (nbits), \
371 .enable_reg = PM8607_##ereg, \
372 .enable_bit = (ebit), \
373 .slope_double = (0), \
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -0400374 .vol_table = (unsigned int *)&LDO##_id##_table, \
375 .vol_suspend = (unsigned int *)&LDO##_id##_suspend_table, \
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400376}
377
378static struct pm8607_regulator_info pm8607_regulator_info[] = {
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -0400379 PM8607_DVC(BUCK1, 6, GO, 0, SUPPLIES_EN11, 0),
380 PM8607_DVC(BUCK2, 6, GO, 1, SUPPLIES_EN11, 1),
381 PM8607_DVC(BUCK3, 6, GO, 2, SUPPLIES_EN11, 2),
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400382
Haojian Zhuang9f79e9d2010-05-04 09:54:51 -0400383 PM8607_LDO( 1, LDO1, 0, 2, SUPPLIES_EN11, 3),
384 PM8607_LDO( 2, LDO2, 0, 3, SUPPLIES_EN11, 4),
385 PM8607_LDO( 3, LDO3, 0, 3, SUPPLIES_EN11, 5),
386 PM8607_LDO( 4, LDO4, 0, 3, SUPPLIES_EN11, 6),
387 PM8607_LDO( 5, LDO5, 0, 2, SUPPLIES_EN11, 7),
388 PM8607_LDO( 6, LDO6, 0, 3, SUPPLIES_EN12, 0),
389 PM8607_LDO( 7, LDO7, 0, 3, SUPPLIES_EN12, 1),
390 PM8607_LDO( 8, LDO8, 0, 3, SUPPLIES_EN12, 2),
391 PM8607_LDO( 9, LDO9, 0, 3, SUPPLIES_EN12, 3),
392 PM8607_LDO(10, LDO10, 0, 3, SUPPLIES_EN12, 4),
393 PM8607_LDO(12, LDO12, 0, 4, SUPPLIES_EN12, 5),
394 PM8607_LDO(13, VIBRATOR_SET, 1, 3, VIBRATOR_SET, 0),
395 PM8607_LDO(14, LDO14, 0, 4, SUPPLIES_EN12, 6),
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400396};
397
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400398static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
399{
Haojian Zhuang53dbab72010-01-08 06:01:24 -0500400 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400401 struct pm8607_regulator_info *info = NULL;
Haojian Zhuang586e1a12011-05-06 17:21:23 +0800402 struct regulator_init_data *pdata = pdev->dev.platform_data;
403 struct resource *res;
Haojian Zhuang22aad002011-03-07 23:43:11 +0800404 int i;
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400405
Haojian Zhuang586e1a12011-05-06 17:21:23 +0800406 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
407 if (res == NULL) {
408 dev_err(&pdev->dev, "No I/O resource!\n");
Haojian Zhuang22aad002011-03-07 23:43:11 +0800409 return -EINVAL;
Haojian Zhuang586e1a12011-05-06 17:21:23 +0800410 }
Haojian Zhuang22aad002011-03-07 23:43:11 +0800411 for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) {
412 info = &pm8607_regulator_info[i];
Haojian Zhuang586e1a12011-05-06 17:21:23 +0800413 if (info->desc.id == res->start)
Haojian Zhuang22aad002011-03-07 23:43:11 +0800414 break;
415 }
Haojian Zhuang586e1a12011-05-06 17:21:23 +0800416 if ((i < 0) || (i > PM8607_ID_RG_MAX)) {
Randy Dunlap09969102011-05-26 10:16:15 -0700417 dev_err(&pdev->dev, "Failed to find regulator %llu\n",
418 (unsigned long long)res->start);
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400419 return -EINVAL;
420 }
Haojian Zhuang53dbab72010-01-08 06:01:24 -0500421 info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400422 info->chip = chip;
423
Haojian Zhuang22aad002011-03-07 23:43:11 +0800424 /* check DVC ramp slope double */
Haojian Zhuang586e1a12011-05-06 17:21:23 +0800425 if ((i == PM8607_ID_BUCK3) && info->chip->buck3_double)
426 info->slope_double = 1;
Haojian Zhuang22aad002011-03-07 23:43:11 +0800427
Haojian Zhuang586e1a12011-05-06 17:21:23 +0800428 /* replace driver_data with info */
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400429 info->regulator = regulator_register(&info->desc, &pdev->dev,
Haojian Zhuang22aad002011-03-07 23:43:11 +0800430 pdata, info);
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400431 if (IS_ERR(info->regulator)) {
432 dev_err(&pdev->dev, "failed to register regulator %s\n",
433 info->desc.name);
434 return PTR_ERR(info->regulator);
435 }
436
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400437 platform_set_drvdata(pdev, info);
438 return 0;
439}
440
441static int __devexit pm8607_regulator_remove(struct platform_device *pdev)
442{
443 struct pm8607_regulator_info *info = platform_get_drvdata(pdev);
444
Haojian Zhuang192bbb92010-04-29 13:33:50 -0400445 platform_set_drvdata(pdev, NULL);
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400446 regulator_unregister(info->regulator);
447 return 0;
448}
449
Haojian Zhuang192bbb92010-04-29 13:33:50 -0400450static struct platform_driver pm8607_regulator_driver = {
451 .driver = {
452 .name = "88pm860x-regulator",
453 .owner = THIS_MODULE,
454 },
455 .probe = pm8607_regulator_probe,
456 .remove = __devexit_p(pm8607_regulator_remove),
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400457};
458
459static int __init pm8607_regulator_init(void)
460{
Haojian Zhuang192bbb92010-04-29 13:33:50 -0400461 return platform_driver_register(&pm8607_regulator_driver);
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400462}
463subsys_initcall(pm8607_regulator_init);
464
465static void __exit pm8607_regulator_exit(void)
466{
Haojian Zhuang192bbb92010-04-29 13:33:50 -0400467 platform_driver_unregister(&pm8607_regulator_driver);
Haojian Zhuangbe0e2d32009-10-08 02:03:57 -0400468}
469module_exit(pm8607_regulator_exit);
470
471MODULE_LICENSE("GPL");
472MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
473MODULE_DESCRIPTION("Regulator Driver for Marvell 88PM8607 PMIC");
474MODULE_ALIAS("platform:88pm8607-regulator");