From 72b6a2d6506843375c7b91197f49ef38ca0c6d0f Mon Sep 17 00:00:00 2001 From: Alina Yu Date: Tue, 28 May 2024 14:01:13 +0800 Subject: regulator: rtq2208: Fix invalid memory access when devm_of_regulator_put_matches is called In this patch, a software bug has been fixed. rtq2208_ldo_match is no longer a local variable. It prevents invalid memory access when devm_of_regulator_put_matches is called. Signed-off-by: Alina Yu Link: https://msgid.link/r/4ce8c4f16f1cf3aa4e5f36c0694dd3c5ccf3cd1c.1716870419.git.alina_yu@richtek.com Signed-off-by: Mark Brown --- drivers/regulator/rtq2208-regulator.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/rtq2208-regulator.c b/drivers/regulator/rtq2208-regulator.c index b90e53d922d6..c31b6dc3229c 100644 --- a/drivers/regulator/rtq2208-regulator.c +++ b/drivers/regulator/rtq2208-regulator.c @@ -228,6 +228,11 @@ static const struct regulator_ops rtq2208_regulator_ldo_ops = { .set_suspend_disable = rtq2208_set_suspend_disable, }; +static struct of_regulator_match rtq2208_ldo_match[] = { + {.name = "ldo2", }, + {.name = "ldo1", }, +}; + static unsigned int rtq2208_of_map_mode(unsigned int mode) { switch (mode) { @@ -322,8 +327,7 @@ static irqreturn_t rtq2208_irq_handler(int irqno, void *devid) return IRQ_HANDLED; } -static int rtq2208_of_get_fixed_voltage(struct device *dev, - struct of_regulator_match *rtq2208_ldo_match, int n_fixed) +static int rtq2208_of_get_ldo_dvs_ability(struct device *dev) { struct device_node *np; struct of_regulator_match *match; @@ -338,14 +342,14 @@ static int rtq2208_of_get_fixed_voltage(struct device *dev, if (!np) np = dev->of_node; - ret = of_regulator_match(dev, np, rtq2208_ldo_match, n_fixed); + ret = of_regulator_match(dev, np, rtq2208_ldo_match, ARRAY_SIZE(rtq2208_ldo_match)); of_node_put(np); if (ret < 0) return ret; - for (i = 0; i < n_fixed; i++) { + for (i = 0; i < ARRAY_SIZE(rtq2208_ldo_match); i++) { match = rtq2208_ldo_match + i; init_data = match->init_data; rdesc = (struct rtq2208_regulator_desc *)match->driver_data; @@ -388,8 +392,7 @@ static const struct linear_range rtq2208_vout_range[] = { REGULATOR_LINEAR_RANGE(1310000, 181, 255, 10000), }; -static void rtq2208_init_regulator_desc(struct rtq2208_regulator_desc *rdesc, int mtp_sel, - int idx, struct of_regulator_match *rtq2208_ldo_match, int *ldo_idx) +static void rtq2208_init_regulator_desc(struct rtq2208_regulator_desc *rdesc, int mtp_sel, int idx) { struct regulator_desc *desc; static const struct { @@ -461,8 +464,7 @@ static void rtq2208_init_regulator_desc(struct rtq2208_regulator_desc *rdesc, in static int rtq2208_parse_regulator_dt_data(int n_regulator, const unsigned int *regulator_idx_table, struct rtq2208_regulator_desc *rdesc[RTQ2208_LDO_MAX], struct device *dev) { - struct of_regulator_match rtq2208_ldo_match[2]; - int mtp_sel, ret, i, idx, ldo_idx = 0; + int mtp_sel, i, idx, ret; /* get mtp_sel0 or mtp_sel1 */ mtp_sel = device_property_read_bool(dev, "richtek,mtp-sel-high"); @@ -474,7 +476,7 @@ static int rtq2208_parse_regulator_dt_data(int n_regulator, const unsigned int * if (!rdesc[i]) return -ENOMEM; - rtq2208_init_regulator_desc(rdesc[i], mtp_sel, idx, rtq2208_ldo_match, &ldo_idx); + rtq2208_init_regulator_desc(rdesc[i], mtp_sel, idx); /* init ldo dvs ability */ if (idx >= RTQ2208_LDO2) @@ -482,7 +484,7 @@ static int rtq2208_parse_regulator_dt_data(int n_regulator, const unsigned int * } /* init ldo fixed_uV */ - ret = rtq2208_of_get_fixed_voltage(dev, rtq2208_ldo_match, ldo_idx); + ret = rtq2208_of_get_ldo_dvs_ability(dev); if (ret) return dev_err_probe(dev, ret, "Failed to get ldo fixed_uV\n"); -- cgit v1.2.3 From 74259990b5938dc55fbe2f9b0431d5f370d34b85 Mon Sep 17 00:00:00 2001 From: Alina Yu Date: Tue, 28 May 2024 14:01:14 +0800 Subject: regulator: rtq2208: Fix LDO to be compatible with both fixed and adjustable vout In this patch, LDO's adjustable and fixed Vout settings are compatible. The LDO Vout ability depends on "richtek,fixed-microvolt". If adjustable, the Vout can be set to either 1800mV or 3300mV. Signed-off-by: Alina Yu Link: https://msgid.link/r/5ad4c7728c7fa7f6286db36b99d31c9d0f5d16c7.1716870419.git.alina_yu@richtek.com Signed-off-by: Mark Brown --- drivers/regulator/rtq2208-regulator.c | 37 +++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/rtq2208-regulator.c b/drivers/regulator/rtq2208-regulator.c index c31b6dc3229c..f6afa4e52814 100644 --- a/drivers/regulator/rtq2208-regulator.c +++ b/drivers/regulator/rtq2208-regulator.c @@ -219,7 +219,7 @@ static const struct regulator_ops rtq2208_regulator_buck_ops = { .set_suspend_mode = rtq2208_set_suspend_mode, }; -static const struct regulator_ops rtq2208_regulator_ldo_ops = { +static const struct regulator_ops rtq2208_regulator_ldo_fix_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -228,6 +228,23 @@ static const struct regulator_ops rtq2208_regulator_ldo_ops = { .set_suspend_disable = rtq2208_set_suspend_disable, }; +static const struct regulator_ops rtq2208_regulator_ldo_adj_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_table, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_active_discharge = regulator_set_active_discharge_regmap, + .set_suspend_enable = rtq2208_set_suspend_enable, + .set_suspend_disable = rtq2208_set_suspend_disable, +}; + +static const unsigned int rtq2208_ldo_volt_table[] = { + 1800000, + 3300000, +}; + static struct of_regulator_match rtq2208_ldo_match[] = { {.name = "ldo2", }, {.name = "ldo1", }, @@ -331,7 +348,7 @@ static int rtq2208_of_get_ldo_dvs_ability(struct device *dev) { struct device_node *np; struct of_regulator_match *match; - struct rtq2208_regulator_desc *rdesc; + struct regulator_desc *desc; struct regulator_init_data *init_data; int ret, i; @@ -352,13 +369,21 @@ static int rtq2208_of_get_ldo_dvs_ability(struct device *dev) for (i = 0; i < ARRAY_SIZE(rtq2208_ldo_match); i++) { match = rtq2208_ldo_match + i; init_data = match->init_data; - rdesc = (struct rtq2208_regulator_desc *)match->driver_data; + desc = (struct regulator_desc *)match->desc; - if (!init_data || !rdesc) + if (!init_data || !desc) continue; - if (init_data->constraints.min_uV == init_data->constraints.max_uV) - rdesc->desc.fixed_uV = init_data->constraints.min_uV; + if (init_data->constraints.min_uV == init_data->constraints.max_uV) { + desc->fixed_uV = init_data->constraints.min_uV; + desc->n_voltages = 1; + desc->fixed_uV = init_data->constraints.min_uV; + desc->ops = &rtq2208_regulator_ldo_fix_ops; + } else { + desc->n_voltages = ARRAY_SIZE(rtq2208_ldo_volt_table); + desc->volt_table = rtq2208_ldo_volt_table; + desc->ops = &rtq2208_regulator_ldo_adj_ops; + } } return 0; -- cgit v1.2.3 From af1296d15d8907a5aeeeb4ecd3e5878c9a349048 Mon Sep 17 00:00:00 2001 From: Alina Yu Date: Tue, 28 May 2024 14:01:15 +0800 Subject: regulator: rtq2208: Add fixed LDO VOUT property and check that matches the constraints A fixed LDO VOUT property has been added to specify the fixed_uV of the regulator_desc. Additionally, a check has been included in this version to ensure that the fixed_uV matches the constraints. Signed-off-by: Alina Yu Link: https://msgid.link/r/39357ff9e6e5f3dec5a6f7f833a3591c0defc63a.1716870419.git.alina_yu@richtek.com Signed-off-by: Mark Brown --- drivers/regulator/rtq2208-regulator.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/rtq2208-regulator.c b/drivers/regulator/rtq2208-regulator.c index f6afa4e52814..a5c126afc648 100644 --- a/drivers/regulator/rtq2208-regulator.c +++ b/drivers/regulator/rtq2208-regulator.c @@ -350,6 +350,7 @@ static int rtq2208_of_get_ldo_dvs_ability(struct device *dev) struct of_regulator_match *match; struct regulator_desc *desc; struct regulator_init_data *init_data; + u32 fixed_uV; int ret, i; if (!dev->of_node) @@ -374,9 +375,15 @@ static int rtq2208_of_get_ldo_dvs_ability(struct device *dev) if (!init_data || !desc) continue; - if (init_data->constraints.min_uV == init_data->constraints.max_uV) { - desc->fixed_uV = init_data->constraints.min_uV; + /* specify working fixed voltage if the propery exists */ + ret = of_property_read_u32(match->of_node, "richtek,fixed-microvolt", &fixed_uV); + + if (!ret) { + if (fixed_uV != init_data->constraints.min_uV || + fixed_uV != init_data->constraints.max_uV) + return -EINVAL; desc->n_voltages = 1; + desc->fixed_uV = fixed_uV; desc->fixed_uV = init_data->constraints.min_uV; desc->ops = &rtq2208_regulator_ldo_fix_ops; } else { -- cgit v1.2.3