From 97350c1541d0182195f022f459840a8bd3747b2b Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 17 Aug 2026 22:40:58 -0300 Subject: regulator: pca9450: Use LDO5 low-control enable mask LDO5 has voltage-selection fields in both LDO5CTRL_L and LDO5CTRL_H, selected by the SD_VSEL pin. Its ENMODE field, however, is only in LDO5CTRL_L. The regulator descriptors correctly use LDO5CTRL_L as enable_reg, but use the misleading LDO5H_EN_MASK name for enable_mask. Both mask definitions have the same value, so this causes no functional problem. Use LDO5L_EN_MASK in all LDO5 descriptors and remove the unused LDO5H_EN_MASK definition. Signed-off-by: Fabio Estevam Link: https://patch.msgid.link/20260818014059.351152-1-festevam@gmail.com Signed-off-by: Mark Brown --- include/linux/regulator/pca9450.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/regulator/pca9450.h b/include/linux/regulator/pca9450.h index 0df8b3c48082..2aa73624d0b8 100644 --- a/include/linux/regulator/pca9450.h +++ b/include/linux/regulator/pca9450.h @@ -210,7 +210,6 @@ enum { #define LDO5L_EN_MASK 0xC0 #define LDO5LOUT_MASK 0x0F -#define LDO5H_EN_MASK 0xC0 #define LDO5HOUT_MASK 0x0F /* PCA9450_REG_IRQ bits */ -- cgit v1.2.3 From 0c47038219a048b12c7e095d6f4b0cdd146e878a Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 17 Aug 2026 22:40:59 -0300 Subject: regulator: pca9450: Support regulator-off-in-suspend The PCA9450 uses each regulator's ENMODE field to control whether the regulator remains enabled when the PMIC transitions from RUN to STANDBY mode. The driver does not currently implement set_suspend_disable(), so a regulator configured with regulator-off-in-suspend remains enabled during system suspend. Implement set_suspend_disable() for the buck regulators and LDO3-LDO5. The suspend and runtime controls share ENMODE, so first read the field and leave it unchanged when it is 00b. This preserves the state of a regulator that was already disabled at runtime. For an enabled regulator, program 10b to keep it on in RUN and turn it off while PMIC_STBY_REQ is asserted. Most buck descriptors set enable_val to 01b, while BUCK2 uses 10b. When enable_val is nonzero, regulator_is_enabled_regmap() checks for an exact match. It would therefore report most bucks as disabled after their ENMODE is changed from 01b to 10b, even though all valid nonzero ENMODE values enable the regulator in RUN. Use a custom is_enabled() helper for the buck operation tables that considers a nonzero ENMODE enabled. The LDO descriptors leave enable_val at zero, for which the generic helper already performs this nonzero check, so keep using it for the LDOs. Runtime enable and disable operations remain unchanged: disable writes 00b and enable writes the regulator's default mode. The suspend callback reapplies 10b on each suspend after any intervening runtime operation. Keep LDO1 and LDO2 on regulator operations without set_suspend_disable(), because these regulators supply the SNVS domain and must remain enabled in STANDBY mode. Measured on a custom i.MX8MP board, turning off NVCC_SD2 (LDO5) during system suspend reduced power consumption by approximately 64 mW. Signed-off-by: Fabio Estevam Link: https://patch.msgid.link/20260818014059.351152-2-festevam@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/pca9450-regulator.c | 75 +++++++++++++++++++++++++++++++---- include/linux/regulator/pca9450.h | 3 ++ 2 files changed, 70 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c index 93d0af7f7eda..613bce411f31 100644 --- a/drivers/regulator/pca9450-regulator.c +++ b/drivers/regulator/pca9450-regulator.c @@ -77,10 +77,56 @@ static const unsigned int pca9450_dvs_buck_ramp_table[] = { 25000, 12500, 6250, 3125 }; +static int pca9450_regulator_is_enabled(struct regulator_dev *rdev) +{ + unsigned int val; + int ret; + + ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); + if (ret) + return ret; + + /* All valid nonzero ENMODE values enable the regulator in RUN mode. */ + return !!(val & rdev->desc->enable_mask); +} + +static int pca9450_set_suspend_disable(struct regulator_dev *rdev, + unsigned int suspend_val) +{ + int ret; + + /* Do not enable a runtime-disabled regulator when returning to RUN. */ + ret = pca9450_regulator_is_enabled(rdev); + if (ret < 0) + return ret; + if (!ret) + return 0; + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, + suspend_val); +} + +/* + * ENMODE = 10b keeps the regulator enabled in RUN mode and disables it + * while PMIC_STBY_REQ is asserted. + */ +static int pca9450_buck_set_suspend_disable(struct regulator_dev *rdev) +{ + return pca9450_set_suspend_disable(rdev, + BUCK_ENMODE_ONREQ_STBYREQ); +} + +static int pca9450_ldo_set_suspend_disable(struct regulator_dev *rdev) +{ + return pca9450_set_suspend_disable(rdev, + LDO_ENMODE_ONREQ_STBYREQ); +} + static const struct regulator_ops pca9450_dvs_buck_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, + .is_enabled = pca9450_regulator_is_enabled, .list_voltage = regulator_list_voltage_linear_range, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -88,18 +134,20 @@ static const struct regulator_ops pca9450_dvs_buck_regulator_ops = { .set_ramp_delay = regulator_set_ramp_delay_regmap, .set_mode = pca9450_buck_set_mode, .get_mode = pca9450_buck_get_mode, + .set_suspend_disable = pca9450_buck_set_suspend_disable, }; static const struct regulator_ops pca9450_buck_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, + .is_enabled = pca9450_regulator_is_enabled, .list_voltage = regulator_list_voltage_linear_range, .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, + .set_suspend_disable = pca9450_buck_set_suspend_disable, }; static const struct regulator_ops pca9450_ldo_regulator_ops = { @@ -111,6 +159,16 @@ static const struct regulator_ops pca9450_ldo_regulator_ops = { .get_voltage_sel = regulator_get_voltage_sel_regmap, }; +static const struct regulator_ops pca9450_ldo_suspend_regulator_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_suspend_disable = pca9450_ldo_set_suspend_disable, +}; + static unsigned int pca9450_ldo5_get_reg_voltage_sel(struct regulator_dev *rdev) { struct pca9450 *pca9450 = rdev_get_drvdata(rdev); @@ -164,6 +222,7 @@ static const struct regulator_ops pca9450_ldo5_regulator_ops = { .list_voltage = regulator_list_voltage_linear_range, .set_voltage_sel = pca9450_ldo5_set_voltage_sel_regmap, .get_voltage_sel = pca9450_ldo5_get_voltage_sel_regmap, + .set_suspend_disable = pca9450_ldo_set_suspend_disable, }; /* @@ -575,7 +634,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = { .of_match = of_match_ptr("LDO3"), .regulators_node = of_match_ptr("regulators"), .id = PCA9450_LDO3, - .ops = &pca9450_ldo_regulator_ops, + .ops = &pca9450_ldo_suspend_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = PCA9450_LDO3_VOLTAGE_NUM, .linear_ranges = pca9450_ldo34_volts, @@ -594,7 +653,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = { .of_match = of_match_ptr("LDO4"), .regulators_node = of_match_ptr("regulators"), .id = PCA9450_LDO4, - .ops = &pca9450_ldo_regulator_ops, + .ops = &pca9450_ldo_suspend_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = PCA9450_LDO4_VOLTAGE_NUM, .linear_ranges = pca9450_ldo34_volts, @@ -820,7 +879,7 @@ static struct pca9450_regulator_desc pca9450bc_regulators[] = { .of_match = of_match_ptr("LDO3"), .regulators_node = of_match_ptr("regulators"), .id = PCA9450_LDO3, - .ops = &pca9450_ldo_regulator_ops, + .ops = &pca9450_ldo_suspend_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = PCA9450_LDO3_VOLTAGE_NUM, .linear_ranges = pca9450_ldo34_volts, @@ -839,7 +898,7 @@ static struct pca9450_regulator_desc pca9450bc_regulators[] = { .of_match = of_match_ptr("LDO4"), .regulators_node = of_match_ptr("regulators"), .id = PCA9450_LDO4, - .ops = &pca9450_ldo_regulator_ops, + .ops = &pca9450_ldo_suspend_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = PCA9450_LDO4_VOLTAGE_NUM, .linear_ranges = pca9450_ldo34_volts, @@ -1040,7 +1099,7 @@ static struct pca9450_regulator_desc pca9451a_regulators[] = { .of_match = of_match_ptr("LDO3"), .regulators_node = of_match_ptr("regulators"), .id = PCA9450_LDO3, - .ops = &pca9450_ldo_regulator_ops, + .ops = &pca9450_ldo_suspend_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = PCA9450_LDO3_VOLTAGE_NUM, .linear_ranges = pca9450_ldo34_volts, @@ -1059,7 +1118,7 @@ static struct pca9450_regulator_desc pca9451a_regulators[] = { .of_match = of_match_ptr("LDO4"), .regulators_node = of_match_ptr("regulators"), .id = PCA9450_LDO4, - .ops = &pca9450_ldo_regulator_ops, + .ops = &pca9450_ldo_suspend_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = PCA9450_LDO4_VOLTAGE_NUM, .linear_ranges = pca9450_ldo34_volts, diff --git a/include/linux/regulator/pca9450.h b/include/linux/regulator/pca9450.h index 2aa73624d0b8..bf94df5fafe3 100644 --- a/include/linux/regulator/pca9450.h +++ b/include/linux/regulator/pca9450.h @@ -212,6 +212,9 @@ enum { #define LDO5HOUT_MASK 0x0F +/* LDO ENMODE value: ON in RUN, OFF while PMIC_STBY_REQ is asserted */ +#define LDO_ENMODE_ONREQ_STBYREQ 0x80 + /* PCA9450_REG_IRQ bits */ #define IRQ_PWRON 0x80 #define IRQ_WDOGB 0x40 -- cgit v1.2.3 From f267ad84f59c9170629babb2ca928a26a9adcb0a Mon Sep 17 00:00:00 2001 From: Hemanth Selam Date: Fri, 4 Sep 2026 16:32:00 +0530 Subject: regulator: fix typos in comments Fix typos in comments, reported by scripts/checkpatch.pl using the misspelling list in scripts/spelling.txt. Only touches comments, no code changes. Assisted-by: Cursor:claude-opus-5 Signed-off-by: Hemanth Selam Link: https://patch.msgid.link/20260904110203.10113-2-hemanth.selam@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/ab8500-ext.c | 2 +- drivers/regulator/core.c | 2 +- drivers/regulator/pv88080-regulator.c | 4 ++-- include/linux/regulator/driver.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c index b9955aa4e0d1..c0657362a102 100644 --- a/drivers/regulator/ab8500-ext.c +++ b/drivers/regulator/ab8500-ext.c @@ -88,7 +88,7 @@ static struct regulator_init_data ab8500_ext_regulators[] = { * @update_reg: register to control on/off * @update_mask: mask to enable/disable and set mode of regulator * @update_val: bits holding the regulator current mode - * @update_val_hp: bits to set EN pin active (LPn pin deactive) + * @update_val_hp: bits to set EN pin active (LPn pin deactivate) * normally this means high power mode * @update_val_lp: bits to set EN pin active and LPn pin active * normally this means low power mode diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 6a4008f387b5..1e950260f441 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3029,7 +3029,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev) */ trace_regulator_enable_delay(rdev_get_name(rdev)); - /* If poll_enabled_time is set, poll upto the delay calculated + /* If poll_enabled_time is set, poll up to the delay calculated * above, delaying poll_enabled_time uS to check if the regulator * actually got enabled. * If the regulator isn't enabled after our delay helper has expired, diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c index b96afbf11ff3..1f2c405fd2bd 100644 --- a/drivers/regulator/pv88080-regulator.c +++ b/drivers/regulator/pv88080-regulator.c @@ -432,7 +432,7 @@ static int pv88080_i2c_probe(struct i2c_client *i2c) config.dev = chip->dev; config.regmap = chip->regmap; - /* Registeration for BUCK1, 2, 3 */ + /* Registration for BUCK1, 2, 3 */ for (i = 0; i < PV88080_MAX_REGULATORS-1; i++) { if (init_data) config.init_data = &init_data[i]; @@ -498,7 +498,7 @@ static int pv88080_i2c_probe(struct i2c_client *i2c) pv88080_regulator_info[PV88080_ID_HVBUCK].desc.vsel_mask = regmap_config->hvbuck_vsel_mask; - /* Registeration for HVBUCK */ + /* Registration for HVBUCK */ if (init_data) config.init_data = &init_data[PV88080_ID_HVBUCK]; diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index cc6ce709ec86..55cc519103ed 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -362,7 +362,7 @@ enum regulator_type { * @off_on_delay: guard time (in uS), before re-enabling a regulator * * @poll_enabled_time: The polling interval (in uS) to use while checking that - * the regulator was actually enabled. Max upto enable_time. + * the regulator was actually enabled. Max up to enable_time. * * @of_map_mode: Maps a hardware mode defined in a DeviceTree to a standard mode */ -- cgit v1.2.3 From 3fe744bac408579c1d65e2d70b4c04d0c3818008 Mon Sep 17 00:00:00 2001 From: Duje Mihanović Date: Sat, 13 Jun 2026 16:20:55 +0200 Subject: regulator: 88pm886: Add Vbus regulator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for the PMIC's Vbus regulator. This regulator is mandatory for USB OTG support on boards using the PMIC. Reviewed-by: Karel Balej Signed-off-by: Duje Mihanović Link: https://patch.msgid.link/20260613-88pm886-vbus-v2-3-021dfb02c6bb@dujemihanovic.xyz Signed-off-by: Mark Brown --- drivers/regulator/88pm886-regulator.c | 26 ++++++++++++++++++++++++++ include/linux/mfd/88pm886.h | 7 +++++++ 2 files changed, 33 insertions(+) (limited to 'include/linux') diff --git a/drivers/regulator/88pm886-regulator.c b/drivers/regulator/88pm886-regulator.c index 7328cd1cf265..1961a7968982 100644 --- a/drivers/regulator/88pm886-regulator.c +++ b/drivers/regulator/88pm886-regulator.c @@ -337,6 +337,25 @@ static struct regulator_desc pm886_regulators[] = { }, }; +static const struct linear_range pm886_vbus_volt_ranges[] = { + REGULATOR_LINEAR_RANGE(3750000, 0, 7, 250000) +}; + +static struct regulator_desc pm886_vbus_regulator = { + .name = "vbus", + .regulators_node = "regulators", + .of_match = "vbus", + .ops = &pm886_buck_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 8, + .linear_ranges = pm886_vbus_volt_ranges, + .n_linear_ranges = ARRAY_SIZE(pm886_vbus_volt_ranges), + .vsel_reg = PM886_REG_BOOST_CONFIG1, + .vsel_mask = PM886_REG_BOOST_MASK, + .enable_reg = PM886_REG_BATTERY_CONFIG1, + .enable_mask = PM886_REG_VBUS_EN, +}; + static int pm886_regulator_probe(struct platform_device *pdev) { struct pm886_chip *chip = dev_get_drvdata(pdev->dev.parent); @@ -369,6 +388,13 @@ static int pm886_regulator_probe(struct platform_device *pdev) "Failed to register %s\n", rdesc->name); } + rcfg.regmap = chip->regmap_battery; + rdesc = &pm886_vbus_regulator; + rdev = devm_regulator_register(dev, rdesc, &rcfg); + if (IS_ERR(rdev)) + return dev_err_probe(dev, PTR_ERR(rdev), + "Failed to register %s\n", rdesc->name); + return 0; } diff --git a/include/linux/mfd/88pm886.h b/include/linux/mfd/88pm886.h index 2c24dd3032ab..9e96d2cb92f5 100644 --- a/include/linux/mfd/88pm886.h +++ b/include/linux/mfd/88pm886.h @@ -2,6 +2,7 @@ #ifndef __MFD_88PM886_H #define __MFD_88PM886_H +#include #include #include @@ -130,6 +131,12 @@ #define PM886_GPADC_INDEX_TO_BIAS_uA(i) (1 + (i) * 5) /* Battery block register definitions */ +#define PM886_REG_BATTERY_CONFIG1 0x28 +#define PM886_REG_VBUS_EN BIT(7) + +#define PM886_REG_BOOST_CONFIG1 0x6b +#define PM886_REG_BOOST_MASK GENMASK(2, 0) + #define PM886_REG_CLS_CONFIG1 0x71 struct pm886_chip { -- cgit v1.2.3