2 * da9052-regulator.c: Regulator driver for DA9052
4 * Copyright(c) 2011 Dialog Semiconductor Ltd.
6 * Author: David Dajun Chen <dchen@diasemi.com>
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.
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>
23 #include <linux/mfd/da9052/da9052.h>
24 #include <linux/mfd/da9052/reg.h>
25 #include <linux/mfd/da9052/pdata.h>
28 #define DA9052_BUCK_PERI_3uV_STEP 100000
29 #define DA9052_BUCK_PERI_REG_MAP_UPTO_3uV 24
30 #define DA9052_CONST_3uV 3000000
32 #define DA9052_MIN_UA 0
33 #define DA9052_MAX_UA 3
34 #define DA9052_CURRENT_RANGE 4
37 #define DA9052_BUCK_ILIM_MASK_EVEN 0x0c
38 #define DA9052_BUCK_ILIM_MASK_ODD 0xc0
40 static const u32 da9052_current_limits
[3][4] = {
41 {700000, 800000, 1000000, 1200000}, /* DA9052-BC BUCKs */
42 {1600000, 2000000, 2400000, 3000000}, /* DA9053-AA/Bx BUCK-CORE */
43 {800000, 1000000, 1200000, 1500000}, /* DA9053-AA/Bx BUCK-PRO,
44 * BUCK-MEM and BUCK-PERI
48 struct da9052_regulator_info
{
49 struct regulator_desc reg_desc
;
53 unsigned char volt_shift
;
55 unsigned char activate_bit
;
58 struct da9052_regulator
{
59 struct da9052
*da9052
;
60 struct da9052_regulator_info
*info
;
61 struct regulator_dev
*rdev
;
64 static int verify_range(struct da9052_regulator_info
*info
,
65 int min_uV
, int max_uV
)
67 if (min_uV
> info
->max_uV
|| max_uV
< info
->min_uV
)
73 static int da9052_regulator_enable(struct regulator_dev
*rdev
)
75 struct da9052_regulator
*regulator
= rdev_get_drvdata(rdev
);
76 struct da9052_regulator_info
*info
= regulator
->info
;
77 int offset
= rdev_get_id(rdev
);
79 return da9052_reg_update(regulator
->da9052
,
80 DA9052_BUCKCORE_REG
+ offset
,
81 1 << info
->en_bit
, 1 << info
->en_bit
);
84 static int da9052_regulator_disable(struct regulator_dev
*rdev
)
86 struct da9052_regulator
*regulator
= rdev_get_drvdata(rdev
);
87 struct da9052_regulator_info
*info
= regulator
->info
;
88 int offset
= rdev_get_id(rdev
);
90 return da9052_reg_update(regulator
->da9052
,
91 DA9052_BUCKCORE_REG
+ offset
,
92 1 << info
->en_bit
, 0);
95 static int da9052_regulator_is_enabled(struct regulator_dev
*rdev
)
97 struct da9052_regulator
*regulator
= rdev_get_drvdata(rdev
);
98 struct da9052_regulator_info
*info
= regulator
->info
;
99 int offset
= rdev_get_id(rdev
);
102 ret
= da9052_reg_read(regulator
->da9052
, DA9052_BUCKCORE_REG
+ offset
);
106 return ret
& (1 << info
->en_bit
);
109 static int da9052_dcdc_get_current_limit(struct regulator_dev
*rdev
)
111 struct da9052_regulator
*regulator
= rdev_get_drvdata(rdev
);
112 int offset
= rdev_get_id(rdev
);
115 ret
= da9052_reg_read(regulator
->da9052
, DA9052_BUCKA_REG
+ offset
/2);
119 /* Determine the even or odd position of the buck current limit
123 ret
= (ret
& DA9052_BUCK_ILIM_MASK_EVEN
) >> 2;
125 ret
= (ret
& DA9052_BUCK_ILIM_MASK_ODD
) >> 6;
127 /* Select the appropriate current limit range */
128 if (regulator
->da9052
->chip_id
== DA9052
)
130 else if (offset
== 0)
133 return da9052_current_limits
[row
][ret
];
136 static int da9052_dcdc_set_current_limit(struct regulator_dev
*rdev
, int min_uA
,
139 struct da9052_regulator
*regulator
= rdev_get_drvdata(rdev
);
140 int offset
= rdev_get_id(rdev
);
144 /* Select the appropriate current limit range */
145 if (regulator
->da9052
->chip_id
== DA9052
)
147 else if (offset
== 0)
150 if (min_uA
> da9052_current_limits
[row
][DA9052_MAX_UA
] ||
151 max_uA
< da9052_current_limits
[row
][DA9052_MIN_UA
])
154 for (i
= 0; i
< DA9052_CURRENT_RANGE
; i
++) {
155 if (min_uA
<= da9052_current_limits
[row
][i
]) {
161 /* Determine the even or odd position of the buck current limit
165 return da9052_reg_update(regulator
->da9052
,
166 DA9052_BUCKA_REG
+ offset
/2,
167 DA9052_BUCK_ILIM_MASK_EVEN
,
170 return da9052_reg_update(regulator
->da9052
,
171 DA9052_BUCKA_REG
+ offset
/2,
172 DA9052_BUCK_ILIM_MASK_ODD
,
176 static int da9052_list_buckperi_voltage(struct regulator_dev
*rdev
,
177 unsigned int selector
)
179 struct da9052_regulator
*regulator
= rdev_get_drvdata(rdev
);
180 struct da9052_regulator_info
*info
= regulator
->info
;
183 if ((regulator
->da9052
->chip_id
== DA9052
) &&
184 (selector
>= DA9052_BUCK_PERI_REG_MAP_UPTO_3uV
)) {
185 volt_uV
= ((DA9052_BUCK_PERI_REG_MAP_UPTO_3uV
* info
->step_uV
)
187 volt_uV
+= (selector
- DA9052_BUCK_PERI_REG_MAP_UPTO_3uV
)
188 * (DA9052_BUCK_PERI_3uV_STEP
);
190 volt_uV
= (selector
* info
->step_uV
) + info
->min_uV
;
192 if (volt_uV
> info
->max_uV
)
198 static int da9052_list_voltage(struct regulator_dev
*rdev
,
199 unsigned int selector
)
201 struct da9052_regulator
*regulator
= rdev_get_drvdata(rdev
);
202 struct da9052_regulator_info
*info
= regulator
->info
;
205 volt_uV
= info
->min_uV
+ info
->step_uV
* selector
;
207 if (volt_uV
> info
->max_uV
)
213 static int da9052_regulator_set_voltage_int(struct regulator_dev
*rdev
,
214 int min_uV
, int max_uV
,
215 unsigned int *selector
)
217 struct da9052_regulator
*regulator
= rdev_get_drvdata(rdev
);
218 struct da9052_regulator_info
*info
= regulator
->info
;
219 int offset
= rdev_get_id(rdev
);
222 ret
= verify_range(info
, min_uV
, max_uV
);
226 if (min_uV
< info
->min_uV
)
227 min_uV
= info
->min_uV
;
229 *selector
= DIV_ROUND_UP(min_uV
- info
->min_uV
, info
->step_uV
);
231 ret
= da9052_list_voltage(rdev
, *selector
);
235 return da9052_reg_update(regulator
->da9052
,
236 DA9052_BUCKCORE_REG
+ offset
,
237 (1 << info
->volt_shift
) - 1, *selector
);
240 static int da9052_set_ldo_voltage(struct regulator_dev
*rdev
,
241 int min_uV
, int max_uV
,
242 unsigned int *selector
)
244 return da9052_regulator_set_voltage_int(rdev
, min_uV
, max_uV
, selector
);
247 static int da9052_set_ldo5_6_voltage(struct regulator_dev
*rdev
,
248 int min_uV
, int max_uV
,
249 unsigned int *selector
)
251 struct da9052_regulator
*regulator
= rdev_get_drvdata(rdev
);
252 struct da9052_regulator_info
*info
= regulator
->info
;
255 ret
= da9052_regulator_set_voltage_int(rdev
, min_uV
, max_uV
, selector
);
259 /* Some LDOs are DVC controlled which requires enabling of
260 * the LDO activate bit to implment the changes on the
263 return da9052_reg_update(regulator
->da9052
, DA9052_SUPPLY_REG
,
264 info
->activate_bit
, info
->activate_bit
);
267 static int da9052_set_dcdc_voltage(struct regulator_dev
*rdev
,
268 int min_uV
, int max_uV
,
269 unsigned int *selector
)
271 struct da9052_regulator
*regulator
= rdev_get_drvdata(rdev
);
272 struct da9052_regulator_info
*info
= regulator
->info
;
275 ret
= da9052_regulator_set_voltage_int(rdev
, min_uV
, max_uV
, selector
);
279 /* Some DCDCs are DVC controlled which requires enabling of
280 * the DCDC activate bit to implment the changes on the
283 return da9052_reg_update(regulator
->da9052
, DA9052_SUPPLY_REG
,
284 info
->activate_bit
, info
->activate_bit
);
287 static int da9052_get_regulator_voltage_sel(struct regulator_dev
*rdev
)
289 struct da9052_regulator
*regulator
= rdev_get_drvdata(rdev
);
290 struct da9052_regulator_info
*info
= regulator
->info
;
291 int offset
= rdev_get_id(rdev
);
294 ret
= da9052_reg_read(regulator
->da9052
, DA9052_BUCKCORE_REG
+ offset
);
298 ret
&= ((1 << info
->volt_shift
) - 1);
303 static int da9052_set_buckperi_voltage(struct regulator_dev
*rdev
, int min_uV
,
304 int max_uV
, unsigned int *selector
)
306 struct da9052_regulator
*regulator
= rdev_get_drvdata(rdev
);
307 struct da9052_regulator_info
*info
= regulator
->info
;
308 int offset
= rdev_get_id(rdev
);
311 ret
= verify_range(info
, min_uV
, max_uV
);
315 if (min_uV
< info
->min_uV
)
316 min_uV
= info
->min_uV
;
318 if ((regulator
->da9052
->chip_id
== DA9052
) &&
319 (min_uV
>= DA9052_CONST_3uV
))
320 *selector
= DA9052_BUCK_PERI_REG_MAP_UPTO_3uV
+
321 DIV_ROUND_UP(min_uV
- DA9052_CONST_3uV
,
322 DA9052_BUCK_PERI_3uV_STEP
);
324 *selector
= DIV_ROUND_UP(min_uV
- info
->min_uV
, info
->step_uV
);
326 ret
= da9052_list_buckperi_voltage(rdev
, *selector
);
330 return da9052_reg_update(regulator
->da9052
,
331 DA9052_BUCKCORE_REG
+ offset
,
332 (1 << info
->volt_shift
) - 1, *selector
);
335 static int da9052_get_buckperi_voltage_sel(struct regulator_dev
*rdev
)
337 struct da9052_regulator
*regulator
= rdev_get_drvdata(rdev
);
338 struct da9052_regulator_info
*info
= regulator
->info
;
339 int offset
= rdev_get_id(rdev
);
342 ret
= da9052_reg_read(regulator
->da9052
, DA9052_BUCKCORE_REG
+ offset
);
346 ret
&= ((1 << info
->volt_shift
) - 1);
351 static struct regulator_ops da9052_buckperi_ops
= {
352 .list_voltage
= da9052_list_buckperi_voltage
,
353 .get_voltage_sel
= da9052_get_buckperi_voltage_sel
,
354 .set_voltage
= da9052_set_buckperi_voltage
,
356 .get_current_limit
= da9052_dcdc_get_current_limit
,
357 .set_current_limit
= da9052_dcdc_set_current_limit
,
359 .is_enabled
= da9052_regulator_is_enabled
,
360 .enable
= da9052_regulator_enable
,
361 .disable
= da9052_regulator_disable
,
364 static struct regulator_ops da9052_dcdc_ops
= {
365 .set_voltage
= da9052_set_dcdc_voltage
,
366 .get_current_limit
= da9052_dcdc_get_current_limit
,
367 .set_current_limit
= da9052_dcdc_set_current_limit
,
369 .list_voltage
= da9052_list_voltage
,
370 .get_voltage_sel
= da9052_get_regulator_voltage_sel
,
371 .is_enabled
= da9052_regulator_is_enabled
,
372 .enable
= da9052_regulator_enable
,
373 .disable
= da9052_regulator_disable
,
376 static struct regulator_ops da9052_ldo5_6_ops
= {
377 .set_voltage
= da9052_set_ldo5_6_voltage
,
379 .list_voltage
= da9052_list_voltage
,
380 .get_voltage_sel
= da9052_get_regulator_voltage_sel
,
381 .is_enabled
= da9052_regulator_is_enabled
,
382 .enable
= da9052_regulator_enable
,
383 .disable
= da9052_regulator_disable
,
386 static struct regulator_ops da9052_ldo_ops
= {
387 .set_voltage
= da9052_set_ldo_voltage
,
389 .list_voltage
= da9052_list_voltage
,
390 .get_voltage_sel
= da9052_get_regulator_voltage_sel
,
391 .is_enabled
= da9052_regulator_is_enabled
,
392 .enable
= da9052_regulator_enable
,
393 .disable
= da9052_regulator_disable
,
396 #define DA9052_LDO5_6(_id, step, min, max, sbits, ebits, abits) \
400 .ops = &da9052_ldo5_6_ops,\
401 .type = REGULATOR_VOLTAGE,\
403 .n_voltages = (max - min) / step + 1, \
404 .owner = THIS_MODULE,\
406 .min_uV = (min) * 1000,\
407 .max_uV = (max) * 1000,\
408 .step_uV = (step) * 1000,\
409 .volt_shift = (sbits),\
411 .activate_bit = (abits),\
414 #define DA9052_LDO(_id, step, min, max, sbits, ebits, abits) \
418 .ops = &da9052_ldo_ops,\
419 .type = REGULATOR_VOLTAGE,\
421 .n_voltages = (max - min) / step + 1, \
422 .owner = THIS_MODULE,\
424 .min_uV = (min) * 1000,\
425 .max_uV = (max) * 1000,\
426 .step_uV = (step) * 1000,\
427 .volt_shift = (sbits),\
429 .activate_bit = (abits),\
432 #define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \
435 .name = "BUCK" #_id,\
436 .ops = &da9052_dcdc_ops,\
437 .type = REGULATOR_VOLTAGE,\
439 .n_voltages = (max - min) / step + 1, \
440 .owner = THIS_MODULE,\
442 .min_uV = (min) * 1000,\
443 .max_uV = (max) * 1000,\
444 .step_uV = (step) * 1000,\
445 .volt_shift = (sbits),\
447 .activate_bit = (abits),\
450 #define DA9052_BUCKPERI(_id, step, min, max, sbits, ebits, abits) \
453 .name = "BUCK" #_id,\
454 .ops = &da9052_buckperi_ops,\
455 .type = REGULATOR_VOLTAGE,\
457 .n_voltages = (max - min) / step + 1, \
458 .owner = THIS_MODULE,\
460 .min_uV = (min) * 1000,\
461 .max_uV = (max) * 1000,\
462 .step_uV = (step) * 1000,\
463 .volt_shift = (sbits),\
465 .activate_bit = (abits),\
468 static struct da9052_regulator_info da9052_regulator_info
[] = {
470 DA9052_DCDC(0, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO
),
471 DA9052_DCDC(1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO
),
472 DA9052_DCDC(2, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO
),
473 DA9052_BUCKPERI(3, 50, 1800, 3600, 5, 6, 0),
475 DA9052_LDO(4, 50, 600, 1800, 5, 6, 0),
476 DA9052_LDO5_6(5, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO
),
477 DA9052_LDO5_6(6, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO
),
478 DA9052_LDO(7, 25, 1725, 3300, 6, 6, 0),
479 DA9052_LDO(8, 50, 1200, 3600, 6, 6, 0),
480 DA9052_LDO(9, 50, 1200, 3600, 6, 6, 0),
481 DA9052_LDO(10, 50, 1200, 3600, 6, 6, 0),
482 DA9052_LDO(11, 50, 1200, 3600, 6, 6, 0),
483 DA9052_LDO(12, 50, 1250, 3650, 6, 6, 0),
484 DA9052_LDO(13, 50, 1200, 3600, 6, 6, 0),
487 static struct da9052_regulator_info da9053_regulator_info
[] = {
489 DA9052_DCDC(0, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO
),
490 DA9052_DCDC(1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO
),
491 DA9052_DCDC(2, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO
),
492 DA9052_BUCKPERI(3, 25, 925, 2500, 6, 6, 0),
494 DA9052_LDO(4, 50, 600, 1800, 5, 6, 0),
495 DA9052_LDO5_6(5, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO
),
496 DA9052_LDO5_6(6, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO
),
497 DA9052_LDO(7, 25, 1725, 3300, 6, 6, 0),
498 DA9052_LDO(8, 50, 1200, 3600, 6, 6, 0),
499 DA9052_LDO(9, 50, 1200, 3600, 6, 6, 0),
500 DA9052_LDO(10, 50, 1200, 3600, 6, 6, 0),
501 DA9052_LDO(11, 50, 1200, 3600, 6, 6, 0),
502 DA9052_LDO(12, 50, 1250, 3650, 6, 6, 0),
503 DA9052_LDO(13, 50, 1200, 3600, 6, 6, 0),
506 static inline struct da9052_regulator_info
*find_regulator_info(u8 chip_id
,
509 struct da9052_regulator_info
*info
;
514 for (i
= 0; i
< ARRAY_SIZE(da9052_regulator_info
); i
++) {
515 info
= &da9052_regulator_info
[i
];
516 if (info
->reg_desc
.id
== id
)
523 for (i
= 0; i
< ARRAY_SIZE(da9053_regulator_info
); i
++) {
524 info
= &da9053_regulator_info
[i
];
525 if (info
->reg_desc
.id
== id
)
534 static int __devinit
da9052_regulator_probe(struct platform_device
*pdev
)
536 struct da9052_regulator
*regulator
;
537 struct da9052
*da9052
;
538 struct da9052_pdata
*pdata
;
541 regulator
= devm_kzalloc(&pdev
->dev
, sizeof(struct da9052_regulator
),
546 da9052
= dev_get_drvdata(pdev
->dev
.parent
);
547 pdata
= da9052
->dev
->platform_data
;
548 regulator
->da9052
= da9052
;
550 regulator
->info
= find_regulator_info(regulator
->da9052
->chip_id
,
552 if (regulator
->info
== NULL
) {
553 dev_err(&pdev
->dev
, "invalid regulator ID specified\n");
557 regulator
->rdev
= regulator_register(®ulator
->info
->reg_desc
,
559 pdata
->regulators
[pdev
->id
],
561 if (IS_ERR(regulator
->rdev
)) {
562 dev_err(&pdev
->dev
, "failed to register regulator %s\n",
563 regulator
->info
->reg_desc
.name
);
564 ret
= PTR_ERR(regulator
->rdev
);
568 platform_set_drvdata(pdev
, regulator
);
572 devm_kfree(&pdev
->dev
, regulator
);
576 static int __devexit
da9052_regulator_remove(struct platform_device
*pdev
)
578 struct da9052_regulator
*regulator
= platform_get_drvdata(pdev
);
580 regulator_unregister(regulator
->rdev
);
581 devm_kfree(&pdev
->dev
, regulator
);
586 static struct platform_driver da9052_regulator_driver
= {
587 .probe
= da9052_regulator_probe
,
588 .remove
= __devexit_p(da9052_regulator_remove
),
590 .name
= "da9052-regulator",
591 .owner
= THIS_MODULE
,
595 static int __init
da9052_regulator_init(void)
597 return platform_driver_register(&da9052_regulator_driver
);
599 subsys_initcall(da9052_regulator_init
);
601 static void __exit
da9052_regulator_exit(void)
603 platform_driver_unregister(&da9052_regulator_driver
);
605 module_exit(da9052_regulator_exit
);
607 MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
608 MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9052 PMIC");
609 MODULE_LICENSE("GPL");
610 MODULE_ALIAS("platform:da9052-regulator");