From 19253cac2a9021733e047ab0c04594c7c21182a9 Mon Sep 17 00:00:00 2001 From: Jad Keskes Date: Wed, 17 Jun 2026 10:46:22 +0100 Subject: [PATCH 01/36] regulator: max14577: fix set_mode clobbering enable on MAX77836 LDOs So the PWRMD field in CNFG1_LDO is both the enable bit and the mode. You can't change one without stepping on the other. The problem is that enable() from the regulator core just writes enable_mask (which is PWRMD_NORMAL). If you'd called set_mode(LPM) then disabled and re-enabled, the mode gets reset to NORMAL. And set_mode updates the register through the same field, so it can accidentally enable a disabled regulator. Fix it by storing the mode in per-regulator data. A custom enable writes whatever mode was last set. set_mode only touches hardware if the regulator is already on; otherwise it just caches the value. Add of_map_mode while here so the initial mode can be wired from DT. Signed-off-by: Jad Keskes Acked-by: Lee Jones Link: https://patch.msgid.link/20260617094622.1846471-1-inasj268@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/max14577-regulator.c | 103 ++++++++++++++++++++++++- include/linux/mfd/max14577-private.h | 3 + 2 files changed, 102 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/max14577-regulator.c b/drivers/regulator/max14577-regulator.c index c9d8d5e31cbd..cd592c5de148 100644 --- a/drivers/regulator/max14577-regulator.c +++ b/drivers/regulator/max14577-regulator.c @@ -123,15 +123,88 @@ static const struct regulator_desc max14577_supported_regulators[] = { [MAX14577_CHARGER] = MAX14577_CHARGER_REG, }; +struct max77836_ldo { + struct max14577 *max14577; + unsigned int mode; +}; + +static int max77836_ldo_enable(struct regulator_dev *rdev) +{ + struct max77836_ldo *ldo = rdev_get_drvdata(rdev); + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + MAX77836_CNFG1_LDO_PWRMD_MASK, ldo->mode); +} + +static int max77836_ldo_disable(struct regulator_dev *rdev) +{ + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + MAX77836_CNFG1_LDO_PWRMD_MASK, + MAX77836_CNFG1_LDO_PWRMD_OFF); +} + +static unsigned int max77836_ldo_get_mode(struct regulator_dev *rdev) +{ + struct max77836_ldo *ldo = rdev_get_drvdata(rdev); + + switch (ldo->mode) { + case MAX77836_CNFG1_LDO_PWRMD_LPM: + return REGULATOR_MODE_IDLE; + case MAX77836_CNFG1_LDO_PWRMD_NORMAL: + return REGULATOR_MODE_NORMAL; + default: + return REGULATOR_MODE_INVALID; + } +} + +static int max77836_ldo_set_mode(struct regulator_dev *rdev, + unsigned int mode) +{ + struct max77836_ldo *ldo = rdev_get_drvdata(rdev); + unsigned int val; + + switch (mode) { + case REGULATOR_MODE_NORMAL: + val = MAX77836_CNFG1_LDO_PWRMD_NORMAL; + break; + case REGULATOR_MODE_IDLE: + val = MAX77836_CNFG1_LDO_PWRMD_LPM; + break; + default: + return -EINVAL; + } + + ldo->mode = val; + + /* Only touch hardware if the regulator is already on */ + if (regulator_is_enabled_regmap(rdev)) + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + MAX77836_CNFG1_LDO_PWRMD_MASK, val); + + return 0; +} + +static unsigned int max77836_ldo_of_map_mode(unsigned int mode) +{ + switch (mode) { + case REGULATOR_MODE_NORMAL: + case REGULATOR_MODE_IDLE: + return mode; + default: + return REGULATOR_MODE_INVALID; + } +} + static const struct regulator_ops max77836_ldo_ops = { .is_enabled = regulator_is_enabled_regmap, - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, + .enable = max77836_ldo_enable, + .disable = max77836_ldo_disable, .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - /* TODO: add .set_suspend_mode */ + .get_mode = max77836_ldo_get_mode, + .set_mode = max77836_ldo_set_mode, }; #define MAX77836_LDO_REG(num) { \ @@ -147,6 +220,7 @@ static const struct regulator_ops max77836_ldo_ops = { .uV_step = MAX77836_REGULATOR_LDO_VOLTAGE_STEP, \ .enable_reg = MAX77836_LDO_REG_CNFG1_LDO ## num, \ .enable_mask = MAX77836_CNFG1_LDO_PWRMD_MASK, \ + .of_map_mode = max77836_ldo_of_map_mode, \ .vsel_reg = MAX77836_LDO_REG_CNFG1_LDO ## num, \ .vsel_mask = MAX77836_CNFG1_LDO_TV_MASK, \ } @@ -205,7 +279,6 @@ static int max14577_regulator_probe(struct platform_device *pdev) } config.dev = max14577->dev; - config.driver_data = max14577; for (i = 0; i < supported_regulators_size; i++) { struct regulator_dev *regulator; @@ -217,6 +290,28 @@ static int max14577_regulator_probe(struct platform_device *pdev) config.init_data = pdata->regulators[i].initdata; config.of_node = pdata->regulators[i].of_node; } + + /* + * LDOs need per-regulator driver data to store their mode. + * The charger and safeout share the core MFD struct. + */ + if (dev_type == MAXIM_DEVICE_TYPE_MAX77836 && + (supported_regulators[i].id == MAX77836_LDO1 || + supported_regulators[i].id == MAX77836_LDO2)) { + struct max77836_ldo *ldo; + + ldo = devm_kzalloc(&pdev->dev, sizeof(*ldo), + GFP_KERNEL); + if (!ldo) + return -ENOMEM; + + ldo->max14577 = max14577; + ldo->mode = MAX77836_CNFG1_LDO_PWRMD_NORMAL; + config.driver_data = ldo; + } else { + config.driver_data = max14577; + } + config.regmap = max14577_get_regmap(max14577, supported_regulators[i].id); diff --git a/include/linux/mfd/max14577-private.h b/include/linux/mfd/max14577-private.h index dd51a37fa37f..5957e15b568e 100644 --- a/include/linux/mfd/max14577-private.h +++ b/include/linux/mfd/max14577-private.h @@ -350,6 +350,9 @@ enum max77836_pmic_reg { #define MAX77836_CNFG1_LDO_PWRMD_SHIFT 6 #define MAX77836_CNFG1_LDO_TV_SHIFT 0 #define MAX77836_CNFG1_LDO_PWRMD_MASK (0x3 << MAX77836_CNFG1_LDO_PWRMD_SHIFT) +#define MAX77836_CNFG1_LDO_PWRMD_OFF (0x0 << MAX77836_CNFG1_LDO_PWRMD_SHIFT) +#define MAX77836_CNFG1_LDO_PWRMD_LPM (0x1 << MAX77836_CNFG1_LDO_PWRMD_SHIFT) +#define MAX77836_CNFG1_LDO_PWRMD_NORMAL (0x3 << MAX77836_CNFG1_LDO_PWRMD_SHIFT) #define MAX77836_CNFG1_LDO_TV_MASK (0x3f << MAX77836_CNFG1_LDO_TV_SHIFT) /* LDO1/LDO2 CONFIG2 register */ From 05dfeb2d0ccf87a7b92cd149a393b8423a26a04e Mon Sep 17 00:00:00 2001 From: Kathiravan Thirumoorthy Date: Wed, 17 Jun 2026 23:08:43 +0530 Subject: [PATCH 02/36] regulator: qcom-refgen: correct the regulator type to CURRENT As per the REFGEN IP team, this block supplies the reference current to the PHYs in the SoC. So, correct the regulator type to REGULATOR_CURRENT to match with the HW behavior. Fixes: 7cbfbe237960 ("regulator: Introduce Qualcomm REFGEN regulator driver") Cc: stable@vger.kernel.org Reviewed-by: Konrad Dybcio Signed-off-by: Kathiravan Thirumoorthy Link: https://patch.msgid.link/20260617-ipq9650_refgen-v4-1-c505ea6c6661@oss.qualcomm.com Signed-off-by: Mark Brown --- drivers/regulator/qcom-refgen-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/qcom-refgen-regulator.c b/drivers/regulator/qcom-refgen-regulator.c index 299ac3c8c3bc..6a3795469927 100644 --- a/drivers/regulator/qcom-refgen-regulator.c +++ b/drivers/regulator/qcom-refgen-regulator.c @@ -66,7 +66,7 @@ static const struct regulator_desc sdm845_refgen_desc = { .enable_time = 5, .name = "refgen", .owner = THIS_MODULE, - .type = REGULATOR_VOLTAGE, + .type = REGULATOR_CURRENT, .ops = &(const struct regulator_ops) { .enable = qcom_sdm845_refgen_enable, .disable = qcom_sdm845_refgen_disable, @@ -82,7 +82,7 @@ static const struct regulator_desc sm8250_refgen_desc = { .enable_time = 5, .name = "refgen", .owner = THIS_MODULE, - .type = REGULATOR_VOLTAGE, + .type = REGULATOR_CURRENT, .ops = &(const struct regulator_ops) { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, From 7b5cd466e48818e5cf75cbf4aad14c9ed5d08fe2 Mon Sep 17 00:00:00 2001 From: Kathiravan Thirumoorthy Date: Wed, 17 Jun 2026 23:08:44 +0530 Subject: [PATCH 03/36] regulator: dt-bindings: qcom,sdm845-refgen-regulator: Document IPQ9650 IPQ9650 has two REFGEN blocks which provide reference current to the PCIe, USB and UNIPHY PHYs. Unlike other supported platforms, IPQ9650 requires the REFGEN clocks to be enabled explicitly. Document the IPQ9650 compatible and the required clocks for it. While at it, move the allOf block after the 'required' property section. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Kathiravan Thirumoorthy Link: https://patch.msgid.link/20260617-ipq9650_refgen-v4-2-c505ea6c6661@oss.qualcomm.com Signed-off-by: Mark Brown --- .../qcom,sdm845-refgen-regulator.yaml | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/qcom,sdm845-refgen-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,sdm845-refgen-regulator.yaml index 40f9223d4c27..0bbf7c806fbc 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,sdm845-refgen-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,sdm845-refgen-regulator.yaml @@ -13,9 +13,6 @@ description: The REFGEN (reference voltage generator) regulator provides reference voltage for on-chip IPs (like PHYs) on some Qualcomm SoCs. -allOf: - - $ref: regulator.yaml# - properties: compatible: oneOf: @@ -39,16 +36,44 @@ properties: - const: qcom,sm8250-refgen-regulator - enum: + - qcom,ipq9650-refgen-regulator - qcom,sdm845-refgen-regulator - qcom,sm8250-refgen-regulator reg: maxItems: 1 + clocks: + items: + - description: Core reference clock + - description: AHB interface clock + + clock-names: + items: + - const: core + - const: hclk + required: - compatible - reg +allOf: + - $ref: regulator.yaml# + + - if: + properties: + compatible: + contains: + const: qcom,ipq9650-refgen-regulator + then: + required: + - clocks + - clock-names + else: + properties: + clocks: false + clock-names: false + unevaluatedProperties: false examples: From ca5c1a0ca229fa7e035735e07f1b8959059d03bf Mon Sep 17 00:00:00 2001 From: Kathiravan Thirumoorthy Date: Wed, 17 Jun 2026 23:08:45 +0530 Subject: [PATCH 04/36] regulator: qcom-refgen: add support for the IPQ9650 SoC IPQ9650 SoC has 2 REFGEN blocks providing the reference current to the PCIe and USB, UNIPHY PHYs. For the other SoCs, clock for this block is enabled on power up but that's not the case for IPQ9650 and we have to enable those clocks explicitly to bring up the PHYs properly. Also, add the get_status() callback to report the regulator status to the userspace. Signed-off-by: Kathiravan Thirumoorthy Reviewed-by: Konrad Dybcio Link: https://patch.msgid.link/20260617-ipq9650_refgen-v4-3-c505ea6c6661@oss.qualcomm.com Signed-off-by: Mark Brown --- drivers/regulator/qcom-refgen-regulator.c | 109 +++++++++++++++++++++- 1 file changed, 105 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/qcom-refgen-regulator.c b/drivers/regulator/qcom-refgen-regulator.c index 6a3795469927..cc72e5a43ba6 100644 --- a/drivers/regulator/qcom-refgen-regulator.c +++ b/drivers/regulator/qcom-refgen-regulator.c @@ -3,6 +3,7 @@ // Copyright (c) 2023, Linaro Limited #include +#include #include #include #include @@ -16,6 +17,9 @@ #define REFGEN_BIAS_EN_ENABLE 0x7 #define REFGEN_BIAS_EN_DISABLE 0x6 +#define REFGEN_REG_REFGEN_STATUS 0xc +#define REFGEN_STATUS_OUT_MASK BIT(3) + #define REFGEN_REG_BG_CTRL 0x14 #define REFGEN_BG_CTRL_MASK GENMASK(2, 1) #define REFGEN_BG_CTRL_ENABLE 0x3 @@ -25,6 +29,17 @@ #define REFGEN_PWRDWN_CTRL5_MASK BIT(0) #define REFGEN_PWRDWN_CTRL5_ENABLE 0x1 +struct qcom_refgen_regulator_data { + const struct regulator_desc *rdesc; + bool has_clocks; +}; + +struct qcom_refgen_drvdata { + struct clk_bulk_data *clks; + int num_clks; + bool is_enabled; +}; + static int qcom_sdm845_refgen_enable(struct regulator_dev *rdev) { regmap_update_bits(rdev->regmap, REFGEN_REG_BG_CTRL, REFGEN_BG_CTRL_MASK, @@ -62,6 +77,62 @@ static int qcom_sdm845_refgen_is_enabled(struct regulator_dev *rdev) return 1; } +static int qcom_ipq9650_refgen_enable(struct regulator_dev *rdev) +{ + struct qcom_refgen_drvdata *drvdata = rdev_get_drvdata(rdev); + int ret; + + ret = clk_bulk_prepare_enable(drvdata->num_clks, drvdata->clks); + if (ret) + return ret; + + drvdata->is_enabled = true; + + return 0; +} + +static int qcom_ipq9650_refgen_disable(struct regulator_dev *rdev) +{ + struct qcom_refgen_drvdata *drvdata = rdev_get_drvdata(rdev); + + clk_bulk_disable_unprepare(drvdata->num_clks, drvdata->clks); + + drvdata->is_enabled = false; + + return 0; +} + +static int qcom_ipq9650_refgen_is_enabled(struct regulator_dev *rdev) +{ + struct qcom_refgen_drvdata *drvdata = rdev_get_drvdata(rdev); + + return drvdata->is_enabled; +} + +static int qcom_ipq9650_refgen_get_status(struct regulator_dev *rdev) +{ + u32 val; + + regmap_read(rdev->regmap, REFGEN_REG_REFGEN_STATUS, &val); + if (FIELD_GET(REFGEN_STATUS_OUT_MASK, val)) + return REGULATOR_STATUS_ON; + + return REGULATOR_STATUS_OFF; +} + +static const struct regulator_desc ipq9650_refgen_desc = { + .enable_time = 5, + .name = "refgen", + .owner = THIS_MODULE, + .type = REGULATOR_CURRENT, + .ops = &(const struct regulator_ops) { + .enable = qcom_ipq9650_refgen_enable, + .disable = qcom_ipq9650_refgen_disable, + .is_enabled = qcom_ipq9650_refgen_is_enabled, + .get_status = qcom_ipq9650_refgen_get_status, + }, +}; + static const struct regulator_desc sdm845_refgen_desc = { .enable_time = 5, .name = "refgen", @@ -90,6 +161,19 @@ static const struct regulator_desc sm8250_refgen_desc = { }, }; +static const struct qcom_refgen_regulator_data ipq9650_data = { + .rdesc = &ipq9650_refgen_desc, + .has_clocks = true, +}; + +static const struct qcom_refgen_regulator_data sdm845_data = { + .rdesc = &sdm845_refgen_desc, +}; + +static const struct qcom_refgen_regulator_data sm8250_data = { + .rdesc = &sm8250_refgen_desc, +}; + static const struct regmap_config qcom_refgen_regmap_config = { .reg_bits = 32, .reg_stride = 4, @@ -98,6 +182,8 @@ static const struct regmap_config qcom_refgen_regmap_config = { static int qcom_refgen_probe(struct platform_device *pdev) { + const struct qcom_refgen_regulator_data *data; + struct qcom_refgen_drvdata *drvdata = NULL; struct regulator_init_data *init_data; struct regulator_config config = {}; const struct regulator_desc *rdesc; @@ -106,10 +192,23 @@ static int qcom_refgen_probe(struct platform_device *pdev) struct regmap *regmap; void __iomem *base; - rdesc = of_device_get_match_data(dev); - if (!rdesc) + data = of_device_get_match_data(dev); + if (!data) return -ENODATA; + if (data->has_clocks) { + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + drvdata->num_clks = devm_clk_bulk_get_all(dev, &drvdata->clks); + if (drvdata->num_clks < 0) + return dev_err_probe(dev, drvdata->num_clks, + "failed to get clocks\n"); + } + + rdesc = data->rdesc; + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); @@ -126,6 +225,7 @@ static int qcom_refgen_probe(struct platform_device *pdev) config.init_data = init_data; config.of_node = dev->of_node; config.regmap = regmap; + config.driver_data = drvdata; rdev = devm_regulator_register(dev, rdesc, &config); if (IS_ERR(rdev)) @@ -135,8 +235,9 @@ static int qcom_refgen_probe(struct platform_device *pdev) } static const struct of_device_id qcom_refgen_match_table[] = { - { .compatible = "qcom,sdm845-refgen-regulator", .data = &sdm845_refgen_desc }, - { .compatible = "qcom,sm8250-refgen-regulator", .data = &sm8250_refgen_desc }, + { .compatible = "qcom,ipq9650-refgen-regulator", .data = &ipq9650_data }, + { .compatible = "qcom,sdm845-refgen-regulator", .data = &sdm845_data }, + { .compatible = "qcom,sm8250-refgen-regulator", .data = &sm8250_data }, { } }; MODULE_DEVICE_TABLE(of, qcom_refgen_match_table); From 9f6e4b8befc44271c454657276f38d8c6c8b5a18 Mon Sep 17 00:00:00 2001 From: ChiYuan Huang Date: Fri, 26 Jun 2026 11:38:52 +0800 Subject: [PATCH 05/36] regulator: dt-bindings: rtq2208: Label mtp-sel-high property as deprecated Since it can be identified by hardware register, label the unnecessary property 'richtek,mtp-sel-high' as deprecated. Signed-off-by: ChiYuan Huang Link: https://patch.msgid.link/594ebe167b33ca885c040984624e4b5d1382c0e2.1782444299.git.cy_huang@richtek.com Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/richtek,rtq2208.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/regulator/richtek,rtq2208.yaml b/Documentation/devicetree/bindings/regulator/richtek,rtq2208.yaml index 022c1f197364..25b0865d4c04 100644 --- a/Documentation/devicetree/bindings/regulator/richtek,rtq2208.yaml +++ b/Documentation/devicetree/bindings/regulator/richtek,rtq2208.yaml @@ -42,11 +42,14 @@ properties: richtek,mtp-sel-high: type: boolean + deprecated: true description: vout register selection based on this boolean value. false - Using DVS0 register setting to adjust vout true - Using DVS1 register setting to adjust vout + The property is now deprecated. Will be identified by RG HW register. + regulators: type: object additionalProperties: false @@ -100,7 +103,6 @@ examples: compatible = "richtek,rtq2208"; reg = <0x10>; interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>; - richtek,mtp-sel-high; regulators { buck-a { From 2f84cec84ffa1987a4dee80283f926774030e879 Mon Sep 17 00:00:00 2001 From: ChiYuan Huang Date: Fri, 26 Jun 2026 11:38:53 +0800 Subject: [PATCH 06/36] regualtor: rtq2208: Initiate the default MTP_SEL state by hardware register Read the initial MTP_SEL state by hardware register to prevent the wrong specified property value from the conflict of hardware pin assignment. Signed-off-by: ChiYuan Huang Link: https://patch.msgid.link/557e872a87c603a26cf91f0d4448e527afcbbae8.1782444299.git.cy_huang@richtek.com Signed-off-by: Mark Brown --- drivers/regulator/rtq2208-regulator.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/rtq2208-regulator.c b/drivers/regulator/rtq2208-regulator.c index f669a562f036..7fe082def494 100644 --- a/drivers/regulator/rtq2208-regulator.c +++ b/drivers/regulator/rtq2208-regulator.c @@ -12,6 +12,7 @@ #include /* Register */ +#define RTQ2208_REG_FSOUTB_CNTL 0x11 #define RTQ2208_REG_GLOBAL_INT1 0x12 #define RTQ2208_REG_FLT_RECORDBUCK_CB 0x18 #define RTQ2208_REG_GLOBAL_INT1_MASK 0x1D @@ -34,6 +35,7 @@ #define RTQ2208_REG_HIDDEN1 0xFF /* Mask */ +#define RTQ2208_MTP_SEL_RO_MASK BIT(7) #define RTQ2208_BUCK_NR_MTP_SEL_MASK GENMASK(7, 0) #define RTQ2208_BUCK_EN_NR_MTP_SEL0_MASK BIT(0) #define RTQ2208_BUCK_EN_NR_MTP_SEL1_MASK BIT(1) @@ -465,10 +467,13 @@ static int rtq2208_parse_regulator_dt_data(int n_regulator, const unsigned int * struct rtq2208_regulator_desc *rdesc[RTQ2208_LDO_MAX], struct device *dev, unsigned int ldo1_fixed, unsigned int ldo2_fixed) { + struct regmap *regmap = dev_get_regmap(dev, NULL); int mtp_sel, i, idx; /* get mtp_sel0 or mtp_sel1 */ - mtp_sel = device_property_read_bool(dev, "richtek,mtp-sel-high"); + mtp_sel = regmap_test_bits(regmap, RTQ2208_REG_FSOUTB_CNTL, RTQ2208_MTP_SEL_RO_MASK); + if (mtp_sel < 0) + return dev_err_probe(dev, mtp_sel, "Failed to init mtp_sel state\n"); for (i = 0; i < n_regulator; i++) { idx = regulator_idx_table[i]; From 3ac69e3cb2880042a488fea68eddd2835499582b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Tue, 30 Jun 2026 16:01:07 +0200 Subject: [PATCH 07/36] regulator: Drop unused i2c driver data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two drivers explicitly set .driver_data to zero but don't use this value. So drop the explicit assignment. While touching these arrays, unify usage of whitespace and commas, and use named initializers. Reviewed-by: Laurent Pinchart Signed-off-by: Uwe Kleine-König (The Capable Hub) Link: https://patch.msgid.link/ce4f4851f16d8eea9cca632017d8c64c39ab2bcb.1782827697.git.u.kleine-koenig@baylibre.com Signed-off-by: Mark Brown --- drivers/regulator/max77675-regulator.c | 2 +- drivers/regulator/pf530x-regulator.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/regulator/max77675-regulator.c b/drivers/regulator/max77675-regulator.c index af3eb7174875..ebea08ddf4b8 100644 --- a/drivers/regulator/max77675-regulator.c +++ b/drivers/regulator/max77675-regulator.c @@ -1029,7 +1029,7 @@ static int max77675_regulator_probe(struct i2c_client *client) } static const struct i2c_device_id max77675_i2c_id[] = { - { "max77675", 0 }, + { .name = "max77675" }, { } }; MODULE_DEVICE_TABLE(i2c, max77675_i2c_id); diff --git a/drivers/regulator/pf530x-regulator.c b/drivers/regulator/pf530x-regulator.c index f789c4b6a499..8ad1cbbd7a8c 100644 --- a/drivers/regulator/pf530x-regulator.c +++ b/drivers/regulator/pf530x-regulator.c @@ -353,10 +353,10 @@ static const struct of_device_id pf530x_dt_ids[] = { MODULE_DEVICE_TABLE(of, pf530x_dt_ids); static const struct i2c_device_id pf530x_i2c_id[] = { - { "pf5300", 0 }, - { "pf5301", 0 }, - { "pf5302", 0 }, - {}, + { .name = "pf5300" }, + { .name = "pf5301" }, + { .name = "pf5302" }, + { } }; MODULE_DEVICE_TABLE(i2c, pf530x_i2c_id); From 8e74b2db58671c27809dcea9c0eb9143424f2ca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Tue, 30 Jun 2026 16:01:08 +0200 Subject: [PATCH 08/36] regulator: Use named initializers for arrays of i2c_device_data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While being less compact, using named initializers allows to more easily see which members of the structs are assigned which value without having to lookup the declaration of the struct. And it's also more robust against changes to the struct definition. The mentioned robustness is relevant for a planned change to struct i2c_device_id that replaces .driver_data by an anonymous union. While touching all these arrays, unify usage of whitespace and commas. This patch doesn't modify the compiled arrays, only their representation in source form benefits. The former was confirmed with x86 and arm64 builds. Reviewed-by: Laurent Pinchart Signed-off-by: Uwe Kleine-König (The Capable Hub) Link: https://patch.msgid.link/2e83a9747ac2c92db8f91fd0e0eb311c4efe8e73.1782827697.git.u.kleine-koenig@baylibre.com Signed-off-by: Mark Brown --- drivers/regulator/88pg86x.c | 4 ++-- drivers/regulator/ad5398.c | 4 ++-- drivers/regulator/da9121-regulator.c | 20 ++++++++++---------- drivers/regulator/da9210-regulator.c | 4 ++-- drivers/regulator/da9211-regulator.c | 18 +++++++++--------- drivers/regulator/fan53880.c | 4 ++-- drivers/regulator/isl9305.c | 4 ++-- drivers/regulator/lp3971.c | 2 +- drivers/regulator/lp3972.c | 2 +- drivers/regulator/lp872x.c | 4 ++-- drivers/regulator/lp8755.c | 4 ++-- drivers/regulator/ltc3589.c | 6 +++--- drivers/regulator/ltc3676.c | 2 +- drivers/regulator/max1586.c | 2 +- drivers/regulator/max20086-regulator.c | 8 ++++---- drivers/regulator/max20411-regulator.c | 2 +- drivers/regulator/max77503-regulator.c | 2 +- drivers/regulator/max77826-regulator.c | 2 +- drivers/regulator/max77838-regulator.c | 2 +- drivers/regulator/max77857-regulator.c | 8 ++++---- drivers/regulator/max8649.c | 2 +- drivers/regulator/max8893.c | 2 +- drivers/regulator/max8952.c | 2 +- drivers/regulator/mcp16502.c | 2 +- drivers/regulator/mp5416.c | 6 +++--- drivers/regulator/mp8859.c | 4 ++-- drivers/regulator/mp886x.c | 6 +++--- drivers/regulator/mpq7920.c | 4 ++-- drivers/regulator/mt6311-regulator.c | 4 ++-- drivers/regulator/pf8x00-regulator.c | 8 ++++---- drivers/regulator/pv88060-regulator.c | 4 ++-- drivers/regulator/pv88080-regulator.c | 8 ++++---- drivers/regulator/pv88090-regulator.c | 4 ++-- drivers/regulator/sgm3804-regulator.c | 2 +- drivers/regulator/slg51000-regulator.c | 4 ++-- drivers/regulator/sy8106a-regulator.c | 2 +- drivers/regulator/sy8824x.c | 8 ++++---- drivers/regulator/sy8827n.c | 4 ++-- drivers/regulator/tps6286x-regulator.c | 10 +++++----- drivers/regulator/tps6287x-regulator.c | 10 +++++----- 40 files changed, 100 insertions(+), 100 deletions(-) diff --git a/drivers/regulator/88pg86x.c b/drivers/regulator/88pg86x.c index e6598e74ec94..8c25a1db412f 100644 --- a/drivers/regulator/88pg86x.c +++ b/drivers/regulator/88pg86x.c @@ -92,8 +92,8 @@ static const struct of_device_id __maybe_unused pg86x_dt_ids[] = { MODULE_DEVICE_TABLE(of, pg86x_dt_ids); static const struct i2c_device_id pg86x_i2c_id[] = { - { "88pg867", }, - { "88pg868", }, + { .name = "88pg867" }, + { .name = "88pg868" }, { } }; MODULE_DEVICE_TABLE(i2c, pg86x_i2c_id); diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index eb2a666a45cb..0123ca8157a8 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c @@ -207,8 +207,8 @@ struct ad5398_current_data_format { static const struct ad5398_current_data_format df_10_4_120 = {10, 4, 0, 120000}; static const struct i2c_device_id ad5398_id[] = { - { "ad5398", (kernel_ulong_t)&df_10_4_120 }, - { "ad5821", (kernel_ulong_t)&df_10_4_120 }, + { .name = "ad5398", .driver_data = (kernel_ulong_t)&df_10_4_120 }, + { .name = "ad5821", .driver_data = (kernel_ulong_t)&df_10_4_120 }, { } }; MODULE_DEVICE_TABLE(i2c, ad5398_id); diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c index 36a52f707602..f501cf8152c2 100644 --- a/drivers/regulator/da9121-regulator.c +++ b/drivers/regulator/da9121-regulator.c @@ -1195,16 +1195,16 @@ static void da9121_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id da9121_i2c_id[] = { - {"da9121", DA9121_SUBTYPE_DA9121}, - {"da9130", DA9121_SUBTYPE_DA9130}, - {"da9217", DA9121_SUBTYPE_DA9217}, - {"da9122", DA9121_SUBTYPE_DA9122}, - {"da9131", DA9121_SUBTYPE_DA9131}, - {"da9220", DA9121_SUBTYPE_DA9220}, - {"da9132", DA9121_SUBTYPE_DA9132}, - {"da9141", DA9121_SUBTYPE_DA9141}, - {"da9142", DA9121_SUBTYPE_DA9142}, - {}, + { .name = "da9121", .driver_data = DA9121_SUBTYPE_DA9121 }, + { .name = "da9130", .driver_data = DA9121_SUBTYPE_DA9130 }, + { .name = "da9217", .driver_data = DA9121_SUBTYPE_DA9217 }, + { .name = "da9122", .driver_data = DA9121_SUBTYPE_DA9122 }, + { .name = "da9131", .driver_data = DA9121_SUBTYPE_DA9131 }, + { .name = "da9220", .driver_data = DA9121_SUBTYPE_DA9220 }, + { .name = "da9132", .driver_data = DA9121_SUBTYPE_DA9132 }, + { .name = "da9141", .driver_data = DA9121_SUBTYPE_DA9141 }, + { .name = "da9142", .driver_data = DA9121_SUBTYPE_DA9142 }, + { } }; MODULE_DEVICE_TABLE(i2c, da9121_i2c_id); diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c index 39ade0dba40f..9154e32bd745 100644 --- a/drivers/regulator/da9210-regulator.c +++ b/drivers/regulator/da9210-regulator.c @@ -202,8 +202,8 @@ static int da9210_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id da9210_i2c_id[] = { - { "da9210" }, - {} + { .name = "da9210" }, + { } }; MODULE_DEVICE_TABLE(i2c, da9210_i2c_id); diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c index d4f14d7ea8cf..9cf713755636 100644 --- a/drivers/regulator/da9211-regulator.c +++ b/drivers/regulator/da9211-regulator.c @@ -522,15 +522,15 @@ static int da9211_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id da9211_i2c_id[] = { - {"da9211", DA9211}, - {"da9212", DA9212}, - {"da9213", DA9213}, - {"da9223", DA9223}, - {"da9214", DA9214}, - {"da9224", DA9224}, - {"da9215", DA9215}, - {"da9225", DA9225}, - {}, + { .name = "da9211", .driver_data = DA9211 }, + { .name = "da9212", .driver_data = DA9212 }, + { .name = "da9213", .driver_data = DA9213 }, + { .name = "da9223", .driver_data = DA9223 }, + { .name = "da9214", .driver_data = DA9214 }, + { .name = "da9224", .driver_data = DA9224 }, + { .name = "da9215", .driver_data = DA9215 }, + { .name = "da9225", .driver_data = DA9225 }, + { } }; MODULE_DEVICE_TABLE(i2c, da9211_i2c_id); diff --git a/drivers/regulator/fan53880.c b/drivers/regulator/fan53880.c index 6cb5656845f9..79ba705ec324 100644 --- a/drivers/regulator/fan53880.c +++ b/drivers/regulator/fan53880.c @@ -164,8 +164,8 @@ static const struct of_device_id fan53880_dt_ids[] = { MODULE_DEVICE_TABLE(of, fan53880_dt_ids); static const struct i2c_device_id fan53880_i2c_id[] = { - { "fan53880", }, - {} + { .name = "fan53880" }, + { } }; MODULE_DEVICE_TABLE(i2c, fan53880_i2c_id); diff --git a/drivers/regulator/isl9305.c b/drivers/regulator/isl9305.c index 5a234f25e6bb..ec6bd6bb9721 100644 --- a/drivers/regulator/isl9305.c +++ b/drivers/regulator/isl9305.c @@ -186,8 +186,8 @@ MODULE_DEVICE_TABLE(of, isl9305_dt_ids); #endif static const struct i2c_device_id isl9305_i2c_id[] = { - { "isl9305", }, - { "isl9305h", }, + { .name = "isl9305" }, + { .name = "isl9305h" }, { } }; MODULE_DEVICE_TABLE(i2c, isl9305_i2c_id); diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index d4dab86fe385..6f830ae1bb61 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -439,7 +439,7 @@ static int lp3971_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id lp3971_i2c_id[] = { - { "lp3971" }, + { .name = "lp3971" }, { } }; MODULE_DEVICE_TABLE(i2c, lp3971_i2c_id); diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index 1b918fb72134..235c640ba57f 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -537,7 +537,7 @@ static int lp3972_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id lp3972_i2c_id[] = { - { "lp3972" }, + { .name = "lp3972" }, { } }; MODULE_DEVICE_TABLE(i2c, lp3972_i2c_id); diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 942f37082cb1..5b2faddd8110 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -935,8 +935,8 @@ static const struct of_device_id lp872x_dt_ids[] __maybe_unused = { MODULE_DEVICE_TABLE(of, lp872x_dt_ids); static const struct i2c_device_id lp872x_ids[] = { - {"lp8720", LP8720}, - {"lp8725", LP8725}, + { .name = "lp8720", .driver_data = LP8720 }, + { .name = "lp8725", .driver_data = LP8725 }, { } }; MODULE_DEVICE_TABLE(i2c, lp872x_ids); diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index 5509bee49bda..632320ba1800 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -430,8 +430,8 @@ static void lp8755_remove(struct i2c_client *client) } static const struct i2c_device_id lp8755_id[] = { - { LP8755_NAME }, - {} + { .name = LP8755_NAME }, + { } }; MODULE_DEVICE_TABLE(i2c, lp8755_id); diff --git a/drivers/regulator/ltc3589.c b/drivers/regulator/ltc3589.c index 3f70c2225dba..8bae5d8aeaf4 100644 --- a/drivers/regulator/ltc3589.c +++ b/drivers/regulator/ltc3589.c @@ -445,9 +445,9 @@ static const struct ltc3589_info ltc3589_12_info = { }; static const struct i2c_device_id ltc3589_i2c_id[] = { - { "ltc3589", (kernel_ulong_t)<c3589_info }, - { "ltc3589-1", (kernel_ulong_t)<c3589_12_info }, - { "ltc3589-2", (kernel_ulong_t)<c3589_12_info }, + { .name = "ltc3589", .driver_data = (kernel_ulong_t)<c3589_info }, + { .name = "ltc3589-1", .driver_data = (kernel_ulong_t)<c3589_12_info }, + { .name = "ltc3589-2", .driver_data = (kernel_ulong_t)<c3589_12_info }, { } }; MODULE_DEVICE_TABLE(i2c, ltc3589_i2c_id); diff --git a/drivers/regulator/ltc3676.c b/drivers/regulator/ltc3676.c index 73d511eb1c1d..597d20a200d7 100644 --- a/drivers/regulator/ltc3676.c +++ b/drivers/regulator/ltc3676.c @@ -357,7 +357,7 @@ static int ltc3676_regulator_probe(struct i2c_client *client) } static const struct i2c_device_id ltc3676_i2c_id[] = { - { "ltc3676" }, + { .name = "ltc3676" }, { } }; MODULE_DEVICE_TABLE(i2c, ltc3676_i2c_id); diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 4242fbb7b147..e5cbc09c2d39 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -276,7 +276,7 @@ static int max1586_pmic_probe(struct i2c_client *client) } static const struct i2c_device_id max1586_id[] = { - { "max1586" }, + { .name = "max1586" }, { } }; MODULE_DEVICE_TABLE(i2c, max1586_id); diff --git a/drivers/regulator/max20086-regulator.c b/drivers/regulator/max20086-regulator.c index fcdd2d0317a5..92594b2915f3 100644 --- a/drivers/regulator/max20086-regulator.c +++ b/drivers/regulator/max20086-regulator.c @@ -301,10 +301,10 @@ static const struct max20086_chip_info max20089_chip_info = { }; static const struct i2c_device_id max20086_i2c_id[] = { - { "max20086", (kernel_ulong_t)&max20086_chip_info }, - { "max20087", (kernel_ulong_t)&max20087_chip_info }, - { "max20088", (kernel_ulong_t)&max20088_chip_info }, - { "max20089", (kernel_ulong_t)&max20089_chip_info }, + { .name = "max20086", .driver_data = (kernel_ulong_t)&max20086_chip_info }, + { .name = "max20087", .driver_data = (kernel_ulong_t)&max20087_chip_info }, + { .name = "max20088", .driver_data = (kernel_ulong_t)&max20088_chip_info }, + { .name = "max20089", .driver_data = (kernel_ulong_t)&max20089_chip_info }, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(i2c, max20086_i2c_id); diff --git a/drivers/regulator/max20411-regulator.c b/drivers/regulator/max20411-regulator.c index 6c0ebb970e90..ac7a9aa014aa 100644 --- a/drivers/regulator/max20411-regulator.c +++ b/drivers/regulator/max20411-regulator.c @@ -145,7 +145,7 @@ static const struct of_device_id of_max20411_match_tbl[] = { MODULE_DEVICE_TABLE(of, of_max20411_match_tbl); static const struct i2c_device_id max20411_id[] = { - { "max20411" }, + { .name = "max20411" }, { } }; MODULE_DEVICE_TABLE(i2c, max20411_id); diff --git a/drivers/regulator/max77503-regulator.c b/drivers/regulator/max77503-regulator.c index c7c94e868fc1..1cae846f96d0 100644 --- a/drivers/regulator/max77503-regulator.c +++ b/drivers/regulator/max77503-regulator.c @@ -107,7 +107,7 @@ static const struct of_device_id of_max77503_match_tbl[] = { MODULE_DEVICE_TABLE(of, of_max77503_match_tbl); static const struct i2c_device_id max77503_regulator_id[] = { - {"max77503"}, + { .name = "max77503" }, { } }; diff --git a/drivers/regulator/max77826-regulator.c b/drivers/regulator/max77826-regulator.c index 310bc8ee7af8..8b60a9fcab44 100644 --- a/drivers/regulator/max77826-regulator.c +++ b/drivers/regulator/max77826-regulator.c @@ -278,7 +278,7 @@ static const struct of_device_id __maybe_unused max77826_of_match[] = { MODULE_DEVICE_TABLE(of, max77826_of_match); static const struct i2c_device_id max77826_id[] = { - { "max77826-regulator" }, + { .name = "max77826-regulator" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, max77826_id); diff --git a/drivers/regulator/max77838-regulator.c b/drivers/regulator/max77838-regulator.c index 9faddbfd25fd..765756fdcf6e 100644 --- a/drivers/regulator/max77838-regulator.c +++ b/drivers/regulator/max77838-regulator.c @@ -200,7 +200,7 @@ static const struct of_device_id __maybe_unused max77838_of_match[] = { MODULE_DEVICE_TABLE(of, max77838_of_match); static const struct i2c_device_id max77838_id[] = { - { "max77838-regulator" }, + { .name = "max77838-regulator" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, max77838_id); diff --git a/drivers/regulator/max77857-regulator.c b/drivers/regulator/max77857-regulator.c index 1216cc3a6f72..f1410f845653 100644 --- a/drivers/regulator/max77857-regulator.c +++ b/drivers/regulator/max77857-regulator.c @@ -428,10 +428,10 @@ static int max77857_probe(struct i2c_client *client) } static const struct i2c_device_id max77857_id[] = { - { "max77831", ID_MAX77831 }, - { "max77857", ID_MAX77857 }, - { "max77859", ID_MAX77859 }, - { "max77859a", ID_MAX77859A }, + { .name = "max77831", .driver_data = ID_MAX77831 }, + { .name = "max77857", .driver_data = ID_MAX77857 }, + { .name = "max77859", .driver_data = ID_MAX77859 }, + { .name = "max77859a", .driver_data = ID_MAX77859A }, { } }; MODULE_DEVICE_TABLE(i2c, max77857_id); diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index f57c588bcf28..2d17405242e7 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -240,7 +240,7 @@ static int max8649_regulator_probe(struct i2c_client *client) } static const struct i2c_device_id max8649_id[] = { - { "max8649" }, + { .name = "max8649" }, { } }; MODULE_DEVICE_TABLE(i2c, max8649_id); diff --git a/drivers/regulator/max8893.c b/drivers/regulator/max8893.c index 5a90633d8536..7a0e44a16d49 100644 --- a/drivers/regulator/max8893.c +++ b/drivers/regulator/max8893.c @@ -162,7 +162,7 @@ MODULE_DEVICE_TABLE(of, max8893_dt_match); #endif static const struct i2c_device_id max8893_ids[] = { - { "max8893" }, + { .name = "max8893" }, { } }; MODULE_DEVICE_TABLE(i2c, max8893_ids); diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index 1f94315bfb02..f8b91a5701f3 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -307,7 +307,7 @@ static int max8952_pmic_probe(struct i2c_client *client) } static const struct i2c_device_id max8952_ids[] = { - { "max8952" }, + { .name = "max8952" }, { } }; MODULE_DEVICE_TABLE(i2c, max8952_ids); diff --git a/drivers/regulator/mcp16502.c b/drivers/regulator/mcp16502.c index b34ae0bbba6f..89fd79d446f7 100644 --- a/drivers/regulator/mcp16502.c +++ b/drivers/regulator/mcp16502.c @@ -578,7 +578,7 @@ static const struct dev_pm_ops mcp16502_pm_ops = { }; #endif static const struct i2c_device_id mcp16502_i2c_id[] = { - { "mcp16502" }, + { .name = "mcp16502" }, { } }; MODULE_DEVICE_TABLE(i2c, mcp16502_i2c_id); diff --git a/drivers/regulator/mp5416.c b/drivers/regulator/mp5416.c index e6794190cb68..2948635b1b9f 100644 --- a/drivers/regulator/mp5416.c +++ b/drivers/regulator/mp5416.c @@ -228,9 +228,9 @@ static const struct of_device_id mp5416_of_match[] = { MODULE_DEVICE_TABLE(of, mp5416_of_match); static const struct i2c_device_id mp5416_id[] = { - { "mp5416", (kernel_ulong_t)&mp5416_regulators_desc }, - { "mp5496", (kernel_ulong_t)&mp5496_regulators_desc }, - {} + { .name = "mp5416", .driver_data = (kernel_ulong_t)&mp5416_regulators_desc }, + { .name = "mp5496", .driver_data = (kernel_ulong_t)&mp5496_regulators_desc }, + { } }; MODULE_DEVICE_TABLE(i2c, mp5416_id); diff --git a/drivers/regulator/mp8859.c b/drivers/regulator/mp8859.c index ab105ffd6a2e..9a708e826d93 100644 --- a/drivers/regulator/mp8859.c +++ b/drivers/regulator/mp8859.c @@ -386,8 +386,8 @@ static const struct of_device_id mp8859_dt_id[] __maybe_unused = { MODULE_DEVICE_TABLE(of, mp8859_dt_id); static const struct i2c_device_id mp8859_i2c_id[] = { - { "mp8859", }, - { }, + { .name = "mp8859" }, + { } }; MODULE_DEVICE_TABLE(i2c, mp8859_i2c_id); diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c index 9ad16b04c913..e0b62bc02a1e 100644 --- a/drivers/regulator/mp886x.c +++ b/drivers/regulator/mp886x.c @@ -348,9 +348,9 @@ static const struct of_device_id mp886x_dt_ids[] = { MODULE_DEVICE_TABLE(of, mp886x_dt_ids); static const struct i2c_device_id mp886x_id[] = { - { "mp8867", (kernel_ulong_t)&mp8867_ci }, - { "mp8869", (kernel_ulong_t)&mp8869_ci }, - { }, + { .name = "mp8867", .driver_data = (kernel_ulong_t)&mp8867_ci }, + { .name = "mp8869", .driver_data = (kernel_ulong_t)&mp8869_ci }, + { } }; MODULE_DEVICE_TABLE(i2c, mp886x_id); diff --git a/drivers/regulator/mpq7920.c b/drivers/regulator/mpq7920.c index a670e09891e7..0cbc17deb1d1 100644 --- a/drivers/regulator/mpq7920.c +++ b/drivers/regulator/mpq7920.c @@ -309,8 +309,8 @@ static const struct of_device_id mpq7920_of_match[] = { MODULE_DEVICE_TABLE(of, mpq7920_of_match); static const struct i2c_device_id mpq7920_id[] = { - { "mpq7920", }, - { }, + { .name = "mpq7920" }, + { } }; MODULE_DEVICE_TABLE(i2c, mpq7920_id); diff --git a/drivers/regulator/mt6311-regulator.c b/drivers/regulator/mt6311-regulator.c index 2ebc1c0b5e6f..1d457d1fdf23 100644 --- a/drivers/regulator/mt6311-regulator.c +++ b/drivers/regulator/mt6311-regulator.c @@ -133,8 +133,8 @@ static int mt6311_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id mt6311_i2c_id[] = { - { "mt6311" }, - {} + { .name = "mt6311" }, + { } }; MODULE_DEVICE_TABLE(i2c, mt6311_i2c_id); diff --git a/drivers/regulator/pf8x00-regulator.c b/drivers/regulator/pf8x00-regulator.c index ea3611de42b4..c938b4632ef1 100644 --- a/drivers/regulator/pf8x00-regulator.c +++ b/drivers/regulator/pf8x00-regulator.c @@ -596,10 +596,10 @@ static const struct of_device_id pf8x00_dt_ids[] = { MODULE_DEVICE_TABLE(of, pf8x00_dt_ids); static const struct i2c_device_id pf8x00_i2c_id[] = { - { "pf8100" }, - { "pf8121a" }, - { "pf8200" }, - {} + { .name = "pf8100" }, + { .name = "pf8121a" }, + { .name = "pf8200" }, + { } }; MODULE_DEVICE_TABLE(i2c, pf8x00_i2c_id); diff --git a/drivers/regulator/pv88060-regulator.c b/drivers/regulator/pv88060-regulator.c index ae1c4b9daaa1..375d9e759c47 100644 --- a/drivers/regulator/pv88060-regulator.c +++ b/drivers/regulator/pv88060-regulator.c @@ -360,8 +360,8 @@ static int pv88060_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id pv88060_i2c_id[] = { - { "pv88060" }, - {} + { .name = "pv88060" }, + { } }; MODULE_DEVICE_TABLE(i2c, pv88060_i2c_id); diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c index 9fe539a34786..3dc48d059791 100644 --- a/drivers/regulator/pv88080-regulator.c +++ b/drivers/regulator/pv88080-regulator.c @@ -523,10 +523,10 @@ static const struct of_device_id pv88080_dt_ids[] = { MODULE_DEVICE_TABLE(of, pv88080_dt_ids); static const struct i2c_device_id pv88080_i2c_id[] = { - { "pv88080", (kernel_ulong_t)&pv88080_aa_regs }, - { "pv88080-aa", (kernel_ulong_t)&pv88080_aa_regs }, - { "pv88080-ba", (kernel_ulong_t)&pv88080_ba_regs }, - {} + { .name = "pv88080", .driver_data = (kernel_ulong_t)&pv88080_aa_regs }, + { .name = "pv88080-aa", .driver_data = (kernel_ulong_t)&pv88080_aa_regs }, + { .name = "pv88080-ba", .driver_data = (kernel_ulong_t)&pv88080_ba_regs }, + { } }; MODULE_DEVICE_TABLE(i2c, pv88080_i2c_id); diff --git a/drivers/regulator/pv88090-regulator.c b/drivers/regulator/pv88090-regulator.c index 3c48757bbbda..ca5eeb5dfe62 100644 --- a/drivers/regulator/pv88090-regulator.c +++ b/drivers/regulator/pv88090-regulator.c @@ -381,8 +381,8 @@ static int pv88090_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id pv88090_i2c_id[] = { - { "pv88090" }, - {} + { .name = "pv88090" }, + { } }; MODULE_DEVICE_TABLE(i2c, pv88090_i2c_id); diff --git a/drivers/regulator/sgm3804-regulator.c b/drivers/regulator/sgm3804-regulator.c index c3406cfb73d0..a34c9418b275 100644 --- a/drivers/regulator/sgm3804-regulator.c +++ b/drivers/regulator/sgm3804-regulator.c @@ -285,7 +285,7 @@ static int sgm3804_probe(struct i2c_client *i2c) } static const struct i2c_device_id sgm3804_id[] = { - { "sgm3804" }, + { .name = "sgm3804" }, { } }; MODULE_DEVICE_TABLE(i2c, sgm3804_id); diff --git a/drivers/regulator/slg51000-regulator.c b/drivers/regulator/slg51000-regulator.c index 3bbd4a29e6d3..d682764cdbf8 100644 --- a/drivers/regulator/slg51000-regulator.c +++ b/drivers/regulator/slg51000-regulator.c @@ -497,8 +497,8 @@ static int slg51000_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id slg51000_i2c_id[] = { - { "slg51000" }, - {} + { .name = "slg51000" }, + { } }; MODULE_DEVICE_TABLE(i2c, slg51000_i2c_id); diff --git a/drivers/regulator/sy8106a-regulator.c b/drivers/regulator/sy8106a-regulator.c index d79a4cc25a0d..b2b835c60262 100644 --- a/drivers/regulator/sy8106a-regulator.c +++ b/drivers/regulator/sy8106a-regulator.c @@ -130,7 +130,7 @@ static const struct of_device_id sy8106a_i2c_of_match[] = { MODULE_DEVICE_TABLE(of, sy8106a_i2c_of_match); static const struct i2c_device_id sy8106a_i2c_id[] = { - { "sy8106a" }, + { .name = "sy8106a" }, { } }; MODULE_DEVICE_TABLE(i2c, sy8106a_i2c_id); diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c index 5bec84db25f1..3f07e7da90cb 100644 --- a/drivers/regulator/sy8824x.c +++ b/drivers/regulator/sy8824x.c @@ -213,10 +213,10 @@ static const struct of_device_id sy8824_dt_ids[] = { MODULE_DEVICE_TABLE(of, sy8824_dt_ids); static const struct i2c_device_id sy8824_id[] = { - { "sy8824c", (kernel_ulong_t)&sy8824c_cfg }, - { "sy8824e", (kernel_ulong_t)&sy8824e_cfg }, - { "sy20276", (kernel_ulong_t)&sy20276_cfg }, - { "sy20278", (kernel_ulong_t)&sy20278_cfg }, + { .name = "sy8824c", .driver_data = (kernel_ulong_t)&sy8824c_cfg }, + { .name = "sy8824e", .driver_data = (kernel_ulong_t)&sy8824e_cfg }, + { .name = "sy20276", .driver_data = (kernel_ulong_t)&sy20276_cfg }, + { .name = "sy20278", .driver_data = (kernel_ulong_t)&sy20278_cfg }, { } }; MODULE_DEVICE_TABLE(i2c, sy8824_id); diff --git a/drivers/regulator/sy8827n.c b/drivers/regulator/sy8827n.c index 0b811514782f..a1cac8cc3d96 100644 --- a/drivers/regulator/sy8827n.c +++ b/drivers/regulator/sy8827n.c @@ -180,8 +180,8 @@ static const struct of_device_id sy8827n_dt_ids[] = { MODULE_DEVICE_TABLE(of, sy8827n_dt_ids); static const struct i2c_device_id sy8827n_id[] = { - { "sy8827n", }, - { }, + { .name = "sy8827n" }, + { } }; MODULE_DEVICE_TABLE(i2c, sy8827n_id); diff --git a/drivers/regulator/tps6286x-regulator.c b/drivers/regulator/tps6286x-regulator.c index e29aab06bf79..1ab53bee9f6e 100644 --- a/drivers/regulator/tps6286x-regulator.c +++ b/drivers/regulator/tps6286x-regulator.c @@ -145,11 +145,11 @@ static int tps6286x_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id tps6286x_i2c_id[] = { - { "tps62864" }, - { "tps62866" }, - { "tps62868" }, - { "tps62869" }, - {} + { .name = "tps62864" }, + { .name = "tps62866" }, + { .name = "tps62868" }, + { .name = "tps62869" }, + { } }; MODULE_DEVICE_TABLE(i2c, tps6286x_i2c_id); diff --git a/drivers/regulator/tps6287x-regulator.c b/drivers/regulator/tps6287x-regulator.c index 7b7d3ae39206..c0bc4a6192c4 100644 --- a/drivers/regulator/tps6287x-regulator.c +++ b/drivers/regulator/tps6287x-regulator.c @@ -229,11 +229,11 @@ static const struct of_device_id tps6287x_dt_ids[] = { MODULE_DEVICE_TABLE(of, tps6287x_dt_ids); static const struct i2c_device_id tps6287x_i2c_id[] = { - { "tps62870" }, - { "tps62871" }, - { "tps62872" }, - { "tps62873" }, - {} + { .name = "tps62870" }, + { .name = "tps62871" }, + { .name = "tps62872" }, + { .name = "tps62873" }, + { } }; MODULE_DEVICE_TABLE(i2c, tps6287x_i2c_id); From 2924fa8381ee20d26fad75d749af71b845f57749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig=20=28The=20Capable=20Hub=29?= Date: Tue, 30 Jun 2026 16:01:09 +0200 Subject: [PATCH 09/36] regulator: Improve style of i2c_device_id arrays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two previous patches did some style improvements while adapting the i2c_device_id arrays. Adapt all the remaining regulator drivers to use the same style. That is: - Use a comma after a initialisation value unless the closing } is in the same line. - Don't use a comma after the list terminator. - Use a space after the opening { and one before the closing }; a single space for an empty pair. Signed-off-by: Uwe Kleine-König (The Capable Hub) Link: https://patch.msgid.link/221a2e634f6bbf9638b906470ffb1b2b413e0a5a.1782827697.git.u.kleine-koenig@baylibre.com Signed-off-by: Mark Brown --- drivers/regulator/act8865-regulator.c | 2 +- drivers/regulator/adp5055-regulator.c | 4 ++-- drivers/regulator/aw37503-regulator.c | 4 ++-- drivers/regulator/isl6271a-regulator.c | 2 +- drivers/regulator/max8973-regulator.c | 6 +++--- drivers/regulator/tps51632-regulator.c | 4 ++-- drivers/regulator/tps62360-regulator.c | 10 +++++----- drivers/regulator/tps65023-regulator.c | 6 +++--- drivers/regulator/tps65132-regulator.c | 4 ++-- 9 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index b2a6ddc6f56d..882b6e58e911 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -780,7 +780,7 @@ static const struct i2c_device_id act8865_ids[] = { { .name = "act8600", .driver_data = ACT8600 }, { .name = "act8846", .driver_data = ACT8846 }, { .name = "act8865", .driver_data = ACT8865 }, - { }, + { } }; MODULE_DEVICE_TABLE(i2c, act8865_ids); diff --git a/drivers/regulator/adp5055-regulator.c b/drivers/regulator/adp5055-regulator.c index 4b004a6b2f84..bba138360df1 100644 --- a/drivers/regulator/adp5055-regulator.c +++ b/drivers/regulator/adp5055-regulator.c @@ -404,8 +404,8 @@ static const struct of_device_id adp5055_of_match[] = { MODULE_DEVICE_TABLE(of, adp5055_of_match); static const struct i2c_device_id adp5055_ids[] = { - { .name = "adp5055"}, - { }, + { .name = "adp5055" }, + { } }; MODULE_DEVICE_TABLE(i2c, adp5055_ids); diff --git a/drivers/regulator/aw37503-regulator.c b/drivers/regulator/aw37503-regulator.c index a5ff6dfd29b5..ca5f2a14c28c 100644 --- a/drivers/regulator/aw37503-regulator.c +++ b/drivers/regulator/aw37503-regulator.c @@ -212,8 +212,8 @@ static int aw37503_probe(struct i2c_client *client) } static const struct i2c_device_id aw37503_id[] = { - {.name = "aw37503",}, - {}, + { .name = "aw37503" }, + { } }; MODULE_DEVICE_TABLE(i2c, aw37503_id); diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index 7883cd160727..868f2b823a10 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -138,7 +138,7 @@ static int isl6271a_probe(struct i2c_client *i2c) } static const struct i2c_device_id isl6271a_id[] = { - { .name = "isl6271a", }, + { .name = "isl6271a" }, { } }; diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c index f68caa07f546..95062032dc7e 100644 --- a/drivers/regulator/max8973-regulator.c +++ b/drivers/regulator/max8973-regulator.c @@ -780,9 +780,9 @@ static int max8973_probe(struct i2c_client *client) } static const struct i2c_device_id max8973_id[] = { - {.name = "max8973", .driver_data = MAX8973}, - {.name = "max77621", .driver_data = MAX77621}, - {}, + { .name = "max8973", .driver_data = MAX8973 }, + { .name = "max77621", .driver_data = MAX77621 }, + { } }; MODULE_DEVICE_TABLE(i2c, max8973_id); diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c index 3a384bf9d2c5..8459b49ec26e 100644 --- a/drivers/regulator/tps51632-regulator.c +++ b/drivers/regulator/tps51632-regulator.c @@ -331,8 +331,8 @@ static int tps51632_probe(struct i2c_client *client) } static const struct i2c_device_id tps51632_id[] = { - {.name = "tps51632",}, - {}, + { .name = "tps51632" }, + { } }; MODULE_DEVICE_TABLE(i2c, tps51632_id); diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index be6a6702cbfa..00f19082c1da 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -476,11 +476,11 @@ static void tps62360_shutdown(struct i2c_client *client) } static const struct i2c_device_id tps62360_id[] = { - {.name = "tps62360", .driver_data = TPS62360}, - {.name = "tps62361", .driver_data = TPS62361}, - {.name = "tps62362", .driver_data = TPS62362}, - {.name = "tps62363", .driver_data = TPS62363}, - {}, + { .name = "tps62360", .driver_data = TPS62360 }, + { .name = "tps62361", .driver_data = TPS62361 }, + { .name = "tps62362", .driver_data = TPS62362 }, + { .name = "tps62363", .driver_data = TPS62363 }, + { } }; MODULE_DEVICE_TABLE(i2c, tps62360_id); diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 3334b5b7d907..5a2fc57cddf6 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -319,13 +319,13 @@ MODULE_DEVICE_TABLE(of, tps65023_of_match); static const struct i2c_device_id tps_65023_id[] = { { .name = "tps65023", - .driver_data = (kernel_ulong_t)&tps65023_drv_data + .driver_data = (kernel_ulong_t)&tps65023_drv_data, }, { .name = "tps65021", - .driver_data = (kernel_ulong_t)&tps65021_drv_data + .driver_data = (kernel_ulong_t)&tps65021_drv_data, }, { .name = "tps65020", - .driver_data = (kernel_ulong_t)&tps65020_drv_data + .driver_data = (kernel_ulong_t)&tps65020_drv_data, }, { }, }; diff --git a/drivers/regulator/tps65132-regulator.c b/drivers/regulator/tps65132-regulator.c index 9c2f0dd42613..fecda3fd8ebc 100644 --- a/drivers/regulator/tps65132-regulator.c +++ b/drivers/regulator/tps65132-regulator.c @@ -262,8 +262,8 @@ static int tps65132_probe(struct i2c_client *client) } static const struct i2c_device_id tps65132_id[] = { - {.name = "tps65132",}, - {}, + { .name = "tps65132" }, + { } }; MODULE_DEVICE_TABLE(i2c, tps65132_id); From 7fd28093b3effc4f92566466df364622830ec608 Mon Sep 17 00:00:00 2001 From: Uday Khare Date: Thu, 18 Jun 2026 18:53:27 +0530 Subject: [PATCH 10/36] regulator: tps6594: Fix device node reference leaks in multiphase loop In tps6594_regulator_probe(), the multi-phase configuration loop calls of_find_node_by_name() to find buck nodes by name, and of_get_parent() twice to navigate to the PMIC parent node. None of the acquired node references (np, intermediate parent, np_pmic_parent) are ever released via of_node_put(), causing a reference leak on every loop iteration. Additionally, of_find_node_by_name() can return NULL, but the result was immediately passed to of_node_full_name() and of_get_parent() without a NULL check, which could lead to a NULL pointer dereference. Fix this by: - Adding a NULL check for np after of_find_node_by_name() - Storing the intermediate parent node in a local variable np_parent - Calling of_node_put() on np, np_parent and np_pmic_parent at the end of each loop iteration Fixes: f17ccc5deb4d ("regulator: tps6594-regulator: Add driver for TI TPS6594 regulators") Signed-off-by: Uday Khare Link: https://patch.msgid.link/20260618132327.11529-1-udaykhare77@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/tps6594-regulator.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/tps6594-regulator.c b/drivers/regulator/tps6594-regulator.c index 645e83462c64..31a5218d5510 100644 --- a/drivers/regulator/tps6594-regulator.c +++ b/drivers/regulator/tps6594-regulator.c @@ -669,13 +669,20 @@ static int tps6594_regulator_probe(struct platform_device *pdev) * buck_configured to avoid creating bucks for every buck in multiphase */ for (multi = 0; multi < desc->num_multi_phase_regs; multi++) { + struct device_node *np_parent; + multi_regs = &desc->multi_phase_regs[multi]; np = of_find_node_by_name(tps->dev->of_node, multi_regs->supply_name); - npname = of_node_full_name(np); - np_pmic_parent = of_get_parent(of_get_parent(np)); - if (of_node_cmp(of_node_full_name(np_pmic_parent), tps->dev->of_node->full_name)) + if (!np) continue; - if (strcmp(npname, multi_regs->supply_name) == 0) { + + npname = of_node_full_name(np); + np_parent = of_get_parent(np); + np_pmic_parent = of_get_parent(np_parent); + + if (np_pmic_parent && + !of_node_cmp(of_node_full_name(np_pmic_parent), tps->dev->of_node->full_name) && + strcmp(npname, multi_regs->supply_name) == 0) { switch (multi) { case MULTI_BUCK12: buck_multi[0] = true; @@ -706,6 +713,10 @@ static int tps6594_regulator_probe(struct platform_device *pdev) break; } } + + of_node_put(np_pmic_parent); + of_node_put(np_parent); + of_node_put(np); } reg_irq_nb = desc->num_irq_types * (desc->num_buck_regs + desc->num_ldo_regs); From f9324d670ae0b88cbfb0aa48fcaefa5baeb8da4c Mon Sep 17 00:00:00 2001 From: WenTao Liang Date: Sat, 27 Jun 2026 00:01:50 +0800 Subject: [PATCH 11/36] regulator: as3722_get_regulator_dt_data: fix premature of_node_put leaving dangling of_node pointer In as3722_get_regulator_dt_data(), of_get_child_by_name() acquires a reference on np, which is then assigned to pdev->dev.of_node. The function immediately calls of_node_put(np), releasing the reference and leaving pdev->dev.of_node as a dangling pointer. Remove the of_node_put(np) call to let the device hold the reference. Cc: stable@vger.kernel.org Fixes: bc407334e9a6 ("regulator: as3722: add regulator driver for AMS AS3722") Signed-off-by: WenTao Liang Link: https://patch.msgid.link/20260626160150.54291-1-vulab@iscas.ac.cn Signed-off-by: Mark Brown --- drivers/regulator/as3722-regulator.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c index da378bfdba40..85e2aaa1a06b 100644 --- a/drivers/regulator/as3722-regulator.c +++ b/drivers/regulator/as3722-regulator.c @@ -600,7 +600,6 @@ static int as3722_get_regulator_dt_data(struct platform_device *pdev, ret = of_regulator_match(&pdev->dev, np, as3722_regulator_matches, ARRAY_SIZE(as3722_regulator_matches)); - of_node_put(np); if (ret < 0) { dev_err(&pdev->dev, "Parsing of regulator node failed: %d\n", ret); From 7c8cc25d8d86f9eb3979255935cfdc7d062ad746 Mon Sep 17 00:00:00 2001 From: WenTao Liang Date: Sat, 27 Jun 2026 00:03:26 +0800 Subject: [PATCH 12/36] regulator: max8998_pmic_dt_parse_pdata: of_node_put on reg_np after ownership transferred to rdata In max8998_pmic_dt_parse_pdata(), of_get_child_by_name() acquires a reference on reg_np which is then stored in rdata->reg_node, transferring ownership to the regulator data array. The subsequent of_node_put(reg_np) at the end of the function releases the last matched regulator node's reference, leaving rdata->reg_node as a dangling pointer for the last entry. Remove the spurious of_node_put(reg_np) call. Cc: stable@vger.kernel.org Fixes: 156f252857df ("drivers: regulator: add Maxim 8998 driver") Signed-off-by: WenTao Liang Link: https://patch.msgid.link/20260626160326.54457-1-vulab@iscas.ac.cn Signed-off-by: Mark Brown --- drivers/regulator/max8998.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index cc85fbe8b77c..90651f4d1828 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -582,7 +582,6 @@ static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev, } pdata->num_regulators = rdata - pdata->regulators; - of_node_put(reg_np); of_node_put(regulators_np); pdata->buck_voltage_lock = of_property_read_bool(pmic_np, "max8998,pmic-buck-voltage-lock"); From 4c40e28e833d0142352e8294d50dde637c163a76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Otto=20Pfl=C3=BCger?= Date: Wed, 1 Jul 2026 17:00:02 +0200 Subject: [PATCH 13/36] regulator: Add regulator driver for Unisoc SC2730 PMIC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a regulator driver for the Spreadtrum/Unisoc SC2730 PMIC, used e.g. with the UMS512 and UMS9230 SoCs. This version of the driver is based on a downstream driver provided by Unisoc [1][2] and the existing SC2731 driver. [1]: https://github.com/MotorolaMobilityLLC/kernel-sprd/commit/30be0ddfe6b9a877fc9c328fbd2bae84e645eb31 [2]: https://github.com/MotorolaMobilityLLC/kernel-sprd/blob/android-13-release-tla33/drivers/regulator/sc2730-regulator.c Signed-off-by: Zhongfa Wang [cleanup, adapt to new device tree requirements] Signed-off-by: Otto Pflüger Link: https://patch.msgid.link/20260701-sc2730-regulators-v7-2-6e145ce83657@abscue.de Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 7 + drivers/regulator/Makefile | 1 + drivers/regulator/sc2730-regulator.c | 375 +++++++++++++++++++++++++++ 3 files changed, 383 insertions(+) create mode 100644 drivers/regulator/sc2730-regulator.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index a54a549196fe..89789ac7a786 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -1477,6 +1477,13 @@ config REGULATOR_S5M8767 via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and supports DVS mode with 8bits of output voltage control. +config REGULATOR_SC2730 + tristate "Spreadtrum SC2730 power regulator driver" + depends on MFD_SC27XX_PMIC || COMPILE_TEST + help + This driver provides support for the voltage regulators on the + SC2730 PMIC. + config REGULATOR_SC2731 tristate "Spreadtrum SC2731 power regulator driver" depends on MFD_SC27XX_PMIC || COMPILE_TEST diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 134eee274dbf..5a764cec8df8 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -170,6 +170,7 @@ obj-$(CONFIG_REGULATOR_S2DOS05) += s2dos05-regulator.o obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o +obj-$(CONFIG_REGULATOR_SC2730) += sc2730-regulator.o obj-$(CONFIG_REGULATOR_SC2731) += sc2731-regulator.o obj-$(CONFIG_REGULATOR_SGM3804) += sgm3804-regulator.o obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o diff --git a/drivers/regulator/sc2730-regulator.c b/drivers/regulator/sc2730-regulator.c new file mode 100644 index 000000000000..166b19ed539b --- /dev/null +++ b/drivers/regulator/sc2730-regulator.c @@ -0,0 +1,375 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018-2021 Unisoc Inc. + */ + +#include +#include +#include +#include +#include +#include + +/* + * SC2730 regulator base address + */ +#define SC2730_REGULATOR_BASE 0x1800 + +/* + * SC2730 regulator lock register + */ +#define SC2730_WR_UNLOCK_VALUE 0x6e7f +#define SC2730_PWR_WR_PROT (SC2730_REGULATOR_BASE + 0x3d0) + +/* + * SC2730 enable register + */ +#define SC2730_POWER_PD_SW (SC2730_REGULATOR_BASE + 0x01c) +#define SC2730_LDO_VDDRF18_PD (SC2730_REGULATOR_BASE + 0x10c) +#define SC2730_LDO_VDDCAMIO_PD (SC2730_REGULATOR_BASE + 0x118) +#define SC2730_LDO_VDDWCN_PD (SC2730_REGULATOR_BASE + 0x11c) +#define SC2730_LDO_VDDCAMD1_PD (SC2730_REGULATOR_BASE + 0x128) +#define SC2730_LDO_VDDCAMD0_PD (SC2730_REGULATOR_BASE + 0x134) +#define SC2730_LDO_VDDRF1V25_PD (SC2730_REGULATOR_BASE + 0x140) +#define SC2730_LDO_AVDD12_PD (SC2730_REGULATOR_BASE + 0x14c) +#define SC2730_LDO_VDDCAMA0_PD (SC2730_REGULATOR_BASE + 0x158) +#define SC2730_LDO_VDDCAMA1_PD (SC2730_REGULATOR_BASE + 0x164) +#define SC2730_LDO_VDDCAMMOT_PD (SC2730_REGULATOR_BASE + 0x170) +#define SC2730_LDO_VDDSIM2_PD (SC2730_REGULATOR_BASE + 0x194) +#define SC2730_LDO_VDDEMMCCORE_PD (SC2730_REGULATOR_BASE + 0x1a0) +#define SC2730_LDO_VDDSDCORE_PD (SC2730_REGULATOR_BASE + 0x1ac) +#define SC2730_LDO_VDDSDIO_PD (SC2730_REGULATOR_BASE + 0x1b8) +#define SC2730_LDO_VDDWIFIPA_PD (SC2730_REGULATOR_BASE + 0x1d0) +#define SC2730_LDO_VDDUSB33_PD (SC2730_REGULATOR_BASE + 0x1e8) +#define SC2730_LDO_VDDLDO0_PD (SC2730_REGULATOR_BASE + 0x1f4) +#define SC2730_LDO_VDDLDO1_PD (SC2730_REGULATOR_BASE + 0x200) +#define SC2730_LDO_VDDLDO2_PD (SC2730_REGULATOR_BASE + 0x20c) +#define SC2730_LDO_VDDKPLED_PD (SC2730_REGULATOR_BASE + 0x38c) + +/* + * SC2730 enable mask + */ +#define SC2730_DCDC_CPU_PD_MASK BIT(4) +#define SC2730_DCDC_GPU_PD_MASK BIT(3) +#define SC2730_DCDC_CORE_PD_MASK BIT(5) +#define SC2730_DCDC_MODEM_PD_MASK BIT(11) +#define SC2730_DCDC_MEM_PD_MASK BIT(6) +#define SC2730_DCDC_MEMQ_PD_MASK BIT(12) +#define SC2730_DCDC_GEN0_PD_MASK BIT(8) +#define SC2730_DCDC_GEN1_PD_MASK BIT(7) +#define SC2730_DCDC_SRAM_PD_MASK BIT(13) +#define SC2730_LDO_AVDD18_PD_MASK BIT(2) +#define SC2730_LDO_VDDRF18_PD_MASK BIT(0) +#define SC2730_LDO_VDDCAMIO_PD_MASK BIT(0) +#define SC2730_LDO_VDDWCN_PD_MASK BIT(0) +#define SC2730_LDO_VDDCAMD1_PD_MASK BIT(0) +#define SC2730_LDO_VDDCAMD0_PD_MASK BIT(0) +#define SC2730_LDO_VDDRF1V25_PD_MASK BIT(0) +#define SC2730_LDO_AVDD12_PD_MASK BIT(0) +#define SC2730_LDO_VDDCAMA0_PD_MASK BIT(0) +#define SC2730_LDO_VDDCAMA1_PD_MASK BIT(0) +#define SC2730_LDO_VDDCAMMOT_PD_MASK BIT(0) +#define SC2730_LDO_VDDSIM2_PD_MASK BIT(0) +#define SC2730_LDO_VDDEMMCCORE_PD_MASK BIT(0) +#define SC2730_LDO_VDDSDCORE_PD_MASK BIT(0) +#define SC2730_LDO_VDDSDIO_PD_MASK BIT(0) +#define SC2730_LDO_VDD28_PD_MASK BIT(1) +#define SC2730_LDO_VDDWIFIPA_PD_MASK BIT(0) +#define SC2730_LDO_VDD18_DCXO_PD_MASK BIT(10) +#define SC2730_LDO_VDDUSB33_PD_MASK BIT(0) +#define SC2730_LDO_VDDLDO0_PD_MASK BIT(0) +#define SC2730_LDO_VDDLDO1_PD_MASK BIT(0) +#define SC2730_LDO_VDDLDO2_PD_MASK BIT(0) +#define SC2730_LDO_VDDKPLED_PD_MASK BIT(15) + +/* + * SC2730 vsel register + */ +#define SC2730_DCDC_CPU_VOL (SC2730_REGULATOR_BASE + 0x44) +#define SC2730_DCDC_GPU_VOL (SC2730_REGULATOR_BASE + 0x54) +#define SC2730_DCDC_CORE_VOL (SC2730_REGULATOR_BASE + 0x64) +#define SC2730_DCDC_MODEM_VOL (SC2730_REGULATOR_BASE + 0x74) +#define SC2730_DCDC_MEM_VOL (SC2730_REGULATOR_BASE + 0x84) +#define SC2730_DCDC_MEMQ_VOL (SC2730_REGULATOR_BASE + 0x94) +#define SC2730_DCDC_GEN0_VOL (SC2730_REGULATOR_BASE + 0xa4) +#define SC2730_DCDC_GEN1_VOL (SC2730_REGULATOR_BASE + 0xb4) +#define SC2730_DCDC_SRAM_VOL (SC2730_REGULATOR_BASE + 0xdc) +#define SC2730_LDO_AVDD18_VOL (SC2730_REGULATOR_BASE + 0x104) +#define SC2730_LDO_VDDRF18_VOL (SC2730_REGULATOR_BASE + 0x110) +#define SC2730_LDO_VDDCAMIO_VOL (SC2730_REGULATOR_BASE + 0x28) +#define SC2730_LDO_VDDWCN_VOL (SC2730_REGULATOR_BASE + 0x120) +#define SC2730_LDO_VDDCAMD1_VOL (SC2730_REGULATOR_BASE + 0x12c) +#define SC2730_LDO_VDDCAMD0_VOL (SC2730_REGULATOR_BASE + 0x138) +#define SC2730_LDO_VDDRF1V25_VOL (SC2730_REGULATOR_BASE + 0x144) +#define SC2730_LDO_AVDD12_VOL (SC2730_REGULATOR_BASE + 0x150) +#define SC2730_LDO_VDDCAMA0_VOL (SC2730_REGULATOR_BASE + 0x15c) +#define SC2730_LDO_VDDCAMA1_VOL (SC2730_REGULATOR_BASE + 0x168) +#define SC2730_LDO_VDDCAMMOT_VOL (SC2730_REGULATOR_BASE + 0x174) +#define SC2730_LDO_VDDSIM2_VOL (SC2730_REGULATOR_BASE + 0x198) +#define SC2730_LDO_VDDEMMCCORE_VOL (SC2730_REGULATOR_BASE + 0x1a4) +#define SC2730_LDO_VDDSDCORE_VOL (SC2730_REGULATOR_BASE + 0x1b0) +#define SC2730_LDO_VDDSDIO_VOL (SC2730_REGULATOR_BASE + 0x1bc) +#define SC2730_LDO_VDD28_VOL (SC2730_REGULATOR_BASE + 0x1c8) +#define SC2730_LDO_VDDWIFIPA_VOL (SC2730_REGULATOR_BASE + 0x1d4) +#define SC2730_LDO_VDD18_DCXO_VOL (SC2730_REGULATOR_BASE + 0x1e0) +#define SC2730_LDO_VDDUSB33_VOL (SC2730_REGULATOR_BASE + 0x1ec) +#define SC2730_LDO_VDDLDO0_VOL (SC2730_REGULATOR_BASE + 0x1f8) +#define SC2730_LDO_VDDLDO1_VOL (SC2730_REGULATOR_BASE + 0x204) +#define SC2730_LDO_VDDLDO2_VOL (SC2730_REGULATOR_BASE + 0x210) +#define SC2730_LDO_VDDKPLED_VOL (SC2730_REGULATOR_BASE + 0x38c) + +/* + * SC2730 vsel register mask + */ +#define SC2730_DCDC_CPU_VOL_MASK GENMASK(8, 0) +#define SC2730_DCDC_GPU_VOL_MASK GENMASK(8, 0) +#define SC2730_DCDC_CORE_VOL_MASK GENMASK(8, 0) +#define SC2730_DCDC_MODEM_VOL_MASK GENMASK(8, 0) +#define SC2730_DCDC_MEM_VOL_MASK GENMASK(7, 0) +#define SC2730_DCDC_MEMQ_VOL_MASK GENMASK(8, 0) +#define SC2730_DCDC_GEN0_VOL_MASK GENMASK(7, 0) +#define SC2730_DCDC_GEN1_VOL_MASK GENMASK(7, 0) +#define SC2730_DCDC_SRAM_VOL_MASK GENMASK(8, 0) +#define SC2730_LDO_AVDD18_VOL_MASK GENMASK(5, 0) +#define SC2730_LDO_VDDRF18_VOL_MASK GENMASK(5, 0) +#define SC2730_LDO_VDDCAMIO_VOL_MASK GENMASK(5, 0) +#define SC2730_LDO_VDDWCN_VOL_MASK GENMASK(5, 0) +#define SC2730_LDO_VDDCAMD1_VOL_MASK GENMASK(4, 0) +#define SC2730_LDO_VDDCAMD0_VOL_MASK GENMASK(4, 0) +#define SC2730_LDO_VDDRF1V25_VOL_MASK GENMASK(4, 0) +#define SC2730_LDO_AVDD12_VOL_MASK GENMASK(4, 0) +#define SC2730_LDO_VDDCAMA0_VOL_MASK GENMASK(7, 0) +#define SC2730_LDO_VDDCAMA1_VOL_MASK GENMASK(7, 0) +#define SC2730_LDO_VDDCAMMOT_VOL_MASK GENMASK(7, 0) +#define SC2730_LDO_VDDSIM2_VOL_MASK GENMASK(7, 0) +#define SC2730_LDO_VDDEMMCCORE_VOL_MASK GENMASK(7, 0) +#define SC2730_LDO_VDDSDCORE_VOL_MASK GENMASK(7, 0) +#define SC2730_LDO_VDDSDIO_VOL_MASK GENMASK(7, 0) +#define SC2730_LDO_VDD28_VOL_MASK GENMASK(7, 0) +#define SC2730_LDO_VDDWIFIPA_VOL_MASK GENMASK(7, 0) +#define SC2730_LDO_VDD18_DCXO_VOL_MASK GENMASK(7, 0) +#define SC2730_LDO_VDDUSB33_VOL_MASK GENMASK(7, 0) +#define SC2730_LDO_VDDLDO0_VOL_MASK GENMASK(7, 0) +#define SC2730_LDO_VDDLDO1_VOL_MASK GENMASK(7, 0) +#define SC2730_LDO_VDDLDO2_VOL_MASK GENMASK(7, 0) +#define SC2730_LDO_VDDKPLED_VOL_MASK GENMASK(14, 7) + +enum sc2730_regulator_id { + SC2730_DCDC_CPU, + SC2730_DCDC_GPU, + SC2730_DCDC_CORE, + SC2730_DCDC_MODEM, + SC2730_DCDC_MEM, + SC2730_DCDC_MEMQ, + SC2730_DCDC_GEN0, + SC2730_DCDC_GEN1, + SC2730_DCDC_SRAM, + SC2730_LDO_AVDD18, + SC2730_LDO_VDDRF18, + SC2730_LDO_VDDCAMIO, + SC2730_LDO_VDDWCN, + SC2730_LDO_VDDCAMD1, + SC2730_LDO_VDDCAMD0, + SC2730_LDO_VDDRF1V25, + SC2730_LDO_AVDD12, + SC2730_LDO_VDDCAMA0, + SC2730_LDO_VDDCAMA1, + SC2730_LDO_VDDCAMMOT, + SC2730_LDO_VDDSIM2, + SC2730_LDO_VDDEMMCCORE, + SC2730_LDO_VDDSDCORE, + SC2730_LDO_VDDSDIO, + SC2730_LDO_VDD28, + SC2730_LDO_VDDWIFIPA, + SC2730_LDO_VDD18_DCXO, + SC2730_LDO_VDDUSB33, + SC2730_LDO_VDDLDO0, + SC2730_LDO_VDDLDO1, + SC2730_LDO_VDDLDO2, + SC2730_LDO_VDDKPLED, +}; + +static const struct regulator_ops sc2730_regu_linear_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, +}; + +#define SC2730_REGU_LINEAR(_id, of_name, en_reg, en_mask, vreg, vmask, \ + vstep, vmin, vmax) { \ + .name = #_id, \ + .of_match = of_name, \ + .regulators_node = "regulators", \ + .ops = &sc2730_regu_linear_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = SC2730_##_id, \ + .owner = THIS_MODULE, \ + .min_uV = vmin, \ + .n_voltages = ((vmax) - (vmin)) / (vstep) + 1, \ + .uV_step = vstep, \ + .enable_is_inverted = true, \ + .enable_val = 0, \ + .enable_reg = en_reg, \ + .enable_mask = en_mask, \ + .vsel_reg = vreg, \ + .vsel_mask = vmask, \ + .linear_min_sel = 0, \ +} + +static const struct regulator_desc regulators[] = { + SC2730_REGU_LINEAR(DCDC_CPU, "dcdc-cpu", SC2730_POWER_PD_SW, + SC2730_DCDC_CPU_PD_MASK, SC2730_DCDC_CPU_VOL, + SC2730_DCDC_CPU_VOL_MASK, 3125, 0, 1596875), + SC2730_REGU_LINEAR(DCDC_GPU, "dcdc-gpu", SC2730_POWER_PD_SW, + SC2730_DCDC_GPU_PD_MASK, SC2730_DCDC_GPU_VOL, + SC2730_DCDC_GPU_VOL_MASK, 3125, 0, 1596875), + SC2730_REGU_LINEAR(DCDC_CORE, "dcdc-core", SC2730_POWER_PD_SW, + SC2730_DCDC_CORE_PD_MASK, SC2730_DCDC_CORE_VOL, + SC2730_DCDC_CORE_VOL_MASK, 3125, 0, 1596875), + SC2730_REGU_LINEAR(DCDC_MODEM, "dcdc-modem", SC2730_POWER_PD_SW, + SC2730_DCDC_MODEM_PD_MASK, SC2730_DCDC_MODEM_VOL, + SC2730_DCDC_MODEM_VOL_MASK, 3125, 0, 1596875), + SC2730_REGU_LINEAR(DCDC_MEM, "dcdc-mem", SC2730_POWER_PD_SW, + SC2730_DCDC_MEM_PD_MASK, SC2730_DCDC_MEM_VOL, + SC2730_DCDC_MEM_VOL_MASK, 6250, 0, 1593750), + SC2730_REGU_LINEAR(DCDC_MEMQ, "dcdc-memq", SC2730_POWER_PD_SW, + SC2730_DCDC_MEMQ_PD_MASK, SC2730_DCDC_MEMQ_VOL, + SC2730_DCDC_MEMQ_VOL_MASK, 3125, 0, 1596875), + SC2730_REGU_LINEAR(DCDC_GEN0, "dcdc-gen0", SC2730_POWER_PD_SW, + SC2730_DCDC_GEN0_PD_MASK, SC2730_DCDC_GEN0_VOL, + SC2730_DCDC_GEN0_VOL_MASK, 9375, 20000, 2410625), + SC2730_REGU_LINEAR(DCDC_GEN1, "dcdc-gen1", SC2730_POWER_PD_SW, + SC2730_DCDC_GEN1_PD_MASK, SC2730_DCDC_GEN1_VOL, + SC2730_DCDC_GEN1_VOL_MASK, 6250, 50000, 1643750), + SC2730_REGU_LINEAR(DCDC_SRAM, "dcdc-sram", SC2730_POWER_PD_SW, + SC2730_DCDC_SRAM_PD_MASK, SC2730_DCDC_SRAM_VOL, + SC2730_DCDC_SRAM_VOL_MASK, 3125, 0, 1596875), + SC2730_REGU_LINEAR(LDO_AVDD18, "ldo-avdd18", SC2730_POWER_PD_SW, + SC2730_LDO_AVDD18_PD_MASK, SC2730_LDO_AVDD18_VOL, + SC2730_LDO_AVDD18_VOL_MASK, 10000, 1175000, 1805000), + SC2730_REGU_LINEAR(LDO_VDDRF18, "ldo-vddrf18", SC2730_LDO_VDDRF18_PD, + SC2730_LDO_VDDRF18_PD_MASK, SC2730_LDO_VDDRF18_VOL, + SC2730_LDO_VDDRF18_VOL_MASK, 10000, 1175000, 1805000), + SC2730_REGU_LINEAR(LDO_VDDCAMIO, "ldo-vddcamio", SC2730_LDO_VDDCAMIO_PD, + SC2730_LDO_VDDCAMIO_PD_MASK, SC2730_LDO_VDDCAMIO_VOL, + SC2730_LDO_VDDCAMIO_VOL_MASK, 10000, 1200000, 1830000), + SC2730_REGU_LINEAR(LDO_VDDWCN, "ldo-vddwcn", SC2730_LDO_VDDWCN_PD, + SC2730_LDO_VDDWCN_PD_MASK, SC2730_LDO_VDDWCN_VOL, + SC2730_LDO_VDDWCN_VOL_MASK, 15000, 900000, 1845000), + SC2730_REGU_LINEAR(LDO_VDDCAMD1, "ldo-vddcamd1", SC2730_LDO_VDDCAMD1_PD, + SC2730_LDO_VDDCAMD1_PD_MASK, SC2730_LDO_VDDCAMD1_VOL, + SC2730_LDO_VDDCAMD1_VOL_MASK, 15000, 900000, 1365000), + SC2730_REGU_LINEAR(LDO_VDDCAMD0, "ldo-vddcamd0", SC2730_LDO_VDDCAMD0_PD, + SC2730_LDO_VDDCAMD0_PD_MASK, SC2730_LDO_VDDCAMD0_VOL, + SC2730_LDO_VDDCAMD0_VOL_MASK, 15000, 900000, 1365000), + SC2730_REGU_LINEAR(LDO_VDDRF1V25, "ldo-vddrf1v25", SC2730_LDO_VDDRF1V25_PD, + SC2730_LDO_VDDRF1V25_PD_MASK, SC2730_LDO_VDDRF1V25_VOL, + SC2730_LDO_VDDRF1V25_VOL_MASK, 15000, 900000, 1365000), + SC2730_REGU_LINEAR(LDO_AVDD12, "ldo-avdd12", SC2730_LDO_AVDD12_PD, + SC2730_LDO_AVDD12_PD_MASK, SC2730_LDO_AVDD12_VOL, + SC2730_LDO_AVDD12_VOL_MASK, 15000, 900000, 1365000), + SC2730_REGU_LINEAR(LDO_VDDCAMA0, "ldo-vddcama0", SC2730_LDO_VDDCAMA0_PD, + SC2730_LDO_VDDCAMA0_PD_MASK, SC2730_LDO_VDDCAMA0_VOL, + SC2730_LDO_VDDCAMA0_VOL_MASK, 10000, 1200000, 3750000), + SC2730_REGU_LINEAR(LDO_VDDCAMA1, "ldo-vddcama1", SC2730_LDO_VDDCAMA1_PD, + SC2730_LDO_VDDCAMA1_PD_MASK, SC2730_LDO_VDDCAMA1_VOL, + SC2730_LDO_VDDCAMA1_VOL_MASK, 10000, 1200000, 3750000), + SC2730_REGU_LINEAR(LDO_VDDCAMMOT, "ldo-vddcammot", SC2730_LDO_VDDCAMMOT_PD, + SC2730_LDO_VDDCAMMOT_PD_MASK, SC2730_LDO_VDDCAMMOT_VOL, + SC2730_LDO_VDDCAMMOT_VOL_MASK, 10000, 1200000, 3750000), + SC2730_REGU_LINEAR(LDO_VDDSIM2, "ldo-vddsim2", SC2730_LDO_VDDSIM2_PD, + SC2730_LDO_VDDSIM2_PD_MASK, SC2730_LDO_VDDSIM2_VOL, + SC2730_LDO_VDDSIM2_VOL_MASK, 10000, 1200000, 3750000), + SC2730_REGU_LINEAR(LDO_VDDEMMCCORE, "ldo-vddemmccore", SC2730_LDO_VDDEMMCCORE_PD, + SC2730_LDO_VDDEMMCCORE_PD_MASK, SC2730_LDO_VDDEMMCCORE_VOL, + SC2730_LDO_VDDEMMCCORE_VOL_MASK, 10000, 1200000, 3750000), + SC2730_REGU_LINEAR(LDO_VDDSDCORE, "ldo-vddsdcore", SC2730_LDO_VDDSDCORE_PD, + SC2730_LDO_VDDSDCORE_PD_MASK, SC2730_LDO_VDDSDCORE_VOL, + SC2730_LDO_VDDSDCORE_VOL_MASK, 10000, 1200000, 3750000), + SC2730_REGU_LINEAR(LDO_VDDSDIO, "ldo-vddsdio", SC2730_LDO_VDDSDIO_PD, + SC2730_LDO_VDDSDIO_PD_MASK, SC2730_LDO_VDDSDIO_VOL, + SC2730_LDO_VDDSDIO_VOL_MASK, 10000, 1200000, 3750000), + SC2730_REGU_LINEAR(LDO_VDD28, "ldo-vdd28", SC2730_POWER_PD_SW, + SC2730_LDO_VDD28_PD_MASK, SC2730_LDO_VDD28_VOL, + SC2730_LDO_VDD28_VOL_MASK, 10000, 1200000, 3750000), + SC2730_REGU_LINEAR(LDO_VDDWIFIPA, "ldo-vddwifipa", SC2730_LDO_VDDWIFIPA_PD, + SC2730_LDO_VDDWIFIPA_PD_MASK, SC2730_LDO_VDDWIFIPA_VOL, + SC2730_LDO_VDDWIFIPA_VOL_MASK, 10000, 1200000, 3750000), + SC2730_REGU_LINEAR(LDO_VDD18_DCXO, "ldo-vdd18-dcxo", SC2730_POWER_PD_SW, + SC2730_LDO_VDD18_DCXO_PD_MASK, SC2730_LDO_VDD18_DCXO_VOL, + SC2730_LDO_VDD18_DCXO_VOL_MASK, 10000, 1200000, 3750000), + SC2730_REGU_LINEAR(LDO_VDDUSB33, "ldo-vddusb33", SC2730_LDO_VDDUSB33_PD, + SC2730_LDO_VDDUSB33_PD_MASK, SC2730_LDO_VDDUSB33_VOL, + SC2730_LDO_VDDUSB33_VOL_MASK, 10000, 1200000, 3750000), + SC2730_REGU_LINEAR(LDO_VDDLDO0, "ldo-vddldo0", SC2730_LDO_VDDLDO0_PD, + SC2730_LDO_VDDLDO0_PD_MASK, SC2730_LDO_VDDLDO0_VOL, + SC2730_LDO_VDDLDO0_VOL_MASK, 10000, 1200000, 3750000), + SC2730_REGU_LINEAR(LDO_VDDLDO1, "ldo-vddldo1", SC2730_LDO_VDDLDO1_PD, + SC2730_LDO_VDDLDO1_PD_MASK, SC2730_LDO_VDDLDO1_VOL, + SC2730_LDO_VDDLDO1_VOL_MASK, 10000, 1200000, 3750000), + SC2730_REGU_LINEAR(LDO_VDDLDO2, "ldo-vddldo2", SC2730_LDO_VDDLDO2_PD, + SC2730_LDO_VDDLDO2_PD_MASK, SC2730_LDO_VDDLDO2_VOL, + SC2730_LDO_VDDLDO2_VOL_MASK, 10000, 1200000, 3750000), + SC2730_REGU_LINEAR(LDO_VDDKPLED, "ldo-vddkpled", SC2730_LDO_VDDKPLED_PD, + SC2730_LDO_VDDKPLED_PD_MASK, SC2730_LDO_VDDKPLED_VOL, + SC2730_LDO_VDDKPLED_VOL_MASK, 10000, 1200000, 3750000), +}; + +static int sc2730_regulator_unlock(struct regmap *regmap) +{ + return regmap_write(regmap, SC2730_PWR_WR_PROT, SC2730_WR_UNLOCK_VALUE); +} + +static int sc2730_regulator_probe(struct platform_device *pdev) +{ + int i, ret; + struct regmap *regmap; + struct regulator_config config = { }; + struct regulator_dev *rdev; + + regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!regmap) + return dev_err_probe(&pdev->dev, -ENODEV, "failed to get regmap\n"); + + ret = sc2730_regulator_unlock(regmap); + if (ret) + return dev_err_probe(&pdev->dev, ret, "failed to release regulator lock\n"); + + config.dev = pdev->dev.parent; + config.regmap = regmap; + + for (i = 0; i < ARRAY_SIZE(regulators); i++) { + rdev = devm_regulator_register(&pdev->dev, ®ulators[i], &config); + if (IS_ERR(rdev)) { + return dev_err_probe(&pdev->dev, PTR_ERR(rdev), + "failed to register regulator %s\n", + regulators[i].name); + } + } + + return 0; +} + +static const struct platform_device_id sc2730_regulator_id_table[] = { + { .name = "sc2730-regulator" }, + { } +}; +MODULE_DEVICE_TABLE(platform, sc2730_regulator_id_table); + +static struct platform_driver sc2730_regulator_driver = { + .driver = { + .name = "sc2730-regulator", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, + .probe = sc2730_regulator_probe, + .id_table = sc2730_regulator_id_table, +}; + +module_platform_driver(sc2730_regulator_driver); + +MODULE_AUTHOR("Zhongfa Wang "); +MODULE_DESCRIPTION("Spreadtrum SC2730 regulator driver"); +MODULE_LICENSE("GPL"); From f29a8bf6fde130313ec77c89d7612100ff5bafb2 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Thu, 2 Jul 2026 14:07:39 +0300 Subject: [PATCH 14/36] regulator: dt-bindings: ROHM PMIC state-machine voltages A few of the ROHM PMICs have a state-machine corrsponding to the SOC power-states. Idea is that by changing the PMIC state, all power-outputs will be switched to a pre-defined state. As an example, the SOC may use a low-power state when system is suspended, and when transitioning from the normal operation to suspend, the PMIC can be told to go to SUSPEND-state - which will then switch outputs of all power-rails to pre-defined low-power state matching the SOC expectation for SUSPEND. In addition to the SUSPEND, there are a few other states as well. The voltage values & enable / disable -states matching the SOC expectations can be set for the PMIC states using rohm,dvs--voltage -properties. It all started with the BD71837 supporting this, but over the years these same properties have been used for a few other PMICs, and seems like this HW-state machine design is not going away. Copying the descriptions and types in each PMIC specific binding, and discussing them during the reviews is getting tedious for the reviewers and author(s) alike. Furthermore, having separate descriptions makes it very easy to add errors, or differing, and even contradicting documentation for properties with same name. Avoid these issues by using one common file for the common ROHM PMIC state-machine definitions and only referencing this from the individual PMIC bindings. Signed-off-by: Matti Vaittinen Suggested-by: Rob Herring Reviewed-by: Conor Dooley Link: https://patch.msgid.link/akZGe1CaQFDd3idm@mva-rohm Signed-off-by: Mark Brown --- .../regulator/rohm,bd71815-regulator.yaml | 27 +++------ .../regulator/rohm,bd71828-regulator.yaml | 20 +------ .../regulator/rohm,bd71837-regulator.yaml | 16 +----- .../regulator/rohm,bd71847-regulator.yaml | 16 +----- .../regulator/rohm,bd72720-regulator.yaml | 40 ++----------- .../bindings/regulator/rohm,pmic-states.yaml | 57 +++++++++++++++++++ 6 files changed, 79 insertions(+), 97 deletions(-) create mode 100644 Documentation/devicetree/bindings/regulator/rohm,pmic-states.yaml diff --git a/Documentation/devicetree/bindings/regulator/rohm,bd71815-regulator.yaml b/Documentation/devicetree/bindings/regulator/rohm,bd71815-regulator.yaml index cc4ceb32e9d6..68b5e579e2d3 100644 --- a/Documentation/devicetree/bindings/regulator/rohm,bd71815-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/rohm,bd71815-regulator.yaml @@ -38,7 +38,9 @@ patternProperties: type: object description: Properties for single LDO/BUCK regulator. - $ref: regulator.yaml# + allOf: + - $ref: regulator.yaml# + - $ref: rohm,pmic-states.yaml# properties: regulator-name: @@ -51,15 +53,6 @@ patternProperties: description: GPIO used to control ldo4 state (when ldo4 is controlled by GPIO). - rohm,dvs-run-voltage: - description: - PMIC "RUN" state voltage in uV when PMIC HW states are used. See - comments below for bucks/LDOs which support this. 0 means - regulator should be disabled at RUN state. - $ref: /schemas/types.yaml#/definitions/uint32 - minimum: 0 - maximum: 3300000 - rohm,dvs-snvs-voltage: description: Whether to keep regulator enabled at "SNVS" state or not. @@ -71,21 +64,15 @@ patternProperties: minimum: 0 maximum: 3300000 + rohm,dvs-run-voltage: + minimum: 0 + maximum: 3300000 + rohm,dvs-suspend-voltage: - description: - PMIC "SUSPEND" state voltage in uV when PMIC HW states are used. See - comments below for bucks/LDOs which support this. 0 means - regulator should be disabled at SUSPEND state. - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3300000 rohm,dvs-lpsr-voltage: - description: - PMIC "LPSR" state voltage in uV when PMIC HW states are used. See - comments below for bucks/LDOs which support this. 0 means - regulator should be disabled at LPSR state. - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3300000 diff --git a/Documentation/devicetree/bindings/regulator/rohm,bd71828-regulator.yaml b/Documentation/devicetree/bindings/regulator/rohm,bd71828-regulator.yaml index d898800d6bca..8cba397678a6 100644 --- a/Documentation/devicetree/bindings/regulator/rohm,bd71828-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/rohm,bd71828-regulator.yaml @@ -40,7 +40,9 @@ patternProperties: type: object description: Properties for single BUCK regulator. - $ref: regulator.yaml# + allOf: + - $ref: regulator.yaml# + - $ref: rohm,pmic-states.yaml# properties: regulator-name: @@ -49,34 +51,18 @@ patternProperties: should be "buck1", ..., "buck7" rohm,dvs-run-voltage: - description: - PMIC default "RUN" state voltage in uV. See below table for - bucks which support this. 0 means disabled. - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3300000 rohm,dvs-idle-voltage: - description: - PMIC default "IDLE" state voltage in uV. See below table for - bucks which support this. 0 means disabled. - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3300000 rohm,dvs-suspend-voltage: - description: - PMIC default "SUSPEND" state voltage in uV. See below table for - bucks which support this. 0 means disabled. - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3300000 rohm,dvs-lpsr-voltage: - description: - PMIC default "LPSR" state voltage in uV. See below table for - bucks which support this. 0 means disabled. - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3300000 diff --git a/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.yaml b/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.yaml index 29b350a4f88a..efb38dd15145 100644 --- a/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.yaml @@ -44,7 +44,9 @@ patternProperties: "^BUCK[1-8]$": type: object - $ref: regulator.yaml# + allOf: + - $ref: regulator.yaml# + - $ref: rohm,pmic-states.yaml# description: Properties for single BUCK regulator. @@ -55,28 +57,16 @@ patternProperties: should be "buck1", ..., "buck8" rohm,dvs-run-voltage: - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 1300000 - description: - PMIC default "RUN" state voltage in uV. See below table for - bucks which support this. 0 means disabled. rohm,dvs-idle-voltage: - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 1300000 - description: - PMIC default "IDLE" state voltage in uV. See below table for - bucks which support this. 0 means disabled. rohm,dvs-suspend-voltage: - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 1300000 - description: - PMIC default "SUSPEND" state voltage in uV. See below table for - bucks which support this. 0 means disabled. # Supported default DVS states: # diff --git a/Documentation/devicetree/bindings/regulator/rohm,bd71847-regulator.yaml b/Documentation/devicetree/bindings/regulator/rohm,bd71847-regulator.yaml index 7ba4ccf723d8..ef6f69be24ae 100644 --- a/Documentation/devicetree/bindings/regulator/rohm,bd71847-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/rohm,bd71847-regulator.yaml @@ -43,7 +43,9 @@ patternProperties: "^BUCK[1-6]$": type: object - $ref: regulator.yaml# + allOf: + - $ref: regulator.yaml# + - $ref: rohm,pmic-states.yaml# description: Properties for single BUCK regulator. @@ -54,28 +56,16 @@ patternProperties: should be "buck1", ..., "buck6" rohm,dvs-run-voltage: - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 1300000 - description: - PMIC default "RUN" state voltage in uV. See below table for - bucks which support this. 0 means disabled. rohm,dvs-idle-voltage: - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 1300000 - description: - PMIC default "IDLE" state voltage in uV. See below table for - bucks which support this. 0 means disabled. rohm,dvs-suspend-voltage: - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 1300000 - description: - PMIC default "SUSPEND" state voltage in uV. See below table for - bucks which support this. 0 means disabled. # Supported default DVS states: # diff --git a/Documentation/devicetree/bindings/regulator/rohm,bd72720-regulator.yaml b/Documentation/devicetree/bindings/regulator/rohm,bd72720-regulator.yaml index 5518082129bd..76747bf2bbdd 100644 --- a/Documentation/devicetree/bindings/regulator/rohm,bd72720-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/rohm,bd72720-regulator.yaml @@ -26,41 +26,27 @@ patternProperties: type: object description: Properties for single LDO regulator. - $ref: regulator.yaml# + allOf: + - $ref: regulator.yaml# + - $ref: rohm,pmic-states.yaml# properties: regulator-name: pattern: "^ldo([1-9]|1[0-1])$" rohm,dvs-run-voltage: - description: - PMIC default "RUN" state voltage in uV. See below table for - LDOs which support this. 0 means disabled. - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3300000 rohm,dvs-idle-voltage: - description: - PMIC default "IDLE" state voltage in uV. See below table for - LDOs which support this. 0 means disabled. - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3300000 rohm,dvs-suspend-voltage: - description: - PMIC default "SUSPEND" state voltage in uV. See below table for - LDOs which support this. 0 means disabled. - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3300000 rohm,dvs-lpsr-voltage: - description: - PMIC default "deep-idle" state voltage in uV. See below table for - LDOs which support this. 0 means disabled. - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3300000 @@ -82,7 +68,9 @@ patternProperties: type: object description: Properties for single BUCK regulator. - $ref: regulator.yaml# + allOf: + - $ref: regulator.yaml# + - $ref: rohm,pmic-states.yaml# properties: regulator-name: @@ -97,34 +85,18 @@ patternProperties: maximum: 300000 rohm,dvs-run-voltage: - description: - PMIC default "RUN" state voltage in uV. See below table for - bucks which support this. 0 means disabled. - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3300000 rohm,dvs-idle-voltage: - description: - PMIC default "IDLE" state voltage in uV. See below table for - bucks which support this. 0 means disabled. - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3300000 rohm,dvs-suspend-voltage: - description: - PMIC default "SUSPEND" state voltage in uV. See below table for - bucks which support this. 0 means disabled. - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3300000 rohm,dvs-lpsr-voltage: - description: - PMIC default "deep-idle" state voltage in uV. See below table for - bucks which support this. 0 means disabled. - $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 3300000 diff --git a/Documentation/devicetree/bindings/regulator/rohm,pmic-states.yaml b/Documentation/devicetree/bindings/regulator/rohm,pmic-states.yaml new file mode 100644 index 000000000000..f09f021bdde4 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/rohm,pmic-states.yaml @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/rohm,pmic-states.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ROHM PMICs' hardware state machine descriptions + +maintainers: + - Matti Vaittinen + +description: + Many of the ROHM PMICs have internal state-machine designed to provide + correct voltages for different SOC states. In many cases the states and + transitions are SOC specific, but ones described here can be found from a + few of the different ROHM PMICs. + +properties: + rohm,dvs-run-voltage: + description: + PMIC "RUN" state voltage in uV when PMIC HW states are used. 0 means the + regulator should be disabled at RUN state. Some regulators do not support + setting HW state specific voltage but do support enable/disable control. + For them any positive value means the regulator should be enabled without + touching the voltage. + $ref: /schemas/types.yaml#/definitions/uint32 + + rohm,dvs-suspend-voltage: + description: + PMIC "SUSPEND" state voltage in uV when PMIC HW states are used. 0 means + the regulator should be disabled at SUSPEND state. Some regulators do not + support setting HW state specific voltage but do support enable/disable + control. For them any positive value means the regulator should be + enabled without touching the voltage. + $ref: /schemas/types.yaml#/definitions/uint32 + + rohm,dvs-idle-voltage: + description: + PMIC "IDLE" state voltage in uV. 0 means the regulator should be disabled + at IDLE state. Some regulators do not support setting HW state specific + voltage but do support enable/disable control. For them any positive + value means the regulator should be enabled without touching the voltage. + $ref: /schemas/types.yaml#/definitions/uint32 + + rohm,dvs-lpsr-voltage: + description: + PMIC "LPSR" state voltage in uV when PMIC HW states are used. 0 means the + regulator should be disabled at LPSR state. Some regulators do not + support setting HW state specific voltage but do support enable/disable + control. For them any positive value means the regulator should be + enabled without touching the voltage. Some PMICs' documentation may refer + to this state as a "deep-idle state". + $ref: /schemas/types.yaml#/definitions/uint32 + +# The schema is expected to be reference by PMIC schemas, which may introduce +# other properties that must be allowed. +additionalProperties: true From a58d2e5e1c0406d4375861094070c22d6137713a Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Mon, 6 Jul 2026 18:01:05 +0530 Subject: [PATCH 15/36] regulator: dt-bindings: qcom,usb-vbus-regulator: add qcom,pm4125-vbus-reg The pm4125 PMIC uses a different USB VBUS register layout than pm8150b. It uses a 2-bit VBOOST voltage selector supporting output voltages of 4.25 V, 4.5 V, 4.75 V and 5.0 V, instead of a current-limit selector. Move qcom,pm4125-vbus-reg from the pm8150b fallback items list into the standalone enum since the driver handles it with its own match-data and register layout. Make regulator-min/max-microamp conditional so they are only required for current-limit variants (pm8150b, pm6150, pm7250b, pmi632). Add an if/then condition for qcom,pm4125-vbus-reg requiring regulator-min/ max-microvolt instead, and update the pm4125 example accordingly. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Rakesh Kota Link: https://patch.msgid.link/20260706-add_pm4125-vbus-reg-v3-1-999d78a87b81@oss.qualcomm.com Signed-off-by: Mark Brown --- .../regulator/qcom,usb-vbus-regulator.yaml | 50 +++++++++++++++++-- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml index fcefc722ee2a..024b34d0eb1a 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml @@ -14,17 +14,21 @@ description: | regulator will be enabled in situations where the device is required to provide power to the connected peripheral. -allOf: - - $ref: regulator.yaml# + The pm8150b variant uses an OTG current-limit selector, supporting limits + of 500 mA, 1000 mA, 1500 mA, 2000 mA, 2500 mA and 3000 mA. + + The pm4125 variant uses a different register layout with a 2-bit VBOOST + voltage selector supporting output voltages of 4.25 V, 4.5 V, 4.75 V + and 5.0 V. properties: compatible: oneOf: - enum: - qcom,pm8150b-vbus-reg + - qcom,pm4125-vbus-reg - items: - enum: - - qcom,pm4125-vbus-reg - qcom,pm6150-vbus-reg - qcom,pm7250b-vbus-reg - qcom,pmi632-vbus-reg @@ -34,11 +38,35 @@ properties: maxItems: 1 description: VBUS output base address +allOf: + - $ref: regulator.yaml# + - if: + properties: + compatible: + contains: + enum: + - qcom,pm8150b-vbus-reg + - qcom,pm6150-vbus-reg + - qcom,pm7250b-vbus-reg + - qcom,pmi632-vbus-reg + then: + required: + - regulator-min-microamp + - regulator-max-microamp + + - if: + properties: + compatible: + contains: + const: qcom,pm4125-vbus-reg + then: + required: + - regulator-min-microvolt + - regulator-max-microvolt + required: - compatible - reg - - regulator-min-microamp - - regulator-max-microamp unevaluatedProperties: false @@ -55,4 +83,16 @@ examples: regulator-max-microamp = <3000000>; }; }; + - | + pmic { + #address-cells = <1>; + #size-cells = <0>; + + usb-vbus-regulator@1100 { + compatible = "qcom,pm4125-vbus-reg"; + reg = <0x1100>; + regulator-min-microvolt = <4250000>; + regulator-max-microvolt = <5000000>; + }; + }; ... From 56cb4a0e8e7121e58df6395218c8d64bf2ff08d0 Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Mon, 6 Jul 2026 18:01:06 +0530 Subject: [PATCH 16/36] regulator: qcom_usb_vbus: add register abstraction and PM8150B support Introduce per-compatible regulator descriptor data via struct qcom_usb_vbus_reg_data to abstract register layout differences between PMICs. This allows the probe function to dynamically populate the regulator_desc fields rather than relying on compile-time constants. Refactor the existing PM8150B support to use this abstraction, wiring in its CMD_OTG, OTG_CFG, and current-limit registers through pm8150b_data. No functional change is intended for PM8150B. Signed-off-by: Rakesh Kota Reviewed-by: Bryan O'Donoghue Reviewed-by: Dmitry Baryshkov Link: https://patch.msgid.link/20260706-add_pm4125-vbus-reg-v3-2-999d78a87b81@oss.qualcomm.com Signed-off-by: Mark Brown --- drivers/regulator/qcom_usb_vbus-regulator.c | 71 +++++++++++++++++---- 1 file changed, 57 insertions(+), 14 deletions(-) diff --git a/drivers/regulator/qcom_usb_vbus-regulator.c b/drivers/regulator/qcom_usb_vbus-regulator.c index cd94ed67621f..0201a3983981 100644 --- a/drivers/regulator/qcom_usb_vbus-regulator.c +++ b/drivers/regulator/qcom_usb_vbus-regulator.c @@ -20,6 +20,21 @@ #define OTG_CFG 0x53 #define OTG_EN_SRC_CFG BIT(1) +struct qcom_usb_vbus_reg_data { + u16 cmd_otg; + u16 otg_cfg; + u8 otg_en_src_cfg; + u16 csel_reg; + u8 csel_mask; + const unsigned int *curr_table; + unsigned int n_current_limits; + u16 vsel_reg; + u8 vsel_mask; + const unsigned int *volt_table; + unsigned int n_voltages; + const struct regulator_ops *ops; +}; + static const unsigned int curr_table[] = { 500000, 1000000, 1500000, 2000000, 2500000, 3000000, }; @@ -32,19 +47,23 @@ static const struct regulator_ops qcom_usb_vbus_reg_ops = { .set_current_limit = regulator_set_current_limit_regmap, }; -static struct regulator_desc qcom_usb_vbus_rdesc = { - .name = "usb_vbus", - .ops = &qcom_usb_vbus_reg_ops, - .owner = THIS_MODULE, - .type = REGULATOR_VOLTAGE, +static const struct qcom_usb_vbus_reg_data pm8150b_data = { + .cmd_otg = CMD_OTG, + .otg_cfg = OTG_CFG, + .otg_en_src_cfg = OTG_EN_SRC_CFG, + .csel_reg = OTG_CURRENT_LIMIT_CFG, + .csel_mask = OTG_CURRENT_LIMIT_MASK, .curr_table = curr_table, .n_current_limits = ARRAY_SIZE(curr_table), + .ops = &qcom_usb_vbus_reg_ops, }; static int qcom_usb_vbus_regulator_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + const struct qcom_usb_vbus_reg_data *data; struct regulator_dev *rdev; + struct regulator_desc *rdesc; struct regmap *regmap; struct regulator_config config = { }; struct regulator_init_data *init_data; @@ -57,27 +76,51 @@ static int qcom_usb_vbus_regulator_probe(struct platform_device *pdev) return ret; } + data = of_device_get_match_data(dev); + if (!data) + return -EINVAL; + regmap = dev_get_regmap(dev->parent, NULL); if (!regmap) { dev_err(dev, "Failed to get regmap\n"); return -ENOENT; } - init_data = of_get_regulator_init_data(dev, dev->of_node, - &qcom_usb_vbus_rdesc); + rdesc = devm_kzalloc(dev, sizeof(*rdesc), GFP_KERNEL); + if (!rdesc) + return -ENOMEM; + + rdesc->name = "usb_vbus"; + rdesc->ops = data->ops; + rdesc->owner = THIS_MODULE; + rdesc->type = REGULATOR_VOLTAGE; + rdesc->enable_reg = base + data->cmd_otg; + rdesc->enable_mask = OTG_EN; + + if (data->curr_table) { + rdesc->curr_table = data->curr_table; + rdesc->n_current_limits = data->n_current_limits; + rdesc->csel_reg = base + data->csel_reg; + rdesc->csel_mask = data->csel_mask; + } + + if (data->volt_table) { + rdesc->volt_table = data->volt_table; + rdesc->n_voltages = data->n_voltages; + rdesc->vsel_reg = base + data->vsel_reg; + rdesc->vsel_mask = data->vsel_mask; + } + + init_data = of_get_regulator_init_data(dev, dev->of_node, rdesc); if (!init_data) return -ENOMEM; - qcom_usb_vbus_rdesc.enable_reg = base + CMD_OTG; - qcom_usb_vbus_rdesc.enable_mask = OTG_EN; - qcom_usb_vbus_rdesc.csel_reg = base + OTG_CURRENT_LIMIT_CFG; - qcom_usb_vbus_rdesc.csel_mask = OTG_CURRENT_LIMIT_MASK; config.dev = dev; config.init_data = init_data; config.of_node = dev->of_node; config.regmap = regmap; - rdev = devm_regulator_register(dev, &qcom_usb_vbus_rdesc, &config); + rdev = devm_regulator_register(dev, rdesc, &config); if (IS_ERR(rdev)) { ret = PTR_ERR(rdev); dev_err(dev, "not able to register vbus reg %d\n", ret); @@ -85,13 +128,13 @@ static int qcom_usb_vbus_regulator_probe(struct platform_device *pdev) } /* Disable HW logic for VBUS enable */ - regmap_update_bits(regmap, base + OTG_CFG, OTG_EN_SRC_CFG, 0); + regmap_update_bits(regmap, base + data->otg_cfg, data->otg_en_src_cfg, 0); return 0; } static const struct of_device_id qcom_usb_vbus_regulator_match[] = { - { .compatible = "qcom,pm8150b-vbus-reg" }, + { .compatible = "qcom,pm8150b-vbus-reg", .data = &pm8150b_data }, { } }; MODULE_DEVICE_TABLE(of, qcom_usb_vbus_regulator_match); From d37664f99ef94f7a7bbca4b5ddcb7ab5c801f2e1 Mon Sep 17 00:00:00 2001 From: Rakesh Kota Date: Mon, 6 Jul 2026 18:01:07 +0530 Subject: [PATCH 17/36] regulator: qcom_usb_vbus: add support for qcom,pm4125-vbus-reg The PM4125 PMIC uses a different register layout for USB VBUS control compared to PM8150B. On PM4125, CMD_OTG is at offset 0x50, OTG_CFG is at 0x56, and offset 0x52 is a 2-bit VBOOST voltage selector rather than a current-limit selector. Add pm4125_data using the abstraction introduced for PM8150B, along with dedicated voltage-selector ops and the pm4125_vboost_table covering the four supported boost voltages: 4.25 V, 4.5 V, 4.75 V, and 5.0 V. Signed-off-by: Rakesh Kota Reviewed-by: Bryan O'Donoghue Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Link: https://patch.msgid.link/20260706-add_pm4125-vbus-reg-v3-3-999d78a87b81@oss.qualcomm.com Signed-off-by: Mark Brown --- drivers/regulator/qcom_usb_vbus-regulator.c | 31 +++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/regulator/qcom_usb_vbus-regulator.c b/drivers/regulator/qcom_usb_vbus-regulator.c index 0201a3983981..9aea68876284 100644 --- a/drivers/regulator/qcom_usb_vbus-regulator.c +++ b/drivers/regulator/qcom_usb_vbus-regulator.c @@ -20,6 +20,12 @@ #define OTG_CFG 0x53 #define OTG_EN_SRC_CFG BIT(1) +#define PM4125_VBOOST_EN 0x50 +#define PM4125_VBOOST_SEL 0x52 +#define PM4125_VBOOST_CFG_MASK GENMASK(1, 0) +#define PM4125_VBOOST_CFG 0x56 +#define PM4125_VBOOST_EN_SRC_CFG BIT(0) + struct qcom_usb_vbus_reg_data { u16 cmd_otg; u16 otg_cfg; @@ -39,6 +45,10 @@ static const unsigned int curr_table[] = { 500000, 1000000, 1500000, 2000000, 2500000, 3000000, }; +static const unsigned int pm4125_vboost_table[] = { + 4250000, 4500000, 4750000, 5000000, +}; + static const struct regulator_ops qcom_usb_vbus_reg_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -58,6 +68,26 @@ static const struct qcom_usb_vbus_reg_data pm8150b_data = { .ops = &qcom_usb_vbus_reg_ops, }; +static const struct regulator_ops qcom_usb_vbus_pm4125_reg_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_table, +}; + +static const struct qcom_usb_vbus_reg_data pm4125_data = { + .cmd_otg = PM4125_VBOOST_EN, + .otg_cfg = PM4125_VBOOST_CFG, + .otg_en_src_cfg = PM4125_VBOOST_EN_SRC_CFG, + .vsel_reg = PM4125_VBOOST_SEL, + .vsel_mask = PM4125_VBOOST_CFG_MASK, + .volt_table = pm4125_vboost_table, + .n_voltages = ARRAY_SIZE(pm4125_vboost_table), + .ops = &qcom_usb_vbus_pm4125_reg_ops, +}; + static int qcom_usb_vbus_regulator_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -135,6 +165,7 @@ static int qcom_usb_vbus_regulator_probe(struct platform_device *pdev) static const struct of_device_id qcom_usb_vbus_regulator_match[] = { { .compatible = "qcom,pm8150b-vbus-reg", .data = &pm8150b_data }, + { .compatible = "qcom,pm4125-vbus-reg", .data = &pm4125_data }, { } }; MODULE_DEVICE_TABLE(of, qcom_usb_vbus_regulator_match); From 153bc959ce0f91b4446fb6fb805b8c1d2ca20c75 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 10 Jul 2026 22:34:44 +0300 Subject: [PATCH 18/36] regulator: adp5055: Fix error code in adp5055_of_parse_cb() This code accidentally returned the wrong variable instead of a negative error code. Return -EINVAL. Fixes: 147b2a96f24e ("regulator: adp5055: Add driver for adp5055") Signed-off-by: Dan Carpenter Link: https://patch.msgid.link/alFJVBbiFNxhqa_1@stanley.mountain Signed-off-by: Mark Brown --- drivers/regulator/adp5055-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/adp5055-regulator.c b/drivers/regulator/adp5055-regulator.c index a79274d530df..194dcfe4f527 100644 --- a/drivers/regulator/adp5055-regulator.c +++ b/drivers/regulator/adp5055-regulator.c @@ -224,7 +224,7 @@ static int adp5055_of_parse_cb(struct device_node *np, adp5055->dvs_limit_upper[id] = pval; if (adp5055->dvs_limit_upper[id] > 192000 || adp5055->dvs_limit_upper[id] < 12000) - return dev_err_probe(config->dev, adp5055->dvs_limit_upper[id], + return dev_err_probe(config->dev, -EINVAL, "Out of range - dvs-limit-upper-microvolt value."); ret = of_property_read_u32(np, "adi,dvs-limit-lower-microvolt", &pval); From 25706f1ab9fba4b10169f557bf5fcaf41db0bc65 Mon Sep 17 00:00:00 2001 From: Ninad Naik Date: Wed, 15 Jul 2026 00:52:28 +0530 Subject: [PATCH 19/36] regulator: mcp16502: Convert to dev_err_probe() in mcp16502_probe() The mcp16502_probe() currently uses dev_err() for logging errors. However, functions like devm_regmap_init_i2c, devm_gpiod_get_optional and devm_regulator_register can return -EPROBE_DEFER. Using dev_err() in these situations can cause unnecessary error spam in dmesg. As a result, convert to dev_err_probe(). It also simplifies the print and return operations into single statement. The 'ret' variable is no longer required and has been removed. Originally detected by Coccinelle with this warning "Consider using %pe to print PTR_ERR()" Compile-tested only. Signed-off-by: Ninad Naik Link: https://patch.msgid.link/20260714192228.1639768-1-ninadnaik07@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/mcp16502.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/drivers/regulator/mcp16502.c b/drivers/regulator/mcp16502.c index 89fd79d446f7..07c67ad1ab7f 100644 --- a/drivers/regulator/mcp16502.c +++ b/drivers/regulator/mcp16502.c @@ -508,7 +508,7 @@ static int mcp16502_probe(struct i2c_client *client) struct device *dev; struct mcp16502 *mcp; struct regmap *rmap; - int i, ret; + int i; dev = &client->dev; config.dev = dev; @@ -518,30 +518,23 @@ static int mcp16502_probe(struct i2c_client *client) return -ENOMEM; rmap = devm_regmap_init_i2c(client, &mcp16502_regmap_config); - if (IS_ERR(rmap)) { - ret = PTR_ERR(rmap); - dev_err(dev, "regmap init failed: %d\n", ret); - return ret; - } + if (IS_ERR(rmap)) + return dev_err_probe(dev, PTR_ERR(rmap), "regmap init failed\n"); i2c_set_clientdata(client, mcp); config.regmap = rmap; config.driver_data = mcp; mcp->lpm = devm_gpiod_get_optional(dev, "lpm", GPIOD_OUT_LOW); - if (IS_ERR(mcp->lpm)) { - dev_err(dev, "failed to get lpm pin: %ld\n", PTR_ERR(mcp->lpm)); - return PTR_ERR(mcp->lpm); - } + if (IS_ERR(mcp->lpm)) + return dev_err_probe(dev, PTR_ERR(mcp->lpm), "failed to get lpm pin\n"); for (i = 0; i < NUM_REGULATORS; i++) { rdev = devm_regulator_register(dev, &mcp16502_desc[i], &config); - if (IS_ERR(rdev)) { - dev_err(dev, - "failed to register %s regulator %ld\n", - mcp16502_desc[i].name, PTR_ERR(rdev)); - return PTR_ERR(rdev); - } + if (IS_ERR(rdev)) + return dev_err_probe(dev, PTR_ERR(rdev), + "failed to register %s regulator\n", + mcp16502_desc[i].name); } mcp16502_gpio_set_mode(mcp, MCP16502_OPMODE_ACTIVE); From 07f0feac5f589bd09afd84533632b7c796fc5ef8 Mon Sep 17 00:00:00 2001 From: Bhargav Joshi Date: Fri, 17 Jul 2026 02:54:03 +0530 Subject: [PATCH 20/36] regulator: dt-bindings: tps51632: Convert to DT schema Convert Texas Instruments TPS51632 Voltage regulators from legacy text to DT schema. No functional changes are introduced. Signed-off-by: Bhargav Joshi Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20260717-ti-regulator-tp-v1-1-a49d41dc56d3@gmail.com Signed-off-by: Mark Brown --- .../bindings/regulator/ti,tps51632.yaml | 55 +++++++++++++++++++ .../bindings/regulator/tps51632-regulator.txt | 27 --------- 2 files changed, 55 insertions(+), 27 deletions(-) create mode 100644 Documentation/devicetree/bindings/regulator/ti,tps51632.yaml delete mode 100644 Documentation/devicetree/bindings/regulator/tps51632-regulator.txt diff --git a/Documentation/devicetree/bindings/regulator/ti,tps51632.yaml b/Documentation/devicetree/bindings/regulator/ti,tps51632.yaml new file mode 100644 index 000000000000..67ac40e3ec00 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/ti,tps51632.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/ti,tps51632.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments TPS51632 Voltage regulators + +maintainers: + - Laxman Dewangan + +allOf: + - $ref: regulator.yaml# + +properties: + compatible: + const: ti,tps51632 + + reg: + maxItems: 1 + + ti,enable-pwm-dvfs: + description: Enable the DVFS voltage control through the PWM interface. + type: boolean + + ti,dvfs-step-20mV: + description: + The 20mV step voltage when PWM DVFS enabled. Missing this will set 10mV + step voltage in PWM DVFS mode. In normal mode, the voltage step is 10mV + as per datasheet. + type: boolean + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + tps51632@43 { + compatible = "ti,tps51632"; + reg = <0x43>; + regulator-name = "tps51632-vout"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1500000>; + regulator-boot-on; + ti,enable-pwm-dvfs; + ti,dvfs-step-20mV; + }; + }; diff --git a/Documentation/devicetree/bindings/regulator/tps51632-regulator.txt b/Documentation/devicetree/bindings/regulator/tps51632-regulator.txt deleted file mode 100644 index 2f7e44a96414..000000000000 --- a/Documentation/devicetree/bindings/regulator/tps51632-regulator.txt +++ /dev/null @@ -1,27 +0,0 @@ -TPS51632 Voltage regulators - -Required properties: -- compatible: Must be "ti,tps51632" -- reg: I2C slave address - -Optional properties: -- ti,enable-pwm-dvfs: Enable the DVFS voltage control through the PWM interface. -- ti,dvfs-step-20mV: The 20mV step voltage when PWM DVFS enabled. Missing this - will set 10mV step voltage in PWM DVFS mode. In normal mode, the voltage - step is 10mV as per datasheet. - -Any property defined as part of the core regulator binding, defined in -regulator.txt, can also be used. - -Example: - - tps51632 { - compatible = "ti,tps51632"; - reg = <0x43>; - regulator-name = "tps51632-vout"; - regulator-min-microvolt = <500000>; - regulator-max-microvolt = <1500000>; - regulator-boot-on; - ti,enable-pwm-dvfs; - ti,dvfs-step-20mV; - }; From 64f3d6f2665222d16e90dc691e24607168c8cc29 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Tue, 14 Jul 2026 12:01:45 -0400 Subject: [PATCH 21/36] regulator: dt-bindings: Convert ltc3589.txt to yaml format Convert ltc3589.txt to yaml format. Additional changes: - Add interrupts to match driver code - Require lltc,fb-voltage-divider property ^(sw1|sw2|sw3|bb-out|ldo1|ldo2)$ Signed-off-by: Frank Li Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20260714160147.1641379-1-Frank.Li@oss.nxp.com Signed-off-by: Mark Brown --- .../bindings/regulator/lltc,ltc3589.yaml | 149 ++++++++++++++++++ .../devicetree/bindings/regulator/ltc3589.txt | 99 ------------ 2 files changed, 149 insertions(+), 99 deletions(-) create mode 100644 Documentation/devicetree/bindings/regulator/lltc,ltc3589.yaml delete mode 100644 Documentation/devicetree/bindings/regulator/ltc3589.txt diff --git a/Documentation/devicetree/bindings/regulator/lltc,ltc3589.yaml b/Documentation/devicetree/bindings/regulator/lltc,ltc3589.yaml new file mode 100644 index 000000000000..2c2755bb84eb --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/lltc,ltc3589.yaml @@ -0,0 +1,149 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/lltc,ltc3589.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Linear Technology LTC3589 PMIC + +maintainers: + - Frank Li + +description: + Linear Technology LTC3589, LTC3589-1 and LTC3589-2 are PMICs + containing three buck regulators, one boost regulator and four + LDO regulators. + +properties: + compatible: + enum: + - lltc,ltc3589 + - lltc,ltc3589-1 + - lltc,ltc3589-2 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + regulators: + type: object + additionalProperties: false + + patternProperties: + "^(sw1|sw2|sw3|bb-out|ldo1|ldo2)$": + type: object + unevaluatedProperties: false + $ref: regulator.yaml# + + properties: + lltc,fb-voltage-divider: + description: + Feedback voltage divider resistor values (R1, R2) in ohms. + Regulators sw1, sw2, sw3, and ldo2 can regulate the feedback + reference from 0.3625 V to 0.75 V in 12.5 mV steps. The output + voltage thus ranges between 0.3625 * (1 + R1/R2) V and + 0.75 * (1 + R1/R2) V. Regulators bb-out and ldo1 have a fixed + 0.8 V reference and thus output 0.8 * (1 + R1/R2) V. The ldo3 + regulator is fixed to 1.8 V on LTC3589 and to 2.8 V on + LTC3589-1,2. The ldo4 regulator can output between 1.8 V and + 3.3 V on LTC3589 and between 1.2 V and 3.2 V on LTC3589-1,2 in + four steps. The ldo1 standby regulator can not be disabled and + thus should have the regulator-always-on property set. + $ref: /schemas/types.yaml#/definitions/uint32-array + items: + - description: R1 in ohms + - description: R2 in ohms. + + required: + - lltc,fb-voltage-divider + + "^(ldo3|ldo4)$": + type: object + unevaluatedProperties: false + $ref: regulator.yaml# + +required: + - compatible + - reg + - regulators + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + pmic@34 { + compatible = "lltc,ltc3589-1"; + reg = <0x34>; + + regulators { + sw1 { + regulator-min-microvolt = <591930>; + regulator-max-microvolt = <1224671>; + lltc,fb-voltage-divider = <100000 158000>; + regulator-ramp-delay = <7000>; + regulator-boot-on; + regulator-always-on; + }; + + sw2 { + regulator-min-microvolt = <704123>; + regulator-max-microvolt = <1456803>; + lltc,fb-voltage-divider = <180000 191000>; + regulator-ramp-delay = <7000>; + regulator-boot-on; + regulator-always-on; + }; + + sw3 { + regulator-min-microvolt = <1341250>; + regulator-max-microvolt = <2775000>; + lltc,fb-voltage-divider = <270000 100000>; + regulator-ramp-delay = <7000>; + regulator-boot-on; + regulator-always-on; + }; + + bb-out { + regulator-min-microvolt = <3387341>; + regulator-max-microvolt = <3387341>; + lltc,fb-voltage-divider = <511000 158000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo1 { + regulator-min-microvolt = <1306329>; + regulator-max-microvolt = <1306329>; + lltc,fb-voltage-divider = <100000 158000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo2 { + regulator-min-microvolt = <704123>; + regulator-max-microvolt = <1456806>; + lltc,fb-voltage-divider = <180000 191000>; + regulator-ramp-delay = <7000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo3 { + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-boot-on; + }; + + ldo4 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3200000>; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/regulator/ltc3589.txt b/Documentation/devicetree/bindings/regulator/ltc3589.txt deleted file mode 100644 index 801053036146..000000000000 --- a/Documentation/devicetree/bindings/regulator/ltc3589.txt +++ /dev/null @@ -1,99 +0,0 @@ -Linear Technology LTC3589, LTC3589-1, and LTC3589-2 8-output regulators - -Required properties: -- compatible: "lltc,ltc3589", "lltc,ltc3589-1" or "lltc,ltc3589-2" -- reg: I2C slave address - -Required child node: -- regulators: Contains eight regulator child nodes sw1, sw2, sw3, bb-out, - ldo1, ldo2, ldo3, and ldo4, specifying the initialization data as - documented in Documentation/devicetree/bindings/regulator/regulator.txt. - -Each regulator is defined using the standard binding for regulators. The -nodes for sw1, sw2, sw3, bb-out, ldo1, and ldo2 additionally need to specify -the resistor values of their external feedback voltage dividers: - -Required properties (not on ldo3, ldo4): -- lltc,fb-voltage-divider: An array of two integers containing the resistor - values R1 and R2 of the feedback voltage divider in ohms. - -Regulators sw1, sw2, sw3, and ldo2 can regulate the feedback reference from -0.3625 V to 0.75 V in 12.5 mV steps. The output voltage thus ranges between -0.3625 * (1 + R1/R2) V and 0.75 * (1 + R1/R2) V. Regulators bb-out and ldo1 -have a fixed 0.8 V reference and thus output 0.8 * (1 + R1/R2) V. The ldo3 -regulator is fixed to 1.8 V on LTC3589 and to 2.8 V on LTC3589-1,2. The ldo4 -regulator can output between 1.8 V and 3.3 V on LTC3589 and between 1.2 V -and 3.2 V on LTC3589-1,2 in four steps. The ldo1 standby regulator can not -be disabled and thus should have the regulator-always-on property set. - -Example: - - ltc3589: pmic@34 { - compatible = "lltc,ltc3589-1"; - reg = <0x34>; - - regulators { - sw1_reg: sw1 { - regulator-min-microvolt = <591930>; - regulator-max-microvolt = <1224671>; - lltc,fb-voltage-divider = <100000 158000>; - regulator-ramp-delay = <7000>; - regulator-boot-on; - regulator-always-on; - }; - - sw2_reg: sw2 { - regulator-min-microvolt = <704123>; - regulator-max-microvolt = <1456803>; - lltc,fb-voltage-divider = <180000 191000>; - regulator-ramp-delay = <7000>; - regulator-boot-on; - regulator-always-on; - }; - - sw3_reg: sw3 { - regulator-min-microvolt = <1341250>; - regulator-max-microvolt = <2775000>; - lltc,fb-voltage-divider = <270000 100000>; - regulator-ramp-delay = <7000>; - regulator-boot-on; - regulator-always-on; - }; - - bb_out_reg: bb-out { - regulator-min-microvolt = <3387341>; - regulator-max-microvolt = <3387341>; - lltc,fb-voltage-divider = <511000 158000>; - regulator-boot-on; - regulator-always-on; - }; - - ldo1_reg: ldo1 { - regulator-min-microvolt = <1306329>; - regulator-max-microvolt = <1306329>; - lltc,fb-voltage-divider = <100000 158000>; - regulator-boot-on; - regulator-always-on; - }; - - ldo2_reg: ldo2 { - regulator-min-microvolt = <704123>; - regulator-max-microvolt = <1456806>; - lltc,fb-voltage-divider = <180000 191000>; - regulator-ramp-delay = <7000>; - regulator-boot-on; - regulator-always-on; - }; - - ldo3_reg: ldo3 { - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - regulator-boot-on; - }; - - ldo4_reg: ldo4 { - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <3200000>; - }; - }; - }; From 9396a1d9e14237f857046c0677ab24f3d5df340c Mon Sep 17 00:00:00 2001 From: Sang-Heon Jeon Date: Fri, 24 Jul 2026 03:45:30 +0900 Subject: [PATCH 22/36] regulator: wm831x-isink: remove conditional return with no effect Both branches of the check return the same value, so the check has no effect. Remove it and return the value directly. This is the result of running the Coccinelle script from scripts/coccinelle/misc/cond_return_no_effect.cocci. Signed-off-by: Sang-Heon Jeon Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20260723184538.3888637-29-ekffu200098@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/wm831x-isink.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c index 43f220cea21c..b46e2cde5e9d 100644 --- a/drivers/regulator/wm831x-isink.c +++ b/drivers/regulator/wm831x-isink.c @@ -62,11 +62,7 @@ static int wm831x_isink_disable(struct regulator_dev *rdev) if (ret < 0) return ret; - ret = wm831x_set_bits(wm831x, isink->reg, WM831X_CS1_ENA, 0); - if (ret < 0) - return ret; - - return ret; + return wm831x_set_bits(wm831x, isink->reg, WM831X_CS1_ENA, 0); } From bde9b2c351c8009a270054d3822e164af0ecfdb0 Mon Sep 17 00:00:00 2001 From: Victor Krawiec Date: Thu, 23 Jul 2026 11:39:58 +0200 Subject: [PATCH 23/36] regulator: dt-bindings: Add fan53555 allowed modes Fairchild FAN53555 and its clone from Rockchip, Silergy and TCS support two modes of operation: - Auto-PFM: Allow automatic PFM during light load (default mode) - Forced PWM Some boards require forced PWM mode to keep the supply ripple within acceptable limits under light load conditions. Regulator mode indexes are starting from 1 to keep backward compatibility with existing device trees Signed-off-by: Victor Krawiec Link: https://patch.msgid.link/20260723094001.120264-2-victor.krawiec@arturia.com Signed-off-by: Mark Brown --- .../bindings/regulator/fcs,fan53555.yaml | 8 ++++++++ .../regulator/fcs,fan53555-regulator.h | 20 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 include/dt-bindings/regulator/fcs,fan53555-regulator.h diff --git a/Documentation/devicetree/bindings/regulator/fcs,fan53555.yaml b/Documentation/devicetree/bindings/regulator/fcs,fan53555.yaml index 69bae90fc4b2..9a18891f721e 100644 --- a/Documentation/devicetree/bindings/regulator/fcs,fan53555.yaml +++ b/Documentation/devicetree/bindings/regulator/fcs,fan53555.yaml @@ -48,6 +48,12 @@ properties: VSEL0 register. When this pin is HIGH, VOUT is set by the VSEL1 register. maxItems: 1 + regulator-initial-mode: + enum: + [ 1, 2 ] + description: + Defined in include/dt-bindings/regulator/fcs,fan53555-regulator.h + required: - compatible - reg @@ -56,6 +62,7 @@ unevaluatedProperties: false examples: - | + #include i2c { #address-cells = <1>; #size-cells = <0>; @@ -68,6 +75,7 @@ examples: regulator-max-microvolt = <1800000>; vin-supply = <&parent_reg>; fcs,suspend-voltage-selector = <1>; + regulator-initial-mode = ; }; }; ... diff --git a/include/dt-bindings/regulator/fcs,fan53555-regulator.h b/include/dt-bindings/regulator/fcs,fan53555-regulator.h new file mode 100644 index 000000000000..ce3d6c63a0f1 --- /dev/null +++ b/include/dt-bindings/regulator/fcs,fan53555-regulator.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2026 Arturia - All rights reserved. + * + * Device Tree binding constants for the FAN53555 PMIC regulator + */ + +#ifndef _DT_BINDINGS_REGULATOR_FAN53555_H +#define _DT_BINDINGS_REGULATOR_FAN53555_H + +/* + * Constants to specify regulator modes in device tree for SYR82X regulators + * FAN53555_REGULATOR_MODE_FORCE_PWM: Force fixed PWM mode + * FAN53555_REGULATOR_MODE_AUTO: Allow auto-PFM mode during light load + */ + +#define FAN53555_REGULATOR_MODE_FORCE_PWM 1 +#define FAN53555_REGULATOR_MODE_AUTO 2 + +#endif From 99bc5744e966911e706b857feba7cd877ec3ccb4 Mon Sep 17 00:00:00 2001 From: Victor Krawiec Date: Thu, 23 Jul 2026 11:40:01 +0200 Subject: [PATCH 24/36] regulator: fan53555: Add support for mode operations on Silergy devices Make the PWM mode configurable from devicetree. Some boards require forced PWM mode to keep the supply ripple within acceptable limits under light load conditions Support is restricted to Silergy manufacturer as it is the only one currently tested. Signed-off-by: Victor Krawiec Link: https://patch.msgid.link/20260723094001.120264-5-victor.krawiec@arturia.com Signed-off-by: Mark Brown --- drivers/regulator/fan53555.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index c282236959b1..85f46874eb49 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -21,6 +21,7 @@ #include #include #include +#include /* Voltage setting */ #define FAN53555_VSEL0 0x00 @@ -389,6 +390,18 @@ static int rk8602_voltages_setup_rockchip(struct fan53555_device_info *di) return 0; } +static inline unsigned int fan53555_map_mode(unsigned int mode) +{ + switch (mode) { + case FAN53555_REGULATOR_MODE_FORCE_PWM: + return REGULATOR_MODE_FAST; + case FAN53555_REGULATOR_MODE_AUTO: + return REGULATOR_MODE_NORMAL; + default: + return REGULATOR_MODE_INVALID; + } +} + static int fan53555_voltages_setup_silergy(struct fan53555_device_info *di) { /* Init voltage range and step */ @@ -586,6 +599,17 @@ static int fan53555_device_setup(struct fan53555_device_info *di, return ret; } +static void fan53555_device_mode_map_setup(struct fan53555_device_info *di) +{ + switch (di->vendor) { + case FAN53555_VENDOR_SILERGY: + di->desc.of_map_mode = fan53555_map_mode; + break; + default: + break; + } +} + static int fan53555_regulator_register(struct fan53555_device_info *di, struct regulator_config *config) { @@ -686,6 +710,10 @@ static int fan53555_regulator_probe(struct i2c_client *client) if (!di) return -ENOMEM; + di->vendor = (uintptr_t)i2c_get_match_data(client); + + fan53555_device_mode_map_setup(di); + pdata = dev_get_platdata(&client->dev); if (!pdata) pdata = fan53555_parse_dt(&client->dev, np, &di->desc); @@ -695,7 +723,6 @@ static int fan53555_regulator_probe(struct i2c_client *client) "Platform data not found!\n"); di->regulator = pdata->regulator; - di->vendor = (uintptr_t)i2c_get_match_data(client); if (!dev_fwnode(&client->dev)) { /* if no ramp constraint set, get the pdata ramp_delay */ if (!di->regulator->constraints.ramp_delay) { From 623d9a55685c52b10b995d8dbde9da6283170220 Mon Sep 17 00:00:00 2001 From: Surendra Singh Chouhan Date: Fri, 24 Jul 2026 18:28:57 +0530 Subject: [PATCH 25/36] regulator: tps65185: handle gpiod_get_value_cansleep() error returns tps65185_vposneg_enable() evaluated: if (gpiod_get_value_cansleep(data->pgood_gpio) != 1) return -ETIMEDOUT; gpiod_get_value_cansleep() returns 1 if active, 0 if inactive, and a negative error code (e.g. -EIO or -EINVAL) on failure. Evaluating != 1 treats a negative error code as non-equal, swallowing GPIO read errors and masking them as -ETIMEDOUT. Fix this by capturing the return value of gpiod_get_value_cansleep(). If it returns a negative error code, propagate that error immediately; if it returns 0 (inactive), return -ETIMEDOUT. Fixes: b0fc1e770194 ("regulator: Add TPS65185 driver") Signed-off-by: Surendra Singh Chouhan Reviewed-by: Andreas Kemnade Link: https://patch.msgid.link/20260724125858.75635-1-kr494167@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/tps65185.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/tps65185.c b/drivers/regulator/tps65185.c index 786622d8d598..1f13e4156cab 100644 --- a/drivers/regulator/tps65185.c +++ b/drivers/regulator/tps65185.c @@ -183,7 +183,10 @@ static int tps65185_vposneg_enable(struct regulator_dev *rdev) wait_for_completion_timeout(&data->pgood_completion, msecs_to_jiffies(PGOOD_TIMEOUT_MSECS)); dev_dbg(data->dev, "turned on"); - if (gpiod_get_value_cansleep(data->pgood_gpio) != 1) + ret = gpiod_get_value_cansleep(data->pgood_gpio); + if (ret < 0) + return ret; + if (!ret) return -ETIMEDOUT; return 0; From e95a0a309ca02bf26dc937cdeb3fe2a235c65f63 Mon Sep 17 00:00:00 2001 From: bui duc phuc Date: Wed, 29 Jul 2026 17:00:18 +0700 Subject: [PATCH 26/36] regulator: rt6245: Restore state on enable failure Currently, if regcache_sync() fails after the enable GPIO has been asserted, the driver returns with enable_gpio still set high and regcache_cache_only() left disabled. This leaves the device state inconsistent with the disabled state, where the enable GPIO is low and cache_only is enabled. On failure, restore the original state by setting cache_only back to true and driving the enable GPIO low before returning the error. Signed-off-by: bui duc phuc Link: https://patch.msgid.link/20260729100018.66577-1-phucduc.bui@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/rt6245-regulator.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/rt6245-regulator.c b/drivers/regulator/rt6245-regulator.c index 1843ecec1922..5c0ee04e97ac 100644 --- a/drivers/regulator/rt6245-regulator.c +++ b/drivers/regulator/rt6245-regulator.c @@ -49,8 +49,11 @@ static int rt6245_enable(struct regulator_dev *rdev) regcache_cache_only(regmap, false); ret = regcache_sync(regmap); - if (ret) + if (ret) { + regcache_cache_only(regmap, true); + gpiod_direction_output(priv->enable_gpio, 0); return ret; + } priv->enable_state = true; return 0; From 03eab318cedd6ae34ecd34533cd986edf5237164 Mon Sep 17 00:00:00 2001 From: Joy Zou Date: Fri, 31 Jul 2026 18:21:43 +0800 Subject: [PATCH 27/36] regulator: core: use system_freezable_wq for init complete work schedule_delayed_work() uses system_wq, which is non-freezable, allowing regulator_init_complete_work to run concurrently with system suspend. This work fires ~30s after boot to disable unused regulators via I2C. When it races with PM suspend, the I2C adapter may already be suspended, triggering a -ESHUTDOWN warning in __i2c_transfer(): WARNING: ... at __i2c_transfer+0x36c/0x3c8 Call trace: __i2c_transfer i2c_transfer regmap_i2c_write _regmap_update_bits regulator_disable_regmap _regulator_do_disable regulator_late_cleanup regulator_init_complete_work_function process_one_work Switch to system_freezable_wq so the work is frozen before any device is suspended, eliminating the race. Fixes: 55576cf18537 ("regulator: Defer init completion for a while after late_initcall") Signed-off-by: Joy Zou Reviewed-by: Frank Li Link: https://patch.msgid.link/20260731-b4-regulator-pf01-v2-1-a406c8737fdb@oss.nxp.com Signed-off-by: Mark Brown --- drivers/regulator/core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 2e61606fc1d0..6a4008f387b5 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -27,6 +27,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include @@ -6899,8 +6900,9 @@ static int __init regulator_init_complete(void) * we'd only do this on systems that need it, and a kernel * command line option might be useful. */ - schedule_delayed_work(®ulator_init_complete_work, - msecs_to_jiffies(30000)); + queue_delayed_work(system_freezable_wq, + ®ulator_init_complete_work, + msecs_to_jiffies(30000)); return 0; } From 7595f50ff82260b6dd95af9e339f1d47f45ce753 Mon Sep 17 00:00:00 2001 From: Joy Zou Date: Fri, 31 Jul 2026 18:21:44 +0800 Subject: [PATCH 28/36] regulator: pfuze100: add set_suspend_disable for LDO ops Add a set_suspend_disable callback to pfuze100_ldo_regulator_ops to support the regulator-off-in-suspend DTS property for the VGEN LDO regulators. This allows unused LDO regulators to be properly disabled during system suspend, reducing power consumption. The callback is only used by the LDO ops, so name it accordingly: pfuze100_ldo_set_suspend_disable. It uses the per-regulator stby_reg/stby_mask that already describe the standby control for each LDO, so it works for every LDO covered by these ops. Signed-off-by: Joy Zou Reviewed-by: Frank Li Link: https://patch.msgid.link/20260731-b4-regulator-pf01-v2-2-a406c8737fdb@oss.nxp.com Signed-off-by: Mark Brown --- drivers/regulator/pfuze100-regulator.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index 7d56c22b5e40..d3a0e2505524 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -158,6 +158,25 @@ static int pfuze100_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) return ret; } +static int pfuze100_ldo_set_suspend_disable(struct regulator_dev *rdev) +{ + struct pfuze_chip *pfuze100 = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + struct pfuze_regulator *desc = &pfuze100->regulator_descs[id]; + + /* + * Set the standby bit so the LDO output is turned off when the PMIC + * receives a STANDBY event, using the per-regulator stby_reg/stby_mask + * that describe the standby control for each LDO. + * + * The stby_mask only covers the VGENxSTBY bit. The VGENxLPWR stays at + * its reset value of 0, so the LDO is switched off rather than put + * into low-power mode. + */ + return regmap_update_bits(pfuze100->regmap, desc->stby_reg, + desc->stby_mask, desc->stby_mask); +} + static const struct regulator_ops pfuze100_ldo_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -165,6 +184,7 @@ static const struct regulator_ops pfuze100_ldo_regulator_ops = { .list_voltage = regulator_list_voltage_linear, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_suspend_disable = pfuze100_ldo_set_suspend_disable, }; static const struct regulator_ops pfuze100_fixed_regulator_ops = { From 6f06147a5df6f5de0aa84412bc43db60afed67c9 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 1 Aug 2026 21:54:41 +0200 Subject: [PATCH 29/36] regulator: dt-bindings: Correct white-space style Correct a few white-space issues, like double space after '=' character, which will be flagged by dt-check-style. No functional changes. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260801195440.234183-2-krzysztof.kozlowski@oss.qualcomm.com Signed-off-by: Mark Brown --- .../bindings/regulator/nxp,pf8x00-regulator.yaml | 12 ++++++------ .../devicetree/bindings/regulator/ti,tps51632.yaml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/nxp,pf8x00-regulator.yaml b/Documentation/devicetree/bindings/regulator/nxp,pf8x00-regulator.yaml index 894bdbca78a2..8ac77c1a9b9f 100644 --- a/Documentation/devicetree/bindings/regulator/nxp,pf8x00-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/nxp,pf8x00-regulator.yaml @@ -134,42 +134,42 @@ examples: regulator-always-on; regulator-boot-on; regulator-max-microvolt = <1800000>; - regulator-min-microvolt = <400000>; + regulator-min-microvolt = <400000>; }; reg_buck2: buck2 { regulator-always-on; regulator-boot-on; regulator-max-microvolt = <1800000>; - regulator-min-microvolt = <400000>; + regulator-min-microvolt = <400000>; }; reg_buck3: buck3 { regulator-always-on; regulator-boot-on; regulator-max-microvolt = <1800000>; - regulator-min-microvolt = <400000>; + regulator-min-microvolt = <400000>; }; reg_buck4: buck4 { regulator-always-on; regulator-boot-on; regulator-max-microvolt = <1800000>; - regulator-min-microvolt = <400000>; + regulator-min-microvolt = <400000>; }; reg_buck5: buck5 { regulator-always-on; regulator-boot-on; regulator-max-microvolt = <1800000>; - regulator-min-microvolt = <400000>; + regulator-min-microvolt = <400000>; }; reg_buck6: buck6 { regulator-always-on; regulator-boot-on; regulator-max-microvolt = <1800000>; - regulator-min-microvolt = <400000>; + regulator-min-microvolt = <400000>; }; reg_buck7: buck7 { diff --git a/Documentation/devicetree/bindings/regulator/ti,tps51632.yaml b/Documentation/devicetree/bindings/regulator/ti,tps51632.yaml index 67ac40e3ec00..130fa9796f57 100644 --- a/Documentation/devicetree/bindings/regulator/ti,tps51632.yaml +++ b/Documentation/devicetree/bindings/regulator/ti,tps51632.yaml @@ -44,7 +44,7 @@ examples: tps51632@43 { compatible = "ti,tps51632"; - reg = <0x43>; + reg = <0x43>; regulator-name = "tps51632-vout"; regulator-min-microvolt = <500000>; regulator-max-microvolt = <1500000>; From 0991f3b4624ed713d1d5eb56520c1c9b2deaab7a Mon Sep 17 00:00:00 2001 From: Babanpreet Singh Date: Sun, 2 Aug 2026 01:33:04 +0000 Subject: [PATCH 30/36] regulator: ab8500: Remove stale expand_register kernel-doc entry Commit aeee55b76bfd ("regulator: ab8500: Remove unused embedded struct expand_register") deleted the expand_register member from struct ab8500_regulator_info and, in the same hunk, added an empty "@expand_register:" line to the kernel-doc block. That traded one W=1 warning for another: drivers/regulator/ab8500.c:196 Excess struct member 'expand_register' description in 'ab8500_regulator_info' Drop the leftover line; the remaining @member entries all match the struct. No functional changes. Reported-by: kernel test robot Closes: https://lore.kernel.org/r/202605160857.ZIE3nO9J-lkp@intel.com/ Assisted-by: Claude:claude-opus-5 [kernel-doc] Signed-off-by: Babanpreet Singh Link: https://patch.msgid.link/20260802013304.7-1-bbnpreetsingh@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 6b4a3a3d8385..3705c98b0713 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -173,7 +173,6 @@ struct ab8500_shared_mode { * @voltage_bank: bank to control regulator voltage * @voltage_reg: register to control regulator voltage * @voltage_mask: mask to control regulator voltage - * @expand_register: */ struct ab8500_regulator_info { struct device *dev; From 36c3ea84289913d16dd2ed783534193c957055b9 Mon Sep 17 00:00:00 2001 From: Bhargav Joshi Date: Wed, 29 Jul 2026 12:37:55 +0530 Subject: [PATCH 31/36] regulator: dt-bindings: ti,pbias-omap: Convert to DT schema Convert Texas Instruments PBIAS internal regulator from text to DT schema. Since all in tree DT uses SoC specific compatible along with "ti,pbias-omap" Convert compatible property to require the two-string form. Add child regulator nodes as property as they are fixed and node name is matched by driver. Signed-off-by: Bhargav Joshi Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20260729-ti-pbias-omap-v3-1-20fcc0bdc890@gmail.com Signed-off-by: Mark Brown --- .../bindings/regulator/pbias-regulator.txt | 32 ---- .../bindings/regulator/ti,pbias-omap.yaml | 137 ++++++++++++++++++ 2 files changed, 137 insertions(+), 32 deletions(-) delete mode 100644 Documentation/devicetree/bindings/regulator/pbias-regulator.txt create mode 100644 Documentation/devicetree/bindings/regulator/ti,pbias-omap.yaml diff --git a/Documentation/devicetree/bindings/regulator/pbias-regulator.txt b/Documentation/devicetree/bindings/regulator/pbias-regulator.txt deleted file mode 100644 index acbcb452a69a..000000000000 --- a/Documentation/devicetree/bindings/regulator/pbias-regulator.txt +++ /dev/null @@ -1,32 +0,0 @@ -PBIAS internal regulator for SD card dual voltage i/o pads on OMAP SoCs. - -Required properties: -- compatible: - - should be "ti,pbias-dra7" for DRA7 - - should be "ti,pbias-omap2" for OMAP2 - - should be "ti,pbias-omap3" for OMAP3 - - should be "ti,pbias-omap4" for OMAP4 - - should be "ti,pbias-omap5" for OMAP5 - - "ti,pbias-omap" is deprecated -- reg: pbias register offset from syscon base and size of pbias register. -- syscon : phandle of the system control module -- regulator-name : should be - pbias_mmc_omap2430 for OMAP2430, OMAP3 SoCs - pbias_sim_omap3 for OMAP3 SoCs - pbias_mmc_omap4 for OMAP4 SoCs - pbias_mmc_omap5 for OMAP5 and DRA7 SoC - -Optional properties: -- Any optional property defined in bindings/regulator/regulator.txt - -Example: - - pbias_regulator: pbias_regulator { - compatible = "ti,pbias-omap"; - reg = <0 0x4>; - syscon = <&omap5_padconf_global>; - pbias_mmc_reg: pbias_mmc_omap5 { - regulator-name = "pbias_mmc_omap5"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3000000>; - }; diff --git a/Documentation/devicetree/bindings/regulator/ti,pbias-omap.yaml b/Documentation/devicetree/bindings/regulator/ti,pbias-omap.yaml new file mode 100644 index 000000000000..4533f337963f --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/ti,pbias-omap.yaml @@ -0,0 +1,137 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/ti,pbias-omap.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments PBIAS internal regulator + +maintainers: + - Tony Lindgren + +properties: + compatible: + items: + - enum: + - ti,pbias-dra7 + - ti,pbias-omap2 + - ti,pbias-omap3 + - ti,pbias-omap4 + - ti,pbias-omap5 + - const: ti,pbias-omap + + reg: + maxItems: 1 + + syscon: + $ref: /schemas/types.yaml#/definitions/phandle + description: phandle of the system control module + + pbias_mmc_omap2430: + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + + required: + - regulator-name + + pbias_sim_omap3: + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + + required: + - regulator-name + + pbias_mmc_omap4: + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + + required: + - regulator-name + + pbias_mmc_omap5: + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + + required: + - regulator-name + +required: + - compatible + - reg + - syscon + +allOf: + - if: + properties: + compatible: + contains: + const: ti,pbias-omap2 + then: + required: + - pbias_mmc_omap2430 + properties: + pbias_sim_omap3: false + pbias_mmc_omap4: false + pbias_mmc_omap5: false + + - if: + properties: + compatible: + contains: + const: ti,pbias-omap3 + then: + anyOf: + - required: + - pbias_mmc_omap2430 + - required: + - pbias_sim_omap3 + properties: + pbias_mmc_omap4: false + pbias_mmc_omap5: false + + - if: + properties: + compatible: + contains: + const: ti,pbias-omap4 + then: + required: + - pbias_mmc_omap4 + properties: + pbias_mmc_omap2430: false + pbias_sim_omap3: false + pbias_mmc_omap5: false + + - if: + properties: + compatible: + contains: + enum: + - ti,pbias-omap5 + - ti,pbias-dra7 + then: + required: + - pbias_mmc_omap5 + properties: + pbias_mmc_omap2430: false + pbias_sim_omap3: false + pbias_mmc_omap4: false + +additionalProperties: false + +examples: + - | + pbias_regulator@0 { + compatible = "ti,pbias-omap5", "ti,pbias-omap"; + reg = <0 0x4>; + syscon = <&omap5_padconf_global>; + pbias_mmc_omap5 { + regulator-name = "pbias_mmc_omap5"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3000000>; + }; + }; From edbafe65eef2b58625db1e113fbbfb1fe10c0291 Mon Sep 17 00:00:00 2001 From: Maulik Shah Date: Sat, 1 Aug 2026 13:30:27 +0530 Subject: [PATCH 32/36] soc: qcom: rpmh: Add support to read back resource settings All rpmh_*() APIs so far have supported placing votes for various resource settings but the H/W also have option to read resource settings. Add new rpmh_read() API to allow clients to read back resource setting from H/W. This will be useful for clients like regulators, which currently don't have a way to know the settings applied during bootloader stage. Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Signed-off-by: Maulik Shah Signed-off-by: Kamal Wadhwa Link: https://patch.msgid.link/20260801-b4-read-rpmh-v5-v6-1-9fcb54928523@oss.qualcomm.com Signed-off-by: Mark Brown --- drivers/soc/qcom/rpmh-rsc.c | 13 ++++++++-- drivers/soc/qcom/rpmh.c | 47 +++++++++++++++++++++++++++++++++---- include/soc/qcom/rpmh.h | 5 ++++ include/soc/qcom/tcs.h | 2 ++ 4 files changed, 61 insertions(+), 6 deletions(-) diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index c6f7d5c9c493..ec85c457ea45 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -443,6 +443,7 @@ static irqreturn_t tcs_tx_done(int irq, void *p) int i; unsigned long irq_status; const struct tcs_request *req; + u32 reg; irq_status = readl_relaxed(drv->tcs_base + drv->regs[RSC_DRV_IRQ_STATUS]); @@ -453,6 +454,11 @@ static irqreturn_t tcs_tx_done(int irq, void *p) trace_rpmh_tx_done(drv, i, req); + if (req->is_read) { + reg = drv->regs[RSC_DRV_CMD_RESP_DATA]; + req->cmds[0].data = read_tcs_reg(drv, reg, i); + } + /* Clear AMC trigger & enable modes and * disable interrupt for this TCS */ @@ -493,13 +499,15 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id, const struct tcs_request *msg) { u32 msgid; - u32 cmd_msgid = CMD_MSGID_LEN | CMD_MSGID_WRITE; + u32 cmd_msgid = CMD_MSGID_LEN; u32 cmd_enable = 0; struct tcs_cmd *cmd; int i, j; /* Convert all commands to RR when the request has wait_for_compl set */ cmd_msgid |= msg->wait_for_compl ? CMD_MSGID_RESP_REQ : 0; + if (!msg->is_read) + cmd_msgid |= CMD_MSGID_WRITE; for (i = 0, j = cmd_id; i < msg->num_cmds; i++, j++) { cmd = &msg->cmds[i]; @@ -513,7 +521,8 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id, write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_MSGID], tcs_id, j, msgid); write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_ADDR], tcs_id, j, cmd->addr); - write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_DATA], tcs_id, j, cmd->data); + if (!msg->is_read) + write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_DATA], tcs_id, j, cmd->data); trace_rpmh_send_msg(drv, tcs_id, msg->state, j, msgid, cmd); } diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c index ca37da3dc2b1..f881c4c757ec 100644 --- a/drivers/soc/qcom/rpmh.c +++ b/drivers/soc/qcom/rpmh.c @@ -175,6 +175,9 @@ static int __rpmh_write(const struct device *dev, enum rpmh_state state, struct cache_req *req; int i; + if (rpm_msg->msg.is_read) + goto send_data; + /* Cache the request in our store and link the payload */ for (i = 0; i < rpm_msg->msg.num_cmds; i++) { req = cache_rpm_request(ctrlr, state, &rpm_msg->msg.cmds[i]); @@ -182,6 +185,7 @@ static int __rpmh_write(const struct device *dev, enum rpmh_state state, return PTR_ERR(req); } +send_data: if (state == RPMH_ACTIVE_ONLY_STATE) { ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msg->msg); } else { @@ -194,7 +198,7 @@ static int __rpmh_write(const struct device *dev, enum rpmh_state state, } static int __fill_rpmh_msg(struct rpmh_request *req, enum rpmh_state state, - const struct tcs_cmd *cmd, u32 n) + const struct tcs_cmd *cmd, u32 n, bool is_read) { if (!cmd || !n || n > MAX_RPMH_PAYLOAD) return -EINVAL; @@ -204,10 +208,45 @@ static int __fill_rpmh_msg(struct rpmh_request *req, enum rpmh_state state, req->msg.state = state; req->msg.cmds = req->cmd; req->msg.num_cmds = n; + req->msg.is_read = is_read; return 0; } +/** + * rpmh_read: Read a resource value + * + * @dev: The device making the request + * @cmd: The payload having address of resource to read + * + * Reads the value for the resource address given in tcs_cmd->addr + * and returns the tcs_cmd->data filled with same. + * + * Context: May sleep. Do not call from atomic contexts. + * + * Return: 0 on success, negative errno on failure + */ +int rpmh_read(const struct device *dev, struct tcs_cmd *cmd) +{ + DECLARE_COMPLETION_ONSTACK(compl); + DEFINE_RPMH_MSG_ONSTACK(dev, RPMH_ACTIVE_ONLY_STATE, &compl, rpm_msg); + int ret; + + ret = __fill_rpmh_msg(&rpm_msg, RPMH_ACTIVE_ONLY_STATE, cmd, 1, true); + if (ret) + return ret; + + ret = __rpmh_write(dev, RPMH_ACTIVE_ONLY_STATE, &rpm_msg); + if (ret) + return ret; + + ret = wait_for_completion_timeout(&compl, RPMH_TIMEOUT_MS); + cmd[0].data = rpm_msg.cmd[0].data; + + return (ret > 0) ? 0 : -ETIMEDOUT; +} +EXPORT_SYMBOL_GPL(rpmh_read); + /** * rpmh_write_async: Write a set of RPMH commands * @@ -230,7 +269,7 @@ int rpmh_write_async(const struct device *dev, enum rpmh_state state, return -ENOMEM; rpm_msg->needs_free = true; - ret = __fill_rpmh_msg(rpm_msg, state, cmd, n); + ret = __fill_rpmh_msg(rpm_msg, state, cmd, n, false); if (ret) { kfree(rpm_msg); return ret; @@ -257,7 +296,7 @@ int rpmh_write(const struct device *dev, enum rpmh_state state, DEFINE_RPMH_MSG_ONSTACK(dev, state, &compl, rpm_msg); int ret; - ret = __fill_rpmh_msg(&rpm_msg, state, cmd, n); + ret = __fill_rpmh_msg(&rpm_msg, state, cmd, n, false); if (ret) return ret; @@ -352,7 +391,7 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state, rpm_msgs = req->rpm_msgs; for (i = 0; i < count; i++) { - __fill_rpmh_msg(rpm_msgs + i, state, cmd, n[i]); + __fill_rpmh_msg(rpm_msgs + i, state, cmd, n[i], false); cmd += n[i]; } diff --git a/include/soc/qcom/rpmh.h b/include/soc/qcom/rpmh.h index bdbee1a97d36..14ecbf242b6b 100644 --- a/include/soc/qcom/rpmh.h +++ b/include/soc/qcom/rpmh.h @@ -11,6 +11,8 @@ #if IS_ENABLED(CONFIG_QCOM_RPMH) +int rpmh_read(const struct device *dev, struct tcs_cmd *cmd); + int rpmh_write(const struct device *dev, enum rpmh_state state, const struct tcs_cmd *cmd, u32 n); @@ -24,6 +26,9 @@ void rpmh_invalidate(const struct device *dev); #else +static inline int rpmh_read(const struct device *dev, struct tcs_cmd *cmd) +{ return -ENODEV; } + static inline int rpmh_write(const struct device *dev, enum rpmh_state state, const struct tcs_cmd *cmd, u32 n) { return -ENODEV; } diff --git a/include/soc/qcom/tcs.h b/include/soc/qcom/tcs.h index cff67ce25488..45b8513be2f9 100644 --- a/include/soc/qcom/tcs.h +++ b/include/soc/qcom/tcs.h @@ -51,6 +51,7 @@ struct tcs_cmd { * struct tcs_request: A set of tcs_cmds sent together in a TCS * * @state: state for the request. + * @is_read: set for read only requests * @wait_for_compl: wait until we get a response from the h/w accelerator * (same as setting cmd->wait for all commands in the request) * @num_cmds: the number of @cmds in this request @@ -58,6 +59,7 @@ struct tcs_cmd { */ struct tcs_request { enum rpmh_state state; + bool is_read; u32 wait_for_compl; u32 num_cmds; struct tcs_cmd *cmds; From abd14bebb87e0fa2749371272c8b31d6ee5f0a36 Mon Sep 17 00:00:00 2001 From: Kamal Wadhwa Date: Sat, 1 Aug 2026 13:30:28 +0530 Subject: [PATCH 33/36] regulator: qcom-rpmh: Fix PMIC5 BOB bypass mode handling Currently, when `rpmh_regulator_set_mode_bypass()` helper function is called to set bypass mode, it sends PMIC4's BOB bypass mode value for even if its a PMIC5 BOB. To fix this, introduce new hw_data parameter`pmic_bypass_mode` to store bypass mode value. Use it to send correct PMIC bypass mode value that corresponds to PMIC4/5 BOB regulators from the helper function. Fixes: 610f29e5cc0e8d58 ("regulator: qcom-rpmh: Update PMIC modes for PMIC5") Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Signed-off-by: Kamal Wadhwa Link: https://patch.msgid.link/20260801-b4-read-rpmh-v5-v6-2-9fcb54928523@oss.qualcomm.com Signed-off-by: Mark Brown --- drivers/regulator/qcom-rpmh-regulator.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index 756a4201225e..c47dc9f92279 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -111,6 +111,7 @@ static const struct resource_name_formats vreg_rsc_name_lookup[NUM_REGULATOR_TYP * @hpm_min_load_uA: Minimum load current in microamps that requires * high power mode (HPM) operation. This is used * for LDO hardware type regulators only. + * @pmic_bypass_mode: The PMIC bypass mode value. * @pmic_mode_map: Array indexed by regulator framework mode * containing PMIC hardware modes. Must be large * enough to index all framework modes supported @@ -125,6 +126,7 @@ struct rpmh_vreg_hw_data { int n_linear_ranges; int n_voltages; int hpm_min_load_uA; + int pmic_bypass_mode; const int *pmic_mode_map; unsigned int (*of_map_mode)(unsigned int mode); }; @@ -311,7 +313,7 @@ static int rpmh_regulator_vrm_set_mode_bypass(struct rpmh_vreg *vreg, return pmic_mode; if (bypassed) - cmd.data = PMIC4_BOB_MODE_PASS; + cmd.data = vreg->hw_data->pmic_bypass_mode; else cmd.data = pmic_mode; @@ -767,6 +769,7 @@ static const struct rpmh_vreg_hw_data pmic4_bob = { }, .n_linear_ranges = 1, .n_voltages = 84, + .pmic_bypass_mode = PMIC4_BOB_MODE_PASS, .pmic_mode_map = pmic_mode_map_pmic4_bob, .of_map_mode = rpmh_regulator_pmic4_bob_of_map_mode, }; @@ -975,6 +978,7 @@ static const struct rpmh_vreg_hw_data pmic5_bob = { }, .n_linear_ranges = 1, .n_voltages = 32, + .pmic_bypass_mode = PMIC5_BOB_MODE_PASS, .pmic_mode_map = pmic_mode_map_pmic5_bob, .of_map_mode = rpmh_regulator_pmic4_bob_of_map_mode, }; From 09d99ff7fc3c802c9b31ded9ffdf992d966a0835 Mon Sep 17 00:00:00 2001 From: Kamal Wadhwa Date: Sat, 1 Aug 2026 13:30:29 +0530 Subject: [PATCH 34/36] regulator: qcom-rpmh: readback voltage/bypass/mode set during bootup Currently, during regulator registration, regulator framework sends an unnecessary `min-microvolts` request for the rpmh-regulator device. This happens because in current design, we do not have a way to readback the voltage settings that was set during the bootloader stage. Fix this by using the rpmh_read() API to read the regulator voltage settings done during boot and make it available to regulator framework from the very first read after the bootup. Also use this API to read the mode/bypass settings as well. This will provide the regulator framework a sense of the initial settings done by bootloader and thus preventing any redundant writes for any setting post bootup incase the same setting was already applied during bootup. Signed-off-by: Kamal Wadhwa Link: https://patch.msgid.link/20260801-b4-read-rpmh-v5-v6-3-9fcb54928523@oss.qualcomm.com Signed-off-by: Mark Brown --- drivers/regulator/qcom-rpmh-regulator.c | 120 ++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index c47dc9f92279..77d402ee6bf6 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -4,6 +4,7 @@ #define pr_fmt(fmt) "%s: " fmt, __func__ +#include #include #include #include @@ -61,8 +62,13 @@ static const struct resource_name_formats vreg_rsc_name_lookup[NUM_REGULATOR_TYP }; #define RPMH_REGULATOR_REG_VRM_VOLTAGE 0x0 +#define RPMH_REGULATOR_VOLTAGE_MASK GENMASK(12, 0) + #define RPMH_REGULATOR_REG_ENABLE 0x4 +#define RPMH_REGULATOR_ENABLE_MASK BIT(0) + #define RPMH_REGULATOR_REG_VRM_MODE 0x8 +#define RPMH_REGULATOR_MODE_MASK GENMASK(2, 0) #define PMIC4_LDO_MODE_RETENTION 4 #define PMIC4_LDO_MODE_LPM 5 @@ -248,9 +254,34 @@ static int rpmh_regulator_vrm_set_voltage_sel(struct regulator_dev *rdev, selector > vreg->voltage_selector); } +static int _rpmh_regulator_vrm_get_voltage(struct regulator_dev *rdev, int *uV) +{ + struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); + struct tcs_cmd cmd = { + .addr = vreg->addr + RPMH_REGULATOR_REG_VRM_VOLTAGE, + }; + int ret; + + ret = rpmh_read(vreg->dev, &cmd); + if (!ret) + *uV = (cmd.data & RPMH_REGULATOR_VOLTAGE_MASK) * 1000; + else + dev_err(vreg->dev, "failed to read VOLTAGE ret = %d\n", ret); + + return ret; +} + static int rpmh_regulator_vrm_get_voltage_sel(struct regulator_dev *rdev) { struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); + int ret, uV = 0; + + if (vreg->voltage_selector < 0) { + ret = _rpmh_regulator_vrm_get_voltage(rdev, &uV); + if (!ret && uV != 0) + vreg->voltage_selector = regulator_map_voltage_linear_range(rdev, + uV, INT_MAX); + } return vreg->voltage_selector; } @@ -336,6 +367,22 @@ static int rpmh_regulator_vrm_set_mode(struct regulator_dev *rdev, return ret; } +static int rpmh_regulator_vrm_get_pmic_mode(struct rpmh_vreg *vreg, int *pmic_mode) +{ + struct tcs_cmd cmd = { + .addr = vreg->addr + RPMH_REGULATOR_REG_VRM_MODE, + }; + int ret; + + ret = rpmh_read(vreg->dev, &cmd); + if (!ret) + *pmic_mode = cmd.data & RPMH_REGULATOR_MODE_MASK; + else + return -EINVAL; + + return 0; +} + static unsigned int rpmh_regulator_vrm_get_mode(struct regulator_dev *rdev) { struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); @@ -540,6 +587,73 @@ static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev, return 0; } +static int rpmh_regulator_determine_initial_mode(struct rpmh_vreg *vreg) +{ + struct tcs_cmd cmd = { + .addr = vreg->addr + RPMH_REGULATOR_REG_ENABLE, + }; + int ret, pmic_mode, mode; + int sts; + + ret = rpmh_read(vreg->dev, &cmd); + if (ret) { + dev_err(vreg->dev, "failed to read ENABLE status ret = %d\n", ret); + + return ret; + } + + sts = cmd.data & RPMH_REGULATOR_ENABLE_MASK; + if (!sts) + return 0; + + if (vreg->hw_data->regulator_type == XOB) + return 0; + + ret = rpmh_regulator_vrm_get_pmic_mode(vreg, &pmic_mode); + if (ret < 0) { + vreg->mode = REGULATOR_MODE_INVALID; + dev_err(vreg->dev, "failed to read pmic_mode ret = %d\n", ret); + + return ret; + } + + /* + * NOTE: Since BOB4 BYPASS_MODE value = 0 we cannot confirm if that BOB + * regulator has been sent into bypass mode by bootloader or if bootloader + * just has not requested for any mode voting. Due this limitation, we + * must check if the read pmic_mode value is non-zero before comparing it + * to bypass mode value. This also is needed to avoid setting BYPASS status + * for LDOs which dont support bypass mode, and have the pmic_bypass_mode + * uninitialized value as zero in the vreg hw data. For such cases assume + * lowest mode, if pmic_mode is zero, to allow for mode voting. + */ + if (!pmic_mode) { + for (mode = REGULATOR_MODE_STANDBY; mode > REGULATOR_MODE_INVALID; mode >>= 1) { + if (vreg->hw_data->pmic_mode_map[mode] >= 0) { + vreg->mode = mode; + break; + } + } + + return 0; + } + + if (vreg->hw_data->pmic_bypass_mode == pmic_mode) { + vreg->bypassed = true; + + return 0; + } + + for (mode = REGULATOR_MODE_STANDBY; mode > REGULATOR_MODE_INVALID; mode >>= 1) { + if (pmic_mode == vreg->hw_data->pmic_mode_map[mode]) { + vreg->mode = mode; + break; + } + } + + return 0; +} + static const int pmic_mode_map_pmic4_ldo[REGULATOR_MODE_STANDBY + 1] = { [REGULATOR_MODE_INVALID] = -EINVAL, [REGULATOR_MODE_STANDBY] = PMIC4_LDO_MODE_RETENTION, @@ -1838,6 +1952,12 @@ static int rpmh_regulator_probe(struct platform_device *pdev) vreg_data); if (ret < 0) return ret; + + ret = rpmh_regulator_determine_initial_mode(vreg); + if (ret < 0) + dev_err(dev, "failed to read initial mode for %s\n", + vreg->rdesc.name); + } return 0; From 216e8873bc80e9e9ab5bfe325a4f6d17bb3b8229 Mon Sep 17 00:00:00 2001 From: Kamal Wadhwa Date: Sat, 1 Aug 2026 13:30:30 +0530 Subject: [PATCH 35/36] regulator: qcom-rpmh: Fix coding style issues Fix the code style/format issues reported by checkpatch.pl script. Reviewed-by: Dmitry Baryshkov Signed-off-by: Kamal Wadhwa Link: https://patch.msgid.link/20260801-b4-read-rpmh-v5-v6-4-9fcb54928523@oss.qualcomm.com Signed-off-by: Mark Brown --- drivers/regulator/qcom-rpmh-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index 77d402ee6bf6..250b2c6bb795 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -110,7 +110,7 @@ static const struct resource_name_formats vreg_rsc_name_lookup[NUM_REGULATOR_TYP * regulator * @ops: Pointer to regulator ops callback structure * @voltage_ranges: The possible ranges of voltages supported by this - * PMIC regulator type + * PMIC regulator type * @n_linear_ranges: Number of entries in voltage_ranges * @n_voltages: The number of unique voltage set points defined * by voltage_ranges From e739acbe05b06de78ef7089470f122432f651faa Mon Sep 17 00:00:00 2001 From: Arash Golgol Date: Wed, 12 Aug 2026 16:20:54 +0330 Subject: [PATCH 36/36] regulator: fan53555: Add support for FAN53555BUC23X type FAN53555BUC23X has the ID 0 and REV 0xc, starts at 600mV and increments in 12.5mV steps. Per the datasheet, the FAN53555BUC23X (23 option) is grouped with the 00 and 13 options for soft-start timing (t_SS = 300us typ.), so the existing enable_time = 400 is reused here as well. This variant is found on the ASUS Tinker Edge R (RK3399Pro) as the supply regulator for both vdd_gpu and vdd_cpu_b. Verified across the full GPU OPP table with the userspace devfreq governor. Signed-off-by: Arash Golgol Link: https://patch.msgid.link/20260812125054.19111-1-arash.golgol@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/fan53555.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 85f46874eb49..6557d8cbe98d 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -114,6 +114,7 @@ enum { enum { FAN53555_CHIP_REV_00 = 0x3, FAN53555_CHIP_REV_13 = 0xf, + FAN53555_CHIP_REV_23 = 0xc, }; enum { @@ -306,6 +307,11 @@ static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di) di->vsel_step = 10000; di->enable_time = 400; break; + case FAN53555_CHIP_REV_23: + di->vsel_min = 600000; + di->vsel_step = 12500; + di->enable_time = 400; + break; default: dev_err(di->dev, "Chip ID %d with rev %d not supported!\n",