blob: ddcba361bad632ca3436cdd6d3cc86507580bcaf [file] [log] [blame]
Ashish Jangam08bf1c02011-12-09 19:48:20 +05301/*
2* da9052-regulator.c: Regulator driver for DA9052
3*
4* Copyright(c) 2011 Dialog Semiconductor Ltd.
5*
6* Author: David Dajun Chen <dchen@diasemi.com>
7*
8* This program is free software; you can redistribute it and/or modify
9* it under the terms of the GNU General Public License as published by
10* the Free Software Foundation; either version 2 of the License, or
11* (at your option) any later version.
12*
13*/
14
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/init.h>
18#include <linux/err.h>
19#include <linux/platform_device.h>
20#include <linux/regulator/driver.h>
21#include <linux/regulator/machine.h>
22
23#include <linux/mfd/da9052/da9052.h>
24#include <linux/mfd/da9052/reg.h>
25#include <linux/mfd/da9052/pdata.h>
26
27/* Buck step size */
28#define DA9052_BUCK_PERI_3uV_STEP 100000
29#define DA9052_BUCK_PERI_REG_MAP_UPTO_3uV 24
30#define DA9052_CONST_3uV 3000000
31
32#define DA9052_MIN_UA 0
33#define DA9052_MAX_UA 3
34#define DA9052_CURRENT_RANGE 4
35
36/* Bit masks */
37#define DA9052_BUCK_ILIM_MASK_EVEN 0x0c
38#define DA9052_BUCK_ILIM_MASK_ODD 0xc0
39
Axel Lin9210f052012-03-15 19:58:39 +080040/* DA9052 REGULATOR IDs */
41#define DA9052_ID_BUCK1 0
42#define DA9052_ID_BUCK2 1
43#define DA9052_ID_BUCK3 2
44#define DA9052_ID_BUCK4 3
45#define DA9052_ID_LDO1 4
46#define DA9052_ID_LDO2 5
47#define DA9052_ID_LDO3 6
48#define DA9052_ID_LDO4 7
49#define DA9052_ID_LDO5 8
50#define DA9052_ID_LDO6 9
51#define DA9052_ID_LDO7 10
52#define DA9052_ID_LDO8 11
53#define DA9052_ID_LDO9 12
54#define DA9052_ID_LDO10 13
55
Ashish Jangam08bf1c02011-12-09 19:48:20 +053056static const u32 da9052_current_limits[3][4] = {
57 {700000, 800000, 1000000, 1200000}, /* DA9052-BC BUCKs */
58 {1600000, 2000000, 2400000, 3000000}, /* DA9053-AA/Bx BUCK-CORE */
59 {800000, 1000000, 1200000, 1500000}, /* DA9053-AA/Bx BUCK-PRO,
60 * BUCK-MEM and BUCK-PERI
61 */
62};
63
64struct da9052_regulator_info {
65 struct regulator_desc reg_desc;
66 int step_uV;
67 int min_uV;
68 int max_uV;
69 unsigned char volt_shift;
70 unsigned char en_bit;
71 unsigned char activate_bit;
72};
73
74struct da9052_regulator {
75 struct da9052 *da9052;
76 struct da9052_regulator_info *info;
77 struct regulator_dev *rdev;
78};
79
80static int verify_range(struct da9052_regulator_info *info,
81 int min_uV, int max_uV)
82{
83 if (min_uV > info->max_uV || max_uV < info->min_uV)
84 return -EINVAL;
85
86 return 0;
87}
88
89static int da9052_regulator_enable(struct regulator_dev *rdev)
90{
91 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
92 struct da9052_regulator_info *info = regulator->info;
93 int offset = rdev_get_id(rdev);
94
95 return da9052_reg_update(regulator->da9052,
96 DA9052_BUCKCORE_REG + offset,
97 1 << info->en_bit, 1 << info->en_bit);
98}
99
100static int da9052_regulator_disable(struct regulator_dev *rdev)
101{
102 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
103 struct da9052_regulator_info *info = regulator->info;
104 int offset = rdev_get_id(rdev);
105
106 return da9052_reg_update(regulator->da9052,
107 DA9052_BUCKCORE_REG + offset,
108 1 << info->en_bit, 0);
109}
110
111static int da9052_regulator_is_enabled(struct regulator_dev *rdev)
112{
113 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
114 struct da9052_regulator_info *info = regulator->info;
115 int offset = rdev_get_id(rdev);
116 int ret;
117
118 ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
119 if (ret < 0)
120 return ret;
121
122 return ret & (1 << info->en_bit);
123}
124
125static int da9052_dcdc_get_current_limit(struct regulator_dev *rdev)
126{
127 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
128 int offset = rdev_get_id(rdev);
129 int ret, row = 2;
130
131 ret = da9052_reg_read(regulator->da9052, DA9052_BUCKA_REG + offset/2);
132 if (ret < 0)
133 return ret;
134
135 /* Determine the even or odd position of the buck current limit
136 * register field
137 */
138 if (offset % 2 == 0)
139 ret = (ret & DA9052_BUCK_ILIM_MASK_EVEN) >> 2;
140 else
141 ret = (ret & DA9052_BUCK_ILIM_MASK_ODD) >> 6;
142
143 /* Select the appropriate current limit range */
144 if (regulator->da9052->chip_id == DA9052)
145 row = 0;
146 else if (offset == 0)
147 row = 1;
148
149 return da9052_current_limits[row][ret];
150}
151
152static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA,
153 int max_uA)
154{
155 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
156 int offset = rdev_get_id(rdev);
157 int reg_val = 0;
158 int i, row = 2;
159
160 /* Select the appropriate current limit range */
161 if (regulator->da9052->chip_id == DA9052)
162 row = 0;
163 else if (offset == 0)
164 row = 1;
165
166 if (min_uA > da9052_current_limits[row][DA9052_MAX_UA] ||
167 max_uA < da9052_current_limits[row][DA9052_MIN_UA])
168 return -EINVAL;
169
170 for (i = 0; i < DA9052_CURRENT_RANGE; i++) {
171 if (min_uA <= da9052_current_limits[row][i]) {
172 reg_val = i;
173 break;
174 }
175 }
176
177 /* Determine the even or odd position of the buck current limit
178 * register field
179 */
180 if (offset % 2 == 0)
181 return da9052_reg_update(regulator->da9052,
182 DA9052_BUCKA_REG + offset/2,
183 DA9052_BUCK_ILIM_MASK_EVEN,
184 reg_val << 2);
185 else
186 return da9052_reg_update(regulator->da9052,
187 DA9052_BUCKA_REG + offset/2,
188 DA9052_BUCK_ILIM_MASK_ODD,
189 reg_val << 6);
190}
191
192static int da9052_list_buckperi_voltage(struct regulator_dev *rdev,
193 unsigned int selector)
194{
195 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
196 struct da9052_regulator_info *info = regulator->info;
197 int volt_uV;
198
199 if ((regulator->da9052->chip_id == DA9052) &&
200 (selector >= DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)) {
201 volt_uV = ((DA9052_BUCK_PERI_REG_MAP_UPTO_3uV * info->step_uV)
202 + info->min_uV);
203 volt_uV += (selector - DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)
204 * (DA9052_BUCK_PERI_3uV_STEP);
205 } else
206 volt_uV = (selector * info->step_uV) + info->min_uV;
207
208 if (volt_uV > info->max_uV)
209 return -EINVAL;
210
211 return volt_uV;
212}
213
214static int da9052_list_voltage(struct regulator_dev *rdev,
215 unsigned int selector)
216{
217 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
218 struct da9052_regulator_info *info = regulator->info;
219 int volt_uV;
220
221 volt_uV = info->min_uV + info->step_uV * selector;
222
223 if (volt_uV > info->max_uV)
224 return -EINVAL;
225
226 return volt_uV;
227}
228
229static int da9052_regulator_set_voltage_int(struct regulator_dev *rdev,
230 int min_uV, int max_uV,
231 unsigned int *selector)
232{
233 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
234 struct da9052_regulator_info *info = regulator->info;
235 int offset = rdev_get_id(rdev);
236 int ret;
237
238 ret = verify_range(info, min_uV, max_uV);
239 if (ret < 0)
240 return ret;
241
242 if (min_uV < info->min_uV)
243 min_uV = info->min_uV;
244
Axel Lin93651212012-03-05 20:27:56 +0800245 *selector = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV);
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530246
247 ret = da9052_list_voltage(rdev, *selector);
248 if (ret < 0)
249 return ret;
250
251 return da9052_reg_update(regulator->da9052,
252 DA9052_BUCKCORE_REG + offset,
253 (1 << info->volt_shift) - 1, *selector);
254}
255
256static int da9052_set_ldo_voltage(struct regulator_dev *rdev,
257 int min_uV, int max_uV,
258 unsigned int *selector)
259{
260 return da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector);
261}
262
263static int da9052_set_ldo5_6_voltage(struct regulator_dev *rdev,
264 int min_uV, int max_uV,
265 unsigned int *selector)
266{
267 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
268 struct da9052_regulator_info *info = regulator->info;
269 int ret;
270
271 ret = da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector);
272 if (ret < 0)
273 return ret;
274
275 /* Some LDOs are DVC controlled which requires enabling of
276 * the LDO activate bit to implment the changes on the
277 * LDO output.
278 */
Axel Lin4adf9be2012-03-02 18:07:21 +0800279 return da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG,
280 info->activate_bit, info->activate_bit);
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530281}
282
283static int da9052_set_dcdc_voltage(struct regulator_dev *rdev,
284 int min_uV, int max_uV,
285 unsigned int *selector)
286{
287 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
288 struct da9052_regulator_info *info = regulator->info;
289 int ret;
290
291 ret = da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector);
292 if (ret < 0)
293 return ret;
294
295 /* Some DCDCs are DVC controlled which requires enabling of
296 * the DCDC activate bit to implment the changes on the
297 * DCDC output.
298 */
Axel Lin4adf9be2012-03-02 18:07:21 +0800299 return da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG,
300 info->activate_bit, info->activate_bit);
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530301}
302
303static int da9052_get_regulator_voltage_sel(struct regulator_dev *rdev)
304{
305 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
306 struct da9052_regulator_info *info = regulator->info;
307 int offset = rdev_get_id(rdev);
308 int ret;
309
310 ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
311 if (ret < 0)
312 return ret;
313
314 ret &= ((1 << info->volt_shift) - 1);
315
316 return ret;
317}
318
319static int da9052_set_buckperi_voltage(struct regulator_dev *rdev, int min_uV,
320 int max_uV, unsigned int *selector)
321{
322 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
323 struct da9052_regulator_info *info = regulator->info;
324 int offset = rdev_get_id(rdev);
325 int ret;
326
327 ret = verify_range(info, min_uV, max_uV);
328 if (ret < 0)
329 return ret;
330
331 if (min_uV < info->min_uV)
332 min_uV = info->min_uV;
333
334 if ((regulator->da9052->chip_id == DA9052) &&
335 (min_uV >= DA9052_CONST_3uV))
336 *selector = DA9052_BUCK_PERI_REG_MAP_UPTO_3uV +
Axel Lin93651212012-03-05 20:27:56 +0800337 DIV_ROUND_UP(min_uV - DA9052_CONST_3uV,
338 DA9052_BUCK_PERI_3uV_STEP);
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530339 else
Axel Lin93651212012-03-05 20:27:56 +0800340 *selector = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV);
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530341
342 ret = da9052_list_buckperi_voltage(rdev, *selector);
343 if (ret < 0)
344 return ret;
345
346 return da9052_reg_update(regulator->da9052,
347 DA9052_BUCKCORE_REG + offset,
348 (1 << info->volt_shift) - 1, *selector);
349}
350
351static int da9052_get_buckperi_voltage_sel(struct regulator_dev *rdev)
352{
353 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
354 struct da9052_regulator_info *info = regulator->info;
355 int offset = rdev_get_id(rdev);
356 int ret;
357
358 ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
359 if (ret < 0)
360 return ret;
361
362 ret &= ((1 << info->volt_shift) - 1);
363
364 return ret;
365}
366
367static struct regulator_ops da9052_buckperi_ops = {
368 .list_voltage = da9052_list_buckperi_voltage,
369 .get_voltage_sel = da9052_get_buckperi_voltage_sel,
370 .set_voltage = da9052_set_buckperi_voltage,
371
372 .get_current_limit = da9052_dcdc_get_current_limit,
373 .set_current_limit = da9052_dcdc_set_current_limit,
374
375 .is_enabled = da9052_regulator_is_enabled,
376 .enable = da9052_regulator_enable,
377 .disable = da9052_regulator_disable,
378};
379
380static struct regulator_ops da9052_dcdc_ops = {
381 .set_voltage = da9052_set_dcdc_voltage,
382 .get_current_limit = da9052_dcdc_get_current_limit,
383 .set_current_limit = da9052_dcdc_set_current_limit,
384
385 .list_voltage = da9052_list_voltage,
386 .get_voltage_sel = da9052_get_regulator_voltage_sel,
387 .is_enabled = da9052_regulator_is_enabled,
388 .enable = da9052_regulator_enable,
389 .disable = da9052_regulator_disable,
390};
391
392static struct regulator_ops da9052_ldo5_6_ops = {
393 .set_voltage = da9052_set_ldo5_6_voltage,
394
395 .list_voltage = da9052_list_voltage,
396 .get_voltage_sel = da9052_get_regulator_voltage_sel,
397 .is_enabled = da9052_regulator_is_enabled,
398 .enable = da9052_regulator_enable,
399 .disable = da9052_regulator_disable,
400};
401
402static struct regulator_ops da9052_ldo_ops = {
403 .set_voltage = da9052_set_ldo_voltage,
404
405 .list_voltage = da9052_list_voltage,
406 .get_voltage_sel = da9052_get_regulator_voltage_sel,
407 .is_enabled = da9052_regulator_is_enabled,
408 .enable = da9052_regulator_enable,
409 .disable = da9052_regulator_disable,
410};
411
412#define DA9052_LDO5_6(_id, step, min, max, sbits, ebits, abits) \
413{\
414 .reg_desc = {\
Axel Lin9210f052012-03-15 19:58:39 +0800415 .name = #_id,\
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530416 .ops = &da9052_ldo5_6_ops,\
417 .type = REGULATOR_VOLTAGE,\
Axel Lin9210f052012-03-15 19:58:39 +0800418 .id = DA9052_ID_##_id,\
Axel Lin7b957652012-03-05 20:04:32 +0800419 .n_voltages = (max - min) / step + 1, \
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530420 .owner = THIS_MODULE,\
421 },\
422 .min_uV = (min) * 1000,\
423 .max_uV = (max) * 1000,\
424 .step_uV = (step) * 1000,\
425 .volt_shift = (sbits),\
426 .en_bit = (ebits),\
427 .activate_bit = (abits),\
428}
429
430#define DA9052_LDO(_id, step, min, max, sbits, ebits, abits) \
431{\
432 .reg_desc = {\
Axel Lin9210f052012-03-15 19:58:39 +0800433 .name = #_id,\
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530434 .ops = &da9052_ldo_ops,\
435 .type = REGULATOR_VOLTAGE,\
Axel Lin9210f052012-03-15 19:58:39 +0800436 .id = DA9052_ID_##_id,\
Axel Lin7b957652012-03-05 20:04:32 +0800437 .n_voltages = (max - min) / step + 1, \
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530438 .owner = THIS_MODULE,\
439 },\
440 .min_uV = (min) * 1000,\
441 .max_uV = (max) * 1000,\
442 .step_uV = (step) * 1000,\
443 .volt_shift = (sbits),\
444 .en_bit = (ebits),\
445 .activate_bit = (abits),\
446}
447
448#define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \
449{\
450 .reg_desc = {\
Axel Lin9210f052012-03-15 19:58:39 +0800451 .name = #_id,\
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530452 .ops = &da9052_dcdc_ops,\
453 .type = REGULATOR_VOLTAGE,\
Axel Lin9210f052012-03-15 19:58:39 +0800454 .id = DA9052_ID_##_id,\
Axel Lin7b957652012-03-05 20:04:32 +0800455 .n_voltages = (max - min) / step + 1, \
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530456 .owner = THIS_MODULE,\
457 },\
458 .min_uV = (min) * 1000,\
459 .max_uV = (max) * 1000,\
460 .step_uV = (step) * 1000,\
461 .volt_shift = (sbits),\
462 .en_bit = (ebits),\
463 .activate_bit = (abits),\
464}
465
466#define DA9052_BUCKPERI(_id, step, min, max, sbits, ebits, abits) \
467{\
468 .reg_desc = {\
Axel Lin9210f052012-03-15 19:58:39 +0800469 .name = #_id,\
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530470 .ops = &da9052_buckperi_ops,\
471 .type = REGULATOR_VOLTAGE,\
Axel Lin9210f052012-03-15 19:58:39 +0800472 .id = DA9052_ID_##_id,\
Axel Lin7b957652012-03-05 20:04:32 +0800473 .n_voltages = (max - min) / step + 1, \
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530474 .owner = THIS_MODULE,\
475 },\
476 .min_uV = (min) * 1000,\
477 .max_uV = (max) * 1000,\
478 .step_uV = (step) * 1000,\
479 .volt_shift = (sbits),\
480 .en_bit = (ebits),\
481 .activate_bit = (abits),\
482}
483
Axel Lin6242eae2011-12-20 17:12:00 +0800484static struct da9052_regulator_info da9052_regulator_info[] = {
Axel Lin9210f052012-03-15 19:58:39 +0800485 DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
486 DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
487 DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
488 DA9052_BUCKPERI(BUCK4, 50, 1800, 3600, 5, 6, 0),
489 DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0),
490 DA9052_LDO5_6(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
491 DA9052_LDO5_6(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
492 DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0),
493 DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0),
494 DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0),
495 DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0),
496 DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0),
497 DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0),
498 DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0),
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530499};
500
Axel Lin6242eae2011-12-20 17:12:00 +0800501static struct da9052_regulator_info da9053_regulator_info[] = {
Axel Lin9210f052012-03-15 19:58:39 +0800502 DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
503 DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
504 DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
505 DA9052_BUCKPERI(BUCK4, 25, 925, 2500, 6, 6, 0),
506 DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0),
507 DA9052_LDO5_6(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
508 DA9052_LDO5_6(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
509 DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0),
510 DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0),
511 DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0),
512 DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0),
513 DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0),
514 DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0),
515 DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0),
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530516};
517
518static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
519 int id)
520{
521 struct da9052_regulator_info *info;
522 int i;
523
Ashish Jangam984b5a62011-12-15 18:59:53 +0530524 switch (chip_id) {
525 case DA9052:
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530526 for (i = 0; i < ARRAY_SIZE(da9052_regulator_info); i++) {
527 info = &da9052_regulator_info[i];
528 if (info->reg_desc.id == id)
529 return info;
530 }
Ashish Jangam984b5a62011-12-15 18:59:53 +0530531 break;
532 case DA9053_AA:
533 case DA9053_BA:
534 case DA9053_BB:
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530535 for (i = 0; i < ARRAY_SIZE(da9053_regulator_info); i++) {
536 info = &da9053_regulator_info[i];
537 if (info->reg_desc.id == id)
538 return info;
539 }
Ashish Jangam984b5a62011-12-15 18:59:53 +0530540 break;
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530541 }
542
543 return NULL;
544}
545
546static int __devinit da9052_regulator_probe(struct platform_device *pdev)
547{
548 struct da9052_regulator *regulator;
549 struct da9052 *da9052;
550 struct da9052_pdata *pdata;
551 int ret;
552
Ashish Jangam984b5a62011-12-15 18:59:53 +0530553 regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9052_regulator),
554 GFP_KERNEL);
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530555 if (!regulator)
556 return -ENOMEM;
557
558 da9052 = dev_get_drvdata(pdev->dev.parent);
559 pdata = da9052->dev->platform_data;
560 regulator->da9052 = da9052;
561
562 regulator->info = find_regulator_info(regulator->da9052->chip_id,
563 pdev->id);
564 if (regulator->info == NULL) {
565 dev_err(&pdev->dev, "invalid regulator ID specified\n");
566 ret = -EINVAL;
567 goto err;
568 }
569 regulator->rdev = regulator_register(&regulator->info->reg_desc,
570 &pdev->dev,
571 pdata->regulators[pdev->id],
Mark Brown47aed922011-12-15 15:03:38 +0800572 regulator, NULL);
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530573 if (IS_ERR(regulator->rdev)) {
574 dev_err(&pdev->dev, "failed to register regulator %s\n",
575 regulator->info->reg_desc.name);
576 ret = PTR_ERR(regulator->rdev);
577 goto err;
578 }
579
580 platform_set_drvdata(pdev, regulator);
581
582 return 0;
583err:
Ashish Jangam984b5a62011-12-15 18:59:53 +0530584 devm_kfree(&pdev->dev, regulator);
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530585 return ret;
586}
587
588static int __devexit da9052_regulator_remove(struct platform_device *pdev)
589{
590 struct da9052_regulator *regulator = platform_get_drvdata(pdev);
591
592 regulator_unregister(regulator->rdev);
Ashish Jangam984b5a62011-12-15 18:59:53 +0530593 devm_kfree(&pdev->dev, regulator);
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530594
595 return 0;
596}
597
598static struct platform_driver da9052_regulator_driver = {
599 .probe = da9052_regulator_probe,
600 .remove = __devexit_p(da9052_regulator_remove),
601 .driver = {
602 .name = "da9052-regulator",
603 .owner = THIS_MODULE,
604 },
605};
606
607static int __init da9052_regulator_init(void)
608{
609 return platform_driver_register(&da9052_regulator_driver);
610}
611subsys_initcall(da9052_regulator_init);
612
613static void __exit da9052_regulator_exit(void)
614{
615 platform_driver_unregister(&da9052_regulator_driver);
616}
617module_exit(da9052_regulator_exit);
618
619MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
620MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9052 PMIC");
621MODULE_LICENSE("GPL");
622MODULE_ALIAS("platform:da9052-regulator");