Skip to content

Commit 4b7f495

Browse files
Steve Twissbroonie
authored andcommitted
regulator: da9061: BUCK and LDO regulator driver
Regulator support for the DA9061 is added into the DA9062 regulator driver. The regulators for DA9061 differ from those of DA9062. A new DA9061 enumeration list for the LDOs and Bucks supported by this device is added. Regulator information added: the old regulator information for DA9062 is renamed from local_regulator_info[] to local_da9062_regulator_info[] and a new array is added to support local_da9061_regulator_info[]. The probe() function switches on the da9062_compatible_types enumeration and configures the correct da9062_regulator_info array and number of regulator entries. Kconfig is updated to reflect support for DA9061 and DA9062 regulators. Signed-off-by: Steve Twiss <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent 2ea659a commit 4b7f495

File tree

2 files changed

+293
-14
lines changed

2 files changed

+293
-14
lines changed

drivers/regulator/Kconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,11 +214,11 @@ config REGULATOR_DA9055
214214
will be called da9055-regulator.
215215

216216
config REGULATOR_DA9062
217-
tristate "Dialog Semiconductor DA9062 regulators"
217+
tristate "Dialog Semiconductor DA9061/62 regulators"
218218
depends on MFD_DA9062
219219
help
220220
Say y here to support the BUCKs and LDOs regulators found on
221-
DA9062 PMICs.
221+
DA9061 and DA9062 PMICs.
222222

223223
This driver can also be built as a module. If so, the module
224224
will be called da9062-regulator.

drivers/regulator/da9062-regulator.c

Lines changed: 291 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
* da9062-regulator.c - REGULATOR device driver for DA9062
3-
* Copyright (C) 2015 Dialog Semiconductor Ltd.
2+
* Regulator device driver for DA9061 and DA9062.
3+
* Copyright (C) 2015-2017 Dialog Semiconductor
44
*
55
* This program is free software; you can redistribute it and/or
66
* modify it under the terms of the GNU General Public License
@@ -27,6 +27,17 @@
2727
#include <linux/mfd/da9062/registers.h>
2828

2929
/* Regulator IDs */
30+
enum {
31+
DA9061_ID_BUCK1,
32+
DA9061_ID_BUCK2,
33+
DA9061_ID_BUCK3,
34+
DA9061_ID_LDO1,
35+
DA9061_ID_LDO2,
36+
DA9061_ID_LDO3,
37+
DA9061_ID_LDO4,
38+
DA9061_MAX_REGULATORS,
39+
};
40+
3041
enum {
3142
DA9062_ID_BUCK1,
3243
DA9062_ID_BUCK2,
@@ -88,15 +99,21 @@ enum {
8899

89100
/* Regulator operations */
90101

91-
/* Current limits array (in uA) BUCK1 and BUCK3.
92-
Entry indexes corresponds to register values. */
102+
/* Current limits array (in uA)
103+
* - DA9061_ID_[BUCK1|BUCK3]
104+
* - DA9062_ID_[BUCK1|BUCK2|BUCK4]
105+
* Entry indexes corresponds to register values.
106+
*/
93107
static const int da9062_buck_a_limits[] = {
94108
500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000,
95109
1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1900000, 2000000
96110
};
97111

98-
/* Current limits array (in uA) for BUCK2.
99-
Entry indexes corresponds to register values. */
112+
/* Current limits array (in uA)
113+
* - DA9061_ID_BUCK2
114+
* - DA9062_ID_BUCK3
115+
* Entry indexes corresponds to register values.
116+
*/
100117
static const int da9062_buck_b_limits[] = {
101118
1500000, 1600000, 1700000, 1800000, 1900000, 2000000, 2100000, 2200000,
102119
2300000, 2400000, 2500000, 2600000, 2700000, 2800000, 2900000, 3000000
@@ -405,8 +422,254 @@ static const struct regulator_ops da9062_ldo_ops = {
405422
.set_suspend_mode = da9062_ldo_set_suspend_mode,
406423
};
407424

408-
/* Regulator information */
409-
static const struct da9062_regulator_info local_regulator_info[] = {
425+
/* DA9061 Regulator information */
426+
static const struct da9062_regulator_info local_da9061_regulator_info[] = {
427+
{
428+
.desc.id = DA9061_ID_BUCK1,
429+
.desc.name = "DA9061 BUCK1",
430+
.desc.of_match = of_match_ptr("buck1"),
431+
.desc.regulators_node = of_match_ptr("regulators"),
432+
.desc.ops = &da9062_buck_ops,
433+
.desc.min_uV = (300) * 1000,
434+
.desc.uV_step = (10) * 1000,
435+
.desc.n_voltages = ((1570) - (300))/(10) + 1,
436+
.current_limits = da9062_buck_a_limits,
437+
.n_current_limits = ARRAY_SIZE(da9062_buck_a_limits),
438+
.desc.enable_reg = DA9062AA_BUCK1_CONT,
439+
.desc.enable_mask = DA9062AA_BUCK1_EN_MASK,
440+
.desc.vsel_reg = DA9062AA_VBUCK1_A,
441+
.desc.vsel_mask = DA9062AA_VBUCK1_A_MASK,
442+
.desc.linear_min_sel = 0,
443+
.sleep = REG_FIELD(DA9062AA_VBUCK1_A,
444+
__builtin_ffs((int)DA9062AA_BUCK1_SL_A_MASK) - 1,
445+
sizeof(unsigned int) * 8 -
446+
__builtin_clz((DA9062AA_BUCK1_SL_A_MASK)) - 1),
447+
.suspend_sleep = REG_FIELD(DA9062AA_VBUCK1_B,
448+
__builtin_ffs((int)DA9062AA_BUCK1_SL_B_MASK) - 1,
449+
sizeof(unsigned int) * 8 -
450+
__builtin_clz((DA9062AA_BUCK1_SL_B_MASK)) - 1),
451+
.suspend_vsel_reg = DA9062AA_VBUCK1_B,
452+
.mode = REG_FIELD(DA9062AA_BUCK1_CFG,
453+
__builtin_ffs((int)DA9062AA_BUCK1_MODE_MASK) - 1,
454+
sizeof(unsigned int) * 8 -
455+
__builtin_clz((DA9062AA_BUCK1_MODE_MASK)) - 1),
456+
.suspend = REG_FIELD(DA9062AA_DVC_1,
457+
__builtin_ffs((int)DA9062AA_VBUCK1_SEL_MASK) - 1,
458+
sizeof(unsigned int) * 8 -
459+
__builtin_clz((DA9062AA_VBUCK1_SEL_MASK)) - 1),
460+
.ilimit = REG_FIELD(DA9062AA_BUCK_ILIM_C,
461+
__builtin_ffs((int)DA9062AA_BUCK1_ILIM_MASK) - 1,
462+
sizeof(unsigned int) * 8 -
463+
__builtin_clz((DA9062AA_BUCK1_ILIM_MASK)) - 1),
464+
},
465+
{
466+
.desc.id = DA9061_ID_BUCK2,
467+
.desc.name = "DA9061 BUCK2",
468+
.desc.of_match = of_match_ptr("buck2"),
469+
.desc.regulators_node = of_match_ptr("regulators"),
470+
.desc.ops = &da9062_buck_ops,
471+
.desc.min_uV = (800) * 1000,
472+
.desc.uV_step = (20) * 1000,
473+
.desc.n_voltages = ((3340) - (800))/(20) + 1,
474+
.current_limits = da9062_buck_b_limits,
475+
.n_current_limits = ARRAY_SIZE(da9062_buck_b_limits),
476+
.desc.enable_reg = DA9062AA_BUCK3_CONT,
477+
.desc.enable_mask = DA9062AA_BUCK3_EN_MASK,
478+
.desc.vsel_reg = DA9062AA_VBUCK3_A,
479+
.desc.vsel_mask = DA9062AA_VBUCK3_A_MASK,
480+
.desc.linear_min_sel = 0,
481+
.sleep = REG_FIELD(DA9062AA_VBUCK3_A,
482+
__builtin_ffs((int)DA9062AA_BUCK3_SL_A_MASK) - 1,
483+
sizeof(unsigned int) * 8 -
484+
__builtin_clz((DA9062AA_BUCK3_SL_A_MASK)) - 1),
485+
.suspend_sleep = REG_FIELD(DA9062AA_VBUCK3_B,
486+
__builtin_ffs((int)DA9062AA_BUCK3_SL_B_MASK) - 1,
487+
sizeof(unsigned int) * 8 -
488+
__builtin_clz((DA9062AA_BUCK3_SL_B_MASK)) - 1),
489+
.suspend_vsel_reg = DA9062AA_VBUCK3_B,
490+
.mode = REG_FIELD(DA9062AA_BUCK3_CFG,
491+
__builtin_ffs((int)DA9062AA_BUCK3_MODE_MASK) - 1,
492+
sizeof(unsigned int) * 8 -
493+
__builtin_clz((DA9062AA_BUCK3_MODE_MASK)) - 1),
494+
.suspend = REG_FIELD(DA9062AA_DVC_1,
495+
__builtin_ffs((int)DA9062AA_VBUCK3_SEL_MASK) - 1,
496+
sizeof(unsigned int) * 8 -
497+
__builtin_clz((DA9062AA_VBUCK3_SEL_MASK)) - 1),
498+
.ilimit = REG_FIELD(DA9062AA_BUCK_ILIM_A,
499+
__builtin_ffs((int)DA9062AA_BUCK3_ILIM_MASK) - 1,
500+
sizeof(unsigned int) * 8 -
501+
__builtin_clz((DA9062AA_BUCK3_ILIM_MASK)) - 1),
502+
},
503+
{
504+
.desc.id = DA9061_ID_BUCK3,
505+
.desc.name = "DA9061 BUCK3",
506+
.desc.of_match = of_match_ptr("buck3"),
507+
.desc.regulators_node = of_match_ptr("regulators"),
508+
.desc.ops = &da9062_buck_ops,
509+
.desc.min_uV = (530) * 1000,
510+
.desc.uV_step = (10) * 1000,
511+
.desc.n_voltages = ((1800) - (530))/(10) + 1,
512+
.current_limits = da9062_buck_a_limits,
513+
.n_current_limits = ARRAY_SIZE(da9062_buck_a_limits),
514+
.desc.enable_reg = DA9062AA_BUCK4_CONT,
515+
.desc.enable_mask = DA9062AA_BUCK4_EN_MASK,
516+
.desc.vsel_reg = DA9062AA_VBUCK4_A,
517+
.desc.vsel_mask = DA9062AA_VBUCK4_A_MASK,
518+
.desc.linear_min_sel = 0,
519+
.sleep = REG_FIELD(DA9062AA_VBUCK4_A,
520+
__builtin_ffs((int)DA9062AA_BUCK4_SL_A_MASK) - 1,
521+
sizeof(unsigned int) * 8 -
522+
__builtin_clz((DA9062AA_BUCK4_SL_A_MASK)) - 1),
523+
.suspend_sleep = REG_FIELD(DA9062AA_VBUCK4_B,
524+
__builtin_ffs((int)DA9062AA_BUCK4_SL_B_MASK) - 1,
525+
sizeof(unsigned int) * 8 -
526+
__builtin_clz((DA9062AA_BUCK4_SL_B_MASK)) - 1),
527+
.suspend_vsel_reg = DA9062AA_VBUCK4_B,
528+
.mode = REG_FIELD(DA9062AA_BUCK4_CFG,
529+
__builtin_ffs((int)DA9062AA_BUCK4_MODE_MASK) - 1,
530+
sizeof(unsigned int) * 8 -
531+
__builtin_clz((DA9062AA_BUCK4_MODE_MASK)) - 1),
532+
.suspend = REG_FIELD(DA9062AA_DVC_1,
533+
__builtin_ffs((int)DA9062AA_VBUCK4_SEL_MASK) - 1,
534+
sizeof(unsigned int) * 8 -
535+
__builtin_clz((DA9062AA_VBUCK4_SEL_MASK)) - 1),
536+
.ilimit = REG_FIELD(DA9062AA_BUCK_ILIM_B,
537+
__builtin_ffs((int)DA9062AA_BUCK4_ILIM_MASK) - 1,
538+
sizeof(unsigned int) * 8 -
539+
__builtin_clz((DA9062AA_BUCK4_ILIM_MASK)) - 1),
540+
},
541+
{
542+
.desc.id = DA9061_ID_LDO1,
543+
.desc.name = "DA9061 LDO1",
544+
.desc.of_match = of_match_ptr("ldo1"),
545+
.desc.regulators_node = of_match_ptr("regulators"),
546+
.desc.ops = &da9062_ldo_ops,
547+
.desc.min_uV = (900) * 1000,
548+
.desc.uV_step = (50) * 1000,
549+
.desc.n_voltages = ((3600) - (900))/(50) + 1,
550+
.desc.enable_reg = DA9062AA_LDO1_CONT,
551+
.desc.enable_mask = DA9062AA_LDO1_EN_MASK,
552+
.desc.vsel_reg = DA9062AA_VLDO1_A,
553+
.desc.vsel_mask = DA9062AA_VLDO1_A_MASK,
554+
.desc.linear_min_sel = 0,
555+
.sleep = REG_FIELD(DA9062AA_VLDO1_A,
556+
__builtin_ffs((int)DA9062AA_LDO1_SL_A_MASK) - 1,
557+
sizeof(unsigned int) * 8 -
558+
__builtin_clz((DA9062AA_LDO1_SL_A_MASK)) - 1),
559+
.suspend_sleep = REG_FIELD(DA9062AA_VLDO1_B,
560+
__builtin_ffs((int)DA9062AA_LDO1_SL_B_MASK) - 1,
561+
sizeof(unsigned int) * 8 -
562+
__builtin_clz((DA9062AA_LDO1_SL_B_MASK)) - 1),
563+
.suspend_vsel_reg = DA9062AA_VLDO1_B,
564+
.suspend = REG_FIELD(DA9062AA_DVC_1,
565+
__builtin_ffs((int)DA9062AA_VLDO1_SEL_MASK) - 1,
566+
sizeof(unsigned int) * 8 -
567+
__builtin_clz((DA9062AA_VLDO1_SEL_MASK)) - 1),
568+
.oc_event = REG_FIELD(DA9062AA_STATUS_D,
569+
__builtin_ffs((int)DA9062AA_LDO1_ILIM_MASK) - 1,
570+
sizeof(unsigned int) * 8 -
571+
__builtin_clz((DA9062AA_LDO1_ILIM_MASK)) - 1),
572+
},
573+
{
574+
.desc.id = DA9061_ID_LDO2,
575+
.desc.name = "DA9061 LDO2",
576+
.desc.of_match = of_match_ptr("ldo2"),
577+
.desc.regulators_node = of_match_ptr("regulators"),
578+
.desc.ops = &da9062_ldo_ops,
579+
.desc.min_uV = (900) * 1000,
580+
.desc.uV_step = (50) * 1000,
581+
.desc.n_voltages = ((3600) - (600))/(50) + 1,
582+
.desc.enable_reg = DA9062AA_LDO2_CONT,
583+
.desc.enable_mask = DA9062AA_LDO2_EN_MASK,
584+
.desc.vsel_reg = DA9062AA_VLDO2_A,
585+
.desc.vsel_mask = DA9062AA_VLDO2_A_MASK,
586+
.desc.linear_min_sel = 0,
587+
.sleep = REG_FIELD(DA9062AA_VLDO2_A,
588+
__builtin_ffs((int)DA9062AA_LDO2_SL_A_MASK) - 1,
589+
sizeof(unsigned int) * 8 -
590+
__builtin_clz((DA9062AA_LDO2_SL_A_MASK)) - 1),
591+
.suspend_sleep = REG_FIELD(DA9062AA_VLDO2_B,
592+
__builtin_ffs((int)DA9062AA_LDO2_SL_B_MASK) - 1,
593+
sizeof(unsigned int) * 8 -
594+
__builtin_clz((DA9062AA_LDO2_SL_B_MASK)) - 1),
595+
.suspend_vsel_reg = DA9062AA_VLDO2_B,
596+
.suspend = REG_FIELD(DA9062AA_DVC_1,
597+
__builtin_ffs((int)DA9062AA_VLDO2_SEL_MASK) - 1,
598+
sizeof(unsigned int) * 8 -
599+
__builtin_clz((DA9062AA_VLDO2_SEL_MASK)) - 1),
600+
.oc_event = REG_FIELD(DA9062AA_STATUS_D,
601+
__builtin_ffs((int)DA9062AA_LDO2_ILIM_MASK) - 1,
602+
sizeof(unsigned int) * 8 -
603+
__builtin_clz((DA9062AA_LDO2_ILIM_MASK)) - 1),
604+
},
605+
{
606+
.desc.id = DA9061_ID_LDO3,
607+
.desc.name = "DA9061 LDO3",
608+
.desc.of_match = of_match_ptr("ldo3"),
609+
.desc.regulators_node = of_match_ptr("regulators"),
610+
.desc.ops = &da9062_ldo_ops,
611+
.desc.min_uV = (900) * 1000,
612+
.desc.uV_step = (50) * 1000,
613+
.desc.n_voltages = ((3600) - (900))/(50) + 1,
614+
.desc.enable_reg = DA9062AA_LDO3_CONT,
615+
.desc.enable_mask = DA9062AA_LDO3_EN_MASK,
616+
.desc.vsel_reg = DA9062AA_VLDO3_A,
617+
.desc.vsel_mask = DA9062AA_VLDO3_A_MASK,
618+
.desc.linear_min_sel = 0,
619+
.sleep = REG_FIELD(DA9062AA_VLDO3_A,
620+
__builtin_ffs((int)DA9062AA_LDO3_SL_A_MASK) - 1,
621+
sizeof(unsigned int) * 8 -
622+
__builtin_clz((DA9062AA_LDO3_SL_A_MASK)) - 1),
623+
.suspend_sleep = REG_FIELD(DA9062AA_VLDO3_B,
624+
__builtin_ffs((int)DA9062AA_LDO3_SL_B_MASK) - 1,
625+
sizeof(unsigned int) * 8 -
626+
__builtin_clz((DA9062AA_LDO3_SL_B_MASK)) - 1),
627+
.suspend_vsel_reg = DA9062AA_VLDO3_B,
628+
.suspend = REG_FIELD(DA9062AA_DVC_1,
629+
__builtin_ffs((int)DA9062AA_VLDO3_SEL_MASK) - 1,
630+
sizeof(unsigned int) * 8 -
631+
__builtin_clz((DA9062AA_VLDO3_SEL_MASK)) - 1),
632+
.oc_event = REG_FIELD(DA9062AA_STATUS_D,
633+
__builtin_ffs((int)DA9062AA_LDO3_ILIM_MASK) - 1,
634+
sizeof(unsigned int) * 8 -
635+
__builtin_clz((DA9062AA_LDO3_ILIM_MASK)) - 1),
636+
},
637+
{
638+
.desc.id = DA9061_ID_LDO4,
639+
.desc.name = "DA9061 LDO4",
640+
.desc.of_match = of_match_ptr("ldo4"),
641+
.desc.regulators_node = of_match_ptr("regulators"),
642+
.desc.ops = &da9062_ldo_ops,
643+
.desc.min_uV = (900) * 1000,
644+
.desc.uV_step = (50) * 1000,
645+
.desc.n_voltages = ((3600) - (900))/(50) + 1,
646+
.desc.enable_reg = DA9062AA_LDO4_CONT,
647+
.desc.enable_mask = DA9062AA_LDO4_EN_MASK,
648+
.desc.vsel_reg = DA9062AA_VLDO4_A,
649+
.desc.vsel_mask = DA9062AA_VLDO4_A_MASK,
650+
.desc.linear_min_sel = 0,
651+
.sleep = REG_FIELD(DA9062AA_VLDO4_A,
652+
__builtin_ffs((int)DA9062AA_LDO4_SL_A_MASK) - 1,
653+
sizeof(unsigned int) * 8 -
654+
__builtin_clz((DA9062AA_LDO4_SL_A_MASK)) - 1),
655+
.suspend_sleep = REG_FIELD(DA9062AA_VLDO4_B,
656+
__builtin_ffs((int)DA9062AA_LDO4_SL_B_MASK) - 1,
657+
sizeof(unsigned int) * 8 -
658+
__builtin_clz((DA9062AA_LDO4_SL_B_MASK)) - 1),
659+
.suspend_vsel_reg = DA9062AA_VLDO4_B,
660+
.suspend = REG_FIELD(DA9062AA_DVC_1,
661+
__builtin_ffs((int)DA9062AA_VLDO4_SEL_MASK) - 1,
662+
sizeof(unsigned int) * 8 -
663+
__builtin_clz((DA9062AA_VLDO4_SEL_MASK)) - 1),
664+
.oc_event = REG_FIELD(DA9062AA_STATUS_D,
665+
__builtin_ffs((int)DA9062AA_LDO4_ILIM_MASK) - 1,
666+
sizeof(unsigned int) * 8 -
667+
__builtin_clz((DA9062AA_LDO4_ILIM_MASK)) - 1),
668+
},
669+
};
670+
671+
/* DA9062 Regulator information */
672+
static const struct da9062_regulator_info local_da9062_regulator_info[] = {
410673
{
411674
.desc.id = DA9062_ID_BUCK1,
412675
.desc.name = "DA9062 BUCK1",
@@ -727,25 +990,41 @@ static int da9062_regulator_probe(struct platform_device *pdev)
727990
struct da9062_regulators *regulators;
728991
struct da9062_regulator *regl;
729992
struct regulator_config config = { };
993+
const struct da9062_regulator_info *rinfo;
730994
int irq, n, ret;
731995
size_t size;
996+
int max_regulators;
997+
998+
switch (chip->chip_type) {
999+
case COMPAT_TYPE_DA9061:
1000+
max_regulators = DA9061_MAX_REGULATORS;
1001+
rinfo = local_da9061_regulator_info;
1002+
break;
1003+
case COMPAT_TYPE_DA9062:
1004+
max_regulators = DA9062_MAX_REGULATORS;
1005+
rinfo = local_da9062_regulator_info;
1006+
break;
1007+
default:
1008+
dev_err(chip->dev, "Unrecognised chip type\n");
1009+
return -ENODEV;
1010+
}
7321011

7331012
/* Allocate memory required by usable regulators */
7341013
size = sizeof(struct da9062_regulators) +
735-
DA9062_MAX_REGULATORS * sizeof(struct da9062_regulator);
1014+
max_regulators * sizeof(struct da9062_regulator);
7361015
regulators = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
7371016
if (!regulators)
7381017
return -ENOMEM;
7391018

740-
regulators->n_regulators = DA9062_MAX_REGULATORS;
1019+
regulators->n_regulators = max_regulators;
7411020
platform_set_drvdata(pdev, regulators);
7421021

7431022
n = 0;
7441023
while (n < regulators->n_regulators) {
7451024
/* Initialise regulator structure */
7461025
regl = &regulators->regulator[n];
7471026
regl->hw = chip;
748-
regl->info = &local_regulator_info[n];
1027+
regl->info = &rinfo[n];
7491028
regl->desc = regl->info->desc;
7501029
regl->desc.type = REGULATOR_VOLTAGE;
7511030
regl->desc.owner = THIS_MODULE;
@@ -836,6 +1115,6 @@ module_exit(da9062_regulator_cleanup);
8361115

8371116
/* Module information */
8381117
MODULE_AUTHOR("S Twiss <[email protected]>");
839-
MODULE_DESCRIPTION("REGULATOR device driver for Dialog DA9062");
1118+
MODULE_DESCRIPTION("REGULATOR device driver for Dialog DA9062 and DA9061");
8401119
MODULE_LICENSE("GPL");
8411120
MODULE_ALIAS("platform:da9062-regulators");

0 commit comments

Comments
 (0)