regulator: da9063: implement setter for voltage monitoring
authorBenjamin Bara <benjamin.bara@skidata.com>
Wed, 5 Apr 2023 17:14:35 +0000 (19:14 +0200)
committerMark Brown <broonie@kernel.org>
Wed, 12 Apr 2023 11:52:10 +0000 (12:52 +0100)
Allow to en- and disable voltage monitoring from the device tree.
Consider that the da9063 only monitors under- *and* over-voltage
together, so both must be set to the same severity and value.

Reviewed-by: Adam Ward <DLG-Adam.Ward.opensource@dm.renesas.com>
Signed-off-by: Benjamin Bara <benjamin.bara@skidata.com>
Link: https://lore.kernel.org/r/20230403-da9063-disable-unused-v3-2-cc4dc698864c@skidata.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/regulator/da9063-regulator.c

index 7d204b1d6b3fa582be08b225d44b3790a1b51fe3..c5dd77be558b6becf2ee37285e7590037e46e1fc 100644 (file)
@@ -207,6 +207,24 @@ static const unsigned int da9063_bmem_bio_merged_limits[] = {
        4600000, 4800000, 5000000, 5200000, 5400000, 5600000, 5800000, 6000000
 };
 
+static int da9063_set_xvp(struct regulator_dev *rdev, int lim_uV, int severity, bool enable)
+{
+       struct da9063_regulator *regl = rdev_get_drvdata(rdev);
+       struct device *dev = regl->hw->dev;
+
+       dev_dbg(dev, "%s: lim: %d, sev: %d, en: %d\n", regl->desc.name, lim_uV, severity, enable);
+
+       /*
+        * only support enable and disable.
+        * the da9063 offers a GPIO (GP_FB2) which is unasserted if an XV happens.
+        * therefore ignore severity here, as there might be handlers in hardware.
+        */
+       if (lim_uV)
+               return -EINVAL;
+
+       return regmap_field_write(regl->vmon, enable ? 1 : 0);
+}
+
 static int da9063_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
 {
        struct da9063_regulator *regl = rdev_get_drvdata(rdev);
@@ -545,37 +563,41 @@ static int da9063_buck_get_current_limit(struct regulator_dev *rdev)
 }
 
 static const struct regulator_ops da9063_buck_ops = {
-       .enable                 = regulator_enable_regmap,
-       .disable                = regulator_disable_regmap,
-       .is_enabled             = regulator_is_enabled_regmap,
-       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
-       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
-       .list_voltage           = regulator_list_voltage_linear,
-       .set_current_limit      = da9063_buck_set_current_limit,
-       .get_current_limit      = da9063_buck_get_current_limit,
-       .set_mode               = da9063_buck_set_mode,
-       .get_mode               = da9063_buck_get_mode,
-       .get_status             = da9063_buck_get_status,
-       .set_suspend_voltage    = da9063_set_suspend_voltage,
-       .set_suspend_enable     = da9063_suspend_enable,
-       .set_suspend_disable    = da9063_suspend_disable,
-       .set_suspend_mode       = da9063_buck_set_suspend_mode,
+       .enable                         = regulator_enable_regmap,
+       .disable                        = regulator_disable_regmap,
+       .is_enabled                     = regulator_is_enabled_regmap,
+       .get_voltage_sel                = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel                = regulator_set_voltage_sel_regmap,
+       .list_voltage                   = regulator_list_voltage_linear,
+       .set_current_limit              = da9063_buck_set_current_limit,
+       .get_current_limit              = da9063_buck_get_current_limit,
+       .set_mode                       = da9063_buck_set_mode,
+       .get_mode                       = da9063_buck_get_mode,
+       .get_status                     = da9063_buck_get_status,
+       .set_suspend_voltage            = da9063_set_suspend_voltage,
+       .set_suspend_enable             = da9063_suspend_enable,
+       .set_suspend_disable            = da9063_suspend_disable,
+       .set_suspend_mode               = da9063_buck_set_suspend_mode,
+       .set_over_voltage_protection    = da9063_set_xvp,
+       .set_under_voltage_protection   = da9063_set_xvp,
 };
 
 static const struct regulator_ops da9063_ldo_ops = {
-       .enable                 = regulator_enable_regmap,
-       .disable                = regulator_disable_regmap,
-       .is_enabled             = regulator_is_enabled_regmap,
-       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
-       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
-       .list_voltage           = regulator_list_voltage_linear,
-       .set_mode               = da9063_ldo_set_mode,
-       .get_mode               = da9063_ldo_get_mode,
-       .get_status             = da9063_ldo_get_status,
-       .set_suspend_voltage    = da9063_set_suspend_voltage,
-       .set_suspend_enable     = da9063_suspend_enable,
-       .set_suspend_disable    = da9063_suspend_disable,
-       .set_suspend_mode       = da9063_ldo_set_suspend_mode,
+       .enable                         = regulator_enable_regmap,
+       .disable                        = regulator_disable_regmap,
+       .is_enabled                     = regulator_is_enabled_regmap,
+       .get_voltage_sel                = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel                = regulator_set_voltage_sel_regmap,
+       .list_voltage                   = regulator_list_voltage_linear,
+       .set_mode                       = da9063_ldo_set_mode,
+       .get_mode                       = da9063_ldo_get_mode,
+       .get_status                     = da9063_ldo_get_status,
+       .set_suspend_voltage            = da9063_set_suspend_voltage,
+       .set_suspend_enable             = da9063_suspend_enable,
+       .set_suspend_disable            = da9063_suspend_disable,
+       .set_suspend_mode               = da9063_ldo_set_suspend_mode,
+       .set_over_voltage_protection    = da9063_set_xvp,
+       .set_under_voltage_protection   = da9063_set_xvp,
 };
 
 /* Info of regulators for DA9063 */
@@ -749,6 +771,41 @@ static const struct regulator_init_data *da9063_get_regulator_initdata(
        return NULL;
 }
 
+static int da9063_check_xvp_constraints(struct regulator_config *config)
+{
+       struct da9063_regulator *regl = config->driver_data;
+       const struct regulation_constraints *constr = &config->init_data->constraints;
+       const struct notification_limit *uv_l = &constr->under_voltage_limits;
+       const struct notification_limit *ov_l = &constr->over_voltage_limits;
+
+       /* make sure that only one severity is used to clarify if unchanged, enabled or disabled */
+       if ((!!uv_l->prot + !!uv_l->err + !!uv_l->warn) > 1) {
+               dev_err(config->dev, "%s: at most one voltage monitoring severity allowed!\n",
+                       regl->desc.name);
+               return -EINVAL;
+       }
+
+       /* make sure that UV and OV monitoring is set to the same severity and value */
+       if (uv_l->prot != ov_l->prot) {
+               dev_err(config->dev,
+                       "%s: protection-microvolt: value must be equal for uv and ov!\n",
+                       regl->desc.name);
+               return -EINVAL;
+       }
+       if (uv_l->err != ov_l->err) {
+               dev_err(config->dev, "%s: error-microvolt: value must be equal for uv and ov!\n",
+                       regl->desc.name);
+               return -EINVAL;
+       }
+       if (uv_l->warn != ov_l->warn) {
+               dev_err(config->dev, "%s: warn-microvolt: value must be equal for uv and ov!\n",
+                       regl->desc.name);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static struct of_regulator_match da9063_matches[] = {
        [DA9063_ID_BCORE1]           = { .name = "bcore1"           },
        [DA9063_ID_BCORE2]           = { .name = "bcore2"           },
@@ -970,6 +1027,11 @@ static int da9063_regulator_probe(struct platform_device *pdev)
                if (da9063_reg_matches)
                        config.of_node = da9063_reg_matches[id].of_node;
                config.regmap = da9063->regmap;
+
+               ret = da9063_check_xvp_constraints(&config);
+               if (ret)
+                       return ret;
+
                regl->rdev = devm_regulator_register(&pdev->dev, &regl->desc,
                                                     &config);
                if (IS_ERR(regl->rdev)) {