]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
regulator: pca9450: Add support for mode operations
authorMartijn de Gouw <martijn.de.gouw@prodrive-technologies.com>
Sun, 25 May 2025 07:18:21 +0000 (09:18 +0200)
committerMark Brown <broonie@kernel.org>
Sun, 8 Jun 2025 22:35:16 +0000 (23:35 +0100)
Make the PWM mode on the buck controllers configurable from
devicetree. Some boards require forced PWM mode to keep the supply
ripple within acceptable limits under light load conditions.

Signed-off-by: Martijn de Gouw <martijn.de.gouw@prodrive-technologies.com>
Link: https://patch.msgid.link/20250525071823.819342-2-martijn.de.gouw@prodrive-technologies.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/regulator/pca9450-regulator.c

index 14d19a6d665573e56877784c33c3490b8f41d755..f6faf14a9c536093c7b4576272c6f94137707a3d 100644 (file)
 #include <linux/regulator/machine.h>
 #include <linux/regulator/of_regulator.h>
 #include <linux/regulator/pca9450.h>
+#include <dt-bindings/regulator/nxp,pca9450-regulator.h>
+
+static unsigned int pca9450_buck_get_mode(struct regulator_dev *rdev);
+static int pca9450_buck_set_mode(struct regulator_dev *rdev, unsigned int mode);
 
 struct pc9450_dvs_config {
        unsigned int run_reg; /* dvs0 */
        unsigned int run_mask;
        unsigned int standby_reg; /* dvs1 */
        unsigned int standby_mask;
+       unsigned int mode_reg; /* ctrl */
+       unsigned int mode_mask;
 };
 
 struct pca9450_regulator_desc {
@@ -80,6 +86,8 @@ static const struct regulator_ops pca9450_dvs_buck_regulator_ops = {
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
        .set_voltage_time_sel = regulator_set_voltage_time_sel,
        .set_ramp_delay = regulator_set_ramp_delay_regmap,
+       .set_mode = pca9450_buck_set_mode,
+       .get_mode = pca9450_buck_get_mode,
 };
 
 static const struct regulator_ops pca9450_buck_regulator_ops = {
@@ -90,6 +98,8 @@ static const struct regulator_ops pca9450_buck_regulator_ops = {
        .set_voltage_sel = regulator_set_voltage_sel_regmap,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
        .set_voltage_time_sel = regulator_set_voltage_time_sel,
+       .set_mode = pca9450_buck_set_mode,
+       .get_mode = pca9450_buck_get_mode,
 };
 
 static const struct regulator_ops pca9450_ldo_regulator_ops = {
@@ -285,7 +295,64 @@ static int pca9450_set_dvs_levels(struct device_node *np,
        return ret;
 }
 
-static const struct pca9450_regulator_desc pca9450a_regulators[] = {
+static inline unsigned int pca9450_map_mode(unsigned int mode)
+{
+       switch (mode) {
+       case PCA9450_BUCK_MODE_AUTO:
+               return REGULATOR_MODE_NORMAL;
+       case PCA9450_BUCK_MODE_FORCE_PWM:
+               return REGULATOR_MODE_FAST;
+       default:
+               return REGULATOR_MODE_INVALID;
+       }
+}
+
+static int pca9450_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+       struct pca9450_regulator_desc *desc = container_of(rdev->desc,
+                                       struct pca9450_regulator_desc, desc);
+       const struct pc9450_dvs_config *dvs = &desc->dvs;
+       int val;
+
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               val = dvs->mode_mask;
+               break;
+       case REGULATOR_MODE_NORMAL:
+               val = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       dev_dbg(&rdev->dev, "pca9450 buck set_mode %#x, %#x, %#x\n",
+               dvs->mode_reg, dvs->mode_mask, val);
+
+       return regmap_update_bits(rdev->regmap, dvs->mode_reg,
+                                 dvs->mode_mask, val);
+}
+
+static unsigned int pca9450_buck_get_mode(struct regulator_dev *rdev)
+{
+       struct pca9450_regulator_desc *desc = container_of(rdev->desc,
+                                       struct pca9450_regulator_desc, desc);
+       const struct pc9450_dvs_config *dvs = &desc->dvs;
+       int ret = 0, regval;
+
+       ret = regmap_read(rdev->regmap, dvs->mode_reg, &regval);
+       if (ret != 0) {
+               dev_err(&rdev->dev,
+                       "Failed to get pca9450 buck mode: %d\n", ret);
+               return ret;
+       }
+
+       if ((regval & dvs->mode_mask) == dvs->mode_mask)
+               return REGULATOR_MODE_FAST;
+
+       return REGULATOR_MODE_NORMAL;
+}
+
+static struct pca9450_regulator_desc pca9450a_regulators[] = {
        {
                .desc = {
                        .name = "buck1",
@@ -308,12 +375,15 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = {
                        .enable_val = BUCK_ENMODE_ONREQ,
                        .owner = THIS_MODULE,
                        .of_parse_cb = pca9450_set_dvs_levels,
+                       .of_map_mode = pca9450_map_mode,
                },
                .dvs = {
                        .run_reg = PCA9450_REG_BUCK1OUT_DVS0,
                        .run_mask = BUCK1OUT_DVS0_MASK,
                        .standby_reg = PCA9450_REG_BUCK1OUT_DVS1,
                        .standby_mask = BUCK1OUT_DVS1_MASK,
+                       .mode_reg = PCA9450_REG_BUCK1CTRL,
+                       .mode_mask = BUCK1_FPWM,
                },
        },
        {
@@ -338,12 +408,15 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = {
                        .n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table),
                        .owner = THIS_MODULE,
                        .of_parse_cb = pca9450_set_dvs_levels,
+                       .of_map_mode = pca9450_map_mode,
                },
                .dvs = {
                        .run_reg = PCA9450_REG_BUCK2OUT_DVS0,
                        .run_mask = BUCK2OUT_DVS0_MASK,
                        .standby_reg = PCA9450_REG_BUCK2OUT_DVS1,
                        .standby_mask = BUCK2OUT_DVS1_MASK,
+                       .mode_reg = PCA9450_REG_BUCK2CTRL,
+                       .mode_mask = BUCK2_FPWM,
                },
        },
        {
@@ -368,12 +441,15 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = {
                        .n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table),
                        .owner = THIS_MODULE,
                        .of_parse_cb = pca9450_set_dvs_levels,
+                       .of_map_mode = pca9450_map_mode,
                },
                .dvs = {
                        .run_reg = PCA9450_REG_BUCK3OUT_DVS0,
                        .run_mask = BUCK3OUT_DVS0_MASK,
                        .standby_reg = PCA9450_REG_BUCK3OUT_DVS1,
                        .standby_mask = BUCK3OUT_DVS1_MASK,
+                       .mode_reg = PCA9450_REG_BUCK3CTRL,
+                       .mode_mask = BUCK3_FPWM,
                },
        },
        {
@@ -393,6 +469,11 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = {
                        .enable_mask = BUCK4_ENMODE_MASK,
                        .enable_val = BUCK_ENMODE_ONREQ,
                        .owner = THIS_MODULE,
+                       .of_map_mode = pca9450_map_mode,
+               },
+               .dvs = {
+                       .mode_reg = PCA9450_REG_BUCK4CTRL,
+                       .mode_mask = BUCK4_FPWM,
                },
        },
        {
@@ -412,6 +493,11 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = {
                        .enable_mask = BUCK5_ENMODE_MASK,
                        .enable_val = BUCK_ENMODE_ONREQ,
                        .owner = THIS_MODULE,
+                       .of_map_mode = pca9450_map_mode,
+               },
+               .dvs = {
+                       .mode_reg = PCA9450_REG_BUCK5CTRL,
+                       .mode_mask = BUCK5_FPWM,
                },
        },
        {
@@ -431,6 +517,11 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = {
                        .enable_mask = BUCK6_ENMODE_MASK,
                        .enable_val = BUCK_ENMODE_ONREQ,
                        .owner = THIS_MODULE,
+                       .of_map_mode = pca9450_map_mode,
+               },
+               .dvs = {
+                       .mode_reg = PCA9450_REG_BUCK6CTRL,
+                       .mode_mask = BUCK6_FPWM,
                },
        },
        {
@@ -529,7 +620,7 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = {
  * Buck3 removed on PCA9450B and connected with Buck1 internal for dual phase
  * on PCA9450C as no Buck3.
  */
-static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
+static struct pca9450_regulator_desc pca9450bc_regulators[] = {
        {
                .desc = {
                        .name = "buck1",
@@ -552,12 +643,15 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
                        .n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table),
                        .owner = THIS_MODULE,
                        .of_parse_cb = pca9450_set_dvs_levels,
+                       .of_map_mode = pca9450_map_mode,
                },
                .dvs = {
                        .run_reg = PCA9450_REG_BUCK1OUT_DVS0,
                        .run_mask = BUCK1OUT_DVS0_MASK,
                        .standby_reg = PCA9450_REG_BUCK1OUT_DVS1,
                        .standby_mask = BUCK1OUT_DVS1_MASK,
+                       .mode_reg = PCA9450_REG_BUCK1CTRL,
+                       .mode_mask = BUCK1_FPWM,
                },
        },
        {
@@ -582,12 +676,15 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
                        .n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table),
                        .owner = THIS_MODULE,
                        .of_parse_cb = pca9450_set_dvs_levels,
+                       .of_map_mode = pca9450_map_mode,
                },
                .dvs = {
                        .run_reg = PCA9450_REG_BUCK2OUT_DVS0,
                        .run_mask = BUCK2OUT_DVS0_MASK,
                        .standby_reg = PCA9450_REG_BUCK2OUT_DVS1,
                        .standby_mask = BUCK2OUT_DVS1_MASK,
+                       .mode_reg = PCA9450_REG_BUCK2CTRL,
+                       .mode_mask = BUCK2_FPWM,
                },
        },
        {
@@ -607,6 +704,11 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
                        .enable_mask = BUCK4_ENMODE_MASK,
                        .enable_val = BUCK_ENMODE_ONREQ,
                        .owner = THIS_MODULE,
+                       .of_map_mode = pca9450_map_mode,
+               },
+               .dvs = {
+                       .mode_reg = PCA9450_REG_BUCK4CTRL,
+                       .mode_mask = BUCK4_FPWM,
                },
        },
        {
@@ -626,6 +728,11 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
                        .enable_mask = BUCK5_ENMODE_MASK,
                        .enable_val = BUCK_ENMODE_ONREQ,
                        .owner = THIS_MODULE,
+                       .of_map_mode = pca9450_map_mode,
+               },
+               .dvs = {
+                       .mode_reg = PCA9450_REG_BUCK5CTRL,
+                       .mode_mask = BUCK5_FPWM,
                },
        },
        {
@@ -645,6 +752,11 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
                        .enable_mask = BUCK6_ENMODE_MASK,
                        .enable_val = BUCK_ENMODE_ONREQ,
                        .owner = THIS_MODULE,
+                       .of_map_mode = pca9450_map_mode,
+               },
+               .dvs = {
+                       .mode_reg = PCA9450_REG_BUCK6CTRL,
+                       .mode_mask = BUCK6_FPWM,
                },
        },
        {
@@ -739,7 +851,7 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
        },
 };
 
-static const struct pca9450_regulator_desc pca9451a_regulators[] = {
+static struct pca9450_regulator_desc pca9451a_regulators[] = {
        {
                .desc = {
                        .name = "buck1",
@@ -990,7 +1102,7 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
 {
        enum pca9450_chip_type type = (unsigned int)(uintptr_t)
                                      of_device_get_match_data(&i2c->dev);
-       const struct pca9450_regulator_desc     *regulator_desc;
+       const struct pca9450_regulator_desc *regulator_desc;
        struct regulator_config config = { };
        struct regulator_dev *ldo5;
        struct pca9450 *pca9450;