From 1e2cc8c5e0745b545d4974788dc606d678b6e564 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 26 Jun 2019 21:26:31 +0800 Subject: [PATCH 01/52] regulator: lm363x: Fix off-by-one n_voltages for lm3632 ldo_vpos/ldo_vneg According to the datasheet https://www.ti.com/lit/ds/symlink/lm3632a.pdf Table 20. VPOS Bias Register Field Descriptions VPOS[5:0] Sets the Positive Display Bias (LDO) Voltage (50 mV per step) 000000: 4 V 000001: 4.05 V 000010: 4.1 V .................... 011101: 5.45 V 011110: 5.5 V (Default) 011111: 5.55 V .................... 100111: 5.95 V 101000: 6 V Note: Codes 101001 to 111111 map to 6 V The LM3632_LDO_VSEL_MAX should be 0b101000 (0x28), so the maximum voltage can match the datasheet. Fixes: 3a8d1a73a037 ("regulator: add LM363X driver") Signed-off-by: Axel Lin Link: https://lore.kernel.org/r/20190626132632.32629-1-axel.lin@ingics.com Signed-off-by: Mark Brown --- drivers/regulator/lm363x-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/lm363x-regulator.c b/drivers/regulator/lm363x-regulator.c index 5647e2f97ff8..e4a27d63bf90 100644 --- a/drivers/regulator/lm363x-regulator.c +++ b/drivers/regulator/lm363x-regulator.c @@ -30,7 +30,7 @@ /* LM3632 */ #define LM3632_BOOST_VSEL_MAX 0x26 -#define LM3632_LDO_VSEL_MAX 0x29 +#define LM3632_LDO_VSEL_MAX 0x28 #define LM3632_VBOOST_MIN 4500000 #define LM3632_VLDO_MIN 4000000 From 962f170d9344e5d9edb3903971c591f42d55e226 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 26 Jun 2019 21:26:32 +0800 Subject: [PATCH 02/52] regulator: lm363x: Fix n_voltages setting for lm36274 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the datasheet http://www.ti.com/lit/ds/symlink/lm36274.pdf: Table 23. VPOS Bias Register Field Descriptions VPOS[5:0]: VPOS voltage (50-mV steps): VPOS = 4 V + (Code × 50 mV), 6.5 V max 000000 = 4 V 000001 = 4.05 V : 011110 = 5.5 V (Default) : 110010 = 6.5 V 110011 to 111111 map to 6.5 V So the LM36274_LDO_VSEL_MAX should be 0b110010 (0x32). The valid selectors are 0 ... LM36274_LDO_VSEL_MAX, n_voltages should be LM36274_LDO_VSEL_MAX + 1. Similarly, the n_voltages should be LM36274_BOOST_VSEL_MAX + 1 for LM36274_BOOST. Fixes: bff5e8071533 ("regulator: lm363x: Add support for LM36274") Signed-off-by: Axel Lin Link: https://lore.kernel.org/r/20190626132632.32629-2-axel.lin@ingics.com Signed-off-by: Mark Brown --- drivers/regulator/lm363x-regulator.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/lm363x-regulator.c b/drivers/regulator/lm363x-regulator.c index e4a27d63bf90..4b9f618b07e9 100644 --- a/drivers/regulator/lm363x-regulator.c +++ b/drivers/regulator/lm363x-regulator.c @@ -36,7 +36,7 @@ /* LM36274 */ #define LM36274_BOOST_VSEL_MAX 0x3f -#define LM36274_LDO_VSEL_MAX 0x34 +#define LM36274_LDO_VSEL_MAX 0x32 #define LM36274_VOLTAGE_MIN 4000000 /* Common */ @@ -226,7 +226,7 @@ static const struct regulator_desc lm363x_regulator_desc[] = { .of_match = "vboost", .id = LM36274_BOOST, .ops = &lm363x_boost_voltage_table_ops, - .n_voltages = LM36274_BOOST_VSEL_MAX, + .n_voltages = LM36274_BOOST_VSEL_MAX + 1, .min_uV = LM36274_VOLTAGE_MIN, .uV_step = LM363X_STEP_50mV, .type = REGULATOR_VOLTAGE, @@ -239,7 +239,7 @@ static const struct regulator_desc lm363x_regulator_desc[] = { .of_match = "vpos", .id = LM36274_LDO_POS, .ops = &lm363x_regulator_voltage_table_ops, - .n_voltages = LM36274_LDO_VSEL_MAX, + .n_voltages = LM36274_LDO_VSEL_MAX + 1, .min_uV = LM36274_VOLTAGE_MIN, .uV_step = LM363X_STEP_50mV, .type = REGULATOR_VOLTAGE, @@ -254,7 +254,7 @@ static const struct regulator_desc lm363x_regulator_desc[] = { .of_match = "vneg", .id = LM36274_LDO_NEG, .ops = &lm363x_regulator_voltage_table_ops, - .n_voltages = LM36274_LDO_VSEL_MAX, + .n_voltages = LM36274_LDO_VSEL_MAX + 1, .min_uV = LM36274_VOLTAGE_MIN, .uV_step = LM363X_STEP_50mV, .type = REGULATOR_VOLTAGE, From d850c6f5fad60b6edec08300977303aae855ffff Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 11 Jul 2019 20:21:38 +0800 Subject: [PATCH 03/52] regulator: rk808: Return REGULATOR_MODE_INVALID for invalid mode -EINVAL is not a valid return value for .of_map_mode, return REGULATOR_MODE_INVALID instead. Signed-off-by: Axel Lin Link: https://lore.kernel.org/r/20190711122138.5221-1-axel.lin@ingics.com Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index e7af0c53d449..61bd5ef0806c 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -606,7 +606,7 @@ static unsigned int rk8xx_regulator_of_map_mode(unsigned int mode) case 2: return REGULATOR_MODE_NORMAL; default: - return -EINVAL; + return REGULATOR_MODE_INVALID; } } From 2d09a79bf637f91d1bbfcfd4520e3639dd15897c Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Mon, 22 Jul 2019 21:14:18 -0400 Subject: [PATCH 04/52] regulator: act8865: Add support for act8600 charger This provides a way to monitor battery charge status via the power supply subsystem. Signed-off-by: Maarten ter Huurne Signed-off-by: Paul Cercueil Link: https://lore.kernel.org/r/20190723011418.29143-1-paul@crapouillou.net Signed-off-by: Mark Brown --- drivers/regulator/act8865-regulator.c | 84 +++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index cf72d7c6b8c9..e63285de485d 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -118,6 +119,11 @@ #define ACT8600_LDO10_ENA 0x40 /* ON - [6] */ #define ACT8600_SUDCDC_VSEL_MASK 0xFF /* SUDCDC VSET - [7:0] */ +#define ACT8600_APCH_CHG_ACIN BIT(7) +#define ACT8600_APCH_CHG_USB BIT(6) +#define ACT8600_APCH_CSTATE0 BIT(5) +#define ACT8600_APCH_CSTATE1 BIT(4) + /* * ACT8865 voltage number */ @@ -372,6 +378,75 @@ static void act8865_power_off(void) while (1); } +static int act8600_charger_get_status(struct regmap *map) +{ + unsigned int val; + int ret; + u8 state0, state1; + + ret = regmap_read(map, ACT8600_APCH_STAT, &val); + if (ret < 0) + return ret; + + state0 = val & ACT8600_APCH_CSTATE0; + state1 = val & ACT8600_APCH_CSTATE1; + + if (state0 && !state1) + return POWER_SUPPLY_STATUS_CHARGING; + if (!state0 && state1) + return POWER_SUPPLY_STATUS_NOT_CHARGING; + if (!state0 && !state1) + return POWER_SUPPLY_STATUS_DISCHARGING; + + return POWER_SUPPLY_STATUS_UNKNOWN; +} + +static int act8600_charger_get_property(struct power_supply *psy, + enum power_supply_property psp, union power_supply_propval *val) +{ + struct regmap *map = power_supply_get_drvdata(psy); + int ret; + + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + ret = act8600_charger_get_status(map); + if (ret < 0) + return ret; + + val->intval = ret; + break; + default: + return -EINVAL; + } + + return 0; +} + +static enum power_supply_property act8600_charger_properties[] = { + POWER_SUPPLY_PROP_STATUS, +}; + +static const struct power_supply_desc act8600_charger_desc = { + .name = "act8600-charger", + .type = POWER_SUPPLY_TYPE_BATTERY, + .properties = act8600_charger_properties, + .num_properties = ARRAY_SIZE(act8600_charger_properties), + .get_property = act8600_charger_get_property, +}; + +static int act8600_charger_probe(struct device *dev, struct regmap *regmap) +{ + struct power_supply *charger; + struct power_supply_config cfg = { + .drv_data = regmap, + .of_node = dev->of_node, + }; + + charger = devm_power_supply_register(dev, &act8600_charger_desc, &cfg); + + return IS_ERR(charger) ? PTR_ERR(charger) : 0; +} + static int act8865_pmic_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { @@ -483,6 +558,15 @@ static int act8865_pmic_probe(struct i2c_client *client, } } + if (type == ACT8600) { + ret = act8600_charger_probe(dev, act8865->regmap); + if (ret < 0) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to probe charger"); + return ret; + } + } + i2c_set_clientdata(client, act8865); return 0; From 03b77f0b8587a9a0f9d2f1503da3d120aa6fe730 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 23 Jul 2019 09:41:02 +0800 Subject: [PATCH 05/52] regulator: stm32-booster: Remove .min_uV and .list_voltage for fixed regulator Setting .n_voltages = 1 and .fixed_uV is enough for fixed regulator, remove the redundant .min_uV and .list_voltage settings. Signed-off-by: Axel Lin Acked-by: Fabrice Gasnier Link: https://lore.kernel.org/r/20190723014102.25103-1-axel.lin@ingics.com Signed-off-by: Mark Brown --- drivers/regulator/stm32-booster.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/regulator/stm32-booster.c b/drivers/regulator/stm32-booster.c index 2a897666c650..03f162ffd144 100644 --- a/drivers/regulator/stm32-booster.c +++ b/drivers/regulator/stm32-booster.c @@ -20,7 +20,6 @@ #define STM32MP1_SYSCFG_EN_BOOSTER_MASK BIT(8) static const struct regulator_ops stm32h7_booster_ops = { - .list_voltage = regulator_list_voltage_linear, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -31,7 +30,6 @@ static const struct regulator_desc stm32h7_booster_desc = { .supply_name = "vdda", .n_voltages = 1, .type = REGULATOR_VOLTAGE, - .min_uV = 3300000, .fixed_uV = 3300000, .ramp_delay = 66000, /* up to 50us to stabilize */ .ops = &stm32h7_booster_ops, @@ -53,7 +51,6 @@ static int stm32mp1_booster_disable(struct regulator_dev *rdev) } static const struct regulator_ops stm32mp1_booster_ops = { - .list_voltage = regulator_list_voltage_linear, .enable = stm32mp1_booster_enable, .disable = stm32mp1_booster_disable, .is_enabled = regulator_is_enabled_regmap, @@ -64,7 +61,6 @@ static const struct regulator_desc stm32mp1_booster_desc = { .supply_name = "vdda", .n_voltages = 1, .type = REGULATOR_VOLTAGE, - .min_uV = 3300000, .fixed_uV = 3300000, .ramp_delay = 66000, .ops = &stm32mp1_booster_ops, From cd81a91d04b8b869bbbf62ae80bd5e8c0e7a2b93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= Date: Tue, 23 Jul 2019 18:32:06 +0200 Subject: [PATCH 06/52] regulator: act8865: rename fixed LDO ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename act8865_ldo_ops to act8865_fixed_ldo_ops to make room for variable-output LDO ops change. Signed-off-by: Michał Mirosław Link: https://lore.kernel.org/r/12b1fe419e93dfe663990009bf1b2fbf630e9934.1563898936.git.mirq-linux@rere.qmqm.pl Signed-off-by: Mark Brown --- drivers/regulator/act8865-regulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index e63285de485d..672ed56448ca 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -233,7 +233,7 @@ static const struct regulator_ops act8865_ops = { .is_enabled = regulator_is_enabled_regmap, }; -static const struct regulator_ops act8865_ldo_ops = { +static const struct regulator_ops act8865_fixed_ldo_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -287,7 +287,7 @@ static const struct regulator_desc act8600_regulators[] = { .of_match = of_match_ptr("LDO_REG9"), .regulators_node = of_match_ptr("regulators"), .id = ACT8600_ID_LDO9, - .ops = &act8865_ldo_ops, + .ops = &act8865_fixed_ldo_ops, .type = REGULATOR_VOLTAGE, .n_voltages = 1, .fixed_uV = 3300000, @@ -300,7 +300,7 @@ static const struct regulator_desc act8600_regulators[] = { .of_match = of_match_ptr("LDO_REG10"), .regulators_node = of_match_ptr("regulators"), .id = ACT8600_ID_LDO10, - .ops = &act8865_ldo_ops, + .ops = &act8865_fixed_ldo_ops, .type = REGULATOR_VOLTAGE, .n_voltages = 1, .fixed_uV = 1200000, From a5f888c53db575e3b04e7b4597699da67b9cd2eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= Date: Tue, 23 Jul 2019 18:32:07 +0200 Subject: [PATCH 07/52] regulator: act8865: support regulator-pull-down property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AC8865 has internal 1.5k pull-down resistor that can be enabled when LDO is shut down. Signed-off-by: Michał Mirosław Link: https://lore.kernel.org/r/d7338f0dfcac63eb958a6b5e42e2d540b3d3f54a.1563898936.git.mirq-linux@rere.qmqm.pl Signed-off-by: Mark Brown --- drivers/regulator/act8865-regulator.c | 41 ++++++++++++++++++++------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index 672ed56448ca..b515e0785d67 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -113,6 +113,8 @@ * Field Definitions. */ #define ACT8865_ENA 0x80 /* ON - [7] */ +#define ACT8865_DIS 0x40 /* DIS - [6] */ + #define ACT8865_VSEL_MASK 0x3F /* VSET - [5:0] */ @@ -233,13 +235,24 @@ static const struct regulator_ops act8865_ops = { .is_enabled = regulator_is_enabled_regmap, }; +static const struct regulator_ops act8865_ldo_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_pull_down = regulator_set_pull_down_regmap, +}; + static const struct regulator_ops act8865_fixed_ldo_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, }; -#define ACT88xx_REG(_name, _family, _id, _vsel_reg, _supply) \ +#define ACT88xx_REG_(_name, _family, _id, _vsel_reg, _supply, _ops) \ [_family##_ID_##_id] = { \ .name = _name, \ .of_match = of_match_ptr(_name), \ @@ -247,7 +260,7 @@ static const struct regulator_ops act8865_fixed_ldo_ops = { .supply_name = _supply, \ .id = _family##_ID_##_id, \ .type = REGULATOR_VOLTAGE, \ - .ops = &act8865_ops, \ + .ops = _ops, \ .n_voltages = ACT8865_VOLTAGE_NUM, \ .linear_ranges = act8865_voltage_ranges, \ .n_linear_ranges = ARRAY_SIZE(act8865_voltage_ranges), \ @@ -255,9 +268,17 @@ static const struct regulator_ops act8865_fixed_ldo_ops = { .vsel_mask = ACT8865_VSEL_MASK, \ .enable_reg = _family##_##_id##_CTRL, \ .enable_mask = ACT8865_ENA, \ + .pull_down_reg = _family##_##_id##_CTRL, \ + .pull_down_mask = ACT8865_DIS, \ .owner = THIS_MODULE, \ } +#define ACT88xx_REG(_name, _family, _id, _vsel_reg, _supply) \ + ACT88xx_REG_(_name, _family, _id, _vsel_reg, _supply, &act8865_ops) + +#define ACT88xx_LDO(_name, _family, _id, _vsel_reg, _supply) \ + ACT88xx_REG_(_name, _family, _id, _vsel_reg, _supply, &act8865_ldo_ops) + static const struct regulator_desc act8600_regulators[] = { ACT88xx_REG("DCDC1", ACT8600, DCDC1, VSET, "vp1"), ACT88xx_REG("DCDC2", ACT8600, DCDC2, VSET, "vp2"), @@ -329,20 +350,20 @@ static const struct regulator_desc act8865_regulators[] = { ACT88xx_REG("DCDC_REG1", ACT8865, DCDC1, VSET1, "vp1"), ACT88xx_REG("DCDC_REG2", ACT8865, DCDC2, VSET1, "vp2"), ACT88xx_REG("DCDC_REG3", ACT8865, DCDC3, VSET1, "vp3"), - ACT88xx_REG("LDO_REG1", ACT8865, LDO1, VSET, "inl45"), - ACT88xx_REG("LDO_REG2", ACT8865, LDO2, VSET, "inl45"), - ACT88xx_REG("LDO_REG3", ACT8865, LDO3, VSET, "inl67"), - ACT88xx_REG("LDO_REG4", ACT8865, LDO4, VSET, "inl67"), + ACT88xx_LDO("LDO_REG1", ACT8865, LDO1, VSET, "inl45"), + ACT88xx_LDO("LDO_REG2", ACT8865, LDO2, VSET, "inl45"), + ACT88xx_LDO("LDO_REG3", ACT8865, LDO3, VSET, "inl67"), + ACT88xx_LDO("LDO_REG4", ACT8865, LDO4, VSET, "inl67"), }; static const struct regulator_desc act8865_alt_regulators[] = { ACT88xx_REG("DCDC_REG1", ACT8865, DCDC1, VSET2, "vp1"), ACT88xx_REG("DCDC_REG2", ACT8865, DCDC2, VSET2, "vp2"), ACT88xx_REG("DCDC_REG3", ACT8865, DCDC3, VSET2, "vp3"), - ACT88xx_REG("LDO_REG1", ACT8865, LDO1, VSET, "inl45"), - ACT88xx_REG("LDO_REG2", ACT8865, LDO2, VSET, "inl45"), - ACT88xx_REG("LDO_REG3", ACT8865, LDO3, VSET, "inl67"), - ACT88xx_REG("LDO_REG4", ACT8865, LDO4, VSET, "inl67"), + ACT88xx_LDO("LDO_REG1", ACT8865, LDO1, VSET, "inl45"), + ACT88xx_LDO("LDO_REG2", ACT8865, LDO2, VSET, "inl45"), + ACT88xx_LDO("LDO_REG3", ACT8865, LDO3, VSET, "inl67"), + ACT88xx_LDO("LDO_REG4", ACT8865, LDO4, VSET, "inl67"), }; #ifdef CONFIG_OF From 1889c6e6ac6e15b3631d7e320f740219aa46504a Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Wed, 24 Jul 2019 17:22:36 +0800 Subject: [PATCH 08/52] regulator: act8865: fix ptr_ret.cocci warnings drivers/regulator/act8865-regulator.c:447:8-14: WARNING: PTR_ERR_OR_ZERO can be used Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR Generated by: scripts/coccinelle/api/ptr_ret.cocci Fixes: 2d09a79bf637 ("regulator: act8865: Add support for act8600 charger") CC: Maarten ter Huurne Signed-off-by: kbuild test robot Link: https://lore.kernel.org/r/20190724092236.witxtfmubun25l2t@1905cc33b6dd Signed-off-by: Mark Brown --- drivers/regulator/act8865-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index b515e0785d67..6a90d3c7a452 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -465,7 +465,7 @@ static int act8600_charger_probe(struct device *dev, struct regmap *regmap) charger = devm_power_supply_register(dev, &act8600_charger_desc, &cfg); - return IS_ERR(charger) ? PTR_ERR(charger) : 0; + return PTR_ERR_OR_ZERO(charger); } static int act8865_pmic_probe(struct i2c_client *client, From 47241933b43dec5b10d067e6e094f4d31a1cf3e7 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:37 -0700 Subject: [PATCH 09/52] regulator: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: Liam Girdwood Cc: Mark Brown Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20190730181557.90391-38-swboyd@chromium.org Signed-off-by: Mark Brown --- drivers/regulator/da9062-regulator.c | 4 +--- drivers/regulator/da9063-regulator.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c index 2ffc64622451..56f3f72d7707 100644 --- a/drivers/regulator/da9062-regulator.c +++ b/drivers/regulator/da9062-regulator.c @@ -1032,10 +1032,8 @@ static int da9062_regulator_probe(struct platform_device *pdev) /* LDOs overcurrent event support */ irq = platform_get_irq_byname(pdev, "LDO_LIM"); - if (irq < 0) { - dev_err(&pdev->dev, "Failed to get IRQ.\n"); + if (irq < 0) return irq; - } regulators->irq_ldo_lim = irq; ret = devm_request_threaded_irq(&pdev->dev, irq, diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index 02f816318fba..28b1b20f45bd 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -863,10 +863,8 @@ static int da9063_regulator_probe(struct platform_device *pdev) /* LDOs overcurrent event support */ irq = platform_get_irq_byname(pdev, "LDO_LIM"); - if (irq < 0) { - dev_err(&pdev->dev, "Failed to get IRQ.\n"); + if (irq < 0) return irq; - } ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, da9063_ldo_lim_event, From db2a17320a25a63b46ddb081a306af9ded1b906e Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Sun, 4 Aug 2019 21:50:23 +0530 Subject: [PATCH 10/52] regulator: core: Add of_node_put() before return Each iteration of for_each_child_of_node puts the previous node, but in the case of a return from the middle of the loop, there is no put, thus causing a memory leak. Hence add an of_node_put before the return in two places. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190804162023.5673-1-nishkadg.linux@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e0c0cf462004..7a5d52948703 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -380,9 +380,12 @@ static struct device_node *of_get_child_regulator(struct device_node *parent, if (!regnode) { regnode = of_get_child_regulator(child, prop_name); - if (regnode) + if (regnode) { + of_node_put(child); return regnode; + } } else { + of_node_put(child); return regnode; } } From d566aae1c80d9be2276057b3236c68bdcc5b3254 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 8 Aug 2019 15:03:42 +0530 Subject: [PATCH 11/52] regulator: dt-bindings: Add PM8150x compatibles Add PM8150, PM8150L and PM8009 compatibles for these PMICs found in some Qualcomm platforms. Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20190808093343.5600-1-vkoul@kernel.org Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/qcom,rpmh-regulator.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt index 14d2eee96b3d..1a9cab50503a 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt @@ -25,6 +25,9 @@ Supported regulator node names: PM8998: smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2 PMI8998: bob PM8005: smps1 - smps4 + PM8150: smps1 - smps10, ldo1 - ldo18 + PM8150L: smps1 - smps8, ldo1 - ldo11, bob, flash, rgb + PM8009: smps1 - smps2, ld01 - ldo7 ======================== First Level Nodes - PMIC @@ -35,7 +38,10 @@ First Level Nodes - PMIC Value type: Definition: Must be one of: "qcom,pm8998-rpmh-regulators", "qcom,pmi8998-rpmh-regulators" or - "qcom,pm8005-rpmh-regulators". + "qcom,pm8005-rpmh-regulators" or + "qcom,pm8150-rpmh-regulators" or + "qcom,pm8150l-rpmh-regulators" or + "qcom,pm8009-rpmh-regulators". - qcom,pmic-id Usage: required From 06369bcc15a1620930a17fb35e26477504cd2255 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 8 Aug 2019 15:03:43 +0530 Subject: [PATCH 12/52] regulator: qcom-rpmh: Add support for SM8150 Add support from RPMH regulators found in SM8150 platform Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20190808093343.5600-2-vkoul@kernel.org Signed-off-by: Mark Brown --- drivers/regulator/qcom-rpmh-regulator.c | 147 ++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index b2c2d01d1637..693ffec62f3e 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -637,6 +637,72 @@ static const struct rpmh_vreg_hw_data pmic4_lvs = { /* LVS hardware does not support voltage or mode configuration. */ }; +static const struct rpmh_vreg_hw_data pmic5_pldo = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_drms_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(1504000, 0, 255, 8000), + .n_voltages = 256, + .hpm_min_load_uA = 10000, + .pmic_mode_map = pmic_mode_map_pmic4_ldo, + .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, +}; + +static const struct rpmh_vreg_hw_data pmic5_pldo_lv = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_drms_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(1504000, 0, 62, 8000), + .n_voltages = 63, + .hpm_min_load_uA = 10000, + .pmic_mode_map = pmic_mode_map_pmic4_ldo, + .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, +}; + +static const struct rpmh_vreg_hw_data pmic5_nldo = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_drms_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 123, 8000), + .n_voltages = 124, + .hpm_min_load_uA = 30000, + .pmic_mode_map = pmic_mode_map_pmic4_ldo, + .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, +}; + +static const struct rpmh_vreg_hw_data pmic5_hfsmps510 = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000), + .n_voltages = 216, + .pmic_mode_map = pmic_mode_map_pmic4_smps, + .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, +}; + +static const struct rpmh_vreg_hw_data pmic5_ftsmps510 = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 263, 4000), + .n_voltages = 264, + .pmic_mode_map = pmic_mode_map_pmic4_smps, + .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, +}; + +static const struct rpmh_vreg_hw_data pmic5_hfsmps515 = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(2800000, 0, 4, 1600), + .n_voltages = 5, + .pmic_mode_map = pmic_mode_map_pmic4_smps, + .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, +}; + +static const struct rpmh_vreg_hw_data pmic5_bob = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_bypass_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 135, 32000), + .n_voltages = 135, + .pmic_mode_map = pmic_mode_map_pmic4_bob, + .of_map_mode = rpmh_regulator_pmic4_bob_of_map_mode, +}; + #define RPMH_VREG(_name, _resource_name, _hw_data, _supply_name) \ { \ .name = _name, \ @@ -705,6 +771,75 @@ static const struct rpmh_vreg_init_data pm8005_vreg_data[] = { {}, }; +static const struct rpmh_vreg_init_data pm8150_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps510, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps510, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps510, "vdd-s3"), + RPMH_VREG("smps4", "smp%s4", &pmic5_hfsmps510, "vdd-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic5_hfsmps510, "vdd-s5"), + RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps510, "vdd-s6"), + RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps510, "vdd-s7"), + RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps510, "vdd-s8"), + RPMH_VREG("smps9", "smp%s9", &pmic5_ftsmps510, "vdd-s9"), + RPMH_VREG("smps10", "smp%s10", &pmic5_ftsmps510, "vdd-s10"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1-l8-l11"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_pldo, "vdd-l2-l10"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3-l4-l5-l18"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l3-l4-l5-l18"), + RPMH_VREG("ldo5", "ldo%s5", &pmic5_nldo, "vdd-l3-l4-l5-l18"), + RPMH_VREG("ldo6", "ldo%s6", &pmic5_nldo, "vdd-l6-l9"), + RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l7-l12-l14-l15"), + RPMH_VREG("ldo8", "ldo%s8", &pmic5_nldo, "vdd-l1-l8-l11"), + RPMH_VREG("ldo9", "ldo%s9", &pmic5_nldo, "vdd-l6-l9"), + RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo, "vdd-l2-l10"), + RPMH_VREG("ldo11", "ldo%s11", &pmic5_nldo, "vdd-l1-l8-l11"), + RPMH_VREG("ldo12", "ldo%s12", &pmic5_pldo_lv, "vdd-l7-l12-l14-l15"), + RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo, "vdd-l13-l6-l17"), + RPMH_VREG("ldo14", "ldo%s14", &pmic5_pldo_lv, "vdd-l7-l12-l14-l15"), + RPMH_VREG("ldo15", "ldo%s15", &pmic5_pldo_lv, "vdd-l7-l12-l14-l15"), + RPMH_VREG("ldo16", "ldo%s16", &pmic5_pldo, "vdd-l13-l6-l17"), + RPMH_VREG("ldo17", "ldo%s17", &pmic5_pldo, "vdd-l13-l6-l17"), + RPMH_VREG("ldo18", "ldo%s18", &pmic5_nldo, "vdd-l3-l4-l5-l18"), + {}, +}; + +static const struct rpmh_vreg_init_data pm8150l_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps510, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps510, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps510, "vdd-s3"), + RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps510, "vdd-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps510, "vdd-s5"), + RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps510, "vdd-s6"), + RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps510, "vdd-s7"), + RPMH_VREG("smps8", "smp%s8", &pmic5_hfsmps510, "vdd-s8"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_pldo_lv, "vdd-l1-l8"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2-l3"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l2-l3"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_pldo, "vdd-l4-l5-l6"), + RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l4-l5-l6"), + RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l4-l5-l6"), + RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l7-l11"), + RPMH_VREG("ldo8", "ldo%s8", &pmic5_pldo_lv, "vdd-l1-l8-l11"), + RPMH_VREG("ldo9", "ldo%s9", &pmic5_pldo, "vdd-l9-l10"), + RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo, "vdd-l9-l10"), + RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo, "vdd-l7-l11"), + RPMH_VREG("bob", "bob%s1", &pmic5_bob, "vdd-bob"), + {}, +}; + +static const struct rpmh_vreg_init_data pm8009_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_hfsmps510, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_hfsmps515, "vdd-s2"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l4"), + RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l5-l6"), + RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l5-l6"), + RPMH_VREG("ldo7", "ldo%s6", &pmic5_pldo_lv, "vdd-l7"), + {}, +}; + static int rpmh_regulator_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -755,6 +890,18 @@ static const struct of_device_id rpmh_regulator_match_table[] = { .compatible = "qcom,pm8005-rpmh-regulators", .data = pm8005_vreg_data, }, + { + .compatible = "qcom,pm8150-rpmh-regulators", + .data = pm8150_vreg_data, + }, + { + .compatible = "qcom,pm8150l-rpmh-regulators", + .data = pm8150l_vreg_data, + }, + { + .compatible = "qcom,pm8009-rpmh-regulators", + .data = pm8009_vreg_data, + }, {} }; MODULE_DEVICE_TABLE(of, rpmh_regulator_match_table); From 5375f1efd70b5adbbbaded22889d50c07f6f89a4 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 7 Aug 2019 21:38:22 +0800 Subject: [PATCH 13/52] regulator: act8865: Fix build error without CONFIG_POWER_SUPPLY Building without CONFIG_POWER_SUPPLY will fail: drivers/regulator/act8865-regulator.o: In function `act8865_pmic_probe': act8865-regulator.c:(.text+0x357): undefined reference to `devm_power_supply_register' drivers/regulator/act8865-regulator.o: In function `act8600_charger_get_property': act8865-regulator.c:(.text+0x3f1): undefined reference to `power_supply_get_drvdata' Add POWER_SUPPLY dependency to Kconfig. Reported-by: Hulk Robot Fixes: 2d09a79bf637 ("regulator: act8865: Add support for act8600 charger") Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190807133822.67124-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index b57093d7c01f..37e64884b9ee 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -83,6 +83,7 @@ config REGULATOR_88PM8607 config REGULATOR_ACT8865 tristate "Active-semi act8865 voltage regulator" depends on I2C + depends on POWER_SUPPLY select REGMAP_I2C help This driver controls a active-semi act8865 voltage output From c6e20fa49818381dfa7288fad4c33b84408aab54 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 9 Aug 2019 13:06:13 +0530 Subject: [PATCH 14/52] regulator: dt-bindings: Sort the compatibles and nodes It helps to keep sorted order for compatibles and nodes, so sort them Suggested-by: Bjorn Andersson Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20190809073616.1235-1-vkoul@kernel.org Signed-off-by: Mark Brown --- .../regulator/qcom,rpmh-regulator.txt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt index 1a9cab50503a..bab9f71140b8 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt @@ -22,12 +22,12 @@ RPMh resource. The names used for regulator nodes must match those supported by a given PMIC. Supported regulator node names: - PM8998: smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2 - PMI8998: bob PM8005: smps1 - smps4 + PM8009: smps1 - smps2, ldo1 - ldo7 PM8150: smps1 - smps10, ldo1 - ldo18 PM8150L: smps1 - smps8, ldo1 - ldo11, bob, flash, rgb - PM8009: smps1 - smps2, ld01 - ldo7 + PM8998: smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2 + PMI8998: bob ======================== First Level Nodes - PMIC @@ -36,12 +36,13 @@ First Level Nodes - PMIC - compatible Usage: required Value type: - Definition: Must be one of: "qcom,pm8998-rpmh-regulators", - "qcom,pmi8998-rpmh-regulators" or - "qcom,pm8005-rpmh-regulators" or - "qcom,pm8150-rpmh-regulators" or - "qcom,pm8150l-rpmh-regulators" or - "qcom,pm8009-rpmh-regulators". + Definition: Must be one of below: + "qcom,pm8005-rpmh-regulators" + "qcom,pm8009-rpmh-regulators" + "qcom,pm8150-rpmh-regulators" + "qcom,pm8150l-rpmh-regulators" + "qcom,pm8998-rpmh-regulators" + "qcom,pmi8998-rpmh-regulators" - qcom,pmic-id Usage: required From 7172fb7f3abea4787ca01dda7297241c4b0f0af5 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 9 Aug 2019 13:06:14 +0530 Subject: [PATCH 15/52] regulator: qcom-rpmh: Sort the compatibles It helps to keep sorted order for compatibles, so sort them Suggested-by: Bjorn Andersson Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20190809073616.1235-2-vkoul@kernel.org Signed-off-by: Mark Brown --- drivers/regulator/qcom-rpmh-regulator.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index 693ffec62f3e..0ef2716da3bd 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -878,18 +878,14 @@ static int rpmh_regulator_probe(struct platform_device *pdev) } static const struct of_device_id rpmh_regulator_match_table[] = { - { - .compatible = "qcom,pm8998-rpmh-regulators", - .data = pm8998_vreg_data, - }, - { - .compatible = "qcom,pmi8998-rpmh-regulators", - .data = pmi8998_vreg_data, - }, { .compatible = "qcom,pm8005-rpmh-regulators", .data = pm8005_vreg_data, }, + { + .compatible = "qcom,pm8009-rpmh-regulators", + .data = pm8009_vreg_data, + }, { .compatible = "qcom,pm8150-rpmh-regulators", .data = pm8150_vreg_data, @@ -899,8 +895,12 @@ static const struct of_device_id rpmh_regulator_match_table[] = { .data = pm8150l_vreg_data, }, { - .compatible = "qcom,pm8009-rpmh-regulators", - .data = pm8009_vreg_data, + .compatible = "qcom,pm8998-rpmh-regulators", + .data = pm8998_vreg_data, + }, + { + .compatible = "qcom,pmi8998-rpmh-regulators", + .data = pmi8998_vreg_data, }, {} }; From 553c452d6093d66e7617ed6c68cc93547d07075f Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 9 Aug 2019 13:06:15 +0530 Subject: [PATCH 16/52] regulator: qcom-rpmh: Fix pmic5_bob voltage count pmic5_bob voltages count is 136 [0,135] so update it Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20190809073616.1235-3-vkoul@kernel.org 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 0ef2716da3bd..391ed844a251 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -698,7 +698,7 @@ static const struct rpmh_vreg_hw_data pmic5_bob = { .regulator_type = VRM, .ops = &rpmh_regulator_vrm_bypass_ops, .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 135, 32000), - .n_voltages = 135, + .n_voltages = 136, .pmic_mode_map = pmic_mode_map_pmic4_bob, .of_map_mode = rpmh_regulator_pmic4_bob_of_map_mode, }; From 610f29e5cc0e8d5864dd049b0b3576d9437ae7b4 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 9 Aug 2019 13:06:16 +0530 Subject: [PATCH 17/52] regulator: qcom-rpmh: Update PMIC modes for PMIC5 Add the PMIC5 modes and use them pmic5 ldo and smps Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20190809073616.1235-4-vkoul@kernel.org Signed-off-by: Mark Brown --- drivers/regulator/qcom-rpmh-regulator.c | 52 +++++++++++++++++++++---- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index 391ed844a251..db6c085da65e 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -50,6 +50,20 @@ enum rpmh_regulator_type { #define PMIC4_BOB_MODE_AUTO 2 #define PMIC4_BOB_MODE_PWM 3 +#define PMIC5_LDO_MODE_RETENTION 3 +#define PMIC5_LDO_MODE_LPM 4 +#define PMIC5_LDO_MODE_HPM 7 + +#define PMIC5_SMPS_MODE_RETENTION 3 +#define PMIC5_SMPS_MODE_PFM 4 +#define PMIC5_SMPS_MODE_AUTO 6 +#define PMIC5_SMPS_MODE_PWM 7 + +#define PMIC5_BOB_MODE_PASS 2 +#define PMIC5_BOB_MODE_PFM 4 +#define PMIC5_BOB_MODE_AUTO 6 +#define PMIC5_BOB_MODE_PWM 7 + /** * struct rpmh_vreg_hw_data - RPMh regulator hardware configurations * @regulator_type: RPMh accelerator type used to manage this @@ -488,6 +502,14 @@ static const int pmic_mode_map_pmic4_ldo[REGULATOR_MODE_STANDBY + 1] = { [REGULATOR_MODE_FAST] = -EINVAL, }; +static const int pmic_mode_map_pmic5_ldo[REGULATOR_MODE_STANDBY + 1] = { + [REGULATOR_MODE_INVALID] = -EINVAL, + [REGULATOR_MODE_STANDBY] = PMIC5_LDO_MODE_RETENTION, + [REGULATOR_MODE_IDLE] = PMIC5_LDO_MODE_LPM, + [REGULATOR_MODE_NORMAL] = PMIC5_LDO_MODE_HPM, + [REGULATOR_MODE_FAST] = -EINVAL, +}; + static unsigned int rpmh_regulator_pmic4_ldo_of_map_mode(unsigned int rpmh_mode) { unsigned int mode; @@ -518,6 +540,14 @@ static const int pmic_mode_map_pmic4_smps[REGULATOR_MODE_STANDBY + 1] = { [REGULATOR_MODE_FAST] = PMIC4_SMPS_MODE_PWM, }; +static const int pmic_mode_map_pmic5_smps[REGULATOR_MODE_STANDBY + 1] = { + [REGULATOR_MODE_INVALID] = -EINVAL, + [REGULATOR_MODE_STANDBY] = PMIC5_SMPS_MODE_RETENTION, + [REGULATOR_MODE_IDLE] = PMIC5_SMPS_MODE_PFM, + [REGULATOR_MODE_NORMAL] = PMIC5_SMPS_MODE_AUTO, + [REGULATOR_MODE_FAST] = PMIC5_SMPS_MODE_PWM, +}; + static unsigned int rpmh_regulator_pmic4_smps_of_map_mode(unsigned int rpmh_mode) { @@ -552,6 +582,14 @@ static const int pmic_mode_map_pmic4_bob[REGULATOR_MODE_STANDBY + 1] = { [REGULATOR_MODE_FAST] = PMIC4_BOB_MODE_PWM, }; +static const int pmic_mode_map_pmic5_bob[REGULATOR_MODE_STANDBY + 1] = { + [REGULATOR_MODE_INVALID] = -EINVAL, + [REGULATOR_MODE_STANDBY] = -EINVAL, + [REGULATOR_MODE_IDLE] = PMIC5_BOB_MODE_PFM, + [REGULATOR_MODE_NORMAL] = PMIC5_BOB_MODE_AUTO, + [REGULATOR_MODE_FAST] = PMIC5_BOB_MODE_PWM, +}; + static unsigned int rpmh_regulator_pmic4_bob_of_map_mode(unsigned int rpmh_mode) { unsigned int mode; @@ -643,7 +681,7 @@ static const struct rpmh_vreg_hw_data pmic5_pldo = { .voltage_range = REGULATOR_LINEAR_RANGE(1504000, 0, 255, 8000), .n_voltages = 256, .hpm_min_load_uA = 10000, - .pmic_mode_map = pmic_mode_map_pmic4_ldo, + .pmic_mode_map = pmic_mode_map_pmic5_ldo, .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, }; @@ -653,7 +691,7 @@ static const struct rpmh_vreg_hw_data pmic5_pldo_lv = { .voltage_range = REGULATOR_LINEAR_RANGE(1504000, 0, 62, 8000), .n_voltages = 63, .hpm_min_load_uA = 10000, - .pmic_mode_map = pmic_mode_map_pmic4_ldo, + .pmic_mode_map = pmic_mode_map_pmic5_ldo, .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, }; @@ -663,7 +701,7 @@ static const struct rpmh_vreg_hw_data pmic5_nldo = { .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 123, 8000), .n_voltages = 124, .hpm_min_load_uA = 30000, - .pmic_mode_map = pmic_mode_map_pmic4_ldo, + .pmic_mode_map = pmic_mode_map_pmic5_ldo, .of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode, }; @@ -672,7 +710,7 @@ static const struct rpmh_vreg_hw_data pmic5_hfsmps510 = { .ops = &rpmh_regulator_vrm_ops, .voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000), .n_voltages = 216, - .pmic_mode_map = pmic_mode_map_pmic4_smps, + .pmic_mode_map = pmic_mode_map_pmic5_smps, .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, }; @@ -681,7 +719,7 @@ static const struct rpmh_vreg_hw_data pmic5_ftsmps510 = { .ops = &rpmh_regulator_vrm_ops, .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 263, 4000), .n_voltages = 264, - .pmic_mode_map = pmic_mode_map_pmic4_smps, + .pmic_mode_map = pmic_mode_map_pmic5_smps, .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, }; @@ -690,7 +728,7 @@ static const struct rpmh_vreg_hw_data pmic5_hfsmps515 = { .ops = &rpmh_regulator_vrm_ops, .voltage_range = REGULATOR_LINEAR_RANGE(2800000, 0, 4, 1600), .n_voltages = 5, - .pmic_mode_map = pmic_mode_map_pmic4_smps, + .pmic_mode_map = pmic_mode_map_pmic5_smps, .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, }; @@ -699,7 +737,7 @@ static const struct rpmh_vreg_hw_data pmic5_bob = { .ops = &rpmh_regulator_vrm_bypass_ops, .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 135, 32000), .n_voltages = 136, - .pmic_mode_map = pmic_mode_map_pmic4_bob, + .pmic_mode_map = pmic_mode_map_pmic5_bob, .of_map_mode = rpmh_regulator_pmic4_bob_of_map_mode, }; From 906c4d5c939b4d8ebe7be357121271df7b8c9582 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Thu, 25 Jul 2019 11:45:40 +0200 Subject: [PATCH 18/52] dt-bindings: regulator: twl6030: Add retain-on-reset property During reset the VMMC regulator doesn't reach 0V and only drops to 1.8V, furthermore the pulse width is under 200us whereas the SD specification expect 1ms. For this 2 reasons being able to no reset at all the VMMC during warm reset and keep the current voltage is a good workaround. The TWL6030 allows this but needs to be aware of it and this configuration should also be shared with the bootloader. This is the purpose of this new property: ti,retain-on-reset Signed-off-by: Gregory CLEMENT Link: https://lore.kernel.org/r/20190725094542.16547-2-gregory.clement@bootlin.com Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/twl-regulator.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/twl-regulator.txt b/Documentation/devicetree/bindings/regulator/twl-regulator.txt index 74a91c4f8530..549f80436deb 100644 --- a/Documentation/devicetree/bindings/regulator/twl-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/twl-regulator.txt @@ -71,3 +71,10 @@ Example: regulator-min-microvolt = <1000000>; regulator-max-microvolt = <3000000>; }; + +For twl6030 regulators/LDOs: + + - ti,retain-on-reset: Does not turn off the supplies during warm + reset. Could be needed for VMMC, as TWL6030 + reset sequence for this signal does not comply + with the SD specification. From 621d3ce830649d56ef1c9611e370d05ceaffd7fc Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Thu, 25 Jul 2019 11:45:41 +0200 Subject: [PATCH 19/52] regulator: twl6030: use variable for device node Instead of refering the full pdev->dev.of_node use a local variable. Signed-off-by: Gregory CLEMENT Link: https://lore.kernel.org/r/20190725094542.16547-3-gregory.clement@bootlin.com Signed-off-by: Mark Brown --- drivers/regulator/twl6030-regulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/twl6030-regulator.c b/drivers/regulator/twl6030-regulator.c index 5fe208b381eb..d73c81542ceb 100644 --- a/drivers/regulator/twl6030-regulator.c +++ b/drivers/regulator/twl6030-regulator.c @@ -665,14 +665,14 @@ static int twlreg_probe(struct platform_device *pdev) struct regulation_constraints *c; struct regulator_dev *rdev; struct regulator_config config = { }; + struct device_node *np = pdev->dev.of_node; template = of_device_get_match_data(&pdev->dev); if (!template) return -ENODEV; id = template->desc.id; - initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node, - &template->desc); + initdata = of_get_regulator_init_data(&pdev->dev, np, &template->desc); if (!initdata) return -EINVAL; @@ -713,7 +713,7 @@ static int twlreg_probe(struct platform_device *pdev) config.dev = &pdev->dev; config.init_data = initdata; config.driver_data = info; - config.of_node = pdev->dev.of_node; + config.of_node = np; rdev = devm_regulator_register(&pdev->dev, &info->desc, &config); if (IS_ERR(rdev)) { From d9df0187b6edd5871255cee29128c63f134e599c Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Thu, 25 Jul 2019 11:45:42 +0200 Subject: [PATCH 20/52] regulator: twl6030: workaround the VMMC reset behavior During reset the VMMC regulator doesn't reach 0V and only drops to 1.8V, furthermore the pulse width is under 200us whereas the SD specification expect 1ms. The WR_S bit allows the TWL6030 to no reset at all the VMMC during warm reset and keep the current voltage. Thanks to this workaround the SD card doesn't reach a undefined reset stage. Actually this behavior is available for all the LDO regulator, so the driver will also allow to use it with any of these regulator. Signed-off-by: Gregory CLEMENT Link: https://lore.kernel.org/r/20190725094542.16547-4-gregory.clement@bootlin.com Signed-off-by: Mark Brown --- drivers/regulator/twl6030-regulator.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/twl6030-regulator.c b/drivers/regulator/twl6030-regulator.c index d73c81542ceb..b8100c3cedad 100644 --- a/drivers/regulator/twl6030-regulator.c +++ b/drivers/regulator/twl6030-regulator.c @@ -57,6 +57,9 @@ struct twlreg_info { #define VREG_BC_PROC 3 #define VREG_BC_CLK_RST 4 +/* TWL6030 LDO register values for VREG_VOLTAGE */ +#define TWL6030_VREG_VOLTAGE_WR_S BIT(7) + /* TWL6030 LDO register values for CFG_STATE */ #define TWL6030_CFG_STATE_OFF 0x00 #define TWL6030_CFG_STATE_ON 0x01 @@ -68,9 +71,10 @@ struct twlreg_info { #define TWL6030_CFG_STATE_APP(v) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\ TWL6030_CFG_STATE_APP_SHIFT) -/* Flags for SMPS Voltage reading */ +/* Flags for SMPS Voltage reading and LDO reading*/ #define SMPS_OFFSET_EN BIT(0) #define SMPS_EXTENDED_EN BIT(1) +#define TWL_6030_WARM_RESET BIT(3) /* twl6032 SMPS EPROM values */ #define TWL6030_SMPS_OFFSET 0xB0 @@ -250,6 +254,9 @@ twl6030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { struct twlreg_info *info = rdev_get_drvdata(rdev); + if (info->flags & TWL_6030_WARM_RESET) + selector |= TWL6030_VREG_VOLTAGE_WR_S; + return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, selector); } @@ -259,6 +266,9 @@ static int twl6030ldo_get_voltage_sel(struct regulator_dev *rdev) struct twlreg_info *info = rdev_get_drvdata(rdev); int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE); + if (info->flags & TWL_6030_WARM_RESET) + vsel &= ~TWL6030_VREG_VOLTAGE_WR_S; + return vsel; } @@ -710,6 +720,9 @@ static int twlreg_probe(struct platform_device *pdev) break; } + if (of_get_property(np, "ti,retain-on-reset", NULL)) + info->flags |= TWL_6030_WARM_RESET; + config.dev = &pdev->dev; config.init_data = initdata; config.driver_data = info; From 9e127fab67e3ec4451696da0c7872fd291b9372b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 13 Aug 2019 14:31:14 +0100 Subject: [PATCH 21/52] regulator: max8660: remove redundant assignment of variable ret Variable ret is initialized to a value that is never read before a return statement and hence can be removed. Remove it. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190813133114.14931-1-colin.king@canonical.com Signed-off-by: Mark Brown --- drivers/regulator/max8660.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 4bca54446287..347043a5a9a7 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -485,7 +485,6 @@ static int max8660_probe(struct i2c_client *client, rdev = devm_regulator_register(&client->dev, &max8660_reg[id], &config); if (IS_ERR(rdev)) { - ret = PTR_ERR(rdev); dev_err(&client->dev, "failed to register %s\n", max8660_reg[id].name); return PTR_ERR(rdev); From ff461ebfd4b7051d9b79ca023741e6c2d960a912 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Wed, 14 Aug 2019 00:02:56 +0530 Subject: [PATCH 22/52] regulator: act8865 regulator modes and suspend states Add documentation for act8865 regulator modes and suspend states. Add active-semi,8865-regulator.h file for device tree binding constants for act8865 regulators. Signed-off-by: Raag Jadav Link: https://lore.kernel.org/r/1565721176-8955-3-git-send-email-raagjadav@gmail.com Signed-off-by: Mark Brown --- .../bindings/regulator/act8865-regulator.txt | 27 ++++++++++++++++-- .../regulator/active-semi,8865-regulator.h | 28 +++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 include/dt-bindings/regulator/active-semi,8865-regulator.h diff --git a/Documentation/devicetree/bindings/regulator/act8865-regulator.txt b/Documentation/devicetree/bindings/regulator/act8865-regulator.txt index 3ae9f1088845..b9f58e480349 100644 --- a/Documentation/devicetree/bindings/regulator/act8865-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/act8865-regulator.txt @@ -34,6 +34,9 @@ Optional input supply properties: - inl67-supply: The input supply for LDO_REG3 and LDO_REG4 Any standard regulator properties can be used to configure the single regulator. +regulator-initial-mode, regulator-allowed-modes and regulator-mode could be specified +for act8865 using mode values from dt-bindings/regulator/active-semi,8865-regulator.h +file. The valid names for regulators are: - for act8846: @@ -47,6 +50,8 @@ The valid names for regulators are: Example: -------- +#include + i2c1: i2c@f0018000 { pmic: act8865@5b { compatible = "active-semi,act8865"; @@ -65,9 +70,19 @@ Example: regulator-name = "VCC_1V2"; regulator-min-microvolt = <1100000>; regulator-max-microvolt = <1300000>; - regulator-suspend-mem-microvolt = <1150000>; - regulator-suspend-standby-microvolt = <1150000>; regulator-always-on; + + regulator-allowed-modes = , + ; + regulator-initial-mode = ; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-min-microvolt = <1150000>; + regulator-suspend-max-microvolt = <1150000>; + regulator-changeable-in-suspend; + regulator-mode = ; + }; }; vcc_3v3_reg: DCDC_REG3 { @@ -82,6 +97,14 @@ Example: regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; + + regulator-allowed-modes = , + ; + regulator-initial-mode = ; + + regulator-state-mem { + regulator-off-in-suspend; + }; }; vddfuse_reg: LDO_REG2 { diff --git a/include/dt-bindings/regulator/active-semi,8865-regulator.h b/include/dt-bindings/regulator/active-semi,8865-regulator.h new file mode 100644 index 000000000000..15473dbeaf38 --- /dev/null +++ b/include/dt-bindings/regulator/active-semi,8865-regulator.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Device Tree binding constants for the ACT8865 PMIC regulators + */ + +#ifndef _DT_BINDINGS_REGULATOR_ACT8865_H +#define _DT_BINDINGS_REGULATOR_ACT8865_H + +/* + * These constants should be used to specify regulator modes in device tree for + * ACT8865 regulators as follows: + * ACT8865_REGULATOR_MODE_FIXED: It is specific to DCDC regulators and it + * specifies the usage of fixed-frequency + * PWM. + * + * ACT8865_REGULATOR_MODE_NORMAL: It is specific to LDO regulators and it + * specifies the usage of normal mode. + * + * ACT8865_REGULATOR_MODE_LOWPOWER: For DCDC and LDO regulators; it specify + * the usage of proprietary power-saving + * mode. + */ + +#define ACT8865_REGULATOR_MODE_FIXED 1 +#define ACT8865_REGULATOR_MODE_NORMAL 2 +#define ACT8865_REGULATOR_MODE_LOWPOWER 3 + +#endif From 81eeb0a35c2e40bcaf122c6aae3be4f7d9abe201 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 15 Aug 2019 11:07:04 +0530 Subject: [PATCH 23/52] regulator: core: Add label to collate of_node_put() statements In function of_get_child_regulator(), the loop for_each_child_of_node() contains two mid-loop return statements, each preceded by a statement putting child. In order to reduce this repetition, create a new label, err_node_put, that puts child and then returns the required value; edit the mid-loop return blocks to instead go to this new label. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190815053704.32156-1-nishkadg.linux@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/core.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 7a5d52948703..4a27a46ec6e7 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -380,16 +380,17 @@ static struct device_node *of_get_child_regulator(struct device_node *parent, if (!regnode) { regnode = of_get_child_regulator(child, prop_name); - if (regnode) { - of_node_put(child); - return regnode; - } + if (regnode) + goto err_node_put; } else { - of_node_put(child); - return regnode; + goto err_node_put; } } return NULL; + +err_node_put: + of_node_put(child); + return regnode; } /** From 955741a5120bb1ed19d3b12da90bb947d3a0cb99 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Wed, 14 Aug 2019 00:02:55 +0530 Subject: [PATCH 24/52] regulator: act8865: operating mode and suspend state support Implement ->set_mode(), ->get_mode() and ->set_suspend_xx() hooks for act8865 with unlocked expert registers. Based on work done by Borris Brezillon on [1]. [1] https://www.spinics.net/lists/kernel/msg2942960.html Signed-off-by: Raag Jadav Link: https://lore.kernel.org/r/1565721176-8955-2-git-send-email-raagjadav@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/act8865-regulator.c | 187 +++++++++++++++++++++++++- 1 file changed, 186 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index 6a90d3c7a452..0fa97f934df4 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -19,6 +19,7 @@ #include #include #include +#include /* * ACT8600 Global Register Map. @@ -90,23 +91,31 @@ */ #define ACT8865_SYS_MODE 0x00 #define ACT8865_SYS_CTRL 0x01 +#define ACT8865_SYS_UNLK_REGS 0x0b #define ACT8865_DCDC1_VSET1 0x20 #define ACT8865_DCDC1_VSET2 0x21 #define ACT8865_DCDC1_CTRL 0x22 +#define ACT8865_DCDC1_SUS 0x24 #define ACT8865_DCDC2_VSET1 0x30 #define ACT8865_DCDC2_VSET2 0x31 #define ACT8865_DCDC2_CTRL 0x32 +#define ACT8865_DCDC2_SUS 0x34 #define ACT8865_DCDC3_VSET1 0x40 #define ACT8865_DCDC3_VSET2 0x41 #define ACT8865_DCDC3_CTRL 0x42 +#define ACT8865_DCDC3_SUS 0x44 #define ACT8865_LDO1_VSET 0x50 #define ACT8865_LDO1_CTRL 0x51 +#define ACT8865_LDO1_SUS 0x52 #define ACT8865_LDO2_VSET 0x54 #define ACT8865_LDO2_CTRL 0x55 +#define ACT8865_LDO2_SUS 0x56 #define ACT8865_LDO3_VSET 0x60 #define ACT8865_LDO3_CTRL 0x61 +#define ACT8865_LDO3_SUS 0x62 #define ACT8865_LDO4_VSET 0x64 #define ACT8865_LDO4_CTRL 0x65 +#define ACT8865_LDO4_SUS 0x66 #define ACT8865_MSTROFF 0x20 /* @@ -225,6 +234,171 @@ static const struct regulator_linear_range act8600_sudcdc_voltage_ranges[] = { REGULATOR_LINEAR_RANGE(41400000, 248, 255, 0), }; +static int act8865_set_suspend_state(struct regulator_dev *rdev, bool enable) +{ + struct regmap *regmap = rdev->regmap; + int id = rdev->desc->id, reg, val; + + switch (id) { + case ACT8865_ID_DCDC1: + reg = ACT8865_DCDC1_SUS; + val = 0xa8; + break; + case ACT8865_ID_DCDC2: + reg = ACT8865_DCDC2_SUS; + val = 0xa8; + break; + case ACT8865_ID_DCDC3: + reg = ACT8865_DCDC3_SUS; + val = 0xa8; + break; + case ACT8865_ID_LDO1: + reg = ACT8865_LDO1_SUS; + val = 0xe8; + break; + case ACT8865_ID_LDO2: + reg = ACT8865_LDO2_SUS; + val = 0xe8; + break; + case ACT8865_ID_LDO3: + reg = ACT8865_LDO3_SUS; + val = 0xe8; + break; + case ACT8865_ID_LDO4: + reg = ACT8865_LDO4_SUS; + val = 0xe8; + break; + default: + return -EINVAL; + } + + if (enable) + val |= BIT(4); + + /* + * Ask the PMIC to enable/disable this output when entering hibernate + * mode. + */ + return regmap_write(regmap, reg, val); +} + +static int act8865_set_suspend_enable(struct regulator_dev *rdev) +{ + return act8865_set_suspend_state(rdev, true); +} + +static int act8865_set_suspend_disable(struct regulator_dev *rdev) +{ + return act8865_set_suspend_state(rdev, false); +} + +static unsigned int act8865_of_map_mode(unsigned int mode) +{ + switch (mode) { + case ACT8865_REGULATOR_MODE_FIXED: + return REGULATOR_MODE_FAST; + case ACT8865_REGULATOR_MODE_NORMAL: + return REGULATOR_MODE_NORMAL; + case ACT8865_REGULATOR_MODE_LOWPOWER: + return REGULATOR_MODE_STANDBY; + default: + return REGULATOR_MODE_INVALID; + } +} + +static int act8865_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + struct regmap *regmap = rdev->regmap; + int id = rdev_get_id(rdev); + int reg, val = 0; + + switch (id) { + case ACT8865_ID_DCDC1: + reg = ACT8865_DCDC1_CTRL; + break; + case ACT8865_ID_DCDC2: + reg = ACT8865_DCDC2_CTRL; + break; + case ACT8865_ID_DCDC3: + reg = ACT8865_DCDC3_CTRL; + break; + case ACT8865_ID_LDO1: + reg = ACT8865_LDO1_CTRL; + break; + case ACT8865_ID_LDO2: + reg = ACT8865_LDO2_CTRL; + break; + case ACT8865_ID_LDO3: + reg = ACT8865_LDO3_CTRL; + break; + case ACT8865_ID_LDO4: + reg = ACT8865_LDO4_CTRL; + break; + default: + return -EINVAL; + } + + switch (mode) { + case REGULATOR_MODE_FAST: + case REGULATOR_MODE_NORMAL: + if (id <= ACT8865_ID_DCDC3) + val = BIT(5); + break; + case REGULATOR_MODE_STANDBY: + if (id > ACT8865_ID_DCDC3) + val = BIT(5); + break; + default: + return -EINVAL; + } + + return regmap_update_bits(regmap, reg, BIT(5), val); +} + +static unsigned int act8865_get_mode(struct regulator_dev *rdev) +{ + struct regmap *regmap = rdev->regmap; + int id = rdev_get_id(rdev); + int reg, ret, val = 0; + + switch (id) { + case ACT8865_ID_DCDC1: + reg = ACT8865_DCDC1_CTRL; + break; + case ACT8865_ID_DCDC2: + reg = ACT8865_DCDC2_CTRL; + break; + case ACT8865_ID_DCDC3: + reg = ACT8865_DCDC3_CTRL; + break; + case ACT8865_ID_LDO1: + reg = ACT8865_LDO1_CTRL; + break; + case ACT8865_ID_LDO2: + reg = ACT8865_LDO2_CTRL; + break; + case ACT8865_ID_LDO3: + reg = ACT8865_LDO3_CTRL; + break; + case ACT8865_ID_LDO4: + reg = ACT8865_LDO4_CTRL; + break; + default: + return -EINVAL; + } + + ret = regmap_read(regmap, reg, &val); + if (ret) + return ret; + + if (id <= ACT8865_ID_DCDC3 && (val & BIT(5))) + return REGULATOR_MODE_FAST; + else if (id > ACT8865_ID_DCDC3 && !(val & BIT(5))) + return REGULATOR_MODE_NORMAL; + else + return REGULATOR_MODE_STANDBY; +} + static const struct regulator_ops act8865_ops = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, @@ -232,7 +406,11 @@ static const struct regulator_ops act8865_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, + .set_mode = act8865_set_mode, + .get_mode = act8865_get_mode, .is_enabled = regulator_is_enabled_regmap, + .set_suspend_enable = act8865_set_suspend_enable, + .set_suspend_disable = act8865_set_suspend_disable, }; static const struct regulator_ops act8865_ldo_ops = { @@ -242,7 +420,11 @@ static const struct regulator_ops act8865_ldo_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, + .set_mode = act8865_set_mode, + .get_mode = act8865_get_mode, .is_enabled = regulator_is_enabled_regmap, + .set_suspend_enable = act8865_set_suspend_enable, + .set_suspend_disable = act8865_set_suspend_disable, .set_pull_down = regulator_set_pull_down_regmap, }; @@ -256,6 +438,7 @@ static const struct regulator_ops act8865_fixed_ldo_ops = { [_family##_ID_##_id] = { \ .name = _name, \ .of_match = of_match_ptr(_name), \ + .of_map_mode = act8865_of_map_mode, \ .regulators_node = of_match_ptr("regulators"), \ .supply_name = _supply, \ .id = _family##_ID_##_id, \ @@ -590,7 +773,9 @@ static int act8865_pmic_probe(struct i2c_client *client, i2c_set_clientdata(client, act8865); - return 0; + /* Unlock expert registers for ACT8865. */ + return type != ACT8865 ? 0 : regmap_write(act8865->regmap, + ACT8865_SYS_UNLK_REGS, 0xef); } static const struct i2c_device_id act8865_ids[] = { From d3733bc80a5c992679ba9c117c2649ba305338ca Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 27 Aug 2019 08:45:00 +0000 Subject: [PATCH 25/52] regulator: add binding for the SY8824C voltage regulator SY8824C is an I2C-controlled adjustable voltage regulator made by Silergy Corp. Add its device tree binding. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20190827163341.61df63a7@xhacker.debian Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/sy8824x.txt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Documentation/devicetree/bindings/regulator/sy8824x.txt diff --git a/Documentation/devicetree/bindings/regulator/sy8824x.txt b/Documentation/devicetree/bindings/regulator/sy8824x.txt new file mode 100644 index 000000000000..ff8d1af04f7b --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/sy8824x.txt @@ -0,0 +1,20 @@ +SY8824C Voltage regulator + +Required properties: +- compatible: Must be "silergy,sy8824c" +- reg: I2C slave address + +Any property defined as part of the core regulator binding, defined in +./regulator.txt, can also be used. + +Example: + + vcore: regulator@00 { + compatible = "silergy,sy8824c"; + reg = <0x66>; + regulator-name = "vcore"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1150000>; + regulator-boot-on; + regulator-always-on; + }; From d5a2b8220335a605ce22357dd71864f942dda2b9 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 27 Aug 2019 08:45:33 +0000 Subject: [PATCH 26/52] regulator: add support for SY8824C regulator SY8824C is an I2C attached single output regulator made by Silergy Corp, which is used on several Synaptics berlin platforms to control the power supply of the ARM cores. Add a driver for it. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20190827163418.1a32fc48@xhacker.debian Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 7 ++ drivers/regulator/Makefile | 1 + drivers/regulator/sy8824x.c | 192 ++++++++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+) create mode 100644 drivers/regulator/sy8824x.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 37e64884b9ee..e2bf936d0be6 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -907,6 +907,13 @@ config REGULATOR_SY8106A help This driver supports SY8106A single output regulator. +config REGULATOR_SY8824X + tristate "Silergy SY8824C regulator" + depends on I2C && (OF || COMPILE_TEST) + select REGMAP_I2C + help + This driver supports SY8824C single output regulator. + config REGULATOR_TPS51632 tristate "TI TPS51632 Power Regulator" depends on I2C diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index eef73b5a35a4..922bf975070f 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -111,6 +111,7 @@ obj-$(CONFIG_REGULATOR_STM32_PWR) += stm32-pwr.o obj-$(CONFIG_REGULATOR_STPMIC1) += stpmic1_regulator.o obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o obj-$(CONFIG_REGULATOR_SY8106A) += sy8106a-regulator.o +obj-$(CONFIG_REGULATOR_SY8824X) += sy8824x.o obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c new file mode 100644 index 000000000000..2d8a61ca6643 --- /dev/null +++ b/drivers/regulator/sy8824x.c @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SY8824C regulator driver + * + * Copyright (C) 2019 Synaptics Incorporated + * + * Author: Jisheng Zhang + */ + +#include +#include +#include +#include +#include +#include + +#define BUCK_EN (1 << 7) +#define MODE (1 << 6) + +struct sy8824_config { + /* registers */ + unsigned int vol_reg; + unsigned int mode_reg; + unsigned int enable_reg; + /* Voltage range and step(linear) */ + unsigned int vsel_min; + unsigned int vsel_step; + unsigned int vsel_count; +}; + +struct sy8824_device_info { + struct device *dev; + struct regulator_desc desc; + struct regulator_init_data *regulator; + const struct sy8824_config *cfg; +}; + +static int sy8824_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + struct sy8824_device_info *di = rdev_get_drvdata(rdev); + const struct sy8824_config *cfg = di->cfg; + + switch (mode) { + case REGULATOR_MODE_FAST: + regmap_update_bits(rdev->regmap, cfg->mode_reg, MODE, MODE); + break; + case REGULATOR_MODE_NORMAL: + regmap_update_bits(rdev->regmap, cfg->mode_reg, MODE, 0); + break; + default: + return -EINVAL; + } + return 0; +} + +static unsigned int sy8824_get_mode(struct regulator_dev *rdev) +{ + struct sy8824_device_info *di = rdev_get_drvdata(rdev); + const struct sy8824_config *cfg = di->cfg; + u32 val; + int ret = 0; + + ret = regmap_read(rdev->regmap, cfg->mode_reg, &val); + if (ret < 0) + return ret; + if (val & MODE) + return REGULATOR_MODE_FAST; + else + return REGULATOR_MODE_NORMAL; +} + +static const struct regulator_ops sy8824_regulator_ops = { + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .map_voltage = regulator_map_voltage_linear, + .list_voltage = regulator_list_voltage_linear, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_mode = sy8824_set_mode, + .get_mode = sy8824_get_mode, +}; + +static int sy8824_regulator_register(struct sy8824_device_info *di, + struct regulator_config *config) +{ + struct regulator_desc *rdesc = &di->desc; + const struct sy8824_config *cfg = di->cfg; + struct regulator_dev *rdev; + + rdesc->name = "sy8824-reg"; + rdesc->supply_name = "vin"; + rdesc->ops = &sy8824_regulator_ops; + rdesc->type = REGULATOR_VOLTAGE; + rdesc->n_voltages = cfg->vsel_count; + rdesc->enable_reg = cfg->enable_reg; + rdesc->enable_mask = BUCK_EN; + rdesc->min_uV = cfg->vsel_min; + rdesc->uV_step = cfg->vsel_step; + rdesc->vsel_reg = cfg->vol_reg; + rdesc->vsel_mask = cfg->vsel_count - 1; + rdesc->owner = THIS_MODULE; + + rdev = devm_regulator_register(di->dev, &di->desc, config); + return PTR_ERR_OR_ZERO(rdev); +} + +static const struct regmap_config sy8824_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +static int sy8824_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct device_node *np = dev->of_node; + struct sy8824_device_info *di; + struct regulator_config config = { }; + struct regmap *regmap; + int ret; + + di = devm_kzalloc(dev, sizeof(struct sy8824_device_info), GFP_KERNEL); + if (!di) + return -ENOMEM; + + di->regulator = of_get_regulator_init_data(dev, np, &di->desc); + if (!di->regulator) { + dev_err(dev, "Platform data not found!\n"); + return -EINVAL; + } + + di->dev = dev; + di->cfg = of_device_get_match_data(dev); + + regmap = devm_regmap_init_i2c(client, &sy8824_regmap_config); + if (IS_ERR(regmap)) { + dev_err(dev, "Failed to allocate regmap!\n"); + return PTR_ERR(regmap); + } + i2c_set_clientdata(client, di); + + config.dev = di->dev; + config.init_data = di->regulator; + config.regmap = regmap; + config.driver_data = di; + config.of_node = np; + + ret = sy8824_regulator_register(di, &config); + if (ret < 0) + dev_err(dev, "Failed to register regulator!\n"); + return ret; +} + +static const struct sy8824_config sy8824c_cfg = { + .vol_reg = 0x00, + .mode_reg = 0x00, + .enable_reg = 0x00, + .vsel_min = 762500, + .vsel_step = 12500, + .vsel_count = 64, +}; + +static const struct of_device_id sy8824_dt_ids[] = { + { + .compatible = "silergy,sy8824c", + .data = &sy8824c_cfg + }, + { } +}; +MODULE_DEVICE_TABLE(of, sy8824_dt_ids); + +static const struct i2c_device_id sy8824_id[] = { + { "sy8824", }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, sy8824_id); + +static struct i2c_driver sy8824_regulator_driver = { + .driver = { + .name = "sy8824-regulator", + .of_match_table = of_match_ptr(sy8824_dt_ids), + }, + .probe = sy8824_i2c_probe, + .id_table = sy8824_id, +}; +module_i2c_driver(sy8824_regulator_driver); + +MODULE_AUTHOR("Jisheng Zhang "); +MODULE_DESCRIPTION("SY8824C regulator driver"); +MODULE_LICENSE("GPL v2"); From 90de3ae410aaaa63ee7518fac3dabd38f15972c4 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 27 Aug 2019 08:46:21 +0000 Subject: [PATCH 27/52] dt-bindings: sy8824x: Document SY8824E support SY8824E is an I2C-controlled adjustable voltage regulator made by Silergy Corp. The only difference between SY8824C and SY8824E is the vsel_min. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20190827163505.361890af@xhacker.debian Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regulator/sy8824x.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/sy8824x.txt b/Documentation/devicetree/bindings/regulator/sy8824x.txt index ff8d1af04f7b..31fefa3baa71 100644 --- a/Documentation/devicetree/bindings/regulator/sy8824x.txt +++ b/Documentation/devicetree/bindings/regulator/sy8824x.txt @@ -1,7 +1,9 @@ -SY8824C Voltage regulator +SY8824C/SY8824E Voltage regulator Required properties: -- compatible: Must be "silergy,sy8824c" +- compatible: Must be one of the following. + "silergy,sy8824c" + "silergy,sy8824e" - reg: I2C slave address Any property defined as part of the core regulator binding, defined in From 67a7b05b297eba72ee4e0655966ae7cc769d3a26 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 27 Aug 2019 08:47:30 +0000 Subject: [PATCH 28/52] regulator: sy8824x: add SY8824E support The only difference between SY8824E and SY8824C/D is the vsel_min. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20190827163537.52023c4e@xhacker.debian Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 2 +- drivers/regulator/sy8824x.c | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index e2bf936d0be6..2e50423b3c08 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -908,7 +908,7 @@ config REGULATOR_SY8106A This driver supports SY8106A single output regulator. config REGULATOR_SY8824X - tristate "Silergy SY8824C regulator" + tristate "Silergy SY8824C/SY8824E regulator" depends on I2C && (OF || COMPILE_TEST) select REGMAP_I2C help diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c index 2d8a61ca6643..b1438d94eee2 100644 --- a/drivers/regulator/sy8824x.c +++ b/drivers/regulator/sy8824x.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * SY8824C regulator driver + * SY8824C/SY8824E regulator driver * * Copyright (C) 2019 Synaptics Incorporated * @@ -162,11 +162,24 @@ static const struct sy8824_config sy8824c_cfg = { .vsel_count = 64, }; +static const struct sy8824_config sy8824e_cfg = { + .vol_reg = 0x00, + .mode_reg = 0x00, + .enable_reg = 0x00, + .vsel_min = 700000, + .vsel_step = 12500, + .vsel_count = 64, +}; + static const struct of_device_id sy8824_dt_ids[] = { { .compatible = "silergy,sy8824c", .data = &sy8824c_cfg }, + { + .compatible = "silergy,sy8824e", + .data = &sy8824e_cfg + }, { } }; MODULE_DEVICE_TABLE(of, sy8824_dt_ids); @@ -188,5 +201,5 @@ static struct i2c_driver sy8824_regulator_driver = { module_i2c_driver(sy8824_regulator_driver); MODULE_AUTHOR("Jisheng Zhang "); -MODULE_DESCRIPTION("SY8824C regulator driver"); +MODULE_DESCRIPTION("SY8824C/SY8824E regulator driver"); MODULE_LICENSE("GPL v2"); From 253f6cb8b893f5260198d8be244bfc11c3b54d76 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 27 Aug 2019 08:48:04 +0000 Subject: [PATCH 29/52] dt-bindings: sy8824x: Document SY20276 support SY20276 is an I2C-controlled adjustable voltage regulator made by Silergy Corp. The differences between SY8824C and SY20276 are different vsel_min, vsel_step, vsel_count and regs for mode/enable. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20190827163650.47ed1213@xhacker.debian Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regulator/sy8824x.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/regulator/sy8824x.txt b/Documentation/devicetree/bindings/regulator/sy8824x.txt index 31fefa3baa71..28600541b5de 100644 --- a/Documentation/devicetree/bindings/regulator/sy8824x.txt +++ b/Documentation/devicetree/bindings/regulator/sy8824x.txt @@ -1,9 +1,10 @@ -SY8824C/SY8824E Voltage regulator +SY8824C/SY8824E/SY20276 Voltage regulator Required properties: - compatible: Must be one of the following. "silergy,sy8824c" "silergy,sy8824e" + "silergy,sy20276" - reg: I2C slave address Any property defined as part of the core regulator binding, defined in From 92fd0db2cd414c5c78f8f959ed7325e2b24f9445 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 27 Aug 2019 08:48:36 +0000 Subject: [PATCH 30/52] regulator: sy8824x: add SY20276 support The differences between SY8824C and SY20276 are different vsel_min, vsel_step, vsel_count and regs for mode/enable. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20190827163721.1947f7a0@xhacker.debian Signed-off-by: Mark Brown --- drivers/regulator/sy8824x.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c index b1438d94eee2..9410c3470870 100644 --- a/drivers/regulator/sy8824x.c +++ b/drivers/regulator/sy8824x.c @@ -171,6 +171,15 @@ static const struct sy8824_config sy8824e_cfg = { .vsel_count = 64, }; +static const struct sy8824_config sy20276_cfg = { + .vol_reg = 0x00, + .mode_reg = 0x01, + .enable_reg = 0x01, + .vsel_min = 600000, + .vsel_step = 10000, + .vsel_count = 128, +}; + static const struct of_device_id sy8824_dt_ids[] = { { .compatible = "silergy,sy8824c", @@ -180,6 +189,10 @@ static const struct of_device_id sy8824_dt_ids[] = { .compatible = "silergy,sy8824e", .data = &sy8824e_cfg }, + { + .compatible = "silergy,sy20276", + .data = &sy20276_cfg + }, { } }; MODULE_DEVICE_TABLE(of, sy8824_dt_ids); From f27b425d13a34c8b9767c666b7fab30692960276 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 27 Aug 2019 08:49:09 +0000 Subject: [PATCH 31/52] dt-bindings: sy8824x: Document SY20278 support SY20276 is an I2C-controlled adjustable voltage regulator made by Silergy Corp. The differences between SY8824C and SY20278 are different regs for mode/enable. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20190827163754.170cf130@xhacker.debian Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regulator/sy8824x.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/regulator/sy8824x.txt b/Documentation/devicetree/bindings/regulator/sy8824x.txt index 28600541b5de..c5e95850c427 100644 --- a/Documentation/devicetree/bindings/regulator/sy8824x.txt +++ b/Documentation/devicetree/bindings/regulator/sy8824x.txt @@ -5,6 +5,7 @@ Required properties: "silergy,sy8824c" "silergy,sy8824e" "silergy,sy20276" + "silergy,sy20278" - reg: I2C slave address Any property defined as part of the core regulator binding, defined in From b60c2c4aa512f3e95f4525c02df57dcc71a0cdc7 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 27 Aug 2019 08:49:45 +0000 Subject: [PATCH 32/52] regulator: sy8824x: add SY20278 support The differences between SY8824C and SY20278 are different regs for mode/enable. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20190827163830.2c94f29b@xhacker.debian Signed-off-by: Mark Brown --- drivers/regulator/sy8824x.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c index 9410c3470870..1a7fa4865491 100644 --- a/drivers/regulator/sy8824x.c +++ b/drivers/regulator/sy8824x.c @@ -180,6 +180,15 @@ static const struct sy8824_config sy20276_cfg = { .vsel_count = 128, }; +static const struct sy8824_config sy20278_cfg = { + .vol_reg = 0x00, + .mode_reg = 0x01, + .enable_reg = 0x01, + .vsel_min = 762500, + .vsel_step = 12500, + .vsel_count = 64, +}; + static const struct of_device_id sy8824_dt_ids[] = { { .compatible = "silergy,sy8824c", @@ -193,6 +202,10 @@ static const struct of_device_id sy8824_dt_ids[] = { .compatible = "silergy,sy20276", .data = &sy20276_cfg }, + { + .compatible = "silergy,sy20278", + .data = &sy20278_cfg + }, { } }; MODULE_DEVICE_TABLE(of, sy8824_dt_ids); From fa00eb4eb2361ffc594bd9c6d78c585e7112c5dc Mon Sep 17 00:00:00 2001 From: Hsin-Hsiung Wang Date: Fri, 23 Aug 2019 11:45:26 +0800 Subject: [PATCH 33/52] regulator: Add document for MT6358 regulator add dt-binding document for MediaTek MT6358 PMIC Reviewed-by: Rob Herring Signed-off-by: Hsin-Hsiung Wang Link: https://lore.kernel.org/r/1566531931-9772-6-git-send-email-hsin-hsiung.wang@mediatek.com Signed-off-by: Mark Brown --- .../bindings/regulator/mt6358-regulator.txt | 358 ++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 Documentation/devicetree/bindings/regulator/mt6358-regulator.txt diff --git a/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt b/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt new file mode 100644 index 000000000000..9a90a92f2d7e --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/mt6358-regulator.txt @@ -0,0 +1,358 @@ +MediaTek MT6358 Regulator + +All voltage regulators provided by the MT6358 PMIC are described as the +subnodes of the MT6358 regulators node. Each regulator is named according +to its regulator type, buck_ and ldo_. The definition for each +of these nodes is defined using the standard binding for regulators at +Documentation/devicetree/bindings/regulator/regulator.txt. + +The valid names for regulators are:: +BUCK: + buck_vdram1, buck_vcore, buck_vpa, buck_vproc11, buck_vproc12, buck_vgpu, + buck_vs2, buck_vmodem, buck_vs1 +LDO: + ldo_vdram2, ldo_vsim1, ldo_vibr, ldo_vrf12, ldo_vio18, ldo_vusb, ldo_vcamio, + ldo_vcamd, ldo_vcn18, ldo_vfe28, ldo_vsram_proc11, ldo_vcn28, ldo_vsram_others, + ldo_vsram_gpu, ldo_vxo22, ldo_vefuse, ldo_vaux18, ldo_vmch, ldo_vbif28, + ldo_vsram_proc12, ldo_vcama1, ldo_vemc, ldo_vio28, ldo_va12, ldo_vrf18, + ldo_vcn33_bt, ldo_vcn33_wifi, ldo_vcama2, ldo_vmc, ldo_vldo28, ldo_vaud28, + ldo_vsim2 + +Example: + + pmic { + compatible = "mediatek,mt6358"; + + mt6358regulator: mt6358regulator { + compatible = "mediatek,mt6358-regulator"; + + mt6358_vdram1_reg: buck_vdram1 { + regulator-compatible = "buck_vdram1"; + regulator-name = "vdram1"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <2087500>; + regulator-ramp-delay = <12500>; + regulator-enable-ramp-delay = <0>; + regulator-always-on; + }; + + mt6358_vcore_reg: buck_vcore { + regulator-name = "vcore"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1293750>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <200>; + regulator-always-on; + }; + + mt6358_vpa_reg: buck_vpa { + regulator-name = "vpa"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3650000>; + regulator-ramp-delay = <50000>; + regulator-enable-ramp-delay = <250>; + }; + + mt6358_vproc11_reg: buck_vproc11 { + regulator-name = "vproc11"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1293750>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <200>; + regulator-always-on; + }; + + mt6358_vproc12_reg: buck_vproc12 { + regulator-name = "vproc12"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1293750>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <200>; + regulator-always-on; + }; + + mt6358_vgpu_reg: buck_vgpu { + regulator-name = "vgpu"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1293750>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <200>; + }; + + mt6358_vs2_reg: buck_vs2 { + regulator-name = "vs2"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <2087500>; + regulator-ramp-delay = <12500>; + regulator-enable-ramp-delay = <0>; + regulator-always-on; + }; + + mt6358_vmodem_reg: buck_vmodem { + regulator-name = "vmodem"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1293750>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <900>; + regulator-always-on; + }; + + mt6358_vs1_reg: buck_vs1 { + regulator-name = "vs1"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <2587500>; + regulator-ramp-delay = <12500>; + regulator-enable-ramp-delay = <0>; + regulator-always-on; + }; + + mt6358_vdram2_reg: ldo_vdram2 { + regulator-name = "vdram2"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <3300>; + }; + + mt6358_vsim1_reg: ldo_vsim1 { + regulator-name = "vsim1"; + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <3100000>; + regulator-enable-ramp-delay = <540>; + }; + + mt6358_vibr_reg: ldo_vibr { + regulator-name = "vibr"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <60>; + }; + + mt6358_vrf12_reg: ldo_vrf12 { + compatible = "regulator-fixed"; + regulator-name = "vrf12"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-enable-ramp-delay = <120>; + }; + + mt6358_vio18_reg: ldo_vio18 { + compatible = "regulator-fixed"; + regulator-name = "vio18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <2700>; + regulator-always-on; + }; + + mt6358_vusb_reg: ldo_vusb { + regulator-name = "vusb"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3100000>; + regulator-enable-ramp-delay = <270>; + regulator-always-on; + }; + + mt6358_vcamio_reg: ldo_vcamio { + compatible = "regulator-fixed"; + regulator-name = "vcamio"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <270>; + }; + + mt6358_vcamd_reg: ldo_vcamd { + regulator-name = "vcamd"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <270>; + }; + + mt6358_vcn18_reg: ldo_vcn18 { + compatible = "regulator-fixed"; + regulator-name = "vcn18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <270>; + }; + + mt6358_vfe28_reg: ldo_vfe28 { + compatible = "regulator-fixed"; + regulator-name = "vfe28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <270>; + }; + + mt6358_vsram_proc11_reg: ldo_vsram_proc11 { + regulator-name = "vsram_proc11"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1293750>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <240>; + regulator-always-on; + }; + + mt6358_vcn28_reg: ldo_vcn28 { + compatible = "regulator-fixed"; + regulator-name = "vcn28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <270>; + }; + + mt6358_vsram_others_reg: ldo_vsram_others { + regulator-name = "vsram_others"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1293750>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <240>; + regulator-always-on; + }; + + mt6358_vsram_gpu_reg: ldo_vsram_gpu { + regulator-name = "vsram_gpu"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1293750>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <240>; + }; + + mt6358_vxo22_reg: ldo_vxo22 { + compatible = "regulator-fixed"; + regulator-name = "vxo22"; + regulator-min-microvolt = <2200000>; + regulator-max-microvolt = <2200000>; + regulator-enable-ramp-delay = <120>; + regulator-always-on; + }; + + mt6358_vefuse_reg: ldo_vefuse { + regulator-name = "vefuse"; + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <1900000>; + regulator-enable-ramp-delay = <270>; + }; + + mt6358_vaux18_reg: ldo_vaux18 { + compatible = "regulator-fixed"; + regulator-name = "vaux18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <270>; + }; + + mt6358_vmch_reg: ldo_vmch { + regulator-name = "vmch"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <60>; + }; + + mt6358_vbif28_reg: ldo_vbif28 { + compatible = "regulator-fixed"; + regulator-name = "vbif28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <270>; + }; + + mt6358_vsram_proc12_reg: ldo_vsram_proc12 { + regulator-name = "vsram_proc12"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1293750>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <240>; + regulator-always-on; + }; + + mt6358_vcama1_reg: ldo_vcama1 { + regulator-name = "vcama1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3000000>; + regulator-enable-ramp-delay = <270>; + }; + + mt6358_vemc_reg: ldo_vemc { + regulator-name = "vemc"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <60>; + regulator-always-on; + }; + + mt6358_vio28_reg: ldo_vio28 { + compatible = "regulator-fixed"; + regulator-name = "vio28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <270>; + }; + + mt6358_va12_reg: ldo_va12 { + compatible = "regulator-fixed"; + regulator-name = "va12"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-enable-ramp-delay = <270>; + regulator-always-on; + }; + + mt6358_vrf18_reg: ldo_vrf18 { + compatible = "regulator-fixed"; + regulator-name = "vrf18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <120>; + }; + + mt6358_vcn33_bt_reg: ldo_vcn33_bt { + regulator-name = "vcn33_bt"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3500000>; + regulator-enable-ramp-delay = <270>; + }; + + mt6358_vcn33_wifi_reg: ldo_vcn33_wifi { + regulator-name = "vcn33_wifi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3500000>; + regulator-enable-ramp-delay = <270>; + }; + + mt6358_vcama2_reg: ldo_vcama2 { + regulator-name = "vcama2"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3000000>; + regulator-enable-ramp-delay = <270>; + }; + + mt6358_vmc_reg: ldo_vmc { + regulator-name = "vmc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <60>; + }; + + mt6358_vldo28_reg: ldo_vldo28 { + regulator-name = "vldo28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3000000>; + regulator-enable-ramp-delay = <270>; + }; + + mt6358_vaud28_reg: ldo_vaud28 { + compatible = "regulator-fixed"; + regulator-name = "vaud28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <270>; + }; + + mt6358_vsim2_reg: ldo_vsim2 { + regulator-name = "vsim2"; + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <3100000>; + regulator-enable-ramp-delay = <540>; + }; + }; + }; From f67ff1bd58f0c102f0194c3888ddbc4a87dd1382 Mon Sep 17 00:00:00 2001 From: Hsin-Hsiung Wang Date: Fri, 23 Aug 2019 11:45:28 +0800 Subject: [PATCH 34/52] regulator: mt6358: Add support for MT6358 regulator The MT6358 is a regulator found on boards based on MediaTek MT8183 and probably other SoCs. It is a so called pmic and connects as a slave to SoC using SPI, wrapped inside the pmic-wrapper. Signed-off-by: Hsin-Hsiung Wang Link: https://lore.kernel.org/r/1566531931-9772-8-git-send-email-hsin-hsiung.wang@mediatek.com Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 9 + drivers/regulator/Makefile | 1 + drivers/regulator/mt6358-regulator.c | 549 +++++++++++++++++++++ include/linux/regulator/mt6358-regulator.h | 56 +++ 4 files changed, 615 insertions(+) create mode 100644 drivers/regulator/mt6358-regulator.c create mode 100644 include/linux/regulator/mt6358-regulator.h diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 2e50423b3c08..d6d8785630b1 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -619,6 +619,15 @@ config REGULATOR_MT6323 This driver supports the control of different power rails of device through regulator interface. +config REGULATOR_MT6358 + tristate "MediaTek MT6358 PMIC" + depends on MFD_MT6397 + help + Say y here to select this option to enable the power regulator of + MediaTek MT6358 PMIC. + This driver supports the control of different power rails of device + through regulator interface. + config REGULATOR_MT6380 tristate "MediaTek MT6380 PMIC" depends on MTK_PMIC_WRAP diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 922bf975070f..2210ba56f9bd 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -79,6 +79,7 @@ obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o obj-$(CONFIG_REGULATOR_MCP16502) += mcp16502.o obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o +obj-$(CONFIG_REGULATOR_MT6358) += mt6358-regulator.o obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o diff --git a/drivers/regulator/mt6358-regulator.c b/drivers/regulator/mt6358-regulator.c new file mode 100644 index 000000000000..ba42682e06f3 --- /dev/null +++ b/drivers/regulator/mt6358-regulator.c @@ -0,0 +1,549 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2019 MediaTek Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MT6358_BUCK_MODE_AUTO 0 +#define MT6358_BUCK_MODE_FORCE_PWM 1 + +/* + * MT6358 regulators' information + * + * @desc: standard fields of regulator description. + * @qi: Mask for query enable signal status of regulators + */ +struct mt6358_regulator_info { + struct regulator_desc desc; + u32 status_reg; + u32 qi; + const u32 *index_table; + unsigned int n_table; + u32 vsel_shift; + u32 da_vsel_reg; + u32 da_vsel_mask; + u32 da_vsel_shift; + u32 modeset_reg; + u32 modeset_mask; + u32 modeset_shift; +}; + +#define MT6358_BUCK(match, vreg, min, max, step, \ + volt_ranges, vosel_mask, _da_vsel_reg, _da_vsel_mask, \ + _da_vsel_shift, _modeset_reg, _modeset_shift) \ +[MT6358_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = &mt6358_volt_range_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6358_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ((max) - (min)) / (step) + 1, \ + .linear_ranges = volt_ranges, \ + .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ + .vsel_reg = MT6358_BUCK_##vreg##_ELR0, \ + .vsel_mask = vosel_mask, \ + .enable_reg = MT6358_BUCK_##vreg##_CON0, \ + .enable_mask = BIT(0), \ + .of_map_mode = mt6358_map_mode, \ + }, \ + .status_reg = MT6358_BUCK_##vreg##_DBG1, \ + .qi = BIT(0), \ + .da_vsel_reg = _da_vsel_reg, \ + .da_vsel_mask = _da_vsel_mask, \ + .da_vsel_shift = _da_vsel_shift, \ + .modeset_reg = _modeset_reg, \ + .modeset_mask = BIT(_modeset_shift), \ + .modeset_shift = _modeset_shift \ +} + +#define MT6358_LDO(match, vreg, ldo_volt_table, \ + ldo_index_table, enreg, enbit, vosel, \ + vosel_mask, vosel_shift) \ +[MT6358_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = &mt6358_volt_table_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6358_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(ldo_volt_table), \ + .volt_table = ldo_volt_table, \ + .vsel_reg = vosel, \ + .vsel_mask = vosel_mask, \ + .enable_reg = enreg, \ + .enable_mask = BIT(enbit), \ + }, \ + .status_reg = MT6358_LDO_##vreg##_CON1, \ + .qi = BIT(15), \ + .index_table = ldo_index_table, \ + .n_table = ARRAY_SIZE(ldo_index_table), \ + .vsel_shift = vosel_shift, \ +} + +#define MT6358_LDO1(match, vreg, min, max, step, \ + volt_ranges, _da_vsel_reg, _da_vsel_mask, \ + _da_vsel_shift, vosel, vosel_mask) \ +[MT6358_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = &mt6358_volt_range_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6358_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ((max) - (min)) / (step) + 1, \ + .linear_ranges = volt_ranges, \ + .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ + .vsel_reg = vosel, \ + .vsel_mask = vosel_mask, \ + .enable_reg = MT6358_LDO_##vreg##_CON0, \ + .enable_mask = BIT(0), \ + }, \ + .da_vsel_reg = _da_vsel_reg, \ + .da_vsel_mask = _da_vsel_mask, \ + .da_vsel_shift = _da_vsel_shift, \ + .status_reg = MT6358_LDO_##vreg##_DBG1, \ + .qi = BIT(0), \ +} + +#define MT6358_REG_FIXED(match, vreg, \ + enreg, enbit, volt) \ +[MT6358_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = &mt6358_volt_fixed_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6358_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = 1, \ + .enable_reg = enreg, \ + .enable_mask = BIT(enbit), \ + .min_uV = volt, \ + }, \ + .status_reg = MT6358_LDO_##vreg##_CON1, \ + .qi = BIT(15), \ +} + +static const struct regulator_linear_range buck_volt_range1[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 6250), +}; + +static const struct regulator_linear_range buck_volt_range2[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 12500), +}; + +static const struct regulator_linear_range buck_volt_range3[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000), +}; + +static const struct regulator_linear_range buck_volt_range4[] = { + REGULATOR_LINEAR_RANGE(1000000, 0, 0x7f, 12500), +}; + +static const u32 vdram2_voltages[] = { + 600000, 1800000, +}; + +static const u32 vsim_voltages[] = { + 1700000, 1800000, 2700000, 3000000, 3100000, +}; + +static const u32 vibr_voltages[] = { + 1200000, 1300000, 1500000, 1800000, + 2000000, 2800000, 3000000, 3300000, +}; + +static const u32 vusb_voltages[] = { + 3000000, 3100000, +}; + +static const u32 vcamd_voltages[] = { + 900000, 1000000, 1100000, 1200000, + 1300000, 1500000, 1800000, +}; + +static const u32 vefuse_voltages[] = { + 1700000, 1800000, 1900000, +}; + +static const u32 vmch_vemc_voltages[] = { + 2900000, 3000000, 3300000, +}; + +static const u32 vcama_voltages[] = { + 1800000, 2500000, 2700000, + 2800000, 2900000, 3000000, +}; + +static const u32 vcn33_bt_wifi_voltages[] = { + 3300000, 3400000, 3500000, +}; + +static const u32 vmc_voltages[] = { + 1800000, 2900000, 3000000, 3300000, +}; + +static const u32 vldo28_voltages[] = { + 2800000, 3000000, +}; + +static const u32 vdram2_idx[] = { + 0, 12, +}; + +static const u32 vsim_idx[] = { + 3, 4, 8, 11, 12, +}; + +static const u32 vibr_idx[] = { + 0, 1, 2, 4, 5, 9, 11, 13, +}; + +static const u32 vusb_idx[] = { + 3, 4, +}; + +static const u32 vcamd_idx[] = { + 3, 4, 5, 6, 7, 9, 12, +}; + +static const u32 vefuse_idx[] = { + 11, 12, 13, +}; + +static const u32 vmch_vemc_idx[] = { + 2, 3, 5, +}; + +static const u32 vcama_idx[] = { + 0, 7, 9, 10, 11, 12, +}; + +static const u32 vcn33_bt_wifi_idx[] = { + 1, 2, 3, +}; + +static const u32 vmc_idx[] = { + 4, 10, 11, 13, +}; + +static const u32 vldo28_idx[] = { + 1, 3, +}; + +static unsigned int mt6358_map_mode(unsigned int mode) +{ + return mode == MT6358_BUCK_MODE_AUTO ? + REGULATOR_MODE_NORMAL : REGULATOR_MODE_FAST; +} + +static int mt6358_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) +{ + int idx, ret; + const u32 *pvol; + struct mt6358_regulator_info *info = rdev_get_drvdata(rdev); + + pvol = info->index_table; + + idx = pvol[selector]; + ret = regmap_update_bits(rdev->regmap, info->desc.vsel_reg, + info->desc.vsel_mask, + idx << info->vsel_shift); + + return ret; +} + +static int mt6358_get_voltage_sel(struct regulator_dev *rdev) +{ + int idx, ret; + u32 selector; + struct mt6358_regulator_info *info = rdev_get_drvdata(rdev); + const u32 *pvol; + + ret = regmap_read(rdev->regmap, info->desc.vsel_reg, &selector); + if (ret != 0) { + dev_info(&rdev->dev, + "Failed to get mt6358 %s vsel reg: %d\n", + info->desc.name, ret); + return ret; + } + + selector = (selector & info->desc.vsel_mask) >> info->vsel_shift; + pvol = info->index_table; + for (idx = 0; idx < info->desc.n_voltages; idx++) { + if (pvol[idx] == selector) + return idx; + } + + return -EINVAL; +} + +static int mt6358_get_buck_voltage_sel(struct regulator_dev *rdev) +{ + int ret, regval; + struct mt6358_regulator_info *info = rdev_get_drvdata(rdev); + + ret = regmap_read(rdev->regmap, info->da_vsel_reg, ®val); + if (ret != 0) { + dev_err(&rdev->dev, + "Failed to get mt6358 Buck %s vsel reg: %d\n", + info->desc.name, ret); + return ret; + } + + ret = (regval >> info->da_vsel_shift) & info->da_vsel_mask; + + return ret; +} + +static int mt6358_get_status(struct regulator_dev *rdev) +{ + int ret; + u32 regval; + struct mt6358_regulator_info *info = rdev_get_drvdata(rdev); + + ret = regmap_read(rdev->regmap, info->status_reg, ®val); + if (ret != 0) { + dev_info(&rdev->dev, "Failed to get enable reg: %d\n", ret); + return ret; + } + + return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF; +} + +static int mt6358_regulator_set_mode(struct regulator_dev *rdev, + unsigned int mode) +{ + struct mt6358_regulator_info *info = rdev_get_drvdata(rdev); + int val; + + switch (mode) { + case REGULATOR_MODE_FAST: + val = MT6358_BUCK_MODE_FORCE_PWM; + break; + case REGULATOR_MODE_NORMAL: + val = MT6358_BUCK_MODE_AUTO; + break; + default: + return -EINVAL; + } + + dev_dbg(&rdev->dev, "mt6358 buck set_mode %#x, %#x, %#x, %#x\n", + info->modeset_reg, info->modeset_mask, + info->modeset_shift, val); + + val <<= info->modeset_shift; + + return regmap_update_bits(rdev->regmap, info->modeset_reg, + info->modeset_mask, val); +} + +static unsigned int mt6358_regulator_get_mode(struct regulator_dev *rdev) +{ + struct mt6358_regulator_info *info = rdev_get_drvdata(rdev); + int ret, regval; + + ret = regmap_read(rdev->regmap, info->modeset_reg, ®val); + if (ret != 0) { + dev_err(&rdev->dev, + "Failed to get mt6358 buck mode: %d\n", ret); + return ret; + } + + switch ((regval & info->modeset_mask) >> info->modeset_shift) { + case MT6358_BUCK_MODE_AUTO: + return REGULATOR_MODE_NORMAL; + case MT6358_BUCK_MODE_FORCE_PWM: + return REGULATOR_MODE_FAST; + default: + return -EINVAL; + } +} + +static const struct regulator_ops mt6358_volt_range_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = mt6358_get_buck_voltage_sel, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_status = mt6358_get_status, + .set_mode = mt6358_regulator_set_mode, + .get_mode = mt6358_regulator_get_mode, +}; + +static const struct regulator_ops mt6358_volt_table_ops = { + .list_voltage = regulator_list_voltage_table, + .map_voltage = regulator_map_voltage_iterate, + .set_voltage_sel = mt6358_set_voltage_sel, + .get_voltage_sel = mt6358_get_voltage_sel, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_status = mt6358_get_status, +}; + +static const struct regulator_ops mt6358_volt_fixed_ops = { + .list_voltage = regulator_list_voltage_linear, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_status = mt6358_get_status, +}; + +/* The array is indexed by id(MT6358_ID_XXX) */ +static struct mt6358_regulator_info mt6358_regulators[] = { + MT6358_BUCK("buck_vdram1", VDRAM1, 500000, 2087500, 12500, + buck_volt_range2, 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f, + 0, MT6358_VDRAM1_ANA_CON0, 8), + MT6358_BUCK("buck_vcore", VCORE, 500000, 1293750, 6250, + buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f, + 0, MT6358_VCORE_VGPU_ANA_CON0, 1), + MT6358_BUCK("buck_vpa", VPA, 500000, 3650000, 50000, + buck_volt_range3, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, 0, + MT6358_VPA_ANA_CON0, 3), + MT6358_BUCK("buck_vproc11", VPROC11, 500000, 1293750, 6250, + buck_volt_range1, 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f, + 0, MT6358_VPROC_ANA_CON0, 1), + MT6358_BUCK("buck_vproc12", VPROC12, 500000, 1293750, 6250, + buck_volt_range1, 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f, + 0, MT6358_VPROC_ANA_CON0, 2), + MT6358_BUCK("buck_vgpu", VGPU, 500000, 1293750, 6250, + buck_volt_range1, 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f, 0, + MT6358_VCORE_VGPU_ANA_CON0, 2), + MT6358_BUCK("buck_vs2", VS2, 500000, 2087500, 12500, + buck_volt_range2, 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f, 0, + MT6358_VS2_ANA_CON0, 8), + MT6358_BUCK("buck_vmodem", VMODEM, 500000, 1293750, 6250, + buck_volt_range1, 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f, + 0, MT6358_VMODEM_ANA_CON0, 8), + MT6358_BUCK("buck_vs1", VS1, 1000000, 2587500, 12500, + buck_volt_range4, 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f, 0, + MT6358_VS1_ANA_CON0, 8), + MT6358_REG_FIXED("ldo_vrf12", VRF12, + MT6358_LDO_VRF12_CON0, 0, 1200000), + MT6358_REG_FIXED("ldo_vio18", VIO18, + MT6358_LDO_VIO18_CON0, 0, 1800000), + MT6358_REG_FIXED("ldo_vcamio", VCAMIO, + MT6358_LDO_VCAMIO_CON0, 0, 1800000), + MT6358_REG_FIXED("ldo_vcn18", VCN18, MT6358_LDO_VCN18_CON0, 0, 1800000), + MT6358_REG_FIXED("ldo_vfe28", VFE28, MT6358_LDO_VFE28_CON0, 0, 2800000), + MT6358_REG_FIXED("ldo_vcn28", VCN28, MT6358_LDO_VCN28_CON0, 0, 2800000), + MT6358_REG_FIXED("ldo_vxo22", VXO22, MT6358_LDO_VXO22_CON0, 0, 2200000), + MT6358_REG_FIXED("ldo_vaux18", VAUX18, + MT6358_LDO_VAUX18_CON0, 0, 1800000), + MT6358_REG_FIXED("ldo_vbif28", VBIF28, + MT6358_LDO_VBIF28_CON0, 0, 2800000), + MT6358_REG_FIXED("ldo_vio28", VIO28, MT6358_LDO_VIO28_CON0, 0, 2800000), + MT6358_REG_FIXED("ldo_va12", VA12, MT6358_LDO_VA12_CON0, 0, 1200000), + MT6358_REG_FIXED("ldo_vrf18", VRF18, MT6358_LDO_VRF18_CON0, 0, 1800000), + MT6358_REG_FIXED("ldo_vaud28", VAUD28, + MT6358_LDO_VAUD28_CON0, 0, 2800000), + MT6358_LDO("ldo_vdram2", VDRAM2, vdram2_voltages, vdram2_idx, + MT6358_LDO_VDRAM2_CON0, 0, MT6358_LDO_VDRAM2_ELR0, 0x10, 0), + MT6358_LDO("ldo_vsim1", VSIM1, vsim_voltages, vsim_idx, + MT6358_LDO_VSIM1_CON0, 0, MT6358_VSIM1_ANA_CON0, 0xf00, 8), + MT6358_LDO("ldo_vibr", VIBR, vibr_voltages, vibr_idx, + MT6358_LDO_VIBR_CON0, 0, MT6358_VIBR_ANA_CON0, 0xf00, 8), + MT6358_LDO("ldo_vusb", VUSB, vusb_voltages, vusb_idx, + MT6358_LDO_VUSB_CON0_0, 0, MT6358_VUSB_ANA_CON0, 0x700, 8), + MT6358_LDO("ldo_vcamd", VCAMD, vcamd_voltages, vcamd_idx, + MT6358_LDO_VCAMD_CON0, 0, MT6358_VCAMD_ANA_CON0, 0xf00, 8), + MT6358_LDO("ldo_vefuse", VEFUSE, vefuse_voltages, vefuse_idx, + MT6358_LDO_VEFUSE_CON0, 0, MT6358_VEFUSE_ANA_CON0, 0xf00, 8), + MT6358_LDO("ldo_vmch", VMCH, vmch_vemc_voltages, vmch_vemc_idx, + MT6358_LDO_VMCH_CON0, 0, MT6358_VMCH_ANA_CON0, 0x700, 8), + MT6358_LDO("ldo_vcama1", VCAMA1, vcama_voltages, vcama_idx, + MT6358_LDO_VCAMA1_CON0, 0, MT6358_VCAMA1_ANA_CON0, 0xf00, 8), + MT6358_LDO("ldo_vemc", VEMC, vmch_vemc_voltages, vmch_vemc_idx, + MT6358_LDO_VEMC_CON0, 0, MT6358_VEMC_ANA_CON0, 0x700, 8), + MT6358_LDO("ldo_vcn33_bt", VCN33_BT, vcn33_bt_wifi_voltages, + vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_0, + 0, MT6358_VCN33_ANA_CON0, 0x300, 8), + MT6358_LDO("ldo_vcn33_wifi", VCN33_WIFI, vcn33_bt_wifi_voltages, + vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_1, + 0, MT6358_VCN33_ANA_CON0, 0x300, 8), + MT6358_LDO("ldo_vcama2", VCAMA2, vcama_voltages, vcama_idx, + MT6358_LDO_VCAMA2_CON0, 0, MT6358_VCAMA2_ANA_CON0, 0xf00, 8), + MT6358_LDO("ldo_vmc", VMC, vmc_voltages, vmc_idx, + MT6358_LDO_VMC_CON0, 0, MT6358_VMC_ANA_CON0, 0xf00, 8), + MT6358_LDO("ldo_vldo28", VLDO28, vldo28_voltages, vldo28_idx, + MT6358_LDO_VLDO28_CON0_0, 0, + MT6358_VLDO28_ANA_CON0, 0x300, 8), + MT6358_LDO("ldo_vsim2", VSIM2, vsim_voltages, vsim_idx, + MT6358_LDO_VSIM2_CON0, 0, MT6358_VSIM2_ANA_CON0, 0xf00, 8), + MT6358_LDO1("ldo_vsram_proc11", VSRAM_PROC11, 500000, 1293750, 6250, + buck_volt_range1, MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f, 8, + MT6358_LDO_VSRAM_CON0, 0x7f), + MT6358_LDO1("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250, + buck_volt_range1, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f, 8, + MT6358_LDO_VSRAM_CON2, 0x7f), + MT6358_LDO1("ldo_vsram_gpu", VSRAM_GPU, 500000, 1293750, 6250, + buck_volt_range1, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f, 8, + MT6358_LDO_VSRAM_CON3, 0x7f), + MT6358_LDO1("ldo_vsram_proc12", VSRAM_PROC12, 500000, 1293750, 6250, + buck_volt_range1, MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f, 8, + MT6358_LDO_VSRAM_CON1, 0x7f), +}; + +static int mt6358_regulator_probe(struct platform_device *pdev) +{ + struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent); + struct regulator_config config = {}; + struct regulator_dev *rdev; + int i; + + for (i = 0; i < MT6358_MAX_REGULATOR; i++) { + config.dev = &pdev->dev; + config.driver_data = &mt6358_regulators[i]; + config.regmap = mt6397->regmap; + + rdev = devm_regulator_register(&pdev->dev, + &mt6358_regulators[i].desc, + &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "failed to register %s\n", + mt6358_regulators[i].desc.name); + return PTR_ERR(rdev); + } + } + + return 0; +} + +static const struct platform_device_id mt6358_platform_ids[] = { + {"mt6358-regulator", 0}, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(platform, mt6358_platform_ids); + +static struct platform_driver mt6358_regulator_driver = { + .driver = { + .name = "mt6358-regulator", + }, + .probe = mt6358_regulator_probe, + .id_table = mt6358_platform_ids, +}; + +module_platform_driver(mt6358_regulator_driver); + +MODULE_AUTHOR("Hsin-Hsiung Wang "); +MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6358 PMIC"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/regulator/mt6358-regulator.h b/include/linux/regulator/mt6358-regulator.h new file mode 100644 index 000000000000..1cc304946d09 --- /dev/null +++ b/include/linux/regulator/mt6358-regulator.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef __LINUX_REGULATOR_MT6358_H +#define __LINUX_REGULATOR_MT6358_H + +enum { + MT6358_ID_VDRAM1 = 0, + MT6358_ID_VCORE, + MT6358_ID_VPA, + MT6358_ID_VPROC11, + MT6358_ID_VPROC12, + MT6358_ID_VGPU, + MT6358_ID_VS2, + MT6358_ID_VMODEM, + MT6358_ID_VS1, + MT6358_ID_VDRAM2 = 9, + MT6358_ID_VSIM1, + MT6358_ID_VIBR, + MT6358_ID_VRF12, + MT6358_ID_VIO18, + MT6358_ID_VUSB, + MT6358_ID_VCAMIO, + MT6358_ID_VCAMD, + MT6358_ID_VCN18, + MT6358_ID_VFE28, + MT6358_ID_VSRAM_PROC11, + MT6358_ID_VCN28, + MT6358_ID_VSRAM_OTHERS, + MT6358_ID_VSRAM_GPU, + MT6358_ID_VXO22, + MT6358_ID_VEFUSE, + MT6358_ID_VAUX18, + MT6358_ID_VMCH, + MT6358_ID_VBIF28, + MT6358_ID_VSRAM_PROC12, + MT6358_ID_VCAMA1, + MT6358_ID_VEMC, + MT6358_ID_VIO28, + MT6358_ID_VA12, + MT6358_ID_VRF18, + MT6358_ID_VCN33_BT, + MT6358_ID_VCN33_WIFI, + MT6358_ID_VCAMA2, + MT6358_ID_VMC, + MT6358_ID_VLDO28, + MT6358_ID_VAUD28, + MT6358_ID_VSIM2, + MT6358_ID_RG_MAX, +}; + +#define MT6358_MAX_REGULATOR MT6358_ID_RG_MAX + +#endif /* __LINUX_REGULATOR_MT6358_H */ From 50bc5731f7fc086693d78e42b7d252b97a35cda1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 30 Aug 2019 12:29:22 +0100 Subject: [PATCH 35/52] regulator: mt6358: Add BROKEN dependency while waiting for MFD to merge The mt6358 driver was merged in error, it depends on an existing MFD rather than a newly added one and needs updates to that driver. Disable the build until those are merged. Reported-by: Stephen Rothwell Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index d6d8785630b1..3ee63531f6d5 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -621,7 +621,7 @@ config REGULATOR_MT6323 config REGULATOR_MT6358 tristate "MediaTek MT6358 PMIC" - depends on MFD_MT6397 + depends on MFD_MT6397 && BROKEN help Say y here to select this option to enable the power regulator of MediaTek MT6358 PMIC. From dab106742318c833e1f97d0e6be86b82e33bc5a3 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Thu, 29 Aug 2019 06:49:18 +0000 Subject: [PATCH 36/52] regulator: sy8824x: use c++style for the comment block near SPDX Update the entire comment block to be C++ style so it looks consistent. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20190829143749.4b42bc65@xhacker.debian Signed-off-by: Mark Brown --- drivers/regulator/sy8824x.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c index 1a7fa4865491..d806fa7020d4 100644 --- a/drivers/regulator/sy8824x.c +++ b/drivers/regulator/sy8824x.c @@ -1,11 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 -/* - * SY8824C/SY8824E regulator driver - * - * Copyright (C) 2019 Synaptics Incorporated - * - * Author: Jisheng Zhang - */ +// +// SY8824C/SY8824E regulator driver +// +// Copyright (C) 2019 Synaptics Incorporated +// +// Author: Jisheng Zhang #include #include From e02e23d5f01937cec2c76a8e61aea0b4e5f53626 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Thu, 29 Aug 2019 06:50:46 +0000 Subject: [PATCH 37/52] regulator: sy8824x: add prefixes to BUCK_EN and MODE macros Add prefixes to BUCK_EN and MODE macros to namespace them. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20190829143927.395d0385@xhacker.debian Signed-off-by: Mark Brown --- drivers/regulator/sy8824x.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c index d806fa7020d4..92adb4f3ee19 100644 --- a/drivers/regulator/sy8824x.c +++ b/drivers/regulator/sy8824x.c @@ -13,8 +13,8 @@ #include #include -#define BUCK_EN (1 << 7) -#define MODE (1 << 6) +#define SY8824C_BUCK_EN (1 << 7) +#define SY8824C_MODE (1 << 6) struct sy8824_config { /* registers */ @@ -41,10 +41,12 @@ static int sy8824_set_mode(struct regulator_dev *rdev, unsigned int mode) switch (mode) { case REGULATOR_MODE_FAST: - regmap_update_bits(rdev->regmap, cfg->mode_reg, MODE, MODE); + regmap_update_bits(rdev->regmap, cfg->mode_reg, + SY8824C_MODE, SY8824C_MODE); break; case REGULATOR_MODE_NORMAL: - regmap_update_bits(rdev->regmap, cfg->mode_reg, MODE, 0); + regmap_update_bits(rdev->regmap, cfg->mode_reg, + SY8824C_MODE, 0); break; default: return -EINVAL; @@ -62,7 +64,7 @@ static unsigned int sy8824_get_mode(struct regulator_dev *rdev) ret = regmap_read(rdev->regmap, cfg->mode_reg, &val); if (ret < 0) return ret; - if (val & MODE) + if (val & SY8824C_MODE) return REGULATOR_MODE_FAST; else return REGULATOR_MODE_NORMAL; @@ -94,7 +96,7 @@ static int sy8824_regulator_register(struct sy8824_device_info *di, rdesc->type = REGULATOR_VOLTAGE; rdesc->n_voltages = cfg->vsel_count; rdesc->enable_reg = cfg->enable_reg; - rdesc->enable_mask = BUCK_EN; + rdesc->enable_mask = SY8824C_BUCK_EN; rdesc->min_uV = cfg->vsel_min; rdesc->uV_step = cfg->vsel_step; rdesc->vsel_reg = cfg->vol_reg; From baedad4c35ce35973263f8991d288c280f4bd05d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 29 Aug 2019 13:54:35 +0100 Subject: [PATCH 38/52] MAINTAINERS: Add keyword pattern on regulator_get_optional() In an effort to try to contain abuses of regulator_get_optional() add a keyword entry to the MAINTAINERS stanza for the regulator API so that the regulator maintainers get CCed on new usages. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20190829125435.48770-1-broonie@kernel.org Signed-off-by: Mark Brown --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..6cfb528d0a2e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17234,6 +17234,7 @@ F: Documentation/power/regulator/ F: drivers/regulator/ F: include/dt-bindings/regulator/ F: include/linux/regulator/ +K: regulator_get_optional VRF M: David Ahern From d0087e72710ca7d1b309bf427286da58418ea89e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 30 Aug 2019 09:17:37 +0200 Subject: [PATCH 39/52] regulator: provide regulator_bulk_set_supply_names() There are many regulator consumers who - before using the regulator bulk functions - set the supply names in regulator_bulk_data using a for loop. Let's provide a simple helper in the consumer API that allows users to do the same with a single function call. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20190830071740.4267-2-brgl@bgdev.pl Signed-off-by: Mark Brown --- drivers/regulator/helpers.c | 21 +++++++++++++++++++++ include/linux/regulator/consumer.h | 12 ++++++++++++ 2 files changed, 33 insertions(+) diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c index 4986cc5064a1..ca3dc3f3bb29 100644 --- a/drivers/regulator/helpers.c +++ b/drivers/regulator/helpers.c @@ -860,3 +860,24 @@ int regulator_get_current_limit_regmap(struct regulator_dev *rdev) return -EINVAL; } EXPORT_SYMBOL_GPL(regulator_get_current_limit_regmap); + +/** + * regulator_bulk_set_supply_names - initialize the 'supply' fields in an array + * of regulator_bulk_data structs + * + * @consumers: array of regulator_bulk_data entries to initialize + * @supply_names: array of supply name strings + * @num_supplies: number of supply names to initialize + * + * Note: the 'consumers' array must be the size of 'num_supplies'. + */ +void regulator_bulk_set_supply_names(struct regulator_bulk_data *consumers, + const char *const *supply_names, + unsigned int num_supplies) +{ + unsigned int i; + + for (i = 0; i < num_supplies; i++) + consumers[i].supply = supply_names[i]; +} +EXPORT_SYMBOL_GPL(regulator_bulk_set_supply_names); diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 815983419375..6d2181a76987 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -281,6 +281,12 @@ void devm_regulator_unregister_notifier(struct regulator *regulator, void *regulator_get_drvdata(struct regulator *regulator); void regulator_set_drvdata(struct regulator *regulator, void *data); +/* misc helpers */ + +void regulator_bulk_set_supply_names(struct regulator_bulk_data *consumers, + const char *const *supply_names, + unsigned int num_supplies); + #else /* @@ -580,6 +586,12 @@ static inline int regulator_list_voltage(struct regulator *regulator, unsigned s return -EINVAL; } +void regulator_bulk_set_supply_names(struct regulator_bulk_data *consumers, + const char *const *supply_names, + unsigned int num_supplies) +{ +} + #endif static inline int regulator_set_voltage_triplet(struct regulator *regulator, From d072cb263f9e0ce3f8f6089c17e3466885971fa8 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 2 Sep 2019 17:13:32 +0200 Subject: [PATCH 40/52] regulator: add missing 'static inline' to a helper's stub The build fails when CONFIG_REGULATOR is not selected because the stub for regulator_bulk_set_supply_names() is missing the 'static inline' attribute. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20190902151332.28058-1-brgl@bgdev.pl Signed-off-by: Mark Brown --- include/linux/regulator/consumer.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 6d2181a76987..337a46391527 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -586,9 +586,10 @@ static inline int regulator_list_voltage(struct regulator *regulator, unsigned s return -EINVAL; } -void regulator_bulk_set_supply_names(struct regulator_bulk_data *consumers, - const char *const *supply_names, - unsigned int num_supplies) +static inline void +regulator_bulk_set_supply_names(struct regulator_bulk_data *consumers, + const char *const *supply_names, + unsigned int num_supplies) { } From 55576cf1853798e86f620766e23b604c9224c19c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 4 Sep 2019 13:42:50 +0100 Subject: [PATCH 41/52] regulator: Defer init completion for a while after late_initcall The kernel has no way of knowing when we have finished instantiating drivers, between deferred probe and systems that build key drivers as modules we might be doing this long after userspace has booted. This has always been a bit of an issue with regulator_init_complete since it can power off hardware that's not had it's driver loaded which can result in user visible effects, the main case is powering off displays. Practically speaking it's not been an issue in real systems since most systems that use the regulator API are embedded and build in key drivers anyway but with Arm laptops coming on the market it's becoming more of an issue so let's do something about it. In the absence of any better idea just defer the powering off for 30s after late_initcall(), this is obviously a hack but it should mask the issue for now and it's no more arbitrary than late_initcall() itself. Ideally we'd have some heuristics to detect if we're on an affected system and tune or skip the delay appropriately, and there may be some need for a command line option to be added. Link: https://lore.kernel.org/r/20190904124250.25844-1-broonie@kernel.org Signed-off-by: Mark Brown Tested-by: Lee Jones Cc: stable@vger.kernel.org --- drivers/regulator/core.c | 42 +++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 4a27a46ec6e7..340db986b67f 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -5644,7 +5644,7 @@ static int __init regulator_init(void) /* init early to allow our consumers to complete system booting */ core_initcall(regulator_init); -static int __init regulator_late_cleanup(struct device *dev, void *data) +static int regulator_late_cleanup(struct device *dev, void *data) { struct regulator_dev *rdev = dev_to_rdev(dev); const struct regulator_ops *ops = rdev->desc->ops; @@ -5693,17 +5693,8 @@ unlock: return 0; } -static int __init regulator_init_complete(void) +static void regulator_init_complete_work_function(struct work_struct *work) { - /* - * Since DT doesn't provide an idiomatic mechanism for - * enabling full constraints and since it's much more natural - * with DT to provide them just assume that a DT enabled - * system has full constraints. - */ - if (of_have_populated_dt()) - has_full_constraints = true; - /* * Regulators may had failed to resolve their input supplies * when were registered, either because the input supply was @@ -5721,6 +5712,35 @@ static int __init regulator_init_complete(void) */ class_for_each_device(®ulator_class, NULL, NULL, regulator_late_cleanup); +} + +static DECLARE_DELAYED_WORK(regulator_init_complete_work, + regulator_init_complete_work_function); + +static int __init regulator_init_complete(void) +{ + /* + * Since DT doesn't provide an idiomatic mechanism for + * enabling full constraints and since it's much more natural + * with DT to provide them just assume that a DT enabled + * system has full constraints. + */ + if (of_have_populated_dt()) + has_full_constraints = true; + + /* + * We punt completion for an arbitrary amount of time since + * systems like distros will load many drivers from userspace + * so consumers might not always be ready yet, this is + * particularly an issue with laptops where this might bounce + * the display off then on. Ideally we'd get a notification + * from userspace when this happens but we don't so just wait + * a bit and hope we waited long enough. It'd be better if + * 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)); return 0; } From a95744670664a8a184eb26049dc7020f221a0979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Wed, 4 Sep 2019 12:35:00 -0700 Subject: [PATCH 42/52] regulator: tps65132: Stop parsing DT when gpio is not found MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case of a missing (optional) gpio don't fall through up to "ti,active-discharge-time-us" due to devm_fwnode_get_index_gpiod_from_child() returning NULL (since gpiod_get_from_of_node() returned NULL) but rather indicate success as intended. This makes the driver probe correctly when e.g. only the enable gpio is given. Signed-off-by: Guido Günther Link: https://lore.kernel.org/r/363bd50cc7c60daa57d614a341d1fd649f05194c.1567625660.git.agx@sigxcpu.org Signed-off-by: Mark Brown --- drivers/regulator/tps65132-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/tps65132-regulator.c b/drivers/regulator/tps65132-regulator.c index 6e22f5ebba2e..e302bd01a084 100644 --- a/drivers/regulator/tps65132-regulator.c +++ b/drivers/regulator/tps65132-regulator.c @@ -138,7 +138,7 @@ static int tps65132_of_parse_cb(struct device_node *np, rpdata->en_gpiod = devm_fwnode_get_index_gpiod_from_child(tps->dev, "enable", 0, &np->fwnode, 0, "enable"); - if (IS_ERR(rpdata->en_gpiod)) { + if (IS_ERR_OR_NULL(rpdata->en_gpiod)) { ret = PTR_ERR(rpdata->en_gpiod); /* Ignore the error other than probe defer */ @@ -150,7 +150,7 @@ static int tps65132_of_parse_cb(struct device_node *np, rpdata->act_dis_gpiod = devm_fwnode_get_index_gpiod_from_child( tps->dev, "active-discharge", 0, &np->fwnode, 0, "active-discharge"); - if (IS_ERR(rpdata->act_dis_gpiod)) { + if (IS_ERR_OR_NULL(rpdata->act_dis_gpiod)) { ret = PTR_ERR(rpdata->act_dis_gpiod); /* Ignore the error other than probe defer */ From 6cbe29c92311ea6ef67a7eac2bc089357412973b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 6 Sep 2019 14:06:32 +0100 Subject: [PATCH 43/52] regulator: lp8788-ldo: make array en_mask static const, makes object smaller Don't populate the array en_mask on the stack but instead make it static const. Makes the object code smaller by 87 bytes. Before: text data bss dec hex filename 12967 3408 0 16375 3ff7 drivers/regulator/lp8788-ldo.o After: text data bss dec hex filename 12816 3472 0 16288 3fa0 drivers/regulator/lp8788-ldo.o (gcc version 9.2.1, amd64) Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190906130632.6709-1-colin.king@canonical.com Signed-off-by: Mark Brown --- drivers/regulator/lp8788-ldo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c index 1b00f3638996..00e9bb92c326 100644 --- a/drivers/regulator/lp8788-ldo.c +++ b/drivers/regulator/lp8788-ldo.c @@ -464,7 +464,7 @@ static int lp8788_config_ldo_enable_mode(struct platform_device *pdev, { struct lp8788 *lp = ldo->lp; enum lp8788_ext_ldo_en_id enable_id; - u8 en_mask[] = { + static const u8 en_mask[] = { [EN_ALDO1] = LP8788_EN_SEL_ALDO1_M, [EN_ALDO234] = LP8788_EN_SEL_ALDO234_M, [EN_ALDO5] = LP8788_EN_SEL_ALDO5_M, From c0b913447b75538c3cf4b8016fd2e06509895020 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 4 Sep 2019 14:42:00 -0700 Subject: [PATCH 44/52] regulator: slg51000: use devm_gpiod_get_optional() in probe The CS GPIO line is clearly optional GPIO (and marked as such in the binding document) and we should handle it accordingly. The current code treats all errors as meaning that there is no GPIO defined, which is wrong, as it does not handle deferrals raised by the underlying code properly, nor does it recognize non-existing GPIO from any other initialization error. As far as I can see the only reason the driver, unlike all others, is using OF-specific devm_gpiod_get_from_of_node() so that it can assign a custom label to the selected GPIO line. Given that noone else needs that, it should not be doing that either. Let's switch to using more appropriate devm_gpiod_get_optional(). Signed-off-by: Dmitry Torokhov Link: https://lore.kernel.org/r/20190904214200.GA66118@dtor-ws Signed-off-by: Mark Brown --- drivers/regulator/slg51000-regulator.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/slg51000-regulator.c b/drivers/regulator/slg51000-regulator.c index 4d859fef55e6..a0565daecace 100644 --- a/drivers/regulator/slg51000-regulator.c +++ b/drivers/regulator/slg51000-regulator.c @@ -447,19 +447,20 @@ static int slg51000_i2c_probe(struct i2c_client *client, { struct device *dev = &client->dev; struct slg51000 *chip; - struct gpio_desc *cs_gpiod = NULL; + struct gpio_desc *cs_gpiod; int error, ret; chip = devm_kzalloc(dev, sizeof(struct slg51000), GFP_KERNEL); if (!chip) return -ENOMEM; - cs_gpiod = devm_gpiod_get_from_of_node(dev, dev->of_node, - "dlg,cs-gpios", 0, - GPIOD_OUT_HIGH - | GPIOD_FLAGS_BIT_NONEXCLUSIVE, - "slg51000-cs"); - if (!IS_ERR(cs_gpiod)) { + cs_gpiod = devm_gpiod_get_optional(dev, "dlg,cs", + GPIOD_OUT_HIGH | + GPIOD_FLAGS_BIT_NONEXCLUSIVE); + if (IS_ERR(cs_gpiod)) + return PTR_ERR(cs_gpiod); + + if (cs_gpiod) { dev_info(dev, "Found chip selector property\n"); chip->cs_gpiod = cs_gpiod; } From 6cadd8ae213678be654042ff8655630d84272ec3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 8 Sep 2019 11:57:20 +0800 Subject: [PATCH 45/52] regulator: lp87565: Simplify lp87565_buck_set_ramp_delay Use rdev->regmap/&rdev->dev instead of lp87565->regmap/lp87565->dev. In additional, the lp87565->dev actually is the parent mfd device, so the dev_err message is misleading here with lp87565->dev. Signed-off-by: Axel Lin Link: https://lore.kernel.org/r/20190908035720.17748-1-axel.lin@ingics.com Signed-off-by: Mark Brown --- drivers/regulator/lp87565-regulator.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/lp87565-regulator.c b/drivers/regulator/lp87565-regulator.c index 0c440c5e2832..4ae12ac1f4c6 100644 --- a/drivers/regulator/lp87565-regulator.c +++ b/drivers/regulator/lp87565-regulator.c @@ -65,7 +65,6 @@ static int lp87565_buck_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) { int id = rdev_get_id(rdev); - struct lp87565 *lp87565 = rdev_get_drvdata(rdev); unsigned int reg; int ret; @@ -86,11 +85,11 @@ static int lp87565_buck_set_ramp_delay(struct regulator_dev *rdev, else reg = 0; - ret = regmap_update_bits(lp87565->regmap, regulators[id].ctrl2_reg, + ret = regmap_update_bits(rdev->regmap, regulators[id].ctrl2_reg, LP87565_BUCK_CTRL_2_SLEW_RATE, reg << __ffs(LP87565_BUCK_CTRL_2_SLEW_RATE)); if (ret) { - dev_err(lp87565->dev, "SLEW RATE write failed: %d\n", ret); + dev_err(&rdev->dev, "SLEW RATE write failed: %d\n", ret); return ret; } From d57d90f4443bd725b3facdc6130a1940af4560c4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 9 Sep 2019 17:57:23 +0200 Subject: [PATCH 46/52] regulator: s2mps11: Consistently use local variable The value under 's2mps11->ext_control_gpiod[i]' is assigned to local variable and used in probe in one place before. Use it consistently later so code will be easier to read. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20190909155723.24734-1-krzk@kernel.org Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 054baaadfdfd..5bc00884cf51 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -1226,7 +1226,7 @@ common_reg: goto out; } - if (s2mps11->ext_control_gpiod[i]) { + if (config.ena_gpiod) { ret = s2mps14_pmic_enable_ext_control(s2mps11, regulator); if (ret < 0) { From 8959e5324485ace9bedc33ce1e760b759d4dd2ac Mon Sep 17 00:00:00 2001 From: Philippe Schenker Date: Tue, 10 Sep 2019 06:21:15 +0000 Subject: [PATCH 47/52] regulator: fixed: add possibility to enable by clock This commit adds the possibility to choose the compatible "regulator-fixed-clock" in devicetree. This is a special regulator-fixed that has to have a clock, from which the regulator gets switched on and off. Signed-off-by: Philippe Schenker Link: https://lore.kernel.org/r/20190910062103.39641-2-philippe.schenker@toradex.com Signed-off-by: Mark Brown --- drivers/regulator/fixed.c | 83 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 999547dde99d..d90a6fd8cbc7 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -23,14 +23,63 @@ #include #include #include +#include #include #include +#include + struct fixed_voltage_data { struct regulator_desc desc; struct regulator_dev *dev; + + struct clk *enable_clock; + unsigned int clk_enable_counter; }; +struct fixed_dev_type { + bool has_enable_clock; +}; + +static const struct fixed_dev_type fixed_voltage_data = { + .has_enable_clock = false, +}; + +static const struct fixed_dev_type fixed_clkenable_data = { + .has_enable_clock = true, +}; + +static int reg_clock_enable(struct regulator_dev *rdev) +{ + struct fixed_voltage_data *priv = rdev_get_drvdata(rdev); + int ret = 0; + + ret = clk_prepare_enable(priv->enable_clock); + if (ret) + return ret; + + priv->clk_enable_counter++; + + return ret; +} + +static int reg_clock_disable(struct regulator_dev *rdev) +{ + struct fixed_voltage_data *priv = rdev_get_drvdata(rdev); + + clk_disable_unprepare(priv->enable_clock); + priv->clk_enable_counter--; + + return 0; +} + +static int reg_clock_is_enabled(struct regulator_dev *rdev) +{ + struct fixed_voltage_data *priv = rdev_get_drvdata(rdev); + + return priv->clk_enable_counter > 0; +} + /** * of_get_fixed_voltage_config - extract fixed_voltage_config structure info @@ -84,10 +133,19 @@ of_get_fixed_voltage_config(struct device *dev, static struct regulator_ops fixed_voltage_ops = { }; +static struct regulator_ops fixed_voltage_clkenabled_ops = { + .enable = reg_clock_enable, + .disable = reg_clock_disable, + .is_enabled = reg_clock_is_enabled, +}; + static int reg_fixed_voltage_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct fixed_voltage_config *config; struct fixed_voltage_data *drvdata; + const struct fixed_dev_type *drvtype = + of_match_device(dev->driver->of_match_table, dev)->data; struct regulator_config cfg = { }; enum gpiod_flags gflags; int ret; @@ -118,7 +176,18 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) } drvdata->desc.type = REGULATOR_VOLTAGE; drvdata->desc.owner = THIS_MODULE; - drvdata->desc.ops = &fixed_voltage_ops; + + if (drvtype->has_enable_clock) { + drvdata->desc.ops = &fixed_voltage_clkenabled_ops; + + drvdata->enable_clock = devm_clk_get(dev, NULL); + if (IS_ERR(drvdata->enable_clock)) { + dev_err(dev, "Cant get enable-clock from devicetree\n"); + return -ENOENT; + } + } else { + drvdata->desc.ops = &fixed_voltage_ops; + } drvdata->desc.enable_time = config->startup_delay; @@ -191,8 +260,16 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) #if defined(CONFIG_OF) static const struct of_device_id fixed_of_match[] = { - { .compatible = "regulator-fixed", }, - {}, + { + .compatible = "regulator-fixed", + .data = &fixed_voltage_data, + }, + { + .compatible = "regulator-fixed-clock", + .data = &fixed_clkenable_data, + }, + { + }, }; MODULE_DEVICE_TABLE(of, fixed_of_match); #endif From 9c86d003d62030e064f5670fb6172b65afd21e86 Mon Sep 17 00:00:00 2001 From: Philippe Schenker Date: Tue, 10 Sep 2019 06:21:19 +0000 Subject: [PATCH 48/52] dt-bindings: regulator: add regulator-fixed-clock binding This adds the documentation to the compatible regulator-fixed-clock. This binding is a special binding of regulator-fixed and adds the ability to add a clock to regulator-fixed, so the regulator can be enabled and disabled with that clock. If the special compatible regulator-fixed-clock is used it is mandatory to supply a clock. Signed-off-by: Philippe Schenker Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20190910062103.39641-4-philippe.schenker@toradex.com Signed-off-by: Mark Brown --- .../bindings/regulator/fixed-regulator.yaml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml b/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml index a650b457085d..a78150c47aa2 100644 --- a/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/fixed-regulator.yaml @@ -19,9 +19,19 @@ description: allOf: - $ref: "regulator.yaml#" +if: + properties: + compatible: + contains: + const: regulator-fixed-clock + required: + - clocks + properties: compatible: - const: regulator-fixed + enum: + - const: regulator-fixed + - const: regulator-fixed-clock regulator-name: true @@ -29,6 +39,13 @@ properties: description: gpio to use for enable control maxItems: 1 + clocks: + description: + clock to use for enable control. This binding is only available if + the compatible is chosen to regulator-fixed-clock. The clock binding + is mandatory if compatible is chosen to regulator-fixed-clock. + maxItems: 1 + startup-delay-us: description: startup time in microseconds $ref: /schemas/types.yaml#/definitions/uint32 From 3ba5368dc4e5947cb70287754960776c471eb23d Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Tue, 10 Sep 2019 10:51:44 +0900 Subject: [PATCH 49/52] regulator: uniphier: Add Pro5 USB3 VBUS support Pro5 SoC has same scheme of USB3 VBUS as Pro4, so the data for Pro5 is equivalent to Pro4. Signed-off-by: Kunihiko Hayashi Link: https://lore.kernel.org/r/1568080304-1572-1-git-send-email-hayashi.kunihiko@socionext.com Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/uniphier-regulator.txt | 5 +++-- drivers/regulator/uniphier-regulator.c | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/uniphier-regulator.txt b/Documentation/devicetree/bindings/regulator/uniphier-regulator.txt index c9919f4b92d2..94fd38b0d163 100644 --- a/Documentation/devicetree/bindings/regulator/uniphier-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/uniphier-regulator.txt @@ -13,6 +13,7 @@ this layer. These clocks and resets should be described in each property. Required properties: - compatible: Should be "socionext,uniphier-pro4-usb3-regulator" - for Pro4 SoC + "socionext,uniphier-pro5-usb3-regulator" - for Pro5 SoC "socionext,uniphier-pxs2-usb3-regulator" - for PXs2 SoC "socionext,uniphier-ld20-usb3-regulator" - for LD20 SoC "socionext,uniphier-pxs3-usb3-regulator" - for PXs3 SoC @@ -20,12 +21,12 @@ Required properties: - clocks: A list of phandles to the clock gate for USB3 glue layer. According to the clock-names, appropriate clocks are required. - clock-names: Should contain - "gio", "link" - for Pro4 SoC + "gio", "link" - for Pro4 and Pro5 SoCs "link" - for others - resets: A list of phandles to the reset control for USB3 glue layer. According to the reset-names, appropriate resets are required. - reset-names: Should contain - "gio", "link" - for Pro4 SoC + "gio", "link" - for Pro4 and Pro5 SoCs "link" - for others See Documentation/devicetree/bindings/regulator/regulator.txt diff --git a/drivers/regulator/uniphier-regulator.c b/drivers/regulator/uniphier-regulator.c index 9026d5a3e964..2311924c3103 100644 --- a/drivers/regulator/uniphier-regulator.c +++ b/drivers/regulator/uniphier-regulator.c @@ -185,6 +185,10 @@ static const struct of_device_id uniphier_regulator_match[] = { .compatible = "socionext,uniphier-pro4-usb3-regulator", .data = &uniphier_pro4_usb3_data, }, + { + .compatible = "socionext,uniphier-pro5-usb3-regulator", + .data = &uniphier_pro4_usb3_data, + }, { .compatible = "socionext,uniphier-pxs2-usb3-regulator", .data = &uniphier_pxs2_usb3_data, From 2418f749641caa59d5bc01b66ba16ec5414b28dc Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 10 Sep 2019 10:00:50 -0700 Subject: [PATCH 50/52] regulator: max77686: fix obtaining "maxim,ena" GPIO This fixes 96392c3d8ca4, as devm_gpiod_get_from_of_node() does not do translation "con-id" -> "con-id-gpios" that our bindings expects, and therefore it was wrong to change connection ID to be simply "maxim,ena" when moving to using devm_gpiod_get_from_of_node(). Fixes: 96392c3d8ca4 ("regulator: max77686: Pass descriptor instead of GPIO number") Signed-off-by: Dmitry Torokhov Link: https://lore.kernel.org/r/20190910170050.GA55530@dtor-ws Signed-off-by: Mark Brown --- drivers/regulator/max77686-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/max77686-regulator.c b/drivers/regulator/max77686-regulator.c index 8020eb57374a..c8e579e99316 100644 --- a/drivers/regulator/max77686-regulator.c +++ b/drivers/regulator/max77686-regulator.c @@ -257,7 +257,7 @@ static int max77686_of_parse_cb(struct device_node *np, case MAX77686_BUCK9: case MAX77686_LDO20 ... MAX77686_LDO22: config->ena_gpiod = gpiod_get_from_of_node(np, - "maxim,ena", + "maxim,ena-gpios", 0, GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE, "max77686-regulator"); From 5eda8e95b7922cb9dd1343f7beece3cd78565216 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 10 Sep 2019 10:02:46 -0700 Subject: [PATCH 51/52] regulator: da9211: fix obtaining "enable" GPIO This fixes 11da04af0d3b, as devm_gpiod_get_from_of_node() does not do translation "con-id" -> "con-id-gpios" that our bindings expects, and therefore it was wrong to change connection ID to be simply "enable" when moving to using devm_gpiod_get_from_of_node(). Fixes: 11da04af0d3b ("regulator: da9211: Pass descriptors instead of GPIO numbers") Signed-off-by: Dmitry Torokhov Link: https://lore.kernel.org/r/20190910170246.GA56792@dtor-ws Signed-off-by: Mark Brown --- drivers/regulator/da9211-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c index 0309823d2c72..bf80748f1ccc 100644 --- a/drivers/regulator/da9211-regulator.c +++ b/drivers/regulator/da9211-regulator.c @@ -285,7 +285,7 @@ static struct da9211_pdata *da9211_parse_regulators_dt( pdata->reg_node[n] = da9211_matches[i].of_node; pdata->gpiod_ren[n] = devm_gpiod_get_from_of_node(dev, da9211_matches[i].of_node, - "enable", + "enable-gpios", 0, GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE, "da9211-enable"); From c82f27df07573ec7b124efe176d2ac6c038787a5 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Tue, 10 Sep 2019 21:22:29 +0200 Subject: [PATCH 52/52] regulator: core: Fix error return for /sys access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit regulator_uV_show() is missing error handling if regulator_get_voltage_rdev() returns negative values. Instead it prints the errno as a string, e.g. -EINVAL as "-22" which could be interpreted as -22 µV. We also do not need to hold the lock while converting the integer to a string. Reported-by: Adam Ford Signed-off-by: H. Nikolaus Schaller Tested-by: Adam Ford Link: https://lore.kernel.org/r/f37f2a1276efcb34cf3b7f1a25481175be048806.1568143348.git.hns@goldelico.com Signed-off-by: Mark Brown --- drivers/regulator/core.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 340db986b67f..afe94470b67f 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -568,13 +568,15 @@ static ssize_t regulator_uV_show(struct device *dev, struct device_attribute *attr, char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); - ssize_t ret; + int uV; regulator_lock(rdev); - ret = sprintf(buf, "%d\n", regulator_get_voltage_rdev(rdev)); + uV = regulator_get_voltage_rdev(rdev); regulator_unlock(rdev); - return ret; + if (uV < 0) + return uV; + return sprintf(buf, "%d\n", uV); } static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL);