From 692fab0820520f5a400446ab3016a237dca32109 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Wed, 2 Nov 2022 10:07:16 +0800 Subject: regulator: docs: add missing helper Add missing devm_regulator_bulk_get_const() to devres.rst, it's introduced by commit 1de452a0edda ("regulator: core: Allow drivers to define their init data as const"). Fixes: 1de452a0edda ("regulator: core: Allow drivers to define their init data as const") Cc: Liam Girdwood Cc: Mark Brown Cc: Douglas Anderson Cc: Jonathan Corbet Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20221102020716.1397449-1-yangyingliang@huawei.com Signed-off-by: Mark Brown --- Documentation/driver-api/driver-model/devres.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst index 687adb58048e..ff8158274fb3 100644 --- a/Documentation/driver-api/driver-model/devres.rst +++ b/Documentation/driver-api/driver-model/devres.rst @@ -408,6 +408,7 @@ PWM REGULATOR devm_regulator_bulk_register_supply_alias() devm_regulator_bulk_get() + devm_regulator_bulk_get_const() devm_regulator_bulk_get_enable() devm_regulator_bulk_put() devm_regulator_get() -- cgit v1.2.3 From 8facce4349d46fbc2ac4f6da3786130ddd104440 Mon Sep 17 00:00:00 2001 From: ChiYuan Huang Date: Mon, 31 Oct 2022 10:28:53 +0800 Subject: regulator: Add bindings for Richtek RT6190 regulator Add devicetree binding for Richtek RT6190 4-Switch buckboost controller. Signed-off-by: ChiYuan Huang Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/1667183334-16511-2-git-send-email-u0084500@gmail.com Signed-off-by: Mark Brown --- .../bindings/regulator/richtek,rt6190.yaml | 79 ++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 Documentation/devicetree/bindings/regulator/richtek,rt6190.yaml diff --git a/Documentation/devicetree/bindings/regulator/richtek,rt6190.yaml b/Documentation/devicetree/bindings/regulator/richtek,rt6190.yaml new file mode 100644 index 000000000000..29f7d3d5d658 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/richtek,rt6190.yaml @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/richtek,rt6190.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Richtek RT6190 4-Switch BuckBoost controller + +maintainers: + - ChiYuan Huang + +description: | + The RT6190 is 4-Switch BuckBoost controller designed for converting input + voltage to output voltage that can be equal to, higher or lower than input + voltage. It operates with wide input voltage range from 4.5V to 36V, and + the output voltage can be set from 3V to 36V by external FB pin. It's commonly + used for the application like as BuckBoost bus supply, docking station and USB + power delivery product. + + Datasheet is available at + https://www.richtek.com/assets/product_file/RT6190/DS6190-02.pdf + +allOf: + - $ref: regulator.yaml# + +properties: + compatible: + enum: + - richtek,rt6190 + + reg: + maxItems: 1 + + enable-gpios: + maxItems: 1 + + wakeup-source: true + + interrupts: + maxItems: 1 + + regulator-allowed-modes: + description: | + buck allowed operating mode + 0: PSM mode (light load Power Saving Mode) + 1: FCCM mode (Forced-CCM mode) + maxItems: 2 + items: + enum: [0, 1] + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + #include + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + regulator@2c { + compatible = "richtek,rt6190"; + reg = <0x2c>; + wakeup-source; + interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>; + enable-gpios = <&gpio26 1 GPIO_ACTIVE_HIGH>; + regulator-name = "richtek,rt6190-buckboost"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <32000000>; + regulator-min-microamp = <306000>; + regulator-max-microamp = <12114000>; + regulator-allowed-modes = <0 1>; + }; + }; -- cgit v1.2.3 From e6999e7cca7eecd64c27dc72c51d11cb33079a0c Mon Sep 17 00:00:00 2001 From: ChiYuan Huang Date: Mon, 31 Oct 2022 10:28:54 +0800 Subject: regulator: rt6190: Add support for Richtek RT6190 regulator Add support for Richtek RT6190 4-Switch BuckBoost controller. Signed-off-by: ChiYuan Huang Link: https://lore.kernel.org/r/1667183334-16511-3-git-send-email-u0084500@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 11 + drivers/regulator/Makefile | 1 + drivers/regulator/rt6190-regulator.c | 495 +++++++++++++++++++++++++++++++++++ 3 files changed, 507 insertions(+) create mode 100644 drivers/regulator/rt6190-regulator.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 070e4403c6c2..4e4614d70bde 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -1124,6 +1124,17 @@ config REGULATOR_RT6160 The wide output range is from 2025mV to 5200mV and can be used on most common application scenario. +config REGULATOR_RT6190 + tristate "Richtek RT6190 4-Switch BuckBoost controller" + depends on I2C + select REGMAP_I2C + help + The RT6190 is a 4-Switch BuckBoost controller designed for converting + input voltage to output voltage that can be equal to, higher or lower + than input voltage. It operates with wide input voltage range from + 4.5V to 36V, and the output voltage can be set from 3V to 36V by + external FB pin. + config REGULATOR_RT6245 tristate "Richtek RT6245 voltage regulator" depends on I2C diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 5962307e1130..c3b5cf6cceab 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -134,6 +134,7 @@ obj-$(CONFIG_REGULATOR_RT5120) += rt5120-regulator.o obj-$(CONFIG_REGULATOR_RT5190A) += rt5190a-regulator.o obj-$(CONFIG_REGULATOR_RT5759) += rt5759-regulator.o obj-$(CONFIG_REGULATOR_RT6160) += rt6160-regulator.o +obj-$(CONFIG_REGULATOR_RT6190) += rt6190-regulator.o obj-$(CONFIG_REGULATOR_RT6245) += rt6245-regulator.o obj-$(CONFIG_REGULATOR_RTMV20) += rtmv20-regulator.o obj-$(CONFIG_REGULATOR_RTQ2134) += rtq2134-regulator.o diff --git a/drivers/regulator/rt6190-regulator.c b/drivers/regulator/rt6190-regulator.c new file mode 100644 index 000000000000..995e028abdd7 --- /dev/null +++ b/drivers/regulator/rt6190-regulator.c @@ -0,0 +1,495 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022 Richtek Technology Corp. + * + * Author: ChiYuan Huang + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RT6190_REG_VID 0x00 +#define RT6190_REG_OUTV 0x01 +#define RT6190_REG_OUTC 0x03 +#define RT6190_REG_SET1 0x0D +#define RT6190_REG_SET2 0x0E +#define RT6190_REG_SET4 0x10 +#define RT6190_REG_RATIO 0x11 +#define RT6190_REG_OUT_VOLT_L 0x12 +#define RT6190_REG_TEMP_H 0x1B +#define RT6190_REG_STAT1 0x1C +#define RT6190_REG_ALERT1 0x1E +#define RT6190_REG_ALERT2 0x1F +#define RT6190_REG_MASK2 0x21 +#define RT6190_REG_OCPEN 0x28 +#define RT6190_REG_SET5 0x29 +#define RT6190_REG_VBUSC_ADC 0x32 +#define RT6190_REG_BUSC_VOLT_L 0x33 +#define RT6190_REG_BUSC_VOLT_H 0x34 +#define RT6190_REG_STAT3 0x37 +#define RT6190_REG_ALERT3 0x38 +#define RT6190_REG_MASK3 0x39 + +#define RT6190_ENPWM_MASK BIT(7) +#define RT6190_ENDCHG_MASK BIT(4) +#define RT6190_ALERT_OTPEVT BIT(6) +#define RT6190_ALERT_UVPEVT BIT(5) +#define RT6190_ALERT_OVPEVT BIT(4) +#define RT6190_ENGCP_MASK BIT(1) +#define RT6190_FCCM_MASK BIT(7) + +#define RICHTEK_VID 0x82 +#define RT6190_OUT_MIN_UV 3000000 +#define RT6190_OUT_MAX_UV 32000000 +#define RT6190_OUT_STEP_UV 20000 +#define RT6190_OUT_N_VOLT (RT6190_OUT_MAX_UV / RT6190_OUT_STEP_UV + 1) +#define RT6190_OUTV_MINSEL 150 +#define RT6190_OUT_MIN_UA 306000 +#define RT6190_OUT_MAX_UA 12114000 +#define RT6190_OUT_STEP_UA 24000 +#define RT6190_OUTC_MINSEL 19 +#define RT6190_EN_TIME_US 500 + +#define RT6190_PSM_MODE 0 +#define RT6190_FCCM_MODE 1 + +struct rt6190_data { + struct device *dev; + struct regmap *regmap; + struct gpio_desc *enable_gpio; + unsigned int cached_alert_evt; +}; + +static int rt6190_out_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) +{ + struct regmap *regmap = rdev_get_regmap(rdev); + __le16 le_sel = cpu_to_le16(selector); + + return regmap_raw_write(regmap, RT6190_REG_OUTV, &le_sel, + sizeof(le_sel)); +} + +static int rt6190_out_get_voltage_sel(struct regulator_dev *rdev) +{ + struct regmap *regmap = rdev_get_regmap(rdev); + __le16 le_sel; + int ret; + + ret = regmap_raw_read(regmap, RT6190_REG_OUTV, &le_sel, sizeof(le_sel)); + + return ret ?: le16_to_cpu(le_sel); +} + +static int rt6190_out_enable(struct regulator_dev *rdev) +{ + struct rt6190_data *data = rdev_get_drvdata(rdev); + struct regmap *regmap = rdev_get_regmap(rdev); + u8 out_cfg[4]; + int ret; + + pm_runtime_get_sync(data->dev); + + /* + * From off to on, vout config will restore to IC default. + * Read vout configs before enable, and restore them after enable + */ + ret = regmap_raw_read(regmap, RT6190_REG_OUTV, out_cfg, + sizeof(out_cfg)); + if (ret) + return ret; + + ret = regulator_enable_regmap(rdev); + if (ret) + return ret; + + ret = regmap_raw_write(regmap, RT6190_REG_OUTV, out_cfg, + sizeof(out_cfg)); + if (ret) + return ret; + + return regmap_update_bits(regmap, RT6190_REG_SET5, RT6190_ENGCP_MASK, + RT6190_ENGCP_MASK); +} + +static int rt6190_out_disable(struct regulator_dev *rdev) +{ + struct rt6190_data *data = rdev_get_drvdata(rdev); + struct regmap *regmap = rdev_get_regmap(rdev); + int ret; + + ret = regmap_update_bits(regmap, RT6190_REG_SET5, RT6190_ENGCP_MASK, 0); + if (ret) + return ret; + + ret = regulator_disable_regmap(rdev); + if (ret) + return ret; + + /* cleared cached alert event */ + data->cached_alert_evt = 0; + + pm_runtime_put(data->dev); + + return 0; +} + +static int rt6190_out_set_current_limit(struct regulator_dev *rdev, int min_uA, + int max_uA) +{ + struct regmap *regmap = rdev_get_regmap(rdev); + int csel, clim; + __le16 le_csel; + + if (min_uA < RT6190_OUT_MIN_UA || max_uA > RT6190_OUT_MAX_UA) + return -EINVAL; + + csel = DIV_ROUND_UP(min_uA - RT6190_OUT_MIN_UA, RT6190_OUT_STEP_UA); + + clim = RT6190_OUT_MIN_UA + RT6190_OUT_STEP_UA * csel; + if (clim > max_uA) + return -EINVAL; + + csel += RT6190_OUTC_MINSEL; + le_csel = cpu_to_le16(csel); + + return regmap_raw_write(regmap, RT6190_REG_OUTC, &le_csel, + sizeof(le_csel)); +} + +static int rt6190_out_get_current_limit(struct regulator_dev *rdev) +{ + struct regmap *regmap = rdev_get_regmap(rdev); + __le16 le_csel; + int csel, ret; + + ret = regmap_raw_read(regmap, RT6190_REG_OUTC, &le_csel, + sizeof(le_csel)); + if (ret) + return ret; + + csel = le16_to_cpu(le_csel); + csel -= RT6190_OUTC_MINSEL; + + return RT6190_OUT_MIN_UA + RT6190_OUT_STEP_UA * csel; +} + +static int rt6190_out_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + struct regmap *regmap = rdev_get_regmap(rdev); + unsigned int val; + + switch (mode) { + case REGULATOR_MODE_FAST: + val = RT6190_FCCM_MASK; + break; + case REGULATOR_MODE_NORMAL: + val = 0; + break; + default: + return -EINVAL; + } + + return regmap_update_bits(regmap, RT6190_REG_SET1, RT6190_FCCM_MASK, + val); +} + +static unsigned int rt6190_out_get_mode(struct regulator_dev *rdev) +{ + struct regmap *regmap = rdev_get_regmap(rdev); + unsigned int config; + int ret; + + ret = regmap_read(regmap, RT6190_REG_SET1, &config); + if (ret) + return REGULATOR_MODE_INVALID; + + if (config & RT6190_FCCM_MASK) + return REGULATOR_MODE_FAST; + + return REGULATOR_MODE_NORMAL; +} + +static int rt6190_out_get_error_flags(struct regulator_dev *rdev, + unsigned int *flags) +{ + struct rt6190_data *data = rdev_get_drvdata(rdev); + unsigned int state, rpt_flags = 0; + int ret; + + ret = regmap_read(data->regmap, RT6190_REG_STAT1, &state); + if (ret) + return ret; + + state |= data->cached_alert_evt; + + if (state & RT6190_ALERT_OTPEVT) + rpt_flags |= REGULATOR_ERROR_OVER_TEMP; + + if (state & RT6190_ALERT_UVPEVT) + rpt_flags |= REGULATOR_ERROR_UNDER_VOLTAGE; + + if (state & RT6190_ALERT_OVPEVT) + rpt_flags |= REGULATOR_ERROR_REGULATION_OUT; + + *flags = rpt_flags; + + return 0; +} + +static unsigned int rt6190_out_of_map_mode(unsigned int mode) +{ + switch (mode) { + case RT6190_PSM_MODE: + return REGULATOR_MODE_NORMAL; + case RT6190_FCCM_MODE: + return REGULATOR_MODE_FAST; + default: + return REGULATOR_MODE_INVALID; + } +} + +static const struct regulator_ops rt6190_regulator_ops = { + .list_voltage = regulator_list_voltage_linear, + .set_voltage_sel = rt6190_out_set_voltage_sel, + .get_voltage_sel = rt6190_out_get_voltage_sel, + .enable = rt6190_out_enable, + .disable = rt6190_out_disable, + .is_enabled = regulator_is_enabled_regmap, + .set_current_limit = rt6190_out_set_current_limit, + .get_current_limit = rt6190_out_get_current_limit, + .set_active_discharge = regulator_set_active_discharge_regmap, + .set_mode = rt6190_out_set_mode, + .get_mode = rt6190_out_get_mode, + .get_error_flags = rt6190_out_get_error_flags, +}; + +static const struct regulator_desc rt6190_regulator_desc = { + .name = "rt6190-regulator", + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .ops = &rt6190_regulator_ops, + .min_uV = RT6190_OUT_MIN_UV, + .uV_step = RT6190_OUT_STEP_UV, + .n_voltages = RT6190_OUT_N_VOLT, + .linear_min_sel = RT6190_OUTV_MINSEL, + .enable_reg = RT6190_REG_SET2, + .enable_mask = RT6190_ENPWM_MASK, + .active_discharge_reg = RT6190_REG_SET2, + .active_discharge_mask = RT6190_ENDCHG_MASK, + .active_discharge_on = RT6190_ENDCHG_MASK, + .of_map_mode = rt6190_out_of_map_mode, +}; + +static bool rt6190_is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT6190_REG_OUT_VOLT_L ... RT6190_REG_ALERT2: + case RT6190_REG_BUSC_VOLT_L ... RT6190_REG_BUSC_VOLT_H: + case RT6190_REG_STAT3 ... RT6190_REG_ALERT3: + return true; + default: + return false; + } +} + +static const struct regmap_config rt6190_regmap_config = { + .name = "rt6190", + .cache_type = REGCACHE_FLAT, + .reg_bits = 8, + .val_bits = 8, + .max_register = RT6190_REG_MASK3, + .num_reg_defaults_raw = RT6190_REG_MASK3 + 1, + .volatile_reg = rt6190_is_volatile_reg, +}; + +static irqreturn_t rt6190_irq_handler(int irq, void *devid) +{ + struct regulator_dev *rdev = devid; + struct rt6190_data *data = rdev_get_drvdata(rdev); + unsigned int alert; + int ret; + + ret = regmap_read(data->regmap, RT6190_REG_ALERT1, &alert); + if (ret) + return IRQ_NONE; + + /* Write clear alert events */ + ret = regmap_write(data->regmap, RT6190_REG_ALERT1, alert); + if (ret) + return IRQ_NONE; + + data->cached_alert_evt |= alert; + + if (alert & RT6190_ALERT_OTPEVT) + regulator_notifier_call_chain(rdev, REGULATOR_EVENT_OVER_TEMP, NULL); + + if (alert & RT6190_ALERT_UVPEVT) + regulator_notifier_call_chain(rdev, REGULATOR_EVENT_UNDER_VOLTAGE, NULL); + + if (alert & RT6190_ALERT_OVPEVT) + regulator_notifier_call_chain(rdev, REGULATOR_EVENT_REGULATION_OUT, NULL); + + return IRQ_HANDLED; +} + +static int rt6190_init_registers(struct regmap *regmap) +{ + int ret; + + /* Enable_ADC = 1 */ + ret = regmap_write(regmap, RT6190_REG_SET4, 0x82); + if (ret) + return ret; + + /* Config default VOUT ratio to be higher */ + ret = regmap_write(regmap, RT6190_REG_RATIO, 0x20); + + /* Mask unused alert */ + ret = regmap_write(regmap, RT6190_REG_MASK2, 0); + if (ret) + return ret; + + /* OCP config */ + ret = regmap_write(regmap, RT6190_REG_OCPEN, 0); + if (ret) + return ret; + + /* Enable VBUSC ADC */ + return regmap_write(regmap, RT6190_REG_VBUSC_ADC, 0x02); +} + +static int rt6190_probe(struct i2c_client *i2c) +{ + struct device *dev = &i2c->dev; + struct rt6190_data *data; + struct gpio_desc *enable_gpio; + struct regmap *regmap; + struct regulator_dev *rdev; + struct regulator_config cfg = {}; + unsigned int vid; + int ret; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH); + if (IS_ERR(enable_gpio)) + return dev_err_probe(dev, PTR_ERR(enable_gpio), "Failed to get 'enable' gpio\n"); + else if (enable_gpio) + usleep_range(RT6190_EN_TIME_US, RT6190_EN_TIME_US * 2); + + regmap = devm_regmap_init_i2c(i2c, &rt6190_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), "Failed to init regmap\n"); + + data->dev = dev; + data->enable_gpio = enable_gpio; + data->regmap = regmap; + i2c_set_clientdata(i2c, data); + + ret = regmap_read(regmap, RT6190_REG_VID, &vid); + if (ret) + return dev_err_probe(dev, ret, "Failed to read VID\n"); + + if (vid != RICHTEK_VID) + return dev_err_probe(dev, -ENODEV, "Incorrect VID 0x%02x\n", vid); + + ret = rt6190_init_registers(regmap); + if (ret) + return dev_err_probe(dev, ret, "Failed to init registers\n"); + + pm_runtime_set_active(dev); + ret = devm_pm_runtime_enable(dev); + if (ret) + return dev_err_probe(dev, ret, "Failed to set pm_runtime enable\n"); + + cfg.dev = dev; + cfg.of_node = dev->of_node; + cfg.driver_data = data; + cfg.init_data = of_get_regulator_init_data(dev, dev->of_node, + &rt6190_regulator_desc); + + rdev = devm_regulator_register(dev, &rt6190_regulator_desc, &cfg); + if (IS_ERR(rdev)) + return dev_err_probe(dev, PTR_ERR(rdev), "Failed to register regulator\n"); + + if (i2c->irq) { + ret = devm_request_threaded_irq(dev, i2c->irq, NULL, + rt6190_irq_handler, + IRQF_ONESHOT, dev_name(dev), + rdev); + if (ret) + return dev_err_probe(dev, ret, "Failed to register interrupt\n"); + } + + return 0; +} + +static int rt6190_runtime_suspend(struct device *dev) +{ + struct rt6190_data *data = dev_get_drvdata(dev); + struct regmap *regmap = data->regmap; + + if (!data->enable_gpio) + return 0; + + regcache_cache_only(regmap, true); + regcache_mark_dirty(regmap); + + gpiod_set_value(data->enable_gpio, 0); + + return 0; +} + +static int rt6190_runtime_resume(struct device *dev) +{ + struct rt6190_data *data = dev_get_drvdata(dev); + struct regmap *regmap = data->regmap; + + if (!data->enable_gpio) + return 0; + + gpiod_set_value(data->enable_gpio, 1); + usleep_range(RT6190_EN_TIME_US, RT6190_EN_TIME_US * 2); + + regcache_cache_only(regmap, false); + return regcache_sync(regmap); +} + +static const struct dev_pm_ops __maybe_unused rt6190_dev_pm = { + RUNTIME_PM_OPS(rt6190_runtime_suspend, rt6190_runtime_resume, NULL) +}; + +static const struct of_device_id rt6190_of_dev_table[] = { + { .compatible = "richtek,rt6190" }, + {} +}; +MODULE_DEVICE_TABLE(of, rt6190_of_dev_table); + +static struct i2c_driver rt6190_driver = { + .driver = { + .name = "rt6190", + .of_match_table = rt6190_of_dev_table, + .pm = pm_ptr(&rt6190_dev_pm), + }, + .probe_new = rt6190_probe, +}; +module_i2c_driver(rt6190_driver); + +MODULE_DESCRIPTION("Richtek RT6190 regulator driver"); +MODULE_AUTHOR("ChiYuan Huang "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From fd1845069711cdf1b1aaaa0f22311b7736396331 Mon Sep 17 00:00:00 2001 From: Zev Weiss Date: Mon, 31 Oct 2022 16:37:02 -0700 Subject: regulator: devres: Add devm_regulator_bulk_get_exclusive() We had an exclusive variant of the devm_regulator_get() API, but no corresponding variant for the bulk API; let's add one now. We add a generalized version of the existing regulator_bulk_get() function that additionally takes a get_type parameter and redefine regulator_bulk_get() in terms of it, then do similarly with devm_regulator_bulk_get(), and finally add the new devm_regulator_bulk_get_exclusive(). Signed-off-by: Zev Weiss Link: https://lore.kernel.org/r/20221031233704.22575-2-zev@bewilderbeest.net Signed-off-by: Mark Brown --- drivers/regulator/core.c | 42 +++++++++++++----------- drivers/regulator/devres.c | 66 +++++++++++++++++++++++++++----------- drivers/regulator/internal.h | 2 ++ include/linux/regulator/consumer.h | 2 ++ 4 files changed, 76 insertions(+), 36 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index bcccad8f7516..704f91720dfe 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -4778,22 +4778,8 @@ static int _notifier_call_chain(struct regulator_dev *rdev, return blocking_notifier_call_chain(&rdev->notifier, event, data); } -/** - * regulator_bulk_get - get multiple regulator consumers - * - * @dev: Device to supply - * @num_consumers: Number of consumers to register - * @consumers: Configuration of consumers; clients are stored here. - * - * @return 0 on success, an errno on failure. - * - * This helper function allows drivers to get several regulator - * consumers in one operation. If any of the regulators cannot be - * acquired then any regulators that were allocated will be freed - * before returning to the caller. - */ -int regulator_bulk_get(struct device *dev, int num_consumers, - struct regulator_bulk_data *consumers) +int _regulator_bulk_get(struct device *dev, int num_consumers, + struct regulator_bulk_data *consumers, enum regulator_get_type get_type) { int i; int ret; @@ -4802,8 +4788,8 @@ int regulator_bulk_get(struct device *dev, int num_consumers, consumers[i].consumer = NULL; for (i = 0; i < num_consumers; i++) { - consumers[i].consumer = regulator_get(dev, - consumers[i].supply); + consumers[i].consumer = _regulator_get(dev, + consumers[i].supply, get_type); if (IS_ERR(consumers[i].consumer)) { ret = dev_err_probe(dev, PTR_ERR(consumers[i].consumer), "Failed to get supply '%s'", @@ -4830,6 +4816,26 @@ err: return ret; } + +/** + * regulator_bulk_get - get multiple regulator consumers + * + * @dev: Device to supply + * @num_consumers: Number of consumers to register + * @consumers: Configuration of consumers; clients are stored here. + * + * @return 0 on success, an errno on failure. + * + * This helper function allows drivers to get several regulator + * consumers in one operation. If any of the regulators cannot be + * acquired then any regulators that were allocated will be freed + * before returning to the caller. + */ +int regulator_bulk_get(struct device *dev, int num_consumers, + struct regulator_bulk_data *consumers) +{ + return _regulator_bulk_get(dev, num_consumers, consumers, NORMAL_GET); +} EXPORT_SYMBOL_GPL(regulator_bulk_get); static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c index 3265e75e97ab..fec0398d98b0 100644 --- a/drivers/regulator/devres.c +++ b/drivers/regulator/devres.c @@ -186,23 +186,9 @@ static void devm_regulator_bulk_release(struct device *dev, void *res) regulator_bulk_free(devres->num_consumers, devres->consumers); } -/** - * devm_regulator_bulk_get - managed get multiple regulator consumers - * - * @dev: device to supply - * @num_consumers: number of consumers to register - * @consumers: configuration of consumers; clients are stored here. - * - * @return 0 on success, an errno on failure. - * - * This helper function allows drivers to get several regulator - * consumers in one operation with management, the regulators will - * automatically be freed when the device is unbound. If any of the - * regulators cannot be acquired then any regulators that were - * allocated will be freed before returning to the caller. - */ -int devm_regulator_bulk_get(struct device *dev, int num_consumers, - struct regulator_bulk_data *consumers) +static int _devm_regulator_bulk_get(struct device *dev, int num_consumers, + struct regulator_bulk_data *consumers, + enum regulator_get_type get_type) { struct regulator_bulk_devres *devres; int ret; @@ -212,7 +198,7 @@ int devm_regulator_bulk_get(struct device *dev, int num_consumers, if (!devres) return -ENOMEM; - ret = regulator_bulk_get(dev, num_consumers, consumers); + ret = _regulator_bulk_get(dev, num_consumers, consumers, get_type); if (!ret) { devres->consumers = consumers; devres->num_consumers = num_consumers; @@ -223,8 +209,52 @@ int devm_regulator_bulk_get(struct device *dev, int num_consumers, return ret; } + +/** + * devm_regulator_bulk_get - managed get multiple regulator consumers + * + * @dev: device to supply + * @num_consumers: number of consumers to register + * @consumers: configuration of consumers; clients are stored here. + * + * @return 0 on success, an errno on failure. + * + * This helper function allows drivers to get several regulator + * consumers in one operation with management, the regulators will + * automatically be freed when the device is unbound. If any of the + * regulators cannot be acquired then any regulators that were + * allocated will be freed before returning to the caller. + */ +int devm_regulator_bulk_get(struct device *dev, int num_consumers, + struct regulator_bulk_data *consumers) +{ + return _devm_regulator_bulk_get(dev, num_consumers, consumers, NORMAL_GET); +} EXPORT_SYMBOL_GPL(devm_regulator_bulk_get); +/** + * devm_regulator_bulk_get_exclusive - managed exclusive get of multiple + * regulator consumers + * + * @dev: device to supply + * @num_consumers: number of consumers to register + * @consumers: configuration of consumers; clients are stored here. + * + * @return 0 on success, an errno on failure. + * + * This helper function allows drivers to exclusively get several + * regulator consumers in one operation with management, the regulators + * will automatically be freed when the device is unbound. If any of + * the regulators cannot be acquired then any regulators that were + * allocated will be freed before returning to the caller. + */ +int devm_regulator_bulk_get_exclusive(struct device *dev, int num_consumers, + struct regulator_bulk_data *consumers) +{ + return _devm_regulator_bulk_get(dev, num_consumers, consumers, EXCLUSIVE_GET); +} +EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_exclusive); + /** * devm_regulator_bulk_get_const - devm_regulator_bulk_get() w/ const data * diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h index 1e9c71642143..fb4433068d29 100644 --- a/drivers/regulator/internal.h +++ b/drivers/regulator/internal.h @@ -122,4 +122,6 @@ enum regulator_get_type { struct regulator *_regulator_get(struct device *dev, const char *id, enum regulator_get_type get_type); +int _regulator_bulk_get(struct device *dev, int num_consumers, + struct regulator_bulk_data *consumers, enum regulator_get_type get_type); #endif diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index ee3b4a014611..628a52b8e63f 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -247,6 +247,8 @@ int __must_check regulator_bulk_get(struct device *dev, int num_consumers, int __must_check devm_regulator_bulk_get(struct device *dev, int num_consumers, struct regulator_bulk_data *consumers); void devm_regulator_bulk_put(struct regulator_bulk_data *consumers); +int __must_check devm_regulator_bulk_get_exclusive(struct device *dev, int num_consumers, + struct regulator_bulk_data *consumers); int __must_check devm_regulator_bulk_get_const( struct device *dev, int num_consumers, const struct regulator_bulk_data *in_consumers, -- cgit v1.2.3 From 14b8ad4c2580231fc45c2313ef822a15bb12f63f Mon Sep 17 00:00:00 2001 From: Zev Weiss Date: Mon, 31 Oct 2022 16:37:03 -0700 Subject: regulator: Add regulator-output binding This describes a power output supplied by a regulator, such as a power outlet on a power distribution unit (PDU). Signed-off-by: Zev Weiss Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20221031233704.22575-3-zev@bewilderbeest.net Signed-off-by: Mark Brown --- .../bindings/regulator/regulator-output.yaml | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 Documentation/devicetree/bindings/regulator/regulator-output.yaml diff --git a/Documentation/devicetree/bindings/regulator/regulator-output.yaml b/Documentation/devicetree/bindings/regulator/regulator-output.yaml new file mode 100644 index 000000000000..078b37a1a71a --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/regulator-output.yaml @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- + +$id: http://devicetree.org/schemas/regulator/regulator-output.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Regulator output connector + +maintainers: + - Zev Weiss + +description: | + This describes a power output connector supplied by a regulator, + such as a power outlet on a power distribution unit (PDU). The + connector may be standalone or merely one channel or set of pins + within a ganged physical connector carrying multiple independent + power outputs. + +properties: + compatible: + const: regulator-output + + vout-supply: + description: + Phandle of the regulator supplying the output. + +required: + - compatible + - vout-supply + +additionalProperties: false + +examples: + - | + output { + compatible = "regulator-output"; + vout-supply = <&output_reg>; + }; -- cgit v1.2.3 From 5c51d4afcf3fd36159713556402e16cfab794ae9 Mon Sep 17 00:00:00 2001 From: Zev Weiss Date: Mon, 31 Oct 2022 16:37:04 -0700 Subject: regulator: userspace-consumer: Handle regulator-output DT nodes In addition to adding some fairly simple OF support code, we make some slight adjustments to the userspace-consumer driver to properly support use with regulator-output hardware: - We now do an exclusive get of the supply regulators so as to prevent regulator_init_complete_work from automatically disabling them. - Instead of assuming that the supply is initially disabled, we now query its state to determine the initial value of drvdata->enabled. Signed-off-by: Zev Weiss Link: https://lore.kernel.org/r/20221031233704.22575-4-zev@bewilderbeest.net Signed-off-by: Mark Brown --- drivers/regulator/userspace-consumer.c | 60 ++++++++++++++++++++++++---- include/linux/regulator/userspace-consumer.h | 1 + 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/userspace-consumer.c b/drivers/regulator/userspace-consumer.c index 8ca28664776e..402c8037cf39 100644 --- a/drivers/regulator/userspace-consumer.c +++ b/drivers/regulator/userspace-consumer.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,7 @@ struct userspace_consumer_data { struct mutex lock; bool enabled; + bool no_autoswitch; int num_supplies; struct regulator_bulk_data *supplies; @@ -96,19 +98,50 @@ static struct attribute *attributes[] = { NULL, }; +static umode_t attr_visible(struct kobject *kobj, struct attribute *attr, int idx) +{ + struct device *dev = kobj_to_dev(kobj); + struct userspace_consumer_data *data = dev_get_drvdata(dev); + + /* If a name hasn't been set, don't bother with the attribute */ + if (attr == &dev_attr_name.attr && !data->name) + return 0; + + return attr->mode; +} + static const struct attribute_group attr_group = { .attrs = attributes, + .is_visible = attr_visible, }; static int regulator_userspace_consumer_probe(struct platform_device *pdev) { + struct regulator_userspace_consumer_data tmpdata; struct regulator_userspace_consumer_data *pdata; struct userspace_consumer_data *drvdata; int ret; pdata = dev_get_platdata(&pdev->dev); - if (!pdata) + if (!pdata) { + if (!pdev->dev.of_node) + return -EINVAL; + + pdata = &tmpdata; + memset(pdata, 0, sizeof(*pdata)); + + pdata->no_autoswitch = true; + pdata->num_supplies = 1; + pdata->supplies = devm_kzalloc(&pdev->dev, sizeof(*pdata->supplies), GFP_KERNEL); + if (!pdata->supplies) + return -ENOMEM; + pdata->supplies[0].supply = "vout"; + } + + if (pdata->num_supplies < 1) { + dev_err(&pdev->dev, "At least one supply required\n"); return -EINVAL; + } drvdata = devm_kzalloc(&pdev->dev, sizeof(struct userspace_consumer_data), @@ -119,21 +152,24 @@ static int regulator_userspace_consumer_probe(struct platform_device *pdev) drvdata->name = pdata->name; drvdata->num_supplies = pdata->num_supplies; drvdata->supplies = pdata->supplies; + drvdata->no_autoswitch = pdata->no_autoswitch; mutex_init(&drvdata->lock); - ret = devm_regulator_bulk_get(&pdev->dev, drvdata->num_supplies, - drvdata->supplies); + ret = devm_regulator_bulk_get_exclusive(&pdev->dev, drvdata->num_supplies, + drvdata->supplies); if (ret) { dev_err(&pdev->dev, "Failed to get supplies: %d\n", ret); return ret; } + platform_set_drvdata(pdev, drvdata); + ret = sysfs_create_group(&pdev->dev.kobj, &attr_group); if (ret != 0) return ret; - if (pdata->init_on) { + if (pdata->init_on && !pdata->no_autoswitch) { ret = regulator_bulk_enable(drvdata->num_supplies, drvdata->supplies); if (ret) { @@ -143,8 +179,12 @@ static int regulator_userspace_consumer_probe(struct platform_device *pdev) } } - drvdata->enabled = pdata->init_on; - platform_set_drvdata(pdev, drvdata); + ret = regulator_is_enabled(pdata->supplies[0].consumer); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to get regulator status\n"); + goto err_enable; + } + drvdata->enabled = !!ret; return 0; @@ -160,17 +200,23 @@ static int regulator_userspace_consumer_remove(struct platform_device *pdev) sysfs_remove_group(&pdev->dev.kobj, &attr_group); - if (data->enabled) + if (data->enabled && !data->no_autoswitch) regulator_bulk_disable(data->num_supplies, data->supplies); return 0; } +static const struct of_device_id regulator_userspace_consumer_of_match[] = { + { .compatible = "regulator-output", }, + {}, +}; + static struct platform_driver regulator_userspace_consumer_driver = { .probe = regulator_userspace_consumer_probe, .remove = regulator_userspace_consumer_remove, .driver = { .name = "reg-userspace-consumer", + .of_match_table = regulator_userspace_consumer_of_match, }, }; diff --git a/include/linux/regulator/userspace-consumer.h b/include/linux/regulator/userspace-consumer.h index b5dba0628951..2249ee697f8b 100644 --- a/include/linux/regulator/userspace-consumer.h +++ b/include/linux/regulator/userspace-consumer.h @@ -21,6 +21,7 @@ struct regulator_userspace_consumer_data { struct regulator_bulk_data *supplies; bool init_on; + bool no_autoswitch; }; #endif /* __REGULATOR_PLATFORM_CONSUMER_H_ */ -- cgit v1.2.3 From 0cda8c43aa2477b7a9f9bed0adff2f34d3afc143 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Wed, 9 Nov 2022 12:08:46 +0100 Subject: regulator: qcom_smd: Add PMR735a regulators PMR735a is already supported in the RPMH regulator driver, but there are cases where it's bundled with SMD RPM SoCs. Port it over to qcom_smd-regulator to enable usage in such cases. Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20221109110846.45789-2-konrad.dybcio@linaro.org Signed-off-by: Mark Brown --- drivers/regulator/qcom_smd-regulator.c | 24 ++++++++++++++++++++++++ include/linux/soc/qcom/smd-rpm.h | 2 ++ 2 files changed, 26 insertions(+) diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c index f98168d58dce..9eaae13fd385 100644 --- a/drivers/regulator/qcom_smd-regulator.c +++ b/drivers/regulator/qcom_smd-regulator.c @@ -677,6 +677,15 @@ static const struct regulator_desc pm6125_ftsmps = { .ops = &rpm_smps_ldo_ops, }; +static const struct regulator_desc pmic5_ftsmps520 = { + .linear_ranges = (struct linear_range[]) { + REGULATOR_LINEAR_RANGE(300000, 0, 263, 4000), + }, + .n_linear_ranges = 1, + .n_voltages = 264, + .ops = &rpm_smps_ldo_ops, +}; + static const struct regulator_desc pms405_hfsmps3 = { .linear_ranges = (struct linear_range[]) { REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000), @@ -1265,6 +1274,20 @@ static const struct rpm_regulator_data rpm_pmi8998_regulators[] = { {} }; +static const struct rpm_regulator_data rpm_pmr735a_regulators[] = { + { "s1", QCOM_SMD_RPM_SMPE, 1, &pmic5_ftsmps520, "vdd_s1"}, + { "s2", QCOM_SMD_RPM_SMPE, 2, &pmic5_ftsmps520, "vdd_s2"}, + { "s3", QCOM_SMD_RPM_SMPE, 3, &pms405_hfsmps3, "vdd_s3"}, + { "l1", QCOM_SMD_RPM_LDOE, 1, &pm660_nldo660, "vdd_l1_l2"}, + { "l2", QCOM_SMD_RPM_LDOE, 2, &pm660_nldo660, "vdd_l1_l2"}, + { "l3", QCOM_SMD_RPM_LDOE, 3, &pm660_nldo660, "vdd_l3"}, + { "l4", QCOM_SMD_RPM_LDOE, 4, &pm660_ht_lvpldo, "vdd_l4"}, + { "l5", QCOM_SMD_RPM_LDOE, 5, &pm660_nldo660, "vdd_l5_l6"}, + { "l6", QCOM_SMD_RPM_LDOE, 6, &pm660_nldo660, "vdd_l5_l6"}, + { "l7", QCOM_SMD_RPM_LDOE, 7, &pm660_pldo660, "vdd_l7_bob"}, + {} +}; + static const struct rpm_regulator_data rpm_pms405_regulators[] = { { "s1", QCOM_SMD_RPM_SMPA, 1, &pms405_hfsmps3, "vdd_s1" }, { "s2", QCOM_SMD_RPM_SMPA, 2, &pms405_hfsmps3, "vdd_s2" }, @@ -1305,6 +1328,7 @@ static const struct of_device_id rpm_of_match[] = { { .compatible = "qcom,rpm-pma8084-regulators", .data = &rpm_pma8084_regulators }, { .compatible = "qcom,rpm-pmi8994-regulators", .data = &rpm_pmi8994_regulators }, { .compatible = "qcom,rpm-pmi8998-regulators", .data = &rpm_pmi8998_regulators }, + { .compatible = "qcom,rpm-pmr735a-regulators", .data = &rpm_pmr735a_regulators }, { .compatible = "qcom,rpm-pms405-regulators", .data = &rpm_pms405_regulators }, {} }; diff --git a/include/linux/soc/qcom/smd-rpm.h b/include/linux/soc/qcom/smd-rpm.h index 3ab8c07f71c0..62de54992e49 100644 --- a/include/linux/soc/qcom/smd-rpm.h +++ b/include/linux/soc/qcom/smd-rpm.h @@ -19,6 +19,7 @@ struct qcom_smd_rpm; #define QCOM_SMD_RPM_CLK_BUF_A 0x616B6C63 #define QCOM_SMD_RPM_LDOA 0x616f646c #define QCOM_SMD_RPM_LDOB 0x626F646C +#define QCOM_SMD_RPM_LDOE 0x656f646c #define QCOM_SMD_RPM_RWCX 0x78637772 #define QCOM_SMD_RPM_RWMX 0x786d7772 #define QCOM_SMD_RPM_RWLC 0x636c7772 @@ -32,6 +33,7 @@ struct qcom_smd_rpm; #define QCOM_SMD_RPM_QUP_CLK 0x707571 #define QCOM_SMD_RPM_SMPA 0x61706d73 #define QCOM_SMD_RPM_SMPB 0x62706d73 +#define QCOM_SMD_RPM_SMPE 0x65706d73 #define QCOM_SMD_RPM_SPDM 0x63707362 #define QCOM_SMD_RPM_VSA 0x00617376 #define QCOM_SMD_RPM_MMAXI_CLK 0x69786d6d -- cgit v1.2.3 From 9263c69696c8c75ef97ebf57cb4f308c4c2420ea Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Wed, 9 Nov 2022 12:08:45 +0100 Subject: regulator: qcom,smd: Document PMR735a PMR735a also appears to be bundled with some SMD RPM SoCs. Document it. Signed-off-by: Konrad Dybcio Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20221109110846.45789-1-konrad.dybcio@linaro.org Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml index 961eed51912c..8c45f53212b1 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml @@ -71,6 +71,8 @@ description: For pmi8998, bob + For pmr735a, s1, s2, s3, l1, l2, l3, l4, l5, l6, l7 + For pms405, s1, s2, s3, s4, s5, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13 @@ -98,6 +100,7 @@ properties: - qcom,rpm-pma8084-regulators - qcom,rpm-pmi8994-regulators - qcom,rpm-pmi8998-regulators + - qcom,rpm-pmr735a-regulators - qcom,rpm-pms405-regulators patternProperties: -- cgit v1.2.3 From 91016037216b3aaa0fa1b616d388053fb4202835 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Thu, 10 Nov 2022 13:12:25 +0100 Subject: regulator: qcom_smd: Fix PMR735a S3 regulator spec PMR735a has a wider range than previously defined. Fix it. Fixes: 0cda8c43aa24 ("regulator: qcom_smd: Add PMR735a regulators") Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20221110121225.9216-1-konrad.dybcio@linaro.org Signed-off-by: Mark Brown --- drivers/regulator/qcom_smd-regulator.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c index 9eaae13fd385..9f2b58458841 100644 --- a/drivers/regulator/qcom_smd-regulator.c +++ b/drivers/regulator/qcom_smd-regulator.c @@ -686,6 +686,15 @@ static const struct regulator_desc pmic5_ftsmps520 = { .ops = &rpm_smps_ldo_ops, }; +static const struct regulator_desc pmic5_hfsmps515 = { + .linear_ranges = (struct linear_range[]) { + REGULATOR_LINEAR_RANGE(320000, 0, 235, 16000), + }, + .n_linear_ranges = 1, + .n_voltages = 236, + .ops = &rpm_smps_ldo_ops, +}; + static const struct regulator_desc pms405_hfsmps3 = { .linear_ranges = (struct linear_range[]) { REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000), @@ -1277,7 +1286,7 @@ static const struct rpm_regulator_data rpm_pmi8998_regulators[] = { static const struct rpm_regulator_data rpm_pmr735a_regulators[] = { { "s1", QCOM_SMD_RPM_SMPE, 1, &pmic5_ftsmps520, "vdd_s1"}, { "s2", QCOM_SMD_RPM_SMPE, 2, &pmic5_ftsmps520, "vdd_s2"}, - { "s3", QCOM_SMD_RPM_SMPE, 3, &pms405_hfsmps3, "vdd_s3"}, + { "s3", QCOM_SMD_RPM_SMPE, 3, &pmic5_hfsmps515, "vdd_s3"}, { "l1", QCOM_SMD_RPM_LDOE, 1, &pm660_nldo660, "vdd_l1_l2"}, { "l2", QCOM_SMD_RPM_LDOE, 2, &pm660_nldo660, "vdd_l1_l2"}, { "l3", QCOM_SMD_RPM_LDOE, 3, &pm660_nldo660, "vdd_l3"}, -- cgit v1.2.3 From f2b41b748c19962b82709d9f23c6b2b0ce9d2f91 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 15 Nov 2022 17:15:08 +0800 Subject: regulator: core: fix unbalanced of node refcount in regulator_dev_lookup() I got the the following report: OF: ERROR: memory leak, expected refcount 1 instead of 2, of_node_get()/of_node_put() unbalanced - destroy cset entry: attach overlay node /i2c/pmic@62/regulators/exten In of_get_regulator(), the node is returned from of_parse_phandle() with refcount incremented, after using it, of_node_put() need be called. Fixes: 69511a452e6d ("regulator: map consumer regulator based on device tree") Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20221115091508.900752-1-yangyingliang@huawei.com Signed-off-by: Mark Brown --- drivers/regulator/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 704f91720dfe..3f6c6185c187 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1943,6 +1943,7 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev, node = of_get_regulator(dev, supply); if (node) { r = of_find_regulator_by_node(node); + of_node_put(node); if (r) return r; -- cgit v1.2.3 From dd801b2265c81bf0c8b0b4b8f7c1e7bfed078403 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Thu, 10 Nov 2022 22:07:05 +0100 Subject: regulator: qcom-rpmh: Fix PMR735a S3 regulator spec PMR735a has a wider range than previously defined. Fix it. Fixes: c4e5aa3dbee5 ("regulator: qcom-rpmh: Add PM7325/PMR735A regulator support") Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20221110210706.80301-1-konrad.dybcio@linaro.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 4158ff126a67..f90bcdeecea5 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -1187,7 +1187,7 @@ static const struct rpmh_vreg_init_data pm7325_vreg_data[] = { static const struct rpmh_vreg_init_data pmr735a_vreg_data[] = { RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps520, "vdd-s1"), RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps520, "vdd-s2"), - RPMH_VREG("smps3", "smp%s3", &pmic5_hfsmps510, "vdd-s3"), + RPMH_VREG("smps3", "smp%s3", &pmic5_hfsmps515, "vdd-s3"), RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1-l2"), RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l1-l2"), RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"), -- cgit v1.2.3 From b8dfb3bed5524589052dafa0e4d6c4e25ae11544 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 16 Nov 2022 11:20:53 +0100 Subject: regulator: dt-bindings: qcom,rpmh: clean up example indentation Remove a line break and increase indentation of the continuation line to avoid having the 'regulator-allowed-modes' example be reproduced verbatim with four-spaces indentation (instead of a tab, which is still too little) in devicetree sources. Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20221116102054.4673-2-johan+linaro@kernel.org Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/qcom,rpmh-regulator.yaml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml index 90c3bda31c23..7ff51b558702 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml @@ -412,9 +412,8 @@ examples: regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-initial-mode = ; - regulator-allowed-modes = - ; + regulator-allowed-modes = ; regulator-allow-set-load; }; @@ -431,9 +430,8 @@ examples: bob { regulator-min-microvolt = <3312000>; regulator-max-microvolt = <3600000>; - regulator-allowed-modes = - ; + regulator-allowed-modes = ; regulator-initial-mode = ; }; }; -- cgit v1.2.3 From bc64f30eb9a5edb299ee0a1a05cc21e4079fd9f3 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Wed, 16 Nov 2022 07:32:12 +0200 Subject: lib/test_linear_ranges: Use LINEAR_RANGE() New initialization macro for linear ranges was added. Slightly simplify the test code by using this macro - and at the same time also verify the macro is working as intended. Use the newly added LINEAR_RANGE() initialization macro for linear range test. Signed-off-by: Matti Vaittinen Link: https://lore.kernel.org/r/Y3R13IRrs+x5PcZ4@dc75zzyyyyyyyyyyyyydt-3.rev.dnainternet.fi Signed-off-by: Mark Brown --- lib/test_linear_ranges.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/lib/test_linear_ranges.c b/lib/test_linear_ranges.c index 676e0b8abcdd..c18f9c0f1f25 100644 --- a/lib/test_linear_ranges.c +++ b/lib/test_linear_ranges.c @@ -107,17 +107,8 @@ static const unsigned int range2_vals[] = { RANGE2_MIN, RANGE2_MIN + #define SMALLEST_VAL RANGE1_MIN static struct linear_range testr[] = { - { - .min = RANGE1_MIN, - .min_sel = RANGE1_MIN_SEL, - .max_sel = RANGE1_MAX_SEL, - .step = RANGE1_STEP, - }, { - .min = RANGE2_MIN, - .min_sel = RANGE2_MIN_SEL, - .max_sel = RANGE2_MAX_SEL, - .step = RANGE2_STEP - }, + LINEAR_RANGE(RANGE1_MIN, RANGE1_MIN_SEL, RANGE1_MAX_SEL, RANGE1_STEP), + LINEAR_RANGE(RANGE2_MIN, RANGE2_MIN_SEL, RANGE2_MAX_SEL, RANGE2_STEP), }; static void range_test_get_value(struct kunit *test) -- cgit v1.2.3 From 27b9ecc7a9ba1d0014779bfe5a6dbf630899c6e7 Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Tue, 15 Nov 2022 07:36:01 +0000 Subject: regulator: Add of_regulator_bulk_get_all It work exactly like regulator_bulk_get() but instead of working on a provided list of names, it seek all consumers properties matching xxx-supply. Signed-off-by: Corentin Labbe Link: https://lore.kernel.org/r/20221115073603.3425396-2-clabbe@baylibre.com Signed-off-by: Mark Brown --- drivers/regulator/of_regulator.c | 92 ++++++++++++++++++++++++++++++++++++++ include/linux/regulator/consumer.h | 8 ++++ 2 files changed, 100 insertions(+) diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 0aff1c2886b5..584c92f1a317 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -701,3 +701,95 @@ struct regulator_dev *of_parse_coupled_regulator(struct regulator_dev *rdev, return c_rdev; } + +/* + * Check if name is a supply name according to the '*-supply' pattern + * return 0 if false + * return length of supply name without the -supply + */ +static int is_supply_name(const char *name) +{ + int strs, i; + + strs = strlen(name); + /* string need to be at minimum len(x-supply) */ + if (strs < 8) + return 0; + for (i = strs - 6; i > 0; i--) { + /* find first '-' and check if right part is supply */ + if (name[i] != '-') + continue; + if (strcmp(name + i + 1, "supply") != 0) + return 0; + return i; + } + return 0; +} + +/* + * of_regulator_bulk_get_all - get multiple regulator consumers + * + * @dev: Device to supply + * @np: device node to search for consumers + * @consumers: Configuration of consumers; clients are stored here. + * + * @return number of regulators on success, an errno on failure. + * + * This helper function allows drivers to get several regulator + * consumers in one operation. If any of the regulators cannot be + * acquired then any regulators that were allocated will be freed + * before returning to the caller. + */ +int of_regulator_bulk_get_all(struct device *dev, struct device_node *np, + struct regulator_bulk_data **consumers) +{ + int num_consumers = 0; + struct regulator *tmp; + struct property *prop; + int i, n = 0, ret; + char name[64]; + + *consumers = NULL; + + /* + * first pass: get numbers of xxx-supply + * second pass: fill consumers + */ +restart: + for_each_property_of_node(np, prop) { + i = is_supply_name(prop->name); + if (i == 0) + continue; + if (!*consumers) { + num_consumers++; + continue; + } else { + memcpy(name, prop->name, i); + name[i] = '\0'; + tmp = regulator_get(dev, name); + if (!tmp) { + ret = -EINVAL; + goto error; + } + (*consumers)[n].consumer = tmp; + n++; + continue; + } + } + if (*consumers) + return num_consumers; + if (num_consumers == 0) + return 0; + *consumers = kmalloc_array(num_consumers, + sizeof(struct regulator_bulk_data), + GFP_KERNEL); + if (!*consumers) + return -ENOMEM; + goto restart; + +error: + while (--n >= 0) + regulator_put(consumers[n]->consumer); + return ret; +} +EXPORT_SYMBOL_GPL(of_regulator_bulk_get_all); diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index ee3b4a014611..276488dad61d 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -244,6 +244,8 @@ int regulator_disable_deferred(struct regulator *regulator, int ms); int __must_check regulator_bulk_get(struct device *dev, int num_consumers, struct regulator_bulk_data *consumers); +int __must_check of_regulator_bulk_get_all(struct device *dev, struct device_node *np, + struct regulator_bulk_data **consumers); int __must_check devm_regulator_bulk_get(struct device *dev, int num_consumers, struct regulator_bulk_data *consumers); void devm_regulator_bulk_put(struct regulator_bulk_data *consumers); @@ -479,6 +481,12 @@ static inline int devm_regulator_bulk_get(struct device *dev, int num_consumers, return 0; } +static inline int of_regulator_bulk_get_all(struct device *dev, struct device_node *np, + struct regulator_bulk_data **consumers) +{ + return 0; +} + static inline int regulator_bulk_enable(int num_consumers, struct regulator_bulk_data *consumers) { -- cgit v1.2.3 From 2da34b2301386bfed929d41c2e5367d484a140fe Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 9 Nov 2022 16:53:25 +0000 Subject: regulator: arizona-micsupp: Don't hardcode use of ARIZONA defines When Madera support was added to this driver the code was left using ARIZONA_* defines. This wasn't causing any problem because those defines just happened to have the same value as the equivalent MADERA_* defines. But it is not ideal to assume this, and future devices that can share this driver do not have the same register map. Fix the code to refer to the register data in struct regulator_desc. Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20221109165331.29332-7-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- drivers/regulator/arizona-micsupp.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index f6cfd3f6f0dd..21c36972a8e9 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -34,7 +34,7 @@ struct arizona_micsupp { struct regulator_dev *regulator; struct regmap *regmap; struct snd_soc_dapm_context **dapm; - unsigned int enable_reg; + const struct regulator_desc *desc; struct device *dev; struct regulator_consumer_supply supply; @@ -49,10 +49,11 @@ static void arizona_micsupp_check_cp(struct work_struct *work) container_of(work, struct arizona_micsupp, check_cp_work); struct snd_soc_dapm_context *dapm = *micsupp->dapm; struct snd_soc_component *component; + const struct regulator_desc *desc = micsupp->desc; unsigned int val; int ret; - ret = regmap_read(micsupp->regmap, micsupp->enable_reg, &val); + ret = regmap_read(micsupp->regmap, desc->enable_reg, &val); if (ret != 0) { dev_err(micsupp->dev, "Failed to read CP state: %d\n", ret); @@ -62,8 +63,8 @@ static void arizona_micsupp_check_cp(struct work_struct *work) if (dapm) { component = snd_soc_dapm_to_component(dapm); - if ((val & (ARIZONA_CPMIC_ENA | ARIZONA_CPMIC_BYPASS)) == - ARIZONA_CPMIC_ENA) + if ((val & (desc->enable_mask | desc->bypass_mask)) == + desc->enable_mask) snd_soc_component_force_enable_pin(component, "MICSUPP"); else @@ -209,7 +210,6 @@ static const struct regulator_desc madera_micsupp = { .type = REGULATOR_VOLTAGE, .n_voltages = 40, .ops = &arizona_micsupp_ops, - .vsel_reg = MADERA_LDO2_CONTROL_1, .vsel_mask = MADERA_LDO2_VSEL_MASK, .enable_reg = MADERA_MIC_CHARGE_PUMP_1, @@ -264,7 +264,7 @@ static int arizona_micsupp_common_init(struct platform_device *pdev, micsupp->init_data.consumer_supplies = &micsupp->supply; micsupp->supply.supply = "MICVDD"; micsupp->supply.dev_name = dev_name(micsupp->dev); - micsupp->enable_reg = desc->enable_reg; + micsupp->desc = desc; config.dev = micsupp->dev; config.driver_data = micsupp; @@ -285,8 +285,7 @@ static int arizona_micsupp_common_init(struct platform_device *pdev, config.init_data = &micsupp->init_data; /* Default to regulated mode */ - regmap_update_bits(micsupp->regmap, micsupp->enable_reg, - ARIZONA_CPMIC_BYPASS, 0); + regmap_update_bits(micsupp->regmap, desc->enable_reg, desc->bypass_mask, 0); micsupp->regulator = devm_regulator_register(&pdev->dev, desc, -- cgit v1.2.3 From 9211402fe72428bffe8e474448e671deeb6c52cb Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 9 Nov 2022 16:53:26 +0000 Subject: regulator: arizona-micsupp: Don't use a common regulator name The Arizona and Madera codecs all have a datasheet name of "MICVDD" for the regulator output. But future codecs with a regulator that can be controlled by this driver have different naming convention for the output of the regulator. Move the setting of the supply name from arizona_micsupp_common_init() to arizona_micsupp_probe() and madera_micsupp_probe(). Signed-off-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20221109165331.29332-8-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- drivers/regulator/arizona-micsupp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index 21c36972a8e9..596ecd8041cd 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -262,7 +262,6 @@ static int arizona_micsupp_common_init(struct platform_device *pdev, INIT_WORK(&micsupp->check_cp_work, arizona_micsupp_check_cp); micsupp->init_data.consumer_supplies = &micsupp->supply; - micsupp->supply.supply = "MICVDD"; micsupp->supply.dev_name = dev_name(micsupp->dev); micsupp->desc = desc; @@ -319,6 +318,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev) micsupp->dapm = &arizona->dapm; micsupp->dev = arizona->dev; + micsupp->supply.supply = "MICVDD"; + /* * Since the chip usually supplies itself we provide some * default init_data for it. This will be overridden with @@ -354,6 +355,8 @@ static int madera_micsupp_probe(struct platform_device *pdev) micsupp->dev = madera->dev; micsupp->init_data = arizona_micsupp_ext_default; + micsupp->supply.supply = "MICVDD"; + return arizona_micsupp_common_init(pdev, micsupp, &madera_micsupp, &madera->pdata.micvdd); } -- cgit v1.2.3 From c957387c402a1a213102e38f92b800d7909a728d Mon Sep 17 00:00:00 2001 From: Peng Wu Date: Tue, 22 Nov 2022 08:22:42 +0000 Subject: regulator: of: fix a NULL vs IS_ERR() check in of_regulator_bulk_get_all() The regulator_get() function never returns NULL. It returns error pointers. Fixes: 27b9ecc7a9ba ("regulator: Add of_regulator_bulk_get_all") Signed-off-by: Peng Wu Link: https://lore.kernel.org/r/20221122082242.82937-1-wupeng58@huawei.com Signed-off-by: Mark Brown --- drivers/regulator/of_regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 584c92f1a317..f7529f1bf8b2 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -767,7 +767,7 @@ restart: memcpy(name, prop->name, i); name[i] = '\0'; tmp = regulator_get(dev, name); - if (!tmp) { + if (IS_ERR(tmp)) { ret = -EINVAL; goto error; } -- cgit v1.2.3 From 020cf73b47414a84b666d3e6736a6ae957e27840 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:34 +0100 Subject: regulator: da9121-regulator: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function doesn't make use of the i2c_device_id * parameter so it can be trivially converted. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-541-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/da9121-regulator.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c index e4c753b83088..d016e049d264 100644 --- a/drivers/regulator/da9121-regulator.c +++ b/drivers/regulator/da9121-regulator.c @@ -1128,8 +1128,7 @@ static inline int da9121_of_get_id(struct device *dev) return (uintptr_t)id->data; } -static int da9121_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int da9121_i2c_probe(struct i2c_client *i2c) { struct da9121 *chip; const int mask_all[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; @@ -1197,7 +1196,7 @@ static struct i2c_driver da9121_regulator_driver = { .name = "da9121", .of_match_table = of_match_ptr(da9121_dt_ids), }, - .probe = da9121_i2c_probe, + .probe_new = da9121_i2c_probe, .remove = da9121_i2c_remove, .id_table = da9121_i2c_id, }; -- cgit v1.2.3 From 2532d5f8d5c20d5a0a8a0d57a311bc5df00dea04 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:37 +0100 Subject: regulator: lp3972: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function doesn't make use of the i2c_device_id * parameter so it can be trivially converted. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-544-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/lp3972.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index 2d276bbeedf2..27b216bf18fc 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -495,8 +495,7 @@ static int setup_regulators(struct lp3972 *lp3972, return 0; } -static int lp3972_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int lp3972_i2c_probe(struct i2c_client *i2c) { struct lp3972 *lp3972; struct lp3972_platform_data *pdata = dev_get_platdata(&i2c->dev); @@ -547,7 +546,7 @@ static struct i2c_driver lp3972_i2c_driver = { .driver = { .name = "lp3972", }, - .probe = lp3972_i2c_probe, + .probe_new = lp3972_i2c_probe, .id_table = lp3972_i2c_id, }; -- cgit v1.2.3 From cb28f74b4809a00b40fdf0c44ccf51ab950581d3 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:39 +0100 Subject: regulator: lp8755: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function doesn't make use of the i2c_device_id * parameter so it can be trivially converted. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-546-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/lp8755.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index 31b43426d47c..467dfdcebc91 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -357,8 +357,7 @@ static const struct regmap_config lp8755_regmap = { .max_register = LP8755_REG_MAX, }; -static int lp8755_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int lp8755_probe(struct i2c_client *client) { int ret, icnt; struct lp8755_chip *pchip; @@ -442,7 +441,7 @@ static struct i2c_driver lp8755_i2c_driver = { .driver = { .name = LP8755_NAME, }, - .probe = lp8755_probe, + .probe_new = lp8755_probe, .remove = lp8755_remove, .id_table = lp8755_id, }; -- cgit v1.2.3 From 3d54f7ba248b0ad1791bc356e9ad3d9020a1c472 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:41 +0100 Subject: regulator: max1586: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function doesn't make use of the i2c_device_id * parameter so it can be trivially converted. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-548-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/max1586.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index d4958394e608..a00aa2e8ff3f 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -207,8 +207,7 @@ static const struct of_device_id __maybe_unused max1586_of_match[] = { }; MODULE_DEVICE_TABLE(of, max1586_of_match); -static int max1586_pmic_probe(struct i2c_client *client, - const struct i2c_device_id *i2c_id) +static int max1586_pmic_probe(struct i2c_client *client) { struct max1586_platform_data *pdata, pdata_of; struct regulator_config config = { }; @@ -290,7 +289,7 @@ static const struct i2c_device_id max1586_id[] = { MODULE_DEVICE_TABLE(i2c, max1586_id); static struct i2c_driver max1586_pmic_driver = { - .probe = max1586_pmic_probe, + .probe_new = max1586_pmic_probe, .driver = { .name = "max1586", .of_match_table = of_match_ptr(max1586_of_match), -- cgit v1.2.3 From 3cf4417385d0ac8f02f22888e12a6d21d97d89fc Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:42 +0100 Subject: regulator: max8649: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function doesn't make use of the i2c_device_id * parameter so it can be trivially converted. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-549-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/max8649.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index e86d8bd25fdc..aed5443d88e1 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -145,8 +145,7 @@ static const struct regmap_config max8649_regmap_config = { .val_bits = 8, }; -static int max8649_regulator_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int max8649_regulator_probe(struct i2c_client *client) { struct max8649_platform_data *pdata = dev_get_platdata(&client->dev); struct max8649_regulator_info *info = NULL; @@ -247,7 +246,7 @@ static const struct i2c_device_id max8649_id[] = { MODULE_DEVICE_TABLE(i2c, max8649_id); static struct i2c_driver max8649_driver = { - .probe = max8649_regulator_probe, + .probe_new = max8649_regulator_probe, .driver = { .name = "max8649", }, -- cgit v1.2.3 From c20c36735949b3b7984692fbab3d92b0e8a845ec Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:44 +0100 Subject: regulator: max8952: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function doesn't make use of the i2c_device_id * parameter so it can be trivially converted. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-551-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/max8952.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index ccd5da63cdf2..360a33ecc093 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -171,8 +171,7 @@ static struct max8952_platform_data *max8952_parse_dt(struct device *dev) } #endif -static int max8952_pmic_probe(struct i2c_client *client, - const struct i2c_device_id *i2c_id) +static int max8952_pmic_probe(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; struct max8952_platform_data *pdata = dev_get_platdata(&client->dev); @@ -314,7 +313,7 @@ static const struct i2c_device_id max8952_ids[] = { MODULE_DEVICE_TABLE(i2c, max8952_ids); static struct i2c_driver max8952_pmic_driver = { - .probe = max8952_pmic_probe, + .probe_new = max8952_pmic_probe, .driver = { .name = "max8952", .of_match_table = of_match_ptr(max8952_dt_match), -- cgit v1.2.3 From ed56fa6e804cb13bbe29e9214792308817f6e553 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:46 +0100 Subject: regulator: pca9450-regulator: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function doesn't make use of the i2c_device_id * parameter so it can be trivially converted. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-553-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/pca9450-regulator.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c index 14b7d3376516..c6351fac9f4d 100644 --- a/drivers/regulator/pca9450-regulator.c +++ b/drivers/regulator/pca9450-regulator.c @@ -701,8 +701,7 @@ static irqreturn_t pca9450_irq_handler(int irq, void *data) return IRQ_HANDLED; } -static int pca9450_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int pca9450_i2c_probe(struct i2c_client *i2c) { enum pca9450_chip_type type = (unsigned int)(uintptr_t) of_device_get_match_data(&i2c->dev); @@ -875,7 +874,7 @@ static struct i2c_driver pca9450_i2c_driver = { .name = "nxp-pca9450", .of_match_table = pca9450_of_match, }, - .probe = pca9450_i2c_probe, + .probe_new = pca9450_i2c_probe, }; module_i2c_driver(pca9450_i2c_driver); -- cgit v1.2.3 From d85d02d17a608b558d44510e9824668c5d4fe5d8 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:49 +0100 Subject: regulator: rpi-panel-attiny-regulator: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function doesn't make use of the i2c_device_id * parameter so it can be trivially converted. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-556-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/rpi-panel-attiny-regulator.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/rpi-panel-attiny-regulator.c b/drivers/regulator/rpi-panel-attiny-regulator.c index 308f7972941b..34514976475e 100644 --- a/drivers/regulator/rpi-panel-attiny-regulator.c +++ b/drivers/regulator/rpi-panel-attiny-regulator.c @@ -282,8 +282,7 @@ static int attiny_i2c_read(struct i2c_client *client, u8 reg, unsigned int *buf) /* * I2C driver interface functions */ -static int attiny_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int attiny_i2c_probe(struct i2c_client *i2c) { struct backlight_properties props = { }; struct regulator_config config = { }; @@ -399,7 +398,7 @@ static struct i2c_driver attiny_regulator_driver = { .name = "rpi_touchscreen_attiny", .of_match_table = of_match_ptr(attiny_dt_ids), }, - .probe = attiny_i2c_probe, + .probe_new = attiny_i2c_probe, .remove = attiny_i2c_remove, }; -- cgit v1.2.3 From d4885f306304ff29eec06b9ad5f526a1099e0418 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:50 +0100 Subject: regulator: tps51632-regulator: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function doesn't make use of the i2c_device_id * parameter so it can be trivially converted. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-557-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/tps51632-regulator.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c index 85e3326b99eb..152c5ad6709c 100644 --- a/drivers/regulator/tps51632-regulator.c +++ b/drivers/regulator/tps51632-regulator.c @@ -247,8 +247,7 @@ static struct tps51632_regulator_platform_data * } #endif -static int tps51632_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int tps51632_probe(struct i2c_client *client) { struct tps51632_regulator_platform_data *pdata; struct regulator_dev *rdev; @@ -354,7 +353,7 @@ static struct i2c_driver tps51632_i2c_driver = { .name = "tps51632", .of_match_table = of_match_ptr(tps51632_of_match), }, - .probe = tps51632_probe, + .probe_new = tps51632_probe, .id_table = tps51632_id, }; -- cgit v1.2.3 From e34782316281c78c5911f86d4699d4f35a607c9d Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:52 +0100 Subject: regulator: tps6286x-regulator: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function doesn't make use of the i2c_device_id * parameter so it can be trivially converted. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-559-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/tps6286x-regulator.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/tps6286x-regulator.c b/drivers/regulator/tps6286x-regulator.c index e29deda30d75..207ac1d1d88d 100644 --- a/drivers/regulator/tps6286x-regulator.c +++ b/drivers/regulator/tps6286x-regulator.c @@ -111,8 +111,7 @@ static const struct of_device_id tps6286x_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, tps6286x_dt_ids); -static int tps6286x_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int tps6286x_i2c_probe(struct i2c_client *i2c) { struct device *dev = &i2c->dev; struct regulator_config config = {}; @@ -150,7 +149,7 @@ static struct i2c_driver tps6286x_regulator_driver = { .name = "tps6286x", .of_match_table = of_match_ptr(tps6286x_dt_ids), }, - .probe = tps6286x_i2c_probe, + .probe_new = tps6286x_i2c_probe, .id_table = tps6286x_i2c_id, }; -- cgit v1.2.3 From 44501eba9bb28946382b7a53099ce8098d1610f0 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Wed, 23 Nov 2022 14:00:05 +0200 Subject: regulator: bd718x7: Drop unnecessary info print A device-tree node name was printed when bd718x7 driver's feedback-loop feature was developed. This print was accidentally left in driver. The info-level print just pollutes the log. Drop unnecessary pr_info() Fixes: d2ad981151b3 ("regulator: bd718x7: Support external connection to scale voltages") Signed-off-by: Matti Vaittinen Link: https://lore.kernel.org/r/33fd99abf2451999938fef4ba6cf7b3f19e9b992.1669203610.git.mazziesaccount@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/bd718x7-regulator.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c index 00efb18a836c..d161b0026f33 100644 --- a/drivers/regulator/bd718x7-regulator.c +++ b/drivers/regulator/bd718x7-regulator.c @@ -1576,8 +1576,6 @@ static int setup_feedback_loop(struct device *dev, struct device_node *np, if (!of_node_name_eq(np, desc->of_match)) continue; - pr_info("Looking at node '%s'\n", desc->of_match); - /* The feedback loop connection does not make sense for LDOs */ if (desc->id >= BD718XX_LDO1) return -EINVAL; -- cgit v1.2.3 From d4e93e8da012880882671a46ac6ae3aefcae8076 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Wed, 23 Nov 2022 14:00:21 +0200 Subject: regulator: bd71815: bd71828: bd9576: Use dev_err_probe() The dev_err_probe() has (at least) following benefits over dev_err() when printing an error print for a failed function call at a device driver probe: - Omit error level print if error is 'EPRBE_DEFER' - Standardized print format for returned error - return the error value allowing shortening calls like: if (ret) { dev_err(...); return ret; } to if (ret) return dev_err_probe(...); Convert the ROHM BD71828, ROHM BD71815 and ROHM BD9576 regulator drivers to use the dev_err_probe() when returned error is not hard-coded constant. Signed-off-by: Matti Vaittinen Link: https://lore.kernel.org/r/0b644da4a8f58558ffe474d2593f85c46de2f965.1669203610.git.mazziesaccount@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/bd71815-regulator.c | 10 +++---- drivers/regulator/bd71828-regulator.c | 21 ++++++-------- drivers/regulator/bd9576-regulator.c | 54 ++++++++++++++++------------------- 3 files changed, 38 insertions(+), 47 deletions(-) diff --git a/drivers/regulator/bd71815-regulator.c b/drivers/regulator/bd71815-regulator.c index c2b8b8be7824..8b55046eded8 100644 --- a/drivers/regulator/bd71815-regulator.c +++ b/drivers/regulator/bd71815-regulator.c @@ -602,12 +602,10 @@ static int bd7181x_probe(struct platform_device *pdev) config.ena_gpiod = NULL; rdev = devm_regulator_register(&pdev->dev, desc, &config); - if (IS_ERR(rdev)) { - dev_err(&pdev->dev, - "failed to register %s regulator\n", - desc->name); - return PTR_ERR(rdev); - } + if (IS_ERR(rdev)) + return dev_err_probe(&pdev->dev, PTR_ERR(rdev), + "failed to register %s regulator\n", + desc->name); } return 0; } diff --git a/drivers/regulator/bd71828-regulator.c b/drivers/regulator/bd71828-regulator.c index a4f09a5a30ca..ad728f4f2241 100644 --- a/drivers/regulator/bd71828-regulator.c +++ b/drivers/regulator/bd71828-regulator.c @@ -750,23 +750,20 @@ static int bd71828_probe(struct platform_device *pdev) rd = &bd71828_rdata[i]; rdev = devm_regulator_register(&pdev->dev, &rd->desc, &config); - if (IS_ERR(rdev)) { - dev_err(&pdev->dev, - "failed to register %s regulator\n", - rd->desc.name); - return PTR_ERR(rdev); - } + if (IS_ERR(rdev)) + return dev_err_probe(&pdev->dev, PTR_ERR(rdev), + "failed to register %s regulator\n", + rd->desc.name); + for (j = 0; j < rd->reg_init_amnt; j++) { ret = regmap_update_bits(config.regmap, rd->reg_inits[j].reg, rd->reg_inits[j].mask, rd->reg_inits[j].val); - if (ret) { - dev_err(&pdev->dev, - "regulator %s init failed\n", - rd->desc.name); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, + "regulator %s init failed\n", + rd->desc.name); } } return 0; diff --git a/drivers/regulator/bd9576-regulator.c b/drivers/regulator/bd9576-regulator.c index 393c8693b327..02c70768652b 100644 --- a/drivers/regulator/bd9576-regulator.c +++ b/drivers/regulator/bd9576-regulator.c @@ -953,30 +953,28 @@ static int bd957x_probe(struct platform_device *pdev) dev_fwnode(pdev->dev.parent), "rohm,vout1-en", GPIOD_OUT_LOW, "vout1-en"); - if (!IS_ERR(en)) { - /* VOUT1_OPS gpio ctrl */ - /* - * Regulator core prioritizes the ena_gpio over - * enable/disable/is_enabled callbacks so no need to - * clear them. We can still use same ops - */ + + /* VOUT1_OPS gpio ctrl */ + /* + * Regulator core prioritizes the ena_gpio over + * enable/disable/is_enabled callbacks so no need to clear them + * even if GPIO is used. So, we can still use same ops. + * + * In theory it is possible someone wants to set vout1-en LOW + * during OTP loading and set VOUT1 to be controlled by GPIO - + * but control the GPIO from some where else than this driver. + * For that to work we should unset the is_enabled callback + * here. + * + * I believe such case where rohm,vout1-en-low is set and + * vout1-en-gpios is not is likely to be a misconfiguration. + * So let's just err out for now. + */ + if (!IS_ERR(en)) config.ena_gpiod = en; - } else { - /* - * In theory it is possible someone wants to set - * vout1-en LOW during OTP loading and set VOUT1 to be - * controlled by GPIO - but control the GPIO from some - * where else than this driver. For that to work we - * should unset the is_enabled callback here. - * - * I believe such case where rohm,vout1-en-low is set - * and vout1-en-gpios is not is likely to be a - * misconfiguration. So let's just err out for now. - */ - dev_err(&pdev->dev, - "Failed to get VOUT1 control GPIO\n"); - return PTR_ERR(en); - } + else + return dev_err_probe(&pdev->dev, PTR_ERR(en), + "Failed to get VOUT1 control GPIO\n"); } /* @@ -1037,12 +1035,10 @@ static int bd957x_probe(struct platform_device *pdev) r->rdev = devm_regulator_register(&pdev->dev, desc, &config); - if (IS_ERR(r->rdev)) { - dev_err(&pdev->dev, - "failed to register %s regulator\n", - desc->name); - return PTR_ERR(r->rdev); - } + if (IS_ERR(r->rdev)) + return dev_err_probe(&pdev->dev, PTR_ERR(r->rdev), + "failed to register %s regulator\n", + desc->name); /* * Clear the VOUT1 GPIO setting - rest of the regulators do not * support GPIO control -- cgit v1.2.3 From 662a9bf883f42d09145cf083d93dadf0307f15ea Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Wed, 23 Nov 2022 14:00:38 +0200 Subject: regulator: bd718x7: Use dev_err_probe() The dev_err_probe() has (at least) following benefits over dev_err() when printing an error print for a failed function call at a device driver probe: - Omit error level print if error is 'EPRBE_DEFER' - Standardized print format for returned error - return the error value allowing shortening calls like: if (ret) { dev_err(...); return ret; } to if (ret) return dev_err_probe(...); Convert the ROHM BD718x7 regulator driver to use the dev_err_probe() when returned error is not hard-coded constant. NOTE: This commit also changes the error handling path to return immediately from a spot where the error is spotted instead of using a single point of exit. Signed-off-by: Matti Vaittinen Link: https://lore.kernel.org/r/fee54c2d04bb41b51381e31523f9ed31575206d2.1669203610.git.mazziesaccount@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/bd718x7-regulator.c | 51 +++++++++++++---------------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c index d161b0026f33..894fab0d53d0 100644 --- a/drivers/regulator/bd718x7-regulator.c +++ b/drivers/regulator/bd718x7-regulator.c @@ -1706,20 +1706,17 @@ static int bd718xx_probe(struct platform_device *pdev) break; default: dev_err(&pdev->dev, "Unsupported chip type\n"); - err = -EINVAL; - goto err; + return -EINVAL; } /* Register LOCK release */ err = regmap_update_bits(regmap, BD718XX_REG_REGLOCK, (REGLOCK_PWRSEQ | REGLOCK_VREG), 0); - if (err) { - dev_err(&pdev->dev, "Failed to unlock PMIC (%d)\n", err); - goto err; - } else { - dev_dbg(&pdev->dev, "Unlocked lock register 0x%x\n", - BD718XX_REG_REGLOCK); - } + if (err) + return dev_err_probe(&pdev->dev, err, "Failed to unlock PMIC\n"); + + dev_dbg(&pdev->dev, "Unlocked lock register 0x%x\n", + BD718XX_REG_REGLOCK); use_snvs = of_property_read_bool(pdev->dev.parent->of_node, "rohm,reset-snvs-powered"); @@ -1736,13 +1733,11 @@ static int bd718xx_probe(struct platform_device *pdev) BD718XX_WDOG_POWEROFF_MASK | BD718XX_KEY_L_POWEROFF_MASK, BD718XX_POWOFF_TO_RDY); - if (err) { - dev_err(&pdev->dev, "Failed to change reset target\n"); - goto err; - } else { - dev_dbg(&pdev->dev, - "Changed all resets from SVNS to READY\n"); - } + if (err) + return dev_err_probe(&pdev->dev, err, + "Failed to change reset target\n"); + + dev_dbg(&pdev->dev, "Changed all resets from SVNS to READY\n"); } config.dev = pdev->dev.parent; @@ -1778,13 +1773,10 @@ static int bd718xx_probe(struct platform_device *pdev) desc->ops = swops[i]; rdev = devm_regulator_register(&pdev->dev, desc, &config); - if (IS_ERR(rdev)) { - dev_err(&pdev->dev, - "failed to register %s regulator\n", - desc->name); - err = PTR_ERR(rdev); - goto err; - } + if (IS_ERR(rdev)) + return dev_err_probe(&pdev->dev, PTR_ERR(rdev), + "failed to register %s regulator\n", + desc->name); /* * Regulator register gets the regulator constraints and @@ -1807,28 +1799,23 @@ static int bd718xx_probe(struct platform_device *pdev) !rdev->constraints->boot_on)) { err = regmap_update_bits(regmap, r->init.reg, r->init.mask, r->init.val); - if (err) { - dev_err(&pdev->dev, + if (err) + return dev_err_probe(&pdev->dev, err, "Failed to take control for (%s)\n", desc->name); - goto err; - } } for (j = 0; j < r->additional_init_amnt; j++) { err = regmap_update_bits(regmap, r->additional_inits[j].reg, r->additional_inits[j].mask, r->additional_inits[j].val); - if (err) { - dev_err(&pdev->dev, + if (err) + return dev_err_probe(&pdev->dev, err, "Buck (%s) initialization failed\n", desc->name); - goto err; - } } } -err: return err; } -- cgit v1.2.3 From dc8d006d15b623c1d80b90b45d6dcb6e890dad09 Mon Sep 17 00:00:00 2001 From: Wang ShaoBo Date: Wed, 23 Nov 2022 11:46:16 +0800 Subject: regulator: core: use kfree_const() to free space conditionally Use kfree_const() to free supply_name conditionally in create_regulator() as supply_name may be allocated from kmalloc() or directly from .rodata section. Fixes: 87fe29b61f95 ("regulator: push allocations in create_regulator() outside of lock") Signed-off-by: Wang ShaoBo Link: https://lore.kernel.org/r/20221123034616.3609537-1-bobo.shaobowang@huawei.com Signed-off-by: Mark Brown --- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 3f6c6185c187..989b22249ca2 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1813,7 +1813,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); if (regulator == NULL) { - kfree(supply_name); + kfree_const(supply_name); return NULL; } -- cgit v1.2.3 From 7f69edba960bbdcbc829d8d0995b1117ce29e8b1 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:33 +0100 Subject: regulator: ad5398: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .probe_new() doesn't get the i2c_device_id * parameter, so determine that explicitly in the probe function. Signed-off-by: Uwe Kleine-König Acked-by: Michael Hennerich Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-540-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/ad5398.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index 75f432f61e91..2ba8ac1773d1 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c @@ -212,9 +212,9 @@ static const struct i2c_device_id ad5398_id[] = { }; MODULE_DEVICE_TABLE(i2c, ad5398_id); -static int ad5398_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ad5398_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct regulator_init_data *init_data = dev_get_platdata(&client->dev); struct regulator_config config = { }; struct ad5398_chip_info *chip; @@ -254,7 +254,7 @@ static int ad5398_probe(struct i2c_client *client, } static struct i2c_driver ad5398_driver = { - .probe = ad5398_probe, + .probe_new = ad5398_probe, .driver = { .name = "ad5398", }, -- cgit v1.2.3 From 87feccb347b25f5dc6ff451123b832c9ad5dddfe Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:38 +0100 Subject: regulator: lp872x: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .probe_new() doesn't get the i2c_device_id * parameter, so determine that explicitly in the probe function. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-545-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/lp872x.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 35d826fe9def..c576894c3d52 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -879,8 +879,9 @@ static struct lp872x_platform_data } #endif -static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id) +static int lp872x_probe(struct i2c_client *cl) { + const struct i2c_device_id *id = i2c_client_get_device_id(cl); struct lp872x *lp; struct lp872x_platform_data *pdata; int ret; @@ -946,7 +947,7 @@ static struct i2c_driver lp872x_driver = { .name = "lp872x", .of_match_table = of_match_ptr(lp872x_dt_ids), }, - .probe = lp872x_probe, + .probe_new = lp872x_probe, .id_table = lp872x_ids, }; -- cgit v1.2.3 From 78c8f6cdb51d471928d481ed3b2c82dbc110a1ed Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:40 +0100 Subject: regulator: ltc3589: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .probe_new() doesn't get the i2c_device_id * parameter, so determine that explicitly in the probe function. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-547-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/ltc3589.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/ltc3589.c b/drivers/regulator/ltc3589.c index 5e0b669c3a01..460d34c50fb0 100644 --- a/drivers/regulator/ltc3589.c +++ b/drivers/regulator/ltc3589.c @@ -378,9 +378,9 @@ static irqreturn_t ltc3589_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int ltc3589_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ltc3589_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct device *dev = &client->dev; struct regulator_desc *descs; struct ltc3589 *ltc3589; @@ -476,7 +476,7 @@ static struct i2c_driver ltc3589_driver = { .name = DRIVER_NAME, .of_match_table = of_match_ptr(ltc3589_of_match), }, - .probe = ltc3589_probe, + .probe_new = ltc3589_probe, .id_table = ltc3589_i2c_id, }; module_i2c_driver(ltc3589_driver); -- cgit v1.2.3 From dbf31dac703009174226bb87b3914bd092040327 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:43 +0100 Subject: regulator: max8660: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .probe_new() doesn't get the i2c_device_id * parameter, so determine that explicitly in the probe function. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-550-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/max8660.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 347043a5a9a7..711623be8eb5 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -367,9 +367,9 @@ static inline int max8660_pdata_from_dt(struct device *dev, } #endif -static int max8660_probe(struct i2c_client *client, - const struct i2c_device_id *i2c_id) +static int max8660_probe(struct i2c_client *client) { + const struct i2c_device_id *i2c_id = i2c_client_get_device_id(client); struct device *dev = &client->dev; struct max8660_platform_data pdata_of, *pdata = dev_get_platdata(dev); struct regulator_config config = { }; @@ -503,7 +503,7 @@ static const struct i2c_device_id max8660_id[] = { MODULE_DEVICE_TABLE(i2c, max8660_id); static struct i2c_driver max8660_driver = { - .probe = max8660_probe, + .probe_new = max8660_probe, .driver = { .name = "max8660", }, -- cgit v1.2.3 From 4e85e5d64f66ac5e4b0286ee4b6f8e8ce1044d42 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:45 +0100 Subject: regulator: max8973-regulator: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .probe_new() doesn't get the i2c_device_id * parameter, so determine that explicitly in the probe function. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-552-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/max8973-regulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c index 596cc36aaff6..7e00a45db26a 100644 --- a/drivers/regulator/max8973-regulator.c +++ b/drivers/regulator/max8973-regulator.c @@ -586,9 +586,9 @@ static const struct of_device_id of_max8973_match_tbl[] = { }; MODULE_DEVICE_TABLE(of, of_max8973_match_tbl); -static int max8973_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int max8973_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct max8973_regulator_platform_data *pdata; struct regulator_init_data *ridata; struct regulator_config config = { }; @@ -806,7 +806,7 @@ static struct i2c_driver max8973_i2c_driver = { .name = "max8973", .of_match_table = of_max8973_match_tbl, }, - .probe = max8973_probe, + .probe_new = max8973_probe, .id_table = max8973_id, }; -- cgit v1.2.3 From 18804160277ec2ab992373385f86c6af2322b28b Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:51 +0100 Subject: regulator: tps62360-regulator: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .probe_new() doesn't get the i2c_device_id * parameter, so determine that explicitly in the probe function. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-558-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/tps62360-regulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index 7c697bdf344e..da1b2b1341ae 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -322,9 +322,9 @@ static const struct of_device_id tps62360_of_match[] = { MODULE_DEVICE_TABLE(of, tps62360_of_match); #endif -static int tps62360_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int tps62360_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct regulator_config config = { }; struct tps62360_regulator_platform_data *pdata; struct regulator_dev *rdev; @@ -497,7 +497,7 @@ static struct i2c_driver tps62360_i2c_driver = { .name = "tps62360", .of_match_table = of_match_ptr(tps62360_of_match), }, - .probe = tps62360_probe, + .probe_new = tps62360_probe, .shutdown = tps62360_shutdown, .id_table = tps62360_id, }; -- cgit v1.2.3 From 3b5b07dde998f6ade7433a8db019cf816c7e35af Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:53 +0100 Subject: regulator: tps65023-regulator: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .probe_new() doesn't get the i2c_device_id * parameter, so determine that explicitly in the probe function. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-560-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/tps65023-regulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index d24333344f93..680a57ff0837 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -257,9 +257,9 @@ static struct tps_driver_data tps65023_drv_data = { .core_regulator = TPS65023_DCDC_1, }; -static int tps_65023_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int tps_65023_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct regulator_init_data *init_data = dev_get_platdata(&client->dev); struct regulator_config config = { }; struct tps_pmic *tps; @@ -336,7 +336,7 @@ static struct i2c_driver tps_65023_i2c_driver = { .name = "tps65023", .of_match_table = of_match_ptr(tps65023_of_match), }, - .probe = tps_65023_probe, + .probe_new = tps_65023_probe, .id_table = tps_65023_id, }; -- cgit v1.2.3 From 0a60d098261dfdf2d7e892ab1faf935fea612826 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Wed, 23 Nov 2022 17:36:37 +0200 Subject: regulator: dt-bindings: qcom,rpmh: Add compatible for PM8550 Add compatible string for PM8550 used in SM8550 boards. Signed-off-by: Abel Vesa Link: https://lore.kernel.org/r/20221123153638.721254-2-abel.vesa@linaro.org Signed-off-by: Mark Brown --- .../bindings/regulator/qcom,rpmh-regulator.yaml | 26 ++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml index 7ff51b558702..297a75069f60 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml @@ -47,6 +47,7 @@ description: | For PM8350, smps1 - smps12, ldo1 - ldo10 For PM8350C, smps1 - smps10, ldo1 - ldo13, bob For PM8450, smps1 - smps6, ldo1 - ldo4 + For PM8550, smps1 - smps6, ldo1 - ldo17, bob1 - bob2 For PM8998, smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2 For PMI8998, bob For PMR735A, smps1 - smps3, ldo1 - ldo7 @@ -70,6 +71,9 @@ properties: - qcom,pm8350-rpmh-regulators - qcom,pm8350c-rpmh-regulators - qcom,pm8450-rpmh-regulators + - qcom,pm8550-rpmh-regulators + - qcom,pm8550ve-rpmh-regulators + - qcom,pm8550vs-rpmh-regulators - qcom,pm8998-rpmh-regulators - qcom,pmg1110-rpmh-regulators - qcom,pmi8998-rpmh-regulators @@ -83,7 +87,7 @@ properties: RPMh resource name suffix used for the regulators found on this PMIC. $ref: /schemas/types.yaml#/definitions/string - enum: [a, b, c, d, e, f, h, k] + enum: [a, b, c, d, e, f, g, h, k] qcom,always-wait-for-ack: description: | @@ -107,7 +111,7 @@ properties: regulator-allow-set-load: ["regulator-allowed-modes"] patternProperties: - "^(smps|ldo|lvs)[0-9]+$": + "^(smps|ldo|lvs|bob)[0-9]+$": type: object $ref: "regulator.yaml#" description: smps/ldo regulator nodes(s). @@ -299,6 +303,24 @@ allOf: "^vdd-l[1-4]-supply$": true "^vdd-s[1-6]-supply$": true + - if: + properties: + compatible: + enum: + - qcom,pm8550-rpmh-regulators + - qcom,pm8550ve-rpmh-regulators + - qcom,pm8550vs-rpmh-regulators + then: + properties: + vdd-l2-l13-l14-supply: true + vdd-l5-l16-supply: true + vdd-l6-l7-supply: true + vdd-l8-l9-supply: true + patternProperties: + "^vdd-l([1-4]|1[0-7])-supply$": true + "^vdd-s[1-6]-supply$": true + "^vdd-bob[1-2]-supply$": true + - if: properties: compatible: -- cgit v1.2.3 From e6e3776d682d7f06e1a49be0d2a95dc6456f8be2 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Wed, 23 Nov 2022 17:36:38 +0200 Subject: regulator: qcom-rpmh: Add support for PM8550 regulators Add the rpmh regulators found in PM8550 PMIC and its variants, along with their compatibles and configuration data. They also contain some FT-SMPS 525, so add their configuration as well. Signed-off-by: Abel Vesa Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20221123153638.721254-3-abel.vesa@linaro.org Signed-off-by: Mark Brown --- drivers/regulator/qcom-rpmh-regulator.c | 81 +++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index f90bcdeecea5..43b5b9377714 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -731,6 +731,24 @@ static const struct rpmh_vreg_hw_data pmic5_ftsmps520 = { .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, }; +static const struct rpmh_vreg_hw_data pmic5_ftsmps525_lv = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 267, 4000), + .n_voltages = 268, + .pmic_mode_map = pmic_mode_map_pmic5_smps, + .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, +}; + +static const struct rpmh_vreg_hw_data pmic5_ftsmps525_mv = { + .regulator_type = VRM, + .ops = &rpmh_regulator_vrm_ops, + .voltage_range = REGULATOR_LINEAR_RANGE(600000, 0, 267, 8000), + .n_voltages = 268, + .pmic_mode_map = pmic_mode_map_pmic5_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, @@ -987,6 +1005,57 @@ static const struct rpmh_vreg_init_data pm8450_vreg_data[] = { {} }; +static const struct rpmh_vreg_init_data pm8550_vreg_data[] = { + RPMH_VREG("ldo1", "ldo%s1", &pmic5_pldo, "vdd-l1-l4-l10"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_pldo, "vdd-l2-l13-l14"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l1-l4-l10"), + RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l5-l16"), + RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo_lv, "vdd-l6-l7"), + RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo_lv, "vdd-l6-l7"), + RPMH_VREG("ldo8", "ldo%s8", &pmic5_pldo_lv, "vdd-l8-l9"), + RPMH_VREG("ldo9", "ldo%s9", &pmic5_pldo, "vdd-l8-l9"), + RPMH_VREG("ldo10", "ldo%s10", &pmic5_nldo, "vdd-l1-l4-l10"), + RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo, "vdd-l11"), + RPMH_VREG("ldo12", "ldo%s12", &pmic5_pldo, "vdd-l12"), + RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo, "vdd-l2-l13-l14"), + RPMH_VREG("ldo14", "ldo%s14", &pmic5_pldo, "vdd-l2-l13-l14"), + RPMH_VREG("ldo15", "ldo%s15", &pmic5_pldo, "vdd-l15"), + RPMH_VREG("ldo16", "ldo%s16", &pmic5_pldo, "vdd-l5-l16"), + RPMH_VREG("ldo17", "ldo%s17", &pmic5_pldo, "vdd-l17"), + RPMH_VREG("bob1", "bob%s1", &pmic5_bob, "vdd-bob1"), + RPMH_VREG("bob2", "bob%s2", &pmic5_bob, "vdd-bob2"), + {} +}; + +static const struct rpmh_vreg_init_data pm8550vs_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525_lv, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525_lv, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525_lv, "vdd-s3"), + RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525_lv, "vdd-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525_lv, "vdd-s5"), + RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525_mv, "vdd-s6"), + 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"), + {} +}; + +static const struct rpmh_vreg_init_data pm8550ve_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525_lv, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525_lv, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525_lv, "vdd-s3"), + RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525_lv, "vdd-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525_lv, "vdd-s5"), + RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525_lv, "vdd-s6"), + RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps525_lv, "vdd-s7"), + RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps525_lv, "vdd-s8"), + 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"), + {} +}; + 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"), @@ -1314,6 +1383,18 @@ static const struct of_device_id __maybe_unused rpmh_regulator_match_table[] = { .compatible = "qcom,pm8450-rpmh-regulators", .data = pm8450_vreg_data, }, + { + .compatible = "qcom,pm8550-rpmh-regulators", + .data = pm8550_vreg_data, + }, + { + .compatible = "qcom,pm8550ve-rpmh-regulators", + .data = pm8550ve_vreg_data, + }, + { + .compatible = "qcom,pm8550vs-rpmh-regulators", + .data = pm8550vs_vreg_data, + }, { .compatible = "qcom,pm8998-rpmh-regulators", .data = pm8998_vreg_data, -- cgit v1.2.3 From 3d2a78ae5df5d7f48c002e5f73d18d8c7628d266 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:32 +0100 Subject: regulator: act8865-regulator: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .probe_new() doesn't get the i2c_device_id * parameter, so determine that explicitly in the probe function. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-539-uwe@kleine-koenig.org 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 19b9742c9ecc..53f2c75cdeb4 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -651,9 +651,9 @@ static int act8600_charger_probe(struct device *dev, struct regmap *regmap) return PTR_ERR_OR_ZERO(charger); } -static int act8865_pmic_probe(struct i2c_client *client, - const struct i2c_device_id *i2c_id) +static int act8865_pmic_probe(struct i2c_client *client) { + const struct i2c_device_id *i2c_id = i2c_client_get_device_id(client); const struct regulator_desc *regulators; struct act8865_platform_data *pdata = NULL; struct device *dev = &client->dev; @@ -790,7 +790,7 @@ static struct i2c_driver act8865_pmic_driver = { .driver = { .name = "act8865", }, - .probe = act8865_pmic_probe, + .probe_new = act8865_pmic_probe, .id_table = act8865_ids, }; -- cgit v1.2.3 From 655425650f5e361224a86aa11bf3c044bf04df2a Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:35 +0100 Subject: regulator: fan53555: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .probe_new() doesn't get the i2c_device_id * parameter, so determine that explicitly in the probe function. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-542-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/fan53555.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index dac1fb584fa3..529963a7e4f5 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -549,9 +549,9 @@ static const struct of_device_id __maybe_unused fan53555_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, fan53555_dt_ids); -static int fan53555_regulator_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int fan53555_regulator_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct device_node *np = client->dev.of_node; struct fan53555_device_info *di; struct fan53555_platform_data *pdata; @@ -665,7 +665,7 @@ static struct i2c_driver fan53555_regulator_driver = { .name = "fan53555-regulator", .of_match_table = of_match_ptr(fan53555_dt_ids), }, - .probe = fan53555_regulator_probe, + .probe_new = fan53555_regulator_probe, .id_table = fan53555_id, }; -- cgit v1.2.3 From 69518d21deaa448be65b7c0be67aab230e88eaa7 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:36 +0100 Subject: regulator: isl6271a-regulator: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .probe_new() doesn't get the i2c_device_id * parameter, so determine that explicitly in the probe function. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-543-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/isl6271a-regulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index 591a64e1ca61..b23b052eab10 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -97,9 +97,9 @@ static const struct regulator_desc isl_rd[] = { }, }; -static int isl6271a_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int isl6271a_probe(struct i2c_client *i2c) { + const struct i2c_device_id *id = i2c_client_get_device_id(i2c); struct regulator_dev *rdev; struct regulator_config config = { }; struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev); @@ -148,7 +148,7 @@ static struct i2c_driver isl6271a_i2c_driver = { .driver = { .name = "isl6271a", }, - .probe = isl6271a_probe, + .probe_new = isl6271a_probe, .id_table = isl6271a_id, }; -- cgit v1.2.3 From 8348c710b51bac713a6fd2e07d64eb71d5680e2e Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:47 +0100 Subject: regulator: pfuze100-regulator: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .probe_new() doesn't get the i2c_device_id * parameter, so determine that explicitly in the probe function. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-554-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/pfuze100-regulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index d899d6e98fb8..9ab604289b5c 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -683,9 +683,9 @@ static const struct regmap_config pfuze_regmap_config = { .cache_type = REGCACHE_RBTREE, }; -static int pfuze100_regulator_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int pfuze100_regulator_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); struct pfuze_chip *pfuze_chip; struct regulator_config config = { }; int i, ret; @@ -847,7 +847,7 @@ static struct i2c_driver pfuze_driver = { .name = "pfuze100-regulator", .of_match_table = pfuze_dt_ids, }, - .probe = pfuze100_regulator_probe, + .probe_new = pfuze100_regulator_probe, }; module_i2c_driver(pfuze_driver); -- cgit v1.2.3 From c9f9ef15b84222f4cc686b1013ee3fd192b0bab8 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Nov 2022 23:44:48 +0100 Subject: regulator: pv88080-regulator: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .probe_new() doesn't get the i2c_device_id * parameter, so determine that explicitly in the probe function. Signed-off-by: Uwe Kleine-König Acked-for-MFD-by: Lee Jones Acked-for-Backlight-by: Lee Jones Link: https://lore.kernel.org/r/20221118224540.619276-555-uwe@kleine-koenig.org Signed-off-by: Mark Brown --- drivers/regulator/pv88080-regulator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c index 2a74cc05acfe..15a67c05f519 100644 --- a/drivers/regulator/pv88080-regulator.c +++ b/drivers/regulator/pv88080-regulator.c @@ -374,9 +374,9 @@ error_i2c: /* * I2C driver interface functions */ -static int pv88080_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int pv88080_i2c_probe(struct i2c_client *i2c) { + const struct i2c_device_id *id = i2c_client_get_device_id(i2c); struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev); struct pv88080 *chip; const struct pv88080_compatible_regmap *regmap_config; @@ -559,7 +559,7 @@ static struct i2c_driver pv88080_regulator_driver = { .name = "pv88080", .of_match_table = of_match_ptr(pv88080_dt_ids), }, - .probe = pv88080_i2c_probe, + .probe_new = pv88080_i2c_probe, .id_table = pv88080_i2c_id, }; -- cgit v1.2.3 From c4b02c92d9673ef4704fd0c8f008fec183517b64 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 24 Nov 2022 14:47:08 +0100 Subject: regulator: Drop obsolete dependencies on COMPILE_TEST Since commit 0166dc11be91 ("of: make CONFIG_OF user selectable"), it is possible to test-build any driver which depends on OF on any architecture by explicitly selecting OF. Therefore depending on COMPILE_TEST as an alternative is no longer needed. It is actually better to always build such drivers with OF enabled, so that the test builds are closer to how each driver will actually be built on its intended target. Building them without OF may not test much as the compiler will optimize out potentially large parts of the code. In the worst case, this could even pop false positive warnings. Dropping COMPILE_TEST here improves the quality of our testing and avoids wasting time on non-existent issues. As a minor optimization, this also lets us drop several occurrences of of_match_ptr(), __maybe_unused and some ifdef guarding, as we now know what all of this will resolve to, we might as well save cpp some work. Signed-off-by: Jean Delvare Cc: Liam Girdwood Cc: Mark Brown Cc: Icenowy Zheng Link: https://lore.kernel.org/r/20221124144708.64371b98@endymion.delvare Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 10 +++++----- drivers/regulator/fan53880.c | 16 +++++++--------- drivers/regulator/mp886x.c | 2 +- drivers/regulator/sy8106a-regulator.c | 4 ++-- drivers/regulator/sy8824x.c | 2 +- drivers/regulator/sy8827n.c | 4 +--- 6 files changed, 17 insertions(+), 21 deletions(-) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 4e4614d70bde..c0f200c3f122 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -377,7 +377,7 @@ config REGULATOR_FAN53555 config REGULATOR_FAN53880 tristate "Fairchild FAN53880 Regulator" - depends on I2C && (OF || COMPILE_TEST) + depends on I2C && OF select REGMAP_I2C help This driver supports Fairchild (ON Semiconductor) FAN53880 @@ -743,7 +743,7 @@ config REGULATOR_MP8859 config REGULATOR_MP886X tristate "MPS MP8869 regulator driver" - depends on I2C && (OF || COMPILE_TEST) + depends on I2C && OF select REGMAP_I2C help This driver supports the MP8869 voltage regulator. @@ -1299,21 +1299,21 @@ config REGULATOR_SY7636A config REGULATOR_SY8106A tristate "Silergy SY8106A regulator" - depends on I2C && (OF || COMPILE_TEST) + depends on I2C && OF select REGMAP_I2C help This driver supports SY8106A single output regulator. config REGULATOR_SY8824X tristate "Silergy SY8824C/SY8824E regulator" - depends on I2C && (OF || COMPILE_TEST) + depends on I2C && OF select REGMAP_I2C help This driver supports SY8824C single output regulator. config REGULATOR_SY8827N tristate "Silergy SY8827N regulator" - depends on I2C && (OF || COMPILE_TEST) + depends on I2C && OF select REGMAP_I2C help This driver supports SY8827N single output regulator. diff --git a/drivers/regulator/fan53880.c b/drivers/regulator/fan53880.c index 8f25930d2769..1d88d5381544 100644 --- a/drivers/regulator/fan53880.c +++ b/drivers/regulator/fan53880.c @@ -42,8 +42,8 @@ static const struct regulator_ops fan53880_ops = { #define FAN53880_LDO(_num, _supply, _default) \ [FAN53880_LDO ## _num] = { \ .name = "LDO"#_num, \ - .of_match = of_match_ptr("LDO"#_num), \ - .regulators_node = of_match_ptr("regulators"), \ + .of_match = "LDO"#_num, \ + .regulators_node = "regulators", \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ .linear_ranges = (struct linear_range[]) { \ @@ -68,8 +68,8 @@ static const struct regulator_desc fan53880_regulators[] = { FAN53880_LDO(4, "VIN4", 1800000), [FAN53880_BUCK] = { .name = "BUCK", - .of_match = of_match_ptr("BUCK"), - .regulators_node = of_match_ptr("regulators"), + .of_match = "BUCK", + .regulators_node = "regulators", .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .linear_ranges = (struct linear_range[]) { @@ -88,8 +88,8 @@ static const struct regulator_desc fan53880_regulators[] = { }, [FAN53880_BOOST] = { .name = "BOOST", - .of_match = of_match_ptr("BOOST"), - .regulators_node = of_match_ptr("regulators"), + .of_match = "BOOST", + .regulators_node = "regulators", .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .linear_ranges = (struct linear_range[]) { @@ -157,13 +157,11 @@ static int fan53880_i2c_probe(struct i2c_client *i2c) return 0; } -#ifdef CONFIG_OF static const struct of_device_id fan53880_dt_ids[] = { { .compatible = "onnn,fan53880", }, {} }; MODULE_DEVICE_TABLE(of, fan53880_dt_ids); -#endif static const struct i2c_device_id fan53880_i2c_id[] = { { "fan53880", }, @@ -174,7 +172,7 @@ MODULE_DEVICE_TABLE(i2c, fan53880_i2c_id); static struct i2c_driver fan53880_regulator_driver = { .driver = { .name = "fan53880", - .of_match_table = of_match_ptr(fan53880_dt_ids), + .of_match_table = fan53880_dt_ids, }, .probe_new = fan53880_i2c_probe, .id_table = fan53880_i2c_id, diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c index 8ad4722eca4b..6a0c94c15027 100644 --- a/drivers/regulator/mp886x.c +++ b/drivers/regulator/mp886x.c @@ -362,7 +362,7 @@ MODULE_DEVICE_TABLE(i2c, mp886x_id); static struct i2c_driver mp886x_regulator_driver = { .driver = { .name = "mp886x-regulator", - .of_match_table = of_match_ptr(mp886x_dt_ids), + .of_match_table = mp886x_dt_ids, }, .probe_new = mp886x_i2c_probe, .id_table = mp886x_id, diff --git a/drivers/regulator/sy8106a-regulator.c b/drivers/regulator/sy8106a-regulator.c index c119f85259a5..b10bd99768a3 100644 --- a/drivers/regulator/sy8106a-regulator.c +++ b/drivers/regulator/sy8106a-regulator.c @@ -123,7 +123,7 @@ static int sy8106a_i2c_probe(struct i2c_client *i2c) return 0; } -static const struct of_device_id __maybe_unused sy8106a_i2c_of_match[] = { +static const struct of_device_id sy8106a_i2c_of_match[] = { { .compatible = "silergy,sy8106a" }, { }, }; @@ -138,7 +138,7 @@ MODULE_DEVICE_TABLE(i2c, sy8106a_i2c_id); static struct i2c_driver sy8106a_regulator_driver = { .driver = { .name = "sy8106a", - .of_match_table = of_match_ptr(sy8106a_i2c_of_match), + .of_match_table = sy8106a_i2c_of_match, }, .probe_new = sy8106a_i2c_probe, .id_table = sy8106a_i2c_id, diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c index 5e915cf307b3..2a81519bdf67 100644 --- a/drivers/regulator/sy8824x.c +++ b/drivers/regulator/sy8824x.c @@ -233,7 +233,7 @@ 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), + .of_match_table = sy8824_dt_ids, }, .probe_new = sy8824_i2c_probe, .id_table = sy8824_id, diff --git a/drivers/regulator/sy8827n.c b/drivers/regulator/sy8827n.c index 7d5d9f879ce3..936a94b6df5b 100644 --- a/drivers/regulator/sy8827n.c +++ b/drivers/regulator/sy8827n.c @@ -170,7 +170,6 @@ static int sy8827n_i2c_probe(struct i2c_client *client) return ret; } -#ifdef CONFIG_OF static const struct of_device_id sy8827n_dt_ids[] = { { .compatible = "silergy,sy8827n", @@ -178,7 +177,6 @@ static const struct of_device_id sy8827n_dt_ids[] = { { } }; MODULE_DEVICE_TABLE(of, sy8827n_dt_ids); -#endif static const struct i2c_device_id sy8827n_id[] = { { "sy8827n", }, @@ -189,7 +187,7 @@ MODULE_DEVICE_TABLE(i2c, sy8827n_id); static struct i2c_driver sy8827n_regulator_driver = { .driver = { .name = "sy8827n-regulator", - .of_match_table = of_match_ptr(sy8827n_dt_ids), + .of_match_table = sy8827n_dt_ids, }, .probe_new = sy8827n_i2c_probe, .id_table = sy8827n_id, -- cgit v1.2.3 From 647e57351f8ebc37d8e12cbc0f4bf7471754a0cc Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Thu, 20 Oct 2022 22:42:40 +0200 Subject: regulator: rk808: reduce 'struct rk808' usage Reduce usage of 'struct rk808' (driver data of the parent MFD), so that only the chip variant field is still being accessed directly. This allows restructuring the MFD driver to support SPI based PMICs. Acked-by: Mark Brown Signed-off-by: Sebastian Reichel Link: https://lore.kernel.org/r/20221020204251.108565-3-sebastian.reichel@collabora.com Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 127dc2e2e690..ce9c64cadeba 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -14,7 +14,6 @@ #include #include -#include #include #include #include @@ -1286,19 +1285,23 @@ dt_parse_end: static int rk808_regulator_probe(struct platform_device *pdev) { struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); - struct i2c_client *client = rk808->i2c; struct regulator_config config = {}; struct regulator_dev *rk808_rdev; struct rk808_regulator_data *pdata; const struct regulator_desc *regulators; + struct regmap *regmap; int ret, i, nregulators; + regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!regmap) + return -ENODEV; + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; - ret = rk808_regulator_dt_parse_pdata(&pdev->dev, &client->dev, - rk808->regmap, pdata); + ret = rk808_regulator_dt_parse_pdata(&pdev->dev, pdev->dev.parent, + regmap, pdata); if (ret < 0) return ret; @@ -1326,21 +1329,22 @@ static int rk808_regulator_probe(struct platform_device *pdev) nregulators = RK818_NUM_REGULATORS; break; default: - dev_err(&client->dev, "unsupported RK8XX ID %lu\n", + dev_err(&pdev->dev, "unsupported RK8XX ID %lu\n", rk808->variant); return -EINVAL; } - config.dev = &client->dev; + config.dev = &pdev->dev; + config.dev->of_node = pdev->dev.parent->of_node; config.driver_data = pdata; - config.regmap = rk808->regmap; + config.regmap = regmap; /* Instantiate the regulators */ for (i = 0; i < nregulators; i++) { rk808_rdev = devm_regulator_register(&pdev->dev, ®ulators[i], &config); if (IS_ERR(rk808_rdev)) { - dev_err(&client->dev, + dev_err(&pdev->dev, "failed to register %d regulator\n", i); return PTR_ERR(rk808_rdev); } -- cgit v1.2.3 From f39f8709c217d82aabbf51d8669731137ce09aea Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Thu, 20 Oct 2022 22:42:49 +0200 Subject: regulator: rk808: Use dev_err_probe Print error message for potential EPROBE_DEFER error using dev_err_probe, which captures the reason in /sys/kernel/debug/devices_deferred and otherwise silences the message. Signed-off-by: Sebastian Reichel Link: https://lore.kernel.org/r/20221020204251.108565-12-sebastian.reichel@collabora.com Signed-off-by: Mark Brown --- drivers/regulator/rk808-regulator.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index ce9c64cadeba..fa9fc1aa1ae3 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -1343,11 +1343,9 @@ static int rk808_regulator_probe(struct platform_device *pdev) for (i = 0; i < nregulators; i++) { rk808_rdev = devm_regulator_register(&pdev->dev, ®ulators[i], &config); - if (IS_ERR(rk808_rdev)) { - dev_err(&pdev->dev, - "failed to register %d regulator\n", i); - return PTR_ERR(rk808_rdev); - } + if (IS_ERR(rk808_rdev)) + return dev_err_probe(&pdev->dev, PTR_ERR(rk808_rdev), + "failed to register %d regulator\n", i); } return 0; -- cgit v1.2.3 From 0591b14ce0398125439c759f889647369aa616a0 Mon Sep 17 00:00:00 2001 From: Rui Zhang Date: Thu, 1 Dec 2022 11:38:06 +0800 Subject: regulator: core: fix use_count leakage when handling boot-on MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I found a use_count leakage towards supply regulator of rdev with boot-on option. ┌───────────────────┐ ┌───────────────────┐ │ regulator_dev A │ │ regulator_dev B │ │ (boot-on) │ │ (boot-on) │ │ use_count=0 │◀──supply──│ use_count=1 │ │ │ │ │ └───────────────────┘ └───────────────────┘ In case of rdev(A) configured with `regulator-boot-on', the use_count of supplying regulator(B) will increment inside regulator_enable(rdev->supply). Thus, B will acts like always-on, and further balanced regulator_enable/disable cannot actually disable it anymore. However, B was also configured with `regulator-boot-on', we wish it could be disabled afterwards. Signed-off-by: Rui Zhang Link: https://lore.kernel.org/r/20221201033806.2567812-1-zr.zhang@vivo.com Signed-off-by: Mark Brown --- drivers/regulator/core.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 989b22249ca2..866401f3fb10 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1596,7 +1596,13 @@ static int set_machine_constraints(struct regulator_dev *rdev) if (rdev->supply_name && !rdev->supply) return -EPROBE_DEFER; - if (rdev->supply) { + /* If supplying regulator has already been enabled, + * it's not intended to have use_count increment + * when rdev is only boot-on. + */ + if (rdev->supply && + (rdev->constraints->always_on || + !regulator_is_enabled(rdev->supply))) { ret = regulator_enable(rdev->supply); if (ret < 0) { _regulator_put(rdev->supply); -- cgit v1.2.3 From da46ee19cbd8344d6860816b4827a7ce95764867 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Thu, 1 Dec 2022 20:27:05 +0800 Subject: regulator: core: fix module refcount leak in set_supply() If create_regulator() fails in set_supply(), the module refcount needs be put to keep refcount balanced. Fixes: e2c09ae7a74d ("regulator: core: Increase refcount for regulator supply's module") Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20221201122706.4055992-2-yangyingliang@huawei.com Signed-off-by: Mark Brown --- drivers/regulator/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 866401f3fb10..76630c2c4180 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1646,6 +1646,7 @@ static int set_supply(struct regulator_dev *rdev, rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); if (rdev->supply == NULL) { + module_put(supply_rdev->owner); err = -ENOMEM; return err; } -- cgit v1.2.3 From ba62319a42c50e6254e98b3f316464fac8e77968 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Fri, 2 Dec 2022 10:51:11 +0800 Subject: regulator: core: fix resource leak in regulator_register() I got some resource leak reports while doing fault injection test: OF: ERROR: memory leak, expected refcount 1 instead of 100, of_node_get()/of_node_put() unbalanced - destroy cset entry: attach overlay node /i2c/pmic@64/regulators/buck1 unreferenced object 0xffff88810deea000 (size 512): comm "490-i2c-rt5190a", pid 253, jiffies 4294859840 (age 5061.046s) hex dump (first 32 bytes): 00 00 00 00 ad 4e ad de ff ff ff ff 00 00 00 00 .....N.......... ff ff ff ff ff ff ff ff a0 1e 00 a1 ff ff ff ff ................ backtrace: [<00000000d78541e2>] kmalloc_trace+0x21/0x110 [<00000000b343d153>] device_private_init+0x32/0xd0 [<00000000be1f0c70>] device_add+0xb2d/0x1030 [<00000000e3e6344d>] regulator_register+0xaf2/0x12a0 [<00000000e2f5e754>] devm_regulator_register+0x57/0xb0 [<000000008b898197>] rt5190a_probe+0x52a/0x861 [rt5190a_regulator] unreferenced object 0xffff88810b617b80 (size 32): comm "490-i2c-rt5190a", pid 253, jiffies 4294859904 (age 5060.983s) hex dump (first 32 bytes): 72 65 67 75 6c 61 74 6f 72 2e 32 38 36 38 2d 53 regulator.2868-S 55 50 50 4c 59 00 ff ff 29 00 00 00 2b 00 00 00 UPPLY...)...+... backtrace: [<000000009da9280d>] __kmalloc_node_track_caller+0x44/0x1b0 [<0000000025c6a4e5>] kstrdup+0x3a/0x70 [<00000000790efb69>] create_regulator+0xc0/0x4e0 [<0000000005ed203a>] regulator_resolve_supply+0x2d4/0x440 [<0000000045796214>] regulator_register+0x10b3/0x12a0 [<00000000e2f5e754>] devm_regulator_register+0x57/0xb0 [<000000008b898197>] rt5190a_probe+0x52a/0x861 [rt5190a_regulator] After calling regulator_resolve_supply(), the 'rdev->supply' is set by set_supply(), after this set, in the error path, the resources need be released, so call regulator_put() to avoid the leaks. Fixes: aea6cb99703e ("regulator: resolve supply after creating regulator") Fixes: 8a866d527ac0 ("regulator: core: Resolve supply name earlier to prevent double-init") Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20221202025111.496402-1-yangyingliang@huawei.com Signed-off-by: Mark Brown --- drivers/regulator/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 76630c2c4180..8258facc697b 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -5654,6 +5654,7 @@ unset_supplies: regulator_remove_coupling(rdev); mutex_unlock(®ulator_list_mutex); wash: + regulator_put(rdev->supply); kfree(rdev->coupling_desc.coupled_rdevs); mutex_lock(®ulator_list_mutex); regulator_ena_gpio_free(rdev); -- cgit v1.2.3 From b4387db19d7f1caf166852782a5f0e5a393bdf24 Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Tue, 29 Nov 2022 16:57:01 +0100 Subject: regulator: dt-bindings: Add binding schema for mt6357 regulators Add YAML schema for the MediaTek MT6357 regulators. Signed-off-by: Fabien Parent Reviewed-by: Krzysztof Kozlowski Signed-off-by: Alexandre Mergnat Link: https://lore.kernel.org/r/20221005-mt6357-support-v7-2-477e60126749@baylibre.com Signed-off-by: Mark Brown --- .../regulator/mediatek,mt6357-regulator.yaml | 294 +++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 Documentation/devicetree/bindings/regulator/mediatek,mt6357-regulator.yaml diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6357-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6357-regulator.yaml new file mode 100644 index 000000000000..6327bb2f6ee0 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6357-regulator.yaml @@ -0,0 +1,294 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/mediatek,mt6357-regulator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT6357 Regulators + +maintainers: + - Chen Zhong + - Fabien Parent + - Alexandre Mergnat + +description: | + The MT6357 PMIC provides 5 BUCK and 29 LDO. + Regulators and nodes are named according to the regulator type: + - buck- + - ldo-. + MT6357 regulators node should be sub node of the MT6397 MFD node. + +patternProperties: + "^buck-v(core|modem|pa|proc|s1)$": + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + description: + Properties for single BUCK regulator. + + required: + - regulator-name + - regulator-min-microvolt + - regulator-max-microvolt + + "^ldo-v(camio18|aud28|aux18|io18|io28|rf12|rf18|cn18|cn28|fe28)$": + type: object + $ref: fixed-regulator.yaml# + unevaluatedProperties: false + description: + Properties for single fixed LDO regulator. + + required: + - regulator-name + - regulator-min-microvolt + - regulator-max-microvolt + + "^ldo-v(efuse|ibr|ldo28|mch|cama|camd|cn33-bt|cn33-wifi)$": + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + description: + Properties for single LDO regulator. + + required: + - regulator-name + - regulator-min-microvolt + - regulator-max-microvolt + + "^ldo-v(xo22|emc|mc|sim1|sim2|sram-others|sram-proc|dram|usb33)$": + type: object + $ref: regulator.yaml# + unevaluatedProperties: false + description: + Properties for single LDO regulator. + + required: + - regulator-name + - regulator-min-microvolt + - regulator-max-microvolt + +additionalProperties: false + +examples: + - | + pmic { + regulators { + mt6357_vproc_reg: buck-vproc { + regulator-name = "vproc"; + regulator-min-microvolt = <518750>; + regulator-max-microvolt = <1312500>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <220>; + regulator-always-on; + }; + mt6357_vcore_reg: buck-vcore { + regulator-name = "vcore"; + regulator-min-microvolt = <518750>; + regulator-max-microvolt = <1312500>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <220>; + regulator-always-on; + }; + mt6357_vmodem_reg: buck-vmodem { + regulator-name = "vmodem"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1193750>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <220>; + }; + mt6357_vs1_reg: buck-vs1 { + regulator-name = "vs1"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <2200000>; + regulator-ramp-delay = <12500>; + regulator-enable-ramp-delay = <220>; + regulator-always-on; + }; + mt6357_vpa_reg: buck-vpa { + regulator-name = "vpa"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <3650000>; + regulator-ramp-delay = <50000>; + regulator-enable-ramp-delay = <220>; + }; + mt6357_vfe28_reg: ldo-vfe28 { + compatible = "regulator-fixed"; + regulator-name = "vfe28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vxo22_reg: ldo-vxo22 { + regulator-name = "vxo22"; + regulator-min-microvolt = <2200000>; + regulator-max-microvolt = <2400000>; + regulator-enable-ramp-delay = <110>; + }; + mt6357_vrf18_reg: ldo-vrf18 { + compatible = "regulator-fixed"; + regulator-name = "vrf18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <110>; + }; + mt6357_vrf12_reg: ldo-vrf12 { + compatible = "regulator-fixed"; + regulator-name = "vrf12"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-enable-ramp-delay = <110>; + }; + mt6357_vefuse_reg: ldo-vefuse { + regulator-name = "vefuse"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vcn33_bt_reg: ldo-vcn33-bt { + regulator-name = "vcn33-bt"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3500000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vcn33_wifi_reg: ldo-vcn33-wifi { + regulator-name = "vcn33-wifi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3500000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vcn28_reg: ldo-vcn28 { + compatible = "regulator-fixed"; + regulator-name = "vcn28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vcn18_reg: ldo-vcn18 { + compatible = "regulator-fixed"; + regulator-name = "vcn18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vcama_reg: ldo-vcama { + regulator-name = "vcama"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vcamd_reg: ldo-vcamd { + regulator-name = "vcamd"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vcamio_reg: ldo-vcamio18 { + compatible = "regulator-fixed"; + regulator-name = "vcamio"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vldo28_reg: ldo-vldo28 { + regulator-name = "vldo28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3000000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vsram_others_reg: ldo-vsram-others { + regulator-name = "vsram-others"; + regulator-min-microvolt = <518750>; + regulator-max-microvolt = <1312500>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <110>; + regulator-always-on; + }; + mt6357_vsram_proc_reg: ldo-vsram-proc { + regulator-name = "vsram-proc"; + regulator-min-microvolt = <518750>; + regulator-max-microvolt = <1312500>; + regulator-ramp-delay = <6250>; + regulator-enable-ramp-delay = <110>; + regulator-always-on; + }; + mt6357_vaux18_reg: ldo-vaux18 { + compatible = "regulator-fixed"; + regulator-name = "vaux18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vaud28_reg: ldo-vaud28 { + compatible = "regulator-fixed"; + regulator-name = "vaud28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vio28_reg: ldo-vio28 { + compatible = "regulator-fixed"; + regulator-name = "vio28"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vio18_reg: ldo-vio18 { + compatible = "regulator-fixed"; + regulator-name = "vio18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-enable-ramp-delay = <264>; + regulator-always-on; + }; + mt6357_vdram_reg: ldo-vdram { + regulator-name = "vdram"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1200000>; + regulator-enable-ramp-delay = <3300>; + }; + mt6357_vmc_reg: ldo-vmc { + regulator-name = "vmc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <44>; + }; + mt6357_vmch_reg: ldo-vmch { + regulator-name = "vmch"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <44>; + }; + mt6357_vemc_reg: ldo-vemc { + regulator-name = "vemc"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <44>; + regulator-always-on; + }; + mt6357_vsim1_reg: ldo-vsim1 { + regulator-name = "vsim1"; + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <3100000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vsim2_reg: ldo-vsim2 { + regulator-name = "vsim2"; + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <3100000>; + regulator-enable-ramp-delay = <264>; + }; + mt6357_vibr_reg: ldo-vibr { + regulator-name = "vibr"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3300000>; + regulator-enable-ramp-delay = <44>; + }; + mt6357_vusb33_reg: ldo-vusb33 { + regulator-name = "vusb33"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3100000>; + regulator-enable-ramp-delay = <264>; + }; + }; + }; +... -- cgit v1.2.3 From dafc7cde23dca239987d3cd000b11cdccc3728ea Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Tue, 29 Nov 2022 16:57:06 +0100 Subject: regulator: add mt6357 regulator Add regulator driver for the MT6357 PMIC. Signed-off-by: Fabien Parent Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Alexandre Mergnat Link: https://lore.kernel.org/r/20221005-mt6357-support-v7-7-477e60126749@baylibre.com Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 9 + drivers/regulator/Makefile | 1 + drivers/regulator/mt6357-regulator.c | 453 +++++++++++++++++++++++++++++ include/linux/regulator/mt6357-regulator.h | 51 ++++ 4 files changed, 514 insertions(+) create mode 100644 drivers/regulator/mt6357-regulator.c create mode 100644 include/linux/regulator/mt6357-regulator.h diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index c0f200c3f122..820c9a0788e5 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -805,6 +805,15 @@ config REGULATOR_MT6332 This driver supports the control of different power rails of device through regulator interface +config REGULATOR_MT6357 + tristate "MediaTek MT6357 PMIC" + depends on MFD_MT6397 + help + Say y here to select this option to enable the power regulator of + MediaTek MT6357 PMIC. + 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 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index c3b5cf6cceab..b9f5eb35bf5f 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -97,6 +97,7 @@ obj-$(CONFIG_REGULATOR_MT6315) += mt6315-regulator.o obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o obj-$(CONFIG_REGULATOR_MT6331) += mt6331-regulator.o obj-$(CONFIG_REGULATOR_MT6332) += mt6332-regulator.o +obj-$(CONFIG_REGULATOR_MT6357) += mt6357-regulator.o obj-$(CONFIG_REGULATOR_MT6358) += mt6358-regulator.o obj-$(CONFIG_REGULATOR_MT6359) += mt6359-regulator.o obj-$(CONFIG_REGULATOR_MT6360) += mt6360-regulator.o diff --git a/drivers/regulator/mt6357-regulator.c b/drivers/regulator/mt6357-regulator.c new file mode 100644 index 000000000000..b2352b96aed2 --- /dev/null +++ b/drivers/regulator/mt6357-regulator.c @@ -0,0 +1,453 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2022 MediaTek Inc. +// Copyright (c) 2022 BayLibre, SAS. +// Author: Chen Zhong +// Author: Fabien Parent +// Author: Alexandre Mergnat +// +// Based on mt6397-regulator.c +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * MT6357 regulators' information + * + * @desc: standard fields of regulator description. + * @da_vsel_reg: Monitor register for query buck's voltage. + * @da_vsel_mask: Mask for query buck's voltage. + */ +struct mt6357_regulator_info { + struct regulator_desc desc; + u32 da_vsel_reg; + u32 da_vsel_mask; +}; + +#define MT6357_BUCK(match, vreg, min, max, step, \ + volt_ranges, vosel_reg, vosel_mask, _da_vsel_mask) \ +[MT6357_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .regulators_node = "regulators", \ + .ops = &mt6357_volt_range_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6357_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_reg, \ + .vsel_mask = vosel_mask, \ + .enable_reg = MT6357_BUCK_##vreg##_CON0, \ + .enable_mask = BIT(0), \ + }, \ + .da_vsel_reg = MT6357_BUCK_##vreg##_DBG0, \ + .da_vsel_mask = vosel_mask, \ +} + +#define MT6357_LDO(match, vreg, ldo_volt_table, \ + enreg, vosel, vosel_mask) \ +[MT6357_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .regulators_node = "regulators", \ + .ops = &mt6357_volt_table_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6357_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(0), \ + }, \ +} + +#define MT6357_LDO1(match, vreg, min, max, step, volt_ranges, \ + enreg, vosel, vosel_mask) \ +[MT6357_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .regulators_node = "regulators", \ + .ops = &mt6357_volt_range_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6357_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 = enreg, \ + .enable_mask = BIT(0), \ + }, \ + .da_vsel_reg = MT6357_LDO_##vreg##_DBG0, \ + .da_vsel_mask = 0x7f00, \ +} + +#define MT6357_REG_FIXED(match, vreg, volt) \ +[MT6357_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .regulators_node = "regulators", \ + .ops = &mt6357_volt_fixed_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6357_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = 1, \ + .enable_reg = MT6357_LDO_##vreg##_CON0, \ + .enable_mask = BIT(0), \ + .min_uV = volt, \ + }, \ +} + +/** + * mt6357_get_buck_voltage_sel - get_voltage_sel for regmap users + * + * @rdev: regulator to operate on + * + * Regulators that use regmap for their register I/O can set the + * da_vsel_reg and da_vsel_mask fields in the info structure and + * then use this as their get_voltage_vsel operation. + */ +static int mt6357_get_buck_voltage_sel(struct regulator_dev *rdev) +{ + int ret, regval; + struct mt6357_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 mt6357 Buck %s vsel reg: %d\n", + info->desc.name, ret); + return ret; + } + + regval &= info->da_vsel_mask; + regval >>= ffs(info->da_vsel_mask) - 1; + + return regval; +} + +static const struct regulator_ops mt6357_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 = mt6357_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, +}; + +static const struct regulator_ops mt6357_volt_table_ops = { + .list_voltage = regulator_list_voltage_table, + .map_voltage = regulator_map_voltage_iterate, + .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, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + +static const struct regulator_ops mt6357_volt_fixed_ops = { + .list_voltage = regulator_list_voltage_linear, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + +static const int vxo22_voltages[] = { + 2200000, + 0, + 2400000, +}; + +static const int vefuse_voltages[] = { + 1200000, + 1300000, + 1500000, + 0, + 1800000, + 0, + 0, + 0, + 0, + 2800000, + 2900000, + 3000000, + 0, + 3300000, +}; + +static const int vcn33_voltages[] = { + 0, + 3300000, + 3400000, + 3500000, +}; + +static const int vcama_voltages[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2500000, + 0, + 0, + 2800000, +}; + +static const int vcamd_voltages[] = { + 0, + 0, + 0, + 0, + 1000000, + 1100000, + 1200000, + 1300000, + 0, + 1500000, + 0, + 0, + 1800000, +}; + +static const int vldo28_voltages[] = { + 0, + 2800000, + 0, + 3000000, +}; + +static const int vdram_voltages[] = { + 0, + 1100000, + 1200000, +}; + +static const int vsim_voltages[] = { + 0, + 0, + 0, + 1700000, + 1800000, + 0, + 0, + 0, + 2700000, + 0, + 0, + 3000000, + 3100000, +}; + +static const int vibr_voltages[] = { + 1200000, + 1300000, + 1500000, + 0, + 1800000, + 2000000, + 0, + 0, + 0, + 2800000, + 0, + 3000000, + 0, + 3300000, +}; + +static const int vmc_voltages[] = { + 0, + 0, + 0, + 0, + 1800000, + 0, + 0, + 0, + 0, + 0, + 2900000, + 3000000, + 0, + 3300000, +}; + +static const int vmch_voltages[] = { + 0, + 0, + 2900000, + 3000000, + 0, + 3300000, +}; + +static const int vemc_voltages[] = { + 0, + 0, + 2900000, + 3000000, + 0, + 3300000, +}; + +static const int vusb_voltages[] = { + 0, + 0, + 0, + 3000000, + 3100000, +}; + +static const struct linear_range buck_volt_range1[] = { + REGULATOR_LINEAR_RANGE(518750, 0, 0x7f, 6250), +}; + +static const struct linear_range buck_volt_range2[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 6250), +}; + +static const struct linear_range buck_volt_range3[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000), +}; + +static const struct linear_range buck_volt_range4[] = { + REGULATOR_LINEAR_RANGE(1200000, 0, 0x7f, 12500), +}; + +/* The array is indexed by id(MT6357_ID_XXX) */ +static struct mt6357_regulator_info mt6357_regulators[] = { + /* Bucks */ + MT6357_BUCK("buck-vcore", VCORE, 518750, 1312500, 6250, + buck_volt_range1, MT6357_BUCK_VCORE_ELR0, 0x7f, 0x7f), + MT6357_BUCK("buck-vproc", VPROC, 518750, 1312500, 6250, + buck_volt_range1, MT6357_BUCK_VPROC_ELR0, 0x7f, 0x7f), + MT6357_BUCK("buck-vmodem", VMODEM, 500000, 1293750, 6250, + buck_volt_range2, MT6357_BUCK_VMODEM_ELR0, 0x7f, 0x7f), + MT6357_BUCK("buck-vpa", VPA, 500000, 3650000, 50000, + buck_volt_range3, MT6357_BUCK_VPA_CON1, 0x3f, 0x3f), + MT6357_BUCK("buck-vs1", VS1, 1200000, 2787500, 12500, + buck_volt_range4, MT6357_BUCK_VS1_ELR0, 0x7f, 0x7f), + + /* LDOs */ + MT6357_LDO("ldo-vcama", VCAMA, vcama_voltages, + MT6357_LDO_VCAMA_CON0, MT6357_VCAMA_ANA_CON0, 0xf00), + MT6357_LDO("ldo-vcamd", VCAMD, vcamd_voltages, + MT6357_LDO_VCAMD_CON0, MT6357_VCAMD_ANA_CON0, 0xf00), + MT6357_LDO("ldo-vcn33-bt", VCN33_BT, vcn33_voltages, + MT6357_LDO_VCN33_CON0_0, MT6357_VCN33_ANA_CON0, 0x300), + MT6357_LDO("ldo-vcn33-wifi", VCN33_WIFI, vcn33_voltages, + MT6357_LDO_VCN33_CON0_1, MT6357_VCN33_ANA_CON0, 0x300), + MT6357_LDO("ldo-vdram", VDRAM, vdram_voltages, + MT6357_LDO_VDRAM_CON0, MT6357_VDRAM_ELR_2, 0x300), + MT6357_LDO("ldo-vefuse", VEFUSE, vefuse_voltages, + MT6357_LDO_VEFUSE_CON0, MT6357_VEFUSE_ANA_CON0, 0xf00), + MT6357_LDO("ldo-vemc", VEMC, vemc_voltages, + MT6357_LDO_VEMC_CON0, MT6357_VEMC_ANA_CON0, 0x700), + MT6357_LDO("ldo-vibr", VIBR, vibr_voltages, + MT6357_LDO_VIBR_CON0, MT6357_VIBR_ANA_CON0, 0xf00), + MT6357_LDO("ldo-vldo28", VLDO28, vldo28_voltages, + MT6357_LDO_VLDO28_CON0_0, MT6357_VLDO28_ANA_CON0, 0x300), + MT6357_LDO("ldo-vmc", VMC, vmc_voltages, + MT6357_LDO_VMC_CON0, MT6357_VMC_ANA_CON0, 0xf00), + MT6357_LDO("ldo-vmch", VMCH, vmch_voltages, + MT6357_LDO_VMCH_CON0, MT6357_VMCH_ANA_CON0, 0x700), + MT6357_LDO("ldo-vsim1", VSIM1, vsim_voltages, + MT6357_LDO_VSIM1_CON0, MT6357_VSIM1_ANA_CON0, 0xf00), + MT6357_LDO("ldo-vsim2", VSIM2, vsim_voltages, + MT6357_LDO_VSIM2_CON0, MT6357_VSIM2_ANA_CON0, 0xf00), + MT6357_LDO("ldo-vusb33", VUSB33, vusb_voltages, + MT6357_LDO_VUSB33_CON0_0, MT6357_VUSB33_ANA_CON0, 0x700), + MT6357_LDO("ldo-vxo22", VXO22, vxo22_voltages, + MT6357_LDO_VXO22_CON0, MT6357_VXO22_ANA_CON0, 0x300), + + MT6357_LDO1("ldo-vsram-proc", VSRAM_PROC, 518750, 1312500, 6250, + buck_volt_range1, MT6357_LDO_VSRAM_PROC_CON0, + MT6357_LDO_VSRAM_CON0, 0x7f00), + MT6357_LDO1("ldo-vsram-others", VSRAM_OTHERS, 518750, 1312500, 6250, + buck_volt_range1, MT6357_LDO_VSRAM_OTHERS_CON0, + MT6357_LDO_VSRAM_CON1, 0x7f00), + + MT6357_REG_FIXED("ldo-vaud28", VAUD28, 2800000), + MT6357_REG_FIXED("ldo-vaux18", VAUX18, 1800000), + MT6357_REG_FIXED("ldo-vcamio18", VCAMIO, 1800000), + MT6357_REG_FIXED("ldo-vcn18", VCN18, 1800000), + MT6357_REG_FIXED("ldo-vcn28", VCN28, 2800000), + MT6357_REG_FIXED("ldo-vfe28", VFE28, 2800000), + MT6357_REG_FIXED("ldo-vio18", VIO18, 1800000), + MT6357_REG_FIXED("ldo-vio28", VIO28, 2800000), + MT6357_REG_FIXED("ldo-vrf12", VRF12, 1200000), + MT6357_REG_FIXED("ldo-vrf18", VRF18, 1800000), +}; + +static int mt6357_regulator_probe(struct platform_device *pdev) +{ + struct mt6397_chip *mt6357 = dev_get_drvdata(pdev->dev.parent); + struct regulator_config config = {}; + struct regulator_dev *rdev; + int i; + + pdev->dev.of_node = pdev->dev.parent->of_node; + + for (i = 0; i < MT6357_MAX_REGULATOR; i++) { + config.dev = &pdev->dev; + config.driver_data = &mt6357_regulators[i]; + config.regmap = mt6357->regmap; + + rdev = devm_regulator_register(&pdev->dev, + &mt6357_regulators[i].desc, + &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "failed to register %s\n", + mt6357_regulators[i].desc.name); + return PTR_ERR(rdev); + } + } + + return 0; +} + +static const struct platform_device_id mt6357_platform_ids[] = { + { "mt6357-regulator" }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(platform, mt6357_platform_ids); + +static struct platform_driver mt6357_regulator_driver = { + .driver = { + .name = "mt6357-regulator", + }, + .probe = mt6357_regulator_probe, + .id_table = mt6357_platform_ids, +}; + +module_platform_driver(mt6357_regulator_driver); + +MODULE_AUTHOR("Chen Zhong "); +MODULE_AUTHOR("Fabien Parent "); +MODULE_AUTHOR("Alexandre Mergnat "); +MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6357 PMIC"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/regulator/mt6357-regulator.h b/include/linux/regulator/mt6357-regulator.h new file mode 100644 index 000000000000..238b1ee77ea6 --- /dev/null +++ b/include/linux/regulator/mt6357-regulator.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2022 MediaTek Inc. + */ + +#ifndef __LINUX_REGULATOR_MT6357_H +#define __LINUX_REGULATOR_MT6357_H + +enum { + /* Bucks */ + MT6357_ID_VCORE, + MT6357_ID_VMODEM, + MT6357_ID_VPA, + MT6357_ID_VPROC, + MT6357_ID_VS1, + + /* LDOs */ + MT6357_ID_VAUX18, + MT6357_ID_VAUD28, + MT6357_ID_VCAMA, + MT6357_ID_VCAMD, + MT6357_ID_VCAMIO, + MT6357_ID_VCN18, + MT6357_ID_VCN28, + MT6357_ID_VCN33_BT, + MT6357_ID_VCN33_WIFI, + MT6357_ID_VDRAM, + MT6357_ID_VEFUSE, + MT6357_ID_VEMC, + MT6357_ID_VFE28, + MT6357_ID_VIBR, + MT6357_ID_VIO18, + MT6357_ID_VIO28, + MT6357_ID_VLDO28, + MT6357_ID_VMC, + MT6357_ID_VMCH, + MT6357_ID_VRF12, + MT6357_ID_VRF18, + MT6357_ID_VSIM1, + MT6357_ID_VSIM2, + MT6357_ID_VSRAM_OTHERS, + MT6357_ID_VSRAM_PROC, + MT6357_ID_VUSB33, + MT6357_ID_VXO22, + + MT6357_ID_RG_MAX, +}; + +#define MT6357_MAX_REGULATOR MT6357_ID_RG_MAX + +#endif /* __LINUX_REGULATOR_MT6357_H */ -- cgit v1.2.3 From cf34ac6aa2b12fb0c3aacfdcae8acd7904b949ec Mon Sep 17 00:00:00 2001 From: Yuan Can Date: Sat, 3 Dec 2022 06:21:09 +0000 Subject: regulator: qcom-labibb: Fix missing of_node_put() in qcom_labibb_regulator_probe() The reg_node needs to be released through of_node_put() in the error handling path when of_irq_get_byname() failed. Fixes: 390af53e0411 ("regulator: qcom-labibb: Implement short-circuit and over-current IRQs") Signed-off-by: Yuan Can Link: https://lore.kernel.org/r/20221203062109.115043-1-yuancan@huawei.com Signed-off-by: Mark Brown --- drivers/regulator/qcom-labibb-regulator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/qcom-labibb-regulator.c b/drivers/regulator/qcom-labibb-regulator.c index 639b71eb41ff..bcf7140f3bc9 100644 --- a/drivers/regulator/qcom-labibb-regulator.c +++ b/drivers/regulator/qcom-labibb-regulator.c @@ -822,6 +822,7 @@ static int qcom_labibb_regulator_probe(struct platform_device *pdev) if (irq == 0) irq = -EINVAL; + of_node_put(reg_node); return dev_err_probe(vreg->dev, irq, "Short-circuit irq not found.\n"); } -- cgit v1.2.3 From 2a17ddfdca25ac4cbb0d317362608ec32f98fd82 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 6 Dec 2022 15:15:55 -0600 Subject: dt-bindings: Add missing 'unevaluatedProperties' to regulator nodes Several regulator schemas are missing 'unevaluatedProperties' constraint which means any extra properties are allowed. Upon adding the constraint, there's numerous warnings from using the deprecated 'regulator-compatible' property. Remove the usage as examples shouldn't be using long since deprecated properties. Signed-off-by: Rob Herring Acked-by: Lee Jones Acked-by: Sebastian Reichel Acked-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20221206211554.92005-1-robh@kernel.org Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/mfd/max77650.yaml | 2 -- Documentation/devicetree/bindings/mfd/mediatek,mt6360.yaml | 9 --------- .../devicetree/bindings/power/supply/mt6360_charger.yaml | 2 +- .../devicetree/bindings/regulator/max77650-regulator.yaml | 1 + Documentation/devicetree/bindings/regulator/max8660.yaml | 6 +----- .../devicetree/bindings/regulator/mt6360-regulator.yaml | 12 +++--------- 6 files changed, 6 insertions(+), 26 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/max77650.yaml b/Documentation/devicetree/bindings/mfd/max77650.yaml index b0a0f0d3d9d4..4181174fcf58 100644 --- a/Documentation/devicetree/bindings/mfd/max77650.yaml +++ b/Documentation/devicetree/bindings/mfd/max77650.yaml @@ -100,14 +100,12 @@ examples: compatible = "maxim,max77650-regulator"; max77650_ldo: regulator-ldo { - regulator-compatible = "ldo"; regulator-name = "max77650-ldo"; regulator-min-microvolt = <1350000>; regulator-max-microvolt = <2937500>; }; max77650_sbb0: regulator-sbb0 { - regulator-compatible = "sbb0"; regulator-name = "max77650-sbb0"; regulator-min-microvolt = <800000>; regulator-max-microvolt = <1587500>; diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6360.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6360.yaml index 28eee02441ee..fb65abf30d57 100644 --- a/Documentation/devicetree/bindings/mfd/mediatek,mt6360.yaml +++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6360.yaml @@ -83,7 +83,6 @@ examples: richtek,vinovp-microvolt = <14500000>; otg_vbus_regulator: usb-otg-vbus-regulator { - regulator-compatible = "usb-otg-vbus"; regulator-name = "usb-otg-vbus"; regulator-min-microvolt = <4425000>; regulator-max-microvolt = <5825000>; @@ -145,7 +144,6 @@ examples: compatible = "mediatek,mt6360-regulator"; LDO_VIN3-supply = <&BUCK2>; buck1 { - regulator-compatible = "BUCK1"; regulator-name = "mt6360,buck1"; regulator-min-microvolt = <300000>; regulator-max-microvolt = <1300000>; @@ -154,7 +152,6 @@ examples: MT6360_OPMODE_ULP>; }; BUCK2: buck2 { - regulator-compatible = "BUCK2"; regulator-name = "mt6360,buck2"; regulator-min-microvolt = <300000>; regulator-max-microvolt = <1300000>; @@ -163,7 +160,6 @@ examples: MT6360_OPMODE_ULP>; }; ldo6 { - regulator-compatible = "LDO6"; regulator-name = "mt6360,ldo6"; regulator-min-microvolt = <500000>; regulator-max-microvolt = <2100000>; @@ -171,7 +167,6 @@ examples: MT6360_OPMODE_LP>; }; ldo7 { - regulator-compatible = "LDO7"; regulator-name = "mt6360,ldo7"; regulator-min-microvolt = <500000>; regulator-max-microvolt = <2100000>; @@ -179,7 +174,6 @@ examples: MT6360_OPMODE_LP>; }; ldo1 { - regulator-compatible = "LDO1"; regulator-name = "mt6360,ldo1"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3600000>; @@ -187,7 +181,6 @@ examples: MT6360_OPMODE_LP>; }; ldo2 { - regulator-compatible = "LDO2"; regulator-name = "mt6360,ldo2"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3600000>; @@ -195,7 +188,6 @@ examples: MT6360_OPMODE_LP>; }; ldo3 { - regulator-compatible = "LDO3"; regulator-name = "mt6360,ldo3"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3600000>; @@ -203,7 +195,6 @@ examples: MT6360_OPMODE_LP>; }; ldo5 { - regulator-compatible = "LDO5"; regulator-name = "mt6360,ldo5"; regulator-min-microvolt = <2700000>; regulator-max-microvolt = <3600000>; diff --git a/Documentation/devicetree/bindings/power/supply/mt6360_charger.yaml b/Documentation/devicetree/bindings/power/supply/mt6360_charger.yaml index b89b15a5bfa4..4c74cc78729e 100644 --- a/Documentation/devicetree/bindings/power/supply/mt6360_charger.yaml +++ b/Documentation/devicetree/bindings/power/supply/mt6360_charger.yaml @@ -26,6 +26,7 @@ properties: type: object description: OTG boost regulator. $ref: /schemas/regulator/regulator.yaml# + unevaluatedProperties: false required: - compatible @@ -39,7 +40,6 @@ examples: richtek,vinovp-microvolt = <14500000>; otg_vbus_regulator: usb-otg-vbus-regulator { - regulator-compatible = "usb-otg-vbus"; regulator-name = "usb-otg-vbus"; regulator-min-microvolt = <4425000>; regulator-max-microvolt = <5825000>; diff --git a/Documentation/devicetree/bindings/regulator/max77650-regulator.yaml b/Documentation/devicetree/bindings/regulator/max77650-regulator.yaml index ce0a4021ae7f..01b9775a92d1 100644 --- a/Documentation/devicetree/bindings/regulator/max77650-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/max77650-regulator.yaml @@ -26,6 +26,7 @@ properties: patternProperties: "^regulator-(ldo|sbb[0-2])$": $ref: "regulator.yaml#" + unevaluatedProperties: false required: - compatible diff --git a/Documentation/devicetree/bindings/regulator/max8660.yaml b/Documentation/devicetree/bindings/regulator/max8660.yaml index 9c038698f880..552176cc2315 100644 --- a/Documentation/devicetree/bindings/regulator/max8660.yaml +++ b/Documentation/devicetree/bindings/regulator/max8660.yaml @@ -26,6 +26,7 @@ properties: patternProperties: "regulator-.+": $ref: "regulator.yaml#" + unevaluatedProperties: false additionalProperties: false @@ -43,31 +44,26 @@ examples: regulators { regulator-V3 { - regulator-compatible= "V3(DCDC)"; regulator-min-microvolt = <725000>; regulator-max-microvolt = <1800000>; }; regulator-V4 { - regulator-compatible= "V4(DCDC)"; regulator-min-microvolt = <725000>; regulator-max-microvolt = <1800000>; }; regulator-V5 { - regulator-compatible= "V5(LDO)"; regulator-min-microvolt = <1700000>; regulator-max-microvolt = <2000000>; }; regulator-V6 { - regulator-compatible= "V6(LDO)"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; }; regulator-V7 { - regulator-compatible= "V7(LDO)"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; }; diff --git a/Documentation/devicetree/bindings/regulator/mt6360-regulator.yaml b/Documentation/devicetree/bindings/regulator/mt6360-regulator.yaml index a462d99a25cc..8a0931dc2f30 100644 --- a/Documentation/devicetree/bindings/regulator/mt6360-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/mt6360-regulator.yaml @@ -27,9 +27,11 @@ properties: patternProperties: "^buck[12]$": $ref: "regulator.yaml#" + unevaluatedProperties: false "^ldo[123567]$": $ref: "regulator.yaml#" + unevaluatedProperties: false required: - compatible @@ -44,7 +46,6 @@ examples: compatible = "mediatek,mt6360-regulator"; LDO_VIN3-supply = <&BUCK2>; buck1 { - regulator-compatible = "BUCK1"; regulator-name = "mt6360,buck1"; regulator-min-microvolt = <300000>; regulator-max-microvolt = <1300000>; @@ -53,7 +54,6 @@ examples: MT6360_OPMODE_ULP>; }; BUCK2: buck2 { - regulator-compatible = "BUCK2"; regulator-name = "mt6360,buck2"; regulator-min-microvolt = <300000>; regulator-max-microvolt = <1300000>; @@ -62,7 +62,6 @@ examples: MT6360_OPMODE_ULP>; }; ldo6 { - regulator-compatible = "LDO6"; regulator-name = "mt6360,ldo6"; regulator-min-microvolt = <500000>; regulator-max-microvolt = <2100000>; @@ -70,7 +69,6 @@ examples: MT6360_OPMODE_LP>; }; ldo7 { - regulator-compatible = "LDO7"; regulator-name = "mt6360,ldo7"; regulator-min-microvolt = <500000>; regulator-max-microvolt = <2100000>; @@ -78,15 +76,13 @@ examples: MT6360_OPMODE_LP>; }; ldo1 { - regulator-compatible = "LDO1"; regulator-name = "mt6360,ldo1"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3600000>; regulator-allowed-modes = ; }; - ldo2 { - regulator-compatible = "LDO2"; + ldo2 { regulator-name = "mt6360,ldo2"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3600000>; @@ -94,7 +90,6 @@ examples: MT6360_OPMODE_LP>; }; ldo3 { - regulator-compatible = "LDO3"; regulator-name = "mt6360,ldo3"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3600000>; @@ -102,7 +97,6 @@ examples: MT6360_OPMODE_LP>; }; ldo5 { - regulator-compatible = "LDO5"; regulator-name = "mt6360,ldo5"; regulator-min-microvolt = <2700000>; regulator-max-microvolt = <3600000>; -- cgit v1.2.3 From 8f3cbcd6b440032ebc7f7d48a1689dcc70a4eb98 Mon Sep 17 00:00:00 2001 From: ChiYuan Huang Date: Tue, 6 Dec 2022 15:22:21 +0800 Subject: regulator: core: Use different devices for resource allocation and DT lookup Following by the below discussion, there's the potential UAF issue between regulator and mfd. https://lore.kernel.org/all/20221128143601.1698148-1-yangyingliang@huawei.com/ From the analysis of Yingliang CPU A |CPU B mt6370_probe() | devm_mfd_add_devices() | |mt6370_regulator_probe() | regulator_register() | //allocate init_data and add it to devres | regulator_of_get_init_data() i2c_unregister_device() | device_del() | devres_release_all() | // init_data is freed | release_nodes() | | // using init_data causes UAF | regulator_register() It's common to use mfd core to create child device for the regulator. In order to do the DT lookup for init data, the child that registered the regulator would pass its parent as the parameter. And this causes init data resource allocated to its parent, not itself. The issue happen when parent device is going to release and regulator core is still doing some operation of init data constraint for the regulator of child device. To fix it, this patch expand 'regulator_register' API to use the different devices for init data allocation and DT lookup. Reported-by: Yang Yingliang Signed-off-by: ChiYuan Huang Link: https://lore.kernel.org/r/1670311341-32664-1-git-send-email-u0084500@gmail.com Signed-off-by: Mark Brown --- drivers/platform/x86/intel/int3472/clk_and_regulator.c | 3 ++- drivers/regulator/core.c | 8 ++++---- drivers/regulator/devres.c | 2 +- drivers/regulator/of_regulator.c | 2 +- drivers/regulator/stm32-vrefbuf.c | 2 +- include/linux/regulator/driver.h | 3 ++- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/platform/x86/intel/int3472/clk_and_regulator.c b/drivers/platform/x86/intel/int3472/clk_and_regulator.c index 1cf958983e86..b2342b3d78c7 100644 --- a/drivers/platform/x86/intel/int3472/clk_and_regulator.c +++ b/drivers/platform/x86/intel/int3472/clk_and_regulator.c @@ -185,7 +185,8 @@ int skl_int3472_register_regulator(struct int3472_discrete_device *int3472, cfg.init_data = &init_data; cfg.ena_gpiod = int3472->regulator.gpio; - int3472->regulator.rdev = regulator_register(&int3472->regulator.rdesc, + int3472->regulator.rdev = regulator_register(int3472->dev, + &int3472->regulator.rdesc, &cfg); if (IS_ERR(int3472->regulator.rdev)) { ret = PTR_ERR(int3472->regulator.rdev); diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 8258facc697b..c84e8d78dc7e 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -5409,6 +5409,7 @@ static struct regulator_coupler generic_regulator_coupler = { /** * regulator_register - register regulator + * @dev: the device that drive the regulator * @regulator_desc: regulator to register * @cfg: runtime configuration for regulator * @@ -5417,7 +5418,8 @@ static struct regulator_coupler generic_regulator_coupler = { * or an ERR_PTR() on error. */ struct regulator_dev * -regulator_register(const struct regulator_desc *regulator_desc, +regulator_register(struct device *dev, + const struct regulator_desc *regulator_desc, const struct regulator_config *cfg) { const struct regulator_init_data *init_data; @@ -5426,7 +5428,6 @@ regulator_register(const struct regulator_desc *regulator_desc, struct regulator_dev *rdev; bool dangling_cfg_gpiod = false; bool dangling_of_gpiod = false; - struct device *dev; int ret, i; bool resolved_early = false; @@ -5439,8 +5440,7 @@ regulator_register(const struct regulator_desc *regulator_desc, goto rinse; } - dev = cfg->dev; - WARN_ON(!dev); + WARN_ON(!dev || !cfg->dev); if (regulator_desc->name == NULL || regulator_desc->ops == NULL) { ret = -EINVAL; diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c index fec0398d98b0..90bb0d178885 100644 --- a/drivers/regulator/devres.c +++ b/drivers/regulator/devres.c @@ -415,7 +415,7 @@ struct regulator_dev *devm_regulator_register(struct device *dev, if (!ptr) return ERR_PTR(-ENOMEM); - rdev = regulator_register(regulator_desc, config); + rdev = regulator_register(dev, regulator_desc, config); if (!IS_ERR(rdev)) { *ptr = rdev; devres_add(dev, ptr); diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index f7529f1bf8b2..1b65e5e4e40f 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -505,7 +505,7 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev, struct device_node *child; struct regulator_init_data *init_data = NULL; - child = regulator_of_get_init_node(dev, desc); + child = regulator_of_get_init_node(config->dev, desc); if (!child) return NULL; diff --git a/drivers/regulator/stm32-vrefbuf.c b/drivers/regulator/stm32-vrefbuf.c index 30ea3bc8ca19..7a454b7b6eab 100644 --- a/drivers/regulator/stm32-vrefbuf.c +++ b/drivers/regulator/stm32-vrefbuf.c @@ -210,7 +210,7 @@ static int stm32_vrefbuf_probe(struct platform_device *pdev) pdev->dev.of_node, &stm32_vrefbuf_regu); - rdev = regulator_register(&stm32_vrefbuf_regu, &config); + rdev = regulator_register(&pdev->dev, &stm32_vrefbuf_regu, &config); if (IS_ERR(rdev)) { ret = PTR_ERR(rdev); dev_err(&pdev->dev, "register failed with error %d\n", ret); diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index f9a7461e72b8..d3b4a3d4514a 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -687,7 +687,8 @@ static inline int regulator_err2notif(int err) struct regulator_dev * -regulator_register(const struct regulator_desc *regulator_desc, +regulator_register(struct device *dev, + const struct regulator_desc *regulator_desc, const struct regulator_config *config); struct regulator_dev * devm_regulator_register(struct device *dev, -- cgit v1.2.3