Skip to content

Commit d877cad

Browse files
committed
regulator: da9063: disable unused voltage monitors
Merge series from Benjamin Bara <[email protected]>: Follow-up for my initial patch regarding the disabling of unused voltage monitors. We use the PWR_OK functionality, which asserts GP_FB2 if every monitored voltage is in range. This patch should provide the possibility to deactivate a voltage monitor from the DT if the regulator might be disabled during run time. For this purpose, the regulator notification support is used: https://lore.kernel.org/all/[email protected]/
2 parents c4a413e + 0271b61 commit d877cad

File tree

3 files changed

+157
-30
lines changed

3 files changed

+157
-30
lines changed

Documentation/devicetree/bindings/mfd/dlg,da9063.yaml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ maintainers:
1212
description: |
1313
For device-tree bindings of other sub-modules refer to the binding documents
1414
under the respective sub-system directories.
15+
Using regulator-{uv,ov}-{warn,error,protection}-microvolt requires special
16+
handling: First, when GP_FB2 is used, it must be ensured that there is no
17+
moment where all voltage monitors are disabled. Next, as da9063 only supports
18+
UV *and* OV monitoring, both must be set to the same severity and value
19+
(0: disable, 1: enable).
1520
1621
properties:
1722
compatible:
@@ -121,11 +126,19 @@ examples:
121126
regulator-max-microamp = <2000000>;
122127
regulator-boot-on;
123128
};
129+
ldo6 {
130+
/* UNUSED */
131+
regulator-name = "LDO_6";
132+
regulator-uv-protection-microvolt = <0>;
133+
regulator-ov-protection-microvolt = <0>;
134+
};
124135
ldo11 {
125136
regulator-name = "LDO_11";
126137
regulator-min-microvolt = <900000>;
127-
regulator-max-microvolt = <3600000>;
128-
regulator-boot-on;
138+
regulator-max-microvolt = <900000>;
139+
regulator-uv-protection-microvolt = <1>;
140+
regulator-ov-protection-microvolt = <1>;
141+
regulator-always-on;
129142
};
130143
};
131144
};

drivers/regulator/da9063-regulator.c

Lines changed: 119 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ struct da9063_regulator_info {
8383

8484
/* DA9063 event detection bit */
8585
struct reg_field oc_event;
86+
87+
/* DA9063 voltage monitor bit */
88+
struct reg_field vmon;
8689
};
8790

8891
/* Macros for LDO */
@@ -148,6 +151,7 @@ struct da9063_regulator {
148151
struct regmap_field *suspend;
149152
struct regmap_field *sleep;
150153
struct regmap_field *suspend_sleep;
154+
struct regmap_field *vmon;
151155
};
152156

153157
/* Encapsulates all information for the regulators driver */
@@ -203,6 +207,24 @@ static const unsigned int da9063_bmem_bio_merged_limits[] = {
203207
4600000, 4800000, 5000000, 5200000, 5400000, 5600000, 5800000, 6000000
204208
};
205209

210+
static int da9063_set_xvp(struct regulator_dev *rdev, int lim_uV, int severity, bool enable)
211+
{
212+
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
213+
struct device *dev = regl->hw->dev;
214+
215+
dev_dbg(dev, "%s: lim: %d, sev: %d, en: %d\n", regl->desc.name, lim_uV, severity, enable);
216+
217+
/*
218+
* only support enable and disable.
219+
* the da9063 offers a GPIO (GP_FB2) which is unasserted if an XV happens.
220+
* therefore ignore severity here, as there might be handlers in hardware.
221+
*/
222+
if (lim_uV)
223+
return -EINVAL;
224+
225+
return regmap_field_write(regl->vmon, enable ? 1 : 0);
226+
}
227+
206228
static int da9063_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
207229
{
208230
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
@@ -541,37 +563,41 @@ static int da9063_buck_get_current_limit(struct regulator_dev *rdev)
541563
}
542564

543565
static const struct regulator_ops da9063_buck_ops = {
544-
.enable = regulator_enable_regmap,
545-
.disable = regulator_disable_regmap,
546-
.is_enabled = regulator_is_enabled_regmap,
547-
.get_voltage_sel = regulator_get_voltage_sel_regmap,
548-
.set_voltage_sel = regulator_set_voltage_sel_regmap,
549-
.list_voltage = regulator_list_voltage_linear,
550-
.set_current_limit = da9063_buck_set_current_limit,
551-
.get_current_limit = da9063_buck_get_current_limit,
552-
.set_mode = da9063_buck_set_mode,
553-
.get_mode = da9063_buck_get_mode,
554-
.get_status = da9063_buck_get_status,
555-
.set_suspend_voltage = da9063_set_suspend_voltage,
556-
.set_suspend_enable = da9063_suspend_enable,
557-
.set_suspend_disable = da9063_suspend_disable,
558-
.set_suspend_mode = da9063_buck_set_suspend_mode,
566+
.enable = regulator_enable_regmap,
567+
.disable = regulator_disable_regmap,
568+
.is_enabled = regulator_is_enabled_regmap,
569+
.get_voltage_sel = regulator_get_voltage_sel_regmap,
570+
.set_voltage_sel = regulator_set_voltage_sel_regmap,
571+
.list_voltage = regulator_list_voltage_linear,
572+
.set_current_limit = da9063_buck_set_current_limit,
573+
.get_current_limit = da9063_buck_get_current_limit,
574+
.set_mode = da9063_buck_set_mode,
575+
.get_mode = da9063_buck_get_mode,
576+
.get_status = da9063_buck_get_status,
577+
.set_suspend_voltage = da9063_set_suspend_voltage,
578+
.set_suspend_enable = da9063_suspend_enable,
579+
.set_suspend_disable = da9063_suspend_disable,
580+
.set_suspend_mode = da9063_buck_set_suspend_mode,
581+
.set_over_voltage_protection = da9063_set_xvp,
582+
.set_under_voltage_protection = da9063_set_xvp,
559583
};
560584

561585
static const struct regulator_ops da9063_ldo_ops = {
562-
.enable = regulator_enable_regmap,
563-
.disable = regulator_disable_regmap,
564-
.is_enabled = regulator_is_enabled_regmap,
565-
.get_voltage_sel = regulator_get_voltage_sel_regmap,
566-
.set_voltage_sel = regulator_set_voltage_sel_regmap,
567-
.list_voltage = regulator_list_voltage_linear,
568-
.set_mode = da9063_ldo_set_mode,
569-
.get_mode = da9063_ldo_get_mode,
570-
.get_status = da9063_ldo_get_status,
571-
.set_suspend_voltage = da9063_set_suspend_voltage,
572-
.set_suspend_enable = da9063_suspend_enable,
573-
.set_suspend_disable = da9063_suspend_disable,
574-
.set_suspend_mode = da9063_ldo_set_suspend_mode,
586+
.enable = regulator_enable_regmap,
587+
.disable = regulator_disable_regmap,
588+
.is_enabled = regulator_is_enabled_regmap,
589+
.get_voltage_sel = regulator_get_voltage_sel_regmap,
590+
.set_voltage_sel = regulator_set_voltage_sel_regmap,
591+
.list_voltage = regulator_list_voltage_linear,
592+
.set_mode = da9063_ldo_set_mode,
593+
.get_mode = da9063_ldo_get_mode,
594+
.get_status = da9063_ldo_get_status,
595+
.set_suspend_voltage = da9063_set_suspend_voltage,
596+
.set_suspend_enable = da9063_suspend_enable,
597+
.set_suspend_disable = da9063_suspend_disable,
598+
.set_suspend_mode = da9063_ldo_set_suspend_mode,
599+
.set_over_voltage_protection = da9063_set_xvp,
600+
.set_under_voltage_protection = da9063_set_xvp,
575601
};
576602

577603
/* Info of regulators for DA9063 */
@@ -581,91 +607,110 @@ static const struct da9063_regulator_info da9063_regulator_info[] = {
581607
da9063_buck_a_limits,
582608
DA9063_REG_BUCK_ILIM_C, DA9063_BCORE1_ILIM_MASK),
583609
DA9063_BUCK_COMMON_FIELDS(BCORE1),
610+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_4, DA9063_BCORE1_MON_EN),
584611
},
585612
{
586613
DA9063_BUCK(DA9063, BCORE2, 300, 10, 1570,
587614
da9063_buck_a_limits,
588615
DA9063_REG_BUCK_ILIM_C, DA9063_BCORE2_ILIM_MASK),
589616
DA9063_BUCK_COMMON_FIELDS(BCORE2),
617+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_4, DA9063_BCORE2_MON_EN),
590618
},
591619
{
592620
DA9063_BUCK(DA9063, BPRO, 530, 10, 1800,
593621
da9063_buck_a_limits,
594622
DA9063_REG_BUCK_ILIM_B, DA9063_BPRO_ILIM_MASK),
595623
DA9063_BUCK_COMMON_FIELDS(BPRO),
624+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_4, DA9063_BPRO_MON_EN),
596625
},
597626
{
598627
DA9063_BUCK(DA9063, BMEM, 800, 20, 3340,
599628
da9063_buck_b_limits,
600629
DA9063_REG_BUCK_ILIM_A, DA9063_BMEM_ILIM_MASK),
601630
DA9063_BUCK_COMMON_FIELDS(BMEM),
631+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_4, DA9063_BMEM_MON_EN),
602632
},
603633
{
604634
DA9063_BUCK(DA9063, BIO, 800, 20, 3340,
605635
da9063_buck_b_limits,
606636
DA9063_REG_BUCK_ILIM_A, DA9063_BIO_ILIM_MASK),
607637
DA9063_BUCK_COMMON_FIELDS(BIO),
638+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_4, DA9063_BIO_MON_EN),
608639
},
609640
{
610641
DA9063_BUCK(DA9063, BPERI, 800, 20, 3340,
611642
da9063_buck_b_limits,
612643
DA9063_REG_BUCK_ILIM_B, DA9063_BPERI_ILIM_MASK),
613644
DA9063_BUCK_COMMON_FIELDS(BPERI),
645+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_4, DA9063_BPERI_MON_EN),
614646
},
615647
{
616648
DA9063_BUCK(DA9063, BCORES_MERGED, 300, 10, 1570,
617649
da9063_bcores_merged_limits,
618650
DA9063_REG_BUCK_ILIM_C, DA9063_BCORE1_ILIM_MASK),
619651
/* BCORES_MERGED uses the same register fields as BCORE1 */
620652
DA9063_BUCK_COMMON_FIELDS(BCORE1),
653+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_4, DA9063_BCORE1_MON_EN),
621654
},
622655
{
623656
DA9063_BUCK(DA9063, BMEM_BIO_MERGED, 800, 20, 3340,
624657
da9063_bmem_bio_merged_limits,
625658
DA9063_REG_BUCK_ILIM_A, DA9063_BMEM_ILIM_MASK),
626659
/* BMEM_BIO_MERGED uses the same register fields as BMEM */
627660
DA9063_BUCK_COMMON_FIELDS(BMEM),
661+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_4, DA9063_BMEM_MON_EN),
628662
},
629663
{
630664
DA9063_LDO(DA9063, LDO3, 900, 20, 3440),
631665
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO3_LIM),
666+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_2, DA9063_LDO3_MON_EN),
632667
},
633668
{
634669
DA9063_LDO(DA9063, LDO7, 900, 50, 3600),
635670
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO7_LIM),
671+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_2, DA9063_LDO7_MON_EN),
636672
},
637673
{
638674
DA9063_LDO(DA9063, LDO8, 900, 50, 3600),
639675
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO8_LIM),
676+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_2, DA9063_LDO8_MON_EN),
640677
},
641678
{
642679
DA9063_LDO(DA9063, LDO9, 950, 50, 3600),
680+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_3, DA9063_LDO9_MON_EN),
643681
},
644682
{
645683
DA9063_LDO(DA9063, LDO11, 900, 50, 3600),
646684
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO11_LIM),
685+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_3, DA9063_LDO11_MON_EN),
647686
},
648687

649688
/* The following LDOs are present only on DA9063, not on DA9063L */
650689
{
651690
DA9063_LDO(DA9063, LDO1, 600, 20, 1860),
691+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_2, DA9063_LDO1_MON_EN),
652692
},
653693
{
654694
DA9063_LDO(DA9063, LDO2, 600, 20, 1860),
695+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_2, DA9063_LDO2_MON_EN),
655696
},
656697
{
657698
DA9063_LDO(DA9063, LDO4, 900, 20, 3440),
658699
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO4_LIM),
700+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_2, DA9063_LDO4_MON_EN),
659701
},
660702
{
661703
DA9063_LDO(DA9063, LDO5, 900, 50, 3600),
704+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_2, DA9063_LDO5_MON_EN),
662705
},
663706
{
664707
DA9063_LDO(DA9063, LDO6, 900, 50, 3600),
708+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_2, DA9063_LDO6_MON_EN),
665709
},
666710

667711
{
668712
DA9063_LDO(DA9063, LDO10, 900, 50, 3600),
713+
.vmon = BFIELD(DA9063_BB_REG_MON_REG_3, DA9063_LDO10_MON_EN),
669714
},
670715
};
671716

@@ -726,6 +771,41 @@ static const struct regulator_init_data *da9063_get_regulator_initdata(
726771
return NULL;
727772
}
728773

774+
static int da9063_check_xvp_constraints(struct regulator_config *config)
775+
{
776+
struct da9063_regulator *regl = config->driver_data;
777+
const struct regulation_constraints *constr = &config->init_data->constraints;
778+
const struct notification_limit *uv_l = &constr->under_voltage_limits;
779+
const struct notification_limit *ov_l = &constr->over_voltage_limits;
780+
781+
/* make sure that only one severity is used to clarify if unchanged, enabled or disabled */
782+
if ((!!uv_l->prot + !!uv_l->err + !!uv_l->warn) > 1) {
783+
dev_err(config->dev, "%s: at most one voltage monitoring severity allowed!\n",
784+
regl->desc.name);
785+
return -EINVAL;
786+
}
787+
788+
/* make sure that UV and OV monitoring is set to the same severity and value */
789+
if (uv_l->prot != ov_l->prot) {
790+
dev_err(config->dev,
791+
"%s: protection-microvolt: value must be equal for uv and ov!\n",
792+
regl->desc.name);
793+
return -EINVAL;
794+
}
795+
if (uv_l->err != ov_l->err) {
796+
dev_err(config->dev, "%s: error-microvolt: value must be equal for uv and ov!\n",
797+
regl->desc.name);
798+
return -EINVAL;
799+
}
800+
if (uv_l->warn != ov_l->warn) {
801+
dev_err(config->dev, "%s: warn-microvolt: value must be equal for uv and ov!\n",
802+
regl->desc.name);
803+
return -EINVAL;
804+
}
805+
806+
return 0;
807+
}
808+
729809
static struct of_regulator_match da9063_matches[] = {
730810
[DA9063_ID_BCORE1] = { .name = "bcore1" },
731811
[DA9063_ID_BCORE2] = { .name = "bcore2" },
@@ -932,6 +1012,12 @@ static int da9063_regulator_probe(struct platform_device *pdev)
9321012
if (IS_ERR(regl->suspend_sleep))
9331013
return PTR_ERR(regl->suspend_sleep);
9341014
}
1015+
if (regl->info->vmon.reg) {
1016+
regl->vmon = devm_regmap_field_alloc(&pdev->dev,
1017+
da9063->regmap, regl->info->vmon);
1018+
if (IS_ERR(regl->vmon))
1019+
return PTR_ERR(regl->vmon);
1020+
}
9351021

9361022
/* Register regulator */
9371023
memset(&config, 0, sizeof(config));
@@ -941,6 +1027,11 @@ static int da9063_regulator_probe(struct platform_device *pdev)
9411027
if (da9063_reg_matches)
9421028
config.of_node = da9063_reg_matches[id].of_node;
9431029
config.regmap = da9063->regmap;
1030+
1031+
ret = da9063_check_xvp_constraints(&config);
1032+
if (ret)
1033+
return ret;
1034+
9441035
regl->rdev = devm_regulator_register(&pdev->dev, &regl->desc,
9451036
&config);
9461037
if (IS_ERR(regl->rdev)) {

include/linux/mfd/da9063/registers.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,29 @@
10401040
/* DA9063_REG_CONFIG_J (addr=0x10F) */
10411041
#define DA9063_TWOWIRE_TO 0x40
10421042

1043+
/* DA9063_REG_MON_REG_2 (addr=0x115) */
1044+
#define DA9063_LDO1_MON_EN 0x01
1045+
#define DA9063_LDO2_MON_EN 0x02
1046+
#define DA9063_LDO3_MON_EN 0x04
1047+
#define DA9063_LDO4_MON_EN 0x08
1048+
#define DA9063_LDO5_MON_EN 0x10
1049+
#define DA9063_LDO6_MON_EN 0x20
1050+
#define DA9063_LDO7_MON_EN 0x40
1051+
#define DA9063_LDO8_MON_EN 0x80
1052+
1053+
/* DA9063_REG_MON_REG_3 (addr=0x116) */
1054+
#define DA9063_LDO9_MON_EN 0x01
1055+
#define DA9063_LDO10_MON_EN 0x02
1056+
#define DA9063_LDO11_MON_EN 0x04
1057+
1058+
/* DA9063_REG_MON_REG_4 (addr=0x117) */
1059+
#define DA9063_BCORE1_MON_EN 0x04
1060+
#define DA9063_BCORE2_MON_EN 0x08
1061+
#define DA9063_BPRO_MON_EN 0x10
1062+
#define DA9063_BIO_MON_EN 0x20
1063+
#define DA9063_BMEM_MON_EN 0x40
1064+
#define DA9063_BPERI_MON_EN 0x80
1065+
10431066
/* DA9063_REG_MON_REG_5 (addr=0x116) */
10441067
#define DA9063_MON_A8_IDX_MASK 0x07
10451068
#define DA9063_MON_A8_IDX_NONE 0x00

0 commit comments

Comments
 (0)