From 70ca117b02f3b1c8830fe95e4e3dea2937038e11 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 19 Jun 2019 14:42:39 +0200 Subject: [PATCH 1/3] regulator: s2mps11: Fix ERR_PTR dereference on GPIO lookup failure If devm_gpiod_get_from_of_node() call returns ERR_PTR, it is assigned into an array of GPIO descriptors and used later because such error is not treated as critical thus it is not propagated back to the probe function. All code later expects that such GPIO descriptor is either a NULL or proper value. This later might lead to dereference of ERR_PTR. Only devices with S2MPS14 flavor are affected (other do not control regulators with GPIOs). Fixes: 1c984942f0a4 ("regulator: s2mps11: Pass descriptor instead of GPIO number") Cc: Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 134c62db36c5..af9bf10b4c33 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -824,6 +824,7 @@ static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev, if (IS_ERR(gpio[reg])) { dev_err(&pdev->dev, "Failed to get control GPIO for %d/%s\n", reg, rdata[reg].name); + gpio[reg] = NULL; continue; } if (gpio[reg]) From 16da0eb5ab6ef2dd1d33431199126e63db9997cc Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Jun 2019 13:44:45 +0200 Subject: [PATCH 2/3] regulator: s2mps11: Fix buck7 and buck8 wrong voltages On S2MPS11 device, the buck7 and buck8 regulator voltages start at 750 mV, not 600 mV. Using wrong minimal value caused shifting of these regulator values by 150 mV (e.g. buck7 usually configured to v1.35 V was reported as 1.2 V). On most of the boards these regulators are left in default state so this was only affecting reported voltage. However if any driver wanted to change them, then effectively it would set voltage 150 mV higher than intended. Cc: Fixes: cb74685ecb39 ("regulator: s2mps11: Add samsung s2mps11 regulator driver") Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index af9bf10b4c33..7a89030187a4 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -372,8 +372,8 @@ static const struct regulator_desc s2mps11_regulators[] = { regulator_desc_s2mps11_buck1_4(4), regulator_desc_s2mps11_buck5, regulator_desc_s2mps11_buck67810(6, MIN_600_MV, STEP_6_25_MV), - regulator_desc_s2mps11_buck67810(7, MIN_600_MV, STEP_12_5_MV), - regulator_desc_s2mps11_buck67810(8, MIN_600_MV, STEP_12_5_MV), + regulator_desc_s2mps11_buck67810(7, MIN_750_MV, STEP_12_5_MV), + regulator_desc_s2mps11_buck67810(8, MIN_750_MV, STEP_12_5_MV), regulator_desc_s2mps11_buck9, regulator_desc_s2mps11_buck67810(10, MIN_750_MV, STEP_12_5_MV), }; From 9d83dcb3e4553f34ee1c4f09d65173159f9eb7a7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Jun 2019 13:44:46 +0200 Subject: [PATCH 3/3] regulator: s2mps11: Adjust supported buck voltages to real values The driver was registering buck regulators with unsupported range of voltages for S2MPS11 devices. Basically it assumed that all 256 values are possible for a single 8-bit I2C register controlling buck's voltage. This is not true, as datasheet describes subset of these which can be used. For example for buck[12346] the minimum voltage is 650 mV which corresponds to register value of 0x8. The driver was however registering regulator starting at 600 mV, so for a step of 6.25 mV this gave the same result. However this allowed to try to configure regulators to unsupported values. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 27 +++++++++++++++++---------- include/linux/mfd/samsung/core.h | 1 + include/linux/mfd/samsung/s2mps11.h | 4 +++- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 7a89030187a4..5b7ba7c6c4f6 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -269,9 +269,10 @@ static const struct regulator_ops s2mps11_buck_ops = { .ops = &s2mps11_buck_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ - .min_uV = MIN_600_MV, \ + .min_uV = MIN_650_MV, \ .uV_step = STEP_6_25_MV, \ - .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ + .linear_min_sel = 8, \ + .n_voltages = S2MPS11_BUCK12346_N_VOLTAGES, \ .ramp_delay = S2MPS11_RAMP_DELAY, \ .vsel_reg = S2MPS11_REG_B1CTRL2 + (num - 1) * 2, \ .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ @@ -285,9 +286,10 @@ static const struct regulator_ops s2mps11_buck_ops = { .ops = &s2mps11_buck_ops, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ - .min_uV = MIN_600_MV, \ + .min_uV = MIN_650_MV, \ .uV_step = STEP_6_25_MV, \ - .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ + .linear_min_sel = 8, \ + .n_voltages = S2MPS11_BUCK5_N_VOLTAGES, \ .ramp_delay = S2MPS11_RAMP_DELAY, \ .vsel_reg = S2MPS11_REG_B5CTRL2, \ .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ @@ -295,7 +297,7 @@ static const struct regulator_ops s2mps11_buck_ops = { .enable_mask = S2MPS11_ENABLE_MASK \ } -#define regulator_desc_s2mps11_buck67810(num, min, step) { \ +#define regulator_desc_s2mps11_buck67810(num, min, step, min_sel, voltages) { \ .name = "BUCK"#num, \ .id = S2MPS11_BUCK##num, \ .ops = &s2mps11_buck_ops, \ @@ -303,7 +305,8 @@ static const struct regulator_ops s2mps11_buck_ops = { .owner = THIS_MODULE, \ .min_uV = min, \ .uV_step = step, \ - .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ + .linear_min_sel = min_sel, \ + .n_voltages = voltages, \ .ramp_delay = S2MPS11_RAMP_DELAY, \ .vsel_reg = S2MPS11_REG_B6CTRL2 + (num - 6) * 2, \ .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ @@ -371,11 +374,15 @@ static const struct regulator_desc s2mps11_regulators[] = { regulator_desc_s2mps11_buck1_4(3), regulator_desc_s2mps11_buck1_4(4), regulator_desc_s2mps11_buck5, - regulator_desc_s2mps11_buck67810(6, MIN_600_MV, STEP_6_25_MV), - regulator_desc_s2mps11_buck67810(7, MIN_750_MV, STEP_12_5_MV), - regulator_desc_s2mps11_buck67810(8, MIN_750_MV, STEP_12_5_MV), + regulator_desc_s2mps11_buck67810(6, MIN_650_MV, STEP_6_25_MV, 8, + S2MPS11_BUCK12346_N_VOLTAGES), + regulator_desc_s2mps11_buck67810(7, MIN_750_MV, STEP_12_5_MV, 0, + S2MPS11_BUCK7810_N_VOLTAGES), + regulator_desc_s2mps11_buck67810(8, MIN_750_MV, STEP_12_5_MV, 0, + S2MPS11_BUCK7810_N_VOLTAGES), regulator_desc_s2mps11_buck9, - regulator_desc_s2mps11_buck67810(10, MIN_750_MV, STEP_12_5_MV), + regulator_desc_s2mps11_buck67810(10, MIN_750_MV, STEP_12_5_MV, 0, + S2MPS11_BUCK7810_N_VOLTAGES), }; static const struct regulator_ops s2mps14_reg_ops; diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index 3ca17eb89aa2..f1631a39acfc 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -20,6 +20,7 @@ #define MIN_850_MV 850000 #define MIN_800_MV 800000 #define MIN_750_MV 750000 +#define MIN_650_MV 650000 #define MIN_600_MV 600000 #define MIN_500_MV 500000 diff --git a/include/linux/mfd/samsung/s2mps11.h b/include/linux/mfd/samsung/s2mps11.h index 6e7668a389a1..fc67c9e75bba 100644 --- a/include/linux/mfd/samsung/s2mps11.h +++ b/include/linux/mfd/samsung/s2mps11.h @@ -170,7 +170,9 @@ enum s2mps11_regulators { #define S2MPS11_ENABLE_MASK (0x03 << S2MPS11_ENABLE_SHIFT) #define S2MPS11_ENABLE_SHIFT 0x06 #define S2MPS11_LDO_N_VOLTAGES (S2MPS11_LDO_VSEL_MASK + 1) -#define S2MPS11_BUCK_N_VOLTAGES (S2MPS11_BUCK_VSEL_MASK + 1) +#define S2MPS11_BUCK12346_N_VOLTAGES 153 +#define S2MPS11_BUCK5_N_VOLTAGES 216 +#define S2MPS11_BUCK7810_N_VOLTAGES 225 #define S2MPS11_BUCK9_N_VOLTAGES (S2MPS11_BUCK9_VSEL_MASK + 1) #define S2MPS11_RAMP_DELAY 25000 /* uV/us */