From 4d49177f2cd7dce6e669584a5114b073b26a0d0f Mon Sep 17 00:00:00 2001 From: Markus Reichl Date: Mon, 3 Feb 2020 12:00:33 +0100 Subject: regulator: mp8859: add supply entry Add vin_supply to the regulator description to support a nice regulator tree. Signed-off-by: Markus Reichl Reviewed-by: Heiko Stuebner Link: https://lore.kernel.org/r/20200203110034.1448-1-m.reichl@fivetechno.de Signed-off-by: Mark Brown --- drivers/regulator/mp8859.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/regulator') diff --git a/drivers/regulator/mp8859.c b/drivers/regulator/mp8859.c index 1d26b506ee5b..6ed987648188 100644 --- a/drivers/regulator/mp8859.c +++ b/drivers/regulator/mp8859.c @@ -95,6 +95,7 @@ static const struct regulator_desc mp8859_regulators[] = { .id = 0, .type = REGULATOR_VOLTAGE, .name = "mp8859_dcdc", + .supply_name = "vin", .of_match = of_match_ptr("mp8859_dcdc"), .n_voltages = VOL_MAX_IDX + 1, .linear_ranges = mp8859_dcdc_ranges, -- cgit v1.2.3 From a33b25f57ddeb8545dab6ffee6be0f38d89d42c6 Mon Sep 17 00:00:00 2001 From: Rishi Gupta Date: Thu, 6 Feb 2020 19:18:37 +0530 Subject: regulator: da9063: fix code formatting warnings and errors This commit fixes following errors & warnings in this driver as reported by checkpatch.pl: - WARNING: Prefer 'unsigned int' to bare use of 'unsigned' - WARNING: line over 80 characters - ERROR: space prohibited before that ',' (ctx:WxW) - ERROR: code indent should use tabs where possible - WARNING: Block comments use * on subsequent lines Signed-off-by: Rishi Gupta Link: https://lore.kernel.org/r/1580996917-28494-1-git-send-email-gupt21@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/da9063-regulator.c | 58 +++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 24 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index 2aceb3b7afc2..ae54c76a8580 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -66,7 +66,7 @@ struct da9063_regulator_data { }; struct da9063_regulators_pdata { - unsigned n_regulators; + unsigned int n_regulators; struct da9063_regulator_data *regulator_data; }; @@ -131,7 +131,7 @@ struct da9063_regulator_info { /* Defines asignment of regulators info table to chip model */ struct da9063_dev_model { const struct da9063_regulator_info *regulator_info; - unsigned n_regulators; + unsigned int n_regulators; enum da9063_type type; }; @@ -150,7 +150,7 @@ struct da9063_regulator { /* Encapsulates all information for the regulators driver */ struct da9063_regulators { - unsigned n_regulators; + unsigned int n_regulators; /* Array size to be defined during init. Keep at end. */ struct da9063_regulator regulator[0]; }; @@ -165,38 +165,46 @@ enum { /* Regulator operations */ -/* Current limits array (in uA) for BCORE1, BCORE2, BPRO. - Entry indexes corresponds to register values. */ +/* + * Current limits array (in uA) for BCORE1, BCORE2, BPRO. + * Entry indexes corresponds to register values. + */ static const unsigned int da9063_buck_a_limits[] = { 500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1900000, 2000000 }; -/* Current limits array (in uA) for BMEM, BIO, BPERI. - Entry indexes corresponds to register values. */ +/* + * Current limits array (in uA) for BMEM, BIO, BPERI. + * Entry indexes corresponds to register values. + */ static const unsigned int da9063_buck_b_limits[] = { 1500000, 1600000, 1700000, 1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000, 2600000, 2700000, 2800000, 2900000, 3000000 }; -/* Current limits array (in uA) for merged BCORE1 and BCORE2. - Entry indexes corresponds to register values. */ +/* + * Current limits array (in uA) for merged BCORE1 and BCORE2. + * Entry indexes corresponds to register values. + */ static const unsigned int da9063_bcores_merged_limits[] = { 1000000, 1200000, 1400000, 1600000, 1800000, 2000000, 2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000, 3600000, 3800000, 4000000 }; -/* Current limits array (in uA) for merged BMEM and BIO. - Entry indexes corresponds to register values. */ +/* + * Current limits array (in uA) for merged BMEM and BIO. + * Entry indexes corresponds to register values. + */ static const unsigned int da9063_bmem_bio_merged_limits[] = { 3000000, 3200000, 3400000, 3600000, 3800000, 4000000, 4200000, 4400000, 4600000, 4800000, 5000000, 5200000, 5400000, 5600000, 5800000, 6000000 }; -static int da9063_buck_set_mode(struct regulator_dev *rdev, unsigned mode) +static int da9063_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) { struct da9063_regulator *regl = rdev_get_drvdata(rdev); - unsigned val; + unsigned int val; switch (mode) { case REGULATOR_MODE_FAST: @@ -221,7 +229,7 @@ static int da9063_buck_set_mode(struct regulator_dev *rdev, unsigned mode) * There are 3 modes to map to: FAST, NORMAL, and STANDBY. */ -static unsigned da9063_buck_get_mode(struct regulator_dev *rdev) +static unsigned int da9063_buck_get_mode(struct regulator_dev *rdev) { struct da9063_regulator *regl = rdev_get_drvdata(rdev); struct regmap_field *field; @@ -271,10 +279,10 @@ static unsigned da9063_buck_get_mode(struct regulator_dev *rdev) * There are 2 modes to map to: NORMAL and STANDBY (sleep) for each state. */ -static int da9063_ldo_set_mode(struct regulator_dev *rdev, unsigned mode) +static int da9063_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode) { struct da9063_regulator *regl = rdev_get_drvdata(rdev); - unsigned val; + unsigned int val; switch (mode) { case REGULATOR_MODE_NORMAL: @@ -290,7 +298,7 @@ static int da9063_ldo_set_mode(struct regulator_dev *rdev, unsigned mode) return regmap_field_write(regl->sleep, val); } -static unsigned da9063_ldo_get_mode(struct regulator_dev *rdev) +static unsigned int da9063_ldo_get_mode(struct regulator_dev *rdev) { struct da9063_regulator *regl = rdev_get_drvdata(rdev); struct regmap_field *field; @@ -383,7 +391,8 @@ static int da9063_suspend_disable(struct regulator_dev *rdev) return regmap_field_write(regl->suspend, 0); } -static int da9063_buck_set_suspend_mode(struct regulator_dev *rdev, unsigned mode) +static int da9063_buck_set_suspend_mode(struct regulator_dev *rdev, + unsigned int mode) { struct da9063_regulator *regl = rdev_get_drvdata(rdev); int val; @@ -405,10 +414,11 @@ static int da9063_buck_set_suspend_mode(struct regulator_dev *rdev, unsigned mod return regmap_field_write(regl->mode, val); } -static int da9063_ldo_set_suspend_mode(struct regulator_dev *rdev, unsigned mode) +static int da9063_ldo_set_suspend_mode(struct regulator_dev *rdev, + unsigned int mode) { struct da9063_regulator *regl = rdev_get_drvdata(rdev); - unsigned val; + unsigned int val; switch (mode) { case REGULATOR_MODE_NORMAL: @@ -593,7 +603,7 @@ static irqreturn_t da9063_ldo_lim_event(int irq, void *data) struct da9063_regulators *regulators = data; struct da9063 *hw = regulators->regulator[0].hw; struct da9063_regulator *regl; - int bits, i , ret; + int bits, i, ret; ret = regmap_read(hw->regmap, DA9063_REG_STATUS_D, &bits); if (ret < 0) @@ -605,10 +615,10 @@ static irqreturn_t da9063_ldo_lim_event(int irq, void *data) continue; if (BIT(regl->info->oc_event.lsb) & bits) { - regulator_lock(regl->rdev); + regulator_lock(regl->rdev); regulator_notifier_call_chain(regl->rdev, REGULATOR_EVENT_OVER_CURRENT, NULL); - regulator_unlock(regl->rdev); + regulator_unlock(regl->rdev); } } @@ -833,7 +843,7 @@ static int da9063_regulator_probe(struct platform_device *pdev) if (regl->info->suspend_sleep.reg) { regl->suspend_sleep = devm_regmap_field_alloc(&pdev->dev, - da9063->regmap, regl->info->suspend_sleep); + da9063->regmap, regl->info->suspend_sleep); if (IS_ERR(regl->suspend_sleep)) return PTR_ERR(regl->suspend_sleep); } -- cgit v1.2.3 From 6d8d840b214e12be6556ed7bee803d9280c54f3b Mon Sep 17 00:00:00 2001 From: Rishi Gupta Date: Thu, 6 Feb 2020 19:19:56 +0530 Subject: regulator: da9063: remove redundant return statement The devm_request_threaded_irq() already returns 0 on success and negative error code on failure. So return from this itself can be used while preserving error log in case of failure. Signed-off-by: Rishi Gupta Link: https://lore.kernel.org/r/1580996996-28798-1-git-send-email-gupt21@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/da9063-regulator.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index ae54c76a8580..aaa994293e9b 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -877,12 +877,10 @@ static int da9063_regulator_probe(struct platform_device *pdev) NULL, da9063_ldo_lim_event, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "LDO_LIM", regulators); - if (ret) { + if (ret) dev_err(&pdev->dev, "Failed to request LDO_LIM IRQ.\n"); - return ret; - } - return 0; + return ret; } static struct platform_driver da9063_regulator_driver = { -- cgit v1.2.3 From a273188b87fd7afc9b1a0f814452ecfb4e764f62 Mon Sep 17 00:00:00 2001 From: Saravanan Sekar Date: Tue, 4 Feb 2020 12:04:18 +0100 Subject: regulator: mp5416: add mp5416 regulator driver Adding regulator driver for the device mp5416. The MP5416 PMIC device contains four DC-DC buck converters and five regulators, accessed over I2C. Signed-off-by: Saravanan Sekar Link: https://lore.kernel.org/r/20200204110419.25933-3-sravanhome@gmail.com Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 10 ++ drivers/regulator/Makefile | 1 + drivers/regulator/mp5416.c | 245 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 256 insertions(+) create mode 100644 drivers/regulator/mp5416.c (limited to 'drivers/regulator') diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 074a2ef55943..b8ae513514a8 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -613,6 +613,16 @@ config REGULATOR_MCP16502 through the regulator interface. In addition it enables suspend-to-ram/standby transition. +config REGULATOR_MP5416 + tristate "Monolithic MP5416 PMIC" + depends on I2C && OF + select REGMAP_I2C + help + Say y here to support the MP5416 PMIC. This will enable supports + the software controllable 4 buck and 4 LDO regulators. + Say M here if you want to include support for the regulator as a + module. + config REGULATOR_MP8859 tristate "MPS MP8859 regulator driver" depends on I2C diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index c0d6b96ebd78..bc69d6481646 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -78,6 +78,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o obj-$(CONFIG_REGULATOR_MCP16502) += mcp16502.o +obj-$(CONFIG_REGULATOR_MP5416) += mp5416.o obj-$(CONFIG_REGULATOR_MP8859) += mp8859.o obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o diff --git a/drivers/regulator/mp5416.c b/drivers/regulator/mp5416.c new file mode 100644 index 000000000000..7954ad17249b --- /dev/null +++ b/drivers/regulator/mp5416.c @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// mp5416.c - regulator driver for mps mp5416 +// +// Copyright 2020 Monolithic Power Systems, Inc +// +// Author: Saravanan Sekar + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MP5416_REG_CTL0 0x00 +#define MP5416_REG_CTL1 0x01 +#define MP5416_REG_CTL2 0x02 +#define MP5416_REG_ILIM 0x03 +#define MP5416_REG_BUCK1 0x04 +#define MP5416_REG_BUCK2 0x05 +#define MP5416_REG_BUCK3 0x06 +#define MP5416_REG_BUCK4 0x07 +#define MP5416_REG_LDO1 0x08 +#define MP5416_REG_LDO2 0x09 +#define MP5416_REG_LDO3 0x0a +#define MP5416_REG_LDO4 0x0b + +#define MP5416_REGULATOR_EN BIT(7) +#define MP5416_MASK_VSET 0x7f +#define MP5416_MASK_BUCK1_ILIM 0xc0 +#define MP5416_MASK_BUCK2_ILIM 0x0c +#define MP5416_MASK_BUCK3_ILIM 0x30 +#define MP5416_MASK_BUCK4_ILIM 0x03 +#define MP5416_MASK_DVS_SLEWRATE 0xc0 + +/* values in uV */ +#define MP5416_VOLT1_MIN 600000 +#define MP5416_VOLT1_MAX 2187500 +#define MP5416_VOLT1_STEP 12500 +#define MP5416_VOLT2_MIN 800000 +#define MP5416_VOLT2_MAX 3975000 +#define MP5416_VOLT2_STEP 25000 + +#define MP5416_VOLT1_RANGE \ + ((MP5416_VOLT1_MAX - MP5416_VOLT1_MIN)/MP5416_VOLT1_STEP + 1) +#define MP5416_VOLT2_RANGE \ + ((MP5416_VOLT2_MAX - MP5416_VOLT2_MIN)/MP5416_VOLT2_STEP + 1) + +#define MP5416BUCK(_name, _id, _ilim, _dreg, _dval, _vsel) \ + [MP5416_BUCK ## _id] = { \ + .id = MP5416_BUCK ## _id, \ + .name = _name, \ + .of_match = _name, \ + .regulators_node = "regulators", \ + .ops = &mp5416_buck_ops, \ + .min_uV = MP5416_VOLT ##_vsel## _MIN, \ + .uV_step = MP5416_VOLT ##_vsel## _STEP, \ + .n_voltages = MP5416_VOLT ##_vsel## _RANGE, \ + .curr_table = _ilim, \ + .n_current_limits = ARRAY_SIZE(_ilim), \ + .csel_reg = MP5416_REG_ILIM, \ + .csel_mask = MP5416_MASK_BUCK ## _id ##_ILIM, \ + .vsel_reg = MP5416_REG_BUCK ## _id, \ + .vsel_mask = MP5416_MASK_VSET, \ + .enable_reg = MP5416_REG_BUCK ## _id, \ + .enable_mask = MP5416_REGULATOR_EN, \ + .active_discharge_on = _dval, \ + .active_discharge_reg = _dreg, \ + .active_discharge_mask = _dval, \ + .owner = THIS_MODULE, \ + } + +#define MP5416LDO(_name, _id) \ + [MP5416_LDO ## _id] = { \ + .id = MP5416_LDO ## _id, \ + .name = _name, \ + .of_match = _name, \ + .regulators_node = "regulators", \ + .ops = &mp5416_ldo_ops, \ + .min_uV = MP5416_VOLT2_MIN, \ + .uV_step = MP5416_VOLT2_STEP, \ + .n_voltages = MP5416_VOLT2_RANGE, \ + .vsel_reg = MP5416_REG_LDO ##_id, \ + .vsel_mask = MP5416_MASK_VSET, \ + .enable_reg = MP5416_REG_LDO ##_id, \ + .enable_mask = MP5416_REGULATOR_EN, \ + .active_discharge_on = BIT(_id), \ + .active_discharge_reg = MP5416_REG_CTL2, \ + .active_discharge_mask = BIT(_id), \ + .owner = THIS_MODULE, \ + } + +enum mp5416_regulators { + MP5416_BUCK1, + MP5416_BUCK2, + MP5416_BUCK3, + MP5416_BUCK4, + MP5416_LDO1, + MP5416_LDO2, + MP5416_LDO3, + MP5416_LDO4, + MP5416_MAX_REGULATORS, +}; + +static const struct regmap_config mp5416_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x0d, +}; + +/* Current limits array (in uA) + * ILIM1 & ILIM3 + */ +static const unsigned int mp5416_I_limits1[] = { + 3800000, 4600000, 5600000, 6800000 +}; + +/* ILIM2 & ILIM4 */ +static const unsigned int mp5416_I_limits2[] = { + 2200000, 3200000, 4200000, 5200000 +}; + +static int mp5416_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay); + +static const struct regulator_ops mp5416_ldo_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_active_discharge = regulator_set_active_discharge_regmap, +}; + +static const struct regulator_ops mp5416_buck_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_active_discharge = regulator_set_active_discharge_regmap, + .get_current_limit = regulator_get_current_limit_regmap, + .set_current_limit = regulator_set_current_limit_regmap, + .set_ramp_delay = mp5416_set_ramp_delay, +}; + +static struct regulator_desc mp5416_regulators_desc[MP5416_MAX_REGULATORS] = { + MP5416BUCK("buck1", 1, mp5416_I_limits1, MP5416_REG_CTL1, BIT(0), 1), + MP5416BUCK("buck2", 2, mp5416_I_limits2, MP5416_REG_CTL1, BIT(1), 2), + MP5416BUCK("buck3", 3, mp5416_I_limits1, MP5416_REG_CTL1, BIT(2), 1), + MP5416BUCK("buck4", 4, mp5416_I_limits2, MP5416_REG_CTL2, BIT(5), 2), + MP5416LDO("ldo1", 1), + MP5416LDO("ldo2", 2), + MP5416LDO("ldo3", 3), + MP5416LDO("ldo4", 4), +}; + +/* + * DVS ramp rate BUCK1 to BUCK4 + * 00: 32mV/us + * 01: 16mV/us + * 10: 8mV/us + * 11: 4mV/us + */ +static int mp5416_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) +{ + unsigned int ramp_val; + + if (ramp_delay > 32000 || ramp_delay < 0) + return -EINVAL; + + if (ramp_delay <= 4000) + ramp_val = 3; + else if (ramp_delay <= 8000) + ramp_val = 2; + else if (ramp_delay <= 16000) + ramp_val = 1; + else + ramp_val = 0; + + return regmap_update_bits(rdev->regmap, MP5416_REG_CTL2, + MP5416_MASK_DVS_SLEWRATE, ramp_val << 6); +} + +static int mp5416_i2c_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct regulator_config config = { NULL, }; + struct regulator_dev *rdev; + struct regmap *regmap; + int i; + + regmap = devm_regmap_init_i2c(client, &mp5416_regmap_config); + if (IS_ERR(regmap)) { + dev_err(dev, "Failed to allocate regmap!\n"); + return PTR_ERR(regmap); + } + + config.dev = dev; + config.regmap = regmap; + + for (i = 0; i < MP5416_MAX_REGULATORS; i++) { + rdev = devm_regulator_register(dev, + &mp5416_regulators_desc[i], + &config); + if (IS_ERR(rdev)) { + dev_err(dev, "Failed to register regulator!\n"); + return PTR_ERR(rdev); + } + } + + return 0; +} + +static const struct of_device_id mp5416_of_match[] = { + { .compatible = "mps,mp5416" }, + {}, +}; +MODULE_DEVICE_TABLE(of, mp5416_of_match); + +static const struct i2c_device_id mp5416_id[] = { + { "mp5416", }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, mp5416_id); + +static struct i2c_driver mp5416_regulator_driver = { + .driver = { + .name = "mp5416", + .of_match_table = of_match_ptr(mp5416_of_match), + }, + .probe_new = mp5416_i2c_probe, + .id_table = mp5416_id, +}; +module_i2c_driver(mp5416_regulator_driver); + +MODULE_AUTHOR("Saravanan Sekar "); +MODULE_DESCRIPTION("MP5416 PMIC regulator driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 23a653eb1f3f16755720dde406f137441add88d0 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 11 Feb 2020 17:47:10 -0600 Subject: regulator: da9063: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertenly introduced[3] to the codebase from now on. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20200211234710.GA29532@embeddedor Signed-off-by: Mark Brown --- drivers/regulator/da9063-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index aaa994293e9b..44727704d3c5 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -152,7 +152,7 @@ struct da9063_regulator { struct da9063_regulators { unsigned int n_regulators; /* Array size to be defined during init. Keep at end. */ - struct da9063_regulator regulator[0]; + struct da9063_regulator regulator[]; }; /* BUCK modes for DA9063 */ -- cgit v1.2.3 From d69f763fd360ec62dab9024f98209655f3046c68 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 11 Feb 2020 17:46:12 -0600 Subject: regulator: da9062: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertenly introduced[3] to the codebase from now on. This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Acked-by: Adam Thomson Link: https://lore.kernel.org/r/20200211234612.GA28682@embeddedor Signed-off-by: Mark Brown --- drivers/regulator/da9062-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c index d3ce0278bfbe..d8112f56e94e 100644 --- a/drivers/regulator/da9062-regulator.c +++ b/drivers/regulator/da9062-regulator.c @@ -73,7 +73,7 @@ struct da9062_regulators { int irq_ldo_lim; unsigned n_regulators; /* Array size to be defined during init. Keep at end. */ - struct da9062_regulator regulator[0]; + struct da9062_regulator regulator[]; }; /* Regulator operations */ -- cgit v1.2.3 From 502cdd605edd95209661c8bf90927af6d05c011c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 12 Feb 2020 23:02:23 +0800 Subject: regulator: mp5416: Fix output discharge enable bit for LDOs The .active_discharge_on/.active_discharge_mask settings does not match the datasheet, fix it. Signed-off-by: Axel Lin Link: https://lore.kernel.org/r/20200212150223.20042-1-axel.lin@ingics.com Signed-off-by: Mark Brown --- drivers/regulator/mp5416.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/mp5416.c b/drivers/regulator/mp5416.c index 7954ad17249b..67ce1b52a1a1 100644 --- a/drivers/regulator/mp5416.c +++ b/drivers/regulator/mp5416.c @@ -73,7 +73,7 @@ .owner = THIS_MODULE, \ } -#define MP5416LDO(_name, _id) \ +#define MP5416LDO(_name, _id, _dval) \ [MP5416_LDO ## _id] = { \ .id = MP5416_LDO ## _id, \ .name = _name, \ @@ -87,9 +87,9 @@ .vsel_mask = MP5416_MASK_VSET, \ .enable_reg = MP5416_REG_LDO ##_id, \ .enable_mask = MP5416_REGULATOR_EN, \ - .active_discharge_on = BIT(_id), \ + .active_discharge_on = _dval, \ .active_discharge_reg = MP5416_REG_CTL2, \ - .active_discharge_mask = BIT(_id), \ + .active_discharge_mask = _dval, \ .owner = THIS_MODULE, \ } @@ -155,10 +155,10 @@ static struct regulator_desc mp5416_regulators_desc[MP5416_MAX_REGULATORS] = { MP5416BUCK("buck2", 2, mp5416_I_limits2, MP5416_REG_CTL1, BIT(1), 2), MP5416BUCK("buck3", 3, mp5416_I_limits1, MP5416_REG_CTL1, BIT(2), 1), MP5416BUCK("buck4", 4, mp5416_I_limits2, MP5416_REG_CTL2, BIT(5), 2), - MP5416LDO("ldo1", 1), - MP5416LDO("ldo2", 2), - MP5416LDO("ldo3", 3), - MP5416LDO("ldo4", 4), + MP5416LDO("ldo1", 1, BIT(4)), + MP5416LDO("ldo2", 2, BIT(3)), + MP5416LDO("ldo3", 3, BIT(2)), + MP5416LDO("ldo4", 4, BIT(1)), }; /* -- cgit v1.2.3 From a0fc8b6a3bc52f3a3ecf13eb380e15c470b8e6f8 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Sun, 23 Feb 2020 00:56:34 +0100 Subject: regulator: axp20x: Fix misleading use of negation It works incidentally, because AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN is non-zero, but the false branch value really should be just 0. Signed-off-by: Ondrej Jirman Acked-by: Chen-Yu Tsai Link: https://lore.kernel.org/r/20200222235634.243805-1-megous@megous.com Signed-off-by: Mark Brown --- drivers/regulator/axp20x-regulator.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index 16f0c8570036..1e6eb5b1f8d8 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -381,8 +381,7 @@ static int axp20x_set_ramp_delay(struct regulator_dev *rdev, int ramp) mask = AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_RATE_MASK | AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN_MASK; enable = (ramp > 0) ? - AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN : - !AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN; + AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN : 0; break; } @@ -393,8 +392,7 @@ static int axp20x_set_ramp_delay(struct regulator_dev *rdev, int ramp) mask = AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE_MASK | AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN_MASK; enable = (ramp > 0) ? - AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN : - !AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN; + AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN : 0; break; } -- cgit v1.2.3 From b5f25304aece9f2e7eaab275bbb5461c666bf38c Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Wed, 19 Feb 2020 17:37:11 +0100 Subject: regulator: add smb208 support Smb208 regulators are used on some ipq806x soc. Add support for it to make it avaiable on some routers that use it. Signed-off-by: Ansuel Smith Signed-off-by: Adrian Panella Acked-by: Lee Jones Link: https://lore.kernel.org/r/20200219163711.479-1-ansuelsmth@gmail.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/mfd/qcom-rpm.txt | 4 ++++ drivers/regulator/qcom_rpm-regulator.c | 9 +++++++++ 2 files changed, 13 insertions(+) (limited to 'drivers/regulator') diff --git a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt index 3c91ad430eea..b823b8625243 100644 --- a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt +++ b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt @@ -61,6 +61,7 @@ Regulator nodes are identified by their compatible: "qcom,rpm-pm8901-regulators" "qcom,rpm-pm8921-regulators" "qcom,rpm-pm8018-regulators" + "qcom,rpm-smb208-regulators" - vdd_l0_l1_lvs-supply: - vdd_l2_l11_l12-supply: @@ -171,6 +172,9 @@ pm8018: s1, s2, s3, s4, s5, , l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l14, lvs1 +smb208: + s1a, s1b, s2a, s2b + The content of each sub-node is defined by the standard binding for regulators - see regulator.txt - with additional custom properties described below: diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c index 7407cd5a1b74..7fc97f23fcf4 100644 --- a/drivers/regulator/qcom_rpm-regulator.c +++ b/drivers/regulator/qcom_rpm-regulator.c @@ -925,12 +925,21 @@ static const struct rpm_regulator_data rpm_pm8921_regulators[] = { { } }; +static const struct rpm_regulator_data rpm_smb208_regulators[] = { + { "s1a", QCOM_RPM_SMB208_S1a, &smb208_smps, "vin_s1a" }, + { "s1b", QCOM_RPM_SMB208_S1b, &smb208_smps, "vin_s1b" }, + { "s2a", QCOM_RPM_SMB208_S2a, &smb208_smps, "vin_s2a" }, + { "s2b", QCOM_RPM_SMB208_S2b, &smb208_smps, "vin_s2b" }, + { } +}; + static const struct of_device_id rpm_of_match[] = { { .compatible = "qcom,rpm-pm8018-regulators", .data = &rpm_pm8018_regulators }, { .compatible = "qcom,rpm-pm8058-regulators", .data = &rpm_pm8058_regulators }, { .compatible = "qcom,rpm-pm8901-regulators", .data = &rpm_pm8901_regulators }, { .compatible = "qcom,rpm-pm8921-regulators", .data = &rpm_pm8921_regulators }, + { .compatible = "qcom,rpm-smb208-regulators", .data = &rpm_smb208_regulators }, { } }; MODULE_DEVICE_TABLE(of, rpm_of_match); -- cgit v1.2.3 From 6179b0e90cbc0117cd4ff994bc24f4ea417b11d7 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Mon, 2 Mar 2020 19:55:18 +0800 Subject: regulator: anatop: Improve Kconfig dependency ANATOP regulator should depend on ARCH_MXC or COMPILE_TEST. Signed-off-by: Anson Huang Link: https://lore.kernel.org/r/1583150118-8014-1-git-send-email-Anson.Huang@nxp.com Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/regulator') diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index b8ae513514a8..64a39f34ef37 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -107,6 +107,7 @@ config REGULATOR_AD5398 config REGULATOR_ANATOP tristate "Freescale i.MX on-chip ANATOP LDO regulators" + depends on ARCH_MXC || COMPILE_TEST depends on MFD_SYSCON help Say y here to support Freescale i.MX on-chip ANATOP LDOs -- cgit v1.2.3 From 0cd71b9a43ad80f4d9a8bfde6ec6db8daf447029 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Mon, 2 Mar 2020 14:14:28 +0000 Subject: regulator: pwm: Don't warn on probe deferral Deferred probe is an expected return value for devm_pwm_get(). Given that the driver deals with it properly, rather than warn on probe deferral, only output a message on probe deferral if debug level prints are enabled. Signed-off-by: Jon Hunter Link: https://lore.kernel.org/r/20200302141428.14119-1-jonathanh@nvidia.com Signed-off-by: Mark Brown --- drivers/regulator/pwm-regulator.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c index e74e11101fc1..638329bd0745 100644 --- a/drivers/regulator/pwm-regulator.c +++ b/drivers/regulator/pwm-regulator.c @@ -354,7 +354,11 @@ static int pwm_regulator_probe(struct platform_device *pdev) drvdata->pwm = devm_pwm_get(&pdev->dev, NULL); if (IS_ERR(drvdata->pwm)) { ret = PTR_ERR(drvdata->pwm); - dev_err(&pdev->dev, "Failed to get PWM: %d\n", ret); + if (ret == -EPROBE_DEFER) + dev_dbg(&pdev->dev, + "Failed to get PWM, deferring probe\n"); + else + dev_err(&pdev->dev, "Failed to get PWM: %d\n", ret); return ret; } -- cgit v1.2.3 From 788bfc6eb6912df40a31245566b3e5c99ea7a66a Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 3 Mar 2020 21:44:12 +0800 Subject: regulator: anatop: Lower error message level for -EPROBE_DEFER devm_regulator_register() could return -EPROBE_DEFER when trying to get init data and NOT all resources are available at that time, for this case, error message is better to be present for debug level ONLY. Signed-off-by: Anson Huang Link: https://lore.kernel.org/r/1583243052-1930-1-git-send-email-Anson.Huang@nxp.com Signed-off-by: Mark Brown --- drivers/regulator/anatop-regulator.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index 754739d004e5..ca92b3de0e9c 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c @@ -305,9 +305,13 @@ static int anatop_regulator_probe(struct platform_device *pdev) /* register regulator */ rdev = devm_regulator_register(dev, rdesc, &config); if (IS_ERR(rdev)) { - dev_err(dev, "failed to register %s\n", - rdesc->name); - return PTR_ERR(rdev); + ret = PTR_ERR(rdev); + if (ret == -EPROBE_DEFER) + dev_dbg(dev, "failed to register %s, deferring...\n", + rdesc->name); + else + dev_err(dev, "failed to register %s\n", rdesc->name); + return ret; } platform_set_drvdata(pdev, rdev); -- cgit v1.2.3 From 6e5505cf3ee411761fae8b7419e4f673be41690a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 12 Mar 2020 20:32:45 +0200 Subject: regulator: core: Avoid device name duplication in NORMAL_GET With current code: st-gyro-i2c i2c-PRP0001:00: i2c-PRP0001:00 supply vdd not found, using dummy regulator which looks a bit oververbose. Replace this with simplified format string for the above case, and drop "deviceless" case since for all dev_*() macros used in _regulator_get() the "(null)" will be printed anyway. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200312183245.1612-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/regulator/core.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index d015d99cb59d..7486f6e4e613 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1849,7 +1849,6 @@ struct regulator *_regulator_get(struct device *dev, const char *id, { struct regulator_dev *rdev; struct regulator *regulator; - const char *devname = dev ? dev_name(dev) : "deviceless"; struct device_link *link; int ret; @@ -1887,9 +1886,7 @@ struct regulator *_regulator_get(struct device *dev, const char *id, * enabled, even if it isn't hooked up, and just * provide a dummy. */ - dev_warn(dev, - "%s supply %s not found, using dummy regulator\n", - devname, id); + dev_warn(dev, "supply %s not found, using dummy regulator\n", id); rdev = dummy_regulator_rdev; get_device(&rdev->dev); break; -- cgit v1.2.3 From 97be82880b617fb6bc06ff19e3ddb039501b2dcf Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Mon, 16 Mar 2020 22:30:20 +0800 Subject: regulator: add support for MP8869 regulator The MP8869 from Monolithic Power Systems is a single output DC/DC converter. The voltage can be controlled via I2C. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20200316223020.1a6d92ae@xhacker Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 7 ++ drivers/regulator/Makefile | 1 + drivers/regulator/mp886x.c | 230 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 238 insertions(+) create mode 100644 drivers/regulator/mp886x.c (limited to 'drivers/regulator') diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 64a39f34ef37..f4b72cb098ef 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -635,6 +635,13 @@ config REGULATOR_MP8859 Say M here if you want to include support for the regulator as a module. The module will be named "mp8859". +config REGULATOR_MP886X + tristate "MPS MP8869 regulator driver" + depends on I2C && (OF || COMPILE_TEST) + select REGMAP_I2C + help + This driver supports the MP8869 voltage regulator. + config REGULATOR_MPQ7920 tristate "Monolithic MPQ7920 PMIC" depends on I2C && OF diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index bc69d6481646..6610ee001d9a 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -80,6 +80,7 @@ obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o obj-$(CONFIG_REGULATOR_MCP16502) += mcp16502.o obj-$(CONFIG_REGULATOR_MP5416) += mp5416.o obj-$(CONFIG_REGULATOR_MP8859) += mp8859.o +obj-$(CONFIG_REGULATOR_MP886X) += mp886x.o obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c new file mode 100644 index 000000000000..f77321a449ca --- /dev/null +++ b/drivers/regulator/mp886x.c @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// MP8869 regulator driver +// +// Copyright (C) 2020 Synaptics Incorporated +// +// Author: Jisheng Zhang + +#include +#include +#include +#include +#include +#include +#include + +#define MP886X_VSEL 0x00 +#define MP886X_V_BOOT (1 << 7) +#define MP886X_SYSCNTLREG1 0x01 +#define MP886X_MODE (1 << 0) +#define MP886X_GO (1 << 6) +#define MP886X_EN (1 << 7) + +struct mp886x_device_info { + struct device *dev; + struct regulator_desc desc; + struct regulator_init_data *regulator; + struct gpio_desc *en_gpio; + u32 r[2]; + unsigned int sel; +}; + +static int mp886x_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + switch (mode) { + case REGULATOR_MODE_FAST: + regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1, + MP886X_MODE, MP886X_MODE); + break; + case REGULATOR_MODE_NORMAL: + regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1, + MP886X_MODE, 0); + break; + default: + return -EINVAL; + } + return 0; +} + +static unsigned int mp886x_get_mode(struct regulator_dev *rdev) +{ + u32 val; + int ret; + + ret = regmap_read(rdev->regmap, MP886X_SYSCNTLREG1, &val); + if (ret < 0) + return ret; + if (val & MP886X_MODE) + return REGULATOR_MODE_FAST; + else + return REGULATOR_MODE_NORMAL; +} + +static int mp8869_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel) +{ + int ret; + + ret = regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1, + MP886X_GO, MP886X_GO); + if (ret < 0) + return ret; + + sel <<= ffs(rdev->desc->vsel_mask) - 1; + return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, + MP886X_V_BOOT | rdev->desc->vsel_mask, sel); +} + +static inline unsigned int mp8869_scale(unsigned int uv, u32 r1, u32 r2) +{ + u32 tmp = uv * r1 / r2; + + return uv + tmp; +} + +static int mp8869_get_voltage_sel(struct regulator_dev *rdev) +{ + struct mp886x_device_info *di = rdev_get_drvdata(rdev); + int ret, uv; + unsigned int val; + bool fbloop; + + ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val); + if (ret) + return ret; + + fbloop = val & MP886X_V_BOOT; + if (fbloop) { + uv = rdev->desc->min_uV; + uv = mp8869_scale(uv, di->r[0], di->r[1]); + return regulator_map_voltage_linear(rdev, uv, uv); + } + + val &= rdev->desc->vsel_mask; + val >>= ffs(rdev->desc->vsel_mask) - 1; + + return val; +} + +static const struct regulator_ops mp8869_regulator_ops = { + .set_voltage_sel = mp8869_set_voltage_sel, + .get_voltage_sel = mp8869_get_voltage_sel, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .map_voltage = regulator_map_voltage_linear, + .list_voltage = regulator_list_voltage_linear, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_mode = mp886x_set_mode, + .get_mode = mp886x_get_mode, +}; + +static int mp886x_regulator_register(struct mp886x_device_info *di, + struct regulator_config *config) +{ + struct regulator_desc *rdesc = &di->desc; + struct regulator_dev *rdev; + + rdesc->name = "mp886x-reg"; + rdesc->supply_name = "vin"; + rdesc->ops = of_device_get_match_data(di->dev); + rdesc->type = REGULATOR_VOLTAGE; + rdesc->n_voltages = 128; + rdesc->enable_reg = MP886X_SYSCNTLREG1; + rdesc->enable_mask = MP886X_EN; + rdesc->min_uV = 600000; + rdesc->uV_step = 10000; + rdesc->vsel_reg = MP886X_VSEL; + rdesc->vsel_mask = 0x3f; + rdesc->owner = THIS_MODULE; + + rdev = devm_regulator_register(di->dev, &di->desc, config); + if (IS_ERR(rdev)) + return PTR_ERR(rdev); + di->sel = rdesc->ops->get_voltage_sel(rdev); + return 0; +} + +static const struct regmap_config mp886x_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +static int mp886x_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct device_node *np = dev->of_node; + struct mp886x_device_info *di; + struct regulator_config config = { }; + struct regmap *regmap; + int ret; + + di = devm_kzalloc(dev, sizeof(struct mp886x_device_info), GFP_KERNEL); + if (!di) + return -ENOMEM; + + di->regulator = of_get_regulator_init_data(dev, np, &di->desc); + if (!di->regulator) { + dev_err(dev, "Platform data not found!\n"); + return -EINVAL; + } + + ret = of_property_read_u32_array(np, "mps,fb-voltage-divider", + di->r, 2); + if (ret) + return ret; + + di->en_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); + if (IS_ERR(di->en_gpio)) + return PTR_ERR(di->en_gpio); + + di->dev = dev; + + regmap = devm_regmap_init_i2c(client, &mp886x_regmap_config); + if (IS_ERR(regmap)) { + dev_err(dev, "Failed to allocate regmap!\n"); + return PTR_ERR(regmap); + } + i2c_set_clientdata(client, di); + + config.dev = di->dev; + config.init_data = di->regulator; + config.regmap = regmap; + config.driver_data = di; + config.of_node = np; + + ret = mp886x_regulator_register(di, &config); + if (ret < 0) + dev_err(dev, "Failed to register regulator!\n"); + return ret; +} + +static const struct of_device_id mp886x_dt_ids[] = { + { + .compatible = "mps,mp8869", + .data = &mp8869_regulator_ops + }, + { } +}; +MODULE_DEVICE_TABLE(of, mp886x_dt_ids); + +static const struct i2c_device_id mp886x_id[] = { + { "mp886x", }, + { }, +}; +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), + }, + .probe = mp886x_i2c_probe, + .id_table = mp886x_id, +}; +module_i2c_driver(mp886x_regulator_driver); + +MODULE_AUTHOR("Jisheng Zhang "); +MODULE_DESCRIPTION("MP886x regulator driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 751ca3aa15be815373536eb8b3dc44910b800e9f Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Mon, 16 Mar 2020 22:31:27 +0800 Subject: regulator: mp886x: add MP8867 support MP8867 is an I2C-controlled adjustable voltage regulator made by Monolithic Power Systems. The difference between MP8867 and MP8869 are: 1.If V_BOOT, the vref of MP8869 is fixed at 600mv while vref of MP8867 is determined by the I2C control. 2.For MP8867, when setting voltage, if the step is within 5, we need to manually set the GO BIT to 0. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20200316223127.4b1ecc92@xhacker Signed-off-by: Mark Brown --- drivers/regulator/mp886x.c | 62 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c index f77321a449ca..1786f7162019 100644 --- a/drivers/regulator/mp886x.c +++ b/drivers/regulator/mp886x.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // -// MP8869 regulator driver +// MP8867/MP8869 regulator driver // // Copyright (C) 2020 Synaptics Incorporated // @@ -119,6 +119,62 @@ static const struct regulator_ops mp8869_regulator_ops = { .get_mode = mp886x_get_mode, }; +static int mp8867_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel) +{ + struct mp886x_device_info *di = rdev_get_drvdata(rdev); + int ret, delta; + + ret = mp8869_set_voltage_sel(rdev, sel); + if (ret < 0) + return ret; + + delta = di->sel - sel; + if (abs(delta) <= 5) + ret = regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1, + MP886X_GO, 0); + di->sel = sel; + + return ret; +} + +static int mp8867_get_voltage_sel(struct regulator_dev *rdev) +{ + struct mp886x_device_info *di = rdev_get_drvdata(rdev); + int ret, uv; + unsigned int val; + bool fbloop; + + ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val); + if (ret) + return ret; + + fbloop = val & MP886X_V_BOOT; + + val &= rdev->desc->vsel_mask; + val >>= ffs(rdev->desc->vsel_mask) - 1; + + if (fbloop) { + uv = regulator_list_voltage_linear(rdev, val); + uv = mp8869_scale(uv, di->r[0], di->r[1]); + return regulator_map_voltage_linear(rdev, uv, uv); + } + + return val; +} + +static const struct regulator_ops mp8867_regulator_ops = { + .set_voltage_sel = mp8867_set_voltage_sel, + .get_voltage_sel = mp8867_get_voltage_sel, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .map_voltage = regulator_map_voltage_linear, + .list_voltage = regulator_list_voltage_linear, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_mode = mp886x_set_mode, + .get_mode = mp886x_get_mode, +}; + static int mp886x_regulator_register(struct mp886x_device_info *di, struct regulator_config *config) { @@ -201,6 +257,10 @@ static int mp886x_i2c_probe(struct i2c_client *client, } static const struct of_device_id mp886x_dt_ids[] = { + { + .compatible = "mps,mp8867", + .data = &mp8867_regulator_ops + }, { .compatible = "mps,mp8869", .data = &mp8869_regulator_ops -- cgit v1.2.3 From 99f75ce6661993b8ba7ae0c94e95cb25454fdf1e Mon Sep 17 00:00:00 2001 From: Martin Fuzzey Date: Tue, 17 Mar 2020 17:14:26 +0100 Subject: regulator: da9063: fix suspend The .set_suspend_enable() and .set_suspend_disable() methods are not supposed to immediately change the regulator state but just indicated if the regulator should be enabled or disabled when standby mode is entered (by a hardware signal). However currently they set control the SEL bits in the DVC registers, which causes the voltage to change to immediately between the "A" (normal) and "B" (standby) values as programmed and does nothing for the enable state... This means that "regulator-on-in-suspend" does not work (the regulator is switched off when the PMIC enters standby mode on the hardware signal) and, potentially, depending on the A and B voltage configurations the voltage could be incorrectly changed *before* actually entering suspend. The right bit to use for the functionality is the "CONF" bit in the "CONT" register. The detailed register description says "Sequencer target state" for this bit which is not very clear but the functional description is clearer. >From 5.1.5 System Enable: De-asserting SYS_EN (changing from active to passive state) clears control SYSTEM_EN which triggers a power down sequence into hibernate/standby mode ... With the exception of supplies that have the xxxx_CONF control bit asserted, all regulators in power domains POWER1, POWER, and SYSTEM are sequentially disabled in reverse order. Regulators with the _CONF bit set remain on but change the active voltage controlregisters from V_A to V_B (if V_B is notalready selected). Signed-off-by: Martin Fuzzey Link: https://lore.kernel.org/r/1584461691-14344-1-git-send-email-martin.fuzzey@flowbird.group Signed-off-by: Mark Brown --- drivers/regulator/da9063-regulator.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index 2aceb3b7afc2..46b7301efcd6 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -100,6 +100,7 @@ struct da9063_regulator_info { .desc.vsel_mask = DA9063_V##regl_name##_MASK, \ .desc.linear_min_sel = DA9063_V##regl_name##_BIAS, \ .sleep = BFIELD(DA9063_REG_V##regl_name##_A, DA9063_LDO_SL), \ + .suspend = BFIELD(DA9063_REG_##regl_name##_CONT, DA9063_LDO_CONF), \ .suspend_sleep = BFIELD(DA9063_REG_V##regl_name##_B, DA9063_LDO_SL), \ .suspend_vsel_reg = DA9063_REG_V##regl_name##_B @@ -124,6 +125,7 @@ struct da9063_regulator_info { .desc.vsel_mask = DA9063_VBUCK_MASK, \ .desc.linear_min_sel = DA9063_VBUCK_BIAS, \ .sleep = BFIELD(DA9063_REG_V##regl_name##_A, DA9063_BUCK_SL), \ + .suspend = BFIELD(DA9063_REG_##regl_name##_CONT, DA9063_BUCK_CONF), \ .suspend_sleep = BFIELD(DA9063_REG_V##regl_name##_B, DA9063_BUCK_SL), \ .suspend_vsel_reg = DA9063_REG_V##regl_name##_B, \ .mode = BFIELD(DA9063_REG_##regl_name##_CFG, DA9063_BUCK_MODE_MASK) @@ -465,42 +467,36 @@ static const struct da9063_regulator_info da9063_regulator_info[] = { da9063_buck_a_limits, DA9063_REG_BUCK_ILIM_C, DA9063_BCORE1_ILIM_MASK), DA9063_BUCK_COMMON_FIELDS(BCORE1), - .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBCORE1_SEL), }, { DA9063_BUCK(DA9063, BCORE2, 300, 10, 1570, da9063_buck_a_limits, DA9063_REG_BUCK_ILIM_C, DA9063_BCORE2_ILIM_MASK), DA9063_BUCK_COMMON_FIELDS(BCORE2), - .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBCORE2_SEL), }, { DA9063_BUCK(DA9063, BPRO, 530, 10, 1800, da9063_buck_a_limits, DA9063_REG_BUCK_ILIM_B, DA9063_BPRO_ILIM_MASK), DA9063_BUCK_COMMON_FIELDS(BPRO), - .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBPRO_SEL), }, { DA9063_BUCK(DA9063, BMEM, 800, 20, 3340, da9063_buck_b_limits, DA9063_REG_BUCK_ILIM_A, DA9063_BMEM_ILIM_MASK), DA9063_BUCK_COMMON_FIELDS(BMEM), - .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBMEM_SEL), }, { DA9063_BUCK(DA9063, BIO, 800, 20, 3340, da9063_buck_b_limits, DA9063_REG_BUCK_ILIM_A, DA9063_BIO_ILIM_MASK), DA9063_BUCK_COMMON_FIELDS(BIO), - .suspend = BFIELD(DA9063_REG_DVC_2, DA9063_VBIO_SEL), }, { DA9063_BUCK(DA9063, BPERI, 800, 20, 3340, da9063_buck_b_limits, DA9063_REG_BUCK_ILIM_B, DA9063_BPERI_ILIM_MASK), DA9063_BUCK_COMMON_FIELDS(BPERI), - .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBPERI_SEL), }, { DA9063_BUCK(DA9063, BCORES_MERGED, 300, 10, 1570, @@ -508,7 +504,6 @@ static const struct da9063_regulator_info da9063_regulator_info[] = { DA9063_REG_BUCK_ILIM_C, DA9063_BCORE1_ILIM_MASK), /* BCORES_MERGED uses the same register fields as BCORE1 */ DA9063_BUCK_COMMON_FIELDS(BCORE1), - .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBCORE1_SEL), }, { DA9063_BUCK(DA9063, BMEM_BIO_MERGED, 800, 20, 3340, @@ -516,21 +511,17 @@ static const struct da9063_regulator_info da9063_regulator_info[] = { DA9063_REG_BUCK_ILIM_A, DA9063_BMEM_ILIM_MASK), /* BMEM_BIO_MERGED uses the same register fields as BMEM */ DA9063_BUCK_COMMON_FIELDS(BMEM), - .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBMEM_SEL), }, { DA9063_LDO(DA9063, LDO3, 900, 20, 3440), - .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO3_SEL), .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO3_LIM), }, { DA9063_LDO(DA9063, LDO7, 900, 50, 3600), - .suspend = BFIELD(DA9063_REG_LDO7_CONT, DA9063_VLDO7_SEL), .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO7_LIM), }, { DA9063_LDO(DA9063, LDO8, 900, 50, 3600), - .suspend = BFIELD(DA9063_REG_LDO8_CONT, DA9063_VLDO8_SEL), .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO8_LIM), }, { @@ -539,36 +530,29 @@ static const struct da9063_regulator_info da9063_regulator_info[] = { }, { DA9063_LDO(DA9063, LDO11, 900, 50, 3600), - .suspend = BFIELD(DA9063_REG_LDO11_CONT, DA9063_VLDO11_SEL), .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO11_LIM), }, /* The following LDOs are present only on DA9063, not on DA9063L */ { DA9063_LDO(DA9063, LDO1, 600, 20, 1860), - .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO1_SEL), }, { DA9063_LDO(DA9063, LDO2, 600, 20, 1860), - .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO2_SEL), }, { DA9063_LDO(DA9063, LDO4, 900, 20, 3440), - .suspend = BFIELD(DA9063_REG_DVC_2, DA9063_VLDO4_SEL), .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO4_LIM), }, { DA9063_LDO(DA9063, LDO5, 900, 50, 3600), - .suspend = BFIELD(DA9063_REG_LDO5_CONT, DA9063_VLDO5_SEL), }, { DA9063_LDO(DA9063, LDO6, 900, 50, 3600), - .suspend = BFIELD(DA9063_REG_LDO6_CONT, DA9063_VLDO6_SEL), }, { DA9063_LDO(DA9063, LDO10, 900, 50, 3600), - .suspend = BFIELD(DA9063_REG_LDO10_CONT, DA9063_VLDO10_SEL), }, }; -- cgit v1.2.3 From fc69bab1ec382d16210ef6bb2d3f117a37169de2 Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Tue, 24 Mar 2020 09:25:16 +0000 Subject: regulator: da9063: Fix get_mode() functions to read sleep field get_mode() is used to retrieve the active mode state. Settings-A config is used during active state, whilst Settings-B is for suspend. This means we only need to check the sleep field of each buck and LDO as that field solely relates to Settings-A config. This change is a clone of the get_mode() update which was committed as part of: - regulator: da9062: fix suspend_enable/disable preparation [a72865f057820ea9f57597915da4b651d65eb92f] Signed-off-by: Adam Thomson Link: https://lore.kernel.org/r/20200324092516.60B5C3FB8D@swsrvapps-01.diasemi.com Signed-off-by: Mark Brown --- drivers/regulator/da9063-regulator.c | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index 46b7301efcd6..6d07e6864173 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -226,7 +226,6 @@ static int da9063_buck_set_mode(struct regulator_dev *rdev, unsigned mode) static unsigned da9063_buck_get_mode(struct regulator_dev *rdev) { struct da9063_regulator *regl = rdev_get_drvdata(rdev); - struct regmap_field *field; unsigned int val; int ret; @@ -247,18 +246,7 @@ static unsigned da9063_buck_get_mode(struct regulator_dev *rdev) return REGULATOR_MODE_NORMAL; } - /* Detect current regulator state */ - ret = regmap_field_read(regl->suspend, &val); - if (ret < 0) - return 0; - - /* Read regulator mode from proper register, depending on state */ - if (val) - field = regl->suspend_sleep; - else - field = regl->sleep; - - ret = regmap_field_read(field, &val); + ret = regmap_field_read(regl->sleep, &val); if (ret < 0) return 0; @@ -295,21 +283,9 @@ static int da9063_ldo_set_mode(struct regulator_dev *rdev, unsigned mode) static unsigned da9063_ldo_get_mode(struct regulator_dev *rdev) { struct da9063_regulator *regl = rdev_get_drvdata(rdev); - struct regmap_field *field; int ret, val; - /* Detect current regulator state */ - ret = regmap_field_read(regl->suspend, &val); - if (ret < 0) - return 0; - - /* Read regulator mode from proper register, depending on state */ - if (val) - field = regl->suspend_sleep; - else - field = regl->sleep; - - ret = regmap_field_read(field, &val); + ret = regmap_field_read(regl->sleep, &val); if (ret < 0) return 0; -- cgit v1.2.3 From 86332c343491c6d2228a1e0c80b1ea98a2653d20 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 23 Mar 2020 21:14:24 -0700 Subject: regulator: qcom_smd: Add pmi8994 regulator support The pmi8994 is commonly found on MSM8996 based devices, such as the Dragonboard 820c, where it supplies power to a number of LDOs on the primary PMIC. Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20200324041424.518160-1-bjorn.andersson@linaro.org Signed-off-by: Mark Brown --- .../bindings/regulator/qcom,smd-rpm-regulator.txt | 13 ++++++ drivers/regulator/qcom_smd-regulator.c | 47 ++++++++++++++++++++++ include/linux/soc/qcom/smd-rpm.h | 1 + 3 files changed, 61 insertions(+) (limited to 'drivers/regulator') diff --git a/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.txt b/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.txt index d126df043403..dea4384f4c03 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.txt @@ -26,6 +26,7 @@ Regulator nodes are identified by their compatible: "qcom,rpm-pm8994-regulators" "qcom,rpm-pm8998-regulators" "qcom,rpm-pma8084-regulators" + "qcom,rpm-pmi8994-regulators" "qcom,rpm-pmi8998-regulators" "qcom,rpm-pms405-regulators" @@ -143,6 +144,15 @@ Regulator nodes are identified by their compatible: Definition: reference to regulator supplying the input pin, as described in the data sheet +- vdd_s1-supply: +- vdd_s2-supply: +- vdd_s3-supply: +- vdd_bst_byp-supply: + Usage: optional (pmi8994 only) + Value type: + Definition: reference to regulator supplying the input pin, as + described in the data sheet + - vdd_s1-supply: - vdd_s2-supply: - vdd_s3-supply: @@ -259,6 +269,9 @@ pma8084: l6, l7, l8, l9, l10, l11, l12, l13, l14, l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, l25, l26, l27, lvs1, lvs2, lvs3, lvs4, 5vs1 +pmi8994: + s1, s2, s3, boost-bypass + pmi8998: bob diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c index fff8d5fdef6a..fdde4195cefb 100644 --- a/drivers/regulator/qcom_smd-regulator.c +++ b/drivers/regulator/qcom_smd-regulator.c @@ -445,6 +445,44 @@ static const struct regulator_desc pm8994_lnldo = { .ops = &rpm_smps_ldo_ops_fixed, }; +static const struct regulator_desc pmi8994_ftsmps = { + .linear_ranges = (struct regulator_linear_range[]) { + REGULATOR_LINEAR_RANGE(350000, 0, 199, 5000), + REGULATOR_LINEAR_RANGE(700000, 200, 349, 10000), + }, + .n_linear_ranges = 2, + .n_voltages = 350, + .ops = &rpm_smps_ldo_ops, +}; + +static const struct regulator_desc pmi8994_hfsmps = { + .linear_ranges = (struct regulator_linear_range[]) { + REGULATOR_LINEAR_RANGE(350000, 0, 80, 12500), + REGULATOR_LINEAR_RANGE(700000, 81, 141, 25000), + }, + .n_linear_ranges = 2, + .n_voltages = 142, + .ops = &rpm_smps_ldo_ops, +}; + +static const struct regulator_desc pmi8994_bby = { + .linear_ranges = (struct regulator_linear_range[]) { + REGULATOR_LINEAR_RANGE(3000000, 0, 44, 50000), + }, + .n_linear_ranges = 1, + .n_voltages = 45, + .ops = &rpm_bob_ops, +}; + +static const struct regulator_desc pmi8994_boost = { + .linear_ranges = (struct regulator_linear_range[]) { + REGULATOR_LINEAR_RANGE(4000000, 0, 30, 50000), + }, + .n_linear_ranges = 1, + .n_voltages = 31, + .ops = &rpm_smps_ldo_ops, +}; + static const struct regulator_desc pm8998_ftsmps = { .linear_ranges = (struct regulator_linear_range[]) { REGULATOR_LINEAR_RANGE(320000, 0, 258, 4000), @@ -780,6 +818,14 @@ static const struct rpm_regulator_data rpm_pm8994_regulators[] = { {} }; +static const struct rpm_regulator_data rpm_pmi8994_regulators[] = { + { "s1", QCOM_SMD_RPM_SMPB, 1, &pmi8994_ftsmps, "vdd_s1" }, + { "s2", QCOM_SMD_RPM_SMPB, 2, &pmi8994_hfsmps, "vdd_s2" }, + { "s2", QCOM_SMD_RPM_SMPB, 3, &pmi8994_hfsmps, "vdd_s3" }, + { "boost-bypass", QCOM_SMD_RPM_BBYB, 1, &pmi8994_bby, "vdd_bst_byp" }, + {} +}; + static const struct rpm_regulator_data rpm_pm8998_regulators[] = { { "s1", QCOM_SMD_RPM_SMPA, 1, &pm8998_ftsmps, "vdd_s1" }, { "s2", QCOM_SMD_RPM_SMPA, 2, &pm8998_ftsmps, "vdd_s2" }, @@ -862,6 +908,7 @@ static const struct of_device_id rpm_of_match[] = { { .compatible = "qcom,rpm-pm8994-regulators", .data = &rpm_pm8994_regulators }, { .compatible = "qcom,rpm-pm8998-regulators", .data = &rpm_pm8998_regulators }, { .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-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 9e4fdd861a51..da304ce8c8f7 100644 --- a/include/linux/soc/qcom/smd-rpm.h +++ b/include/linux/soc/qcom/smd-rpm.h @@ -10,6 +10,7 @@ struct qcom_smd_rpm; /* * Constants used for addressing resources in the RPM. */ +#define QCOM_SMD_RPM_BBYB 0x62796262 #define QCOM_SMD_RPM_BOBB 0x62626f62 #define QCOM_SMD_RPM_BOOST 0x61747362 #define QCOM_SMD_RPM_BUS_CLK 0x316b6c63 -- cgit v1.2.3