aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2019-07-10 23:24:10 -0700
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2019-07-10 23:24:10 -0700
commit597473720f4dc69749542bfcfed4a927a43d935e (patch)
tree711bf773910fb93d1dd9120c633adc807685e0d8 /drivers/regulator
parentInput: atmel_mxt_ts - fix leak in mxt_update_cfg() (diff)
parentInput: gpio_keys_polled - allow specifying name of input device (diff)
downloadlinux-dev-597473720f4dc69749542bfcfed4a927a43d935e.tar.xz
linux-dev-597473720f4dc69749542bfcfed4a927a43d935e.zip
Merge branch 'next' into for-linus
Prepare input updates for 5.3 merge window.
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/88pm8607.c40
-rw-r--r--drivers/regulator/Kconfig37
-rw-r--r--drivers/regulator/Makefile3
-rw-r--r--drivers/regulator/act8865-regulator.c5
-rw-r--r--drivers/regulator/act8945a-regulator.c206
-rw-r--r--drivers/regulator/arizona-ldo1.c59
-rw-r--r--drivers/regulator/as3711-regulator.c5
-rw-r--r--drivers/regulator/as3722-regulator.c2
-rw-r--r--drivers/regulator/axp20x-regulator.c877
-rw-r--r--drivers/regulator/bcm590xx-regulator.c4
-rw-r--r--drivers/regulator/bd70528-regulator.c289
-rw-r--r--drivers/regulator/bd718x7-regulator.c214
-rw-r--r--drivers/regulator/bd9571mwv-regulator.c18
-rw-r--r--drivers/regulator/core.c1279
-rw-r--r--drivers/regulator/cpcap-regulator.c106
-rw-r--r--drivers/regulator/da9052-regulator.c66
-rw-r--r--drivers/regulator/da9055-regulator.c46
-rw-r--r--drivers/regulator/da9062-regulator.c37
-rw-r--r--drivers/regulator/da9063-regulator.c37
-rw-r--r--drivers/regulator/da9210-regulator.c57
-rw-r--r--drivers/regulator/da9211-regulator.c6
-rw-r--r--drivers/regulator/dbx500-prcmu.c35
-rw-r--r--drivers/regulator/fan53555.c109
-rw-r--r--drivers/regulator/fixed.c41
-rw-r--r--drivers/regulator/gpio-regulator.c194
-rw-r--r--drivers/regulator/helpers.c125
-rw-r--r--drivers/regulator/hi655x-regulator.c1
-rw-r--r--drivers/regulator/internal.h2
-rw-r--r--drivers/regulator/isl6271a-regulator.c13
-rw-r--r--drivers/regulator/lm363x-regulator.c10
-rw-r--r--drivers/regulator/lochnagar-regulator.c53
-rw-r--r--drivers/regulator/lp3971.c4
-rw-r--r--drivers/regulator/lp3972.c4
-rw-r--r--drivers/regulator/lp872x.c82
-rw-r--r--drivers/regulator/lp873x-regulator.c51
-rw-r--r--drivers/regulator/lp8755.c6
-rw-r--r--drivers/regulator/lp87565-regulator.c4
-rw-r--r--drivers/regulator/lp8788-buck.c40
-rw-r--r--drivers/regulator/lp8788-ldo.c12
-rw-r--r--drivers/regulator/ltc3676.c65
-rw-r--r--drivers/regulator/max14577-regulator.c1
-rw-r--r--drivers/regulator/max77620-regulator.c12
-rw-r--r--drivers/regulator/max77650-regulator.c498
-rw-r--r--drivers/regulator/max77686-regulator.c29
-rw-r--r--drivers/regulator/max77802-regulator.c6
-rw-r--r--drivers/regulator/max8952.c10
-rw-r--r--drivers/regulator/max8973-regulator.c8
-rw-r--r--drivers/regulator/max8997-regulator.c2
-rw-r--r--drivers/regulator/mc13783-regulator.c82
-rw-r--r--drivers/regulator/mc13892-regulator.c72
-rw-r--r--drivers/regulator/mc13xxx-regulator-core.c6
-rw-r--r--drivers/regulator/mc13xxx.h24
-rw-r--r--drivers/regulator/mcp16502.c552
-rw-r--r--drivers/regulator/mt6311-regulator.c10
-rw-r--r--drivers/regulator/of_regulator.c85
-rw-r--r--drivers/regulator/palmas-regulator.c7
-rw-r--r--drivers/regulator/pfuze100-regulator.c2
-rw-r--r--drivers/regulator/pv88060-regulator.c62
-rw-r--r--drivers/regulator/pv88080-regulator.c55
-rw-r--r--drivers/regulator/pv88090-regulator.c53
-rw-r--r--drivers/regulator/pwm-regulator.c17
-rw-r--r--drivers/regulator/qcom-rpmh-regulator.c2
-rw-r--r--drivers/regulator/qcom_smd-regulator.c104
-rw-r--r--drivers/regulator/rk808-regulator.c64
-rw-r--r--drivers/regulator/rt5033-regulator.c4
-rw-r--r--drivers/regulator/s2mpa01.c10
-rw-r--r--drivers/regulator/s2mps11.c60
-rw-r--r--drivers/regulator/s5m8767.c19
-rw-r--r--drivers/regulator/stm32-vrefbuf.c121
-rw-r--r--drivers/regulator/stpmic1_regulator.c304
-rw-r--r--drivers/regulator/tps65090-regulator.c6
-rw-r--r--drivers/regulator/tps65218-regulator.c23
-rw-r--r--drivers/regulator/tps65910-regulator.c4
-rw-r--r--drivers/regulator/twl-regulator.c7
-rw-r--r--drivers/regulator/twl6030-regulator.c88
-rw-r--r--drivers/regulator/uniphier-regulator.c8
-rw-r--r--drivers/regulator/wm831x-dcdc.c85
-rw-r--r--drivers/regulator/wm8350-regulator.c4
-rw-r--r--drivers/regulator/wm8994-regulator.c33
79 files changed, 4832 insertions, 1951 deletions
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index fd86446e499b..753a6a1b30c3 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -11,7 +11,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/err.h>
-#include <linux/i2c.h>
#include <linux/of.h>
#include <linux/regulator/of_regulator.h>
#include <linux/platform_device.h>
@@ -22,12 +21,7 @@
struct pm8607_regulator_info {
struct regulator_desc desc;
- struct pm860x_chip *chip;
- struct regulator_dev *regulator;
- struct i2c_client *i2c;
- struct i2c_client *i2c_8606;
- unsigned int *vol_table;
unsigned int *vol_suspend;
int slope_double;
@@ -210,13 +204,15 @@ static const unsigned int LDO14_suspend_table[] = {
static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
{
struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
- int ret = -EINVAL;
+ int ret;
+
+ ret = regulator_list_voltage_table(rdev, index);
+ if (ret < 0)
+ return ret;
+
+ if (info->slope_double)
+ ret <<= 1;
- if (info->vol_table && (index < rdev->desc->n_voltages)) {
- ret = info->vol_table[index];
- if (info->slope_double)
- ret <<= 1;
- }
return ret;
}
@@ -257,6 +253,7 @@ static const struct regulator_ops pm8606_preg_ops = {
.type = REGULATOR_VOLTAGE, \
.id = PM8607_ID_##vreg, \
.owner = THIS_MODULE, \
+ .volt_table = vreg##_table, \
.n_voltages = ARRAY_SIZE(vreg##_table), \
.vsel_reg = PM8607_##vreg, \
.vsel_mask = ARRAY_SIZE(vreg##_table) - 1, \
@@ -266,7 +263,6 @@ static const struct regulator_ops pm8606_preg_ops = {
.enable_mask = 1 << (ebit), \
}, \
.slope_double = (0), \
- .vol_table = (unsigned int *)&vreg##_table, \
.vol_suspend = (unsigned int *)&vreg##_suspend_table, \
}
@@ -278,6 +274,7 @@ static const struct regulator_ops pm8606_preg_ops = {
.type = REGULATOR_VOLTAGE, \
.id = PM8607_ID_LDO##_id, \
.owner = THIS_MODULE, \
+ .volt_table = LDO##_id##_table, \
.n_voltages = ARRAY_SIZE(LDO##_id##_table), \
.vsel_reg = PM8607_##vreg, \
.vsel_mask = (ARRAY_SIZE(LDO##_id##_table) - 1) << (shift), \
@@ -285,7 +282,6 @@ static const struct regulator_ops pm8606_preg_ops = {
.enable_mask = 1 << (ebit), \
}, \
.slope_double = (0), \
- .vol_table = (unsigned int *)&LDO##_id##_table, \
.vol_suspend = (unsigned int *)&LDO##_id##_suspend_table, \
}
@@ -328,7 +324,7 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev,
return -ENODEV;
}
for_each_child_of_node(nproot, np) {
- if (!of_node_cmp(np->name, info->desc.name)) {
+ if (of_node_name_eq(np, info->desc.name)) {
config->init_data =
of_get_regulator_init_data(&pdev->dev, np,
&info->desc);
@@ -349,6 +345,7 @@ static int pm8607_regulator_probe(struct platform_device *pdev)
struct pm8607_regulator_info *info = NULL;
struct regulator_init_data *pdata = dev_get_platdata(&pdev->dev);
struct regulator_config config = { };
+ struct regulator_dev *rdev;
struct resource *res;
int i;
@@ -371,13 +368,9 @@ static int pm8607_regulator_probe(struct platform_device *pdev)
/* i is used to check regulator ID */
i = -1;
}
- info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
- info->i2c_8606 = (chip->id == CHIP_PM8607) ? chip->companion :
- chip->client;
- info->chip = chip;
/* check DVC ramp slope double */
- if ((i == PM8607_ID_BUCK3) && info->chip->buck3_double)
+ if ((i == PM8607_ID_BUCK3) && chip->buck3_double)
info->slope_double = 1;
config.dev = &pdev->dev;
@@ -392,12 +385,11 @@ static int pm8607_regulator_probe(struct platform_device *pdev)
else
config.regmap = chip->regmap_companion;
- info->regulator = devm_regulator_register(&pdev->dev, &info->desc,
- &config);
- if (IS_ERR(info->regulator)) {
+ rdev = devm_regulator_register(&pdev->dev, &info->desc, &config);
+ if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
info->desc.name);
- return PTR_ERR(info->regulator);
+ return PTR_ERR(rdev);
}
platform_set_drvdata(pdev, info);
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 926cee0d0b5f..b7f249ee5e68 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -180,6 +180,17 @@ config REGULATOR_BCM590XX
BCM590xx PMUs. This will enable support for the software
controllable LDO/Switching regulators.
+config REGULATOR_BD70528
+ tristate "ROHM BD70528 Power Regulator"
+ depends on MFD_ROHM_BD70528
+ help
+ This driver supports voltage regulators on ROHM BD70528 PMIC.
+ This will enable support for the software controllable buck
+ and LDO regulators.
+
+ This driver can also be built as a module. If so, the module
+ will be called bd70528-regulator.
+
config REGULATOR_BD718XX
tristate "ROHM BD71837 Power Regulator"
depends on MFD_ROHM_BD718XX
@@ -457,6 +468,14 @@ config REGULATOR_MAX77620
chip to control Step-Down DC-DC and LDOs. Say Y here to
enable the regulator driver.
+config REGULATOR_MAX77650
+ tristate "Maxim MAX77650/77651 regulator support"
+ depends on MFD_MAX77650
+ help
+ Regulator driver for MAX77650/77651 PMIC from Maxim
+ Semiconductor. This device has a SIMO with three independent
+ power rails and an LDO.
+
config REGULATOR_MAX8649
tristate "Maxim 8649 voltage regulator"
depends on I2C
@@ -484,7 +503,7 @@ config REGULATOR_MAX8925
tristate "Maxim MAX8925 Power Management IC"
depends on MFD_MAX8925
help
- Say y here to support the voltage regulaltor of Maxim MAX8925 PMIC.
+ Say y here to support the voltage regulator of Maxim MAX8925 PMIC.
config REGULATOR_MAX8952
tristate "Maxim MAX8952 Power Management IC"
@@ -501,7 +520,7 @@ config REGULATOR_MAX8973
select REGMAP_I2C
help
The MAXIM MAX8973 high-efficiency. three phase, DC-DC step-down
- switching regulator delievers up to 9A of output current. Each
+ switching regulator delivers up to 9A of output current. Each
phase operates at a 2MHz fixed frequency with a 120 deg shift
from the adjacent phase, allowing the use of small magnetic component.
@@ -567,6 +586,16 @@ config REGULATOR_MC13892
Say y here to support the regulators found on the Freescale MC13892
PMIC.
+config REGULATOR_MCP16502
+ tristate "Microchip MCP16502 PMIC"
+ depends on I2C && OF
+ select REGMAP_I2C
+ help
+ Say y here to support the MCP16502 PMIC. This driver supports
+ basic operations (get/set voltage, get/set operating mode)
+ through the regulator interface. In addition it enables
+ suspend-to-ram/standby transition.
+
config REGULATOR_MT6311
tristate "MediaTek MT6311 PMIC"
depends on I2C
@@ -636,7 +665,7 @@ config REGULATOR_PCF50633
tristate "NXP PCF50633 regulator driver"
depends on MFD_PCF50633
help
- Say Y here to support the voltage regulators and convertors
+ Say Y here to support the voltage regulators and converters
on PCF50633
config REGULATOR_PFUZE100
@@ -914,7 +943,7 @@ config REGULATOR_TPS65132
select REGMAP_I2C
help
This driver supports TPS65132 single inductor - dual output
- power supply specifcally designed for display panels.
+ power supply specifically designed for display panels.
config REGULATOR_TPS65217
tristate "TI TPS65217 Power regulators"
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 72488ef11b8a..1169f8a27d91 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o
obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
+obj-$(CONFIG_REGULATOR_BD70528) += bd70528-regulator.o
obj-$(CONFIG_REGULATOR_BD718XX) += bd718x7-regulator.o
obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
@@ -60,6 +61,7 @@ obj-$(CONFIG_REGULATOR_LTC3676) += ltc3676.o
obj-$(CONFIG_REGULATOR_MAX14577) += max14577-regulator.o
obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o
+obj-$(CONFIG_REGULATOR_MAX77650) += max77650-regulator.o
obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o
obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
obj-$(CONFIG_REGULATOR_MAX8907) += max8907-regulator.o
@@ -74,6 +76,7 @@ obj-$(CONFIG_REGULATOR_MAX77802) += max77802-regulator.o
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_MT6311) += mt6311-regulator.o
obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o
obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o
diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c
index 21e20483bd91..e0239cf3f56d 100644
--- a/drivers/regulator/act8865-regulator.c
+++ b/drivers/regulator/act8865-regulator.c
@@ -131,7 +131,7 @@
* ACT8865 voltage number
*/
#define ACT8865_VOLTAGE_NUM 64
-#define ACT8600_SUDCDC_VOLTAGE_NUM 255
+#define ACT8600_SUDCDC_VOLTAGE_NUM 256
struct act8865 {
struct regmap *regmap;
@@ -222,7 +222,8 @@ static const struct regulator_linear_range act8600_sudcdc_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(3000000, 0, 63, 0),
REGULATOR_LINEAR_RANGE(3000000, 64, 159, 100000),
REGULATOR_LINEAR_RANGE(12600000, 160, 191, 200000),
- REGULATOR_LINEAR_RANGE(19000000, 191, 255, 400000),
+ REGULATOR_LINEAR_RANGE(19000000, 192, 247, 400000),
+ REGULATOR_LINEAR_RANGE(41400000, 248, 255, 0),
};
static struct regulator_ops act8865_ops = {
diff --git a/drivers/regulator/act8945a-regulator.c b/drivers/regulator/act8945a-regulator.c
index 43fda8b4455a..caa61d306a69 100644
--- a/drivers/regulator/act8945a-regulator.c
+++ b/drivers/regulator/act8945a-regulator.c
@@ -15,31 +15,41 @@
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
+#include <dt-bindings/regulator/active-semi,8945a-regulator.h>
/**
* ACT8945A Global Register Map.
*/
#define ACT8945A_SYS_MODE 0x00
#define ACT8945A_SYS_CTRL 0x01
+#define ACT8945A_SYS_UNLK_REGS 0x0b
#define ACT8945A_DCDC1_VSET1 0x20
#define ACT8945A_DCDC1_VSET2 0x21
#define ACT8945A_DCDC1_CTRL 0x22
+#define ACT8945A_DCDC1_SUS 0x24
#define ACT8945A_DCDC2_VSET1 0x30
#define ACT8945A_DCDC2_VSET2 0x31
#define ACT8945A_DCDC2_CTRL 0x32
+#define ACT8945A_DCDC2_SUS 0x34
#define ACT8945A_DCDC3_VSET1 0x40
#define ACT8945A_DCDC3_VSET2 0x41
#define ACT8945A_DCDC3_CTRL 0x42
+#define ACT8945A_DCDC3_SUS 0x44
#define ACT8945A_LDO1_VSET 0x50
#define ACT8945A_LDO1_CTRL 0x51
+#define ACT8945A_LDO1_SUS 0x52
#define ACT8945A_LDO2_VSET 0x54
#define ACT8945A_LDO2_CTRL 0x55
+#define ACT8945A_LDO2_SUS 0x56
#define ACT8945A_LDO3_VSET 0x60
#define ACT8945A_LDO3_CTRL 0x61
+#define ACT8945A_LDO3_SUS 0x62
#define ACT8945A_LDO4_VSET 0x64
#define ACT8945A_LDO4_CTRL 0x65
+#define ACT8945A_LDO4_SUS 0x66
/**
* Field Definitions.
@@ -60,7 +70,12 @@ enum {
ACT8945A_ID_LDO2,
ACT8945A_ID_LDO3,
ACT8945A_ID_LDO4,
- ACT8945A_REG_NUM,
+ ACT8945A_ID_MAX,
+};
+
+struct act8945a_pmic {
+ struct regmap *regmap;
+ u32 op_mode[ACT8945A_ID_MAX];
};
static const struct regulator_linear_range act8945a_voltage_ranges[] = {
@@ -69,6 +84,144 @@ static const struct regulator_linear_range act8945a_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000),
};
+static int act8945a_set_suspend_state(struct regulator_dev *rdev, bool enable)
+{
+ struct regmap *regmap = rdev->regmap;
+ int id = rdev_get_id(rdev);
+ int reg, val;
+
+ switch (id) {
+ case ACT8945A_ID_DCDC1:
+ reg = ACT8945A_DCDC1_SUS;
+ val = 0xa8;
+ break;
+ case ACT8945A_ID_DCDC2:
+ reg = ACT8945A_DCDC2_SUS;
+ val = 0xa8;
+ break;
+ case ACT8945A_ID_DCDC3:
+ reg = ACT8945A_DCDC3_SUS;
+ val = 0xa8;
+ break;
+ case ACT8945A_ID_LDO1:
+ reg = ACT8945A_LDO1_SUS;
+ val = 0xe8;
+ break;
+ case ACT8945A_ID_LDO2:
+ reg = ACT8945A_LDO2_SUS;
+ val = 0xe8;
+ break;
+ case ACT8945A_ID_LDO3:
+ reg = ACT8945A_LDO3_SUS;
+ val = 0xe8;
+ break;
+ case ACT8945A_ID_LDO4:
+ reg = ACT8945A_LDO4_SUS;
+ val = 0xe8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (enable)
+ val |= BIT(4);
+
+ /*
+ * Ask the PMIC to enable/disable this output when entering hibernate
+ * mode.
+ */
+ return regmap_write(regmap, reg, val);
+}
+
+static int act8945a_set_suspend_enable(struct regulator_dev *rdev)
+{
+ return act8945a_set_suspend_state(rdev, true);
+}
+
+static int act8945a_set_suspend_disable(struct regulator_dev *rdev)
+{
+ return act8945a_set_suspend_state(rdev, false);
+}
+
+static unsigned int act8945a_of_map_mode(unsigned int mode)
+{
+ switch (mode) {
+ case ACT8945A_REGULATOR_MODE_FIXED:
+ case ACT8945A_REGULATOR_MODE_NORMAL:
+ return REGULATOR_MODE_NORMAL;
+ case ACT8945A_REGULATOR_MODE_LOWPOWER:
+ return REGULATOR_MODE_STANDBY;
+ default:
+ return REGULATOR_MODE_INVALID;
+ }
+}
+
+static int act8945a_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+ struct act8945a_pmic *act8945a = rdev_get_drvdata(rdev);
+ struct regmap *regmap = rdev->regmap;
+ int id = rdev_get_id(rdev);
+ int reg, ret, val = 0;
+
+ switch (id) {
+ case ACT8945A_ID_DCDC1:
+ reg = ACT8945A_DCDC1_CTRL;
+ break;
+ case ACT8945A_ID_DCDC2:
+ reg = ACT8945A_DCDC2_CTRL;
+ break;
+ case ACT8945A_ID_DCDC3:
+ reg = ACT8945A_DCDC3_CTRL;
+ break;
+ case ACT8945A_ID_LDO1:
+ reg = ACT8945A_LDO1_SUS;
+ break;
+ case ACT8945A_ID_LDO2:
+ reg = ACT8945A_LDO2_SUS;
+ break;
+ case ACT8945A_ID_LDO3:
+ reg = ACT8945A_LDO3_SUS;
+ break;
+ case ACT8945A_ID_LDO4:
+ reg = ACT8945A_LDO4_SUS;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (mode) {
+ case REGULATOR_MODE_STANDBY:
+ if (id > ACT8945A_ID_DCDC3)
+ val = BIT(5);
+ break;
+ case REGULATOR_MODE_NORMAL:
+ if (id <= ACT8945A_ID_DCDC3)
+ val = BIT(5);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_update_bits(regmap, reg, BIT(5), val);
+ if (ret)
+ return ret;
+
+ act8945a->op_mode[id] = mode;
+
+ return 0;
+}
+
+static unsigned int act8945a_get_mode(struct regulator_dev *rdev)
+{
+ struct act8945a_pmic *act8945a = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+
+ if (id < ACT8945A_ID_DCDC1 || id >= ACT8945A_ID_MAX)
+ return -EINVAL;
+
+ return act8945a->op_mode[id];
+}
+
static const struct regulator_ops act8945a_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
@@ -76,7 +229,11 @@ static const struct regulator_ops act8945a_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
+ .set_mode = act8945a_set_mode,
+ .get_mode = act8945a_get_mode,
.is_enabled = regulator_is_enabled_regmap,
+ .set_suspend_enable = act8945a_set_suspend_enable,
+ .set_suspend_disable = act8945a_set_suspend_disable,
};
#define ACT89xx_REG(_name, _family, _id, _vsel_reg, _supply) \
@@ -84,6 +241,7 @@ static const struct regulator_ops act8945a_ops = {
.name = _name, \
.supply_name = _supply, \
.of_match = of_match_ptr("REG_"#_id), \
+ .of_map_mode = act8945a_of_map_mode, \
.regulators_node = of_match_ptr("regulators"), \
.id = _family##_ID_##_id, \
.type = REGULATOR_VOLTAGE, \
@@ -122,10 +280,22 @@ static int act8945a_pmic_probe(struct platform_device *pdev)
{
struct regulator_config config = { };
const struct regulator_desc *regulators;
+ struct act8945a_pmic *act8945a;
struct regulator_dev *rdev;
int i, num_regulators;
bool voltage_select;
+ act8945a = devm_kzalloc(&pdev->dev, sizeof(*act8945a), GFP_KERNEL);
+ if (!act8945a)
+ return -ENOMEM;
+
+ act8945a->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!act8945a->regmap) {
+ dev_err(&pdev->dev,
+ "could not retrieve regmap from parent device\n");
+ return -EINVAL;
+ }
+
voltage_select = of_property_read_bool(pdev->dev.parent->of_node,
"active-semi,vsel-high");
@@ -139,8 +309,10 @@ static int act8945a_pmic_probe(struct platform_device *pdev)
config.dev = &pdev->dev;
config.dev->of_node = pdev->dev.parent->of_node;
+ config.driver_data = act8945a;
for (i = 0; i < num_regulators; i++) {
- rdev = devm_regulator_register(&pdev->dev, &regulators[i], &config);
+ rdev = devm_regulator_register(&pdev->dev, &regulators[i],
+ &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev,
"failed to register %s regulator\n",
@@ -149,14 +321,42 @@ static int act8945a_pmic_probe(struct platform_device *pdev)
}
}
- return 0;
+ platform_set_drvdata(pdev, act8945a);
+
+ /* Unlock expert registers. */
+ return regmap_write(act8945a->regmap, ACT8945A_SYS_UNLK_REGS, 0xef);
+}
+
+static int __maybe_unused act8945a_suspend(struct device *pdev)
+{
+ struct act8945a_pmic *act8945a = dev_get_drvdata(pdev);
+
+ /*
+ * Ask the PMIC to enter the suspend mode on the next PWRHLD
+ * transition.
+ */
+ return regmap_write(act8945a->regmap, ACT8945A_SYS_CTRL, 0x42);
+}
+
+static SIMPLE_DEV_PM_OPS(act8945a_pm, act8945a_suspend, NULL);
+
+static void act8945a_pmic_shutdown(struct platform_device *pdev)
+{
+ struct act8945a_pmic *act8945a = platform_get_drvdata(pdev);
+
+ /*
+ * Ask the PMIC to shutdown everything on the next PWRHLD transition.
+ */
+ regmap_write(act8945a->regmap, ACT8945A_SYS_CTRL, 0x0);
}
static struct platform_driver act8945a_pmic_driver = {
.driver = {
.name = "act8945a-regulator",
+ .pm = &act8945a_pm,
},
.probe = act8945a_pmic_probe,
+ .shutdown = act8945a_pmic_shutdown,
};
module_platform_driver(act8945a_pmic_driver);
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
index 9a72eae4926d..bf3ab405eed1 100644
--- a/drivers/regulator/arizona-ldo1.c
+++ b/drivers/regulator/arizona-ldo1.c
@@ -40,35 +40,10 @@ struct arizona_ldo1 {
struct gpio_desc *ena_gpiod;
};
-static int arizona_ldo1_hc_list_voltage(struct regulator_dev *rdev,
- unsigned int selector)
-{
- if (selector >= rdev->desc->n_voltages)
- return -EINVAL;
-
- if (selector == rdev->desc->n_voltages - 1)
- return 1800000;
- else
- return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
-}
-
-static int arizona_ldo1_hc_map_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV)
-{
- int sel;
-
- sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
- if (sel >= rdev->desc->n_voltages)
- sel = rdev->desc->n_voltages - 1;
-
- return sel;
-}
-
static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev,
unsigned sel)
{
- struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev);
- struct regmap *regmap = ldo->regmap;
+ struct regmap *regmap = rdev_get_regmap(rdev);
unsigned int val;
int ret;
@@ -85,16 +60,12 @@ static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev,
if (val)
return 0;
- val = sel << ARIZONA_LDO1_VSEL_SHIFT;
-
- return regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_1,
- ARIZONA_LDO1_VSEL_MASK, val);
+ return regulator_set_voltage_sel_regmap(rdev, sel);
}
static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev)
{
- struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev);
- struct regmap *regmap = ldo->regmap;
+ struct regmap *regmap = rdev_get_regmap(rdev);
unsigned int val;
int ret;
@@ -105,32 +76,35 @@ static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev)
if (val & ARIZONA_LDO1_HI_PWR)
return rdev->desc->n_voltages - 1;
- ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_1, &val);
- if (ret != 0)
- return ret;
-
- return (val & ARIZONA_LDO1_VSEL_MASK) >> ARIZONA_LDO1_VSEL_SHIFT;
+ return regulator_get_voltage_sel_regmap(rdev);
}
static const struct regulator_ops arizona_ldo1_hc_ops = {
- .list_voltage = arizona_ldo1_hc_list_voltage,
- .map_voltage = arizona_ldo1_hc_map_voltage,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = arizona_ldo1_hc_get_voltage_sel,
.set_voltage_sel = arizona_ldo1_hc_set_voltage_sel,
.get_bypass = regulator_get_bypass_regmap,
.set_bypass = regulator_set_bypass_regmap,
};
+static const struct regulator_linear_range arizona_ldo1_hc_ranges[] = {
+ REGULATOR_LINEAR_RANGE(900000, 0, 0x6, 50000),
+ REGULATOR_LINEAR_RANGE(1800000, 0x7, 0x7, 0),
+};
+
static const struct regulator_desc arizona_ldo1_hc = {
.name = "LDO1",
.supply_name = "LDOVDD",
.type = REGULATOR_VOLTAGE,
.ops = &arizona_ldo1_hc_ops,
+ .vsel_reg = ARIZONA_LDO1_CONTROL_1,
+ .vsel_mask = ARIZONA_LDO1_VSEL_MASK,
.bypass_reg = ARIZONA_LDO1_CONTROL_1,
.bypass_mask = ARIZONA_LDO1_BYPASS,
- .min_uV = 900000,
- .uV_step = 50000,
+ .linear_ranges = arizona_ldo1_hc_ranges,
+ .n_linear_ranges = ARRAY_SIZE(arizona_ldo1_hc_ranges),
.n_voltages = 8,
.enable_time = 1500,
.ramp_delay = 24000,
@@ -283,9 +257,6 @@ static int arizona_ldo1_common_init(struct platform_device *pdev,
of_node_put(config.of_node);
if (IS_ERR(ldo1->regulator)) {
- if (config.ena_gpiod)
- gpiod_put(config.ena_gpiod);
-
ret = PTR_ERR(ldo1->regulator);
dev_err(&pdev->dev, "Failed to register LDO1 supply: %d\n",
ret);
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c
index 565a71343a8e..f7fe218bb3e4 100644
--- a/drivers/regulator/as3711-regulator.c
+++ b/drivers/regulator/as3711-regulator.c
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* AS3711 PMIC regulator driver, using DCDC Step Down and LDO supplies
*
* Copyright (C) 2012 Renesas Electronics Corporation
* Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the version 2 of the GNU General Public License as
- * published by the Free Software Foundation
*/
#include <linux/err.h>
diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c
index 66337e12719b..e5fed289b52d 100644
--- a/drivers/regulator/as3722-regulator.c
+++ b/drivers/regulator/as3722-regulator.c
@@ -886,7 +886,7 @@ static int as3722_regulator_probe(struct platform_device *pdev)
as3722_regs->desc[id].min_uV = 410000;
} else {
as3722_regs->desc[id].n_voltages =
- AS3722_SD0_VSEL_MAX + 1,
+ AS3722_SD0_VSEL_MAX + 1;
as3722_regs->desc[id].min_uV = 610000;
}
as3722_regs->desc[id].uV_step = 10000;
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index a3734039a86a..fba8f58ab769 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -13,31 +13,262 @@
* GNU General Public License for more details.
*/
+#include <linux/bitops.h>
+#include <linux/delay.h>
#include <linux/err.h>
#include <linux/init.h>
+#include <linux/mfd/axp20x.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
-#include <linux/mfd/axp20x.h>
#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
+#define AXP20X_GPIO0_FUNC_MASK GENMASK(3, 0)
+#define AXP20X_GPIO1_FUNC_MASK GENMASK(3, 0)
+
#define AXP20X_IO_ENABLED 0x03
#define AXP20X_IO_DISABLED 0x07
+#define AXP20X_WORKMODE_DCDC2_MASK BIT_MASK(2)
+#define AXP20X_WORKMODE_DCDC3_MASK BIT_MASK(1)
+
+#define AXP20X_FREQ_DCDC_MASK GENMASK(3, 0)
+
+#define AXP20X_VBUS_IPSOUT_MGMT_MASK BIT_MASK(2)
+
+#define AXP20X_DCDC2_V_OUT_MASK GENMASK(5, 0)
+#define AXP20X_DCDC3_V_OUT_MASK GENMASK(7, 0)
+#define AXP20X_LDO24_V_OUT_MASK GENMASK(7, 4)
+#define AXP20X_LDO3_V_OUT_MASK GENMASK(6, 0)
+#define AXP20X_LDO5_V_OUT_MASK GENMASK(7, 4)
+
+#define AXP20X_PWR_OUT_EXTEN_MASK BIT_MASK(0)
+#define AXP20X_PWR_OUT_DCDC3_MASK BIT_MASK(1)
+#define AXP20X_PWR_OUT_LDO2_MASK BIT_MASK(2)
+#define AXP20X_PWR_OUT_LDO4_MASK BIT_MASK(3)
+#define AXP20X_PWR_OUT_DCDC2_MASK BIT_MASK(4)
+#define AXP20X_PWR_OUT_LDO3_MASK BIT_MASK(6)
+
+#define AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_RATE_MASK BIT_MASK(0)
+#define AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_RATE(x) \
+ ((x) << 0)
+#define AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE_MASK BIT_MASK(1)
+#define AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE(x) \
+ ((x) << 1)
+#define AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN_MASK BIT_MASK(2)
+#define AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_EN BIT(2)
+#define AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN_MASK BIT_MASK(3)
+#define AXP20X_DCDC2_LDO3_V_RAMP_LDO3_EN BIT(3)
+
+#define AXP20X_LDO4_V_OUT_1250mV_START 0x0
+#define AXP20X_LDO4_V_OUT_1250mV_STEPS 0
+#define AXP20X_LDO4_V_OUT_1250mV_END \
+ (AXP20X_LDO4_V_OUT_1250mV_START + AXP20X_LDO4_V_OUT_1250mV_STEPS)
+#define AXP20X_LDO4_V_OUT_1300mV_START 0x1
+#define AXP20X_LDO4_V_OUT_1300mV_STEPS 7
+#define AXP20X_LDO4_V_OUT_1300mV_END \
+ (AXP20X_LDO4_V_OUT_1300mV_START + AXP20X_LDO4_V_OUT_1300mV_STEPS)
+#define AXP20X_LDO4_V_OUT_2500mV_START 0x9
+#define AXP20X_LDO4_V_OUT_2500mV_STEPS 0
+#define AXP20X_LDO4_V_OUT_2500mV_END \
+ (AXP20X_LDO4_V_OUT_2500mV_START + AXP20X_LDO4_V_OUT_2500mV_STEPS)
+#define AXP20X_LDO4_V_OUT_2700mV_START 0xa
+#define AXP20X_LDO4_V_OUT_2700mV_STEPS 1
+#define AXP20X_LDO4_V_OUT_2700mV_END \
+ (AXP20X_LDO4_V_OUT_2700mV_START + AXP20X_LDO4_V_OUT_2700mV_STEPS)
+#define AXP20X_LDO4_V_OUT_3000mV_START 0xc
+#define AXP20X_LDO4_V_OUT_3000mV_STEPS 3
+#define AXP20X_LDO4_V_OUT_3000mV_END \
+ (AXP20X_LDO4_V_OUT_3000mV_START + AXP20X_LDO4_V_OUT_3000mV_STEPS)
+#define AXP20X_LDO4_V_OUT_NUM_VOLTAGES 16
+
#define AXP22X_IO_ENABLED 0x03
#define AXP22X_IO_DISABLED 0x04
-#define AXP20X_WORKMODE_DCDC2_MASK BIT(2)
-#define AXP20X_WORKMODE_DCDC3_MASK BIT(1)
-#define AXP22X_WORKMODE_DCDCX_MASK(x) BIT(x)
-
-#define AXP20X_FREQ_DCDC_MASK 0x0f
+#define AXP22X_WORKMODE_DCDCX_MASK(x) BIT_MASK(x)
#define AXP22X_MISC_N_VBUSEN_FUNC BIT(4)
+#define AXP22X_DCDC1_V_OUT_MASK GENMASK(4, 0)
+#define AXP22X_DCDC2_V_OUT_MASK GENMASK(5, 0)
+#define AXP22X_DCDC3_V_OUT_MASK GENMASK(5, 0)
+#define AXP22X_DCDC4_V_OUT_MASK GENMASK(5, 0)
+#define AXP22X_DCDC5_V_OUT_MASK GENMASK(4, 0)
+#define AXP22X_DC5LDO_V_OUT_MASK GENMASK(2, 0)
+#define AXP22X_ALDO1_V_OUT_MASK GENMASK(4, 0)
+#define AXP22X_ALDO2_V_OUT_MASK GENMASK(4, 0)
+#define AXP22X_ALDO3_V_OUT_MASK GENMASK(4, 0)
+#define AXP22X_DLDO1_V_OUT_MASK GENMASK(4, 0)
+#define AXP22X_DLDO2_V_OUT_MASK GENMASK(4, 0)
+#define AXP22X_DLDO3_V_OUT_MASK GENMASK(4, 0)
+#define AXP22X_DLDO4_V_OUT_MASK GENMASK(4, 0)
+#define AXP22X_ELDO1_V_OUT_MASK GENMASK(4, 0)
+#define AXP22X_ELDO2_V_OUT_MASK GENMASK(4, 0)
+#define AXP22X_ELDO3_V_OUT_MASK GENMASK(4, 0)
+#define AXP22X_LDO_IO0_V_OUT_MASK GENMASK(4, 0)
+#define AXP22X_LDO_IO1_V_OUT_MASK GENMASK(4, 0)
+
+#define AXP22X_PWR_OUT_DC5LDO_MASK BIT_MASK(0)
+#define AXP22X_PWR_OUT_DCDC1_MASK BIT_MASK(1)
+#define AXP22X_PWR_OUT_DCDC2_MASK BIT_MASK(2)
+#define AXP22X_PWR_OUT_DCDC3_MASK BIT_MASK(3)
+#define AXP22X_PWR_OUT_DCDC4_MASK BIT_MASK(4)
+#define AXP22X_PWR_OUT_DCDC5_MASK BIT_MASK(5)
+#define AXP22X_PWR_OUT_ALDO1_MASK BIT_MASK(6)
+#define AXP22X_PWR_OUT_ALDO2_MASK BIT_MASK(7)
+
+#define AXP22X_PWR_OUT_SW_MASK BIT_MASK(6)
+#define AXP22X_PWR_OUT_DC1SW_MASK BIT_MASK(7)
+
+#define AXP22X_PWR_OUT_ELDO1_MASK BIT_MASK(0)
+#define AXP22X_PWR_OUT_ELDO2_MASK BIT_MASK(1)
+#define AXP22X_PWR_OUT_ELDO3_MASK BIT_MASK(2)
+#define AXP22X_PWR_OUT_DLDO1_MASK BIT_MASK(3)
+#define AXP22X_PWR_OUT_DLDO2_MASK BIT_MASK(4)
+#define AXP22X_PWR_OUT_DLDO3_MASK BIT_MASK(5)
+#define AXP22X_PWR_OUT_DLDO4_MASK BIT_MASK(6)
+#define AXP22X_PWR_OUT_ALDO3_MASK BIT_MASK(7)
+
+#define AXP803_PWR_OUT_DCDC1_MASK BIT_MASK(0)
+#define AXP803_PWR_OUT_DCDC2_MASK BIT_MASK(1)
+#define AXP803_PWR_OUT_DCDC3_MASK BIT_MASK(2)
+#define AXP803_PWR_OUT_DCDC4_MASK BIT_MASK(3)
+#define AXP803_PWR_OUT_DCDC5_MASK BIT_MASK(4)
+#define AXP803_PWR_OUT_DCDC6_MASK BIT_MASK(5)
+
+#define AXP803_PWR_OUT_FLDO1_MASK BIT_MASK(2)
+#define AXP803_PWR_OUT_FLDO2_MASK BIT_MASK(3)
+
+#define AXP803_DCDC1_V_OUT_MASK GENMASK(4, 0)
+#define AXP803_DCDC2_V_OUT_MASK GENMASK(6, 0)
+#define AXP803_DCDC3_V_OUT_MASK GENMASK(6, 0)
+#define AXP803_DCDC4_V_OUT_MASK GENMASK(6, 0)
+#define AXP803_DCDC5_V_OUT_MASK GENMASK(6, 0)
+#define AXP803_DCDC6_V_OUT_MASK GENMASK(6, 0)
+
+#define AXP803_FLDO1_V_OUT_MASK GENMASK(3, 0)
+#define AXP803_FLDO2_V_OUT_MASK GENMASK(3, 0)
+
+#define AXP803_DCDC23_POLYPHASE_DUAL BIT(6)
+#define AXP803_DCDC56_POLYPHASE_DUAL BIT(5)
+
+#define AXP803_DCDC234_500mV_START 0x00
+#define AXP803_DCDC234_500mV_STEPS 70
+#define AXP803_DCDC234_500mV_END \
+ (AXP803_DCDC234_500mV_START + AXP803_DCDC234_500mV_STEPS)
+#define AXP803_DCDC234_1220mV_START 0x47
+#define AXP803_DCDC234_1220mV_STEPS 4
+#define AXP803_DCDC234_1220mV_END \
+ (AXP803_DCDC234_1220mV_START + AXP803_DCDC234_1220mV_STEPS)
+#define AXP803_DCDC234_NUM_VOLTAGES 76
+
+#define AXP803_DCDC5_800mV_START 0x00
+#define AXP803_DCDC5_800mV_STEPS 32
+#define AXP803_DCDC5_800mV_END \
+ (AXP803_DCDC5_800mV_START + AXP803_DCDC5_800mV_STEPS)
+#define AXP803_DCDC5_1140mV_START 0x21
+#define AXP803_DCDC5_1140mV_STEPS 35
+#define AXP803_DCDC5_1140mV_END \
+ (AXP803_DCDC5_1140mV_START + AXP803_DCDC5_1140mV_STEPS)
+#define AXP803_DCDC5_NUM_VOLTAGES 68
+
+#define AXP803_DCDC6_600mV_START 0x00
+#define AXP803_DCDC6_600mV_STEPS 50
+#define AXP803_DCDC6_600mV_END \
+ (AXP803_DCDC6_600mV_START + AXP803_DCDC6_600mV_STEPS)
+#define AXP803_DCDC6_1120mV_START 0x33
+#define AXP803_DCDC6_1120mV_STEPS 14
+#define AXP803_DCDC6_1120mV_END \
+ (AXP803_DCDC6_1120mV_START + AXP803_DCDC6_1120mV_STEPS)
+#define AXP803_DCDC6_NUM_VOLTAGES 72
+
+#define AXP803_DLDO2_700mV_START 0x00
+#define AXP803_DLDO2_700mV_STEPS 26
+#define AXP803_DLDO2_700mV_END \
+ (AXP803_DLDO2_700mV_START + AXP803_DLDO2_700mV_STEPS)
+#define AXP803_DLDO2_3400mV_START 0x1b
+#define AXP803_DLDO2_3400mV_STEPS 4
+#define AXP803_DLDO2_3400mV_END \
+ (AXP803_DLDO2_3400mV_START + AXP803_DLDO2_3400mV_STEPS)
+#define AXP803_DLDO2_NUM_VOLTAGES 32
+
+#define AXP806_DCDCA_V_CTRL_MASK GENMASK(6, 0)
+#define AXP806_DCDCB_V_CTRL_MASK GENMASK(4, 0)
+#define AXP806_DCDCC_V_CTRL_MASK GENMASK(6, 0)
+#define AXP806_DCDCD_V_CTRL_MASK GENMASK(5, 0)
+#define AXP806_DCDCE_V_CTRL_MASK GENMASK(4, 0)
+#define AXP806_ALDO1_V_CTRL_MASK GENMASK(4, 0)
+#define AXP806_ALDO2_V_CTRL_MASK GENMASK(4, 0)
+#define AXP806_ALDO3_V_CTRL_MASK GENMASK(4, 0)
+#define AXP806_BLDO1_V_CTRL_MASK GENMASK(3, 0)
+#define AXP806_BLDO2_V_CTRL_MASK GENMASK(3, 0)
+#define AXP806_BLDO3_V_CTRL_MASK GENMASK(3, 0)
+#define AXP806_BLDO4_V_CTRL_MASK GENMASK(3, 0)
+#define AXP806_CLDO1_V_CTRL_MASK GENMASK(4, 0)
+#define AXP806_CLDO2_V_CTRL_MASK GENMASK(4, 0)
+#define AXP806_CLDO3_V_CTRL_MASK GENMASK(4, 0)
+
+#define AXP806_PWR_OUT_DCDCA_MASK BIT_MASK(0)
+#define AXP806_PWR_OUT_DCDCB_MASK BIT_MASK(1)
+#define AXP806_PWR_OUT_DCDCC_MASK BIT_MASK(2)
+#define AXP806_PWR_OUT_DCDCD_MASK BIT_MASK(3)
+#define AXP806_PWR_OUT_DCDCE_MASK BIT_MASK(4)
+#define AXP806_PWR_OUT_ALDO1_MASK BIT_MASK(5)
+#define AXP806_PWR_OUT_ALDO2_MASK BIT_MASK(6)
+#define AXP806_PWR_OUT_ALDO3_MASK BIT_MASK(7)
+#define AXP806_PWR_OUT_BLDO1_MASK BIT_MASK(0)
+#define AXP806_PWR_OUT_BLDO2_MASK BIT_MASK(1)
+#define AXP806_PWR_OUT_BLDO3_MASK BIT_MASK(2)
+#define AXP806_PWR_OUT_BLDO4_MASK BIT_MASK(3)
+#define AXP806_PWR_OUT_CLDO1_MASK BIT_MASK(4)
+#define AXP806_PWR_OUT_CLDO2_MASK BIT_MASK(5)
+#define AXP806_PWR_OUT_CLDO3_MASK BIT_MASK(6)
+#define AXP806_PWR_OUT_SW_MASK BIT_MASK(7)
+
+#define AXP806_DCDCAB_POLYPHASE_DUAL 0x40
+#define AXP806_DCDCABC_POLYPHASE_TRI 0x80
+#define AXP806_DCDCABC_POLYPHASE_MASK GENMASK(7, 6)
+
+#define AXP806_DCDCDE_POLYPHASE_DUAL BIT(5)
+
+#define AXP806_DCDCA_600mV_START 0x00
+#define AXP806_DCDCA_600mV_STEPS 50
+#define AXP806_DCDCA_600mV_END \
+ (AXP806_DCDCA_600mV_START + AXP806_DCDCA_600mV_STEPS)
+#define AXP806_DCDCA_1120mV_START 0x33
+#define AXP806_DCDCA_1120mV_STEPS 14
+#define AXP806_DCDCA_1120mV_END \
+ (AXP806_DCDCA_1120mV_START + AXP806_DCDCA_1120mV_STEPS)
+#define AXP806_DCDCA_NUM_VOLTAGES 72
+
+#define AXP806_DCDCD_600mV_START 0x00
+#define AXP806_DCDCD_600mV_STEPS 45
+#define AXP806_DCDCD_600mV_END \
+ (AXP806_DCDCD_600mV_START + AXP806_DCDCD_600mV_STEPS)
+#define AXP806_DCDCD_1600mV_START 0x2e
+#define AXP806_DCDCD_1600mV_STEPS 17
+#define AXP806_DCDCD_1600mV_END \
+ (AXP806_DCDCD_1600mV_START + AXP806_DCDCD_1600mV_STEPS)
+#define AXP806_DCDCD_NUM_VOLTAGES 64
+
+#define AXP809_DCDC4_600mV_START 0x00
+#define AXP809_DCDC4_600mV_STEPS 47
+#define AXP809_DCDC4_600mV_END \
+ (AXP809_DCDC4_600mV_START + AXP809_DCDC4_600mV_STEPS)
+#define AXP809_DCDC4_1800mV_START 0x30
+#define AXP809_DCDC4_1800mV_STEPS 8
+#define AXP809_DCDC4_1800mV_END \
+ (AXP809_DCDC4_1800mV_START + AXP809_DCDC4_1800mV_STEPS)
+#define AXP809_DCDC4_NUM_VOLTAGES 57
+
+#define AXP813_DCDC7_V_OUT_MASK GENMASK(6, 0)
+
+#define AXP813_PWR_OUT_DCDC7_MASK BIT_MASK(6)
+
#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask, _enable_val, _disable_val) \
[_family##_##_id] = { \
@@ -128,6 +359,134 @@
.ops = &axp20x_ops_range, \
}
+static const int axp209_dcdc2_ldo3_slew_rates[] = {
+ 1600,
+ 800,
+};
+
+static int axp20x_set_ramp_delay(struct regulator_dev *rdev, int ramp)
+{
+ struct axp20x_dev *axp20x = rdev_get_drvdata(rdev);
+ const struct regulator_desc *desc;
+ u8 reg, mask, enable, cfg = 0xff;
+ const int *slew_rates;
+ int rate_count = 0;
+
+ desc = rdev->desc;
+
+ switch (axp20x->variant) {
+ case AXP209_ID:
+ if (desc->id == AXP20X_DCDC2) {
+ slew_rates = axp209_dcdc2_ldo3_slew_rates;
+ rate_count = ARRAY_SIZE(axp209_dcdc2_ldo3_slew_rates);
+ reg = AXP20X_DCDC2_LDO3_V_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;
+ break;
+ }
+
+ if (desc->id == AXP20X_LDO3) {
+ slew_rates = axp209_dcdc2_ldo3_slew_rates;
+ rate_count = ARRAY_SIZE(axp209_dcdc2_ldo3_slew_rates);
+ reg = AXP20X_DCDC2_LDO3_V_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;
+ break;
+ }
+
+ if (rate_count > 0)
+ break;
+
+ /* fall through */
+ default:
+ /* Not supported for this regulator */
+ return -ENOTSUPP;
+ }
+
+ if (ramp == 0) {
+ cfg = enable;
+ } else {
+ int i;
+
+ for (i = 0; i < rate_count; i++) {
+ if (ramp <= slew_rates[i])
+ cfg = AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE(i);
+ else
+ break;
+ }
+
+ if (cfg == 0xff) {
+ dev_err(axp20x->dev, "unsupported ramp value %d", ramp);
+ return -EINVAL;
+ }
+
+ cfg |= enable;
+ }
+
+ return regmap_update_bits(axp20x->regmap, reg, mask, cfg);
+}
+
+static int axp20x_regulator_enable_regmap(struct regulator_dev *rdev)
+{
+ struct axp20x_dev *axp20x = rdev_get_drvdata(rdev);
+ const struct regulator_desc *desc;
+
+ if (!rdev)
+ return -EINVAL;
+
+ desc = rdev->desc;
+
+ switch (axp20x->variant) {
+ case AXP209_ID:
+ if ((desc->id == AXP20X_LDO3) &&
+ rdev->constraints && rdev->constraints->soft_start) {
+ int v_out;
+ int ret;
+
+ /*
+ * On some boards, the LDO3 can be overloaded when
+ * turning on, causing the entire PMIC to shutdown
+ * without warning. Turning it on at the minimal voltage
+ * and then setting the voltage to the requested value
+ * works reliably.
+ */
+ if (regulator_is_enabled_regmap(rdev))
+ break;
+
+ v_out = regulator_get_voltage_sel_regmap(rdev);
+ if (v_out < 0)
+ return v_out;
+
+ if (v_out == 0)
+ break;
+
+ ret = regulator_set_voltage_sel_regmap(rdev, 0x00);
+ /*
+ * A small pause is needed between
+ * setting the voltage and enabling the LDO to give the
+ * internal state machine time to process the request.
+ */
+ usleep_range(1000, 5000);
+ ret |= regulator_enable_regmap(rdev);
+ ret |= regulator_set_voltage_sel_regmap(rdev, v_out);
+
+ return ret;
+ }
+ break;
+ default:
+ /* No quirks */
+ break;
+ }
+
+ return regulator_enable_regmap(rdev);
+};
+
static const struct regulator_ops axp20x_ops_fixed = {
.list_voltage = regulator_list_voltage_linear,
};
@@ -145,9 +504,10 @@ static const struct regulator_ops axp20x_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
- .enable = regulator_enable_regmap,
+ .enable = axp20x_regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
+ .set_ramp_delay = axp20x_set_ramp_delay,
};
static const struct regulator_ops axp20x_ops_sw = {
@@ -157,77 +517,116 @@ static const struct regulator_ops axp20x_ops_sw = {
};
static const struct regulator_linear_range axp20x_ldo4_ranges[] = {
- REGULATOR_LINEAR_RANGE(1250000, 0x0, 0x0, 0),
- REGULATOR_LINEAR_RANGE(1300000, 0x1, 0x8, 100000),
- REGULATOR_LINEAR_RANGE(2500000, 0x9, 0x9, 0),
- REGULATOR_LINEAR_RANGE(2700000, 0xa, 0xb, 100000),
- REGULATOR_LINEAR_RANGE(3000000, 0xc, 0xf, 100000),
+ REGULATOR_LINEAR_RANGE(1250000,
+ AXP20X_LDO4_V_OUT_1250mV_START,
+ AXP20X_LDO4_V_OUT_1250mV_END,
+ 0),
+ REGULATOR_LINEAR_RANGE(1300000,
+ AXP20X_LDO4_V_OUT_1300mV_START,
+ AXP20X_LDO4_V_OUT_1300mV_END,
+ 100000),
+ REGULATOR_LINEAR_RANGE(2500000,
+ AXP20X_LDO4_V_OUT_2500mV_START,
+ AXP20X_LDO4_V_OUT_2500mV_END,
+ 0),
+ REGULATOR_LINEAR_RANGE(2700000,
+ AXP20X_LDO4_V_OUT_2700mV_START,
+ AXP20X_LDO4_V_OUT_2700mV_END,
+ 100000),
+ REGULATOR_LINEAR_RANGE(3000000,
+ AXP20X_LDO4_V_OUT_3000mV_START,
+ AXP20X_LDO4_V_OUT_3000mV_END,
+ 100000),
};
static const struct regulator_desc axp20x_regulators[] = {
AXP_DESC(AXP20X, DCDC2, "dcdc2", "vin2", 700, 2275, 25,
- AXP20X_DCDC2_V_OUT, 0x3f, AXP20X_PWR_OUT_CTRL, 0x10),
+ AXP20X_DCDC2_V_OUT, AXP20X_DCDC2_V_OUT_MASK,
+ AXP20X_PWR_OUT_CTRL, AXP20X_PWR_OUT_DCDC2_MASK),
AXP_DESC(AXP20X, DCDC3, "dcdc3", "vin3", 700, 3500, 25,
- AXP20X_DCDC3_V_OUT, 0x7f, AXP20X_PWR_OUT_CTRL, 0x02),
+ AXP20X_DCDC3_V_OUT, AXP20X_DCDC3_V_OUT_MASK,
+ AXP20X_PWR_OUT_CTRL, AXP20X_PWR_OUT_DCDC3_MASK),
AXP_DESC_FIXED(AXP20X, LDO1, "ldo1", "acin", 1300),
AXP_DESC(AXP20X, LDO2, "ldo2", "ldo24in", 1800, 3300, 100,
- AXP20X_LDO24_V_OUT, 0xf0, AXP20X_PWR_OUT_CTRL, 0x04),
+ AXP20X_LDO24_V_OUT, AXP20X_LDO24_V_OUT_MASK,
+ AXP20X_PWR_OUT_CTRL, AXP20X_PWR_OUT_LDO2_MASK),
AXP_DESC(AXP20X, LDO3, "ldo3", "ldo3in", 700, 3500, 25,
- AXP20X_LDO3_V_OUT, 0x7f, AXP20X_PWR_OUT_CTRL, 0x40),
- AXP_DESC_RANGES(AXP20X, LDO4, "ldo4", "ldo24in", axp20x_ldo4_ranges,
- 16, AXP20X_LDO24_V_OUT, 0x0f, AXP20X_PWR_OUT_CTRL,
- 0x08),
+ AXP20X_LDO3_V_OUT, AXP20X_LDO3_V_OUT_MASK,
+ AXP20X_PWR_OUT_CTRL, AXP20X_PWR_OUT_LDO3_MASK),
+ AXP_DESC_RANGES(AXP20X, LDO4, "ldo4", "ldo24in",
+ axp20x_ldo4_ranges, AXP20X_LDO4_V_OUT_NUM_VOLTAGES,
+ AXP20X_LDO24_V_OUT, AXP20X_LDO24_V_OUT_MASK,
+ AXP20X_PWR_OUT_CTRL, AXP20X_PWR_OUT_LDO4_MASK),
AXP_DESC_IO(AXP20X, LDO5, "ldo5", "ldo5in", 1800, 3300, 100,
- AXP20X_LDO5_V_OUT, 0xf0, AXP20X_GPIO0_CTRL, 0x07,
+ AXP20X_LDO5_V_OUT, AXP20X_LDO5_V_OUT_MASK,
+ AXP20X_GPIO0_CTRL, AXP20X_GPIO0_FUNC_MASK,
AXP20X_IO_ENABLED, AXP20X_IO_DISABLED),
};
static const struct regulator_desc axp22x_regulators[] = {
AXP_DESC(AXP22X, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
- AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(1)),
+ AXP22X_DCDC1_V_OUT, AXP22X_DCDC1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_DCDC1_MASK),
AXP_DESC(AXP22X, DCDC2, "dcdc2", "vin2", 600, 1540, 20,
- AXP22X_DCDC2_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(2)),
+ AXP22X_DCDC2_V_OUT, AXP22X_DCDC2_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_DCDC2_MASK),
AXP_DESC(AXP22X, DCDC3, "dcdc3", "vin3", 600, 1860, 20,
- AXP22X_DCDC3_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(3)),
+ AXP22X_DCDC3_V_OUT, AXP22X_DCDC3_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_DCDC3_MASK),
AXP_DESC(AXP22X, DCDC4, "dcdc4", "vin4", 600, 1540, 20,
- AXP22X_DCDC4_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(4)),
+ AXP22X_DCDC4_V_OUT, AXP22X_DCDC4_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_DCDC4_MASK),
AXP_DESC(AXP22X, DCDC5, "dcdc5", "vin5", 1000, 2550, 50,
- AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(5)),
+ AXP22X_DCDC5_V_OUT, AXP22X_DCDC5_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_DCDC5_MASK),
/* secondary switchable output of DCDC1 */
- AXP_DESC_SW(AXP22X, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
- BIT(7)),
+ AXP_DESC_SW(AXP22X, DC1SW, "dc1sw", NULL,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DC1SW_MASK),
/* LDO regulator internally chained to DCDC5 */
AXP_DESC(AXP22X, DC5LDO, "dc5ldo", NULL, 700, 1400, 100,
- AXP22X_DC5LDO_V_OUT, 0x7, AXP22X_PWR_OUT_CTRL1, BIT(0)),
+ AXP22X_DC5LDO_V_OUT, AXP22X_DC5LDO_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_DC5LDO_MASK),
AXP_DESC(AXP22X, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
- AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(6)),
+ AXP22X_ALDO1_V_OUT, AXP22X_ALDO1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_ALDO1_MASK),
AXP_DESC(AXP22X, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
- AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(7)),
+ AXP22X_ALDO2_V_OUT, AXP22X_ALDO2_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_ALDO2_MASK),
AXP_DESC(AXP22X, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
- AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(7)),
+ AXP22X_ALDO3_V_OUT, AXP22X_ALDO3_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL3, AXP22X_PWR_OUT_ALDO3_MASK),
AXP_DESC(AXP22X, DLDO1, "dldo1", "dldoin", 700, 3300, 100,
- AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(3)),
+ AXP22X_DLDO1_V_OUT, AXP22X_DLDO1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO1_MASK),
AXP_DESC(AXP22X, DLDO2, "dldo2", "dldoin", 700, 3300, 100,
- AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(4)),
+ AXP22X_DLDO2_V_OUT, AXP22X_PWR_OUT_DLDO2_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO2_MASK),
AXP_DESC(AXP22X, DLDO3, "dldo3", "dldoin", 700, 3300, 100,
- AXP22X_DLDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
+ AXP22X_DLDO3_V_OUT, AXP22X_DLDO3_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO3_MASK),
AXP_DESC(AXP22X, DLDO4, "dldo4", "dldoin", 700, 3300, 100,
- AXP22X_DLDO4_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(6)),
+ AXP22X_DLDO4_V_OUT, AXP22X_DLDO4_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO4_MASK),
AXP_DESC(AXP22X, ELDO1, "eldo1", "eldoin", 700, 3300, 100,
- AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
+ AXP22X_ELDO1_V_OUT, AXP22X_ELDO1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO1_MASK),
AXP_DESC(AXP22X, ELDO2, "eldo2", "eldoin", 700, 3300, 100,
- AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
+ AXP22X_ELDO2_V_OUT, AXP22X_ELDO2_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO1_MASK),
AXP_DESC(AXP22X, ELDO3, "eldo3", "eldoin", 700, 3300, 100,
- AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
+ AXP22X_ELDO3_V_OUT, AXP22X_ELDO3_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO3_MASK),
/* Note the datasheet only guarantees reliable operation up to
* 3.3V, this needs to be enforced via dts provided constraints */
AXP_DESC_IO(AXP22X, LDO_IO0, "ldo_io0", "ips", 700, 3800, 100,
- AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
+ AXP22X_LDO_IO0_V_OUT, AXP22X_LDO_IO0_V_OUT_MASK,
+ AXP20X_GPIO0_CTRL, AXP20X_GPIO0_FUNC_MASK,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
/* Note the datasheet only guarantees reliable operation up to
* 3.3V, this needs to be enforced via dts provided constraints */
AXP_DESC_IO(AXP22X, LDO_IO1, "ldo_io1", "ips", 700, 3800, 100,
- AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
+ AXP22X_LDO_IO1_V_OUT, AXP22X_LDO_IO1_V_OUT_MASK,
+ AXP20X_GPIO1_CTRL, AXP20X_GPIO1_FUNC_MASK,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000),
};
@@ -240,240 +639,354 @@ static const struct regulator_desc axp22x_drivevbus_regulator = {
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.enable_reg = AXP20X_VBUS_IPSOUT_MGMT,
- .enable_mask = BIT(2),
+ .enable_mask = AXP20X_VBUS_IPSOUT_MGMT_MASK,
.ops = &axp20x_ops_sw,
};
/* DCDC ranges shared with AXP813 */
static const struct regulator_linear_range axp803_dcdc234_ranges[] = {
- REGULATOR_LINEAR_RANGE(500000, 0x0, 0x46, 10000),
- REGULATOR_LINEAR_RANGE(1220000, 0x47, 0x4b, 20000),
+ REGULATOR_LINEAR_RANGE(500000,
+ AXP803_DCDC234_500mV_START,
+ AXP803_DCDC234_500mV_END,
+ 10000),
+ REGULATOR_LINEAR_RANGE(1220000,
+ AXP803_DCDC234_1220mV_START,
+ AXP803_DCDC234_1220mV_END,
+ 20000),
};
static const struct regulator_linear_range axp803_dcdc5_ranges[] = {
- REGULATOR_LINEAR_RANGE(800000, 0x0, 0x20, 10000),
- REGULATOR_LINEAR_RANGE(1140000, 0x21, 0x44, 20000),
+ REGULATOR_LINEAR_RANGE(800000,
+ AXP803_DCDC5_800mV_START,
+ AXP803_DCDC5_800mV_END,
+ 10000),
+ REGULATOR_LINEAR_RANGE(1140000,
+ AXP803_DCDC5_1140mV_START,
+ AXP803_DCDC5_1140mV_END,
+ 20000),
};
static const struct regulator_linear_range axp803_dcdc6_ranges[] = {
- REGULATOR_LINEAR_RANGE(600000, 0x0, 0x32, 10000),
- REGULATOR_LINEAR_RANGE(1120000, 0x33, 0x47, 20000),
+ REGULATOR_LINEAR_RANGE(600000,
+ AXP803_DCDC6_600mV_START,
+ AXP803_DCDC6_600mV_END,
+ 10000),
+ REGULATOR_LINEAR_RANGE(1120000,
+ AXP803_DCDC6_1120mV_START,
+ AXP803_DCDC6_1120mV_END,
+ 20000),
};
-/* AXP806's CLDO2 and AXP809's DLDO1 shares the same range */
+/* AXP806's CLDO2 and AXP809's DLDO1 share the same range */
static const struct regulator_linear_range axp803_dldo2_ranges[] = {
- REGULATOR_LINEAR_RANGE(700000, 0x0, 0x1a, 100000),
- REGULATOR_LINEAR_RANGE(3400000, 0x1b, 0x1f, 200000),
+ REGULATOR_LINEAR_RANGE(700000,
+ AXP803_DLDO2_700mV_START,
+ AXP803_DLDO2_700mV_END,
+ 100000),
+ REGULATOR_LINEAR_RANGE(3400000,
+ AXP803_DLDO2_3400mV_START,
+ AXP803_DLDO2_3400mV_END,
+ 200000),
};
static const struct regulator_desc axp803_regulators[] = {
AXP_DESC(AXP803, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
- AXP803_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(0)),
- AXP_DESC_RANGES(AXP803, DCDC2, "dcdc2", "vin2", axp803_dcdc234_ranges,
- 76, AXP803_DCDC2_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
- BIT(1)),
- AXP_DESC_RANGES(AXP803, DCDC3, "dcdc3", "vin3", axp803_dcdc234_ranges,
- 76, AXP803_DCDC3_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
- BIT(2)),
- AXP_DESC_RANGES(AXP803, DCDC4, "dcdc4", "vin4", axp803_dcdc234_ranges,
- 76, AXP803_DCDC4_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
- BIT(3)),
- AXP_DESC_RANGES(AXP803, DCDC5, "dcdc5", "vin5", axp803_dcdc5_ranges,
- 68, AXP803_DCDC5_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
- BIT(4)),
- AXP_DESC_RANGES(AXP803, DCDC6, "dcdc6", "vin6", axp803_dcdc6_ranges,
- 72, AXP803_DCDC6_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
- BIT(5)),
+ AXP803_DCDC1_V_OUT, AXP803_DCDC1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP803_PWR_OUT_DCDC1_MASK),
+ AXP_DESC_RANGES(AXP803, DCDC2, "dcdc2", "vin2",
+ axp803_dcdc234_ranges, AXP803_DCDC234_NUM_VOLTAGES,
+ AXP803_DCDC2_V_OUT, AXP803_DCDC2_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP803_PWR_OUT_DCDC2_MASK),
+ AXP_DESC_RANGES(AXP803, DCDC3, "dcdc3", "vin3",
+ axp803_dcdc234_ranges, AXP803_DCDC234_NUM_VOLTAGES,
+ AXP803_DCDC3_V_OUT, AXP803_DCDC3_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP803_PWR_OUT_DCDC3_MASK),
+ AXP_DESC_RANGES(AXP803, DCDC4, "dcdc4", "vin4",
+ axp803_dcdc234_ranges, AXP803_DCDC234_NUM_VOLTAGES,
+ AXP803_DCDC4_V_OUT, AXP803_DCDC4_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP803_PWR_OUT_DCDC4_MASK),
+ AXP_DESC_RANGES(AXP803, DCDC5, "dcdc5", "vin5",
+ axp803_dcdc5_ranges, AXP803_DCDC5_NUM_VOLTAGES,
+ AXP803_DCDC5_V_OUT, AXP803_DCDC5_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP803_PWR_OUT_DCDC5_MASK),
+ AXP_DESC_RANGES(AXP803, DCDC6, "dcdc6", "vin6",
+ axp803_dcdc6_ranges, AXP803_DCDC6_NUM_VOLTAGES,
+ AXP803_DCDC6_V_OUT, AXP803_DCDC6_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP803_PWR_OUT_DCDC6_MASK),
/* secondary switchable output of DCDC1 */
- AXP_DESC_SW(AXP803, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
- BIT(7)),
+ AXP_DESC_SW(AXP803, DC1SW, "dc1sw", NULL,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DC1SW_MASK),
AXP_DESC(AXP803, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
- AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(5)),
+ AXP22X_ALDO1_V_OUT, AXP22X_ALDO1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL3, AXP806_PWR_OUT_ALDO1_MASK),
AXP_DESC(AXP803, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
- AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(6)),
+ AXP22X_ALDO2_V_OUT, AXP22X_ALDO2_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL3, AXP806_PWR_OUT_ALDO2_MASK),
AXP_DESC(AXP803, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
- AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(7)),
+ AXP22X_ALDO3_V_OUT, AXP22X_ALDO3_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL3, AXP806_PWR_OUT_ALDO3_MASK),
AXP_DESC(AXP803, DLDO1, "dldo1", "dldoin", 700, 3300, 100,
- AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(3)),
- AXP_DESC_RANGES(AXP803, DLDO2, "dldo2", "dldoin", axp803_dldo2_ranges,
- 32, AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
- BIT(4)),
+ AXP22X_DLDO1_V_OUT, AXP22X_DLDO1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO1_MASK),
+ AXP_DESC_RANGES(AXP803, DLDO2, "dldo2", "dldoin",
+ axp803_dldo2_ranges, AXP803_DLDO2_NUM_VOLTAGES,
+ AXP22X_DLDO2_V_OUT, AXP22X_DLDO2_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO2_MASK),
AXP_DESC(AXP803, DLDO3, "dldo3", "dldoin", 700, 3300, 100,
- AXP22X_DLDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
+ AXP22X_DLDO3_V_OUT, AXP22X_DLDO3_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO3_MASK),
AXP_DESC(AXP803, DLDO4, "dldo4", "dldoin", 700, 3300, 100,
- AXP22X_DLDO4_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(6)),
+ AXP22X_DLDO4_V_OUT, AXP22X_DLDO4_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO4_MASK),
AXP_DESC(AXP803, ELDO1, "eldo1", "eldoin", 700, 1900, 50,
- AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
+ AXP22X_ELDO1_V_OUT, AXP22X_ELDO1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO1_MASK),
AXP_DESC(AXP803, ELDO2, "eldo2", "eldoin", 700, 1900, 50,
- AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
+ AXP22X_ELDO2_V_OUT, AXP22X_ELDO2_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO2_MASK),
AXP_DESC(AXP803, ELDO3, "eldo3", "eldoin", 700, 1900, 50,
- AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
+ AXP22X_ELDO3_V_OUT, AXP22X_ELDO3_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO3_MASK),
AXP_DESC(AXP803, FLDO1, "fldo1", "fldoin", 700, 1450, 50,
- AXP803_FLDO1_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(2)),
+ AXP803_FLDO1_V_OUT, AXP803_FLDO1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL3, AXP803_PWR_OUT_FLDO1_MASK),
AXP_DESC(AXP803, FLDO2, "fldo2", "fldoin", 700, 1450, 50,
- AXP803_FLDO2_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(3)),
+ AXP803_FLDO2_V_OUT, AXP803_FLDO2_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL3, AXP803_PWR_OUT_FLDO2_MASK),
AXP_DESC_IO(AXP803, LDO_IO0, "ldo-io0", "ips", 700, 3300, 100,
- AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
+ AXP22X_LDO_IO0_V_OUT, AXP22X_LDO_IO0_V_OUT_MASK,
+ AXP20X_GPIO0_CTRL, AXP20X_GPIO0_FUNC_MASK,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
AXP_DESC_IO(AXP803, LDO_IO1, "ldo-io1", "ips", 700, 3300, 100,
- AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
+ AXP22X_LDO_IO1_V_OUT, AXP22X_LDO_IO1_V_OUT_MASK,
+ AXP20X_GPIO1_CTRL, AXP20X_GPIO1_FUNC_MASK,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
AXP_DESC_FIXED(AXP803, RTC_LDO, "rtc-ldo", "ips", 3000),
};
static const struct regulator_linear_range axp806_dcdca_ranges[] = {
- REGULATOR_LINEAR_RANGE(600000, 0x0, 0x32, 10000),
- REGULATOR_LINEAR_RANGE(1120000, 0x33, 0x47, 20000),
+ REGULATOR_LINEAR_RANGE(600000,
+ AXP806_DCDCA_600mV_START,
+ AXP806_DCDCA_600mV_END,
+ 10000),
+ REGULATOR_LINEAR_RANGE(1120000,
+ AXP806_DCDCA_1120mV_START,
+ AXP806_DCDCA_1120mV_END,
+ 20000),
};
static const struct regulator_linear_range axp806_dcdcd_ranges[] = {
- REGULATOR_LINEAR_RANGE(600000, 0x0, 0x2d, 20000),
- REGULATOR_LINEAR_RANGE(1600000, 0x2e, 0x3f, 100000),
+ REGULATOR_LINEAR_RANGE(600000,
+ AXP806_DCDCD_600mV_START,
+ AXP806_DCDCD_600mV_END,
+ 20000),
+ REGULATOR_LINEAR_RANGE(1600000,
+ AXP806_DCDCD_600mV_START,
+ AXP806_DCDCD_600mV_END,
+ 100000),
};
static const struct regulator_desc axp806_regulators[] = {
- AXP_DESC_RANGES(AXP806, DCDCA, "dcdca", "vina", axp806_dcdca_ranges,
- 72, AXP806_DCDCA_V_CTRL, 0x7f, AXP806_PWR_OUT_CTRL1,
- BIT(0)),
+ AXP_DESC_RANGES(AXP806, DCDCA, "dcdca", "vina",
+ axp806_dcdca_ranges, AXP806_DCDCA_NUM_VOLTAGES,
+ AXP806_DCDCA_V_CTRL, AXP806_DCDCA_V_CTRL_MASK,
+ AXP806_PWR_OUT_CTRL1, AXP806_PWR_OUT_DCDCA_MASK),
AXP_DESC(AXP806, DCDCB, "dcdcb", "vinb", 1000, 2550, 50,
- AXP806_DCDCB_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(1)),
- AXP_DESC_RANGES(AXP806, DCDCC, "dcdcc", "vinc", axp806_dcdca_ranges,
- 72, AXP806_DCDCC_V_CTRL, 0x7f, AXP806_PWR_OUT_CTRL1,
- BIT(2)),
- AXP_DESC_RANGES(AXP806, DCDCD, "dcdcd", "vind", axp806_dcdcd_ranges,
- 64, AXP806_DCDCD_V_CTRL, 0x3f, AXP806_PWR_OUT_CTRL1,
- BIT(3)),
+ AXP806_DCDCB_V_CTRL, AXP806_DCDCB_V_CTRL_MASK,
+ AXP806_PWR_OUT_CTRL1, AXP806_PWR_OUT_DCDCB_MASK),
+ AXP_DESC_RANGES(AXP806, DCDCC, "dcdcc", "vinc",
+ axp806_dcdca_ranges, AXP806_DCDCA_NUM_VOLTAGES,
+ AXP806_DCDCC_V_CTRL, AXP806_DCDCC_V_CTRL_MASK,
+ AXP806_PWR_OUT_CTRL1, AXP806_PWR_OUT_DCDCC_MASK),
+ AXP_DESC_RANGES(AXP806, DCDCD, "dcdcd", "vind",
+ axp806_dcdcd_ranges, AXP806_DCDCD_NUM_VOLTAGES,
+ AXP806_DCDCD_V_CTRL, AXP806_DCDCD_V_CTRL_MASK,
+ AXP806_PWR_OUT_CTRL1, AXP806_PWR_OUT_DCDCD_MASK),
AXP_DESC(AXP806, DCDCE, "dcdce", "vine", 1100, 3400, 100,
- AXP806_DCDCE_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(4)),
+ AXP806_DCDCE_V_CTRL, AXP806_DCDCE_V_CTRL_MASK,
+ AXP806_PWR_OUT_CTRL1, AXP806_PWR_OUT_DCDCE_MASK),
AXP_DESC(AXP806, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
- AXP806_ALDO1_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(5)),
+ AXP806_ALDO1_V_CTRL, AXP806_ALDO1_V_CTRL_MASK,
+ AXP806_PWR_OUT_CTRL1, AXP806_PWR_OUT_ALDO1_MASK),
AXP_DESC(AXP806, ALDO2, "aldo2", "aldoin", 700, 3400, 100,
- AXP806_ALDO2_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(6)),
+ AXP806_ALDO2_V_CTRL, AXP806_ALDO2_V_CTRL_MASK,
+ AXP806_PWR_OUT_CTRL1, AXP806_PWR_OUT_ALDO2_MASK),
AXP_DESC(AXP806, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
- AXP806_ALDO3_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(7)),
+ AXP806_ALDO3_V_CTRL, AXP806_ALDO3_V_CTRL_MASK,
+ AXP806_PWR_OUT_CTRL1, AXP806_PWR_OUT_ALDO3_MASK),
AXP_DESC(AXP806, BLDO1, "bldo1", "bldoin", 700, 1900, 100,
- AXP806_BLDO1_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(0)),
+ AXP806_BLDO1_V_CTRL, AXP806_BLDO1_V_CTRL_MASK,
+ AXP806_PWR_OUT_CTRL2, AXP806_PWR_OUT_BLDO1_MASK),
AXP_DESC(AXP806, BLDO2, "bldo2", "bldoin", 700, 1900, 100,
- AXP806_BLDO2_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(1)),
+ AXP806_BLDO2_V_CTRL, AXP806_BLDO2_V_CTRL_MASK,
+ AXP806_PWR_OUT_CTRL2, AXP806_PWR_OUT_BLDO2_MASK),
AXP_DESC(AXP806, BLDO3, "bldo3", "bldoin", 700, 1900, 100,
- AXP806_BLDO3_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(2)),
+ AXP806_BLDO3_V_CTRL, AXP806_BLDO3_V_CTRL_MASK,
+ AXP806_PWR_OUT_CTRL2, AXP806_PWR_OUT_BLDO3_MASK),
AXP_DESC(AXP806, BLDO4, "bldo4", "bldoin", 700, 1900, 100,
- AXP806_BLDO4_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(3)),
+ AXP806_BLDO4_V_CTRL, AXP806_BLDO4_V_CTRL_MASK,
+ AXP806_PWR_OUT_CTRL2, AXP806_PWR_OUT_BLDO4_MASK),
AXP_DESC(AXP806, CLDO1, "cldo1", "cldoin", 700, 3300, 100,
- AXP806_CLDO1_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2, BIT(4)),
- AXP_DESC_RANGES(AXP806, CLDO2, "cldo2", "cldoin", axp803_dldo2_ranges,
- 32, AXP806_CLDO2_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2,
- BIT(5)),
+ AXP806_CLDO1_V_CTRL, AXP806_CLDO1_V_CTRL_MASK,
+ AXP806_PWR_OUT_CTRL2, AXP806_PWR_OUT_CLDO1_MASK),
+ AXP_DESC_RANGES(AXP806, CLDO2, "cldo2", "cldoin",
+ axp803_dldo2_ranges, AXP803_DLDO2_NUM_VOLTAGES,
+ AXP806_CLDO2_V_CTRL, AXP806_CLDO2_V_CTRL_MASK,
+ AXP806_PWR_OUT_CTRL2, AXP806_PWR_OUT_CLDO2_MASK),
AXP_DESC(AXP806, CLDO3, "cldo3", "cldoin", 700, 3300, 100,
- AXP806_CLDO3_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2, BIT(6)),
- AXP_DESC_SW(AXP806, SW, "sw", "swin", AXP806_PWR_OUT_CTRL2, BIT(7)),
+ AXP806_CLDO3_V_CTRL, AXP806_CLDO3_V_CTRL_MASK,
+ AXP806_PWR_OUT_CTRL2, AXP806_PWR_OUT_CLDO3_MASK),
+ AXP_DESC_SW(AXP806, SW, "sw", "swin",
+ AXP806_PWR_OUT_CTRL2, AXP806_PWR_OUT_SW_MASK),
};
static const struct regulator_linear_range axp809_dcdc4_ranges[] = {
- REGULATOR_LINEAR_RANGE(600000, 0x0, 0x2f, 20000),
- REGULATOR_LINEAR_RANGE(1800000, 0x30, 0x38, 100000),
+ REGULATOR_LINEAR_RANGE(600000,
+ AXP809_DCDC4_600mV_START,
+ AXP809_DCDC4_600mV_END,
+ 20000),
+ REGULATOR_LINEAR_RANGE(1800000,
+ AXP809_DCDC4_1800mV_START,
+ AXP809_DCDC4_1800mV_END,
+ 100000),
};
static const struct regulator_desc axp809_regulators[] = {
AXP_DESC(AXP809, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
- AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(1)),
+ AXP22X_DCDC1_V_OUT, AXP22X_DCDC1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_DCDC1_MASK),
AXP_DESC(AXP809, DCDC2, "dcdc2", "vin2", 600, 1540, 20,
- AXP22X_DCDC2_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(2)),
+ AXP22X_DCDC2_V_OUT, AXP22X_DCDC2_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_DCDC2_MASK),
AXP_DESC(AXP809, DCDC3, "dcdc3", "vin3", 600, 1860, 20,
- AXP22X_DCDC3_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(3)),
- AXP_DESC_RANGES(AXP809, DCDC4, "dcdc4", "vin4", axp809_dcdc4_ranges,
- 57, AXP22X_DCDC4_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1,
- BIT(4)),
+ AXP22X_DCDC3_V_OUT, AXP22X_DCDC3_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_DCDC3_MASK),
+ AXP_DESC_RANGES(AXP809, DCDC4, "dcdc4", "vin4",
+ axp809_dcdc4_ranges, AXP809_DCDC4_NUM_VOLTAGES,
+ AXP22X_DCDC4_V_OUT, AXP22X_DCDC4_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_DCDC4_MASK),
AXP_DESC(AXP809, DCDC5, "dcdc5", "vin5", 1000, 2550, 50,
- AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(5)),
+ AXP22X_DCDC5_V_OUT, AXP22X_DCDC5_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_DCDC5_MASK),
/* secondary switchable output of DCDC1 */
- AXP_DESC_SW(AXP809, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
- BIT(7)),
+ AXP_DESC_SW(AXP809, DC1SW, "dc1sw", NULL,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DC1SW_MASK),
/* LDO regulator internally chained to DCDC5 */
AXP_DESC(AXP809, DC5LDO, "dc5ldo", NULL, 700, 1400, 100,
- AXP22X_DC5LDO_V_OUT, 0x7, AXP22X_PWR_OUT_CTRL1, BIT(0)),
+ AXP22X_DC5LDO_V_OUT, AXP22X_DC5LDO_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_DC5LDO_MASK),
AXP_DESC(AXP809, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
- AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(6)),
+ AXP22X_ALDO1_V_OUT, AXP22X_ALDO1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_ALDO1_MASK),
AXP_DESC(AXP809, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
- AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(7)),
+ AXP22X_ALDO2_V_OUT, AXP22X_ALDO2_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP22X_PWR_OUT_ALDO2_MASK),
AXP_DESC(AXP809, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
- AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
- AXP_DESC_RANGES(AXP809, DLDO1, "dldo1", "dldoin", axp803_dldo2_ranges,
- 32, AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
- BIT(3)),
+ AXP22X_ALDO3_V_OUT, AXP22X_ALDO3_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ALDO3_MASK),
+ AXP_DESC_RANGES(AXP809, DLDO1, "dldo1", "dldoin",
+ axp803_dldo2_ranges, AXP803_DLDO2_NUM_VOLTAGES,
+ AXP22X_DLDO1_V_OUT, AXP22X_DLDO1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO1_MASK),
AXP_DESC(AXP809, DLDO2, "dldo2", "dldoin", 700, 3300, 100,
- AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(4)),
+ AXP22X_DLDO2_V_OUT, AXP22X_DLDO2_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO2_MASK),
AXP_DESC(AXP809, ELDO1, "eldo1", "eldoin", 700, 3300, 100,
- AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
+ AXP22X_ELDO1_V_OUT, AXP22X_ELDO1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO1_MASK),
AXP_DESC(AXP809, ELDO2, "eldo2", "eldoin", 700, 3300, 100,
- AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
+ AXP22X_ELDO2_V_OUT, AXP22X_ELDO2_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO2_MASK),
AXP_DESC(AXP809, ELDO3, "eldo3", "eldoin", 700, 3300, 100,
- AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
+ AXP22X_ELDO3_V_OUT, AXP22X_ELDO3_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO3_MASK),
/*
* Note the datasheet only guarantees reliable operation up to
* 3.3V, this needs to be enforced via dts provided constraints
*/
AXP_DESC_IO(AXP809, LDO_IO0, "ldo_io0", "ips", 700, 3800, 100,
- AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
+ AXP22X_LDO_IO0_V_OUT, AXP22X_LDO_IO0_V_OUT_MASK,
+ AXP20X_GPIO0_CTRL, AXP20X_GPIO0_FUNC_MASK,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
/*
* Note the datasheet only guarantees reliable operation up to
* 3.3V, this needs to be enforced via dts provided constraints
*/
AXP_DESC_IO(AXP809, LDO_IO1, "ldo_io1", "ips", 700, 3800, 100,
- AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
+ AXP22X_LDO_IO1_V_OUT, AXP22X_LDO_IO1_V_OUT_MASK,
+ AXP20X_GPIO1_CTRL, AXP20X_GPIO1_FUNC_MASK,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
AXP_DESC_FIXED(AXP809, RTC_LDO, "rtc_ldo", "ips", 1800),
- AXP_DESC_SW(AXP809, SW, "sw", "swin", AXP22X_PWR_OUT_CTRL2, BIT(6)),
+ AXP_DESC_SW(AXP809, SW, "sw", "swin",
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_SW_MASK),
};
static const struct regulator_desc axp813_regulators[] = {
AXP_DESC(AXP813, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
- AXP803_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(0)),
- AXP_DESC_RANGES(AXP813, DCDC2, "dcdc2", "vin2", axp803_dcdc234_ranges,
- 76, AXP803_DCDC2_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
- BIT(1)),
- AXP_DESC_RANGES(AXP813, DCDC3, "dcdc3", "vin3", axp803_dcdc234_ranges,
- 76, AXP803_DCDC3_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
- BIT(2)),
- AXP_DESC_RANGES(AXP813, DCDC4, "dcdc4", "vin4", axp803_dcdc234_ranges,
- 76, AXP803_DCDC4_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
- BIT(3)),
- AXP_DESC_RANGES(AXP813, DCDC5, "dcdc5", "vin5", axp803_dcdc5_ranges,
- 68, AXP803_DCDC5_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
- BIT(4)),
- AXP_DESC_RANGES(AXP813, DCDC6, "dcdc6", "vin6", axp803_dcdc6_ranges,
- 72, AXP803_DCDC6_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
- BIT(5)),
- AXP_DESC_RANGES(AXP813, DCDC7, "dcdc7", "vin7", axp803_dcdc6_ranges,
- 72, AXP813_DCDC7_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
- BIT(6)),
+ AXP803_DCDC1_V_OUT, AXP803_DCDC1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP803_PWR_OUT_DCDC1_MASK),
+ AXP_DESC_RANGES(AXP813, DCDC2, "dcdc2", "vin2",
+ axp803_dcdc234_ranges, AXP803_DCDC234_NUM_VOLTAGES,
+ AXP803_DCDC2_V_OUT, AXP803_DCDC2_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP803_PWR_OUT_DCDC2_MASK),
+ AXP_DESC_RANGES(AXP813, DCDC3, "dcdc3", "vin3",
+ axp803_dcdc234_ranges, AXP803_DCDC234_NUM_VOLTAGES,
+ AXP803_DCDC3_V_OUT, AXP803_DCDC3_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP803_PWR_OUT_DCDC3_MASK),
+ AXP_DESC_RANGES(AXP813, DCDC4, "dcdc4", "vin4",
+ axp803_dcdc234_ranges, AXP803_DCDC234_NUM_VOLTAGES,
+ AXP803_DCDC4_V_OUT, AXP803_DCDC4_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP803_PWR_OUT_DCDC4_MASK),
+ AXP_DESC_RANGES(AXP813, DCDC5, "dcdc5", "vin5",
+ axp803_dcdc5_ranges, AXP803_DCDC5_NUM_VOLTAGES,
+ AXP803_DCDC5_V_OUT, AXP803_DCDC5_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP803_PWR_OUT_DCDC5_MASK),
+ AXP_DESC_RANGES(AXP813, DCDC6, "dcdc6", "vin6",
+ axp803_dcdc6_ranges, AXP803_DCDC6_NUM_VOLTAGES,
+ AXP803_DCDC6_V_OUT, AXP803_DCDC6_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP803_PWR_OUT_DCDC6_MASK),
+ AXP_DESC_RANGES(AXP813, DCDC7, "dcdc7", "vin7",
+ axp803_dcdc6_ranges, AXP803_DCDC6_NUM_VOLTAGES,
+ AXP813_DCDC7_V_OUT, AXP813_DCDC7_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL1, AXP813_PWR_OUT_DCDC7_MASK),
AXP_DESC(AXP813, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
- AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(5)),
+ AXP22X_ALDO1_V_OUT, AXP22X_ALDO1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL3, AXP806_PWR_OUT_ALDO1_MASK),
AXP_DESC(AXP813, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
- AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(6)),
+ AXP22X_ALDO2_V_OUT, AXP22X_ALDO2_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL3, AXP806_PWR_OUT_ALDO2_MASK),
AXP_DESC(AXP813, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
- AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(7)),
+ AXP22X_ALDO3_V_OUT, AXP22X_ALDO3_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL3, AXP806_PWR_OUT_ALDO3_MASK),
AXP_DESC(AXP813, DLDO1, "dldo1", "dldoin", 700, 3300, 100,
- AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(3)),
- AXP_DESC_RANGES(AXP813, DLDO2, "dldo2", "dldoin", axp803_dldo2_ranges,
- 32, AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
- BIT(4)),
+ AXP22X_DLDO1_V_OUT, AXP22X_DLDO1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO1_MASK),
+ AXP_DESC_RANGES(AXP813, DLDO2, "dldo2", "dldoin",
+ axp803_dldo2_ranges, AXP803_DLDO2_NUM_VOLTAGES,
+ AXP22X_DLDO2_V_OUT, AXP22X_DLDO2_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO2_MASK),
AXP_DESC(AXP813, DLDO3, "dldo3", "dldoin", 700, 3300, 100,
- AXP22X_DLDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
+ AXP22X_DLDO3_V_OUT, AXP22X_DLDO3_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO3_MASK),
AXP_DESC(AXP813, DLDO4, "dldo4", "dldoin", 700, 3300, 100,
- AXP22X_DLDO4_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(6)),
+ AXP22X_DLDO4_V_OUT, AXP22X_DLDO4_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO4_MASK),
AXP_DESC(AXP813, ELDO1, "eldo1", "eldoin", 700, 1900, 50,
- AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
+ AXP22X_ELDO1_V_OUT, AXP22X_ELDO1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO1_MASK),
AXP_DESC(AXP813, ELDO2, "eldo2", "eldoin", 700, 1900, 50,
- AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
+ AXP22X_ELDO2_V_OUT, AXP22X_ELDO2_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO2_MASK),
AXP_DESC(AXP813, ELDO3, "eldo3", "eldoin", 700, 1900, 50,
- AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
+ AXP22X_ELDO3_V_OUT, AXP22X_ELDO3_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO3_MASK),
/* to do / check ... */
AXP_DESC(AXP813, FLDO1, "fldo1", "fldoin", 700, 1450, 50,
- AXP803_FLDO1_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(2)),
+ AXP803_FLDO1_V_OUT, AXP803_FLDO1_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL3, AXP803_PWR_OUT_FLDO1_MASK),
AXP_DESC(AXP813, FLDO2, "fldo2", "fldoin", 700, 1450, 50,
- AXP803_FLDO2_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(3)),
+ AXP803_FLDO2_V_OUT, AXP803_FLDO2_V_OUT_MASK,
+ AXP22X_PWR_OUT_CTRL3, AXP803_PWR_OUT_FLDO2_MASK),
/*
* TODO: FLDO3 = {DCDC5, FLDOIN} / 2
*
@@ -482,12 +995,15 @@ static const struct regulator_desc axp813_regulators[] = {
*/
AXP_DESC_FIXED(AXP813, RTC_LDO, "rtc-ldo", "ips", 1800),
AXP_DESC_IO(AXP813, LDO_IO0, "ldo-io0", "ips", 700, 3300, 100,
- AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
+ AXP22X_LDO_IO0_V_OUT, AXP22X_LDO_IO0_V_OUT_MASK,
+ AXP20X_GPIO0_CTRL, AXP20X_GPIO0_FUNC_MASK,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
AXP_DESC_IO(AXP813, LDO_IO1, "ldo-io1", "ips", 700, 3300, 100,
- AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
+ AXP22X_LDO_IO1_V_OUT, AXP22X_LDO_IO1_V_OUT_MASK,
+ AXP20X_GPIO1_CTRL, AXP20X_GPIO1_FUNC_MASK,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
- AXP_DESC_SW(AXP813, SW, "sw", "swin", AXP22X_PWR_OUT_CTRL2, BIT(7)),
+ AXP_DESC_SW(AXP813, SW, "sw", "swin",
+ AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DC1SW_MASK),
};
static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
@@ -663,9 +1179,9 @@ static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id)
switch (id) {
case AXP803_DCDC3:
- return !!(reg & BIT(6));
+ return !!(reg & AXP803_DCDC23_POLYPHASE_DUAL);
case AXP803_DCDC6:
- return !!(reg & BIT(5));
+ return !!(reg & AXP803_DCDC56_POLYPHASE_DUAL);
}
break;
@@ -674,12 +1190,15 @@ static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id)
switch (id) {
case AXP806_DCDCB:
- return (((reg & GENMASK(7, 6)) == BIT(6)) ||
- ((reg & GENMASK(7, 6)) == BIT(7)));
+ return (((reg & AXP806_DCDCABC_POLYPHASE_MASK) ==
+ AXP806_DCDCAB_POLYPHASE_DUAL) ||
+ ((reg & AXP806_DCDCABC_POLYPHASE_MASK) ==
+ AXP806_DCDCABC_POLYPHASE_TRI));
case AXP806_DCDCC:
- return ((reg & GENMASK(7, 6)) == BIT(7));
+ return ((reg & AXP806_DCDCABC_POLYPHASE_MASK) ==
+ AXP806_DCDCABC_POLYPHASE_TRI);
case AXP806_DCDCE:
- return !!(reg & BIT(5));
+ return !!(reg & AXP806_DCDCDE_POLYPHASE_DUAL);
}
break;
diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c
index 92d6d7b10cf7..e49c0a7d5dd5 100644
--- a/drivers/regulator/bcm590xx-regulator.c
+++ b/drivers/regulator/bcm590xx-regulator.c
@@ -242,8 +242,12 @@ static int bcm590xx_get_enable_register(int id)
case BCM590XX_REG_SDSR2:
reg = BCM590XX_SDSR2PMCTRL1;
break;
+ case BCM590XX_REG_VSR:
+ reg = BCM590XX_VSRPMCTRL1;
+ break;
case BCM590XX_REG_VBUS:
reg = BCM590XX_OTG_CTRL;
+ break;
}
diff --git a/drivers/regulator/bd70528-regulator.c b/drivers/regulator/bd70528-regulator.c
new file mode 100644
index 000000000000..30e3ed430a8a
--- /dev/null
+++ b/drivers/regulator/bd70528-regulator.c
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 ROHM Semiconductors
+// bd70528-regulator.c ROHM BD70528MWV regulator driver
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/rohm-bd70528.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/slab.h>
+
+#define BUCK_RAMPRATE_250MV 0
+#define BUCK_RAMPRATE_125MV 1
+#define BUCK_RAMP_MAX 250
+
+static const struct regulator_linear_range bd70528_buck1_volts[] = {
+ REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 600000),
+ REGULATOR_LINEAR_RANGE(2750000, 0x2, 0xf, 50000),
+};
+static const struct regulator_linear_range bd70528_buck2_volts[] = {
+ REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 300000),
+ REGULATOR_LINEAR_RANGE(1550000, 0x2, 0xd, 50000),
+ REGULATOR_LINEAR_RANGE(3000000, 0xe, 0xf, 300000),
+};
+static const struct regulator_linear_range bd70528_buck3_volts[] = {
+ REGULATOR_LINEAR_RANGE(800000, 0x00, 0xd, 50000),
+ REGULATOR_LINEAR_RANGE(1800000, 0xe, 0xf, 0),
+};
+
+/* All LDOs have same voltage ranges */
+static const struct regulator_linear_range bd70528_ldo_volts[] = {
+ REGULATOR_LINEAR_RANGE(1650000, 0x0, 0x07, 50000),
+ REGULATOR_LINEAR_RANGE(2100000, 0x8, 0x0f, 100000),
+ REGULATOR_LINEAR_RANGE(2850000, 0x10, 0x19, 50000),
+ REGULATOR_LINEAR_RANGE(3300000, 0x19, 0x1f, 0),
+};
+
+/* Also both LEDs support same voltages */
+static const unsigned int led_volts[] = {
+ 20000, 30000
+};
+
+static int bd70528_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+ if (ramp_delay > 0 && ramp_delay <= BUCK_RAMP_MAX) {
+ unsigned int ramp_value = BUCK_RAMPRATE_250MV;
+
+ if (ramp_delay <= 125)
+ ramp_value = BUCK_RAMPRATE_125MV;
+
+ return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
+ BD70528_MASK_BUCK_RAMP,
+ ramp_value << BD70528_SIFT_BUCK_RAMP);
+ }
+ dev_err(&rdev->dev, "%s: ramp_delay: %d not supported\n",
+ rdev->desc->name, ramp_delay);
+ return -EINVAL;
+}
+
+static int bd70528_led_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int sel)
+{
+ int ret;
+
+ ret = regulator_is_enabled_regmap(rdev);
+ if (ret < 0)
+ return ret;
+
+ if (ret == 0)
+ return regulator_set_voltage_sel_regmap(rdev, sel);
+
+ dev_err(&rdev->dev,
+ "LED voltage change not allowed when led is enabled\n");
+
+ return -EBUSY;
+}
+
+static const struct regulator_ops bd70528_buck_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .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,
+ .set_ramp_delay = bd70528_set_ramp_delay,
+};
+
+static const struct regulator_ops bd70528_ldo_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .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,
+ .set_ramp_delay = bd70528_set_ramp_delay,
+};
+
+static const struct regulator_ops bd70528_led_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_table,
+ .set_voltage_sel = bd70528_led_set_voltage_sel,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
+static const struct regulator_desc bd70528_desc[] = {
+ {
+ .name = "buck1",
+ .of_match = of_match_ptr("BUCK1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD70528_BUCK1,
+ .ops = &bd70528_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd70528_buck1_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd70528_buck1_volts),
+ .n_voltages = BD70528_BUCK_VOLTS,
+ .enable_reg = BD70528_REG_BUCK1_EN,
+ .enable_mask = BD70528_MASK_RUN_EN,
+ .vsel_reg = BD70528_REG_BUCK1_VOLT,
+ .vsel_mask = BD70528_MASK_BUCK_VOLT,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "buck2",
+ .of_match = of_match_ptr("BUCK2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD70528_BUCK2,
+ .ops = &bd70528_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd70528_buck2_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd70528_buck2_volts),
+ .n_voltages = BD70528_BUCK_VOLTS,
+ .enable_reg = BD70528_REG_BUCK2_EN,
+ .enable_mask = BD70528_MASK_RUN_EN,
+ .vsel_reg = BD70528_REG_BUCK2_VOLT,
+ .vsel_mask = BD70528_MASK_BUCK_VOLT,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "buck3",
+ .of_match = of_match_ptr("BUCK3"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD70528_BUCK3,
+ .ops = &bd70528_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd70528_buck3_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd70528_buck3_volts),
+ .n_voltages = BD70528_BUCK_VOLTS,
+ .enable_reg = BD70528_REG_BUCK3_EN,
+ .enable_mask = BD70528_MASK_RUN_EN,
+ .vsel_reg = BD70528_REG_BUCK3_VOLT,
+ .vsel_mask = BD70528_MASK_BUCK_VOLT,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "ldo1",
+ .of_match = of_match_ptr("LDO1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD70528_LDO1,
+ .ops = &bd70528_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd70528_ldo_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts),
+ .n_voltages = BD70528_LDO_VOLTS,
+ .enable_reg = BD70528_REG_LDO1_EN,
+ .enable_mask = BD70528_MASK_RUN_EN,
+ .vsel_reg = BD70528_REG_LDO1_VOLT,
+ .vsel_mask = BD70528_MASK_LDO_VOLT,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "ldo2",
+ .of_match = of_match_ptr("LDO2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD70528_LDO2,
+ .ops = &bd70528_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd70528_ldo_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts),
+ .n_voltages = BD70528_LDO_VOLTS,
+ .enable_reg = BD70528_REG_LDO2_EN,
+ .enable_mask = BD70528_MASK_RUN_EN,
+ .vsel_reg = BD70528_REG_LDO2_VOLT,
+ .vsel_mask = BD70528_MASK_LDO_VOLT,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "ldo3",
+ .of_match = of_match_ptr("LDO3"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD70528_LDO3,
+ .ops = &bd70528_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .linear_ranges = bd70528_ldo_volts,
+ .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts),
+ .n_voltages = BD70528_LDO_VOLTS,
+ .enable_reg = BD70528_REG_LDO3_EN,
+ .enable_mask = BD70528_MASK_RUN_EN,
+ .vsel_reg = BD70528_REG_LDO3_VOLT,
+ .vsel_mask = BD70528_MASK_LDO_VOLT,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "ldo_led1",
+ .of_match = of_match_ptr("LDO_LED1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD70528_LED1,
+ .ops = &bd70528_led_ops,
+ .type = REGULATOR_VOLTAGE,
+ .volt_table = &led_volts[0],
+ .n_voltages = ARRAY_SIZE(led_volts),
+ .enable_reg = BD70528_REG_LED_EN,
+ .enable_mask = BD70528_MASK_LED1_EN,
+ .vsel_reg = BD70528_REG_LED_VOLT,
+ .vsel_mask = BD70528_MASK_LED1_VOLT,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "ldo_led2",
+ .of_match = of_match_ptr("LDO_LED2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .id = BD70528_LED2,
+ .ops = &bd70528_led_ops,
+ .type = REGULATOR_VOLTAGE,
+ .volt_table = &led_volts[0],
+ .n_voltages = ARRAY_SIZE(led_volts),
+ .enable_reg = BD70528_REG_LED_EN,
+ .enable_mask = BD70528_MASK_LED2_EN,
+ .vsel_reg = BD70528_REG_LED_VOLT,
+ .vsel_mask = BD70528_MASK_LED2_VOLT,
+ .owner = THIS_MODULE,
+ },
+
+};
+
+static int bd70528_probe(struct platform_device *pdev)
+{
+ struct rohm_regmap_dev *bd70528;
+ int i;
+ struct regulator_config config = {
+ .dev = pdev->dev.parent,
+ };
+
+ bd70528 = dev_get_drvdata(pdev->dev.parent);
+ if (!bd70528) {
+ dev_err(&pdev->dev, "No MFD driver data\n");
+ return -EINVAL;
+ }
+
+ config.regmap = bd70528->regmap;
+
+ for (i = 0; i < ARRAY_SIZE(bd70528_desc); i++) {
+ struct regulator_dev *rdev;
+
+ rdev = devm_regulator_register(&pdev->dev, &bd70528_desc[i],
+ &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev,
+ "failed to register %s regulator\n",
+ bd70528_desc[i].name);
+ return PTR_ERR(rdev);
+ }
+ }
+ return 0;
+}
+
+static struct platform_driver bd70528_regulator = {
+ .driver = {
+ .name = "bd70528-pmic"
+ },
+ .probe = bd70528_probe,
+};
+
+module_platform_driver(bd70528_regulator);
+
+MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
+MODULE_DESCRIPTION("BD70528 voltage regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c
index 3a47e0372e77..b2191be49670 100644
--- a/drivers/regulator/bd718x7-regulator.c
+++ b/drivers/regulator/bd718x7-regulator.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/mfd/rohm-bd718x7.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
@@ -78,7 +79,7 @@ static int bd718xx_set_voltage_sel_pickable_restricted(
return regulator_set_voltage_sel_pickable_regmap(rdev, sel);
}
-static struct regulator_ops bd718xx_pickable_range_ldo_ops = {
+static const struct regulator_ops bd718xx_pickable_range_ldo_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -87,7 +88,7 @@ static struct regulator_ops bd718xx_pickable_range_ldo_ops = {
.get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
};
-static struct regulator_ops bd718xx_pickable_range_buck_ops = {
+static const struct regulator_ops bd718xx_pickable_range_buck_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -97,7 +98,7 @@ static struct regulator_ops bd718xx_pickable_range_buck_ops = {
.set_voltage_time_sel = regulator_set_voltage_time_sel,
};
-static struct regulator_ops bd718xx_ldo_regulator_ops = {
+static const struct regulator_ops bd718xx_ldo_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -106,7 +107,7 @@ static struct regulator_ops bd718xx_ldo_regulator_ops = {
.get_voltage_sel = regulator_get_voltage_sel_regmap,
};
-static struct regulator_ops bd718xx_ldo_regulator_nolinear_ops = {
+static const struct regulator_ops bd718xx_ldo_regulator_nolinear_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -115,7 +116,7 @@ static struct regulator_ops bd718xx_ldo_regulator_nolinear_ops = {
.get_voltage_sel = regulator_get_voltage_sel_regmap,
};
-static struct regulator_ops bd718xx_buck_regulator_ops = {
+static const struct regulator_ops bd718xx_buck_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -125,17 +126,18 @@ static struct regulator_ops bd718xx_buck_regulator_ops = {
.set_voltage_time_sel = regulator_set_voltage_time_sel,
};
-static struct regulator_ops bd718xx_buck_regulator_nolinear_ops = {
+static const struct regulator_ops bd718xx_buck_regulator_nolinear_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = bd718xx_set_voltage_sel_restricted,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
};
-static struct regulator_ops bd718xx_dvs_buck_regulator_ops = {
+static const struct regulator_ops bd718xx_dvs_buck_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -348,6 +350,135 @@ static const struct reg_init bd71837_ldo6_inits[] = {
},
};
+#define NUM_DVS_BUCKS 4
+
+struct of_dvs_setting {
+ const char *prop;
+ unsigned int reg;
+};
+
+static int set_dvs_levels(const struct of_dvs_setting *dvs,
+ struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regmap *regmap)
+{
+ int ret, i;
+ unsigned int uv;
+
+ ret = of_property_read_u32(np, dvs->prop, &uv);
+ if (ret) {
+ if (ret != -EINVAL)
+ return ret;
+ return 0;
+ }
+
+ for (i = 0; i < desc->n_voltages; i++) {
+ ret = regulator_desc_list_voltage_linear_range(desc, i);
+ if (ret < 0)
+ continue;
+ if (ret == uv) {
+ i <<= ffs(desc->vsel_mask) - 1;
+ ret = regmap_update_bits(regmap, dvs->reg,
+ DVS_BUCK_RUN_MASK, i);
+ break;
+ }
+ }
+ return ret;
+}
+
+static int buck4_set_hw_dvs_levels(struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regulator_config *cfg)
+{
+ int ret, i;
+ const struct of_dvs_setting dvs[] = {
+ {
+ .prop = "rohm,dvs-run-voltage",
+ .reg = BD71837_REG_BUCK4_VOLT_RUN,
+ },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(dvs); i++) {
+ ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap);
+ if (ret)
+ break;
+ }
+ return ret;
+}
+static int buck3_set_hw_dvs_levels(struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regulator_config *cfg)
+{
+ int ret, i;
+ const struct of_dvs_setting dvs[] = {
+ {
+ .prop = "rohm,dvs-run-voltage",
+ .reg = BD71837_REG_BUCK3_VOLT_RUN,
+ },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(dvs); i++) {
+ ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap);
+ if (ret)
+ break;
+ }
+ return ret;
+}
+
+static int buck2_set_hw_dvs_levels(struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regulator_config *cfg)
+{
+ int ret, i;
+ const struct of_dvs_setting dvs[] = {
+ {
+ .prop = "rohm,dvs-run-voltage",
+ .reg = BD718XX_REG_BUCK2_VOLT_RUN,
+ },
+ {
+ .prop = "rohm,dvs-idle-voltage",
+ .reg = BD718XX_REG_BUCK2_VOLT_IDLE,
+ },
+ };
+
+
+
+ for (i = 0; i < ARRAY_SIZE(dvs); i++) {
+ ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap);
+ if (ret)
+ break;
+ }
+ return ret;
+}
+
+static int buck1_set_hw_dvs_levels(struct device_node *np,
+ const struct regulator_desc *desc,
+ struct regulator_config *cfg)
+{
+ int ret, i;
+ const struct of_dvs_setting dvs[] = {
+ {
+ .prop = "rohm,dvs-run-voltage",
+ .reg = BD718XX_REG_BUCK1_VOLT_RUN,
+ },
+ {
+ .prop = "rohm,dvs-idle-voltage",
+ .reg = BD718XX_REG_BUCK1_VOLT_IDLE,
+ },
+ {
+ .prop = "rohm,dvs-suspend-voltage",
+ .reg = BD718XX_REG_BUCK1_VOLT_SUSP,
+ },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(dvs); i++) {
+ ret = set_dvs_levels(&dvs[i], np, desc, cfg->regmap);
+ if (ret)
+ break;
+ }
+ return ret;
+}
+
static const struct bd718xx_regulator_data bd71847_regulators[] = {
{
.desc = {
@@ -366,6 +497,7 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = {
.enable_reg = BD718XX_REG_BUCK1_CTRL,
.enable_mask = BD718XX_BUCK_EN,
.owner = THIS_MODULE,
+ .of_parse_cb = buck1_set_hw_dvs_levels,
},
.init = {
.reg = BD718XX_REG_BUCK1_CTRL,
@@ -389,6 +521,7 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = {
.enable_reg = BD718XX_REG_BUCK2_CTRL,
.enable_mask = BD718XX_BUCK_EN,
.owner = THIS_MODULE,
+ .of_parse_cb = buck2_set_hw_dvs_levels,
},
.init = {
.reg = BD718XX_REG_BUCK2_CTRL,
@@ -660,6 +793,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
.enable_reg = BD718XX_REG_BUCK1_CTRL,
.enable_mask = BD718XX_BUCK_EN,
.owner = THIS_MODULE,
+ .of_parse_cb = buck1_set_hw_dvs_levels,
},
.init = {
.reg = BD718XX_REG_BUCK1_CTRL,
@@ -683,6 +817,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
.enable_reg = BD718XX_REG_BUCK2_CTRL,
.enable_mask = BD718XX_BUCK_EN,
.owner = THIS_MODULE,
+ .of_parse_cb = buck2_set_hw_dvs_levels,
},
.init = {
.reg = BD718XX_REG_BUCK2_CTRL,
@@ -706,6 +841,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
.enable_reg = BD71837_REG_BUCK3_CTRL,
.enable_mask = BD718XX_BUCK_EN,
.owner = THIS_MODULE,
+ .of_parse_cb = buck3_set_hw_dvs_levels,
},
.init = {
.reg = BD71837_REG_BUCK3_CTRL,
@@ -729,6 +865,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
.enable_reg = BD71837_REG_BUCK4_CTRL,
.enable_mask = BD718XX_BUCK_EN,
.owner = THIS_MODULE,
+ .of_parse_cb = buck4_set_hw_dvs_levels,
},
.init = {
.reg = BD71837_REG_BUCK4_CTRL,
@@ -1007,7 +1144,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
};
struct bd718xx_pmic_inits {
- const struct bd718xx_regulator_data (*r_datas)[];
+ const struct bd718xx_regulator_data *r_datas;
unsigned int r_amount;
};
@@ -1017,16 +1154,17 @@ static int bd718xx_probe(struct platform_device *pdev)
struct regulator_config config = { 0 };
struct bd718xx_pmic_inits pmic_regulators[] = {
[BD718XX_TYPE_BD71837] = {
- .r_datas = &bd71837_regulators,
+ .r_datas = bd71837_regulators,
.r_amount = ARRAY_SIZE(bd71837_regulators),
},
[BD718XX_TYPE_BD71847] = {
- .r_datas = &bd71847_regulators,
+ .r_datas = bd71847_regulators,
.r_amount = ARRAY_SIZE(bd71847_regulators),
},
};
int i, j, err;
+ bool use_snvs;
mfd = dev_get_drvdata(pdev->dev.parent);
if (!mfd) {
@@ -1053,13 +1191,37 @@ static int bd718xx_probe(struct platform_device *pdev)
BD718XX_REG_REGLOCK);
}
+ use_snvs = of_property_read_bool(pdev->dev.parent->of_node,
+ "rohm,reset-snvs-powered");
+
+ /*
+ * Change the next stage from poweroff to be READY instead of SNVS
+ * for all reset types because OTP loading at READY will clear SEL
+ * bit allowing HW defaults for power rails to be used
+ */
+ if (!use_snvs) {
+ err = regmap_update_bits(mfd->regmap, BD718XX_REG_TRANS_COND1,
+ BD718XX_ON_REQ_POWEROFF_MASK |
+ BD718XX_SWRESET_POWEROFF_MASK |
+ 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");
+ }
+ }
+
for (i = 0; i < pmic_regulators[mfd->chip_type].r_amount; i++) {
const struct regulator_desc *desc;
struct regulator_dev *rdev;
const struct bd718xx_regulator_data *r;
- r = &(*pmic_regulators[mfd->chip_type].r_datas)[i];
+ r = &pmic_regulators[mfd->chip_type].r_datas[i];
desc = &r->desc;
config.dev = pdev->dev.parent;
@@ -1073,19 +1235,33 @@ static int bd718xx_probe(struct platform_device *pdev)
err = PTR_ERR(rdev);
goto err;
}
- /* Regulator register gets the regulator constraints and
+
+ /*
+ * Regulator register gets the regulator constraints and
* applies them (set_machine_constraints). This should have
* turned the control register(s) to correct values and we
* can now switch the control from PMIC state machine to the
* register interface
+ *
+ * At poweroff transition PMIC HW disables EN bit for
+ * regulators but leaves SEL bit untouched. So if state
+ * transition from POWEROFF is done to SNVS - then all power
+ * rails controlled by SW (having SEL bit set) stay disabled
+ * as EN is cleared. This will result boot failure if any
+ * crucial systems are powered by these rails. We don't
+ * enable SW control for crucial regulators if snvs state is
+ * used
*/
- err = regmap_update_bits(mfd->regmap, r->init.reg,
- r->init.mask, r->init.val);
- if (err) {
- dev_err(&pdev->dev,
- "Failed to write BUCK/LDO SEL bit for (%s)\n",
- desc->name);
- goto err;
+ if (!use_snvs || !rdev->constraints->always_on ||
+ !rdev->constraints->boot_on) {
+ err = regmap_update_bits(mfd->regmap, r->init.reg,
+ r->init.mask, r->init.val);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Failed to take control for (%s)\n",
+ desc->name);
+ goto err;
+ }
}
for (j = 0; j < r->additional_init_amnt; j++) {
err = regmap_update_bits(mfd->regmap,
diff --git a/drivers/regulator/bd9571mwv-regulator.c b/drivers/regulator/bd9571mwv-regulator.c
index 274c5ed7cd73..e690c2ce5b3c 100644
--- a/drivers/regulator/bd9571mwv-regulator.c
+++ b/drivers/regulator/bd9571mwv-regulator.c
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* ROHM BD9571MWV-M regulator driver
*
* Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.com>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether expressed or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License version 2 for more details.
- *
* Based on the TPS65086 driver
*
* NOTE: VD09 is missing
@@ -108,7 +100,7 @@ static int bd9571mwv_reg_set_voltage_sel_regmap(struct regulator_dev *rdev,
}
/* Operations permitted on AVS voltage regulator */
-static struct regulator_ops avs_ops = {
+static const struct regulator_ops avs_ops = {
.set_voltage_sel = bd9571mwv_avs_set_voltage_sel_regmap,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = bd9571mwv_avs_get_voltage_sel_regmap,
@@ -116,7 +108,7 @@ static struct regulator_ops avs_ops = {
};
/* Operations permitted on voltage regulators */
-static struct regulator_ops reg_ops = {
+static const struct regulator_ops reg_ops = {
.set_voltage_sel = bd9571mwv_reg_set_voltage_sel_regmap,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
@@ -124,13 +116,13 @@ static struct regulator_ops reg_ops = {
};
/* Operations permitted on voltage monitors */
-static struct regulator_ops vid_ops = {
+static const struct regulator_ops vid_ops = {
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
};
-static struct regulator_desc regulators[] = {
+static const struct regulator_desc regulators[] = {
BD9571MWV_REG("VD09", "vd09", VD09, avs_ops, 0, 0x7f,
0x80, 600000, 10000, 0x3c),
BD9571MWV_REG("VD18", "vd18", VD18, vid_ops, BD9571MWV_VD18_VID, 0xf,
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 2c66b528aede..68473d0cc57e 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -23,7 +23,6 @@
#include <linux/mutex.h>
#include <linux/suspend.h>
#include <linux/delay.h>
-#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h>
#include <linux/regmap.h>
@@ -50,6 +49,8 @@
#define rdev_dbg(rdev, fmt, ...) \
pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
+static DEFINE_WW_CLASS(regulator_ww_class);
+static DEFINE_MUTEX(regulator_nesting_mutex);
static DEFINE_MUTEX(regulator_list_mutex);
static LIST_HEAD(regulator_map_list);
static LIST_HEAD(regulator_ena_gpio_list);
@@ -80,7 +81,6 @@ struct regulator_enable_gpio {
struct gpio_desc *gpiod;
u32 enable_count; /* a number of enabled shared GPIO */
u32 request_count; /* a number of requested shared GPIO */
- unsigned int ena_gpio_invert:1;
};
/*
@@ -97,7 +97,7 @@ struct regulator_supply_alias {
};
static int _regulator_is_enabled(struct regulator_dev *rdev);
-static int _regulator_disable(struct regulator_dev *rdev);
+static int _regulator_disable(struct regulator *regulator);
static int _regulator_get_voltage(struct regulator_dev *rdev);
static int _regulator_get_current_limit(struct regulator_dev *rdev);
static unsigned int _regulator_get_mode(struct regulator_dev *rdev);
@@ -105,6 +105,11 @@ static int _notifier_call_chain(struct regulator_dev *rdev,
unsigned long event, void *data);
static int _regulator_do_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV);
+static int regulator_balance_voltage(struct regulator_dev *rdev,
+ suspend_state_t state);
+static int regulator_set_voltage_rdev(struct regulator_dev *rdev,
+ int min_uV, int max_uV,
+ suspend_state_t state);
static struct regulator *create_regulator(struct regulator_dev *rdev,
struct device *dev,
const char *supply_name);
@@ -138,18 +143,10 @@ static bool regulator_ops_is_valid(struct regulator_dev *rdev, int ops)
return false;
}
-static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev)
-{
- if (rdev && rdev->supply)
- return rdev->supply->rdev;
-
- return NULL;
-}
-
/**
* regulator_lock_nested - lock a single regulator
* @rdev: regulator source
- * @subclass: mutex subclass used for lockdep
+ * @ww_ctx: w/w mutex acquire context
*
* This function can be called many times by one task on
* a single regulator and its mutex will be locked only
@@ -157,25 +154,54 @@ static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev)
* than the one, which initially locked the mutex, it will
* wait on mutex.
*/
-static void regulator_lock_nested(struct regulator_dev *rdev,
- unsigned int subclass)
+static inline int regulator_lock_nested(struct regulator_dev *rdev,
+ struct ww_acquire_ctx *ww_ctx)
{
- if (!mutex_trylock(&rdev->mutex)) {
- if (rdev->mutex_owner == current) {
+ bool lock = false;
+ int ret = 0;
+
+ mutex_lock(&regulator_nesting_mutex);
+
+ if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) {
+ if (rdev->mutex_owner == current)
rdev->ref_cnt++;
- return;
+ else
+ lock = true;
+
+ if (lock) {
+ mutex_unlock(&regulator_nesting_mutex);
+ ret = ww_mutex_lock(&rdev->mutex, ww_ctx);
+ mutex_lock(&regulator_nesting_mutex);
}
- mutex_lock_nested(&rdev->mutex, subclass);
+ } else {
+ lock = true;
}
- rdev->ref_cnt = 1;
- rdev->mutex_owner = current;
+ if (lock && ret != -EDEADLK) {
+ rdev->ref_cnt++;
+ rdev->mutex_owner = current;
+ }
+
+ mutex_unlock(&regulator_nesting_mutex);
+
+ return ret;
}
-static inline void regulator_lock(struct regulator_dev *rdev)
+/**
+ * regulator_lock - lock a single regulator
+ * @rdev: regulator source
+ *
+ * This function can be called many times by one task on
+ * a single regulator and its mutex will be locked only
+ * once. If a task, which is calling this function is other
+ * than the one, which initially locked the mutex, it will
+ * wait on mutex.
+ */
+void regulator_lock(struct regulator_dev *rdev)
{
- regulator_lock_nested(rdev, 0);
+ regulator_lock_nested(rdev, NULL);
}
+EXPORT_SYMBOL_GPL(regulator_lock);
/**
* regulator_unlock - unlock a single regulator
@@ -184,47 +210,191 @@ static inline void regulator_lock(struct regulator_dev *rdev)
* This function unlocks the mutex when the
* reference counter reaches 0.
*/
-static void regulator_unlock(struct regulator_dev *rdev)
+void regulator_unlock(struct regulator_dev *rdev)
{
- if (rdev->ref_cnt != 0) {
- rdev->ref_cnt--;
+ mutex_lock(&regulator_nesting_mutex);
+
+ if (--rdev->ref_cnt == 0) {
+ rdev->mutex_owner = NULL;
+ ww_mutex_unlock(&rdev->mutex);
+ }
+
+ WARN_ON_ONCE(rdev->ref_cnt < 0);
- if (!rdev->ref_cnt) {
- rdev->mutex_owner = NULL;
- mutex_unlock(&rdev->mutex);
+ mutex_unlock(&regulator_nesting_mutex);
+}
+EXPORT_SYMBOL_GPL(regulator_unlock);
+
+static bool regulator_supply_is_couple(struct regulator_dev *rdev)
+{
+ struct regulator_dev *c_rdev;
+ int i;
+
+ for (i = 1; i < rdev->coupling_desc.n_coupled; i++) {
+ c_rdev = rdev->coupling_desc.coupled_rdevs[i];
+
+ if (rdev->supply->rdev == c_rdev)
+ return true;
+ }
+
+ return false;
+}
+
+static void regulator_unlock_recursive(struct regulator_dev *rdev,
+ unsigned int n_coupled)
+{
+ struct regulator_dev *c_rdev;
+ int i;
+
+ for (i = n_coupled; i > 0; i--) {
+ c_rdev = rdev->coupling_desc.coupled_rdevs[i - 1];
+
+ if (!c_rdev)
+ continue;
+
+ if (c_rdev->supply && !regulator_supply_is_couple(c_rdev))
+ regulator_unlock_recursive(
+ c_rdev->supply->rdev,
+ c_rdev->coupling_desc.n_coupled);
+
+ regulator_unlock(c_rdev);
+ }
+}
+
+static int regulator_lock_recursive(struct regulator_dev *rdev,
+ struct regulator_dev **new_contended_rdev,
+ struct regulator_dev **old_contended_rdev,
+ struct ww_acquire_ctx *ww_ctx)
+{
+ struct regulator_dev *c_rdev;
+ int i, err;
+
+ for (i = 0; i < rdev->coupling_desc.n_coupled; i++) {
+ c_rdev = rdev->coupling_desc.coupled_rdevs[i];
+
+ if (!c_rdev)
+ continue;
+
+ if (c_rdev != *old_contended_rdev) {
+ err = regulator_lock_nested(c_rdev, ww_ctx);
+ if (err) {
+ if (err == -EDEADLK) {
+ *new_contended_rdev = c_rdev;
+ goto err_unlock;
+ }
+
+ /* shouldn't happen */
+ WARN_ON_ONCE(err != -EALREADY);
+ }
+ } else {
+ *old_contended_rdev = NULL;
+ }
+
+ if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) {
+ err = regulator_lock_recursive(c_rdev->supply->rdev,
+ new_contended_rdev,
+ old_contended_rdev,
+ ww_ctx);
+ if (err) {
+ regulator_unlock(c_rdev);
+ goto err_unlock;
+ }
}
}
+
+ return 0;
+
+err_unlock:
+ regulator_unlock_recursive(rdev, i);
+
+ return err;
}
/**
- * regulator_lock_supply - lock a regulator and its supplies
- * @rdev: regulator source
+ * regulator_unlock_dependent - unlock regulator's suppliers and coupled
+ * regulators
+ * @rdev: regulator source
+ * @ww_ctx: w/w mutex acquire context
+ *
+ * Unlock all regulators related with rdev by coupling or supplying.
*/
-static void regulator_lock_supply(struct regulator_dev *rdev)
+static void regulator_unlock_dependent(struct regulator_dev *rdev,
+ struct ww_acquire_ctx *ww_ctx)
{
- int i;
-
- for (i = 0; rdev; rdev = rdev_get_supply(rdev), i++)
- regulator_lock_nested(rdev, i);
+ regulator_unlock_recursive(rdev, rdev->coupling_desc.n_coupled);
+ ww_acquire_fini(ww_ctx);
}
/**
- * regulator_unlock_supply - unlock a regulator and its supplies
- * @rdev: regulator source
+ * regulator_lock_dependent - lock regulator's suppliers and coupled regulators
+ * @rdev: regulator source
+ * @ww_ctx: w/w mutex acquire context
+ *
+ * This function as a wrapper on regulator_lock_recursive(), which locks
+ * all regulators related with rdev by coupling or supplying.
*/
-static void regulator_unlock_supply(struct regulator_dev *rdev)
+static void regulator_lock_dependent(struct regulator_dev *rdev,
+ struct ww_acquire_ctx *ww_ctx)
{
- struct regulator *supply;
+ struct regulator_dev *new_contended_rdev = NULL;
+ struct regulator_dev *old_contended_rdev = NULL;
+ int err;
- while (1) {
- regulator_unlock(rdev);
- supply = rdev->supply;
+ mutex_lock(&regulator_list_mutex);
+
+ ww_acquire_init(ww_ctx, &regulator_ww_class);
+
+ do {
+ if (new_contended_rdev) {
+ ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx);
+ old_contended_rdev = new_contended_rdev;
+ old_contended_rdev->ref_cnt++;
+ }
+
+ err = regulator_lock_recursive(rdev,
+ &new_contended_rdev,
+ &old_contended_rdev,
+ ww_ctx);
+
+ if (old_contended_rdev)
+ regulator_unlock(old_contended_rdev);
+
+ } while (err == -EDEADLK);
+
+ ww_acquire_done(ww_ctx);
+
+ mutex_unlock(&regulator_list_mutex);
+}
- if (!rdev->supply)
- return;
+/**
+ * of_get_child_regulator - get a child regulator device node
+ * based on supply name
+ * @parent: Parent device node
+ * @prop_name: Combination regulator supply name and "-supply"
+ *
+ * Traverse all child nodes.
+ * Extract the child regulator device node corresponding to the supply name.
+ * returns the device node corresponding to the regulator if found, else
+ * returns NULL.
+ */
+static struct device_node *of_get_child_regulator(struct device_node *parent,
+ const char *prop_name)
+{
+ struct device_node *regnode = NULL;
+ struct device_node *child = NULL;
- rdev = supply->rdev;
+ for_each_child_of_node(parent, child) {
+ regnode = of_parse_phandle(child, prop_name, 0);
+
+ if (!regnode) {
+ regnode = of_get_child_regulator(child, prop_name);
+ if (regnode)
+ return regnode;
+ } else {
+ return regnode;
+ }
}
+ return NULL;
}
/**
@@ -247,6 +417,10 @@ static struct device_node *of_get_regulator(struct device *dev, const char *supp
regnode = of_parse_phandle(dev->of_node, prop_name, 0);
if (!regnode) {
+ regnode = of_get_child_regulator(dev->of_node, prop_name);
+ if (regnode)
+ return regnode;
+
dev_dbg(dev, "Looking up %s property in node %pOF failed\n",
prop_name, dev->of_node);
return NULL;
@@ -582,8 +756,10 @@ static ssize_t regulator_total_uA_show(struct device *dev,
int uA = 0;
regulator_lock(rdev);
- list_for_each_entry(regulator, &rdev->consumer_list, list)
- uA += regulator->uA_load;
+ list_for_each_entry(regulator, &rdev->consumer_list, list) {
+ if (regulator->enable_count)
+ uA += regulator->uA_load;
+ }
regulator_unlock(rdev);
return sprintf(buf, "%d\n", uA);
}
@@ -738,14 +914,14 @@ static int drms_uA_update(struct regulator_dev *rdev)
int current_uA = 0, output_uV, input_uV, err;
unsigned int mode;
- lockdep_assert_held_once(&rdev->mutex);
-
/*
* first check to see if we can set modes at all, otherwise just
* tell the consumer everything is OK.
*/
- if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS))
+ if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) {
+ rdev_dbg(rdev, "DRMS operation not allowed\n");
return 0;
+ }
if (!rdev->desc->ops->get_optimum_mode &&
!rdev->desc->ops->set_load)
@@ -756,8 +932,10 @@ static int drms_uA_update(struct regulator_dev *rdev)
return -EINVAL;
/* calc total requested load */
- list_for_each_entry(sibling, &rdev->consumer_list, list)
- current_uA += sibling->uA_load;
+ list_for_each_entry(sibling, &rdev->consumer_list, list) {
+ if (sibling->enable_count)
+ current_uA += sibling->uA_load;
+ }
current_uA += rdev->constraints->system_load;
@@ -815,7 +993,7 @@ static int suspend_set_state(struct regulator_dev *rdev,
if (rstate == NULL)
return 0;
- /* If we have no suspend mode configration don't set anything;
+ /* If we have no suspend mode configuration don't set anything;
* only warn if the driver implements set_suspend_voltage or
* set_suspend_mode callback.
*/
@@ -943,7 +1121,7 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
int current_uV = _regulator_get_voltage(rdev);
if (current_uV == -ENOTRECOVERABLE) {
- /* This regulator can't be read and must be initted */
+ /* This regulator can't be read and must be initialized */
rdev_info(rdev, "Setting %d-%duV\n",
rdev->constraints->min_uV,
rdev->constraints->max_uV);
@@ -1156,17 +1334,14 @@ static int set_machine_constraints(struct regulator_dev *rdev,
rdev_err(rdev, "failed to set initial mode: %d\n", ret);
return ret;
}
- }
-
- /* If the constraints say the regulator should be on at this point
- * and we have control then make sure it is enabled.
- */
- if (rdev->constraints->always_on || rdev->constraints->boot_on) {
- ret = _regulator_do_enable(rdev);
- if (ret < 0 && ret != -EINVAL) {
- rdev_err(rdev, "failed to enable\n");
- return ret;
- }
+ } else if (rdev->constraints->system_load) {
+ /*
+ * We'll only apply the initial system load if an
+ * initial mode wasn't specified.
+ */
+ regulator_lock(rdev);
+ drms_uA_update(rdev);
+ regulator_unlock(rdev);
}
if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable)
@@ -1214,6 +1389,27 @@ static int set_machine_constraints(struct regulator_dev *rdev,
}
}
+ /* If the constraints say the regulator should be on at this point
+ * and we have control then make sure it is enabled.
+ */
+ if (rdev->constraints->always_on || rdev->constraints->boot_on) {
+ if (rdev->supply) {
+ ret = regulator_enable(rdev->supply);
+ if (ret < 0) {
+ _regulator_put(rdev->supply);
+ rdev->supply = NULL;
+ return ret;
+ }
+ }
+
+ ret = _regulator_do_enable(rdev);
+ if (ret < 0 && ret != -EINVAL) {
+ rdev_err(rdev, "failed to enable\n");
+ return ret;
+ }
+ rdev->use_count++;
+ }
+
print_constraints(rdev);
return 0;
}
@@ -1576,7 +1772,7 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
struct device *dev = rdev->dev.parent;
int ret;
- /* No supply to resovle? */
+ /* No supply to resolve? */
if (!rdev->supply_name)
return 0;
@@ -1628,8 +1824,12 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
return ret;
}
- /* Cascade always-on state to supply */
- if (_regulator_is_enabled(rdev)) {
+ /*
+ * In set_machine_constraints() we may have turned this regulator on
+ * but we couldn't propagate to the supply if it hadn't been resolved
+ * yet. Do it now.
+ */
+ if (rdev->use_count) {
ret = regulator_enable(rdev->supply);
if (ret < 0) {
_regulator_put(rdev->supply);
@@ -1713,6 +1913,16 @@ struct regulator *_regulator_get(struct device *dev, const char *id,
return regulator;
}
+ mutex_lock(&regulator_list_mutex);
+ ret = (rdev->coupling_desc.n_resolved != rdev->coupling_desc.n_coupled);
+ mutex_unlock(&regulator_list_mutex);
+
+ if (ret != 0) {
+ regulator = ERR_PTR(-EPROBE_DEFER);
+ put_device(&rdev->dev);
+ return regulator;
+ }
+
ret = regulator_resolve_supply(rdev);
if (ret < 0) {
regulator = ERR_PTR(ret);
@@ -1832,20 +2042,15 @@ static void _regulator_put(struct regulator *regulator)
lockdep_assert_held_once(&regulator_list_mutex);
+ /* Docs say you must disable before calling regulator_put() */
+ WARN_ON(regulator->enable_count);
+
rdev = regulator->rdev;
debugfs_remove_recursive(regulator->debugfs);
if (regulator->dev) {
- int count = 0;
- struct regulator *r;
-
- list_for_each_entry(r, &rdev->consumer_list, list)
- if (r->dev == regulator->dev)
- count++;
-
- if (count == 1)
- device_link_remove(regulator->dev, &rdev->dev);
+ device_link_remove(regulator->dev, &rdev->dev);
/* remove any sysfs entries */
sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
@@ -2016,38 +2221,21 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev,
{
struct regulator_enable_gpio *pin;
struct gpio_desc *gpiod;
- int ret;
- if (config->ena_gpiod)
- gpiod = config->ena_gpiod;
- else
- gpiod = gpio_to_desc(config->ena_gpio);
+ gpiod = config->ena_gpiod;
list_for_each_entry(pin, &regulator_ena_gpio_list, list) {
if (pin->gpiod == gpiod) {
- rdev_dbg(rdev, "GPIO %d is already used\n",
- config->ena_gpio);
+ rdev_dbg(rdev, "GPIO is already used\n");
goto update_ena_gpio_to_rdev;
}
}
- if (!config->ena_gpiod) {
- ret = gpio_request_one(config->ena_gpio,
- GPIOF_DIR_OUT | config->ena_gpio_flags,
- rdev_get_name(rdev));
- if (ret)
- return ret;
- }
-
pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL);
- if (pin == NULL) {
- if (!config->ena_gpiod)
- gpio_free(config->ena_gpio);
+ if (pin == NULL)
return -ENOMEM;
- }
pin->gpiod = gpiod;
- pin->ena_gpio_invert = config->ena_gpio_invert;
list_add(&pin->list, &regulator_ena_gpio_list);
update_ena_gpio_to_rdev:
@@ -2068,7 +2256,6 @@ static void regulator_ena_gpio_free(struct regulator_dev *rdev)
if (pin->gpiod == rdev->ena_pin->gpiod) {
if (pin->request_count <= 1) {
pin->request_count = 0;
- gpiod_put(pin->gpiod);
list_del(&pin->list);
kfree(pin);
rdev->ena_pin = NULL;
@@ -2098,8 +2285,7 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
if (enable) {
/* Enable GPIO at initial use */
if (pin->enable_count == 0)
- gpiod_set_value_cansleep(pin->gpiod,
- !pin->ena_gpio_invert);
+ gpiod_set_value_cansleep(pin->gpiod, 1);
pin->enable_count++;
} else {
@@ -2110,8 +2296,7 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
/* Disable GPIO if not used */
if (pin->enable_count <= 1) {
- gpiod_set_value_cansleep(pin->gpiod,
- pin->ena_gpio_invert);
+ gpiod_set_value_cansleep(pin->gpiod, 0);
pin->enable_count = 0;
}
}
@@ -2188,7 +2373,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
* timer wrapping.
* in case of multiple timer wrapping, either it can be
* detected by out-of-range remaining, or it cannot be
- * detected and we gets a panelty of
+ * detected and we get a penalty of
* _regulator_enable_delay().
*/
remaining = intended - start_jiffy;
@@ -2225,34 +2410,109 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
return 0;
}
+/**
+ * _regulator_handle_consumer_enable - handle that a consumer enabled
+ * @regulator: regulator source
+ *
+ * Some things on a regulator consumer (like the contribution towards total
+ * load on the regulator) only have an effect when the consumer wants the
+ * regulator enabled. Explained in example with two consumers of the same
+ * regulator:
+ * consumer A: set_load(100); => total load = 0
+ * consumer A: regulator_enable(); => total load = 100
+ * consumer B: set_load(1000); => total load = 100
+ * consumer B: regulator_enable(); => total load = 1100
+ * consumer A: regulator_disable(); => total_load = 1000
+ *
+ * This function (together with _regulator_handle_consumer_disable) is
+ * responsible for keeping track of the refcount for a given regulator consumer
+ * and applying / unapplying these things.
+ *
+ * Returns 0 upon no error; -error upon error.
+ */
+static int _regulator_handle_consumer_enable(struct regulator *regulator)
+{
+ struct regulator_dev *rdev = regulator->rdev;
+
+ lockdep_assert_held_once(&rdev->mutex.base);
+
+ regulator->enable_count++;
+ if (regulator->uA_load && regulator->enable_count == 1)
+ return drms_uA_update(rdev);
+
+ return 0;
+}
+
+/**
+ * _regulator_handle_consumer_disable - handle that a consumer disabled
+ * @regulator: regulator source
+ *
+ * The opposite of _regulator_handle_consumer_enable().
+ *
+ * Returns 0 upon no error; -error upon error.
+ */
+static int _regulator_handle_consumer_disable(struct regulator *regulator)
+{
+ struct regulator_dev *rdev = regulator->rdev;
+
+ lockdep_assert_held_once(&rdev->mutex.base);
+
+ if (!regulator->enable_count) {
+ rdev_err(rdev, "Underflow of regulator enable count\n");
+ return -EINVAL;
+ }
+
+ regulator->enable_count--;
+ if (regulator->uA_load && regulator->enable_count == 0)
+ return drms_uA_update(rdev);
+
+ return 0;
+}
+
/* locks held by regulator_enable() */
-static int _regulator_enable(struct regulator_dev *rdev)
+static int _regulator_enable(struct regulator *regulator)
{
+ struct regulator_dev *rdev = regulator->rdev;
int ret;
- lockdep_assert_held_once(&rdev->mutex);
+ lockdep_assert_held_once(&rdev->mutex.base);
- /* check voltage and requested load before enabling */
- if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS))
- drms_uA_update(rdev);
+ if (rdev->use_count == 0 && rdev->supply) {
+ ret = _regulator_enable(rdev->supply);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* balance only if there are regulators coupled */
+ if (rdev->coupling_desc.n_coupled > 1) {
+ ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);
+ if (ret < 0)
+ goto err_disable_supply;
+ }
+
+ ret = _regulator_handle_consumer_enable(regulator);
+ if (ret < 0)
+ goto err_disable_supply;
if (rdev->use_count == 0) {
/* The regulator may on if it's not switchable or left on */
ret = _regulator_is_enabled(rdev);
if (ret == -EINVAL || ret == 0) {
if (!regulator_ops_is_valid(rdev,
- REGULATOR_CHANGE_STATUS))
- return -EPERM;
+ REGULATOR_CHANGE_STATUS)) {
+ ret = -EPERM;
+ goto err_consumer_disable;
+ }
ret = _regulator_do_enable(rdev);
if (ret < 0)
- return ret;
+ goto err_consumer_disable;
_notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE,
NULL);
} else if (ret < 0) {
rdev_err(rdev, "is_enabled() failed: %d\n", ret);
- return ret;
+ goto err_consumer_disable;
}
/* Fallthrough on positive return values - already enabled */
}
@@ -2260,6 +2520,15 @@ static int _regulator_enable(struct regulator_dev *rdev)
rdev->use_count++;
return 0;
+
+err_consumer_disable:
+ _regulator_handle_consumer_disable(regulator);
+
+err_disable_supply:
+ if (rdev->use_count == 0 && rdev->supply)
+ _regulator_disable(rdev->supply);
+
+ return ret;
}
/**
@@ -2276,23 +2545,12 @@ static int _regulator_enable(struct regulator_dev *rdev)
int regulator_enable(struct regulator *regulator)
{
struct regulator_dev *rdev = regulator->rdev;
- int ret = 0;
-
- if (regulator->always_on)
- return 0;
-
- if (rdev->supply) {
- ret = regulator_enable(rdev->supply);
- if (ret != 0)
- return ret;
- }
-
- mutex_lock(&rdev->mutex);
- ret = _regulator_enable(rdev);
- mutex_unlock(&rdev->mutex);
+ struct ww_acquire_ctx ww_ctx;
+ int ret;
- if (ret != 0 && rdev->supply)
- regulator_disable(rdev->supply);
+ regulator_lock_dependent(rdev, &ww_ctx);
+ ret = _regulator_enable(regulator);
+ regulator_unlock_dependent(rdev, &ww_ctx);
return ret;
}
@@ -2330,11 +2588,12 @@ static int _regulator_do_disable(struct regulator_dev *rdev)
}
/* locks held by regulator_disable() */
-static int _regulator_disable(struct regulator_dev *rdev)
+static int _regulator_disable(struct regulator *regulator)
{
+ struct regulator_dev *rdev = regulator->rdev;
int ret = 0;
- lockdep_assert_held_once(&rdev->mutex);
+ lockdep_assert_held_once(&rdev->mutex.base);
if (WARN(rdev->use_count <= 0,
"unbalanced disables for %s\n", rdev_get_name(rdev)))
@@ -2366,12 +2625,18 @@ static int _regulator_disable(struct regulator_dev *rdev)
rdev->use_count = 0;
} else if (rdev->use_count > 1) {
- if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS))
- drms_uA_update(rdev);
-
rdev->use_count--;
}
+ if (ret == 0)
+ ret = _regulator_handle_consumer_disable(regulator);
+
+ if (ret == 0 && rdev->coupling_desc.n_coupled > 1)
+ ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);
+
+ if (ret == 0 && rdev->use_count == 0 && rdev->supply)
+ ret = _regulator_disable(rdev->supply);
+
return ret;
}
@@ -2390,17 +2655,12 @@ static int _regulator_disable(struct regulator_dev *rdev)
int regulator_disable(struct regulator *regulator)
{
struct regulator_dev *rdev = regulator->rdev;
- int ret = 0;
-
- if (regulator->always_on)
- return 0;
-
- mutex_lock(&rdev->mutex);
- ret = _regulator_disable(rdev);
- mutex_unlock(&rdev->mutex);
+ struct ww_acquire_ctx ww_ctx;
+ int ret;
- if (ret == 0 && rdev->supply)
- regulator_disable(rdev->supply);
+ regulator_lock_dependent(rdev, &ww_ctx);
+ ret = _regulator_disable(regulator);
+ regulator_unlock_dependent(rdev, &ww_ctx);
return ret;
}
@@ -2411,7 +2671,7 @@ static int _regulator_force_disable(struct regulator_dev *rdev)
{
int ret = 0;
- lockdep_assert_held_once(&rdev->mutex);
+ lockdep_assert_held_once(&rdev->mutex.base);
ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
REGULATOR_EVENT_PRE_DISABLE, NULL);
@@ -2444,16 +2704,25 @@ static int _regulator_force_disable(struct regulator_dev *rdev)
int regulator_force_disable(struct regulator *regulator)
{
struct regulator_dev *rdev = regulator->rdev;
+ struct ww_acquire_ctx ww_ctx;
int ret;
- mutex_lock(&rdev->mutex);
- regulator->uA_load = 0;
+ regulator_lock_dependent(rdev, &ww_ctx);
+
ret = _regulator_force_disable(regulator->rdev);
- mutex_unlock(&rdev->mutex);
- if (rdev->supply)
- while (rdev->open_count--)
- regulator_disable(rdev->supply);
+ if (rdev->coupling_desc.n_coupled > 1)
+ regulator_balance_voltage(rdev, PM_SUSPEND_ON);
+
+ if (regulator->uA_load) {
+ regulator->uA_load = 0;
+ ret = drms_uA_update(rdev);
+ }
+
+ if (rdev->use_count != 0 && rdev->supply)
+ _regulator_disable(rdev->supply);
+
+ regulator_unlock_dependent(rdev, &ww_ctx);
return ret;
}
@@ -2463,14 +2732,12 @@ static void regulator_disable_work(struct work_struct *work)
{
struct regulator_dev *rdev = container_of(work, struct regulator_dev,
disable_work.work);
+ struct ww_acquire_ctx ww_ctx;
int count, i, ret;
+ struct regulator *regulator;
+ int total_count = 0;
- regulator_lock(rdev);
-
- BUG_ON(!rdev->deferred_disables);
-
- count = rdev->deferred_disables;
- rdev->deferred_disables = 0;
+ regulator_lock_dependent(rdev, &ww_ctx);
/*
* Workqueue functions queue the new work instance while the previous
@@ -2480,29 +2747,33 @@ static void regulator_disable_work(struct work_struct *work)
*/
cancel_delayed_work(&rdev->disable_work);
- for (i = 0; i < count; i++) {
- ret = _regulator_disable(rdev);
- if (ret != 0)
- rdev_err(rdev, "Deferred disable failed: %d\n", ret);
- }
+ list_for_each_entry(regulator, &rdev->consumer_list, list) {
+ count = regulator->deferred_disables;
- regulator_unlock(rdev);
+ if (!count)
+ continue;
+
+ total_count += count;
+ regulator->deferred_disables = 0;
- if (rdev->supply) {
for (i = 0; i < count; i++) {
- ret = regulator_disable(rdev->supply);
- if (ret != 0) {
- rdev_err(rdev,
- "Supply disable failed: %d\n", ret);
- }
+ ret = _regulator_disable(regulator);
+ if (ret != 0)
+ rdev_err(rdev, "Deferred disable failed: %d\n", ret);
}
}
+ WARN_ON(!total_count);
+
+ if (rdev->coupling_desc.n_coupled > 1)
+ regulator_balance_voltage(rdev, PM_SUSPEND_ON);
+
+ regulator_unlock_dependent(rdev, &ww_ctx);
}
/**
* regulator_disable_deferred - disable regulator output with delay
* @regulator: regulator source
- * @ms: miliseconds until the regulator is disabled
+ * @ms: milliseconds until the regulator is disabled
*
* Execute regulator_disable() on the regulator after a delay. This
* is intended for use with devices that require some time to quiesce.
@@ -2515,14 +2786,11 @@ int regulator_disable_deferred(struct regulator *regulator, int ms)
{
struct regulator_dev *rdev = regulator->rdev;
- if (regulator->always_on)
- return 0;
-
if (!ms)
return regulator_disable(regulator);
regulator_lock(rdev);
- rdev->deferred_disables++;
+ regulator->deferred_disables++;
mod_delayed_work(system_power_efficient_wq, &rdev->disable_work,
msecs_to_jiffies(ms));
regulator_unlock(rdev);
@@ -2597,9 +2865,9 @@ int regulator_is_enabled(struct regulator *regulator)
if (regulator->always_on)
return 1;
- mutex_lock(&regulator->rdev->mutex);
+ regulator_lock(regulator->rdev);
ret = _regulator_is_enabled(regulator->rdev);
- mutex_unlock(&regulator->rdev->mutex);
+ regulator_unlock(regulator->rdev);
return ret;
}
@@ -3013,8 +3281,6 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
int ret = 0;
int old_min_uV, old_max_uV;
int current_uV;
- int best_supply_uV = 0;
- int supply_change_uV = 0;
/* If we're setting the same range as last time the change
* should be a noop (some cpufreq implementations use the same
@@ -3054,10 +3320,27 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
voltage->min_uV = min_uV;
voltage->max_uV = max_uV;
- ret = regulator_check_consumers(rdev, &min_uV, &max_uV, state);
+ /* for not coupled regulators this will just set the voltage */
+ ret = regulator_balance_voltage(rdev, state);
if (ret < 0)
goto out2;
+out:
+ return 0;
+out2:
+ voltage->min_uV = old_min_uV;
+ voltage->max_uV = old_max_uV;
+
+ return ret;
+}
+
+static int regulator_set_voltage_rdev(struct regulator_dev *rdev, int min_uV,
+ int max_uV, suspend_state_t state)
+{
+ int best_supply_uV = 0;
+ int supply_change_uV = 0;
+ int ret;
+
if (rdev->supply &&
regulator_ops_is_valid(rdev->supply->rdev,
REGULATOR_CHANGE_VOLTAGE) &&
@@ -3069,13 +3352,13 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
selector = regulator_map_voltage(rdev, min_uV, max_uV);
if (selector < 0) {
ret = selector;
- goto out2;
+ goto out;
}
best_supply_uV = _regulator_list_voltage(rdev, selector, 0);
if (best_supply_uV < 0) {
ret = best_supply_uV;
- goto out2;
+ goto out;
}
best_supply_uV += rdev->desc->min_dropout_uV;
@@ -3083,7 +3366,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
current_supply_uV = _regulator_get_voltage(rdev->supply->rdev);
if (current_supply_uV < 0) {
ret = current_supply_uV;
- goto out2;
+ goto out;
}
supply_change_uV = best_supply_uV - current_supply_uV;
@@ -3095,7 +3378,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
if (ret) {
dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n",
ret);
- goto out2;
+ goto out;
}
}
@@ -3105,7 +3388,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
ret = _regulator_do_set_suspend_voltage(rdev, min_uV,
max_uV, state);
if (ret < 0)
- goto out2;
+ goto out;
if (supply_change_uV < 0) {
ret = regulator_set_voltage_unlocked(rdev->supply,
@@ -3119,10 +3402,273 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
out:
return ret;
-out2:
- voltage->min_uV = old_min_uV;
- voltage->max_uV = old_max_uV;
+}
+
+static int regulator_limit_voltage_step(struct regulator_dev *rdev,
+ int *current_uV, int *min_uV)
+{
+ struct regulation_constraints *constraints = rdev->constraints;
+
+ /* Limit voltage change only if necessary */
+ if (!constraints->max_uV_step || !_regulator_is_enabled(rdev))
+ return 1;
+
+ if (*current_uV < 0) {
+ *current_uV = _regulator_get_voltage(rdev);
+
+ if (*current_uV < 0)
+ return *current_uV;
+ }
+
+ if (abs(*current_uV - *min_uV) <= constraints->max_uV_step)
+ return 1;
+
+ /* Clamp target voltage within the given step */
+ if (*current_uV < *min_uV)
+ *min_uV = min(*current_uV + constraints->max_uV_step,
+ *min_uV);
+ else
+ *min_uV = max(*current_uV - constraints->max_uV_step,
+ *min_uV);
+
+ return 0;
+}
+
+static int regulator_get_optimal_voltage(struct regulator_dev *rdev,
+ int *current_uV,
+ int *min_uV, int *max_uV,
+ suspend_state_t state,
+ int n_coupled)
+{
+ struct coupling_desc *c_desc = &rdev->coupling_desc;
+ struct regulator_dev **c_rdevs = c_desc->coupled_rdevs;
+ struct regulation_constraints *constraints = rdev->constraints;
+ int max_spread = constraints->max_spread;
+ int desired_min_uV = 0, desired_max_uV = INT_MAX;
+ int max_current_uV = 0, min_current_uV = INT_MAX;
+ int highest_min_uV = 0, target_uV, possible_uV;
+ int i, ret;
+ bool done;
+
+ *current_uV = -1;
+
+ /*
+ * If there are no coupled regulators, simply set the voltage
+ * demanded by consumers.
+ */
+ if (n_coupled == 1) {
+ /*
+ * If consumers don't provide any demands, set voltage
+ * to min_uV
+ */
+ desired_min_uV = constraints->min_uV;
+ desired_max_uV = constraints->max_uV;
+
+ ret = regulator_check_consumers(rdev,
+ &desired_min_uV,
+ &desired_max_uV, state);
+ if (ret < 0)
+ return ret;
+
+ possible_uV = desired_min_uV;
+ done = true;
+
+ goto finish;
+ }
+
+ /* Find highest min desired voltage */
+ for (i = 0; i < n_coupled; i++) {
+ int tmp_min = 0;
+ int tmp_max = INT_MAX;
+
+ lockdep_assert_held_once(&c_rdevs[i]->mutex.base);
+
+ ret = regulator_check_consumers(c_rdevs[i],
+ &tmp_min,
+ &tmp_max, state);
+ if (ret < 0)
+ return ret;
+
+ ret = regulator_check_voltage(c_rdevs[i], &tmp_min, &tmp_max);
+ if (ret < 0)
+ return ret;
+
+ highest_min_uV = max(highest_min_uV, tmp_min);
+
+ if (i == 0) {
+ desired_min_uV = tmp_min;
+ desired_max_uV = tmp_max;
+ }
+ }
+
+ /*
+ * Let target_uV be equal to the desired one if possible.
+ * If not, set it to minimum voltage, allowed by other coupled
+ * regulators.
+ */
+ target_uV = max(desired_min_uV, highest_min_uV - max_spread);
+
+ /*
+ * Find min and max voltages, which currently aren't violating
+ * max_spread.
+ */
+ for (i = 1; i < n_coupled; i++) {
+ int tmp_act;
+
+ if (!_regulator_is_enabled(c_rdevs[i]))
+ continue;
+
+ tmp_act = _regulator_get_voltage(c_rdevs[i]);
+ if (tmp_act < 0)
+ return tmp_act;
+
+ min_current_uV = min(tmp_act, min_current_uV);
+ max_current_uV = max(tmp_act, max_current_uV);
+ }
+
+ /* There aren't any other regulators enabled */
+ if (max_current_uV == 0) {
+ possible_uV = target_uV;
+ } else {
+ /*
+ * Correct target voltage, so as it currently isn't
+ * violating max_spread
+ */
+ possible_uV = max(target_uV, max_current_uV - max_spread);
+ possible_uV = min(possible_uV, min_current_uV + max_spread);
+ }
+
+ if (possible_uV > desired_max_uV)
+ return -EINVAL;
+
+ done = (possible_uV == target_uV);
+ desired_min_uV = possible_uV;
+finish:
+ /* Apply max_uV_step constraint if necessary */
+ if (state == PM_SUSPEND_ON) {
+ ret = regulator_limit_voltage_step(rdev, current_uV,
+ &desired_min_uV);
+ if (ret < 0)
+ return ret;
+
+ if (ret == 0)
+ done = false;
+ }
+
+ /* Set current_uV if wasn't done earlier in the code and if necessary */
+ if (n_coupled > 1 && *current_uV == -1) {
+
+ if (_regulator_is_enabled(rdev)) {
+ ret = _regulator_get_voltage(rdev);
+ if (ret < 0)
+ return ret;
+
+ *current_uV = ret;
+ } else {
+ *current_uV = desired_min_uV;
+ }
+ }
+
+ *min_uV = desired_min_uV;
+ *max_uV = desired_max_uV;
+
+ return done;
+}
+
+static int regulator_balance_voltage(struct regulator_dev *rdev,
+ suspend_state_t state)
+{
+ struct regulator_dev **c_rdevs;
+ struct regulator_dev *best_rdev;
+ struct coupling_desc *c_desc = &rdev->coupling_desc;
+ int i, ret, n_coupled, best_min_uV, best_max_uV, best_c_rdev;
+ bool best_c_rdev_done, c_rdev_done[MAX_COUPLED];
+ unsigned int delta, best_delta;
+
+ c_rdevs = c_desc->coupled_rdevs;
+ n_coupled = c_desc->n_coupled;
+
+ /*
+ * If system is in a state other than PM_SUSPEND_ON, don't check
+ * other coupled regulators.
+ */
+ if (state != PM_SUSPEND_ON)
+ n_coupled = 1;
+
+ if (c_desc->n_resolved < n_coupled) {
+ rdev_err(rdev, "Not all coupled regulators registered\n");
+ return -EPERM;
+ }
+
+ for (i = 0; i < n_coupled; i++)
+ c_rdev_done[i] = false;
+
+ /*
+ * Find the best possible voltage change on each loop. Leave the loop
+ * if there isn't any possible change.
+ */
+ do {
+ best_c_rdev_done = false;
+ best_delta = 0;
+ best_min_uV = 0;
+ best_max_uV = 0;
+ best_c_rdev = 0;
+ best_rdev = NULL;
+
+ /*
+ * Find highest difference between optimal voltage
+ * and current voltage.
+ */
+ for (i = 0; i < n_coupled; i++) {
+ /*
+ * optimal_uV is the best voltage that can be set for
+ * i-th regulator at the moment without violating
+ * max_spread constraint in order to balance
+ * the coupled voltages.
+ */
+ int optimal_uV = 0, optimal_max_uV = 0, current_uV = 0;
+
+ if (c_rdev_done[i])
+ continue;
+
+ ret = regulator_get_optimal_voltage(c_rdevs[i],
+ &current_uV,
+ &optimal_uV,
+ &optimal_max_uV,
+ state, n_coupled);
+ if (ret < 0)
+ goto out;
+
+ delta = abs(optimal_uV - current_uV);
+
+ if (delta && best_delta <= delta) {
+ best_c_rdev_done = ret;
+ best_delta = delta;
+ best_rdev = c_rdevs[i];
+ best_min_uV = optimal_uV;
+ best_max_uV = optimal_max_uV;
+ best_c_rdev = i;
+ }
+ }
+
+ /* Nothing to change, return successfully */
+ if (!best_rdev) {
+ ret = 0;
+ goto out;
+ }
+
+ ret = regulator_set_voltage_rdev(best_rdev, best_min_uV,
+ best_max_uV, state);
+
+ if (ret < 0)
+ goto out;
+
+ c_rdev_done[best_c_rdev] = best_c_rdev_done;
+
+ } while (n_coupled > 1);
+
+out:
return ret;
}
@@ -3146,14 +3692,15 @@ out2:
*/
int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
{
- int ret = 0;
+ struct ww_acquire_ctx ww_ctx;
+ int ret;
- regulator_lock_supply(regulator->rdev);
+ regulator_lock_dependent(regulator->rdev, &ww_ctx);
ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV,
PM_SUSPEND_ON);
- regulator_unlock_supply(regulator->rdev);
+ regulator_unlock_dependent(regulator->rdev, &ww_ctx);
return ret;
}
@@ -3225,18 +3772,19 @@ static int _regulator_set_suspend_voltage(struct regulator *regulator,
int regulator_set_suspend_voltage(struct regulator *regulator, int min_uV,
int max_uV, suspend_state_t state)
{
- int ret = 0;
+ struct ww_acquire_ctx ww_ctx;
+ int ret;
/* PM_SUSPEND_ON is handled by regulator_set_voltage() */
if (regulator_check_states(state) || state == PM_SUSPEND_ON)
return -EINVAL;
- regulator_lock_supply(regulator->rdev);
+ regulator_lock_dependent(regulator->rdev, &ww_ctx);
ret = _regulator_set_suspend_voltage(regulator, min_uV,
max_uV, state);
- regulator_unlock_supply(regulator->rdev);
+ regulator_unlock_dependent(regulator->rdev, &ww_ctx);
return ret;
}
@@ -3426,13 +3974,12 @@ static int _regulator_get_voltage(struct regulator_dev *rdev)
*/
int regulator_get_voltage(struct regulator *regulator)
{
+ struct ww_acquire_ctx ww_ctx;
int ret;
- regulator_lock_supply(regulator->rdev);
-
+ regulator_lock_dependent(regulator->rdev, &ww_ctx);
ret = _regulator_get_voltage(regulator->rdev);
-
- regulator_unlock_supply(regulator->rdev);
+ regulator_unlock_dependent(regulator->rdev, &ww_ctx);
return ret;
}
@@ -3650,16 +4197,30 @@ EXPORT_SYMBOL_GPL(regulator_get_error_flags);
* DRMS will sum the total requested load on the regulator and change
* to the most efficient operating mode if platform constraints allow.
*
+ * NOTE: when a regulator consumer requests to have a regulator
+ * disabled then any load that consumer requested no longer counts
+ * toward the total requested load. If the regulator is re-enabled
+ * then the previously requested load will start counting again.
+ *
+ * If a regulator is an always-on regulator then an individual consumer's
+ * load will still be removed if that consumer is fully disabled.
+ *
* On error a negative errno is returned.
*/
int regulator_set_load(struct regulator *regulator, int uA_load)
{
struct regulator_dev *rdev = regulator->rdev;
- int ret;
+ int old_uA_load;
+ int ret = 0;
regulator_lock(rdev);
+ old_uA_load = regulator->uA_load;
regulator->uA_load = uA_load;
- ret = drms_uA_update(rdev);
+ if (regulator->enable_count && old_uA_load != uA_load) {
+ ret = drms_uA_update(rdev);
+ if (ret < 0)
+ regulator->uA_load = old_uA_load;
+ }
regulator_unlock(rdev);
return ret;
@@ -3830,11 +4391,8 @@ int regulator_bulk_enable(int num_consumers,
int ret = 0;
for (i = 0; i < num_consumers; i++) {
- if (consumers[i].consumer->always_on)
- consumers[i].ret = 0;
- else
- async_schedule_domain(regulator_bulk_enable_async,
- &consumers[i], &async_domain);
+ async_schedule_domain(regulator_bulk_enable_async,
+ &consumers[i], &async_domain);
}
async_synchronize_full_domain(&async_domain);
@@ -3968,7 +4526,7 @@ EXPORT_SYMBOL_GPL(regulator_bulk_free);
int regulator_notifier_call_chain(struct regulator_dev *rdev,
unsigned long event, void *data)
{
- lockdep_assert_held_once(&rdev->mutex);
+ lockdep_assert_held_once(&rdev->mutex.base);
_notifier_call_chain(rdev, event, data);
return NOTIFY_DONE;
@@ -4070,10 +4628,6 @@ static umode_t regulator_attr_is_visible(struct kobject *kobj,
if (attr == &dev_attr_bypass.attr)
return ops->get_bypass ? mode : 0;
- /* some attributes are type-specific */
- if (attr == &dev_attr_requested_microamps.attr)
- return rdev->desc->type == REGULATOR_CURRENT ? mode : 0;
-
/* constraints need specific supporting methods */
if (attr == &dev_attr_min_microvolts.attr ||
attr == &dev_attr_max_microvolts.attr)
@@ -4157,7 +4711,7 @@ static int regulator_register_resolve_supply(struct device *dev, void *data)
return 0;
}
-static int regulator_fill_coupling_array(struct regulator_dev *rdev)
+static void regulator_resolve_coupling(struct regulator_dev *rdev)
{
struct coupling_desc *c_desc = &rdev->coupling_desc;
int n_coupled = c_desc->n_coupled;
@@ -4171,33 +4725,58 @@ static int regulator_fill_coupling_array(struct regulator_dev *rdev)
c_rdev = of_parse_coupled_regulator(rdev, i - 1);
- if (c_rdev) {
- c_desc->coupled_rdevs[i] = c_rdev;
- c_desc->n_resolved++;
- }
- }
+ if (!c_rdev)
+ continue;
- if (rdev->coupling_desc.n_resolved < n_coupled)
- return -1;
- else
- return 0;
+ regulator_lock(c_rdev);
+
+ c_desc->coupled_rdevs[i] = c_rdev;
+ c_desc->n_resolved++;
+
+ regulator_unlock(c_rdev);
+
+ regulator_resolve_coupling(c_rdev);
+ }
}
-static int regulator_register_fill_coupling_array(struct device *dev,
- void *data)
+static void regulator_remove_coupling(struct regulator_dev *rdev)
{
- struct regulator_dev *rdev = dev_to_rdev(dev);
+ struct coupling_desc *__c_desc, *c_desc = &rdev->coupling_desc;
+ struct regulator_dev *__c_rdev, *c_rdev;
+ unsigned int __n_coupled, n_coupled;
+ int i, k;
- if (!IS_ENABLED(CONFIG_OF))
- return 0;
+ n_coupled = c_desc->n_coupled;
- if (regulator_fill_coupling_array(rdev))
- rdev_dbg(rdev, "unable to resolve coupling\n");
+ for (i = 1; i < n_coupled; i++) {
+ c_rdev = c_desc->coupled_rdevs[i];
- return 0;
+ if (!c_rdev)
+ continue;
+
+ regulator_lock(c_rdev);
+
+ __c_desc = &c_rdev->coupling_desc;
+ __n_coupled = __c_desc->n_coupled;
+
+ for (k = 1; k < __n_coupled; k++) {
+ __c_rdev = __c_desc->coupled_rdevs[k];
+
+ if (__c_rdev == rdev) {
+ __c_desc->coupled_rdevs[k] = NULL;
+ __c_desc->n_resolved--;
+ break;
+ }
+ }
+
+ regulator_unlock(c_rdev);
+
+ c_desc->coupled_rdevs[i] = NULL;
+ c_desc->n_resolved--;
+ }
}
-static int regulator_resolve_coupling(struct regulator_dev *rdev)
+static int regulator_init_coupling(struct regulator_dev *rdev)
{
int n_phandles;
@@ -4237,13 +4816,6 @@ static int regulator_resolve_coupling(struct regulator_dev *rdev)
if (!of_check_coupling_data(rdev))
return -EPERM;
- /*
- * After everything has been checked, try to fill rdevs array
- * with pointers to regulators parsed from device tree. If some
- * regulators are not registered yet, retry in late init call
- */
- regulator_fill_coupling_array(rdev);
-
return 0;
}
@@ -4265,21 +4837,33 @@ regulator_register(const struct regulator_desc *regulator_desc,
struct regulator_config *config = NULL;
static atomic_t regulator_no = ATOMIC_INIT(-1);
struct regulator_dev *rdev;
+ bool dangling_cfg_gpiod = false;
+ bool dangling_of_gpiod = false;
struct device *dev;
int ret, i;
- if (regulator_desc == NULL || cfg == NULL)
+ if (cfg == NULL)
return ERR_PTR(-EINVAL);
+ if (cfg->ena_gpiod)
+ dangling_cfg_gpiod = true;
+ if (regulator_desc == NULL) {
+ ret = -EINVAL;
+ goto rinse;
+ }
dev = cfg->dev;
WARN_ON(!dev);
- if (regulator_desc->name == NULL || regulator_desc->ops == NULL)
- return ERR_PTR(-EINVAL);
+ if (regulator_desc->name == NULL || regulator_desc->ops == NULL) {
+ ret = -EINVAL;
+ goto rinse;
+ }
if (regulator_desc->type != REGULATOR_VOLTAGE &&
- regulator_desc->type != REGULATOR_CURRENT)
- return ERR_PTR(-EINVAL);
+ regulator_desc->type != REGULATOR_CURRENT) {
+ ret = -EINVAL;
+ goto rinse;
+ }
/* Only one of each should be implemented */
WARN_ON(regulator_desc->ops->get_voltage &&
@@ -4290,16 +4874,20 @@ regulator_register(const struct regulator_desc *regulator_desc,
/* If we're using selectors we must implement list_voltage. */
if (regulator_desc->ops->get_voltage_sel &&
!regulator_desc->ops->list_voltage) {
- return ERR_PTR(-EINVAL);
+ ret = -EINVAL;
+ goto rinse;
}
if (regulator_desc->ops->set_voltage_sel &&
!regulator_desc->ops->list_voltage) {
- return ERR_PTR(-EINVAL);
+ ret = -EINVAL;
+ goto rinse;
}
rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
- if (rdev == NULL)
- return ERR_PTR(-ENOMEM);
+ if (rdev == NULL) {
+ ret = -ENOMEM;
+ goto rinse;
+ }
/*
* Duplicate the config so the driver could override it after
@@ -4308,17 +4896,28 @@ regulator_register(const struct regulator_desc *regulator_desc,
config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL);
if (config == NULL) {
kfree(rdev);
- return ERR_PTR(-ENOMEM);
+ ret = -ENOMEM;
+ goto rinse;
}
init_data = regulator_of_get_init_data(dev, regulator_desc, config,
&rdev->dev.of_node);
+ /*
+ * We need to keep track of any GPIO descriptor coming from the
+ * device tree until we have handled it over to the core. If the
+ * config that was passed in to this function DOES NOT contain
+ * a descriptor, and the config after this call DOES contain
+ * a descriptor, we definitely got one from parsing the device
+ * tree.
+ */
+ if (!cfg->ena_gpiod && config->ena_gpiod)
+ dangling_of_gpiod = true;
if (!init_data) {
init_data = config->init_data;
rdev->dev.of_node = of_node_get(config->of_node);
}
- mutex_init(&rdev->mutex);
+ ww_mutex_init(&rdev->mutex, &regulator_ww_class);
rdev->reg_data = config->driver_data;
rdev->owner = regulator_desc->owner;
rdev->desc = regulator_desc;
@@ -4340,17 +4939,18 @@ regulator_register(const struct regulator_desc *regulator_desc,
goto clean;
}
- if (config->ena_gpiod ||
- ((config->ena_gpio || config->ena_gpio_initialized) &&
- gpio_is_valid(config->ena_gpio))) {
+ if (config->ena_gpiod) {
mutex_lock(&regulator_list_mutex);
ret = regulator_ena_gpio_request(rdev, config);
mutex_unlock(&regulator_list_mutex);
if (ret != 0) {
- rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
- config->ena_gpio, ret);
+ rdev_err(rdev, "Failed to request enable GPIO: %d\n",
+ ret);
goto clean;
}
+ /* The regulator core took over the GPIO descriptor */
+ dangling_cfg_gpiod = false;
+ dangling_of_gpiod = false;
}
/* register with sysfs */
@@ -4380,11 +4980,8 @@ regulator_register(const struct regulator_desc *regulator_desc,
if (ret < 0)
goto wash;
- mutex_lock(&regulator_list_mutex);
- ret = regulator_resolve_coupling(rdev);
- mutex_unlock(&regulator_list_mutex);
-
- if (ret != 0)
+ ret = regulator_init_coupling(rdev);
+ if (ret < 0)
goto wash;
/* add consumers devices */
@@ -4418,6 +5015,11 @@ regulator_register(const struct regulator_desc *regulator_desc,
rdev_init_debugfs(rdev);
+ /* try to resolve regulators coupling since a new one was registered */
+ mutex_lock(&regulator_list_mutex);
+ regulator_resolve_coupling(rdev);
+ mutex_unlock(&regulator_list_mutex);
+
/* try to resolve regulators supply since a new one was registered */
class_for_each_device(&regulator_class, NULL, NULL,
regulator_register_resolve_supply);
@@ -4434,8 +5036,13 @@ wash:
regulator_ena_gpio_free(rdev);
mutex_unlock(&regulator_list_mutex);
clean:
+ if (dangling_of_gpiod)
+ gpiod_put(config->ena_gpiod);
kfree(rdev);
kfree(config);
+rinse:
+ if (dangling_cfg_gpiod)
+ gpiod_put(cfg->ena_gpiod);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(regulator_register);
@@ -4456,15 +5063,19 @@ void regulator_unregister(struct regulator_dev *rdev)
regulator_disable(rdev->supply);
regulator_put(rdev->supply);
}
+
mutex_lock(&regulator_list_mutex);
+
debugfs_remove_recursive(rdev->debugfs);
flush_work(&rdev->disable_work.work);
WARN_ON(rdev->open_count);
+ regulator_remove_coupling(rdev);
unset_regulator_supplies(rdev);
list_del(&rdev->list);
regulator_ena_gpio_free(rdev);
- mutex_unlock(&regulator_list_mutex);
device_unregister(&rdev->dev);
+
+ mutex_unlock(&regulator_list_mutex);
}
EXPORT_SYMBOL_GPL(regulator_unregister);
@@ -4602,6 +5213,12 @@ struct device *rdev_get_dev(struct regulator_dev *rdev)
}
EXPORT_SYMBOL_GPL(rdev_get_dev);
+struct regmap *rdev_get_regmap(struct regulator_dev *rdev)
+{
+ return rdev->regmap;
+}
+EXPORT_SYMBOL_GPL(rdev_get_regmap);
+
void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data)
{
return reg_init_data->driver_data;
@@ -4621,23 +5238,8 @@ static int supply_map_show(struct seq_file *sf, void *data)
return 0;
}
+DEFINE_SHOW_ATTRIBUTE(supply_map);
-static int supply_map_open(struct inode *inode, struct file *file)
-{
- return single_open(file, supply_map_show, inode->i_private);
-}
-#endif
-
-static const struct file_operations supply_map_fops = {
-#ifdef CONFIG_DEBUG_FS
- .open = supply_map_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-#endif
-};
-
-#ifdef CONFIG_DEBUG_FS
struct summary_data {
struct seq_file *s;
struct regulator_dev *parent;
@@ -4672,8 +5274,6 @@ static void regulator_summary_show_subtree(struct seq_file *s,
if (!rdev)
return;
- regulator_lock_nested(rdev, level);
-
opmode = _regulator_get_mode_unlocked(rdev);
seq_printf(s, "%*s%-*s %3d %4d %6d %7s ",
level * 3 + 1, "",
@@ -4712,8 +5312,11 @@ static void regulator_summary_show_subtree(struct seq_file *s,
switch (rdev->desc->type) {
case REGULATOR_VOLTAGE:
- seq_printf(s, "%37dmA %5dmV %5dmV",
+ seq_printf(s, "%3d %33dmA%c%5dmV %5dmV",
+ consumer->enable_count,
consumer->uA_load / 1000,
+ consumer->uA_load && !consumer->enable_count ?
+ '*' : ' ',
consumer->voltage[PM_SUSPEND_ON].min_uV / 1000,
consumer->voltage[PM_SUSPEND_ON].max_uV / 1000);
break;
@@ -4730,8 +5333,105 @@ static void regulator_summary_show_subtree(struct seq_file *s,
class_for_each_device(&regulator_class, NULL, &summary_data,
regulator_summary_show_children);
+}
+
+struct summary_lock_data {
+ struct ww_acquire_ctx *ww_ctx;
+ struct regulator_dev **new_contended_rdev;
+ struct regulator_dev **old_contended_rdev;
+};
+
+static int regulator_summary_lock_one(struct device *dev, void *data)
+{
+ struct regulator_dev *rdev = dev_to_rdev(dev);
+ struct summary_lock_data *lock_data = data;
+ int ret = 0;
+
+ if (rdev != *lock_data->old_contended_rdev) {
+ ret = regulator_lock_nested(rdev, lock_data->ww_ctx);
+
+ if (ret == -EDEADLK)
+ *lock_data->new_contended_rdev = rdev;
+ else
+ WARN_ON_ONCE(ret);
+ } else {
+ *lock_data->old_contended_rdev = NULL;
+ }
+
+ return ret;
+}
+
+static int regulator_summary_unlock_one(struct device *dev, void *data)
+{
+ struct regulator_dev *rdev = dev_to_rdev(dev);
+ struct summary_lock_data *lock_data = data;
+
+ if (lock_data) {
+ if (rdev == *lock_data->new_contended_rdev)
+ return -EDEADLK;
+ }
regulator_unlock(rdev);
+
+ return 0;
+}
+
+static int regulator_summary_lock_all(struct ww_acquire_ctx *ww_ctx,
+ struct regulator_dev **new_contended_rdev,
+ struct regulator_dev **old_contended_rdev)
+{
+ struct summary_lock_data lock_data;
+ int ret;
+
+ lock_data.ww_ctx = ww_ctx;
+ lock_data.new_contended_rdev = new_contended_rdev;
+ lock_data.old_contended_rdev = old_contended_rdev;
+
+ ret = class_for_each_device(&regulator_class, NULL, &lock_data,
+ regulator_summary_lock_one);
+ if (ret)
+ class_for_each_device(&regulator_class, NULL, &lock_data,
+ regulator_summary_unlock_one);
+
+ return ret;
+}
+
+static void regulator_summary_lock(struct ww_acquire_ctx *ww_ctx)
+{
+ struct regulator_dev *new_contended_rdev = NULL;
+ struct regulator_dev *old_contended_rdev = NULL;
+ int err;
+
+ mutex_lock(&regulator_list_mutex);
+
+ ww_acquire_init(ww_ctx, &regulator_ww_class);
+
+ do {
+ if (new_contended_rdev) {
+ ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx);
+ old_contended_rdev = new_contended_rdev;
+ old_contended_rdev->ref_cnt++;
+ }
+
+ err = regulator_summary_lock_all(ww_ctx,
+ &new_contended_rdev,
+ &old_contended_rdev);
+
+ if (old_contended_rdev)
+ regulator_unlock(old_contended_rdev);
+
+ } while (err == -EDEADLK);
+
+ ww_acquire_done(ww_ctx);
+}
+
+static void regulator_summary_unlock(struct ww_acquire_ctx *ww_ctx)
+{
+ class_for_each_device(&regulator_class, NULL, NULL,
+ regulator_summary_unlock_one);
+ ww_acquire_fini(ww_ctx);
+
+ mutex_unlock(&regulator_list_mutex);
}
static int regulator_summary_show_roots(struct device *dev, void *data)
@@ -4747,29 +5447,22 @@ static int regulator_summary_show_roots(struct device *dev, void *data)
static int regulator_summary_show(struct seq_file *s, void *data)
{
+ struct ww_acquire_ctx ww_ctx;
+
seq_puts(s, " regulator use open bypass opmode voltage current min max\n");
seq_puts(s, "---------------------------------------------------------------------------------------\n");
+ regulator_summary_lock(&ww_ctx);
+
class_for_each_device(&regulator_class, NULL, s,
regulator_summary_show_roots);
- return 0;
-}
+ regulator_summary_unlock(&ww_ctx);
-static int regulator_summary_open(struct inode *inode, struct file *file)
-{
- return single_open(file, regulator_summary_show, inode->i_private);
+ return 0;
}
-#endif
-
-static const struct file_operations regulator_summary_fops = {
-#ifdef CONFIG_DEBUG_FS
- .open = regulator_summary_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-#endif
-};
+DEFINE_SHOW_ATTRIBUTE(regulator_summary);
+#endif /* CONFIG_DEBUG_FS */
static int __init regulator_init(void)
{
@@ -4781,12 +5474,13 @@ static int __init regulator_init(void)
if (!debugfs_root)
pr_warn("regulator: Failed to create debugfs directory\n");
+#ifdef CONFIG_DEBUG_FS
debugfs_create_file("supply_map", 0444, debugfs_root, NULL,
&supply_map_fops);
debugfs_create_file("regulator_summary", 0444, debugfs_root,
NULL, &regulator_summary_fops);
-
+#endif
regulator_dummy_init();
return ret;
@@ -4873,9 +5567,6 @@ static int __init regulator_init_complete(void)
class_for_each_device(&regulator_class, NULL, NULL,
regulator_late_cleanup);
- class_for_each_device(&regulator_class, NULL, NULL,
- regulator_register_fill_coupling_array);
-
return 0;
}
late_initcall_sync(regulator_init_complete);
diff --git a/drivers/regulator/cpcap-regulator.c b/drivers/regulator/cpcap-regulator.c
index 2131457937b7..e7dab5c4d1d1 100644
--- a/drivers/regulator/cpcap-regulator.c
+++ b/drivers/regulator/cpcap-regulator.c
@@ -100,12 +100,11 @@ struct cpcap_regulator {
struct regulator_desc rdesc;
const u16 assign_reg;
const u16 assign_mask;
- const u16 vsel_shift;
};
#define CPCAP_REG(_ID, reg, assignment_reg, assignment_mask, val_tbl, \
- mode_mask, volt_mask, volt_shft, \
- mode_val, off_val, volt_trans_time) { \
+ mode_mask, volt_mask, mode_val, off_val, \
+ volt_trans_time) { \
.rdesc = { \
.name = #_ID, \
.of_match = of_match_ptr(#_ID), \
@@ -127,7 +126,6 @@ struct cpcap_regulator {
}, \
.assign_reg = (assignment_reg), \
.assign_mask = (assignment_mask), \
- .vsel_shift = (volt_shft), \
}
struct cpcap_ddata {
@@ -336,155 +334,155 @@ static const unsigned int vaudio_val_tbl[] = { 0, 2775000, };
* SW1 to SW4 and SW6 seems to be unused for mapphone. Note that VSIM and
* VSIMCARD have a shared resource assignment bit.
*/
-static struct cpcap_regulator omap4_regulators[] = {
+static const struct cpcap_regulator omap4_regulators[] = {
CPCAP_REG(SW1, CPCAP_REG_S1C1, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW1_SEL, unknown_val_tbl,
- 0, 0, 0, 0, 0, 0),
+ 0, 0, 0, 0, 0),
CPCAP_REG(SW2, CPCAP_REG_S2C1, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW2_SEL, unknown_val_tbl,
- 0, 0, 0, 0, 0, 0),
+ 0, 0, 0, 0, 0),
CPCAP_REG(SW3, CPCAP_REG_S3C, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW3_SEL, unknown_val_tbl,
- 0, 0, 0, 0, 0, 0),
+ 0, 0, 0, 0, 0),
CPCAP_REG(SW4, CPCAP_REG_S4C1, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW4_SEL, unknown_val_tbl,
- 0, 0, 0, 0, 0, 0),
+ 0, 0, 0, 0, 0),
CPCAP_REG(SW5, CPCAP_REG_S5C, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW5_SEL, sw5_val_tbl,
- 0x28, 0, 0, 0x20 | CPCAP_REG_OFF_MODE_SEC, 0, 0),
+ 0x28, 0, 0x20 | CPCAP_REG_OFF_MODE_SEC, 0, 0),
CPCAP_REG(SW6, CPCAP_REG_S6C, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW6_SEL, unknown_val_tbl,
- 0, 0, 0, 0, 0, 0),
+ 0, 0, 0, 0, 0),
CPCAP_REG(VCAM, CPCAP_REG_VCAMC, CPCAP_REG_ASSIGN2,
CPCAP_BIT_VCAM_SEL, vcam_val_tbl,
- 0x87, 0x30, 4, 0x3, 0, 420),
+ 0x87, 0x30, 0x3, 0, 420),
CPCAP_REG(VCSI, CPCAP_REG_VCSIC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VCSI_SEL, vcsi_val_tbl,
- 0x47, 0x10, 4, 0x43, 0x41, 350),
+ 0x47, 0x10, 0x43, 0x41, 350),
CPCAP_REG(VDAC, CPCAP_REG_VDACC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VDAC_SEL, vdac_val_tbl,
- 0x87, 0x30, 4, 0x3, 0, 420),
+ 0x87, 0x30, 0x3, 0, 420),
CPCAP_REG(VDIG, CPCAP_REG_VDIGC, CPCAP_REG_ASSIGN2,
CPCAP_BIT_VDIG_SEL, vdig_val_tbl,
- 0x87, 0x30, 4, 0x82, 0, 420),
+ 0x87, 0x30, 0x82, 0, 420),
CPCAP_REG(VFUSE, CPCAP_REG_VFUSEC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VFUSE_SEL, vfuse_val_tbl,
- 0x80, 0xf, 0, 0x80, 0, 420),
+ 0x80, 0xf, 0x80, 0, 420),
CPCAP_REG(VHVIO, CPCAP_REG_VHVIOC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VHVIO_SEL, vhvio_val_tbl,
- 0x17, 0, 0, 0, 0x12, 0),
+ 0x17, 0, 0, 0x12, 0),
CPCAP_REG(VSDIO, CPCAP_REG_VSDIOC, CPCAP_REG_ASSIGN2,
CPCAP_BIT_VSDIO_SEL, vsdio_val_tbl,
- 0x87, 0x38, 3, 0x82, 0, 420),
+ 0x87, 0x38, 0x82, 0, 420),
CPCAP_REG(VPLL, CPCAP_REG_VPLLC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VPLL_SEL, vpll_val_tbl,
- 0x43, 0x18, 3, 0x2, 0, 420),
+ 0x43, 0x18, 0x2, 0, 420),
CPCAP_REG(VRF1, CPCAP_REG_VRF1C, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VRF1_SEL, vrf1_val_tbl,
- 0xac, 0x2, 1, 0x4, 0, 10),
+ 0xac, 0x2, 0x4, 0, 10),
CPCAP_REG(VRF2, CPCAP_REG_VRF2C, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VRF2_SEL, vrf2_val_tbl,
- 0x23, 0x8, 3, 0, 0, 10),
+ 0x23, 0x8, 0, 0, 10),
CPCAP_REG(VRFREF, CPCAP_REG_VRFREFC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VRFREF_SEL, vrfref_val_tbl,
- 0x23, 0x8, 3, 0, 0, 420),
+ 0x23, 0x8, 0, 0, 420),
CPCAP_REG(VWLAN1, CPCAP_REG_VWLAN1C, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VWLAN1_SEL, vwlan1_val_tbl,
- 0x47, 0x10, 4, 0, 0, 420),
+ 0x47, 0x10, 0, 0, 420),
CPCAP_REG(VWLAN2, CPCAP_REG_VWLAN2C, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VWLAN2_SEL, vwlan2_val_tbl,
- 0x20c, 0xc0, 6, 0x20c, 0, 420),
+ 0x20c, 0xc0, 0x20c, 0, 420),
CPCAP_REG(VSIM, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3,
0xffff, vsim_val_tbl,
- 0x23, 0x8, 3, 0x3, 0, 420),
+ 0x23, 0x8, 0x3, 0, 420),
CPCAP_REG(VSIMCARD, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3,
0xffff, vsimcard_val_tbl,
- 0x1e80, 0x8, 3, 0x1e00, 0, 420),
+ 0x1e80, 0x8, 0x1e00, 0, 420),
CPCAP_REG(VVIB, CPCAP_REG_VVIBC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VVIB_SEL, vvib_val_tbl,
- 0x1, 0xc, 2, 0x1, 0, 500),
+ 0x1, 0xc, 0x1, 0, 500),
CPCAP_REG(VUSB, CPCAP_REG_VUSBC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VUSB_SEL, vusb_val_tbl,
- 0x11c, 0x40, 6, 0xc, 0, 0),
+ 0x11c, 0x40, 0xc, 0, 0),
CPCAP_REG(VAUDIO, CPCAP_REG_VAUDIOC, CPCAP_REG_ASSIGN4,
CPCAP_BIT_VAUDIO_SEL, vaudio_val_tbl,
- 0x16, 0x1, 0, 0x4, 0, 0),
+ 0x16, 0x1, 0x4, 0, 0),
{ /* sentinel */ },
};
-static struct cpcap_regulator xoom_regulators[] = {
+static const struct cpcap_regulator xoom_regulators[] = {
CPCAP_REG(SW1, CPCAP_REG_S1C1, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW1_SEL, unknown_val_tbl,
- 0, 0, 0, 0, 0, 0),
+ 0, 0, 0, 0, 0),
CPCAP_REG(SW2, CPCAP_REG_S2C1, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW2_SEL, sw2_sw4_val_tbl,
- 0xf00, 0x7f, 0, 0x800, 0, 120),
+ 0xf00, 0x7f, 0x800, 0, 120),
CPCAP_REG(SW3, CPCAP_REG_S3C, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW3_SEL, unknown_val_tbl,
- 0, 0, 0, 0, 0, 0),
+ 0, 0, 0, 0, 0),
CPCAP_REG(SW4, CPCAP_REG_S4C1, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW4_SEL, sw2_sw4_val_tbl,
- 0xf00, 0x7f, 0, 0x900, 0, 100),
+ 0xf00, 0x7f, 0x900, 0, 100),
CPCAP_REG(SW5, CPCAP_REG_S5C, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW5_SEL, sw5_val_tbl,
- 0x2a, 0, 0, 0x22, 0, 0),
+ 0x2a, 0, 0x22, 0, 0),
CPCAP_REG(SW6, CPCAP_REG_S6C, CPCAP_REG_ASSIGN2,
CPCAP_BIT_SW6_SEL, unknown_val_tbl,
- 0, 0, 0, 0, 0, 0),
+ 0, 0, 0, 0, 0),
CPCAP_REG(VCAM, CPCAP_REG_VCAMC, CPCAP_REG_ASSIGN2,
CPCAP_BIT_VCAM_SEL, vcam_val_tbl,
- 0x87, 0x30, 4, 0x7, 0, 420),
+ 0x87, 0x30, 0x7, 0, 420),
CPCAP_REG(VCSI, CPCAP_REG_VCSIC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VCSI_SEL, vcsi_val_tbl,
- 0x47, 0x10, 4, 0x7, 0, 350),
+ 0x47, 0x10, 0x7, 0, 350),
CPCAP_REG(VDAC, CPCAP_REG_VDACC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VDAC_SEL, vdac_val_tbl,
- 0x87, 0x30, 4, 0x3, 0, 420),
+ 0x87, 0x30, 0x3, 0, 420),
CPCAP_REG(VDIG, CPCAP_REG_VDIGC, CPCAP_REG_ASSIGN2,
CPCAP_BIT_VDIG_SEL, vdig_val_tbl,
- 0x87, 0x30, 4, 0x5, 0, 420),
+ 0x87, 0x30, 0x5, 0, 420),
CPCAP_REG(VFUSE, CPCAP_REG_VFUSEC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VFUSE_SEL, vfuse_val_tbl,
- 0x80, 0xf, 0, 0x80, 0, 420),
+ 0x80, 0xf, 0x80, 0, 420),
CPCAP_REG(VHVIO, CPCAP_REG_VHVIOC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VHVIO_SEL, vhvio_val_tbl,
- 0x17, 0, 0, 0x2, 0, 0),
+ 0x17, 0, 0x2, 0, 0),
CPCAP_REG(VSDIO, CPCAP_REG_VSDIOC, CPCAP_REG_ASSIGN2,
CPCAP_BIT_VSDIO_SEL, vsdio_val_tbl,
- 0x87, 0x38, 3, 0x2, 0, 420),
+ 0x87, 0x38, 0x2, 0, 420),
CPCAP_REG(VPLL, CPCAP_REG_VPLLC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VPLL_SEL, vpll_val_tbl,
- 0x43, 0x18, 3, 0x1, 0, 420),
+ 0x43, 0x18, 0x1, 0, 420),
CPCAP_REG(VRF1, CPCAP_REG_VRF1C, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VRF1_SEL, vrf1_val_tbl,
- 0xac, 0x2, 1, 0xc, 0, 10),
+ 0xac, 0x2, 0xc, 0, 10),
CPCAP_REG(VRF2, CPCAP_REG_VRF2C, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VRF2_SEL, vrf2_val_tbl,
- 0x23, 0x8, 3, 0x3, 0, 10),
+ 0x23, 0x8, 0x3, 0, 10),
CPCAP_REG(VRFREF, CPCAP_REG_VRFREFC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VRFREF_SEL, vrfref_val_tbl,
- 0x23, 0x8, 3, 0x3, 0, 420),
+ 0x23, 0x8, 0x3, 0, 420),
CPCAP_REG(VWLAN1, CPCAP_REG_VWLAN1C, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VWLAN1_SEL, vwlan1_val_tbl,
- 0x47, 0x10, 4, 0x5, 0, 420),
+ 0x47, 0x10, 0x5, 0, 420),
CPCAP_REG(VWLAN2, CPCAP_REG_VWLAN2C, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VWLAN2_SEL, vwlan2_val_tbl,
- 0x20c, 0xc0, 6, 0x8, 0, 420),
+ 0x20c, 0xc0, 0x8, 0, 420),
CPCAP_REG(VSIM, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3,
0xffff, vsim_val_tbl,
- 0x23, 0x8, 3, 0x3, 0, 420),
+ 0x23, 0x8, 0x3, 0, 420),
CPCAP_REG(VSIMCARD, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3,
0xffff, vsimcard_val_tbl,
- 0x1e80, 0x8, 3, 0x1e00, 0, 420),
+ 0x1e80, 0x8, 0x1e00, 0, 420),
CPCAP_REG(VVIB, CPCAP_REG_VVIBC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VVIB_SEL, vvib_val_tbl,
- 0x1, 0xc, 2, 0, 0x1, 500),
+ 0x1, 0xc, 0, 0x1, 500),
CPCAP_REG(VUSB, CPCAP_REG_VUSBC, CPCAP_REG_ASSIGN3,
CPCAP_BIT_VUSB_SEL, vusb_val_tbl,
- 0x11c, 0x40, 6, 0xc, 0, 0),
+ 0x11c, 0x40, 0xc, 0, 0),
CPCAP_REG(VAUDIO, CPCAP_REG_VAUDIOC, CPCAP_REG_ASSIGN4,
CPCAP_BIT_VAUDIO_SEL, vaudio_val_tbl,
- 0x16, 0x1, 0, 0x4, 0, 0),
+ 0x16, 0x1, 0x4, 0, 0),
{ /* sentinel */ },
};
diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c
index 37e4025203e3..cefa3558236d 100644
--- a/drivers/regulator/da9052-regulator.c
+++ b/drivers/regulator/da9052-regulator.c
@@ -290,10 +290,10 @@ static const struct regulator_ops da9052_ldo_ops = {
.disable = regulator_disable_regmap,
};
-#define DA9052_LDO(_id, step, min, max, sbits, ebits, abits) \
+#define DA9052_LDO(_id, _name, step, min, max, sbits, ebits, abits) \
{\
.reg_desc = {\
- .name = #_id,\
+ .name = #_name,\
.ops = &da9052_ldo_ops,\
.type = REGULATOR_VOLTAGE,\
.id = DA9052_ID_##_id,\
@@ -310,10 +310,10 @@ static const struct regulator_ops da9052_ldo_ops = {
.activate_bit = (abits),\
}
-#define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \
+#define DA9052_DCDC(_id, _name, step, min, max, sbits, ebits, abits) \
{\
.reg_desc = {\
- .name = #_id,\
+ .name = #_name,\
.ops = &da9052_dcdc_ops,\
.type = REGULATOR_VOLTAGE,\
.id = DA9052_ID_##_id,\
@@ -331,37 +331,37 @@ static const struct regulator_ops da9052_ldo_ops = {
}
static struct da9052_regulator_info da9052_regulator_info[] = {
- DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
- DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
- DA9052_DCDC(BUCK3, 25, 950, 2525, 6, 6, DA9052_SUPPLY_VBMEMGO),
- DA9052_DCDC(BUCK4, 50, 1800, 3600, 5, 6, 0),
- DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0),
- DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
- DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
- DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0),
- DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0),
- DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0),
+ DA9052_DCDC(BUCK1, buck1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
+ DA9052_DCDC(BUCK2, buck2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
+ DA9052_DCDC(BUCK3, buck3, 25, 950, 2525, 6, 6, DA9052_SUPPLY_VBMEMGO),
+ DA9052_DCDC(BUCK4, buck4, 50, 1800, 3600, 5, 6, 0),
+ DA9052_LDO(LDO1, ldo1, 50, 600, 1800, 5, 6, 0),
+ DA9052_LDO(LDO2, ldo2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
+ DA9052_LDO(LDO3, ldo3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
+ DA9052_LDO(LDO4, ldo4, 25, 1725, 3300, 6, 6, 0),
+ DA9052_LDO(LDO5, ldo5, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO6, ldo6, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO7, ldo7, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO8, ldo8, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO9, ldo9, 50, 1250, 3650, 6, 6, 0),
+ DA9052_LDO(LDO10, ldo10, 50, 1200, 3600, 6, 6, 0),
};
static struct da9052_regulator_info da9053_regulator_info[] = {
- DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
- DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
- DA9052_DCDC(BUCK3, 25, 950, 2525, 6, 6, DA9052_SUPPLY_VBMEMGO),
- DA9052_DCDC(BUCK4, 25, 950, 2525, 6, 6, 0),
- DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0),
- DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
- DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
- DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0),
- DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0),
- DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0),
- DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0),
+ DA9052_DCDC(BUCK1, buck1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
+ DA9052_DCDC(BUCK2, buck2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
+ DA9052_DCDC(BUCK3, buck3, 25, 950, 2525, 6, 6, DA9052_SUPPLY_VBMEMGO),
+ DA9052_DCDC(BUCK4, buck4, 25, 950, 2525, 6, 6, 0),
+ DA9052_LDO(LDO1, ldo1, 50, 600, 1800, 5, 6, 0),
+ DA9052_LDO(LDO2, ldo2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
+ DA9052_LDO(LDO3, ldo3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
+ DA9052_LDO(LDO4, ldo4, 25, 1725, 3300, 6, 6, 0),
+ DA9052_LDO(LDO5, ldo5, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO6, ldo6, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO7, ldo7, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO8, ldo8, 50, 1200, 3600, 6, 6, 0),
+ DA9052_LDO(LDO9, ldo9, 50, 1250, 3650, 6, 6, 0),
+ DA9052_LDO(LDO10, ldo10, 50, 1200, 3600, 6, 6, 0),
};
static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
@@ -435,7 +435,7 @@ static int da9052_regulator_probe(struct platform_device *pdev)
return -ENODEV;
for_each_child_of_node(nproot, np) {
- if (!of_node_cmp(np->name,
+ if (of_node_name_eq(np,
regulator->info->reg_desc.name)) {
config.init_data = of_get_regulator_init_data(
&pdev->dev, np,
diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c
index 588c3d2445cf..3c6fac793658 100644
--- a/drivers/regulator/da9055-regulator.c
+++ b/drivers/regulator/da9055-regulator.c
@@ -48,7 +48,9 @@
#define DA9055_ID_LDO6 7
/* DA9055 BUCK current limit */
-static const int da9055_current_limits[] = { 500000, 600000, 700000, 800000 };
+static const unsigned int da9055_current_limits[] = {
+ 500000, 600000, 700000, 800000
+};
struct da9055_conf_reg {
int reg;
@@ -169,39 +171,6 @@ static int da9055_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
val << volt.sl_shift);
}
-static int da9055_buck_get_current_limit(struct regulator_dev *rdev)
-{
- struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
- struct da9055_regulator_info *info = regulator->info;
- int ret;
-
- ret = da9055_reg_read(regulator->da9055, DA9055_REG_BUCK_LIM);
- if (ret < 0)
- return ret;
-
- ret &= info->mode.mask;
- return da9055_current_limits[ret >> info->mode.shift];
-}
-
-static int da9055_buck_set_current_limit(struct regulator_dev *rdev, int min_uA,
- int max_uA)
-{
- struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
- struct da9055_regulator_info *info = regulator->info;
- int i;
-
- for (i = ARRAY_SIZE(da9055_current_limits) - 1; i >= 0; i--) {
- if ((min_uA <= da9055_current_limits[i]) &&
- (da9055_current_limits[i] <= max_uA))
- return da9055_reg_update(regulator->da9055,
- DA9055_REG_BUCK_LIM,
- info->mode.mask,
- i << info->mode.shift);
- }
-
- return -EINVAL;
-}
-
static int da9055_regulator_get_voltage_sel(struct regulator_dev *rdev)
{
struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
@@ -329,8 +298,8 @@ static const struct regulator_ops da9055_buck_ops = {
.get_mode = da9055_buck_get_mode,
.set_mode = da9055_buck_set_mode,
- .get_current_limit = da9055_buck_get_current_limit,
- .set_current_limit = da9055_buck_set_current_limit,
+ .get_current_limit = regulator_get_current_limit_regmap,
+ .set_current_limit = regulator_set_current_limit_regmap,
.get_voltage_sel = da9055_regulator_get_voltage_sel,
.set_voltage_sel = da9055_regulator_set_voltage_sel,
@@ -407,6 +376,10 @@ static const struct regulator_ops da9055_ldo_ops = {
.uV_step = (step) * 1000,\
.linear_min_sel = (voffset),\
.owner = THIS_MODULE,\
+ .curr_table = da9055_current_limits,\
+ .n_current_limits = ARRAY_SIZE(da9055_current_limits),\
+ .csel_reg = DA9055_REG_BUCK_LIM,\
+ .csel_mask = (mbits),\
},\
.conf = {\
.reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
@@ -457,7 +430,6 @@ static int da9055_gpio_init(struct da9055_regulator *regulator,
int gpio_mux = pdata->gpio_ren[id];
config->ena_gpiod = pdata->ena_gpiods[id];
- config->ena_gpio_invert = 1;
/*
* GPI pin is muxed with regulator to control the
diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c
index 34a70d9dc450..b064d8a19d4c 100644
--- a/drivers/regulator/da9062-regulator.c
+++ b/drivers/regulator/da9062-regulator.c
@@ -126,7 +126,7 @@ static int da9062_set_current_limit(struct regulator_dev *rdev,
const struct da9062_regulator_info *rinfo = regl->info;
int n, tval;
- for (n = 0; n < rinfo->n_current_limits; n++) {
+ for (n = rinfo->n_current_limits - 1; n >= 0; n--) {
tval = rinfo->current_limits[n];
if (tval >= min_ua && tval <= max_ua)
return regmap_field_write(regl->ilimit, n);
@@ -992,7 +992,6 @@ static int da9062_regulator_probe(struct platform_device *pdev)
struct regulator_config config = { };
const struct da9062_regulator_info *rinfo;
int irq, n, ret;
- size_t size;
int max_regulators;
switch (chip->chip_type) {
@@ -1010,9 +1009,8 @@ static int da9062_regulator_probe(struct platform_device *pdev)
}
/* Allocate memory required by usable regulators */
- size = sizeof(struct da9062_regulators) +
- max_regulators * sizeof(struct da9062_regulator);
- regulators = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+ regulators = devm_kzalloc(&pdev->dev, struct_size(regulators, regulator,
+ max_regulators), GFP_KERNEL);
if (!regulators)
return -ENOMEM;
@@ -1029,31 +1027,50 @@ static int da9062_regulator_probe(struct platform_device *pdev)
regl->desc.type = REGULATOR_VOLTAGE;
regl->desc.owner = THIS_MODULE;
- if (regl->info->mode.reg)
+ if (regl->info->mode.reg) {
regl->mode = devm_regmap_field_alloc(
&pdev->dev,
chip->regmap,
regl->info->mode);
- if (regl->info->suspend.reg)
+ if (IS_ERR(regl->mode))
+ return PTR_ERR(regl->mode);
+ }
+
+ if (regl->info->suspend.reg) {
regl->suspend = devm_regmap_field_alloc(
&pdev->dev,
chip->regmap,
regl->info->suspend);
- if (regl->info->sleep.reg)
+ if (IS_ERR(regl->suspend))
+ return PTR_ERR(regl->suspend);
+ }
+
+ if (regl->info->sleep.reg) {
regl->sleep = devm_regmap_field_alloc(
&pdev->dev,
chip->regmap,
regl->info->sleep);
- if (regl->info->suspend_sleep.reg)
+ if (IS_ERR(regl->sleep))
+ return PTR_ERR(regl->sleep);
+ }
+
+ if (regl->info->suspend_sleep.reg) {
regl->suspend_sleep = devm_regmap_field_alloc(
&pdev->dev,
chip->regmap,
regl->info->suspend_sleep);
- if (regl->info->ilimit.reg)
+ if (IS_ERR(regl->suspend_sleep))
+ return PTR_ERR(regl->suspend_sleep);
+ }
+
+ if (regl->info->ilimit.reg) {
regl->ilimit = devm_regmap_field_alloc(
&pdev->dev,
chip->regmap,
regl->info->ilimit);
+ if (IS_ERR(regl->ilimit))
+ return PTR_ERR(regl->ilimit);
+ }
/* Register regulator */
memset(&config, 0, sizeof(config));
diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c
index 8cbcd2a3eb20..2b0c7a85306a 100644
--- a/drivers/regulator/da9063-regulator.c
+++ b/drivers/regulator/da9063-regulator.c
@@ -167,7 +167,7 @@ static int da9063_set_current_limit(struct regulator_dev *rdev,
const struct da9063_regulator_info *rinfo = regl->info;
int n, tval;
- for (n = 0; n < rinfo->n_current_limits; n++) {
+ for (n = rinfo->n_current_limits - 1; n >= 0; n--) {
tval = rinfo->current_limits[n];
if (tval >= min_uA && tval <= max_uA)
return regmap_field_write(regl->ilimit, n);
@@ -739,7 +739,6 @@ static int da9063_regulator_probe(struct platform_device *pdev)
struct regulator_config config;
bool bcores_merged, bmem_bio_merged;
int id, irq, n, n_regulators, ret, val;
- size_t size;
regl_pdata = da9063_pdata ? da9063_pdata->regulators_pdata : NULL;
@@ -784,9 +783,8 @@ static int da9063_regulator_probe(struct platform_device *pdev)
n_regulators--; /* remove BMEM_BIO_MERGED */
/* Allocate memory required by usable regulators */
- size = sizeof(struct da9063_regulators) +
- n_regulators * sizeof(struct da9063_regulator);
- regulators = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+ regulators = devm_kzalloc(&pdev->dev, struct_size(regulators,
+ regulator, n_regulators), GFP_KERNEL);
if (!regulators)
return -ENOMEM;
@@ -835,21 +833,40 @@ static int da9063_regulator_probe(struct platform_device *pdev)
regl->desc.type = REGULATOR_VOLTAGE;
regl->desc.owner = THIS_MODULE;
- if (regl->info->mode.reg)
+ if (regl->info->mode.reg) {
regl->mode = devm_regmap_field_alloc(&pdev->dev,
da9063->regmap, regl->info->mode);
- if (regl->info->suspend.reg)
+ if (IS_ERR(regl->mode))
+ return PTR_ERR(regl->mode);
+ }
+
+ if (regl->info->suspend.reg) {
regl->suspend = devm_regmap_field_alloc(&pdev->dev,
da9063->regmap, regl->info->suspend);
- if (regl->info->sleep.reg)
+ if (IS_ERR(regl->suspend))
+ return PTR_ERR(regl->suspend);
+ }
+
+ if (regl->info->sleep.reg) {
regl->sleep = devm_regmap_field_alloc(&pdev->dev,
da9063->regmap, regl->info->sleep);
- if (regl->info->suspend_sleep.reg)
+ if (IS_ERR(regl->sleep))
+ return PTR_ERR(regl->sleep);
+ }
+
+ if (regl->info->suspend_sleep.reg) {
regl->suspend_sleep = devm_regmap_field_alloc(&pdev->dev,
da9063->regmap, regl->info->suspend_sleep);
- if (regl->info->ilimit.reg)
+ if (IS_ERR(regl->suspend_sleep))
+ return PTR_ERR(regl->suspend_sleep);
+ }
+
+ if (regl->info->ilimit.reg) {
regl->ilimit = devm_regmap_field_alloc(&pdev->dev,
da9063->regmap, regl->info->ilimit);
+ if (IS_ERR(regl->ilimit))
+ return PTR_ERR(regl->ilimit);
+ }
/* Register regulator */
memset(&config, 0, sizeof(config));
diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c
index d0496d6b0934..528303771723 100644
--- a/drivers/regulator/da9210-regulator.c
+++ b/drivers/regulator/da9210-regulator.c
@@ -41,10 +41,6 @@ static const struct regmap_config da9210_regmap_config = {
.val_bits = 8,
};
-static int da9210_set_current_limit(struct regulator_dev *rdev, int min_uA,
- int max_uA);
-static int da9210_get_current_limit(struct regulator_dev *rdev);
-
static const struct regulator_ops da9210_buck_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
@@ -52,8 +48,8 @@ static const struct regulator_ops da9210_buck_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
- .set_current_limit = da9210_set_current_limit,
- .get_current_limit = da9210_get_current_limit,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .get_current_limit = regulator_get_current_limit_regmap,
};
/* Default limits measured in millivolts and milliamps */
@@ -62,7 +58,7 @@ static const struct regulator_ops da9210_buck_ops = {
#define DA9210_STEP_MV 10
/* Current limits for buck (uA) indices corresponds with register values */
-static const int da9210_buck_limits[] = {
+static const unsigned int da9210_buck_limits[] = {
1600000, 1800000, 2000000, 2200000, 2400000, 2600000, 2800000, 3000000,
3200000, 3400000, 3600000, 3800000, 4000000, 4200000, 4400000, 4600000
};
@@ -80,47 +76,12 @@ static const struct regulator_desc da9210_reg = {
.enable_reg = DA9210_REG_BUCK_CONT,
.enable_mask = DA9210_BUCK_EN,
.owner = THIS_MODULE,
+ .curr_table = da9210_buck_limits,
+ .n_current_limits = ARRAY_SIZE(da9210_buck_limits),
+ .csel_reg = DA9210_REG_BUCK_ILIM,
+ .csel_mask = DA9210_BUCK_ILIM_MASK,
};
-static int da9210_set_current_limit(struct regulator_dev *rdev, int min_uA,
- int max_uA)
-{
- struct da9210 *chip = rdev_get_drvdata(rdev);
- unsigned int sel;
- int i;
-
- /* search for closest to maximum */
- for (i = ARRAY_SIZE(da9210_buck_limits)-1; i >= 0; i--) {
- if (min_uA <= da9210_buck_limits[i] &&
- max_uA >= da9210_buck_limits[i]) {
- sel = i;
- sel = sel << DA9210_BUCK_ILIM_SHIFT;
- return regmap_update_bits(chip->regmap,
- DA9210_REG_BUCK_ILIM,
- DA9210_BUCK_ILIM_MASK, sel);
- }
- }
-
- return -EINVAL;
-}
-
-static int da9210_get_current_limit(struct regulator_dev *rdev)
-{
- struct da9210 *chip = rdev_get_drvdata(rdev);
- unsigned int data;
- unsigned int sel;
- int ret;
-
- ret = regmap_read(chip->regmap, DA9210_REG_BUCK_ILIM, &data);
- if (ret < 0)
- return ret;
-
- /* select one of 16 values: 0000 (1600mA) to 1111 (4600mA) */
- sel = (data & DA9210_BUCK_ILIM_MASK) >> DA9210_BUCK_ILIM_SHIFT;
-
- return da9210_buck_limits[sel];
-}
-
static irqreturn_t da9210_irq_handler(int irq, void *data)
{
struct da9210 *chip = data;
@@ -131,7 +92,7 @@ static irqreturn_t da9210_irq_handler(int irq, void *data)
if (error < 0)
goto error_i2c;
- mutex_lock(&chip->rdev->mutex);
+ regulator_lock(chip->rdev);
if (val & DA9210_E_OVCURR) {
regulator_notifier_call_chain(chip->rdev,
@@ -157,7 +118,7 @@ static irqreturn_t da9210_irq_handler(int irq, void *data)
handled |= DA9210_E_VMAX;
}
- mutex_unlock(&chip->rdev->mutex);
+ regulator_unlock(chip->rdev);
if (handled) {
/* Clear handled events */
diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c
index 8f68c7a05d27..109ee12d4362 100644
--- a/drivers/regulator/da9211-regulator.c
+++ b/drivers/regulator/da9211-regulator.c
@@ -389,6 +389,12 @@ static int da9211_regulator_init(struct da9211 *chip)
else
config.ena_gpiod = NULL;
+ /*
+ * Hand the GPIO descriptor management over to the regulator
+ * core, remove it from GPIO devres management.
+ */
+ if (config.ena_gpiod)
+ devm_gpiod_unhinge(chip->dev, config.ena_gpiod);
chip->rdev[i] = devm_regulator_register(chip->dev,
&da9211_regulators[i], &config);
if (IS_ERR(chip->rdev[i])) {
diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c
index 8976141c1438..308e3ff0a1bd 100644
--- a/drivers/regulator/dbx500-prcmu.c
+++ b/drivers/regulator/dbx500-prcmu.c
@@ -75,7 +75,7 @@ static struct ux500_regulator_debug {
u8 *state_after_suspend;
} rdebug;
-static int ux500_regulator_power_state_cnt_print(struct seq_file *s, void *p)
+static int ux500_regulator_power_state_cnt_show(struct seq_file *s, void *p)
{
/* print power state count */
seq_printf(s, "ux500-regulator power state count: %i\n",
@@ -83,23 +83,9 @@ static int ux500_regulator_power_state_cnt_print(struct seq_file *s, void *p)
return 0;
}
+DEFINE_SHOW_ATTRIBUTE(ux500_regulator_power_state_cnt);
-static int ux500_regulator_power_state_cnt_open(struct inode *inode,
- struct file *file)
-{
- return single_open(file, ux500_regulator_power_state_cnt_print,
- inode->i_private);
-}
-
-static const struct file_operations ux500_regulator_power_state_cnt_fops = {
- .open = ux500_regulator_power_state_cnt_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static int ux500_regulator_status_print(struct seq_file *s, void *p)
+static int ux500_regulator_status_show(struct seq_file *s, void *p)
{
int i;
@@ -122,20 +108,7 @@ static int ux500_regulator_status_print(struct seq_file *s, void *p)
return 0;
}
-
-static int ux500_regulator_status_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ux500_regulator_status_print,
- inode->i_private);
-}
-
-static const struct file_operations ux500_regulator_status_fops = {
- .open = ux500_regulator_status_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(ux500_regulator_status);
int __attribute__((weak)) dbx500_regulator_testcase(
struct dbx500_regulator_info *regulator_info,
diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
index a3bc8037153e..771a06d1900d 100644
--- a/drivers/regulator/fan53555.c
+++ b/drivers/regulator/fan53555.c
@@ -40,7 +40,6 @@
/* VSEL bit definitions */
#define VSEL_BUCK_EN (1 << 7)
#define VSEL_MODE (1 << 6)
-#define VSEL_NSEL_MASK 0x3F
/* Chip ID and Verison */
#define DIE_ID 0x0F /* ID1 */
#define DIE_REV 0x0F /* ID2 */
@@ -49,14 +48,26 @@
#define CTL_SLEW_MASK (0x7 << 4)
#define CTL_SLEW_SHIFT 4
#define CTL_RESET (1 << 2)
+#define CTL_MODE_VSEL0_MODE BIT(0)
+#define CTL_MODE_VSEL1_MODE BIT(1)
#define FAN53555_NVOLTAGES 64 /* Numbers of voltages */
+#define FAN53526_NVOLTAGES 128
enum fan53555_vendor {
- FAN53555_VENDOR_FAIRCHILD = 0,
+ FAN53526_VENDOR_FAIRCHILD = 0,
+ FAN53555_VENDOR_FAIRCHILD,
FAN53555_VENDOR_SILERGY,
};
+enum {
+ FAN53526_CHIP_ID_01 = 1,
+};
+
+enum {
+ FAN53526_CHIP_REV_08 = 8,
+};
+
/* IC Type */
enum {
FAN53555_CHIP_ID_00 = 0,
@@ -94,8 +105,12 @@ struct fan53555_device_info {
/* Voltage range and step(linear) */
unsigned int vsel_min;
unsigned int vsel_step;
+ unsigned int vsel_count;
/* Voltage slew rate limiting */
unsigned int slew_rate;
+ /* Mode */
+ unsigned int mode_reg;
+ unsigned int mode_mask;
/* Sleep voltage cache */
unsigned int sleep_vol_cache;
};
@@ -111,7 +126,7 @@ static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV)
if (ret < 0)
return ret;
ret = regmap_update_bits(di->regmap, di->sleep_reg,
- VSEL_NSEL_MASK, ret);
+ di->desc.vsel_mask, ret);
if (ret < 0)
return ret;
/* Cache the sleep voltage setting.
@@ -143,11 +158,11 @@ static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode)
switch (mode) {
case REGULATOR_MODE_FAST:
- regmap_update_bits(di->regmap, di->vol_reg,
- VSEL_MODE, VSEL_MODE);
+ regmap_update_bits(di->regmap, di->mode_reg,
+ di->mode_mask, di->mode_mask);
break;
case REGULATOR_MODE_NORMAL:
- regmap_update_bits(di->regmap, di->vol_reg, VSEL_MODE, 0);
+ regmap_update_bits(di->regmap, di->vol_reg, di->mode_mask, 0);
break;
default:
return -EINVAL;
@@ -161,10 +176,10 @@ static unsigned int fan53555_get_mode(struct regulator_dev *rdev)
unsigned int val;
int ret = 0;
- ret = regmap_read(di->regmap, di->vol_reg, &val);
+ ret = regmap_read(di->regmap, di->mode_reg, &val);
if (ret < 0)
return ret;
- if (val & VSEL_MODE)
+ if (val & di->mode_mask)
return REGULATOR_MODE_FAST;
else
return REGULATOR_MODE_NORMAL;
@@ -219,6 +234,34 @@ static const struct regulator_ops fan53555_regulator_ops = {
.set_suspend_disable = fan53555_set_suspend_disable,
};
+static int fan53526_voltages_setup_fairchild(struct fan53555_device_info *di)
+{
+ /* Init voltage range and step */
+ switch (di->chip_id) {
+ case FAN53526_CHIP_ID_01:
+ switch (di->chip_rev) {
+ case FAN53526_CHIP_REV_08:
+ di->vsel_min = 600000;
+ di->vsel_step = 6250;
+ break;
+ default:
+ dev_err(di->dev,
+ "Chip ID %d with rev %d not supported!\n",
+ di->chip_id, di->chip_rev);
+ return -EINVAL;
+ }
+ break;
+ default:
+ dev_err(di->dev,
+ "Chip ID %d not supported!\n", di->chip_id);
+ return -EINVAL;
+ }
+
+ di->vsel_count = FAN53526_NVOLTAGES;
+
+ return 0;
+}
+
static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di)
{
/* Init voltage range and step */
@@ -257,6 +300,8 @@ static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di)
return -EINVAL;
}
+ di->vsel_count = FAN53555_NVOLTAGES;
+
return 0;
}
@@ -274,6 +319,8 @@ static int fan53555_voltages_setup_silergy(struct fan53555_device_info *di)
return -EINVAL;
}
+ di->vsel_count = FAN53555_NVOLTAGES;
+
return 0;
}
@@ -302,7 +349,35 @@ static int fan53555_device_setup(struct fan53555_device_info *di,
return -EINVAL;
}
+ /* Setup mode control register */
+ switch (di->vendor) {
+ case FAN53526_VENDOR_FAIRCHILD:
+ di->mode_reg = FAN53555_CONTROL;
+
+ switch (pdata->sleep_vsel_id) {
+ case FAN53555_VSEL_ID_0:
+ di->mode_mask = CTL_MODE_VSEL1_MODE;
+ break;
+ case FAN53555_VSEL_ID_1:
+ di->mode_mask = CTL_MODE_VSEL0_MODE;
+ break;
+ }
+ break;
+ case FAN53555_VENDOR_FAIRCHILD:
+ case FAN53555_VENDOR_SILERGY:
+ di->mode_reg = di->vol_reg;
+ di->mode_mask = VSEL_MODE;
+ break;
+ default:
+ dev_err(di->dev, "vendor %d not supported!\n", di->vendor);
+ return -EINVAL;
+ }
+
+ /* Setup voltage range */
switch (di->vendor) {
+ case FAN53526_VENDOR_FAIRCHILD:
+ ret = fan53526_voltages_setup_fairchild(di);
+ break;
case FAN53555_VENDOR_FAIRCHILD:
ret = fan53555_voltages_setup_fairchild(di);
break;
@@ -326,13 +401,13 @@ static int fan53555_regulator_register(struct fan53555_device_info *di,
rdesc->supply_name = "vin";
rdesc->ops = &fan53555_regulator_ops;
rdesc->type = REGULATOR_VOLTAGE;
- rdesc->n_voltages = FAN53555_NVOLTAGES;
+ rdesc->n_voltages = di->vsel_count;
rdesc->enable_reg = di->vol_reg;
rdesc->enable_mask = VSEL_BUCK_EN;
rdesc->min_uV = di->vsel_min;
rdesc->uV_step = di->vsel_step;
rdesc->vsel_reg = di->vol_reg;
- rdesc->vsel_mask = VSEL_NSEL_MASK;
+ rdesc->vsel_mask = di->vsel_count - 1;
rdesc->owner = THIS_MODULE;
di->rdev = devm_regulator_register(di->dev, &di->desc, config);
@@ -368,6 +443,9 @@ static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev,
static const struct of_device_id fan53555_dt_ids[] = {
{
+ .compatible = "fcs,fan53526",
+ .data = (void *)FAN53526_VENDOR_FAIRCHILD,
+ }, {
.compatible = "fcs,fan53555",
.data = (void *)FAN53555_VENDOR_FAIRCHILD
}, {
@@ -412,11 +490,13 @@ static int fan53555_regulator_probe(struct i2c_client *client,
} else {
/* if no ramp constraint set, get the pdata ramp_delay */
if (!di->regulator->constraints.ramp_delay) {
- int slew_idx = (pdata->slew_rate & 0x7)
- ? pdata->slew_rate : 0;
+ if (pdata->slew_rate >= ARRAY_SIZE(slew_rates)) {
+ dev_err(&client->dev, "Invalid slew_rate\n");
+ return -EINVAL;
+ }
di->regulator->constraints.ramp_delay
- = slew_rates[slew_idx];
+ = slew_rates[pdata->slew_rate];
}
di->vendor = id->driver_data;
@@ -467,6 +547,9 @@ static int fan53555_regulator_probe(struct i2c_client *client,
static const struct i2c_device_id fan53555_id[] = {
{
+ .name = "fan53526",
+ .driver_data = FAN53526_VENDOR_FAIRCHILD
+ }, {
.name = "fan53555",
.driver_data = FAN53555_VENDOR_FAIRCHILD
}, {
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index ccc29038f19a..b5afc9db2c61 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -79,15 +79,6 @@ of_get_fixed_voltage_config(struct device *dev,
of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
- /*
- * FIXME: we pulled active low/high and open drain handling into
- * gpiolib so it will be handled there. Delete this in the second
- * step when we also remove the custom inversion handling for all
- * legacy boardfiles.
- */
- config->enable_high = 1;
- config->gpio_is_open_drain = 0;
-
if (of_find_property(np, "vin-supply", NULL))
config->input_supply = "vin";
@@ -151,24 +142,14 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
drvdata->desc.fixed_uV = config->microvolts;
- cfg.ena_gpio_invert = !config->enable_high;
- if (config->enabled_at_boot) {
- if (config->enable_high)
- gflags = GPIOD_OUT_HIGH;
- else
- gflags = GPIOD_OUT_LOW;
- } else {
- if (config->enable_high)
- gflags = GPIOD_OUT_LOW;
- else
- gflags = GPIOD_OUT_HIGH;
- }
- if (config->gpio_is_open_drain) {
- if (gflags == GPIOD_OUT_HIGH)
- gflags = GPIOD_OUT_HIGH_OPEN_DRAIN;
- else
- gflags = GPIOD_OUT_LOW_OPEN_DRAIN;
- }
+ /*
+ * The signal will be inverted by the GPIO core if flagged so in the
+ * decriptor.
+ */
+ if (config->enabled_at_boot)
+ gflags = GPIOD_OUT_HIGH;
+ else
+ gflags = GPIOD_OUT_LOW;
/*
* Some fixed regulators share the enable line between two
@@ -183,7 +164,11 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
*/
gflags |= GPIOD_FLAGS_BIT_NONEXCLUSIVE;
- cfg.ena_gpiod = devm_gpiod_get_optional(&pdev->dev, NULL, gflags);
+ /*
+ * Do not use devm* here: the regulator core takes over the
+ * lifecycle management of the GPIO descriptor.
+ */
+ cfg.ena_gpiod = gpiod_get_optional(&pdev->dev, NULL, gflags);
if (IS_ERR(cfg.ena_gpiod))
return PTR_ERR(cfg.ena_gpiod);
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
index b2f5ec4f658a..6157001df0a4 100644
--- a/drivers/regulator/gpio-regulator.c
+++ b/drivers/regulator/gpio-regulator.c
@@ -30,16 +30,15 @@
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/gpio-regulator.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/slab.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
struct gpio_regulator_data {
struct regulator_desc desc;
struct regulator_dev *dev;
- struct gpio *gpios;
+ struct gpio_desc **gpiods;
int nr_gpios;
struct gpio_regulator_state *states;
@@ -82,7 +81,7 @@ static int gpio_regulator_set_voltage(struct regulator_dev *dev,
for (ptr = 0; ptr < data->nr_gpios; ptr++) {
state = (target & (1 << ptr)) >> ptr;
- gpio_set_value_cansleep(data->gpios[ptr].gpio, state);
+ gpiod_set_value_cansleep(data->gpiods[ptr], state);
}
data->state = target;
@@ -119,7 +118,7 @@ static int gpio_regulator_set_current_limit(struct regulator_dev *dev,
for (ptr = 0; ptr < data->nr_gpios; ptr++) {
state = (target & (1 << ptr)) >> ptr;
- gpio_set_value_cansleep(data->gpios[ptr].gpio, state);
+ gpiod_set_value_cansleep(data->gpiods[ptr], state);
}
data->state = target;
@@ -138,7 +137,8 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np,
{
struct gpio_regulator_config *config;
const char *regtype;
- int proplen, gpio, i;
+ int proplen, i;
+ int ngpios;
int ret;
config = devm_kzalloc(dev,
@@ -153,59 +153,36 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np,
config->supply_name = config->init_data->constraints.name;
- if (of_property_read_bool(np, "enable-active-high"))
- config->enable_high = true;
-
if (of_property_read_bool(np, "enable-at-boot"))
config->enabled_at_boot = true;
of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
- config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
- if (config->enable_gpio < 0 && config->enable_gpio != -ENOENT)
- return ERR_PTR(config->enable_gpio);
-
- /* Fetch GPIOs. - optional property*/
- ret = of_gpio_count(np);
- if ((ret < 0) && (ret != -ENOENT))
- return ERR_PTR(ret);
-
- if (ret > 0) {
- config->nr_gpios = ret;
- config->gpios = devm_kcalloc(dev,
- config->nr_gpios, sizeof(struct gpio),
- GFP_KERNEL);
- if (!config->gpios)
+ /* Fetch GPIO init levels */
+ ngpios = gpiod_count(dev, NULL);
+ if (ngpios > 0) {
+ config->gflags = devm_kzalloc(dev,
+ sizeof(enum gpiod_flags)
+ * ngpios,
+ GFP_KERNEL);
+ if (!config->gflags)
return ERR_PTR(-ENOMEM);
- proplen = of_property_count_u32_elems(np, "gpios-states");
- /* optional property */
- if (proplen < 0)
- proplen = 0;
+ for (i = 0; i < ngpios; i++) {
+ u32 val;
- if (proplen > 0 && proplen != config->nr_gpios) {
- dev_warn(dev, "gpios <-> gpios-states mismatch\n");
- proplen = 0;
- }
+ ret = of_property_read_u32_index(np, "gpios-states", i,
+ &val);
- for (i = 0; i < config->nr_gpios; i++) {
- gpio = of_get_named_gpio(np, "gpios", i);
- if (gpio < 0) {
- if (gpio != -ENOENT)
- return ERR_PTR(gpio);
- break;
- }
- config->gpios[i].gpio = gpio;
- config->gpios[i].label = config->supply_name;
- if (proplen > 0) {
- of_property_read_u32_index(np, "gpios-states",
- i, &ret);
- if (ret)
- config->gpios[i].flags =
- GPIOF_OUT_INIT_HIGH;
- }
+ /* Default to high per specification */
+ if (ret)
+ config->gflags[i] = GPIOD_OUT_HIGH;
+ else
+ config->gflags[i] =
+ val ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
}
}
+ config->ngpios = ngpios;
/* Fetch states. */
proplen = of_property_count_u32_elems(np, "states");
@@ -251,59 +228,56 @@ static struct regulator_ops gpio_regulator_current_ops = {
static int gpio_regulator_probe(struct platform_device *pdev)
{
- struct gpio_regulator_config *config = dev_get_platdata(&pdev->dev);
- struct device_node *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+ struct gpio_regulator_config *config = dev_get_platdata(dev);
+ struct device_node *np = dev->of_node;
struct gpio_regulator_data *drvdata;
struct regulator_config cfg = { };
- int ptr, ret, state;
+ enum gpiod_flags gflags;
+ int ptr, ret, state, i;
- drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data),
+ drvdata = devm_kzalloc(dev, sizeof(struct gpio_regulator_data),
GFP_KERNEL);
if (drvdata == NULL)
return -ENOMEM;
if (np) {
- config = of_get_gpio_regulator_config(&pdev->dev, np,
+ config = of_get_gpio_regulator_config(dev, np,
&drvdata->desc);
if (IS_ERR(config))
return PTR_ERR(config);
}
- drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL);
+ drvdata->desc.name = devm_kstrdup(dev, config->supply_name, GFP_KERNEL);
if (drvdata->desc.name == NULL) {
- dev_err(&pdev->dev, "Failed to allocate supply name\n");
+ dev_err(dev, "Failed to allocate supply name\n");
return -ENOMEM;
}
- if (config->nr_gpios != 0) {
- drvdata->gpios = kmemdup(config->gpios,
- config->nr_gpios * sizeof(struct gpio),
- GFP_KERNEL);
- if (drvdata->gpios == NULL) {
- dev_err(&pdev->dev, "Failed to allocate gpio data\n");
- ret = -ENOMEM;
- goto err_name;
- }
-
- drvdata->nr_gpios = config->nr_gpios;
- ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios);
- if (ret) {
- if (ret != -EPROBE_DEFER)
- dev_err(&pdev->dev,
- "Could not obtain regulator setting GPIOs: %d\n",
- ret);
- goto err_memgpio;
- }
+ drvdata->gpiods = devm_kzalloc(dev, sizeof(struct gpio_desc *),
+ GFP_KERNEL);
+ if (!drvdata->gpiods)
+ return -ENOMEM;
+ for (i = 0; i < config->ngpios; i++) {
+ drvdata->gpiods[i] = devm_gpiod_get_index(dev,
+ NULL,
+ i,
+ config->gflags[i]);
+ if (IS_ERR(drvdata->gpiods[i]))
+ return PTR_ERR(drvdata->gpiods[i]);
+ /* This is good to know */
+ gpiod_set_consumer_name(drvdata->gpiods[i], drvdata->desc.name);
}
+ drvdata->nr_gpios = config->ngpios;
- drvdata->states = kmemdup(config->states,
- config->nr_states *
- sizeof(struct gpio_regulator_state),
- GFP_KERNEL);
+ drvdata->states = devm_kmemdup(dev,
+ config->states,
+ config->nr_states *
+ sizeof(struct gpio_regulator_state),
+ GFP_KERNEL);
if (drvdata->states == NULL) {
- dev_err(&pdev->dev, "Failed to allocate state data\n");
- ret = -ENOMEM;
- goto err_stategpio;
+ dev_err(dev, "Failed to allocate state data\n");
+ return -ENOMEM;
}
drvdata->nr_states = config->nr_states;
@@ -322,61 +296,46 @@ static int gpio_regulator_probe(struct platform_device *pdev)
drvdata->desc.ops = &gpio_regulator_current_ops;
break;
default:
- dev_err(&pdev->dev, "No regulator type set\n");
- ret = -EINVAL;
- goto err_memstate;
+ dev_err(dev, "No regulator type set\n");
+ return -EINVAL;
}
/* build initial state from gpio init data. */
state = 0;
for (ptr = 0; ptr < drvdata->nr_gpios; ptr++) {
- if (config->gpios[ptr].flags & GPIOF_OUT_INIT_HIGH)
+ if (config->gflags[ptr] == GPIOD_OUT_HIGH)
state |= (1 << ptr);
}
drvdata->state = state;
- cfg.dev = &pdev->dev;
+ cfg.dev = dev;
cfg.init_data = config->init_data;
cfg.driver_data = drvdata;
cfg.of_node = np;
- if (gpio_is_valid(config->enable_gpio)) {
- cfg.ena_gpio = config->enable_gpio;
- cfg.ena_gpio_initialized = true;
- }
- cfg.ena_gpio_invert = !config->enable_high;
- if (config->enabled_at_boot) {
- if (config->enable_high)
- cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
- else
- cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
- } else {
- if (config->enable_high)
- cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
- else
- cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
- }
+ /*
+ * The signal will be inverted by the GPIO core if flagged so in the
+ * decriptor.
+ */
+ if (config->enabled_at_boot)
+ gflags = GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE;
+ else
+ gflags = GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE;
+
+ cfg.ena_gpiod = gpiod_get_optional(dev, "enable", gflags);
+ if (IS_ERR(cfg.ena_gpiod))
+ return PTR_ERR(cfg.ena_gpiod);
drvdata->dev = regulator_register(&drvdata->desc, &cfg);
if (IS_ERR(drvdata->dev)) {
ret = PTR_ERR(drvdata->dev);
- dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
- goto err_memstate;
+ dev_err(dev, "Failed to register regulator: %d\n", ret);
+ return ret;
}
platform_set_drvdata(pdev, drvdata);
return 0;
-
-err_memstate:
- kfree(drvdata->states);
-err_stategpio:
- gpio_free_array(drvdata->gpios, drvdata->nr_gpios);
-err_memgpio:
- kfree(drvdata->gpios);
-err_name:
- kfree(drvdata->desc.name);
- return ret;
}
static int gpio_regulator_remove(struct platform_device *pdev)
@@ -385,13 +344,6 @@ static int gpio_regulator_remove(struct platform_device *pdev)
regulator_unregister(drvdata->dev);
- gpio_free_array(drvdata->gpios, drvdata->nr_gpios);
-
- kfree(drvdata->states);
- kfree(drvdata->gpios);
-
- kfree(drvdata->desc.name);
-
return 0;
}
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index 5686a1335bd3..32d3f0499e2d 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -594,28 +594,30 @@ int regulator_list_voltage_pickable_linear_range(struct regulator_dev *rdev,
EXPORT_SYMBOL_GPL(regulator_list_voltage_pickable_linear_range);
/**
- * regulator_list_voltage_linear_range - List voltages for linear ranges
+ * regulator_desc_list_voltage_linear_range - List voltages for linear ranges
*
- * @rdev: Regulator device
+ * @desc: Regulator desc for regulator which volatges are to be listed
* @selector: Selector to convert into a voltage
*
* Regulators with a series of simple linear mappings between voltages
- * and selectors can set linear_ranges in the regulator descriptor and
- * then use this function as their list_voltage() operation,
+ * and selectors who have set linear_ranges in the regulator descriptor
+ * can use this function prior regulator registration to list voltages.
+ * This is useful when voltages need to be listed during device-tree
+ * parsing.
*/
-int regulator_list_voltage_linear_range(struct regulator_dev *rdev,
- unsigned int selector)
+int regulator_desc_list_voltage_linear_range(const struct regulator_desc *desc,
+ unsigned int selector)
{
const struct regulator_linear_range *range;
int i;
- if (!rdev->desc->n_linear_ranges) {
- BUG_ON(!rdev->desc->n_linear_ranges);
+ if (!desc->n_linear_ranges) {
+ BUG_ON(!desc->n_linear_ranges);
return -EINVAL;
}
- for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
- range = &rdev->desc->linear_ranges[i];
+ for (i = 0; i < desc->n_linear_ranges; i++) {
+ range = &desc->linear_ranges[i];
if (!(selector >= range->min_sel &&
selector <= range->max_sel))
@@ -628,6 +630,23 @@ int regulator_list_voltage_linear_range(struct regulator_dev *rdev,
return -EINVAL;
}
+EXPORT_SYMBOL_GPL(regulator_desc_list_voltage_linear_range);
+
+/**
+ * regulator_list_voltage_linear_range - List voltages for linear ranges
+ *
+ * @rdev: Regulator device
+ * @selector: Selector to convert into a voltage
+ *
+ * Regulators with a series of simple linear mappings between voltages
+ * and selectors can set linear_ranges in the regulator descriptor and
+ * then use this function as their list_voltage() operation,
+ */
+int regulator_list_voltage_linear_range(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ return regulator_desc_list_voltage_linear_range(rdev->desc, selector);
+}
EXPORT_SYMBOL_GPL(regulator_list_voltage_linear_range);
/**
@@ -761,3 +780,89 @@ int regulator_set_active_discharge_regmap(struct regulator_dev *rdev,
rdev->desc->active_discharge_mask, val);
}
EXPORT_SYMBOL_GPL(regulator_set_active_discharge_regmap);
+
+/**
+ * regulator_set_current_limit_regmap - set_current_limit for regmap users
+ *
+ * @rdev: regulator to operate on
+ * @min_uA: Lower bound for current limit
+ * @max_uA: Upper bound for current limit
+ *
+ * Regulators that use regmap for their register I/O can set curr_table,
+ * csel_reg and csel_mask fields in their descriptor and then use this
+ * as their set_current_limit operation, saving some code.
+ */
+int regulator_set_current_limit_regmap(struct regulator_dev *rdev,
+ int min_uA, int max_uA)
+{
+ unsigned int n_currents = rdev->desc->n_current_limits;
+ int i, sel = -1;
+
+ if (n_currents == 0)
+ return -EINVAL;
+
+ if (rdev->desc->curr_table) {
+ const unsigned int *curr_table = rdev->desc->curr_table;
+ bool ascend = curr_table[n_currents - 1] > curr_table[0];
+
+ /* search for closest to maximum */
+ if (ascend) {
+ for (i = n_currents - 1; i >= 0; i--) {
+ if (min_uA <= curr_table[i] &&
+ curr_table[i] <= max_uA) {
+ sel = i;
+ break;
+ }
+ }
+ } else {
+ for (i = 0; i < n_currents; i++) {
+ if (min_uA <= curr_table[i] &&
+ curr_table[i] <= max_uA) {
+ sel = i;
+ break;
+ }
+ }
+ }
+ }
+
+ if (sel < 0)
+ return -EINVAL;
+
+ sel <<= ffs(rdev->desc->csel_mask) - 1;
+
+ return regmap_update_bits(rdev->regmap, rdev->desc->csel_reg,
+ rdev->desc->csel_mask, sel);
+}
+EXPORT_SYMBOL_GPL(regulator_set_current_limit_regmap);
+
+/**
+ * regulator_get_current_limit_regmap - get_current_limit for regmap users
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * csel_reg and csel_mask fields in their descriptor and then use this
+ * as their get_current_limit operation, saving some code.
+ */
+int regulator_get_current_limit_regmap(struct regulator_dev *rdev)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, rdev->desc->csel_reg, &val);
+ if (ret != 0)
+ return ret;
+
+ val &= rdev->desc->csel_mask;
+ val >>= ffs(rdev->desc->csel_mask) - 1;
+
+ if (rdev->desc->curr_table) {
+ if (val >= rdev->desc->n_current_limits)
+ return -EINVAL;
+
+ return rdev->desc->curr_table[val];
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(regulator_get_current_limit_regmap);
diff --git a/drivers/regulator/hi655x-regulator.c b/drivers/regulator/hi655x-regulator.c
index 36ae54b53814..bba24a6fdb1e 100644
--- a/drivers/regulator/hi655x-regulator.c
+++ b/drivers/regulator/hi655x-regulator.c
@@ -28,7 +28,6 @@
struct hi655x_regulator {
unsigned int disable_reg;
unsigned int status_reg;
- unsigned int ctrl_regs;
unsigned int ctrl_mask;
struct regulator_desc rdesc;
};
diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h
index 943926a156f2..6017f15c5d75 100644
--- a/drivers/regulator/internal.h
+++ b/drivers/regulator/internal.h
@@ -42,6 +42,8 @@ struct regulator {
unsigned int always_on:1;
unsigned int bypass:1;
int uA_load;
+ unsigned int enable_count;
+ unsigned int deferred_disables;
struct regulator_voltage voltage[REGULATOR_STATES_NUM];
const char *supply_name;
struct device_attribute dev_attr;
diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c
index 4abd8e9c81e5..6f28bba81d13 100644
--- a/drivers/regulator/isl6271a-regulator.c
+++ b/drivers/regulator/isl6271a-regulator.c
@@ -31,7 +31,6 @@
/* PMIC details */
struct isl_pmic {
struct i2c_client *client;
- struct regulator_dev *rdev[3];
struct mutex mtx;
};
@@ -66,14 +65,14 @@ static int isl6271a_set_voltage_sel(struct regulator_dev *dev,
return err;
}
-static struct regulator_ops isl_core_ops = {
+static const struct regulator_ops isl_core_ops = {
.get_voltage_sel = isl6271a_get_voltage_sel,
.set_voltage_sel = isl6271a_set_voltage_sel,
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
};
-static struct regulator_ops isl_fixed_ops = {
+static const struct regulator_ops isl_fixed_ops = {
.list_voltage = regulator_list_voltage_linear,
};
@@ -109,6 +108,7 @@ static const struct regulator_desc isl_rd[] = {
static int isl6271a_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
+ struct regulator_dev *rdev;
struct regulator_config config = { };
struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev);
struct isl_pmic *pmic;
@@ -133,11 +133,10 @@ static int isl6271a_probe(struct i2c_client *i2c,
config.init_data = NULL;
config.driver_data = pmic;
- pmic->rdev[i] = devm_regulator_register(&i2c->dev, &isl_rd[i],
- &config);
- if (IS_ERR(pmic->rdev[i])) {
+ rdev = devm_regulator_register(&i2c->dev, &isl_rd[i], &config);
+ if (IS_ERR(rdev)) {
dev_err(&i2c->dev, "failed to register %s\n", id->name);
- return PTR_ERR(pmic->rdev[i]);
+ return PTR_ERR(rdev);
}
}
diff --git a/drivers/regulator/lm363x-regulator.c b/drivers/regulator/lm363x-regulator.c
index bbedb08d257b..c876e161052a 100644
--- a/drivers/regulator/lm363x-regulator.c
+++ b/drivers/regulator/lm363x-regulator.c
@@ -224,13 +224,15 @@ static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev,
/*
* Check LCM_EN1/2_GPIO is configured.
* Those pins are used for enabling VPOS/VNEG LDOs.
+ * Do not use devm* here: the regulator core takes over the
+ * lifecycle management of the GPIO descriptor.
*/
switch (id) {
case LM3632_LDO_POS:
- return devm_gpiod_get_index_optional(dev, "enable", 0,
+ return gpiod_get_index_optional(dev, "enable", 0,
GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
case LM3632_LDO_NEG:
- return devm_gpiod_get_index_optional(dev, "enable", 1,
+ return gpiod_get_index_optional(dev, "enable", 1,
GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
default:
return NULL;
@@ -256,6 +258,9 @@ static int lm363x_regulator_probe(struct platform_device *pdev)
* Register update is required if the pin is used.
*/
gpiod = lm363x_regulator_of_get_enable_gpio(dev, id);
+ if (IS_ERR(gpiod))
+ return PTR_ERR(gpiod);
+
if (gpiod) {
cfg.ena_gpiod = gpiod;
@@ -263,6 +268,7 @@ static int lm363x_regulator_probe(struct platform_device *pdev)
LM3632_EXT_EN_MASK,
LM3632_EXT_EN_MASK);
if (ret) {
+ gpiod_put(gpiod);
dev_err(dev, "External pin err: %d\n", ret);
return ret;
}
diff --git a/drivers/regulator/lochnagar-regulator.c b/drivers/regulator/lochnagar-regulator.c
index 2b5073b9ff86..ff97cc50f2eb 100644
--- a/drivers/regulator/lochnagar-regulator.c
+++ b/drivers/regulator/lochnagar-regulator.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
@@ -20,6 +21,8 @@
#include <linux/regulator/of_regulator.h>
#include <linux/mfd/lochnagar.h>
+#include <linux/mfd/lochnagar1_regs.h>
+#include <linux/mfd/lochnagar2_regs.h>
static const struct regulator_ops lochnagar_micvdd_ops = {
.enable = regulator_enable_regmap,
@@ -191,7 +194,7 @@ static const struct regulator_desc lochnagar_regulators[] = {
.name = "VDDCORE",
.supply_name = "SYSVDD",
.type = REGULATOR_VOLTAGE,
- .n_voltages = 57,
+ .n_voltages = 66,
.ops = &lochnagar_vddcore_ops,
.id = LOCHNAGAR_VDDCORE,
@@ -212,28 +215,53 @@ static const struct regulator_desc lochnagar_regulators[] = {
},
};
+static const struct of_device_id lochnagar_of_match[] = {
+ {
+ .compatible = "cirrus,lochnagar2-micvdd",
+ .data = &lochnagar_regulators[LOCHNAGAR_MICVDD],
+ },
+ {
+ .compatible = "cirrus,lochnagar2-mic1vdd",
+ .data = &lochnagar_regulators[LOCHNAGAR_MIC1VDD],
+ },
+ {
+ .compatible = "cirrus,lochnagar2-mic2vdd",
+ .data = &lochnagar_regulators[LOCHNAGAR_MIC2VDD],
+ },
+ {
+ .compatible = "cirrus,lochnagar2-vddcore",
+ .data = &lochnagar_regulators[LOCHNAGAR_VDDCORE],
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, lochnagar_of_match);
+
static int lochnagar_regulator_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct lochnagar *lochnagar = dev_get_drvdata(dev->parent);
struct regulator_config config = { };
+ const struct of_device_id *of_id;
+ const struct regulator_desc *desc;
struct regulator_dev *rdev;
- int ret, i;
+ int ret;
- config.dev = lochnagar->dev;
+ config.dev = dev;
config.regmap = lochnagar->regmap;
config.driver_data = lochnagar;
- for (i = 0; i < ARRAY_SIZE(lochnagar_regulators); i++) {
- const struct regulator_desc *desc = &lochnagar_regulators[i];
+ of_id = of_match_device(lochnagar_of_match, dev);
+ if (!of_id)
+ return -EINVAL;
- rdev = devm_regulator_register(dev, desc, &config);
- if (IS_ERR(rdev)) {
- ret = PTR_ERR(rdev);
- dev_err(dev, "Failed to register %s regulator: %d\n",
- desc->name, ret);
- return ret;
- }
+ desc = of_id->data;
+
+ rdev = devm_regulator_register(dev, desc, &config);
+ if (IS_ERR(rdev)) {
+ ret = PTR_ERR(rdev);
+ dev_err(dev, "Failed to register %s regulator: %d\n",
+ desc->name, ret);
+ return ret;
}
return 0;
@@ -242,6 +270,7 @@ static int lochnagar_regulator_probe(struct platform_device *pdev)
static struct platform_driver lochnagar_regulator_driver = {
.driver = {
.name = "lochnagar-regulator",
+ .of_match_table = of_match_ptr(lochnagar_of_match),
},
.probe = lochnagar_regulator_probe,
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index 204b5c5270e0..9e45112658ba 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -159,7 +159,7 @@ static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev,
selector << LDO_VOL_CONTR_SHIFT(ldo));
}
-static struct regulator_ops lp3971_ldo_ops = {
+static const struct regulator_ops lp3971_ldo_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.is_enabled = lp3971_ldo_is_enabled,
@@ -233,7 +233,7 @@ static int lp3971_dcdc_set_voltage_sel(struct regulator_dev *dev,
0 << BUCK_VOL_CHANGE_SHIFT(buck));
}
-static struct regulator_ops lp3971_dcdc_ops = {
+static const struct regulator_ops lp3971_dcdc_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.is_enabled = lp3971_dcdc_is_enabled,
diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c
index ff0c275f902e..fb098198b688 100644
--- a/drivers/regulator/lp3972.c
+++ b/drivers/regulator/lp3972.c
@@ -305,7 +305,7 @@ static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev,
return ret;
}
-static struct regulator_ops lp3972_ldo_ops = {
+static const struct regulator_ops lp3972_ldo_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.is_enabled = lp3972_ldo_is_enabled,
@@ -386,7 +386,7 @@ static int lp3972_dcdc_set_voltage_sel(struct regulator_dev *dev,
LP3972_VOL_CHANGE_FLAG_MASK, 0);
}
-static struct regulator_ops lp3972_dcdc_ops = {
+static const struct regulator_ops lp3972_dcdc_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.is_enabled = lp3972_dcdc_is_enabled,
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index 38992112fd6e..ca95257ce252 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -353,64 +353,6 @@ static int lp872x_buck_get_voltage_sel(struct regulator_dev *rdev)
return val & LP872X_VOUT_M;
}
-static int lp8725_buck_set_current_limit(struct regulator_dev *rdev,
- int min_uA, int max_uA)
-{
- struct lp872x *lp = rdev_get_drvdata(rdev);
- enum lp872x_regulator_id buck = rdev_get_id(rdev);
- int i;
- u8 addr;
-
- switch (buck) {
- case LP8725_ID_BUCK1:
- addr = LP8725_BUCK1_VOUT2;
- break;
- case LP8725_ID_BUCK2:
- addr = LP8725_BUCK2_VOUT2;
- break;
- default:
- return -EINVAL;
- }
-
- for (i = ARRAY_SIZE(lp8725_buck_uA) - 1; i >= 0; i--) {
- if (lp8725_buck_uA[i] >= min_uA &&
- lp8725_buck_uA[i] <= max_uA)
- return lp872x_update_bits(lp, addr,
- LP8725_BUCK_CL_M,
- i << LP8725_BUCK_CL_S);
- }
-
- return -EINVAL;
-}
-
-static int lp8725_buck_get_current_limit(struct regulator_dev *rdev)
-{
- struct lp872x *lp = rdev_get_drvdata(rdev);
- enum lp872x_regulator_id buck = rdev_get_id(rdev);
- u8 addr, val;
- int ret;
-
- switch (buck) {
- case LP8725_ID_BUCK1:
- addr = LP8725_BUCK1_VOUT2;
- break;
- case LP8725_ID_BUCK2:
- addr = LP8725_BUCK2_VOUT2;
- break;
- default:
- return -EINVAL;
- }
-
- ret = lp872x_read_byte(lp, addr, &val);
- if (ret)
- return ret;
-
- val = (val & LP8725_BUCK_CL_M) >> LP8725_BUCK_CL_S;
-
- return (val < ARRAY_SIZE(lp8725_buck_uA)) ?
- lp8725_buck_uA[val] : -EINVAL;
-}
-
static int lp872x_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct lp872x *lp = rdev_get_drvdata(rdev);
@@ -478,7 +420,7 @@ static unsigned int lp872x_buck_get_mode(struct regulator_dev *rdev)
return val & mask ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
}
-static struct regulator_ops lp872x_ldo_ops = {
+static const struct regulator_ops lp872x_ldo_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -489,7 +431,7 @@ static struct regulator_ops lp872x_ldo_ops = {
.enable_time = lp872x_regulator_enable_time,
};
-static struct regulator_ops lp8720_buck_ops = {
+static const struct regulator_ops lp8720_buck_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = lp872x_buck_set_voltage_sel,
@@ -502,7 +444,7 @@ static struct regulator_ops lp8720_buck_ops = {
.get_mode = lp872x_buck_get_mode,
};
-static struct regulator_ops lp8725_buck_ops = {
+static const struct regulator_ops lp8725_buck_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = lp872x_buck_set_voltage_sel,
@@ -513,11 +455,11 @@ static struct regulator_ops lp8725_buck_ops = {
.enable_time = lp872x_regulator_enable_time,
.set_mode = lp872x_buck_set_mode,
.get_mode = lp872x_buck_get_mode,
- .set_current_limit = lp8725_buck_set_current_limit,
- .get_current_limit = lp8725_buck_get_current_limit,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .get_current_limit = regulator_get_current_limit_regmap,
};
-static struct regulator_desc lp8720_regulator_desc[] = {
+static const struct regulator_desc lp8720_regulator_desc[] = {
{
.name = "ldo1",
.of_match = of_match_ptr("ldo1"),
@@ -602,7 +544,7 @@ static struct regulator_desc lp8720_regulator_desc[] = {
},
};
-static struct regulator_desc lp8725_regulator_desc[] = {
+static const struct regulator_desc lp8725_regulator_desc[] = {
{
.name = "ldo1",
.of_match = of_match_ptr("ldo1"),
@@ -712,6 +654,10 @@ static struct regulator_desc lp8725_regulator_desc[] = {
.owner = THIS_MODULE,
.enable_reg = LP872X_GENERAL_CFG,
.enable_mask = LP8725_BUCK1_EN_M,
+ .curr_table = lp8725_buck_uA,
+ .n_current_limits = ARRAY_SIZE(lp8725_buck_uA),
+ .csel_reg = LP8725_BUCK1_VOUT2,
+ .csel_mask = LP8725_BUCK_CL_M,
},
{
.name = "buck2",
@@ -724,6 +670,10 @@ static struct regulator_desc lp8725_regulator_desc[] = {
.owner = THIS_MODULE,
.enable_reg = LP872X_GENERAL_CFG,
.enable_mask = LP8725_BUCK2_EN_M,
+ .curr_table = lp8725_buck_uA,
+ .n_current_limits = ARRAY_SIZE(lp8725_buck_uA),
+ .csel_reg = LP8725_BUCK2_VOUT2,
+ .csel_mask = LP8725_BUCK_CL_M,
},
};
@@ -820,7 +770,7 @@ static struct regulator_init_data
static int lp872x_regulator_register(struct lp872x *lp)
{
- struct regulator_desc *desc;
+ const struct regulator_desc *desc;
struct regulator_config cfg = { };
struct regulator_dev *rdev;
int i;
diff --git a/drivers/regulator/lp873x-regulator.c b/drivers/regulator/lp873x-regulator.c
index 70e3df653381..b55de293ca7a 100644
--- a/drivers/regulator/lp873x-regulator.c
+++ b/drivers/regulator/lp873x-regulator.c
@@ -39,6 +39,10 @@
.ramp_delay = _delay, \
.linear_ranges = _lr, \
.n_linear_ranges = ARRAY_SIZE(_lr), \
+ .curr_table = lp873x_buck_uA, \
+ .n_current_limits = ARRAY_SIZE(lp873x_buck_uA), \
+ .csel_reg = (_cr), \
+ .csel_mask = LP873X_BUCK0_CTRL_2_BUCK0_ILIM,\
}, \
.ctrl2_reg = _cr, \
}
@@ -61,7 +65,7 @@ static const struct regulator_linear_range ldo0_ldo1_ranges[] = {
REGULATOR_LINEAR_RANGE(800000, 0x0, 0x19, 100000),
};
-static unsigned int lp873x_buck_ramp_delay[] = {
+static const unsigned int lp873x_buck_ramp_delay[] = {
30000, 15000, 10000, 7500, 3800, 1900, 940, 470
};
@@ -108,45 +112,8 @@ static int lp873x_buck_set_ramp_delay(struct regulator_dev *rdev,
return 0;
}
-static int lp873x_buck_set_current_limit(struct regulator_dev *rdev,
- int min_uA, int max_uA)
-{
- int id = rdev_get_id(rdev);
- struct lp873x *lp873 = rdev_get_drvdata(rdev);
- int i;
-
- for (i = ARRAY_SIZE(lp873x_buck_uA) - 1; i >= 0; i--) {
- if (lp873x_buck_uA[i] >= min_uA &&
- lp873x_buck_uA[i] <= max_uA)
- return regmap_update_bits(lp873->regmap,
- regulators[id].ctrl2_reg,
- LP873X_BUCK0_CTRL_2_BUCK0_ILIM,
- i << __ffs(LP873X_BUCK0_CTRL_2_BUCK0_ILIM));
- }
-
- return -EINVAL;
-}
-
-static int lp873x_buck_get_current_limit(struct regulator_dev *rdev)
-{
- int id = rdev_get_id(rdev);
- struct lp873x *lp873 = rdev_get_drvdata(rdev);
- int ret;
- unsigned int val;
-
- ret = regmap_read(lp873->regmap, regulators[id].ctrl2_reg, &val);
- if (ret)
- return ret;
-
- val = (val & LP873X_BUCK0_CTRL_2_BUCK0_ILIM) >>
- __ffs(LP873X_BUCK0_CTRL_2_BUCK0_ILIM);
-
- return (val < ARRAY_SIZE(lp873x_buck_uA)) ?
- lp873x_buck_uA[val] : -EINVAL;
-}
-
/* Operations permitted on BUCK0, BUCK1 */
-static struct regulator_ops lp873x_buck01_ops = {
+static const struct regulator_ops lp873x_buck01_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
@@ -156,12 +123,12 @@ static struct regulator_ops lp873x_buck01_ops = {
.map_voltage = regulator_map_voltage_linear_range,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_ramp_delay = lp873x_buck_set_ramp_delay,
- .set_current_limit = lp873x_buck_set_current_limit,
- .get_current_limit = lp873x_buck_get_current_limit,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .get_current_limit = regulator_get_current_limit_regmap,
};
/* Operations permitted on LDO0 and LDO1 */
-static struct regulator_ops lp873x_ldo01_ops = {
+static const struct regulator_ops lp873x_ldo01_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c
index 244822bb63cd..14fd38807134 100644
--- a/drivers/regulator/lp8755.c
+++ b/drivers/regulator/lp8755.c
@@ -315,7 +315,7 @@ out_i2c_error:
.vsel_mask = LP8755_BUCK_VOUT_M,\
}
-static struct regulator_desc lp8755_regulators[] = {
+static const struct regulator_desc lp8755_regulators[] = {
lp8755_buck_desc(0),
lp8755_buck_desc(1),
lp8755_buck_desc(2),
@@ -386,7 +386,7 @@ static irqreturn_t lp8755_irq_handler(int irq, void *data)
if (ret < 0)
goto err_i2c;
- /* send OCP event to all regualtor devices */
+ /* send OCP event to all regulator devices */
if ((flag1 & 0x01) && (pchip->irqmask & 0x01))
for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++)
if (pchip->rdev[icnt] != NULL)
@@ -394,7 +394,7 @@ static irqreturn_t lp8755_irq_handler(int irq, void *data)
LP8755_EVENT_OCP,
NULL);
- /* send OVP event to all regualtor devices */
+ /* send OVP event to all regulator devices */
if ((flag1 & 0x02) && (pchip->irqmask & 0x02))
for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++)
if (pchip->rdev[icnt] != NULL)
diff --git a/drivers/regulator/lp87565-regulator.c b/drivers/regulator/lp87565-regulator.c
index c192357d1dea..4ed41731a5b1 100644
--- a/drivers/regulator/lp87565-regulator.c
+++ b/drivers/regulator/lp87565-regulator.c
@@ -51,7 +51,7 @@ static const struct regulator_linear_range buck0_1_2_3_ranges[] = {
REGULATOR_LINEAR_RANGE(1420000, 0x9e, 0xff, 20000),
};
-static unsigned int lp87565_buck_ramp_delay[] = {
+static const unsigned int lp87565_buck_ramp_delay[] = {
30000, 15000, 10000, 7500, 3800, 1900, 940, 470
};
@@ -140,7 +140,7 @@ static int lp87565_buck_get_current_limit(struct regulator_dev *rdev)
}
/* Operations permitted on BUCK0, BUCK1 */
-static struct regulator_ops lp87565_buck_ops = {
+static const struct regulator_ops lp87565_buck_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c
index ec46290b647e..a7d30550bb5f 100644
--- a/drivers/regulator/lp8788-buck.c
+++ b/drivers/regulator/lp8788-buck.c
@@ -95,12 +95,10 @@ struct lp8788_buck {
void *dvs;
};
-/* BUCK 1 ~ 4 voltage table */
-static const int lp8788_buck_vtbl[] = {
- 500000, 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000,
- 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
- 1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000,
- 1950000, 2000000,
+/* BUCK 1 ~ 4 voltage ranges */
+static const struct regulator_linear_range buck_volt_ranges[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0, 0, 0),
+ REGULATOR_LINEAR_RANGE(800000, 1, 25, 50000),
};
static void lp8788_buck1_set_dvs(struct lp8788_buck *buck)
@@ -345,8 +343,8 @@ static unsigned int lp8788_buck_get_mode(struct regulator_dev *rdev)
}
static const struct regulator_ops lp8788_buck12_ops = {
- .list_voltage = regulator_list_voltage_table,
- .map_voltage = regulator_map_voltage_ascend,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
.set_voltage_sel = lp8788_buck12_set_voltage_sel,
.get_voltage_sel = lp8788_buck12_get_voltage_sel,
.enable = regulator_enable_regmap,
@@ -358,8 +356,8 @@ static const struct regulator_ops lp8788_buck12_ops = {
};
static const struct regulator_ops lp8788_buck34_ops = {
- .list_voltage = regulator_list_voltage_table,
- .map_voltage = regulator_map_voltage_ascend,
+ .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 = regulator_get_voltage_sel_regmap,
.enable = regulator_enable_regmap,
@@ -370,13 +368,14 @@ static const struct regulator_ops lp8788_buck34_ops = {
.get_mode = lp8788_buck_get_mode,
};
-static struct regulator_desc lp8788_buck_desc[] = {
+static const struct regulator_desc lp8788_buck_desc[] = {
{
.name = "buck1",
.id = BUCK1,
.ops = &lp8788_buck12_ops,
- .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
- .volt_table = lp8788_buck_vtbl,
+ .n_voltages = 26,
+ .linear_ranges = buck_volt_ranges,
+ .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.enable_reg = LP8788_EN_BUCK,
@@ -386,8 +385,9 @@ static struct regulator_desc lp8788_buck_desc[] = {
.name = "buck2",
.id = BUCK2,
.ops = &lp8788_buck12_ops,
- .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
- .volt_table = lp8788_buck_vtbl,
+ .n_voltages = 26,
+ .linear_ranges = buck_volt_ranges,
+ .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.enable_reg = LP8788_EN_BUCK,
@@ -397,8 +397,9 @@ static struct regulator_desc lp8788_buck_desc[] = {
.name = "buck3",
.id = BUCK3,
.ops = &lp8788_buck34_ops,
- .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
- .volt_table = lp8788_buck_vtbl,
+ .n_voltages = 26,
+ .linear_ranges = buck_volt_ranges,
+ .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.vsel_reg = LP8788_BUCK3_VOUT,
@@ -410,8 +411,9 @@ static struct regulator_desc lp8788_buck_desc[] = {
.name = "buck4",
.id = BUCK4,
.ops = &lp8788_buck34_ops,
- .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
- .volt_table = lp8788_buck_vtbl,
+ .n_voltages = 26,
+ .linear_ranges = buck_volt_ranges,
+ .n_linear_ranges = ARRAY_SIZE(buck_volt_ranges),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.vsel_reg = LP8788_BUCK4_VOUT,
diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c
index 553b4790050f..a2ef146e6b3a 100644
--- a/drivers/regulator/lp8788-ldo.c
+++ b/drivers/regulator/lp8788-ldo.c
@@ -186,7 +186,7 @@ static const struct regulator_ops lp8788_ldo_voltage_fixed_ops = {
.enable_time = lp8788_ldo_enable_time,
};
-static struct regulator_desc lp8788_dldo_desc[] = {
+static const struct regulator_desc lp8788_dldo_desc[] = {
{
.name = "dldo1",
.id = DLDO1,
@@ -343,7 +343,7 @@ static struct regulator_desc lp8788_dldo_desc[] = {
},
};
-static struct regulator_desc lp8788_aldo_desc[] = {
+static const struct regulator_desc lp8788_aldo_desc[] = {
{
.name = "aldo1",
.id = ALDO1,
@@ -501,8 +501,12 @@ static int lp8788_config_ldo_enable_mode(struct platform_device *pdev,
return 0;
}
- /* FIXME: check default mode for GPIO here: high or low? */
- ldo->ena_gpiod = devm_gpiod_get_index_optional(&pdev->dev,
+ /*
+ * Do not use devm* here: the regulator core takes over the
+ * lifecycle management of the GPIO descriptor.
+ * FIXME: check default mode for GPIO here: high or low?
+ */
+ ldo->ena_gpiod = gpiod_get_index_optional(&pdev->dev,
"enable",
enable_id,
GPIOD_OUT_HIGH |
diff --git a/drivers/regulator/ltc3676.c b/drivers/regulator/ltc3676.c
index 71fd0f2a4b76..e6d66e492b85 100644
--- a/drivers/regulator/ltc3676.c
+++ b/drivers/regulator/ltc3676.c
@@ -241,61 +241,10 @@ static struct regulator_desc ltc3676_regulators[LTC3676_NUM_REGULATORS] = {
LTC3676_FIXED_REG(LDO4, ldo4, LDOB, 2),
};
-static bool ltc3676_writeable_reg(struct device *dev, unsigned int reg)
+static bool ltc3676_readable_writeable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
- case LTC3676_IRQSTAT:
- case LTC3676_BUCK1:
- case LTC3676_BUCK2:
- case LTC3676_BUCK3:
- case LTC3676_BUCK4:
- case LTC3676_LDOA:
- case LTC3676_LDOB:
- case LTC3676_SQD1:
- case LTC3676_SQD2:
- case LTC3676_CNTRL:
- case LTC3676_DVB1A:
- case LTC3676_DVB1B:
- case LTC3676_DVB2A:
- case LTC3676_DVB2B:
- case LTC3676_DVB3A:
- case LTC3676_DVB3B:
- case LTC3676_DVB4A:
- case LTC3676_DVB4B:
- case LTC3676_MSKIRQ:
- case LTC3676_MSKPG:
- case LTC3676_USER:
- case LTC3676_HRST:
- case LTC3676_CLIRQ:
- return true;
- }
- return false;
-}
-
-static bool ltc3676_readable_reg(struct device *dev, unsigned int reg)
-{
- switch (reg) {
- case LTC3676_IRQSTAT:
- case LTC3676_BUCK1:
- case LTC3676_BUCK2:
- case LTC3676_BUCK3:
- case LTC3676_BUCK4:
- case LTC3676_LDOA:
- case LTC3676_LDOB:
- case LTC3676_SQD1:
- case LTC3676_SQD2:
- case LTC3676_CNTRL:
- case LTC3676_DVB1A:
- case LTC3676_DVB1B:
- case LTC3676_DVB2A:
- case LTC3676_DVB2B:
- case LTC3676_DVB3A:
- case LTC3676_DVB3B:
- case LTC3676_DVB4A:
- case LTC3676_DVB4B:
- case LTC3676_MSKIRQ:
- case LTC3676_MSKPG:
- case LTC3676_USER:
+ case LTC3676_BUCK1 ... LTC3676_IRQSTAT:
case LTC3676_HRST:
case LTC3676_CLIRQ:
return true;
@@ -306,9 +255,7 @@ static bool ltc3676_readable_reg(struct device *dev, unsigned int reg)
static bool ltc3676_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
- case LTC3676_IRQSTAT:
- case LTC3676_PGSTATL:
- case LTC3676_PGSTATRT:
+ case LTC3676_IRQSTAT ... LTC3676_PGSTATRT:
return true;
}
return false;
@@ -317,8 +264,8 @@ static bool ltc3676_volatile_reg(struct device *dev, unsigned int reg)
static const struct regmap_config ltc3676_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
- .writeable_reg = ltc3676_writeable_reg,
- .readable_reg = ltc3676_readable_reg,
+ .writeable_reg = ltc3676_readable_writeable_reg,
+ .readable_reg = ltc3676_readable_writeable_reg,
.volatile_reg = ltc3676_volatile_reg,
.max_register = LTC3676_CLIRQ,
.use_single_read = true,
@@ -442,5 +389,5 @@ static struct i2c_driver ltc3676_driver = {
module_i2c_driver(ltc3676_driver);
MODULE_AUTHOR("Tim Harvey <tharvey@gateworks.com>");
-MODULE_DESCRIPTION("Regulator driver for Linear Technology LTC1376");
+MODULE_DESCRIPTION("Regulator driver for Linear Technology LTC3676");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/max14577-regulator.c b/drivers/regulator/max14577-regulator.c
index bc7f4751bf9c..85a88a9e4d42 100644
--- a/drivers/regulator/max14577-regulator.c
+++ b/drivers/regulator/max14577-regulator.c
@@ -324,4 +324,3 @@ module_exit(max14577_regulator_exit);
MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
MODULE_DESCRIPTION("Maxim 14577/77836 regulator driver");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:max14577-regulator");
diff --git a/drivers/regulator/max77620-regulator.c b/drivers/regulator/max77620-regulator.c
index b94e3a721721..1607ac673e44 100644
--- a/drivers/regulator/max77620-regulator.c
+++ b/drivers/regulator/max77620-regulator.c
@@ -1,7 +1,7 @@
/*
* Maxim MAX77620 Regulator driver
*
- * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved.
*
* Author: Mallikarjun Kasoju <mkasoju@nvidia.com>
* Laxman Dewangan <ldewangan@nvidia.com>
@@ -690,6 +690,7 @@ static const struct regulator_ops max77620_regulator_ops = {
.active_discharge_mask = MAX77620_SD_CFG1_ADE_MASK, \
.active_discharge_reg = MAX77620_REG_##_id##_CFG, \
.type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
}, \
}
@@ -721,6 +722,7 @@ static const struct regulator_ops max77620_regulator_ops = {
.active_discharge_mask = MAX77620_LDO_CFG2_ADE_MASK, \
.active_discharge_reg = MAX77620_REG_##_id##_CFG2, \
.type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
}, \
}
@@ -803,6 +805,14 @@ static int max77620_regulator_probe(struct platform_device *pdev)
rdesc = &rinfo[id].desc;
pmic->rinfo[id] = &max77620_regs_info[id];
pmic->enable_power_mode[id] = MAX77620_POWER_MODE_NORMAL;
+ pmic->reg_pdata[id].active_fps_src = -1;
+ pmic->reg_pdata[id].active_fps_pd_slot = -1;
+ pmic->reg_pdata[id].active_fps_pu_slot = -1;
+ pmic->reg_pdata[id].suspend_fps_src = -1;
+ pmic->reg_pdata[id].suspend_fps_pd_slot = -1;
+ pmic->reg_pdata[id].suspend_fps_pu_slot = -1;
+ pmic->reg_pdata[id].power_ok = -1;
+ pmic->reg_pdata[id].ramp_rate_setting = -1;
ret = max77620_read_slew_rate(pmic, id);
if (ret < 0)
diff --git a/drivers/regulator/max77650-regulator.c b/drivers/regulator/max77650-regulator.c
new file mode 100644
index 000000000000..31ebf34b01ec
--- /dev/null
+++ b/drivers/regulator/max77650-regulator.c
@@ -0,0 +1,498 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018 BayLibre SAS
+// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+//
+// Regulator driver for MAXIM 77650/77651 charger/power-supply.
+
+#include <linux/of.h>
+#include <linux/mfd/max77650.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+
+#define MAX77650_REGULATOR_EN_CTRL_MASK GENMASK(3, 0)
+#define MAX77650_REGULATOR_EN_CTRL_BITS(_reg) \
+ ((_reg) & MAX77650_REGULATOR_EN_CTRL_MASK)
+#define MAX77650_REGULATOR_ENABLED GENMASK(2, 1)
+#define MAX77650_REGULATOR_DISABLED BIT(2)
+
+#define MAX77650_REGULATOR_V_LDO_MASK GENMASK(6, 0)
+#define MAX77650_REGULATOR_V_SBB_MASK GENMASK(5, 0)
+
+#define MAX77650_REGULATOR_AD_MASK BIT(3)
+#define MAX77650_REGULATOR_AD_DISABLED 0x00
+#define MAX77650_REGULATOR_AD_ENABLED BIT(3)
+
+#define MAX77650_REGULATOR_CURR_LIM_MASK GENMASK(7, 6)
+
+enum {
+ MAX77650_REGULATOR_ID_LDO = 0,
+ MAX77650_REGULATOR_ID_SBB0,
+ MAX77650_REGULATOR_ID_SBB1,
+ MAX77650_REGULATOR_ID_SBB2,
+ MAX77650_REGULATOR_NUM_REGULATORS,
+};
+
+struct max77650_regulator_desc {
+ struct regulator_desc desc;
+ unsigned int regA;
+ unsigned int regB;
+};
+
+static const u32 max77651_sbb1_regulator_volt_table[] = {
+ 2400000, 3200000, 4000000, 4800000,
+ 2450000, 3250000, 4050000, 4850000,
+ 2500000, 3300000, 4100000, 4900000,
+ 2550000, 3350000, 4150000, 4950000,
+ 2600000, 3400000, 4200000, 5000000,
+ 2650000, 3450000, 4250000, 5050000,
+ 2700000, 3500000, 4300000, 5100000,
+ 2750000, 3550000, 4350000, 5150000,
+ 2800000, 3600000, 4400000, 5200000,
+ 2850000, 3650000, 4450000, 5250000,
+ 2900000, 3700000, 4500000, 0,
+ 2950000, 3750000, 4550000, 0,
+ 3000000, 3800000, 4600000, 0,
+ 3050000, 3850000, 4650000, 0,
+ 3100000, 3900000, 4700000, 0,
+ 3150000, 3950000, 4750000, 0,
+};
+
+#define MAX77651_REGULATOR_SBB1_SEL_DEC(_val) \
+ (((_val & 0x3c) >> 2) | ((_val & 0x03) << 4))
+#define MAX77651_REGULATOR_SBB1_SEL_ENC(_val) \
+ (((_val & 0x30) >> 4) | ((_val & 0x0f) << 2))
+
+#define MAX77650_REGULATOR_SBB1_SEL_DECR(_val) \
+ do { \
+ _val = MAX77651_REGULATOR_SBB1_SEL_DEC(_val); \
+ _val--; \
+ _val = MAX77651_REGULATOR_SBB1_SEL_ENC(_val); \
+ } while (0)
+
+#define MAX77650_REGULATOR_SBB1_SEL_INCR(_val) \
+ do { \
+ _val = MAX77651_REGULATOR_SBB1_SEL_DEC(_val); \
+ _val++; \
+ _val = MAX77651_REGULATOR_SBB1_SEL_ENC(_val); \
+ } while (0)
+
+static const unsigned int max77650_current_limit_table[] = {
+ 1000000, 866000, 707000, 500000,
+};
+
+static int max77650_regulator_is_enabled(struct regulator_dev *rdev)
+{
+ struct max77650_regulator_desc *rdesc;
+ struct regmap *map;
+ int val, rv, en;
+
+ rdesc = rdev_get_drvdata(rdev);
+ map = rdev_get_regmap(rdev);
+
+ rv = regmap_read(map, rdesc->regB, &val);
+ if (rv)
+ return rv;
+
+ en = MAX77650_REGULATOR_EN_CTRL_BITS(val);
+
+ return en != MAX77650_REGULATOR_DISABLED;
+}
+
+static int max77650_regulator_enable(struct regulator_dev *rdev)
+{
+ struct max77650_regulator_desc *rdesc;
+ struct regmap *map;
+
+ rdesc = rdev_get_drvdata(rdev);
+ map = rdev_get_regmap(rdev);
+
+ return regmap_update_bits(map, rdesc->regB,
+ MAX77650_REGULATOR_EN_CTRL_MASK,
+ MAX77650_REGULATOR_ENABLED);
+}
+
+static int max77650_regulator_disable(struct regulator_dev *rdev)
+{
+ struct max77650_regulator_desc *rdesc;
+ struct regmap *map;
+
+ rdesc = rdev_get_drvdata(rdev);
+ map = rdev_get_regmap(rdev);
+
+ return regmap_update_bits(map, rdesc->regB,
+ MAX77650_REGULATOR_EN_CTRL_MASK,
+ MAX77650_REGULATOR_DISABLED);
+}
+
+static int max77650_regulator_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int sel)
+{
+ int rv = 0, curr, diff;
+ bool ascending;
+
+ /*
+ * If the regulator is disabled, we can program the desired
+ * voltage right away.
+ */
+ if (!max77650_regulator_is_enabled(rdev))
+ return regulator_set_voltage_sel_regmap(rdev, sel);
+
+ /*
+ * Otherwise we need to manually ramp the output voltage up/down
+ * one step at a time.
+ */
+
+ curr = regulator_get_voltage_sel_regmap(rdev);
+ if (curr < 0)
+ return curr;
+
+ diff = curr - sel;
+ if (diff == 0)
+ return 0; /* Already there. */
+ else if (diff > 0)
+ ascending = false;
+ else
+ ascending = true;
+
+ /*
+ * Make sure we'll get to the right voltage and break the loop even if
+ * the selector equals 0.
+ */
+ for (ascending ? curr++ : curr--;; ascending ? curr++ : curr--) {
+ rv = regulator_set_voltage_sel_regmap(rdev, curr);
+ if (rv)
+ return rv;
+
+ if (curr == sel)
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Special case: non-linear voltage table for max77651 SBB1 - software
+ * must ensure the voltage is ramped in 50mV increments.
+ */
+static int max77651_regulator_sbb1_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int sel)
+{
+ int rv = 0, curr, vcurr, vdest, vdiff;
+
+ /*
+ * If the regulator is disabled, we can program the desired
+ * voltage right away.
+ */
+ if (!max77650_regulator_is_enabled(rdev))
+ return regulator_set_voltage_sel_regmap(rdev, sel);
+
+ curr = regulator_get_voltage_sel_regmap(rdev);
+ if (curr < 0)
+ return curr;
+
+ if (curr == sel)
+ return 0; /* Already there. */
+
+ vcurr = max77651_sbb1_regulator_volt_table[curr];
+ vdest = max77651_sbb1_regulator_volt_table[sel];
+ vdiff = vcurr - vdest;
+
+ for (;;) {
+ if (vdiff > 0)
+ MAX77650_REGULATOR_SBB1_SEL_DECR(curr);
+ else
+ MAX77650_REGULATOR_SBB1_SEL_INCR(curr);
+
+ rv = regulator_set_voltage_sel_regmap(rdev, curr);
+ if (rv)
+ return rv;
+
+ if (curr == sel)
+ break;
+ };
+
+ return 0;
+}
+
+static const struct regulator_ops max77650_regulator_LDO_ops = {
+ .is_enabled = max77650_regulator_is_enabled,
+ .enable = max77650_regulator_enable,
+ .disable = max77650_regulator_disable,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = max77650_regulator_set_voltage_sel,
+ .set_active_discharge = regulator_set_active_discharge_regmap,
+};
+
+static const struct regulator_ops max77650_regulator_SBB_ops = {
+ .is_enabled = max77650_regulator_is_enabled,
+ .enable = max77650_regulator_enable,
+ .disable = max77650_regulator_disable,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = max77650_regulator_set_voltage_sel,
+ .get_current_limit = regulator_get_current_limit_regmap,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .set_active_discharge = regulator_set_active_discharge_regmap,
+};
+
+/* Special case for max77651 SBB1 - non-linear voltage mapping. */
+static const struct regulator_ops max77651_SBB1_regulator_ops = {
+ .is_enabled = max77650_regulator_is_enabled,
+ .enable = max77650_regulator_enable,
+ .disable = max77650_regulator_disable,
+ .list_voltage = regulator_list_voltage_table,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = max77651_regulator_sbb1_set_voltage_sel,
+ .get_current_limit = regulator_get_current_limit_regmap,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .set_active_discharge = regulator_set_active_discharge_regmap,
+};
+
+static struct max77650_regulator_desc max77650_LDO_desc = {
+ .desc = {
+ .name = "ldo",
+ .of_match = of_match_ptr("ldo"),
+ .regulators_node = of_match_ptr("regulators"),
+ .supply_name = "in-ldo",
+ .id = MAX77650_REGULATOR_ID_LDO,
+ .ops = &max77650_regulator_LDO_ops,
+ .min_uV = 1350000,
+ .uV_step = 12500,
+ .n_voltages = 128,
+ .vsel_mask = MAX77650_REGULATOR_V_LDO_MASK,
+ .vsel_reg = MAX77650_REG_CNFG_LDO_A,
+ .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
+ .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
+ .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
+ .active_discharge_reg = MAX77650_REG_CNFG_LDO_B,
+ .enable_time = 100,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .regA = MAX77650_REG_CNFG_LDO_A,
+ .regB = MAX77650_REG_CNFG_LDO_B,
+};
+
+static struct max77650_regulator_desc max77650_SBB0_desc = {
+ .desc = {
+ .name = "sbb0",
+ .of_match = of_match_ptr("sbb0"),
+ .regulators_node = of_match_ptr("regulators"),
+ .supply_name = "in-sbb0",
+ .id = MAX77650_REGULATOR_ID_SBB0,
+ .ops = &max77650_regulator_SBB_ops,
+ .min_uV = 800000,
+ .uV_step = 25000,
+ .n_voltages = 64,
+ .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
+ .vsel_reg = MAX77650_REG_CNFG_SBB0_A,
+ .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
+ .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
+ .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
+ .active_discharge_reg = MAX77650_REG_CNFG_SBB0_B,
+ .enable_time = 100,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .csel_reg = MAX77650_REG_CNFG_SBB0_A,
+ .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,
+ .curr_table = max77650_current_limit_table,
+ .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
+ },
+ .regA = MAX77650_REG_CNFG_SBB0_A,
+ .regB = MAX77650_REG_CNFG_SBB0_B,
+};
+
+static struct max77650_regulator_desc max77650_SBB1_desc = {
+ .desc = {
+ .name = "sbb1",
+ .of_match = of_match_ptr("sbb1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .supply_name = "in-sbb1",
+ .id = MAX77650_REGULATOR_ID_SBB1,
+ .ops = &max77650_regulator_SBB_ops,
+ .min_uV = 800000,
+ .uV_step = 12500,
+ .n_voltages = 64,
+ .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
+ .vsel_reg = MAX77650_REG_CNFG_SBB1_A,
+ .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
+ .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
+ .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
+ .active_discharge_reg = MAX77650_REG_CNFG_SBB1_B,
+ .enable_time = 100,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .csel_reg = MAX77650_REG_CNFG_SBB1_A,
+ .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,
+ .curr_table = max77650_current_limit_table,
+ .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
+ },
+ .regA = MAX77650_REG_CNFG_SBB1_A,
+ .regB = MAX77650_REG_CNFG_SBB1_B,
+};
+
+static struct max77650_regulator_desc max77651_SBB1_desc = {
+ .desc = {
+ .name = "sbb1",
+ .of_match = of_match_ptr("sbb1"),
+ .regulators_node = of_match_ptr("regulators"),
+ .supply_name = "in-sbb1",
+ .id = MAX77650_REGULATOR_ID_SBB1,
+ .ops = &max77651_SBB1_regulator_ops,
+ .volt_table = max77651_sbb1_regulator_volt_table,
+ .n_voltages = ARRAY_SIZE(max77651_sbb1_regulator_volt_table),
+ .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
+ .vsel_reg = MAX77650_REG_CNFG_SBB1_A,
+ .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
+ .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
+ .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
+ .active_discharge_reg = MAX77650_REG_CNFG_SBB1_B,
+ .enable_time = 100,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .csel_reg = MAX77650_REG_CNFG_SBB1_A,
+ .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,
+ .curr_table = max77650_current_limit_table,
+ .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
+ },
+ .regA = MAX77650_REG_CNFG_SBB1_A,
+ .regB = MAX77650_REG_CNFG_SBB1_B,
+};
+
+static struct max77650_regulator_desc max77650_SBB2_desc = {
+ .desc = {
+ .name = "sbb2",
+ .of_match = of_match_ptr("sbb2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .supply_name = "in-sbb0",
+ .id = MAX77650_REGULATOR_ID_SBB2,
+ .ops = &max77650_regulator_SBB_ops,
+ .min_uV = 800000,
+ .uV_step = 50000,
+ .n_voltages = 64,
+ .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
+ .vsel_reg = MAX77650_REG_CNFG_SBB2_A,
+ .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
+ .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
+ .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
+ .active_discharge_reg = MAX77650_REG_CNFG_SBB2_B,
+ .enable_time = 100,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .csel_reg = MAX77650_REG_CNFG_SBB2_A,
+ .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,
+ .curr_table = max77650_current_limit_table,
+ .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
+ },
+ .regA = MAX77650_REG_CNFG_SBB2_A,
+ .regB = MAX77650_REG_CNFG_SBB2_B,
+};
+
+static struct max77650_regulator_desc max77651_SBB2_desc = {
+ .desc = {
+ .name = "sbb2",
+ .of_match = of_match_ptr("sbb2"),
+ .regulators_node = of_match_ptr("regulators"),
+ .supply_name = "in-sbb0",
+ .id = MAX77650_REGULATOR_ID_SBB2,
+ .ops = &max77650_regulator_SBB_ops,
+ .min_uV = 2400000,
+ .uV_step = 50000,
+ .n_voltages = 64,
+ .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
+ .vsel_reg = MAX77650_REG_CNFG_SBB2_A,
+ .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
+ .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
+ .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
+ .active_discharge_reg = MAX77650_REG_CNFG_SBB2_B,
+ .enable_time = 100,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .csel_reg = MAX77650_REG_CNFG_SBB2_A,
+ .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,
+ .curr_table = max77650_current_limit_table,
+ .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
+ },
+ .regA = MAX77650_REG_CNFG_SBB2_A,
+ .regB = MAX77650_REG_CNFG_SBB2_B,
+};
+
+static int max77650_regulator_probe(struct platform_device *pdev)
+{
+ struct max77650_regulator_desc **rdescs;
+ struct max77650_regulator_desc *rdesc;
+ struct regulator_config config = { };
+ struct device *dev, *parent;
+ struct regulator_dev *rdev;
+ struct regmap *map;
+ unsigned int val;
+ int i, rv;
+
+ dev = &pdev->dev;
+ parent = dev->parent;
+
+ if (!dev->of_node)
+ dev->of_node = parent->of_node;
+
+ rdescs = devm_kcalloc(dev, MAX77650_REGULATOR_NUM_REGULATORS,
+ sizeof(*rdescs), GFP_KERNEL);
+ if (!rdescs)
+ return -ENOMEM;
+
+ map = dev_get_regmap(parent, NULL);
+ if (!map)
+ return -ENODEV;
+
+ rv = regmap_read(map, MAX77650_REG_CID, &val);
+ if (rv)
+ return rv;
+
+ rdescs[MAX77650_REGULATOR_ID_LDO] = &max77650_LDO_desc;
+ rdescs[MAX77650_REGULATOR_ID_SBB0] = &max77650_SBB0_desc;
+
+ switch (MAX77650_CID_BITS(val)) {
+ case MAX77650_CID_77650A:
+ case MAX77650_CID_77650C:
+ rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77650_SBB1_desc;
+ rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77650_SBB2_desc;
+ break;
+ case MAX77650_CID_77651A:
+ case MAX77650_CID_77651B:
+ rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77651_SBB1_desc;
+ rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77651_SBB2_desc;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ config.dev = parent;
+
+ for (i = 0; i < MAX77650_REGULATOR_NUM_REGULATORS; i++) {
+ rdesc = rdescs[i];
+ config.driver_data = rdesc;
+
+ rdev = devm_regulator_register(dev, &rdesc->desc, &config);
+ if (IS_ERR(rdev))
+ return PTR_ERR(rdev);
+ }
+
+ return 0;
+}
+
+static struct platform_driver max77650_regulator_driver = {
+ .driver = {
+ .name = "max77650-regulator",
+ },
+ .probe = max77650_regulator_probe,
+};
+module_platform_driver(max77650_regulator_driver);
+
+MODULE_DESCRIPTION("MAXIM 77650/77651 regulator driver");
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/max77686-regulator.c b/drivers/regulator/max77686-regulator.c
index bee060937f56..8020eb57374a 100644
--- a/drivers/regulator/max77686-regulator.c
+++ b/drivers/regulator/max77686-regulator.c
@@ -11,8 +11,7 @@
#include <linux/kernel.h>
#include <linux/bug.h>
#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
@@ -76,6 +75,7 @@ enum max77686_ramp_rate {
};
struct max77686_data {
+ struct device *dev;
DECLARE_BITMAP(gpio_enabled, MAX77686_REGULATORS);
/* Array indexed by regulator id */
@@ -250,26 +250,34 @@ static int max77686_of_parse_cb(struct device_node *np,
struct regulator_config *config)
{
struct max77686_data *max77686 = config->driver_data;
+ int ret;
switch (desc->id) {
case MAX77686_BUCK8:
case MAX77686_BUCK9:
case MAX77686_LDO20 ... MAX77686_LDO22:
- config->ena_gpio = of_get_named_gpio(np,
- "maxim,ena-gpios", 0);
- config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
- config->ena_gpio_initialized = true;
+ config->ena_gpiod = gpiod_get_from_of_node(np,
+ "maxim,ena",
+ 0,
+ GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
+ "max77686-regulator");
+ if (IS_ERR(config->ena_gpiod))
+ config->ena_gpiod = NULL;
break;
default:
return 0;
}
- if (gpio_is_valid(config->ena_gpio)) {
+ if (config->ena_gpiod) {
set_bit(desc->id, max77686->gpio_enabled);
- return regmap_update_bits(config->regmap, desc->enable_reg,
- desc->enable_mask,
- MAX77686_GPIO_CONTROL);
+ ret = regmap_update_bits(config->regmap, desc->enable_reg,
+ desc->enable_mask,
+ MAX77686_GPIO_CONTROL);
+ if (ret) {
+ gpiod_put(config->ena_gpiod);
+ config->ena_gpiod = NULL;
+ }
}
return 0;
@@ -507,6 +515,7 @@ static int max77686_pmic_probe(struct platform_device *pdev)
if (!max77686)
return -ENOMEM;
+ max77686->dev = &pdev->dev;
config.dev = iodev->dev;
config.regmap = iodev->regmap;
config.driver_data = max77686;
diff --git a/drivers/regulator/max77802-regulator.c b/drivers/regulator/max77802-regulator.c
index c30cf5c9f2de..ea7b50397300 100644
--- a/drivers/regulator/max77802-regulator.c
+++ b/drivers/regulator/max77802-regulator.c
@@ -248,9 +248,9 @@ static int max77802_set_ramp_delay_2bit(struct regulator_dev *rdev,
unsigned int ramp_value;
if (id > MAX77802_BUCK4) {
- dev_warn(&rdev->dev,
- "%s: regulator: ramp delay not supported\n",
- rdev->desc->name);
+ dev_warn(&rdev->dev,
+ "%s: regulator: ramp delay not supported\n",
+ rdev->desc->name);
return -EINVAL;
}
ramp_value = max77802_find_ramp_value(rdev, ramp_table_77802_2bit,
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c
index 6c39fff73b8a..cf2a2912cb1b 100644
--- a/drivers/regulator/max8952.c
+++ b/drivers/regulator/max8952.c
@@ -231,9 +231,13 @@ static int max8952_pmic_probe(struct i2c_client *client,
else
gflags = GPIOD_OUT_LOW;
gflags |= GPIOD_FLAGS_BIT_NONEXCLUSIVE;
- gpiod = devm_gpiod_get_optional(&client->dev,
- "max8952,en",
- gflags);
+ /*
+ * Do not use devm* here: the regulator core takes over the
+ * lifecycle management of the GPIO descriptor.
+ */
+ gpiod = gpiod_get_optional(&client->dev,
+ "max8952,en",
+ gflags);
if (IS_ERR(gpiod))
return PTR_ERR(gpiod);
if (gpiod)
diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c
index e7a58b509032..9aee1444181d 100644
--- a/drivers/regulator/max8973-regulator.c
+++ b/drivers/regulator/max8973-regulator.c
@@ -808,7 +808,13 @@ static int max8973_probe(struct i2c_client *client,
config.of_node = client->dev.of_node;
config.regmap = max->regmap;
- /* Register the regulators */
+ /*
+ * Register the regulators
+ * Turn the GPIO descriptor over to the regulator core for
+ * lifecycle management if we pass an ena_gpiod.
+ */
+ if (config.ena_gpiod)
+ devm_gpiod_unhinge(&client->dev, config.ena_gpiod);
rdev = devm_regulator_register(&client->dev, &max->desc, &config);
if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev);
diff --git a/drivers/regulator/max8997-regulator.c b/drivers/regulator/max8997-regulator.c
index 3bf5ddfaaea8..4d2487279a0a 100644
--- a/drivers/regulator/max8997-regulator.c
+++ b/drivers/regulator/max8997-regulator.c
@@ -925,7 +925,7 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
pdata->regulators = rdata;
for_each_child_of_node(regulators_np, reg_np) {
for (i = 0; i < ARRAY_SIZE(regulators); i++)
- if (!of_node_cmp(reg_np->name, regulators[i].name))
+ if (of_node_name_eq(reg_np, regulators[i].name))
break;
if (i == ARRAY_SIZE(regulators)) {
diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c
index 8fd1adc9c9a9..ab558b26cd7c 100644
--- a/drivers/regulator/mc13783-regulator.c
+++ b/drivers/regulator/mc13783-regulator.c
@@ -226,69 +226,69 @@ static const unsigned int mc13783_pwgtdrv_val[] = {
5500000,
};
-static struct regulator_ops mc13783_gpo_regulator_ops;
+static const struct regulator_ops mc13783_gpo_regulator_ops;
-#define MC13783_DEFINE(prefix, name, reg, vsel_reg, voltages) \
- MC13xxx_DEFINE(MC13783_REG_, name, reg, vsel_reg, voltages, \
+#define MC13783_DEFINE(prefix, name, node, reg, vsel_reg, voltages) \
+ MC13xxx_DEFINE(MC13783_REG_, name, node, reg, vsel_reg, voltages, \
mc13xxx_regulator_ops)
-#define MC13783_FIXED_DEFINE(prefix, name, reg, voltages) \
- MC13xxx_FIXED_DEFINE(MC13783_REG_, name, reg, voltages, \
+#define MC13783_FIXED_DEFINE(prefix, name, node, reg, voltages) \
+ MC13xxx_FIXED_DEFINE(MC13783_REG_, name, node, reg, voltages, \
mc13xxx_fixed_regulator_ops)
-#define MC13783_GPO_DEFINE(prefix, name, reg, voltages) \
- MC13xxx_GPO_DEFINE(MC13783_REG_, name, reg, voltages, \
+#define MC13783_GPO_DEFINE(prefix, name, node, reg, voltages) \
+ MC13xxx_GPO_DEFINE(MC13783_REG_, name, node, reg, voltages, \
mc13783_gpo_regulator_ops)
-#define MC13783_DEFINE_SW(_name, _reg, _vsel_reg, _voltages) \
- MC13783_DEFINE(REG, _name, _reg, _vsel_reg, _voltages)
-#define MC13783_DEFINE_REGU(_name, _reg, _vsel_reg, _voltages) \
- MC13783_DEFINE(REG, _name, _reg, _vsel_reg, _voltages)
+#define MC13783_DEFINE_SW(_name, _node, _reg, _vsel_reg, _voltages) \
+ MC13783_DEFINE(REG, _name, _node, _reg, _vsel_reg, _voltages)
+#define MC13783_DEFINE_REGU(_name, _node, _reg, _vsel_reg, _voltages) \
+ MC13783_DEFINE(REG, _name, _node, _reg, _vsel_reg, _voltages)
static struct mc13xxx_regulator mc13783_regulators[] = {
- MC13783_DEFINE_SW(SW1A, SWITCHERS0, SWITCHERS0, mc13783_sw1x_val),
- MC13783_DEFINE_SW(SW1B, SWITCHERS1, SWITCHERS1, mc13783_sw1x_val),
- MC13783_DEFINE_SW(SW2A, SWITCHERS2, SWITCHERS2, mc13783_sw2x_val),
- MC13783_DEFINE_SW(SW2B, SWITCHERS3, SWITCHERS3, mc13783_sw2x_val),
- MC13783_DEFINE_SW(SW3, SWITCHERS5, SWITCHERS5, mc13783_sw3_val),
-
- MC13783_FIXED_DEFINE(REG, VAUDIO, REGULATORMODE0, mc13783_vaudio_val),
- MC13783_FIXED_DEFINE(REG, VIOHI, REGULATORMODE0, mc13783_viohi_val),
- MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0,
+ MC13783_DEFINE_SW(SW1A, sw1a, SWITCHERS0, SWITCHERS0, mc13783_sw1x_val),
+ MC13783_DEFINE_SW(SW1B, sw1b, SWITCHERS1, SWITCHERS1, mc13783_sw1x_val),
+ MC13783_DEFINE_SW(SW2A, sw2a, SWITCHERS2, SWITCHERS2, mc13783_sw2x_val),
+ MC13783_DEFINE_SW(SW2B, sw2b, SWITCHERS3, SWITCHERS3, mc13783_sw2x_val),
+ MC13783_DEFINE_SW(SW3, sw3, SWITCHERS5, SWITCHERS5, mc13783_sw3_val),
+
+ MC13783_FIXED_DEFINE(REG, VAUDIO, vaudio, REGULATORMODE0, mc13783_vaudio_val),
+ MC13783_FIXED_DEFINE(REG, VIOHI, viohi, REGULATORMODE0, mc13783_viohi_val),
+ MC13783_DEFINE_REGU(VIOLO, violo, REGULATORMODE0, REGULATORSETTING0,
mc13783_violo_val),
- MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0,
+ MC13783_DEFINE_REGU(VDIG, vdig, REGULATORMODE0, REGULATORSETTING0,
mc13783_vdig_val),
- MC13783_DEFINE_REGU(VGEN, REGULATORMODE0, REGULATORSETTING0,
+ MC13783_DEFINE_REGU(VGEN, vgen, REGULATORMODE0, REGULATORSETTING0,
mc13783_vgen_val),
- MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0, REGULATORSETTING0,
+ MC13783_DEFINE_REGU(VRFDIG, vrfdig, REGULATORMODE0, REGULATORSETTING0,
mc13783_vrfdig_val),
- MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0, REGULATORSETTING0,
+ MC13783_DEFINE_REGU(VRFREF, vrfref, REGULATORMODE0, REGULATORSETTING0,
mc13783_vrfref_val),
- MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0, REGULATORSETTING0,
+ MC13783_DEFINE_REGU(VRFCP, vrfcp, REGULATORMODE0, REGULATORSETTING0,
mc13783_vrfcp_val),
- MC13783_DEFINE_REGU(VSIM, REGULATORMODE1, REGULATORSETTING0,
+ MC13783_DEFINE_REGU(VSIM, vsim, REGULATORMODE1, REGULATORSETTING0,
mc13783_vsim_val),
- MC13783_DEFINE_REGU(VESIM, REGULATORMODE1, REGULATORSETTING0,
+ MC13783_DEFINE_REGU(VESIM, vesim, REGULATORMODE1, REGULATORSETTING0,
mc13783_vesim_val),
- MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0,
+ MC13783_DEFINE_REGU(VCAM, vcam, REGULATORMODE1, REGULATORSETTING0,
mc13783_vcam_val),
- MC13783_FIXED_DEFINE(REG, VRFBG, REGULATORMODE1, mc13783_vrfbg_val),
- MC13783_DEFINE_REGU(VVIB, REGULATORMODE1, REGULATORSETTING1,
+ MC13783_FIXED_DEFINE(REG, VRFBG, vrfbg, REGULATORMODE1, mc13783_vrfbg_val),
+ MC13783_DEFINE_REGU(VVIB, vvib, REGULATORMODE1, REGULATORSETTING1,
mc13783_vvib_val),
- MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1,
+ MC13783_DEFINE_REGU(VRF1, vrf1, REGULATORMODE1, REGULATORSETTING1,
mc13783_vrf_val),
- MC13783_DEFINE_REGU(VRF2, REGULATORMODE1, REGULATORSETTING1,
+ MC13783_DEFINE_REGU(VRF2, vrf2, REGULATORMODE1, REGULATORSETTING1,
mc13783_vrf_val),
- MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1, REGULATORSETTING1,
+ MC13783_DEFINE_REGU(VMMC1, vmmc1, REGULATORMODE1, REGULATORSETTING1,
mc13783_vmmc_val),
- MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1,
+ MC13783_DEFINE_REGU(VMMC2, vmmc2, REGULATORMODE1, REGULATORSETTING1,
mc13783_vmmc_val),
- MC13783_GPO_DEFINE(REG, GPO1, POWERMISC, mc13783_gpo_val),
- MC13783_GPO_DEFINE(REG, GPO2, POWERMISC, mc13783_gpo_val),
- MC13783_GPO_DEFINE(REG, GPO3, POWERMISC, mc13783_gpo_val),
- MC13783_GPO_DEFINE(REG, GPO4, POWERMISC, mc13783_gpo_val),
- MC13783_GPO_DEFINE(REG, PWGT1SPI, POWERMISC, mc13783_pwgtdrv_val),
- MC13783_GPO_DEFINE(REG, PWGT2SPI, POWERMISC, mc13783_pwgtdrv_val),
+ MC13783_GPO_DEFINE(REG, GPO1, gpo1, POWERMISC, mc13783_gpo_val),
+ MC13783_GPO_DEFINE(REG, GPO2, gpo1, POWERMISC, mc13783_gpo_val),
+ MC13783_GPO_DEFINE(REG, GPO3, gpo1, POWERMISC, mc13783_gpo_val),
+ MC13783_GPO_DEFINE(REG, GPO4, gpo1, POWERMISC, mc13783_gpo_val),
+ MC13783_GPO_DEFINE(REG, PWGT1SPI, pwgt1spi, POWERMISC, mc13783_pwgtdrv_val),
+ MC13783_GPO_DEFINE(REG, PWGT2SPI, pwgt2spi, POWERMISC, mc13783_pwgtdrv_val),
};
static int mc13783_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask,
@@ -380,7 +380,7 @@ static int mc13783_gpo_regulator_is_enabled(struct regulator_dev *rdev)
return (val & mc13xxx_regulators[id].enable_bit) != 0;
}
-static struct regulator_ops mc13783_gpo_regulator_ops = {
+static const struct regulator_ops mc13783_gpo_regulator_ops = {
.enable = mc13783_gpo_regulator_enable,
.disable = mc13783_gpo_regulator_disable,
.is_enabled = mc13783_gpo_regulator_is_enabled,
diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c
index f3fba1cc1379..a731e826a037 100644
--- a/drivers/regulator/mc13892-regulator.c
+++ b/drivers/regulator/mc13892-regulator.c
@@ -242,61 +242,61 @@ static const unsigned int mc13892_pwgtdrv[] = {
5000000,
};
-static struct regulator_ops mc13892_gpo_regulator_ops;
-static struct regulator_ops mc13892_sw_regulator_ops;
+static const struct regulator_ops mc13892_gpo_regulator_ops;
+static const struct regulator_ops mc13892_sw_regulator_ops;
-#define MC13892_FIXED_DEFINE(name, reg, voltages) \
- MC13xxx_FIXED_DEFINE(MC13892_, name, reg, voltages, \
+#define MC13892_FIXED_DEFINE(name, node, reg, voltages) \
+ MC13xxx_FIXED_DEFINE(MC13892_, name, node, reg, voltages, \
mc13xxx_fixed_regulator_ops)
-#define MC13892_GPO_DEFINE(name, reg, voltages) \
- MC13xxx_GPO_DEFINE(MC13892_, name, reg, voltages, \
+#define MC13892_GPO_DEFINE(name, node, reg, voltages) \
+ MC13xxx_GPO_DEFINE(MC13892_, name, node, reg, voltages, \
mc13892_gpo_regulator_ops)
-#define MC13892_SW_DEFINE(name, reg, vsel_reg, voltages) \
- MC13xxx_DEFINE(MC13892_, name, reg, vsel_reg, voltages, \
+#define MC13892_SW_DEFINE(name, node, reg, vsel_reg, voltages) \
+ MC13xxx_DEFINE(MC13892_, name, node, reg, vsel_reg, voltages, \
mc13892_sw_regulator_ops)
-#define MC13892_DEFINE_REGU(name, reg, vsel_reg, voltages) \
- MC13xxx_DEFINE(MC13892_, name, reg, vsel_reg, voltages, \
+#define MC13892_DEFINE_REGU(name, node, reg, vsel_reg, voltages) \
+ MC13xxx_DEFINE(MC13892_, name, node, reg, vsel_reg, voltages, \
mc13xxx_regulator_ops)
static struct mc13xxx_regulator mc13892_regulators[] = {
- MC13892_DEFINE_REGU(VCOINCELL, POWERCTL0, POWERCTL0, mc13892_vcoincell),
- MC13892_SW_DEFINE(SW1, SWITCHERS0, SWITCHERS0, mc13892_sw1),
- MC13892_SW_DEFINE(SW2, SWITCHERS1, SWITCHERS1, mc13892_sw),
- MC13892_SW_DEFINE(SW3, SWITCHERS2, SWITCHERS2, mc13892_sw),
- MC13892_SW_DEFINE(SW4, SWITCHERS3, SWITCHERS3, mc13892_sw),
- MC13892_FIXED_DEFINE(SWBST, SWITCHERS5, mc13892_swbst),
- MC13892_FIXED_DEFINE(VIOHI, REGULATORMODE0, mc13892_viohi),
- MC13892_DEFINE_REGU(VPLL, REGULATORMODE0, REGULATORSETTING0,
+ MC13892_DEFINE_REGU(VCOINCELL, vcoincell, POWERCTL0, POWERCTL0, mc13892_vcoincell),
+ MC13892_SW_DEFINE(SW1, sw1, SWITCHERS0, SWITCHERS0, mc13892_sw1),
+ MC13892_SW_DEFINE(SW2, sw2, SWITCHERS1, SWITCHERS1, mc13892_sw),
+ MC13892_SW_DEFINE(SW3, sw3, SWITCHERS2, SWITCHERS2, mc13892_sw),
+ MC13892_SW_DEFINE(SW4, sw4, SWITCHERS3, SWITCHERS3, mc13892_sw),
+ MC13892_FIXED_DEFINE(SWBST, swbst, SWITCHERS5, mc13892_swbst),
+ MC13892_FIXED_DEFINE(VIOHI, viohi, REGULATORMODE0, mc13892_viohi),
+ MC13892_DEFINE_REGU(VPLL, vpll, REGULATORMODE0, REGULATORSETTING0,
mc13892_vpll),
- MC13892_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0,
+ MC13892_DEFINE_REGU(VDIG, vdig, REGULATORMODE0, REGULATORSETTING0,
mc13892_vdig),
- MC13892_DEFINE_REGU(VSD, REGULATORMODE1, REGULATORSETTING1,
+ MC13892_DEFINE_REGU(VSD, vsd, REGULATORMODE1, REGULATORSETTING1,
mc13892_vsd),
- MC13892_DEFINE_REGU(VUSB2, REGULATORMODE0, REGULATORSETTING0,
+ MC13892_DEFINE_REGU(VUSB2, vusb2, REGULATORMODE0, REGULATORSETTING0,
mc13892_vusb2),
- MC13892_DEFINE_REGU(VVIDEO, REGULATORMODE1, REGULATORSETTING1,
+ MC13892_DEFINE_REGU(VVIDEO, vvideo, REGULATORMODE1, REGULATORSETTING1,
mc13892_vvideo),
- MC13892_DEFINE_REGU(VAUDIO, REGULATORMODE1, REGULATORSETTING1,
+ MC13892_DEFINE_REGU(VAUDIO, vaudio, REGULATORMODE1, REGULATORSETTING1,
mc13892_vaudio),
- MC13892_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0,
+ MC13892_DEFINE_REGU(VCAM, vcam, REGULATORMODE1, REGULATORSETTING0,
mc13892_vcam),
- MC13892_DEFINE_REGU(VGEN1, REGULATORMODE0, REGULATORSETTING0,
+ MC13892_DEFINE_REGU(VGEN1, vgen1, REGULATORMODE0, REGULATORSETTING0,
mc13892_vgen1),
- MC13892_DEFINE_REGU(VGEN2, REGULATORMODE0, REGULATORSETTING0,
+ MC13892_DEFINE_REGU(VGEN2, vgen2, REGULATORMODE0, REGULATORSETTING0,
mc13892_vgen2),
- MC13892_DEFINE_REGU(VGEN3, REGULATORMODE1, REGULATORSETTING0,
+ MC13892_DEFINE_REGU(VGEN3, vgen3, REGULATORMODE1, REGULATORSETTING0,
mc13892_vgen3),
- MC13892_FIXED_DEFINE(VUSB, USB1, mc13892_vusb),
- MC13892_GPO_DEFINE(GPO1, POWERMISC, mc13892_gpo),
- MC13892_GPO_DEFINE(GPO2, POWERMISC, mc13892_gpo),
- MC13892_GPO_DEFINE(GPO3, POWERMISC, mc13892_gpo),
- MC13892_GPO_DEFINE(GPO4, POWERMISC, mc13892_gpo),
- MC13892_GPO_DEFINE(PWGT1SPI, POWERMISC, mc13892_pwgtdrv),
- MC13892_GPO_DEFINE(PWGT2SPI, POWERMISC, mc13892_pwgtdrv),
+ MC13892_FIXED_DEFINE(VUSB, vusb, USB1, mc13892_vusb),
+ MC13892_GPO_DEFINE(GPO1, gpo1, POWERMISC, mc13892_gpo),
+ MC13892_GPO_DEFINE(GPO2, gpo2, POWERMISC, mc13892_gpo),
+ MC13892_GPO_DEFINE(GPO3, gpo3, POWERMISC, mc13892_gpo),
+ MC13892_GPO_DEFINE(GPO4, gpo4, POWERMISC, mc13892_gpo),
+ MC13892_GPO_DEFINE(PWGT1SPI, pwgt1spi, POWERMISC, mc13892_pwgtdrv),
+ MC13892_GPO_DEFINE(PWGT2SPI, pwgt2spi, POWERMISC, mc13892_pwgtdrv),
};
static int mc13892_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask,
@@ -387,7 +387,7 @@ static int mc13892_gpo_regulator_is_enabled(struct regulator_dev *rdev)
}
-static struct regulator_ops mc13892_gpo_regulator_ops = {
+static const struct regulator_ops mc13892_gpo_regulator_ops = {
.enable = mc13892_gpo_regulator_enable,
.disable = mc13892_gpo_regulator_disable,
.is_enabled = mc13892_gpo_regulator_is_enabled,
@@ -479,7 +479,7 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev,
return ret;
}
-static struct regulator_ops mc13892_sw_regulator_ops = {
+static const struct regulator_ops mc13892_sw_regulator_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = mc13892_sw_regulator_set_voltage_sel,
diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c
index 65eb1e0350cf..8ff19150ca92 100644
--- a/drivers/regulator/mc13xxx-regulator-core.c
+++ b/drivers/regulator/mc13xxx-regulator-core.c
@@ -99,7 +99,7 @@ static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev)
return rdev->desc->volt_table[val];
}
-struct regulator_ops mc13xxx_regulator_ops = {
+const struct regulator_ops mc13xxx_regulator_ops = {
.enable = mc13xxx_regulator_enable,
.disable = mc13xxx_regulator_disable,
.is_enabled = mc13xxx_regulator_is_enabled,
@@ -127,7 +127,7 @@ int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
}
EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_set_voltage);
-struct regulator_ops mc13xxx_fixed_regulator_ops = {
+const struct regulator_ops mc13xxx_fixed_regulator_ops = {
.enable = mc13xxx_regulator_enable,
.disable = mc13xxx_regulator_disable,
.is_enabled = mc13xxx_regulator_is_enabled,
@@ -186,7 +186,7 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
for (i = 0; i < num_regulators; i++) {
if (!regulators[i].desc.name)
continue;
- if (!of_node_cmp(child->name,
+ if (of_node_name_eq(child,
regulators[i].desc.name)) {
p->id = i;
p->init_data = of_get_regulator_init_data(
diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h
index 2ab9bfd93b4e..ba7eff1070bd 100644
--- a/drivers/regulator/mc13xxx.h
+++ b/drivers/regulator/mc13xxx.h
@@ -53,13 +53,13 @@ static inline struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
}
#endif
-extern struct regulator_ops mc13xxx_regulator_ops;
-extern struct regulator_ops mc13xxx_fixed_regulator_ops;
+extern const struct regulator_ops mc13xxx_regulator_ops;
+extern const struct regulator_ops mc13xxx_fixed_regulator_ops;
-#define MC13xxx_DEFINE(prefix, _name, _reg, _vsel_reg, _voltages, _ops) \
+#define MC13xxx_DEFINE(prefix, _name, _node, _reg, _vsel_reg, _voltages, _ops) \
[prefix ## _name] = { \
.desc = { \
- .name = #_name, \
+ .name = #_node, \
.n_voltages = ARRAY_SIZE(_voltages), \
.volt_table = _voltages, \
.ops = &_ops, \
@@ -74,10 +74,10 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
.vsel_mask = prefix ## _vsel_reg ## _ ## _name ## VSEL_M,\
}
-#define MC13xxx_FIXED_DEFINE(prefix, _name, _reg, _voltages, _ops) \
+#define MC13xxx_FIXED_DEFINE(prefix, _name, _node, _reg, _voltages, _ops) \
[prefix ## _name] = { \
.desc = { \
- .name = #_name, \
+ .name = #_node, \
.n_voltages = ARRAY_SIZE(_voltages), \
.volt_table = _voltages, \
.ops = &_ops, \
@@ -89,10 +89,10 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
.enable_bit = prefix ## _reg ## _ ## _name ## EN, \
}
-#define MC13xxx_GPO_DEFINE(prefix, _name, _reg, _voltages, _ops) \
+#define MC13xxx_GPO_DEFINE(prefix, _name, _node, _reg, _voltages, _ops) \
[prefix ## _name] = { \
.desc = { \
- .name = #_name, \
+ .name = #_node, \
.n_voltages = ARRAY_SIZE(_voltages), \
.volt_table = _voltages, \
.ops = &_ops, \
@@ -104,9 +104,9 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
.enable_bit = prefix ## _reg ## _ ## _name ## EN, \
}
-#define MC13xxx_DEFINE_SW(_name, _reg, _vsel_reg, _voltages, ops) \
- MC13xxx_DEFINE(SW, _name, _reg, _vsel_reg, _voltages, ops)
-#define MC13xxx_DEFINE_REGU(_name, _reg, _vsel_reg, _voltages, ops) \
- MC13xxx_DEFINE(REGU, _name, _reg, _vsel_reg, _voltages, ops)
+#define MC13xxx_DEFINE_SW(_name, _node, _reg, _vsel_reg, _voltages, ops) \
+ MC13xxx_DEFINE(SW, _name, _node, _reg, _vsel_reg, _voltages, ops)
+#define MC13xxx_DEFINE_REGU(_name, _node, _reg, _vsel_reg, _voltages, ops) \
+ MC13xxx_DEFINE(REGU, _name, _node, _reg, _vsel_reg, _voltages, ops)
#endif
diff --git a/drivers/regulator/mcp16502.c b/drivers/regulator/mcp16502.c
new file mode 100644
index 000000000000..3a8004abe044
--- /dev/null
+++ b/drivers/regulator/mcp16502.c
@@ -0,0 +1,552 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// MCP16502 PMIC driver
+//
+// Copyright (C) 2018 Microchip Technology Inc. and its subsidiaries
+//
+// Author: Andrei Stefanescu <andrei.stefanescu@microchip.com>
+//
+// Inspired from tps65086-regulator.c
+
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/suspend.h>
+#include <linux/gpio/consumer.h>
+
+#define VDD_LOW_SEL 0x0D
+#define VDD_HIGH_SEL 0x3F
+
+#define MCP16502_FLT BIT(7)
+#define MCP16502_ENS BIT(0)
+
+/*
+ * The PMIC has four sets of registers corresponding to four power modes:
+ * Performance, Active, Low-power, Hibernate.
+ *
+ * Registers:
+ * Each regulator has a register for each power mode. To access a register
+ * for a specific regulator and mode BASE_* and OFFSET_* need to be added.
+ *
+ * Operating modes:
+ * In order for the PMIC to transition to operating modes it has to be
+ * controlled via GPIO lines called LPM and HPM.
+ *
+ * The registers are fully configurable such that you can put all regulators in
+ * a low-power state while the PMIC is in Active mode. They are supposed to be
+ * configured at startup and then simply transition to/from a global low-power
+ * state by setting the GPIO lpm pin high/low.
+ *
+ * This driver keeps the PMIC in Active mode, Low-power state is set for the
+ * regulators by enabling/disabling operating mode (FPWM or Auto PFM).
+ *
+ * The PMIC's Low-power and Hibernate modes are used during standby/suspend.
+ * To enter standby/suspend the PMIC will go to Low-power mode. From there, it
+ * will transition to Hibernate when the PWRHLD line is set to low by the MPU.
+ */
+
+/*
+ * This function is useful for iterating over all regulators and accessing their
+ * registers in a generic way or accessing a regulator device by its id.
+ */
+#define MCP16502_BASE(i) (((i) + 1) << 4)
+#define MCP16502_STAT_BASE(i) ((i) + 5)
+
+#define MCP16502_OFFSET_MODE_A 0
+#define MCP16502_OFFSET_MODE_LPM 1
+#define MCP16502_OFFSET_MODE_HIB 2
+
+#define MCP16502_OPMODE_ACTIVE REGULATOR_MODE_NORMAL
+#define MCP16502_OPMODE_LPM REGULATOR_MODE_IDLE
+#define MCP16502_OPMODE_HIB REGULATOR_MODE_STANDBY
+
+#define MCP16502_MODE_AUTO_PFM 0
+#define MCP16502_MODE_FPWM BIT(6)
+
+#define MCP16502_VSEL 0x3F
+#define MCP16502_EN BIT(7)
+#define MCP16502_MODE BIT(6)
+
+#define MCP16502_MIN_REG 0x0
+#define MCP16502_MAX_REG 0x65
+
+static unsigned int mcp16502_of_map_mode(unsigned int mode)
+{
+ if (mode == REGULATOR_MODE_NORMAL || mode == REGULATOR_MODE_IDLE)
+ return mode;
+
+ return REGULATOR_MODE_INVALID;
+}
+
+#define MCP16502_REGULATOR(_name, _id, _ranges, _ops) \
+ [_id] = { \
+ .name = _name, \
+ .regulators_node = of_match_ptr("regulators"), \
+ .id = _id, \
+ .ops = &(_ops), \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .n_voltages = MCP16502_VSEL + 1, \
+ .linear_ranges = _ranges, \
+ .n_linear_ranges = ARRAY_SIZE(_ranges), \
+ .of_match = of_match_ptr(_name), \
+ .of_map_mode = mcp16502_of_map_mode, \
+ .vsel_reg = (((_id) + 1) << 4), \
+ .vsel_mask = MCP16502_VSEL, \
+ .enable_reg = (((_id) + 1) << 4), \
+ .enable_mask = MCP16502_EN, \
+ }
+
+enum {
+ BUCK1 = 0,
+ BUCK2,
+ BUCK3,
+ BUCK4,
+ LDO1,
+ LDO2,
+ NUM_REGULATORS
+};
+
+/*
+ * struct mcp16502 - PMIC representation
+ * @rdev: the regulators belonging to this chip
+ * @rmap: regmap to be used for I2C communication
+ * @lpm: LPM GPIO descriptor
+ */
+struct mcp16502 {
+ struct regulator_dev *rdev[NUM_REGULATORS];
+ struct regmap *rmap;
+ struct gpio_desc *lpm;
+};
+
+/*
+ * mcp16502_gpio_set_mode() - set the GPIO corresponding value
+ *
+ * Used to prepare transitioning into hibernate or resuming from it.
+ */
+static void mcp16502_gpio_set_mode(struct mcp16502 *mcp, int mode)
+{
+ switch (mode) {
+ case MCP16502_OPMODE_ACTIVE:
+ gpiod_set_value(mcp->lpm, 0);
+ break;
+ case MCP16502_OPMODE_LPM:
+ case MCP16502_OPMODE_HIB:
+ gpiod_set_value(mcp->lpm, 1);
+ break;
+ default:
+ pr_err("%s: %d invalid\n", __func__, mode);
+ }
+}
+
+/*
+ * mcp16502_get_reg() - get the PMIC's configuration register for opmode
+ *
+ * @rdev: the regulator whose register we are searching
+ * @opmode: the PMIC's operating mode ACTIVE, Low-power, Hibernate
+ */
+static int mcp16502_get_reg(struct regulator_dev *rdev, int opmode)
+{
+ int reg = MCP16502_BASE(rdev_get_id(rdev));
+
+ switch (opmode) {
+ case MCP16502_OPMODE_ACTIVE:
+ return reg + MCP16502_OFFSET_MODE_A;
+ case MCP16502_OPMODE_LPM:
+ return reg + MCP16502_OFFSET_MODE_LPM;
+ case MCP16502_OPMODE_HIB:
+ return reg + MCP16502_OFFSET_MODE_HIB;
+ default:
+ return -EINVAL;
+ }
+}
+
+/*
+ * mcp16502_get_mode() - return the current operating mode of a regulator
+ *
+ * Note: all functions that are not part of entering/exiting standby/suspend
+ * use the Active mode registers.
+ *
+ * Note: this is different from the PMIC's operatig mode, it is the
+ * MODE bit from the regulator's register.
+ */
+static unsigned int mcp16502_get_mode(struct regulator_dev *rdev)
+{
+ unsigned int val;
+ int ret, reg;
+ struct mcp16502 *mcp = rdev_get_drvdata(rdev);
+
+ reg = mcp16502_get_reg(rdev, MCP16502_OPMODE_ACTIVE);
+ if (reg < 0)
+ return reg;
+
+ ret = regmap_read(mcp->rmap, reg, &val);
+ if (ret)
+ return ret;
+
+ switch (val & MCP16502_MODE) {
+ case MCP16502_MODE_FPWM:
+ return REGULATOR_MODE_NORMAL;
+ case MCP16502_MODE_AUTO_PFM:
+ return REGULATOR_MODE_IDLE;
+ default:
+ return REGULATOR_MODE_INVALID;
+ }
+}
+
+/*
+ * _mcp16502_set_mode() - helper for set_mode and set_suspend_mode
+ *
+ * @rdev: the regulator for which we are setting the mode
+ * @mode: the regulator's mode (the one from MODE bit)
+ * @opmode: the PMIC's operating mode: Active/Low-power/Hibernate
+ */
+static int _mcp16502_set_mode(struct regulator_dev *rdev, unsigned int mode,
+ unsigned int op_mode)
+{
+ int val;
+ int reg;
+ struct mcp16502 *mcp = rdev_get_drvdata(rdev);
+
+ reg = mcp16502_get_reg(rdev, op_mode);
+ if (reg < 0)
+ return reg;
+
+ switch (mode) {
+ case REGULATOR_MODE_NORMAL:
+ val = MCP16502_MODE_FPWM;
+ break;
+ case REGULATOR_MODE_IDLE:
+ val = MCP16502_MODE_AUTO_PFM;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ reg = regmap_update_bits(mcp->rmap, reg, MCP16502_MODE, val);
+ return reg;
+}
+
+/*
+ * mcp16502_set_mode() - regulator_ops set_mode
+ */
+static int mcp16502_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+ return _mcp16502_set_mode(rdev, mode, MCP16502_OPMODE_ACTIVE);
+}
+
+/*
+ * mcp16502_get_status() - regulator_ops get_status
+ */
+static int mcp16502_get_status(struct regulator_dev *rdev)
+{
+ int ret;
+ unsigned int val;
+ struct mcp16502 *mcp = rdev_get_drvdata(rdev);
+
+ ret = regmap_read(mcp->rmap, MCP16502_STAT_BASE(rdev_get_id(rdev)),
+ &val);
+ if (ret)
+ return ret;
+
+ if (val & MCP16502_FLT)
+ return REGULATOR_STATUS_ERROR;
+ else if (val & MCP16502_ENS)
+ return REGULATOR_STATUS_ON;
+ else if (!(val & MCP16502_ENS))
+ return REGULATOR_STATUS_OFF;
+
+ return REGULATOR_STATUS_UNDEFINED;
+}
+
+#ifdef CONFIG_SUSPEND
+/*
+ * mcp16502_suspend_get_target_reg() - get the reg of the target suspend PMIC
+ * mode
+ */
+static int mcp16502_suspend_get_target_reg(struct regulator_dev *rdev)
+{
+ switch (pm_suspend_target_state) {
+ case PM_SUSPEND_STANDBY:
+ return mcp16502_get_reg(rdev, MCP16502_OPMODE_LPM);
+ case PM_SUSPEND_ON:
+ case PM_SUSPEND_MEM:
+ return mcp16502_get_reg(rdev, MCP16502_OPMODE_HIB);
+ default:
+ dev_err(&rdev->dev, "invalid suspend target: %d\n",
+ pm_suspend_target_state);
+ }
+
+ return -EINVAL;
+}
+
+/*
+ * mcp16502_set_suspend_voltage() - regulator_ops set_suspend_voltage
+ */
+static int mcp16502_set_suspend_voltage(struct regulator_dev *rdev, int uV)
+{
+ struct mcp16502 *mcp = rdev_get_drvdata(rdev);
+ int sel = regulator_map_voltage_linear_range(rdev, uV, uV);
+ int reg = mcp16502_suspend_get_target_reg(rdev);
+
+ if (sel < 0)
+ return sel;
+
+ if (reg < 0)
+ return reg;
+
+ return regmap_update_bits(mcp->rmap, reg, MCP16502_VSEL, sel);
+}
+
+/*
+ * mcp16502_set_suspend_mode() - regulator_ops set_suspend_mode
+ */
+static int mcp16502_set_suspend_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ switch (pm_suspend_target_state) {
+ case PM_SUSPEND_STANDBY:
+ return _mcp16502_set_mode(rdev, mode, MCP16502_OPMODE_LPM);
+ case PM_SUSPEND_ON:
+ case PM_SUSPEND_MEM:
+ return _mcp16502_set_mode(rdev, mode, MCP16502_OPMODE_HIB);
+ default:
+ dev_err(&rdev->dev, "invalid suspend target: %d\n",
+ pm_suspend_target_state);
+ }
+
+ return -EINVAL;
+}
+
+/*
+ * mcp16502_set_suspend_enable() - regulator_ops set_suspend_enable
+ */
+static int mcp16502_set_suspend_enable(struct regulator_dev *rdev)
+{
+ struct mcp16502 *mcp = rdev_get_drvdata(rdev);
+ int reg = mcp16502_suspend_get_target_reg(rdev);
+
+ if (reg < 0)
+ return reg;
+
+ return regmap_update_bits(mcp->rmap, reg, MCP16502_EN, MCP16502_EN);
+}
+
+/*
+ * mcp16502_set_suspend_disable() - regulator_ops set_suspend_disable
+ */
+static int mcp16502_set_suspend_disable(struct regulator_dev *rdev)
+{
+ struct mcp16502 *mcp = rdev_get_drvdata(rdev);
+ int reg = mcp16502_suspend_get_target_reg(rdev);
+
+ if (reg < 0)
+ return reg;
+
+ return regmap_update_bits(mcp->rmap, reg, MCP16502_EN, 0);
+}
+#endif /* CONFIG_SUSPEND */
+
+static const struct regulator_ops mcp16502_buck_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .get_status = mcp16502_get_status,
+
+ .set_mode = mcp16502_set_mode,
+ .get_mode = mcp16502_get_mode,
+
+#ifdef CONFIG_SUSPEND
+ .set_suspend_voltage = mcp16502_set_suspend_voltage,
+ .set_suspend_mode = mcp16502_set_suspend_mode,
+ .set_suspend_enable = mcp16502_set_suspend_enable,
+ .set_suspend_disable = mcp16502_set_suspend_disable,
+#endif /* CONFIG_SUSPEND */
+};
+
+/*
+ * LDOs cannot change operating modes.
+ */
+static const struct regulator_ops mcp16502_ldo_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .get_status = mcp16502_get_status,
+
+#ifdef CONFIG_SUSPEND
+ .set_suspend_voltage = mcp16502_set_suspend_voltage,
+ .set_suspend_enable = mcp16502_set_suspend_enable,
+ .set_suspend_disable = mcp16502_set_suspend_disable,
+#endif /* CONFIG_SUSPEND */
+};
+
+static const struct of_device_id mcp16502_ids[] = {
+ { .compatible = "microchip,mcp16502", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, mcp16502_ids);
+
+static const struct regulator_linear_range b1l12_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1200000, VDD_LOW_SEL, VDD_HIGH_SEL, 50000),
+};
+
+static const struct regulator_linear_range b234_ranges[] = {
+ REGULATOR_LINEAR_RANGE(600000, VDD_LOW_SEL, VDD_HIGH_SEL, 25000),
+};
+
+static const struct regulator_desc mcp16502_desc[] = {
+ /* MCP16502_REGULATOR(_name, _id, ranges, regulator_ops) */
+ MCP16502_REGULATOR("VDD_IO", BUCK1, b1l12_ranges, mcp16502_buck_ops),
+ MCP16502_REGULATOR("VDD_DDR", BUCK2, b234_ranges, mcp16502_buck_ops),
+ MCP16502_REGULATOR("VDD_CORE", BUCK3, b234_ranges, mcp16502_buck_ops),
+ MCP16502_REGULATOR("VDD_OTHER", BUCK4, b234_ranges, mcp16502_buck_ops),
+ MCP16502_REGULATOR("LDO1", LDO1, b1l12_ranges, mcp16502_ldo_ops),
+ MCP16502_REGULATOR("LDO2", LDO2, b1l12_ranges, mcp16502_ldo_ops)
+};
+
+static const struct regmap_range mcp16502_ranges[] = {
+ regmap_reg_range(MCP16502_MIN_REG, MCP16502_MAX_REG)
+};
+
+static const struct regmap_access_table mcp16502_yes_reg_table = {
+ .yes_ranges = mcp16502_ranges,
+ .n_yes_ranges = ARRAY_SIZE(mcp16502_ranges),
+};
+
+static const struct regmap_config mcp16502_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = MCP16502_MAX_REG,
+ .cache_type = REGCACHE_NONE,
+ .rd_table = &mcp16502_yes_reg_table,
+ .wr_table = &mcp16502_yes_reg_table,
+};
+
+/*
+ * set_up_regulators() - initialize all regulators
+ */
+static int setup_regulators(struct mcp16502 *mcp, struct device *dev,
+ struct regulator_config config)
+{
+ int i;
+
+ for (i = 0; i < NUM_REGULATORS; i++) {
+ mcp->rdev[i] = devm_regulator_register(dev,
+ &mcp16502_desc[i],
+ &config);
+ if (IS_ERR(mcp->rdev[i])) {
+ dev_err(dev,
+ "failed to register %s regulator %ld\n",
+ mcp16502_desc[i].name, PTR_ERR(mcp->rdev[i]));
+ return PTR_ERR(mcp->rdev[i]);
+ }
+ }
+
+ return 0;
+}
+
+static int mcp16502_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct regulator_config config = { };
+ struct device *dev;
+ struct mcp16502 *mcp;
+ int ret = 0;
+
+ dev = &client->dev;
+ config.dev = dev;
+
+ mcp = devm_kzalloc(dev, sizeof(*mcp), GFP_KERNEL);
+ if (!mcp)
+ return -ENOMEM;
+
+ mcp->rmap = devm_regmap_init_i2c(client, &mcp16502_regmap_config);
+ if (IS_ERR(mcp->rmap)) {
+ ret = PTR_ERR(mcp->rmap);
+ dev_err(dev, "regmap init failed: %d\n", ret);
+ return ret;
+ }
+
+ i2c_set_clientdata(client, mcp);
+ config.regmap = mcp->rmap;
+ config.driver_data = mcp;
+
+ mcp->lpm = devm_gpiod_get(dev, "lpm", GPIOD_OUT_LOW);
+ if (IS_ERR(mcp->lpm)) {
+ dev_err(dev, "failed to get lpm pin: %ld\n", PTR_ERR(mcp->lpm));
+ return PTR_ERR(mcp->lpm);
+ }
+
+ ret = setup_regulators(mcp, dev, config);
+ if (ret != 0)
+ return ret;
+
+ mcp16502_gpio_set_mode(mcp, MCP16502_OPMODE_ACTIVE);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mcp16502_suspend_noirq(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mcp16502 *mcp = i2c_get_clientdata(client);
+
+ mcp16502_gpio_set_mode(mcp, MCP16502_OPMODE_LPM);
+
+ return 0;
+}
+
+static int mcp16502_resume_noirq(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mcp16502 *mcp = i2c_get_clientdata(client);
+
+ mcp16502_gpio_set_mode(mcp, MCP16502_OPMODE_ACTIVE);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_PM
+static const struct dev_pm_ops mcp16502_pm_ops = {
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mcp16502_suspend_noirq,
+ mcp16502_resume_noirq)
+};
+#endif
+static const struct i2c_device_id mcp16502_i2c_id[] = {
+ { "mcp16502", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mcp16502_i2c_id);
+
+static struct i2c_driver mcp16502_drv = {
+ .probe = mcp16502_probe,
+ .driver = {
+ .name = "mcp16502-regulator",
+ .of_match_table = of_match_ptr(mcp16502_ids),
+#ifdef CONFIG_PM
+ .pm = &mcp16502_pm_ops,
+#endif
+ },
+ .id_table = mcp16502_i2c_id,
+};
+
+module_i2c_driver(mcp16502_drv);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MCP16502 PMIC driver");
+MODULE_AUTHOR("Andrei Stefanescu andrei.stefanescu@microchip.com");
diff --git a/drivers/regulator/mt6311-regulator.c b/drivers/regulator/mt6311-regulator.c
index 0495716fd35f..01d69f43d2b0 100644
--- a/drivers/regulator/mt6311-regulator.c
+++ b/drivers/regulator/mt6311-regulator.c
@@ -38,13 +38,9 @@ static const struct regmap_config mt6311_regmap_config = {
#define MT6311_MAX_UV 1393750
#define MT6311_STEP_UV 6250
-static const struct regulator_linear_range buck_volt_range[] = {
- REGULATOR_LINEAR_RANGE(MT6311_MIN_UV, 0, 0x7f, MT6311_STEP_UV),
-};
-
static const struct regulator_ops mt6311_buck_ops = {
- .list_voltage = regulator_list_voltage_linear_range,
- .map_voltage = regulator_map_voltage_linear_range,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
.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,
@@ -71,8 +67,6 @@ static const struct regulator_ops mt6311_ldo_ops = {
.min_uV = MT6311_MIN_UV,\
.uV_step = MT6311_STEP_UV,\
.owner = THIS_MODULE,\
- .linear_ranges = buck_volt_range, \
- .n_linear_ranges = ARRAY_SIZE(buck_volt_range), \
.enable_reg = MT6311_VDVFS11_CON9,\
.enable_mask = MT6311_PMIC_VDVFS11_EN_MASK,\
.vsel_reg = MT6311_VDVFS11_CON12,\
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index c4223b3e0dff..7b6bf3536271 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -20,6 +20,7 @@
#include "internal.h"
static const char *const regulator_states[PM_SUSPEND_MAX + 1] = {
+ [PM_SUSPEND_STANDBY] = "regulator-state-standby",
[PM_SUSPEND_MEM] = "regulator-state-mem",
[PM_SUSPEND_MAX] = "regulator-state-disk",
};
@@ -170,6 +171,10 @@ static void of_get_regulation_constraints(struct device_node *np,
&pval))
constraints->max_spread = pval;
+ if (!of_property_read_u32(np, "regulator-max-step-microvolt",
+ &pval))
+ constraints->max_uV_step = pval;
+
constraints->over_current_protection = of_property_read_bool(np,
"regulator-over-current-protection");
@@ -181,9 +186,11 @@ static void of_get_regulation_constraints(struct device_node *np,
case PM_SUSPEND_MAX:
suspend_state = &constraints->state_disk;
break;
+ case PM_SUSPEND_STANDBY:
+ suspend_state = &constraints->state_standby;
+ break;
case PM_SUSPEND_ON:
case PM_SUSPEND_TO_IDLE:
- case PM_SUSPEND_STANDBY:
default:
continue;
}
@@ -248,7 +255,7 @@ static void of_get_regulation_constraints(struct device_node *np,
* @desc: regulator description
*
* Populates regulator_init_data structure by extracting data from device
- * tree node, returns a pointer to the populated struture or NULL if memory
+ * tree node, returns a pointer to the populated structure or NULL if memory
* alloc fails.
*/
struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
@@ -364,24 +371,25 @@ int of_regulator_match(struct device *dev, struct device_node *node,
}
EXPORT_SYMBOL_GPL(of_regulator_match);
-struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
- const struct regulator_desc *desc,
- struct regulator_config *config,
- struct device_node **node)
+struct device_node *regulator_of_get_init_node(struct device *dev,
+ const struct regulator_desc *desc)
{
struct device_node *search, *child;
- struct regulator_init_data *init_data = NULL;
const char *name;
if (!dev->of_node || !desc->of_match)
return NULL;
- if (desc->regulators_node)
+ if (desc->regulators_node) {
search = of_get_child_by_name(dev->of_node,
desc->regulators_node);
- else
+ } else {
search = of_node_get(dev->of_node);
+ if (!strcmp(desc->of_match, search->name))
+ return search;
+ }
+
if (!search) {
dev_dbg(dev, "Failed to find regulator container node '%s'\n",
desc->regulators_node);
@@ -393,35 +401,48 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
if (!name)
name = child->name;
- if (strcmp(desc->of_match, name))
- continue;
+ if (!strcmp(desc->of_match, name))
+ return of_node_get(child);
+ }
- init_data = of_get_regulator_init_data(dev, child, desc);
- if (!init_data) {
- dev_err(dev,
- "failed to parse DT for regulator %pOFn\n",
- child);
- break;
- }
+ of_node_put(search);
- if (desc->of_parse_cb) {
- if (desc->of_parse_cb(child, desc, config)) {
- dev_err(dev,
- "driver callback failed to parse DT for regulator %pOFn\n",
- child);
- init_data = NULL;
- break;
- }
- }
+ return NULL;
+}
+
+struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
+ const struct regulator_desc *desc,
+ struct regulator_config *config,
+ struct device_node **node)
+{
+ struct device_node *child;
+ struct regulator_init_data *init_data = NULL;
- of_node_get(child);
- *node = child;
- break;
+ child = regulator_of_get_init_node(dev, desc);
+ if (!child)
+ return NULL;
+
+ init_data = of_get_regulator_init_data(dev, child, desc);
+ if (!init_data) {
+ dev_err(dev, "failed to parse DT for regulator %pOFn\n", child);
+ goto error;
}
- of_node_put(search);
+ if (desc->of_parse_cb && desc->of_parse_cb(child, desc, config)) {
+ dev_err(dev,
+ "driver callback failed to parse DT for regulator %pOFn\n",
+ child);
+ goto error;
+ }
+
+ *node = child;
return init_data;
+
+error:
+ of_node_put(child);
+
+ return NULL;
}
static int of_node_match(struct device *dev, const void *data)
@@ -526,7 +547,7 @@ bool of_check_coupling_data(struct regulator_dev *rdev)
NULL);
if (c_n_phandles != n_phandles) {
- dev_err(&rdev->dev, "number of couped reg phandles mismatch\n");
+ dev_err(&rdev->dev, "number of coupled reg phandles mismatch\n");
ret = false;
goto clean;
}
diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
index bb5ab7d78895..7fb9e8dd834e 100644
--- a/drivers/regulator/palmas-regulator.c
+++ b/drivers/regulator/palmas-regulator.c
@@ -382,7 +382,7 @@ static struct palmas_sleep_requestor_info tps65917_sleep_req_info[] = {
EXTERNAL_REQUESTOR_TPS65917(LDO5, 2, 4),
};
-static unsigned int palmas_smps_ramp_delay[4] = {0, 10000, 5000, 2500};
+static const unsigned int palmas_smps_ramp_delay[4] = {0, 10000, 5000, 2500};
#define SMPS_CTRL_MODE_OFF 0x00
#define SMPS_CTRL_MODE_ON 0x01
@@ -443,13 +443,16 @@ static int palmas_ldo_write(struct palmas *palmas, unsigned int reg,
static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode)
{
int id = rdev_get_id(dev);
+ int ret;
struct palmas_pmic *pmic = rdev_get_drvdata(dev);
struct palmas_pmic_driver_data *ddata = pmic->palmas->pmic_ddata;
struct palmas_regs_info *rinfo = &ddata->palmas_regs_info[id];
unsigned int reg;
bool rail_enable = true;
- palmas_smps_read(pmic->palmas, rinfo->ctrl_addr, &reg);
+ ret = palmas_smps_read(pmic->palmas, rinfo->ctrl_addr, &reg);
+ if (ret)
+ return ret;
reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c
index dd41a9bb3f5c..df5df1c495ad 100644
--- a/drivers/regulator/pfuze100-regulator.c
+++ b/drivers/regulator/pfuze100-regulator.c
@@ -370,6 +370,7 @@ static struct pfuze_regulator pfuze100_regulators[] = {
PFUZE100_VGEN_REG(PFUZE100, VGEN4, PFUZE100_VGEN4VOL, 1800000, 3300000, 100000),
PFUZE100_VGEN_REG(PFUZE100, VGEN5, PFUZE100_VGEN5VOL, 1800000, 3300000, 100000),
PFUZE100_VGEN_REG(PFUZE100, VGEN6, PFUZE100_VGEN6VOL, 1800000, 3300000, 100000),
+ PFUZE100_COIN_REG(PFUZE100, COIN, PFUZE100_COINVOL, 0x7, pfuze100_coin),
};
static struct pfuze_regulator pfuze200_regulators[] = {
@@ -436,6 +437,7 @@ static struct of_regulator_match pfuze100_matches[] = {
{ .name = "vgen4", },
{ .name = "vgen5", },
{ .name = "vgen6", },
+ { .name = "coin", },
};
/* PFUZE200 */
diff --git a/drivers/regulator/pv88060-regulator.c b/drivers/regulator/pv88060-regulator.c
index a9446056435f..1600f9821891 100644
--- a/drivers/regulator/pv88060-regulator.c
+++ b/drivers/regulator/pv88060-regulator.c
@@ -53,10 +53,6 @@ enum {
struct pv88060_regulator {
struct regulator_desc desc;
- /* Current limiting */
- unsigned n_current_limits;
- const int *current_limits;
- unsigned int limit_mask;
unsigned int conf; /* buck configuration register */
};
@@ -75,7 +71,7 @@ static const struct regmap_config pv88060_regmap_config = {
* Entry indexes corresponds to register values.
*/
-static const int pv88060_buck1_limits[] = {
+static const unsigned int pv88060_buck1_limits[] = {
1496000, 2393000, 3291000, 4189000
};
@@ -128,40 +124,6 @@ static int pv88060_buck_set_mode(struct regulator_dev *rdev,
PV88060_BUCK_MODE_MASK, val);
}
-static int pv88060_set_current_limit(struct regulator_dev *rdev, int min,
- int max)
-{
- struct pv88060_regulator *info = rdev_get_drvdata(rdev);
- int i;
-
- /* search for closest to maximum */
- for (i = info->n_current_limits; i >= 0; i--) {
- if (min <= info->current_limits[i]
- && max >= info->current_limits[i]) {
- return regmap_update_bits(rdev->regmap,
- info->conf,
- info->limit_mask,
- i << PV88060_BUCK_ILIM_SHIFT);
- }
- }
-
- return -EINVAL;
-}
-
-static int pv88060_get_current_limit(struct regulator_dev *rdev)
-{
- struct pv88060_regulator *info = rdev_get_drvdata(rdev);
- unsigned int data;
- int ret;
-
- ret = regmap_read(rdev->regmap, info->conf, &data);
- if (ret < 0)
- return ret;
-
- data = (data & info->limit_mask) >> PV88060_BUCK_ILIM_SHIFT;
- return info->current_limits[data];
-}
-
static const struct regulator_ops pv88060_buck_ops = {
.get_mode = pv88060_buck_get_mode,
.set_mode = pv88060_buck_set_mode,
@@ -171,8 +133,8 @@ static const struct regulator_ops pv88060_buck_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
- .set_current_limit = pv88060_set_current_limit,
- .get_current_limit = pv88060_get_current_limit,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .get_current_limit = regulator_get_current_limit_regmap,
};
static const struct regulator_ops pv88060_ldo_ops = {
@@ -184,6 +146,12 @@ static const struct regulator_ops pv88060_ldo_ops = {
.list_voltage = regulator_list_voltage_linear,
};
+static const struct regulator_ops pv88060_sw_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
#define PV88060_BUCK(chip, regl_name, min, step, max, limits_array) \
{\
.desc = {\
@@ -201,10 +169,11 @@ static const struct regulator_ops pv88060_ldo_ops = {
.enable_mask = PV88060_BUCK_EN, \
.vsel_reg = PV88060_REG_##regl_name##_CONF0,\
.vsel_mask = PV88060_VBUCK_MASK,\
+ .curr_table = limits_array,\
+ .n_current_limits = ARRAY_SIZE(limits_array),\
+ .csel_reg = PV88060_REG_##regl_name##_CONF1,\
+ .csel_mask = PV88060_BUCK_ILIM_MASK,\
},\
- .current_limits = limits_array,\
- .n_current_limits = ARRAY_SIZE(limits_array),\
- .limit_mask = PV88060_BUCK_ILIM_MASK, \
.conf = PV88060_REG_##regl_name##_CONF1,\
}
@@ -237,9 +206,8 @@ static const struct regulator_ops pv88060_ldo_ops = {
.regulators_node = of_match_ptr("regulators"),\
.type = REGULATOR_VOLTAGE,\
.owner = THIS_MODULE,\
- .ops = &pv88060_ldo_ops,\
- .min_uV = max,\
- .uV_step = 0,\
+ .ops = &pv88060_sw_ops,\
+ .fixed_uV = max,\
.n_voltages = 1,\
.enable_reg = PV88060_REG_##regl_name##_CONF,\
.enable_mask = PV88060_SW_EN,\
diff --git a/drivers/regulator/pv88080-regulator.c b/drivers/regulator/pv88080-regulator.c
index 9a08cb2de501..bdddacdbeb99 100644
--- a/drivers/regulator/pv88080-regulator.c
+++ b/drivers/regulator/pv88080-regulator.c
@@ -45,12 +45,7 @@ enum pv88080_types {
struct pv88080_regulator {
struct regulator_desc desc;
- /* Current limiting */
- unsigned int n_current_limits;
- const int *current_limits;
- unsigned int limit_mask;
unsigned int mode_reg;
- unsigned int limit_reg;
unsigned int conf2;
unsigned int conf5;
};
@@ -102,11 +97,11 @@ static const struct regmap_config pv88080_regmap_config = {
* Entry indexes corresponds to register values.
*/
-static const int pv88080_buck1_limits[] = {
+static const unsigned int pv88080_buck1_limits[] = {
3230000, 5130000, 6960000, 8790000
};
-static const int pv88080_buck23_limits[] = {
+static const unsigned int pv88080_buck23_limits[] = {
1496000, 2393000, 3291000, 4189000
};
@@ -272,40 +267,6 @@ static int pv88080_buck_set_mode(struct regulator_dev *rdev,
PV88080_BUCK1_MODE_MASK, val);
}
-static int pv88080_set_current_limit(struct regulator_dev *rdev, int min,
- int max)
-{
- struct pv88080_regulator *info = rdev_get_drvdata(rdev);
- int i;
-
- /* search for closest to maximum */
- for (i = info->n_current_limits; i >= 0; i--) {
- if (min <= info->current_limits[i]
- && max >= info->current_limits[i]) {
- return regmap_update_bits(rdev->regmap,
- info->limit_reg,
- info->limit_mask,
- i << PV88080_BUCK1_ILIM_SHIFT);
- }
- }
-
- return -EINVAL;
-}
-
-static int pv88080_get_current_limit(struct regulator_dev *rdev)
-{
- struct pv88080_regulator *info = rdev_get_drvdata(rdev);
- unsigned int data;
- int ret;
-
- ret = regmap_read(rdev->regmap, info->limit_reg, &data);
- if (ret < 0)
- return ret;
-
- data = (data & info->limit_mask) >> PV88080_BUCK1_ILIM_SHIFT;
- return info->current_limits[data];
-}
-
static const struct regulator_ops pv88080_buck_ops = {
.get_mode = pv88080_buck_get_mode,
.set_mode = pv88080_buck_set_mode,
@@ -315,8 +276,8 @@ static const struct regulator_ops pv88080_buck_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
- .set_current_limit = pv88080_set_current_limit,
- .get_current_limit = pv88080_get_current_limit,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .get_current_limit = regulator_get_current_limit_regmap,
};
static const struct regulator_ops pv88080_hvbuck_ops = {
@@ -341,9 +302,9 @@ static const struct regulator_ops pv88080_hvbuck_ops = {
.min_uV = min, \
.uV_step = step, \
.n_voltages = ((max) - (min))/(step) + 1, \
+ .curr_table = limits_array, \
+ .n_current_limits = ARRAY_SIZE(limits_array), \
},\
- .current_limits = limits_array, \
- .n_current_limits = ARRAY_SIZE(limits_array), \
}
#define PV88080_HVBUCK(chip, regl_name, min, step, max) \
@@ -521,9 +482,9 @@ static int pv88080_i2c_probe(struct i2c_client *i2c,
if (init_data)
config.init_data = &init_data[i];
- pv88080_regulator_info[i].limit_reg
+ pv88080_regulator_info[i].desc.csel_reg
= regmap_config->buck_regmap[i].buck_limit_reg;
- pv88080_regulator_info[i].limit_mask
+ pv88080_regulator_info[i].desc.csel_mask
= regmap_config->buck_regmap[i].buck_limit_mask;
pv88080_regulator_info[i].mode_reg
= regmap_config->buck_regmap[i].buck_mode_reg;
diff --git a/drivers/regulator/pv88090-regulator.c b/drivers/regulator/pv88090-regulator.c
index 7a0c15957bd0..6e97cc6df2ee 100644
--- a/drivers/regulator/pv88090-regulator.c
+++ b/drivers/regulator/pv88090-regulator.c
@@ -42,10 +42,6 @@ enum {
struct pv88090_regulator {
struct regulator_desc desc;
- /* Current limiting */
- unsigned int n_current_limits;
- const int *current_limits;
- unsigned int limit_mask;
unsigned int conf;
unsigned int conf2;
};
@@ -71,14 +67,14 @@ static const struct regmap_config pv88090_regmap_config = {
* Entry indexes corresponds to register values.
*/
-static const int pv88090_buck1_limits[] = {
+static const unsigned int pv88090_buck1_limits[] = {
220000, 440000, 660000, 880000, 1100000, 1320000, 1540000, 1760000,
1980000, 2200000, 2420000, 2640000, 2860000, 3080000, 3300000, 3520000,
3740000, 3960000, 4180000, 4400000, 4620000, 4840000, 5060000, 5280000,
5500000, 5720000, 5940000, 6160000, 6380000, 6600000, 6820000, 7040000
};
-static const int pv88090_buck23_limits[] = {
+static const unsigned int pv88090_buck23_limits[] = {
1496000, 2393000, 3291000, 4189000
};
@@ -150,40 +146,6 @@ static int pv88090_buck_set_mode(struct regulator_dev *rdev,
PV88090_BUCK1_MODE_MASK, val);
}
-static int pv88090_set_current_limit(struct regulator_dev *rdev, int min,
- int max)
-{
- struct pv88090_regulator *info = rdev_get_drvdata(rdev);
- int i;
-
- /* search for closest to maximum */
- for (i = info->n_current_limits; i >= 0; i--) {
- if (min <= info->current_limits[i]
- && max >= info->current_limits[i]) {
- return regmap_update_bits(rdev->regmap,
- info->conf,
- info->limit_mask,
- i << PV88090_BUCK1_ILIM_SHIFT);
- }
- }
-
- return -EINVAL;
-}
-
-static int pv88090_get_current_limit(struct regulator_dev *rdev)
-{
- struct pv88090_regulator *info = rdev_get_drvdata(rdev);
- unsigned int data;
- int ret;
-
- ret = regmap_read(rdev->regmap, info->conf, &data);
- if (ret < 0)
- return ret;
-
- data = (data & info->limit_mask) >> PV88090_BUCK1_ILIM_SHIFT;
- return info->current_limits[data];
-}
-
static const struct regulator_ops pv88090_buck_ops = {
.get_mode = pv88090_buck_get_mode,
.set_mode = pv88090_buck_set_mode,
@@ -193,8 +155,8 @@ static const struct regulator_ops pv88090_buck_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
- .set_current_limit = pv88090_set_current_limit,
- .get_current_limit = pv88090_get_current_limit,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .get_current_limit = regulator_get_current_limit_regmap,
};
static const struct regulator_ops pv88090_ldo_ops = {
@@ -223,10 +185,11 @@ static const struct regulator_ops pv88090_ldo_ops = {
.enable_mask = PV88090_##regl_name##_EN, \
.vsel_reg = PV88090_REG_##regl_name##_CONF0, \
.vsel_mask = PV88090_V##regl_name##_MASK, \
+ .curr_table = limits_array, \
+ .n_current_limits = ARRAY_SIZE(limits_array), \
+ .csel_reg = PV88090_REG_##regl_name##_CONF1, \
+ .csel_mask = PV88090_##regl_name##_ILIM_MASK, \
},\
- .current_limits = limits_array, \
- .n_current_limits = ARRAY_SIZE(limits_array), \
- .limit_mask = PV88090_##regl_name##_ILIM_MASK, \
.conf = PV88090_REG_##regl_name##_CONF1, \
.conf2 = PV88090_REG_##regl_name##_CONF2, \
}
diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c
index a2fd140eff81..3f53f9134b32 100644
--- a/drivers/regulator/pwm-regulator.c
+++ b/drivers/regulator/pwm-regulator.c
@@ -40,9 +40,6 @@ struct pwm_regulator_data {
/* regulator descriptor */
struct regulator_desc desc;
- /* Regulator ops */
- struct regulator_ops ops;
-
int state;
/* Enable GPIO */
@@ -231,7 +228,7 @@ static int pwm_regulator_set_voltage(struct regulator_dev *rdev,
return 0;
}
-static struct regulator_ops pwm_regulator_voltage_table_ops = {
+static const struct regulator_ops pwm_regulator_voltage_table_ops = {
.set_voltage_sel = pwm_regulator_set_voltage_sel,
.get_voltage_sel = pwm_regulator_get_voltage_sel,
.list_voltage = pwm_regulator_list_voltage,
@@ -241,7 +238,7 @@ static struct regulator_ops pwm_regulator_voltage_table_ops = {
.is_enabled = pwm_regulator_is_enabled,
};
-static struct regulator_ops pwm_regulator_voltage_continuous_ops = {
+static const struct regulator_ops pwm_regulator_voltage_continuous_ops = {
.get_voltage = pwm_regulator_get_voltage,
.set_voltage = pwm_regulator_set_voltage,
.enable = pwm_regulator_enable,
@@ -249,7 +246,7 @@ static struct regulator_ops pwm_regulator_voltage_continuous_ops = {
.is_enabled = pwm_regulator_is_enabled,
};
-static struct regulator_desc pwm_regulator_desc = {
+static const struct regulator_desc pwm_regulator_desc = {
.name = "pwm-regulator",
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
@@ -287,9 +284,7 @@ static int pwm_regulator_init_table(struct platform_device *pdev,
drvdata->state = -EINVAL;
drvdata->duty_cycle_table = duty_cycle_table;
- memcpy(&drvdata->ops, &pwm_regulator_voltage_table_ops,
- sizeof(drvdata->ops));
- drvdata->desc.ops = &drvdata->ops;
+ drvdata->desc.ops = &pwm_regulator_voltage_table_ops;
drvdata->desc.n_voltages = length / sizeof(*duty_cycle_table);
return 0;
@@ -301,9 +296,7 @@ static int pwm_regulator_init_continuous(struct platform_device *pdev,
u32 dutycycle_range[2] = { 0, 100 };
u32 dutycycle_unit = 100;
- memcpy(&drvdata->ops, &pwm_regulator_voltage_continuous_ops,
- sizeof(drvdata->ops));
- drvdata->desc.ops = &drvdata->ops;
+ drvdata->desc.ops = &pwm_regulator_voltage_continuous_ops;
drvdata->desc.continuous_voltage_range = true;
of_property_read_u32_array(pdev->dev.of_node,
diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c
index 39ccf53fdeb3..b2c2d01d1637 100644
--- a/drivers/regulator/qcom-rpmh-regulator.c
+++ b/drivers/regulator/qcom-rpmh-regulator.c
@@ -410,7 +410,7 @@ static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev,
vreg->dev = dev;
for (rpmh_data = pmic_rpmh_data; rpmh_data->name; rpmh_data++)
- if (!strcmp(rpmh_data->name, node->name))
+ if (of_node_name_eq(node, rpmh_data->name))
break;
if (!rpmh_data->name) {
diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c
index f5bca77d67c1..68bc23df4213 100644
--- a/drivers/regulator/qcom_smd-regulator.c
+++ b/drivers/regulator/qcom_smd-regulator.c
@@ -31,6 +31,11 @@ struct qcom_rpm_reg {
int is_enabled;
int uV;
+ u32 load;
+
+ unsigned int enabled_updated:1;
+ unsigned int uv_updated:1;
+ unsigned int load_updated:1;
};
struct rpm_regulator_req {
@@ -43,30 +48,59 @@ struct rpm_regulator_req {
#define RPM_KEY_UV 0x00007675 /* "uv" */
#define RPM_KEY_MA 0x0000616d /* "ma" */
-static int rpm_reg_write_active(struct qcom_rpm_reg *vreg,
- struct rpm_regulator_req *req,
- size_t size)
+static int rpm_reg_write_active(struct qcom_rpm_reg *vreg)
{
- return qcom_rpm_smd_write(vreg->rpm,
- QCOM_SMD_RPM_ACTIVE_STATE,
- vreg->type,
- vreg->id,
- req, size);
+ struct rpm_regulator_req req[3];
+ int reqlen = 0;
+ int ret;
+
+ if (vreg->enabled_updated) {
+ req[reqlen].key = cpu_to_le32(RPM_KEY_SWEN);
+ req[reqlen].nbytes = cpu_to_le32(sizeof(u32));
+ req[reqlen].value = cpu_to_le32(vreg->is_enabled);
+ reqlen++;
+ }
+
+ if (vreg->uv_updated && vreg->is_enabled) {
+ req[reqlen].key = cpu_to_le32(RPM_KEY_UV);
+ req[reqlen].nbytes = cpu_to_le32(sizeof(u32));
+ req[reqlen].value = cpu_to_le32(vreg->uV);
+ reqlen++;
+ }
+
+ if (vreg->load_updated && vreg->is_enabled) {
+ req[reqlen].key = cpu_to_le32(RPM_KEY_MA);
+ req[reqlen].nbytes = cpu_to_le32(sizeof(u32));
+ req[reqlen].value = cpu_to_le32(vreg->load / 1000);
+ reqlen++;
+ }
+
+ if (!reqlen)
+ return 0;
+
+ ret = qcom_rpm_smd_write(vreg->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
+ vreg->type, vreg->id,
+ req, sizeof(req[0]) * reqlen);
+ if (!ret) {
+ vreg->enabled_updated = 0;
+ vreg->uv_updated = 0;
+ vreg->load_updated = 0;
+ }
+
+ return ret;
}
static int rpm_reg_enable(struct regulator_dev *rdev)
{
struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
- struct rpm_regulator_req req;
int ret;
- req.key = cpu_to_le32(RPM_KEY_SWEN);
- req.nbytes = cpu_to_le32(sizeof(u32));
- req.value = cpu_to_le32(1);
+ vreg->is_enabled = 1;
+ vreg->enabled_updated = 1;
- ret = rpm_reg_write_active(vreg, &req, sizeof(req));
- if (!ret)
- vreg->is_enabled = 1;
+ ret = rpm_reg_write_active(vreg);
+ if (ret)
+ vreg->is_enabled = 0;
return ret;
}
@@ -81,16 +115,14 @@ static int rpm_reg_is_enabled(struct regulator_dev *rdev)
static int rpm_reg_disable(struct regulator_dev *rdev)
{
struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
- struct rpm_regulator_req req;
int ret;
- req.key = cpu_to_le32(RPM_KEY_SWEN);
- req.nbytes = cpu_to_le32(sizeof(u32));
- req.value = 0;
+ vreg->is_enabled = 0;
+ vreg->enabled_updated = 1;
- ret = rpm_reg_write_active(vreg, &req, sizeof(req));
- if (!ret)
- vreg->is_enabled = 0;
+ ret = rpm_reg_write_active(vreg);
+ if (ret)
+ vreg->is_enabled = 1;
return ret;
}
@@ -108,16 +140,15 @@ static int rpm_reg_set_voltage(struct regulator_dev *rdev,
unsigned *selector)
{
struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
- struct rpm_regulator_req req;
- int ret = 0;
+ int ret;
+ int old_uV = vreg->uV;
- req.key = cpu_to_le32(RPM_KEY_UV);
- req.nbytes = cpu_to_le32(sizeof(u32));
- req.value = cpu_to_le32(min_uV);
+ vreg->uV = min_uV;
+ vreg->uv_updated = 1;
- ret = rpm_reg_write_active(vreg, &req, sizeof(req));
- if (!ret)
- vreg->uV = min_uV;
+ ret = rpm_reg_write_active(vreg);
+ if (ret)
+ vreg->uV = old_uV;
return ret;
}
@@ -125,13 +156,16 @@ static int rpm_reg_set_voltage(struct regulator_dev *rdev,
static int rpm_reg_set_load(struct regulator_dev *rdev, int load_uA)
{
struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
- struct rpm_regulator_req req;
+ u32 old_load = vreg->load;
+ int ret;
- req.key = cpu_to_le32(RPM_KEY_MA);
- req.nbytes = cpu_to_le32(sizeof(u32));
- req.value = cpu_to_le32(load_uA / 1000);
+ vreg->load = load_uA;
+ vreg->load_updated = 1;
+ ret = rpm_reg_write_active(vreg);
+ if (ret)
+ vreg->load = old_load;
- return rpm_reg_write_active(vreg, &req, sizeof(req));
+ return ret;
}
static const struct regulator_ops rpm_smps_ldo_ops = {
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index 213b68743cc8..23713e16c286 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -1,5 +1,5 @@
/*
- * Regulator driver for Rockchip RK808/RK818
+ * Regulator driver for Rockchip RK805/RK808/RK818
*
* Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
*
@@ -363,28 +363,28 @@ static int rk808_set_suspend_disable(struct regulator_dev *rdev)
rdev->desc->enable_mask);
}
-static struct regulator_ops rk805_reg_ops = {
- .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,
- .enable = regulator_enable_regmap,
- .disable = regulator_disable_regmap,
- .is_enabled = regulator_is_enabled_regmap,
- .set_suspend_voltage = rk808_set_suspend_voltage,
- .set_suspend_enable = rk805_set_suspend_enable,
- .set_suspend_disable = rk805_set_suspend_disable,
+static const struct regulator_ops rk805_reg_ops = {
+ .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,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_suspend_voltage = rk808_set_suspend_voltage,
+ .set_suspend_enable = rk805_set_suspend_enable,
+ .set_suspend_disable = rk805_set_suspend_disable,
};
-static struct regulator_ops rk805_switch_ops = {
- .enable = regulator_enable_regmap,
- .disable = regulator_disable_regmap,
- .is_enabled = regulator_is_enabled_regmap,
- .set_suspend_enable = rk805_set_suspend_enable,
- .set_suspend_disable = rk805_set_suspend_disable,
+static const struct regulator_ops rk805_switch_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_suspend_enable = rk805_set_suspend_enable,
+ .set_suspend_disable = rk805_set_suspend_disable,
};
-static struct regulator_ops rk808_buck1_2_ops = {
+static const struct regulator_ops rk808_buck1_2_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = rk808_buck1_2_get_voltage_sel_regmap,
@@ -399,7 +399,7 @@ static struct regulator_ops rk808_buck1_2_ops = {
.set_suspend_disable = rk808_set_suspend_disable,
};
-static struct regulator_ops rk808_reg_ops = {
+static const struct regulator_ops rk808_reg_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
@@ -412,7 +412,7 @@ static struct regulator_ops rk808_reg_ops = {
.set_suspend_disable = rk808_set_suspend_disable,
};
-static struct regulator_ops rk808_reg_ops_ranges = {
+static const struct regulator_ops rk808_reg_ops_ranges = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
@@ -425,7 +425,7 @@ static struct regulator_ops rk808_reg_ops_ranges = {
.set_suspend_disable = rk808_set_suspend_disable,
};
-static struct regulator_ops rk808_switch_ops = {
+static const struct regulator_ops rk808_switch_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -433,6 +433,12 @@ static struct regulator_ops rk808_switch_ops = {
.set_suspend_disable = rk808_set_suspend_disable,
};
+static const struct regulator_linear_range rk805_buck_1_2_voltage_ranges[] = {
+ REGULATOR_LINEAR_RANGE(712500, 0, 59, 12500),
+ REGULATOR_LINEAR_RANGE(1800000, 60, 62, 200000),
+ REGULATOR_LINEAR_RANGE(2300000, 63, 63, 0),
+};
+
static const struct regulator_desc rk805_reg[] = {
{
.name = "DCDC_REG1",
@@ -440,11 +446,11 @@ static const struct regulator_desc rk805_reg[] = {
.of_match = of_match_ptr("DCDC_REG1"),
.regulators_node = of_match_ptr("regulators"),
.id = RK805_ID_DCDC1,
- .ops = &rk805_reg_ops,
+ .ops = &rk808_reg_ops_ranges,
.type = REGULATOR_VOLTAGE,
- .min_uV = 712500,
- .uV_step = 12500,
.n_voltages = 64,
+ .linear_ranges = rk805_buck_1_2_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk805_buck_1_2_voltage_ranges),
.vsel_reg = RK805_BUCK1_ON_VSEL_REG,
.vsel_mask = RK818_BUCK_VSEL_MASK,
.enable_reg = RK805_DCDC_EN_REG,
@@ -456,11 +462,11 @@ static const struct regulator_desc rk805_reg[] = {
.of_match = of_match_ptr("DCDC_REG2"),
.regulators_node = of_match_ptr("regulators"),
.id = RK805_ID_DCDC2,
- .ops = &rk805_reg_ops,
+ .ops = &rk808_reg_ops_ranges,
.type = REGULATOR_VOLTAGE,
- .min_uV = 712500,
- .uV_step = 12500,
.n_voltages = 64,
+ .linear_ranges = rk805_buck_1_2_voltage_ranges,
+ .n_linear_ranges = ARRAY_SIZE(rk805_buck_1_2_voltage_ranges),
.vsel_reg = RK805_BUCK2_ON_VSEL_REG,
.vsel_mask = RK818_BUCK_VSEL_MASK,
.enable_reg = RK805_DCDC_EN_REG,
@@ -796,7 +802,7 @@ static struct platform_driver rk808_regulator_driver = {
module_platform_driver(rk808_regulator_driver);
-MODULE_DESCRIPTION("regulator driver for the RK808/RK818 series PMICs");
+MODULE_DESCRIPTION("regulator driver for the RK805/RK808/RK818 series PMICs");
MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
diff --git a/drivers/regulator/rt5033-regulator.c b/drivers/regulator/rt5033-regulator.c
index 96d2c18e051a..639cbadc044a 100644
--- a/drivers/regulator/rt5033-regulator.c
+++ b/drivers/regulator/rt5033-regulator.c
@@ -16,14 +16,14 @@
#include <linux/mfd/rt5033-private.h>
#include <linux/regulator/of_regulator.h>
-static struct regulator_ops rt5033_safe_ldo_ops = {
+static const struct regulator_ops rt5033_safe_ldo_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.list_voltage = regulator_list_voltage_linear,
};
-static struct regulator_ops rt5033_buck_ops = {
+static const struct regulator_ops rt5033_buck_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
diff --git a/drivers/regulator/s2mpa01.c b/drivers/regulator/s2mpa01.c
index 095d25f3d2ea..58a1fe583a6c 100644
--- a/drivers/regulator/s2mpa01.c
+++ b/drivers/regulator/s2mpa01.c
@@ -298,13 +298,13 @@ static const struct regulator_desc regulators[] = {
regulator_desc_ldo(2, STEP_50_MV),
regulator_desc_ldo(3, STEP_50_MV),
regulator_desc_ldo(4, STEP_50_MV),
- regulator_desc_ldo(5, STEP_50_MV),
+ regulator_desc_ldo(5, STEP_25_MV),
regulator_desc_ldo(6, STEP_25_MV),
regulator_desc_ldo(7, STEP_50_MV),
regulator_desc_ldo(8, STEP_50_MV),
regulator_desc_ldo(9, STEP_50_MV),
regulator_desc_ldo(10, STEP_50_MV),
- regulator_desc_ldo(11, STEP_25_MV),
+ regulator_desc_ldo(11, STEP_50_MV),
regulator_desc_ldo(12, STEP_50_MV),
regulator_desc_ldo(13, STEP_50_MV),
regulator_desc_ldo(14, STEP_50_MV),
@@ -315,11 +315,11 @@ static const struct regulator_desc regulators[] = {
regulator_desc_ldo(19, STEP_50_MV),
regulator_desc_ldo(20, STEP_50_MV),
regulator_desc_ldo(21, STEP_50_MV),
- regulator_desc_ldo(22, STEP_25_MV),
- regulator_desc_ldo(23, STEP_25_MV),
+ regulator_desc_ldo(22, STEP_50_MV),
+ regulator_desc_ldo(23, STEP_50_MV),
regulator_desc_ldo(24, STEP_50_MV),
regulator_desc_ldo(25, STEP_50_MV),
- regulator_desc_ldo(26, STEP_50_MV),
+ regulator_desc_ldo(26, STEP_25_MV),
regulator_desc_buck1_4(1),
regulator_desc_buck1_4(2),
regulator_desc_buck1_4(3),
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 5bb6f4ca48db..134c62db36c5 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -5,7 +5,7 @@
#include <linux/bug.h>
#include <linux/err.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -14,7 +14,6 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
-#include <linux/of_gpio.h>
#include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps13.h>
@@ -44,7 +43,7 @@ struct s2mps11_info {
* Array (size: number of regulators) with GPIO-s for external
* sleep control.
*/
- int *ext_control_gpio;
+ struct gpio_desc **ext_control_gpiod;
};
static int get_ramp_delay(int ramp_delay)
@@ -363,7 +362,7 @@ static const struct regulator_desc s2mps11_regulators[] = {
regulator_desc_s2mps11_ldo(32, STEP_50_MV),
regulator_desc_s2mps11_ldo(33, STEP_50_MV),
regulator_desc_s2mps11_ldo(34, STEP_50_MV),
- regulator_desc_s2mps11_ldo(35, STEP_50_MV),
+ regulator_desc_s2mps11_ldo(35, STEP_25_MV),
regulator_desc_s2mps11_ldo(36, STEP_50_MV),
regulator_desc_s2mps11_ldo(37, STEP_50_MV),
regulator_desc_s2mps11_ldo(38, STEP_50_MV),
@@ -373,8 +372,8 @@ static const struct regulator_desc s2mps11_regulators[] = {
regulator_desc_s2mps11_buck1_4(4),
regulator_desc_s2mps11_buck5,
regulator_desc_s2mps11_buck67810(6, MIN_600_MV, STEP_6_25_MV),
- regulator_desc_s2mps11_buck67810(7, MIN_600_MV, STEP_6_25_MV),
- regulator_desc_s2mps11_buck67810(8, MIN_600_MV, STEP_6_25_MV),
+ regulator_desc_s2mps11_buck67810(7, MIN_600_MV, STEP_12_5_MV),
+ regulator_desc_s2mps11_buck67810(8, MIN_600_MV, STEP_12_5_MV),
regulator_desc_s2mps11_buck9,
regulator_desc_s2mps11_buck67810(10, MIN_750_MV, STEP_12_5_MV),
};
@@ -511,7 +510,7 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev)
case S2MPS14X:
if (test_bit(rdev_get_id(rdev), s2mps11->suspend_state))
val = S2MPS14_ENABLE_SUSPEND;
- else if (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)]))
+ else if (s2mps11->ext_control_gpiod[rdev_get_id(rdev)])
val = S2MPS14_ENABLE_EXT_CONTROL;
else
val = rdev->desc->enable_mask;
@@ -805,7 +804,7 @@ static int s2mps14_pmic_enable_ext_control(struct s2mps11_info *s2mps11,
static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev,
struct of_regulator_match *rdata, struct s2mps11_info *s2mps11)
{
- int *gpio = s2mps11->ext_control_gpio;
+ struct gpio_desc **gpio = s2mps11->ext_control_gpiod;
unsigned int i;
unsigned int valid_regulators[3] = { S2MPS14_LDO10, S2MPS14_LDO11,
S2MPS14_LDO12 };
@@ -816,11 +815,20 @@ static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev,
if (!rdata[reg].init_data || !rdata[reg].of_node)
continue;
- gpio[reg] = of_get_named_gpio(rdata[reg].of_node,
- "samsung,ext-control-gpios", 0);
- if (gpio_is_valid(gpio[reg]))
- dev_dbg(&pdev->dev, "Using GPIO %d for ext-control over %d/%s\n",
- gpio[reg], reg, rdata[reg].name);
+ gpio[reg] = devm_gpiod_get_from_of_node(&pdev->dev,
+ rdata[reg].of_node,
+ "samsung,ext-control-gpios",
+ 0,
+ GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
+ "s2mps11-regulator");
+ if (IS_ERR(gpio[reg])) {
+ dev_err(&pdev->dev, "Failed to get control GPIO for %d/%s\n",
+ reg, rdata[reg].name);
+ continue;
+ }
+ if (gpio[reg])
+ dev_dbg(&pdev->dev, "Using GPIO for ext-control over %d/%s\n",
+ reg, rdata[reg].name);
}
}
@@ -1126,17 +1134,10 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
return -EINVAL;
}
- s2mps11->ext_control_gpio = devm_kmalloc_array(&pdev->dev,
- rdev_num, sizeof(*s2mps11->ext_control_gpio),
- GFP_KERNEL);
- if (!s2mps11->ext_control_gpio)
+ s2mps11->ext_control_gpiod = devm_kcalloc(&pdev->dev, rdev_num,
+ sizeof(*s2mps11->ext_control_gpiod), GFP_KERNEL);
+ if (!s2mps11->ext_control_gpiod)
return -ENOMEM;
- /*
- * 0 is a valid GPIO so initialize all GPIO-s to negative value
- * to indicate that external control won't be used for this regulator.
- */
- for (i = 0; i < rdev_num; i++)
- s2mps11->ext_control_gpio[i] = -EINVAL;
if (!iodev->dev->of_node) {
if (iodev->pdata) {
@@ -1166,8 +1167,6 @@ common_reg:
config.dev = &pdev->dev;
config.regmap = iodev->regmap_pmic;
config.driver_data = s2mps11;
- config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
- config.ena_gpio_initialized = true;
for (i = 0; i < rdev_num; i++) {
struct regulator_dev *regulator;
@@ -1178,8 +1177,13 @@ common_reg:
config.init_data = rdata[i].init_data;
config.of_node = rdata[i].of_node;
}
- config.ena_gpio = s2mps11->ext_control_gpio[i];
-
+ config.ena_gpiod = s2mps11->ext_control_gpiod[i];
+ /*
+ * Hand the GPIO descriptor management over to the regulator
+ * core, remove it from devres management.
+ */
+ if (config.ena_gpiod)
+ devm_gpiod_unhinge(&pdev->dev, config.ena_gpiod);
regulator = devm_regulator_register(&pdev->dev,
&regulators[i], &config);
if (IS_ERR(regulator)) {
@@ -1189,7 +1193,7 @@ common_reg:
goto out;
}
- if (gpio_is_valid(s2mps11->ext_control_gpio[i])) {
+ if (s2mps11->ext_control_gpiod[i]) {
ret = s2mps14_pmic_enable_ext_control(s2mps11,
regulator);
if (ret < 0) {
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index 219b9afda0cb..bb9d1a083299 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -115,7 +115,7 @@ static const struct sec_voltage_desc *reg_voltage_map[] = {
[S5M8767_BUCK9] = &buck_voltage_val3,
};
-static unsigned int s5m8767_opmode_reg[][4] = {
+static const unsigned int s5m8767_opmode_reg[][4] = {
/* {OFF, ON, LOWPOWER, SUSPEND} */
/* LDO1 ... LDO28 */
{0x0, 0x3, 0x2, 0x1}, /* LDO1 */
@@ -339,13 +339,9 @@ static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,
unsigned int new_sel)
{
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
- const struct sec_voltage_desc *desc;
- int reg_id = rdev_get_id(rdev);
-
- desc = reg_voltage_map[reg_id];
if ((old_sel < new_sel) && s5m8767->ramp_delay)
- return DIV_ROUND_UP(desc->step * (new_sel - old_sel),
+ return DIV_ROUND_UP(rdev->desc->uV_step * (new_sel - old_sel),
s5m8767->ramp_delay * 1000);
return 0;
}
@@ -561,7 +557,7 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
pdata->opmode = rmode;
for_each_child_of_node(regulators_np, reg_np) {
for (i = 0; i < ARRAY_SIZE(regulators); i++)
- if (!of_node_cmp(reg_np->name, regulators[i].name))
+ if (of_node_name_eq(reg_np, regulators[i].name))
break;
if (i == ARRAY_SIZE(regulators)) {
@@ -956,10 +952,17 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
config.regmap = iodev->regmap_pmic;
config.of_node = pdata->regulators[i].reg_node;
config.ena_gpiod = NULL;
- if (pdata->regulators[i].ext_control_gpiod)
+ if (pdata->regulators[i].ext_control_gpiod) {
+ /* Assigns config.ena_gpiod */
s5m8767_regulator_config_ext_control(s5m8767,
&pdata->regulators[i], &config);
+ /*
+ * Hand the GPIO descriptor management over to the
+ * regulator core, remove it from devres management.
+ */
+ devm_gpiod_unhinge(s5m8767->dev, config.ena_gpiod);
+ }
rdev = devm_regulator_register(&pdev->dev, &regulators[id],
&config);
if (IS_ERR(rdev)) {
diff --git a/drivers/regulator/stm32-vrefbuf.c b/drivers/regulator/stm32-vrefbuf.c
index e0a9c445ed67..ba2f24949dc9 100644
--- a/drivers/regulator/stm32-vrefbuf.c
+++ b/drivers/regulator/stm32-vrefbuf.c
@@ -15,6 +15,7 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
+#include <linux/pm_runtime.h>
/* STM32 VREFBUF registers */
#define STM32_VREFBUF_CSR 0x00
@@ -25,9 +26,12 @@
#define STM32_HIZ BIT(1)
#define STM32_ENVR BIT(0)
+#define STM32_VREFBUF_AUTO_SUSPEND_DELAY_MS 10
+
struct stm32_vrefbuf {
void __iomem *base;
struct clk *clk;
+ struct device *dev;
};
static const unsigned int stm32_vrefbuf_voltages[] = {
@@ -38,9 +42,16 @@ static const unsigned int stm32_vrefbuf_voltages[] = {
static int stm32_vrefbuf_enable(struct regulator_dev *rdev)
{
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
- u32 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
+ u32 val;
int ret;
+ ret = pm_runtime_get_sync(priv->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(priv->dev);
+ return ret;
+ }
+
+ val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
val = (val & ~STM32_HIZ) | STM32_ENVR;
writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
@@ -59,45 +70,95 @@ static int stm32_vrefbuf_enable(struct regulator_dev *rdev)
writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
}
+ pm_runtime_mark_last_busy(priv->dev);
+ pm_runtime_put_autosuspend(priv->dev);
+
return ret;
}
static int stm32_vrefbuf_disable(struct regulator_dev *rdev)
{
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
- u32 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
+ u32 val;
+ int ret;
+ ret = pm_runtime_get_sync(priv->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(priv->dev);
+ return ret;
+ }
+
+ val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
val = (val & ~STM32_ENVR) | STM32_HIZ;
writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
+ pm_runtime_mark_last_busy(priv->dev);
+ pm_runtime_put_autosuspend(priv->dev);
+
return 0;
}
static int stm32_vrefbuf_is_enabled(struct regulator_dev *rdev)
{
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
+ int ret;
+
+ ret = pm_runtime_get_sync(priv->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(priv->dev);
+ return ret;
+ }
+
+ ret = readl_relaxed(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR;
- return readl_relaxed(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR;
+ pm_runtime_mark_last_busy(priv->dev);
+ pm_runtime_put_autosuspend(priv->dev);
+
+ return ret;
}
static int stm32_vrefbuf_set_voltage_sel(struct regulator_dev *rdev,
unsigned sel)
{
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
- u32 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
+ u32 val;
+ int ret;
+ ret = pm_runtime_get_sync(priv->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(priv->dev);
+ return ret;
+ }
+
+ val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
val = (val & ~STM32_VRS) | FIELD_PREP(STM32_VRS, sel);
writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
+ pm_runtime_mark_last_busy(priv->dev);
+ pm_runtime_put_autosuspend(priv->dev);
+
return 0;
}
static int stm32_vrefbuf_get_voltage_sel(struct regulator_dev *rdev)
{
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
- u32 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
+ u32 val;
+ int ret;
- return FIELD_GET(STM32_VRS, val);
+ ret = pm_runtime_get_sync(priv->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(priv->dev);
+ return ret;
+ }
+
+ val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
+ ret = FIELD_GET(STM32_VRS, val);
+
+ pm_runtime_mark_last_busy(priv->dev);
+ pm_runtime_put_autosuspend(priv->dev);
+
+ return ret;
}
static const struct regulator_ops stm32_vrefbuf_volt_ops = {
@@ -130,6 +191,7 @@ static int stm32_vrefbuf_probe(struct platform_device *pdev)
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
+ priv->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->base = devm_ioremap_resource(&pdev->dev, res);
@@ -140,10 +202,17 @@ static int stm32_vrefbuf_probe(struct platform_device *pdev)
if (IS_ERR(priv->clk))
return PTR_ERR(priv->clk);
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev,
+ STM32_VREFBUF_AUTO_SUSPEND_DELAY_MS);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
ret = clk_prepare_enable(priv->clk);
if (ret) {
dev_err(&pdev->dev, "clk prepare failed with error %d\n", ret);
- return ret;
+ goto err_pm_stop;
}
config.dev = &pdev->dev;
@@ -161,10 +230,17 @@ static int stm32_vrefbuf_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, rdev);
+ pm_runtime_mark_last_busy(&pdev->dev);
+ pm_runtime_put_autosuspend(&pdev->dev);
+
return 0;
err_clk_dis:
clk_disable_unprepare(priv->clk);
+err_pm_stop:
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
return ret;
}
@@ -174,12 +250,42 @@ static int stm32_vrefbuf_remove(struct platform_device *pdev)
struct regulator_dev *rdev = platform_get_drvdata(pdev);
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
+ pm_runtime_get_sync(&pdev->dev);
regulator_unregister(rdev);
clk_disable_unprepare(priv->clk);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
return 0;
};
+static int __maybe_unused stm32_vrefbuf_runtime_suspend(struct device *dev)
+{
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
+ struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
+
+ clk_disable_unprepare(priv->clk);
+
+ return 0;
+}
+
+static int __maybe_unused stm32_vrefbuf_runtime_resume(struct device *dev)
+{
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
+ struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
+
+ return clk_prepare_enable(priv->clk);
+}
+
+static const struct dev_pm_ops stm32_vrefbuf_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(stm32_vrefbuf_runtime_suspend,
+ stm32_vrefbuf_runtime_resume,
+ NULL)
+};
+
static const struct of_device_id stm32_vrefbuf_of_match[] = {
{ .compatible = "st,stm32-vrefbuf", },
{},
@@ -192,6 +298,7 @@ static struct platform_driver stm32_vrefbuf_driver = {
.driver = {
.name = "stm32-vrefbuf",
.of_match_table = of_match_ptr(stm32_vrefbuf_of_match),
+ .pm = &stm32_vrefbuf_pm_ops,
},
};
module_platform_driver(stm32_vrefbuf_driver);
diff --git a/drivers/regulator/stpmic1_regulator.c b/drivers/regulator/stpmic1_regulator.c
index e15634edb8ce..f09061473613 100644
--- a/drivers/regulator/stpmic1_regulator.c
+++ b/drivers/regulator/stpmic1_regulator.c
@@ -12,8 +12,10 @@
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
+#include <dt-bindings/mfd/st,stpmic1.h>
+
/**
- * stpmic1 regulator description
+ * stpmic1 regulator description: this structure is used as driver data
* @desc: regulator framework description
* @mask_reset_reg: mask reset register address
* @mask_reset_mask: mask rank and mask reset register mask
@@ -28,28 +30,9 @@ struct stpmic1_regulator_cfg {
u8 icc_mask;
};
-/**
- * stpmic1 regulator data: this structure is used as driver data
- * @regul_id: regulator id
- * @reg_node: DT node of regulator (unused on non-DT platforms)
- * @cfg: stpmic specific regulator description
- * @mask_reset: mask_reset bit value
- * @irq_curlim: current limit interrupt number
- * @regmap: point to parent regmap structure
- */
-struct stpmic1_regulator {
- unsigned int regul_id;
- struct device_node *reg_node;
- struct stpmic1_regulator_cfg *cfg;
- u8 mask_reset;
- int irq_curlim;
- struct regmap *regmap;
-};
-
static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode);
static unsigned int stpmic1_get_mode(struct regulator_dev *rdev);
static int stpmic1_set_icc(struct regulator_dev *rdev);
-static int stpmic1_regulator_parse_dt(void *driver_data);
static unsigned int stpmic1_map_mode(unsigned int mode);
enum {
@@ -72,15 +55,13 @@ enum {
/* Enable time worst case is 5000mV/(2250uV/uS) */
#define PMIC_ENABLE_TIME_US 2200
-#define STPMIC1_BUCK_MODE_NORMAL 0
-#define STPMIC1_BUCK_MODE_LP BUCK_HPLP_ENABLE_MASK
-
-struct regulator_linear_range buck1_ranges[] = {
- REGULATOR_LINEAR_RANGE(600000, 0, 30, 25000),
- REGULATOR_LINEAR_RANGE(1350000, 31, 63, 0),
+static const struct regulator_linear_range buck1_ranges[] = {
+ REGULATOR_LINEAR_RANGE(725000, 0, 4, 0),
+ REGULATOR_LINEAR_RANGE(725000, 5, 36, 25000),
+ REGULATOR_LINEAR_RANGE(1500000, 37, 63, 0),
};
-struct regulator_linear_range buck2_ranges[] = {
+static const struct regulator_linear_range buck2_ranges[] = {
REGULATOR_LINEAR_RANGE(1000000, 0, 17, 0),
REGULATOR_LINEAR_RANGE(1050000, 18, 19, 0),
REGULATOR_LINEAR_RANGE(1100000, 20, 21, 0),
@@ -94,7 +75,7 @@ struct regulator_linear_range buck2_ranges[] = {
REGULATOR_LINEAR_RANGE(1500000, 36, 63, 0),
};
-struct regulator_linear_range buck3_ranges[] = {
+static const struct regulator_linear_range buck3_ranges[] = {
REGULATOR_LINEAR_RANGE(1000000, 0, 19, 0),
REGULATOR_LINEAR_RANGE(1100000, 20, 23, 0),
REGULATOR_LINEAR_RANGE(1200000, 24, 27, 0),
@@ -102,10 +83,9 @@ struct regulator_linear_range buck3_ranges[] = {
REGULATOR_LINEAR_RANGE(1400000, 32, 35, 0),
REGULATOR_LINEAR_RANGE(1500000, 36, 55, 100000),
REGULATOR_LINEAR_RANGE(3400000, 56, 63, 0),
-
};
-struct regulator_linear_range buck4_ranges[] = {
+static const struct regulator_linear_range buck4_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 27, 25000),
REGULATOR_LINEAR_RANGE(1300000, 28, 29, 0),
REGULATOR_LINEAR_RANGE(1350000, 30, 31, 0),
@@ -113,24 +93,21 @@ struct regulator_linear_range buck4_ranges[] = {
REGULATOR_LINEAR_RANGE(1450000, 34, 35, 0),
REGULATOR_LINEAR_RANGE(1500000, 36, 60, 100000),
REGULATOR_LINEAR_RANGE(3900000, 61, 63, 0),
-
};
-struct regulator_linear_range ldo1_ranges[] = {
+static const struct regulator_linear_range ldo1_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0),
-
};
-struct regulator_linear_range ldo2_ranges[] = {
+static const struct regulator_linear_range ldo2_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
REGULATOR_LINEAR_RANGE(3300000, 25, 30, 0),
-
};
-struct regulator_linear_range ldo3_ranges[] = {
+static const struct regulator_linear_range ldo3_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
REGULATOR_LINEAR_RANGE(3300000, 25, 30, 0),
@@ -138,18 +115,18 @@ struct regulator_linear_range ldo3_ranges[] = {
REGULATOR_LINEAR_RANGE(500000, 31, 31, 0),
};
-struct regulator_linear_range ldo5_ranges[] = {
+static const struct regulator_linear_range ldo5_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
REGULATOR_LINEAR_RANGE(1700000, 8, 30, 100000),
REGULATOR_LINEAR_RANGE(3900000, 31, 31, 0),
};
-struct regulator_linear_range ldo6_ranges[] = {
+static const struct regulator_linear_range ldo6_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 24, 100000),
REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0),
};
-static struct regulator_ops stpmic1_ldo_ops = {
+static const struct regulator_ops stpmic1_ldo_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.is_enabled = regulator_is_enabled_regmap,
@@ -157,11 +134,10 @@ static struct regulator_ops stpmic1_ldo_ops = {
.disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
- .set_pull_down = regulator_set_pull_down_regmap,
.set_over_current_protection = stpmic1_set_icc,
};
-static struct regulator_ops stpmic1_ldo3_ops = {
+static const struct regulator_ops stpmic1_ldo3_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_iterate,
.is_enabled = regulator_is_enabled_regmap,
@@ -169,21 +145,19 @@ static struct regulator_ops stpmic1_ldo3_ops = {
.disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
- .set_pull_down = regulator_set_pull_down_regmap,
.get_bypass = regulator_get_bypass_regmap,
.set_bypass = regulator_set_bypass_regmap,
.set_over_current_protection = stpmic1_set_icc,
};
-static struct regulator_ops stpmic1_ldo4_fixed_regul_ops = {
+static const struct regulator_ops stpmic1_ldo4_fixed_regul_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
- .set_pull_down = regulator_set_pull_down_regmap,
.set_over_current_protection = stpmic1_set_icc,
};
-static struct regulator_ops stpmic1_buck_ops = {
+static const struct regulator_ops stpmic1_buck_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.is_enabled = regulator_is_enabled_regmap,
@@ -197,20 +171,27 @@ static struct regulator_ops stpmic1_buck_ops = {
.set_over_current_protection = stpmic1_set_icc,
};
-static struct regulator_ops stpmic1_vref_ddr_ops = {
+static const struct regulator_ops stpmic1_vref_ddr_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
- .set_pull_down = regulator_set_pull_down_regmap,
};
-static struct regulator_ops stpmic1_switch_regul_ops = {
+static const struct regulator_ops stpmic1_boost_regul_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.set_over_current_protection = stpmic1_set_icc,
};
+static const struct regulator_ops stpmic1_switch_regul_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .set_over_current_protection = stpmic1_set_icc,
+ .set_active_discharge = regulator_set_active_discharge_regmap,
+};
+
#define REG_LDO(ids, base) { \
.name = #ids, \
.id = STPMIC1_##ids, \
@@ -227,8 +208,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
.enable_val = 1, \
.disable_val = 0, \
.enable_time = PMIC_ENABLE_TIME_US, \
- .pull_down_reg = ids##_PULL_DOWN_REG, \
- .pull_down_mask = ids##_PULL_DOWN_MASK, \
.supply_name = #base, \
}
@@ -252,8 +231,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
.bypass_mask = LDO_BYPASS_MASK, \
.bypass_val_on = LDO_BYPASS_MASK, \
.bypass_val_off = 0, \
- .pull_down_reg = ids##_PULL_DOWN_REG, \
- .pull_down_mask = ids##_PULL_DOWN_MASK, \
.supply_name = #base, \
}
@@ -271,8 +248,6 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
.enable_val = 1, \
.disable_val = 0, \
.enable_time = PMIC_ENABLE_TIME_US, \
- .pull_down_reg = ids##_PULL_DOWN_REG, \
- .pull_down_mask = ids##_PULL_DOWN_MASK, \
.supply_name = #base, \
}
@@ -312,12 +287,47 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
.enable_val = 1, \
.disable_val = 0, \
.enable_time = PMIC_ENABLE_TIME_US, \
- .pull_down_reg = ids##_PULL_DOWN_REG, \
- .pull_down_mask = ids##_PULL_DOWN_MASK, \
.supply_name = #base, \
}
-#define REG_SWITCH(ids, base, reg, mask, val) { \
+#define REG_BOOST(ids, base) { \
+ .name = #ids, \
+ .id = STPMIC1_##ids, \
+ .n_voltages = 1, \
+ .ops = &stpmic1_boost_regul_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = 0, \
+ .fixed_uV = 5000000, \
+ .enable_reg = BST_SW_CR, \
+ .enable_mask = BOOST_ENABLED, \
+ .enable_val = BOOST_ENABLED, \
+ .disable_val = 0, \
+ .enable_time = PMIC_ENABLE_TIME_US, \
+ .supply_name = #base, \
+}
+
+#define REG_VBUS_OTG(ids, base) { \
+ .name = #ids, \
+ .id = STPMIC1_##ids, \
+ .n_voltages = 1, \
+ .ops = &stpmic1_switch_regul_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = 0, \
+ .fixed_uV = 5000000, \
+ .enable_reg = BST_SW_CR, \
+ .enable_mask = USBSW_OTG_SWITCH_ENABLED, \
+ .enable_val = USBSW_OTG_SWITCH_ENABLED, \
+ .disable_val = 0, \
+ .enable_time = PMIC_ENABLE_TIME_US, \
+ .supply_name = #base, \
+ .active_discharge_reg = BST_SW_CR, \
+ .active_discharge_mask = VBUS_OTG_DISCHARGE, \
+ .active_discharge_on = VBUS_OTG_DISCHARGE, \
+}
+
+#define REG_SW_OUT(ids, base) { \
.name = #ids, \
.id = STPMIC1_##ids, \
.n_voltages = 1, \
@@ -326,15 +336,18 @@ static struct regulator_ops stpmic1_switch_regul_ops = {
.owner = THIS_MODULE, \
.min_uV = 0, \
.fixed_uV = 5000000, \
- .enable_reg = (reg), \
- .enable_mask = (mask), \
- .enable_val = (val), \
+ .enable_reg = BST_SW_CR, \
+ .enable_mask = SWIN_SWOUT_ENABLED, \
+ .enable_val = SWIN_SWOUT_ENABLED, \
.disable_val = 0, \
.enable_time = PMIC_ENABLE_TIME_US, \
.supply_name = #base, \
+ .active_discharge_reg = BST_SW_CR, \
+ .active_discharge_mask = SW_OUT_DISCHARGE, \
+ .active_discharge_on = SW_OUT_DISCHARGE, \
}
-struct stpmic1_regulator_cfg stpmic1_regulator_cfgs[] = {
+static const struct stpmic1_regulator_cfg stpmic1_regulator_cfgs[] = {
[STPMIC1_BUCK1] = {
.desc = REG_BUCK(BUCK1, buck1),
.icc_reg = BUCKS_ICCTO_CR,
@@ -411,23 +424,17 @@ struct stpmic1_regulator_cfg stpmic1_regulator_cfgs[] = {
.mask_reset_mask = BIT(6),
},
[STPMIC1_BOOST] = {
- .desc = REG_SWITCH(BOOST, boost, BST_SW_CR,
- BOOST_ENABLED,
- BOOST_ENABLED),
+ .desc = REG_BOOST(BOOST, boost),
.icc_reg = BUCKS_ICCTO_CR,
.icc_mask = BIT(6),
},
[STPMIC1_VBUS_OTG] = {
- .desc = REG_SWITCH(VBUS_OTG, pwr_sw1, BST_SW_CR,
- USBSW_OTG_SWITCH_ENABLED,
- USBSW_OTG_SWITCH_ENABLED),
+ .desc = REG_VBUS_OTG(VBUS_OTG, pwr_sw1),
.icc_reg = BUCKS_ICCTO_CR,
.icc_mask = BIT(4),
},
[STPMIC1_SW_OUT] = {
- .desc = REG_SWITCH(SW_OUT, pwr_sw2, BST_SW_CR,
- SWIN_SWOUT_ENABLED,
- SWIN_SWOUT_ENABLED),
+ .desc = REG_SW_OUT(SW_OUT, pwr_sw2),
.icc_reg = BUCKS_ICCTO_CR,
.icc_mask = BIT(5),
},
@@ -448,8 +455,9 @@ static unsigned int stpmic1_map_mode(unsigned int mode)
static unsigned int stpmic1_get_mode(struct regulator_dev *rdev)
{
int value;
+ struct regmap *regmap = rdev_get_regmap(rdev);
- regmap_read(rdev->regmap, rdev->desc->enable_reg, &value);
+ regmap_read(regmap, rdev->desc->enable_reg, &value);
if (value & STPMIC1_BUCK_MODE_LP)
return REGULATOR_MODE_STANDBY;
@@ -460,6 +468,7 @@ static unsigned int stpmic1_get_mode(struct regulator_dev *rdev)
static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
int value;
+ struct regmap *regmap = rdev_get_regmap(rdev);
switch (mode) {
case REGULATOR_MODE_NORMAL:
@@ -472,75 +481,43 @@ static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode)
return -EINVAL;
}
- return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+ return regmap_update_bits(regmap, rdev->desc->enable_reg,
STPMIC1_BUCK_MODE_LP, value);
}
static int stpmic1_set_icc(struct regulator_dev *rdev)
{
- struct stpmic1_regulator *regul = rdev_get_drvdata(rdev);
+ struct stpmic1_regulator_cfg *cfg = rdev_get_drvdata(rdev);
+ struct regmap *regmap = rdev_get_regmap(rdev);
/* enable switch off in case of over current */
- return regmap_update_bits(regul->regmap, regul->cfg->icc_reg,
- regul->cfg->icc_mask, regul->cfg->icc_mask);
+ return regmap_update_bits(regmap, cfg->icc_reg, cfg->icc_mask,
+ cfg->icc_mask);
}
static irqreturn_t stpmic1_curlim_irq_handler(int irq, void *data)
{
struct regulator_dev *rdev = (struct regulator_dev *)data;
- mutex_lock(&rdev->mutex);
+ regulator_lock(rdev);
/* Send an overcurrent notification */
regulator_notifier_call_chain(rdev,
REGULATOR_EVENT_OVER_CURRENT,
NULL);
- mutex_unlock(&rdev->mutex);
+ regulator_unlock(rdev);
return IRQ_HANDLED;
}
-static int stpmic1_regulator_init(struct platform_device *pdev,
- struct regulator_dev *rdev)
-{
- struct stpmic1_regulator *regul = rdev_get_drvdata(rdev);
- int ret = 0;
-
- /* set mask reset */
- if (regul->mask_reset && regul->cfg->mask_reset_reg != 0) {
- ret = regmap_update_bits(regul->regmap,
- regul->cfg->mask_reset_reg,
- regul->cfg->mask_reset_mask,
- regul->cfg->mask_reset_mask);
- if (ret) {
- dev_err(&pdev->dev, "set mask reset failed\n");
- return ret;
- }
- }
-
- /* setup an irq handler for over-current detection */
- if (regul->irq_curlim > 0) {
- ret = devm_request_threaded_irq(&pdev->dev,
- regul->irq_curlim, NULL,
- stpmic1_curlim_irq_handler,
- IRQF_ONESHOT | IRQF_SHARED,
- pdev->name, rdev);
- if (ret) {
- dev_err(&pdev->dev, "Request IRQ failed\n");
- return ret;
- }
- }
- return 0;
-}
-
#define MATCH(_name, _id) \
[STPMIC1_##_id] = { \
.name = #_name, \
.desc = &stpmic1_regulator_cfgs[STPMIC1_##_id].desc, \
}
-static struct of_regulator_match stpmic1_regulators_matches[] = {
+static struct of_regulator_match stpmic1_matches[] = {
MATCH(buck1, BUCK1),
MATCH(buck2, BUCK2),
MATCH(buck3, BUCK3),
@@ -557,94 +534,75 @@ static struct of_regulator_match stpmic1_regulators_matches[] = {
MATCH(pwr_sw2, SW_OUT),
};
-static int stpmic1_regulator_parse_dt(void *driver_data)
-{
- struct stpmic1_regulator *regul =
- (struct stpmic1_regulator *)driver_data;
-
- if (!regul)
- return -EINVAL;
-
- if (of_get_property(regul->reg_node, "st,mask-reset", NULL))
- regul->mask_reset = 1;
-
- regul->irq_curlim = of_irq_get(regul->reg_node, 0);
-
- return 0;
-}
-
-static struct
-regulator_dev *stpmic1_regulator_register(struct platform_device *pdev, int id,
- struct regulator_init_data *init_data,
- struct stpmic1_regulator *regul)
+static int stpmic1_regulator_register(struct platform_device *pdev, int id,
+ struct of_regulator_match *match,
+ const struct stpmic1_regulator_cfg *cfg)
{
struct stpmic1 *pmic_dev = dev_get_drvdata(pdev->dev.parent);
struct regulator_dev *rdev;
struct regulator_config config = {};
+ int ret = 0;
+ int irq;
config.dev = &pdev->dev;
- config.init_data = init_data;
- config.of_node = stpmic1_regulators_matches[id].of_node;
+ config.init_data = match->init_data;
+ config.of_node = match->of_node;
config.regmap = pmic_dev->regmap;
- config.driver_data = regul;
-
- regul->regul_id = id;
- regul->reg_node = config.of_node;
- regul->cfg = &stpmic1_regulator_cfgs[id];
- regul->regmap = pmic_dev->regmap;
+ config.driver_data = (void *)cfg;
- rdev = devm_regulator_register(&pdev->dev, &regul->cfg->desc, &config);
+ rdev = devm_regulator_register(&pdev->dev, &cfg->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register %s regulator\n",
- regul->cfg->desc.name);
+ cfg->desc.name);
+ return PTR_ERR(rdev);
+ }
+
+ /* set mask reset */
+ if (of_get_property(config.of_node, "st,mask-reset", NULL) &&
+ cfg->mask_reset_reg != 0) {
+ ret = regmap_update_bits(pmic_dev->regmap,
+ cfg->mask_reset_reg,
+ cfg->mask_reset_mask,
+ cfg->mask_reset_mask);
+ if (ret) {
+ dev_err(&pdev->dev, "set mask reset failed\n");
+ return ret;
+ }
}
- return rdev;
+ /* setup an irq handler for over-current detection */
+ irq = of_irq_get(config.of_node, 0);
+ if (irq > 0) {
+ ret = devm_request_threaded_irq(&pdev->dev,
+ irq, NULL,
+ stpmic1_curlim_irq_handler,
+ IRQF_ONESHOT | IRQF_SHARED,
+ pdev->name, rdev);
+ if (ret) {
+ dev_err(&pdev->dev, "Request IRQ failed\n");
+ return ret;
+ }
+ }
+ return 0;
}
static int stpmic1_regulator_probe(struct platform_device *pdev)
{
- struct regulator_dev *rdev;
- struct stpmic1_regulator *regul;
- struct regulator_init_data *init_data;
- struct device_node *np;
int i, ret;
- np = pdev->dev.of_node;
-
- ret = of_regulator_match(&pdev->dev, np,
- stpmic1_regulators_matches,
- ARRAY_SIZE(stpmic1_regulators_matches));
+ ret = of_regulator_match(&pdev->dev, pdev->dev.of_node, stpmic1_matches,
+ ARRAY_SIZE(stpmic1_matches));
if (ret < 0) {
dev_err(&pdev->dev,
"Error in PMIC regulator device tree node");
return ret;
}
- regul = devm_kzalloc(&pdev->dev, ARRAY_SIZE(stpmic1_regulator_cfgs) *
- sizeof(struct stpmic1_regulator),
- GFP_KERNEL);
- if (!regul)
- return -ENOMEM;
-
for (i = 0; i < ARRAY_SIZE(stpmic1_regulator_cfgs); i++) {
- /* Parse DT & find regulators to register */
- init_data = stpmic1_regulators_matches[i].init_data;
- if (init_data)
- init_data->regulator_init = &stpmic1_regulator_parse_dt;
-
- rdev = stpmic1_regulator_register(pdev, i, init_data, regul);
- if (IS_ERR(rdev))
- return PTR_ERR(rdev);
-
- ret = stpmic1_regulator_init(pdev, rdev);
- if (ret) {
- dev_err(&pdev->dev,
- "failed to initialize regulator %d\n", ret);
+ ret = stpmic1_regulator_register(pdev, i, &stpmic1_matches[i],
+ &stpmic1_regulator_cfgs[i]);
+ if (ret < 0)
return ret;
- }
-
- regul++;
}
dev_dbg(&pdev->dev, "stpmic1_regulator driver probed\n");
diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c
index db714d5edafc..0614551796a1 100644
--- a/drivers/regulator/tps65090-regulator.c
+++ b/drivers/regulator/tps65090-regulator.c
@@ -480,6 +480,12 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
else
config.of_node = NULL;
+ /*
+ * Hand the GPIO descriptor management over to the regulator
+ * core, remove it from devres management.
+ */
+ if (config.ena_gpiod)
+ devm_gpiod_unhinge(&pdev->dev, config.ena_gpiod);
rdev = devm_regulator_register(&pdev->dev, ri->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c
index 6209beee1018..95708d34876b 100644
--- a/drivers/regulator/tps65218-regulator.c
+++ b/drivers/regulator/tps65218-regulator.c
@@ -188,7 +188,8 @@ static struct regulator_ops tps65218_ldo1_dcdc34_ops = {
.set_suspend_disable = tps65218_pmic_set_suspend_disable,
};
-static const int ls3_currents[] = { 100, 200, 500, 1000 };
+static const int ls3_currents[] = { 100000, 200000, 500000, 1000000 };
+
static int tps65218_pmic_set_input_current_lim(struct regulator_dev *dev,
int lim_uA)
@@ -204,7 +205,8 @@ static int tps65218_pmic_set_input_current_lim(struct regulator_dev *dev,
return -EINVAL;
return tps65218_set_bits(tps, dev->desc->csel_reg, dev->desc->csel_mask,
- index << 2, TPS65218_PROTECT_L1);
+ index << __builtin_ctz(dev->desc->csel_mask),
+ TPS65218_PROTECT_L1);
}
static int tps65218_pmic_set_current_limit(struct regulator_dev *dev,
@@ -214,7 +216,7 @@ static int tps65218_pmic_set_current_limit(struct regulator_dev *dev,
unsigned int num_currents = ARRAY_SIZE(ls3_currents);
struct tps65218 *tps = rdev_get_drvdata(dev);
- while (index < num_currents && ls3_currents[index] < max_uA)
+ while (index < num_currents && ls3_currents[index] <= max_uA)
index++;
index--;
@@ -223,7 +225,8 @@ static int tps65218_pmic_set_current_limit(struct regulator_dev *dev,
return -EINVAL;
return tps65218_set_bits(tps, dev->desc->csel_reg, dev->desc->csel_mask,
- index << 2, TPS65218_PROTECT_L1);
+ index << __builtin_ctz(dev->desc->csel_mask),
+ TPS65218_PROTECT_L1);
}
static int tps65218_pmic_get_current_limit(struct regulator_dev *dev)
@@ -236,12 +239,13 @@ static int tps65218_pmic_get_current_limit(struct regulator_dev *dev)
if (retval < 0)
return retval;
- index = (index & dev->desc->csel_mask) >> 2;
+ index = (index & dev->desc->csel_mask) >>
+ __builtin_ctz(dev->desc->csel_mask);
return ls3_currents[index];
}
-static struct regulator_ops tps65218_ls3_ops = {
+static struct regulator_ops tps65218_ls23_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = tps65218_pmic_enable,
.disable = tps65218_pmic_disable,
@@ -303,8 +307,13 @@ static const struct regulator_desc regulators[] = {
TPS65218_ENABLE2_LDO1_EN, 0, 0, ldo1_dcdc3_ranges,
2, 0, 0, TPS65218_REG_SEQ6,
TPS65218_SEQ6_LDO1_SEQ_MASK),
+ TPS65218_REGULATOR("LS2", "regulator-ls2", TPS65218_LS_2,
+ REGULATOR_CURRENT, tps65218_ls23_ops, 0, 0, 0,
+ TPS65218_REG_ENABLE2, TPS65218_ENABLE2_LS2_EN,
+ TPS65218_REG_CONFIG2, TPS65218_CONFIG2_LS2ILIM_MASK,
+ NULL, 0, 0, 0, 0, 0),
TPS65218_REGULATOR("LS3", "regulator-ls3", TPS65218_LS_3,
- REGULATOR_CURRENT, tps65218_ls3_ops, 0, 0, 0,
+ REGULATOR_CURRENT, tps65218_ls23_ops, 0, 0, 0,
TPS65218_REG_ENABLE2, TPS65218_ENABLE2_LS3_EN,
TPS65218_REG_CONFIG2, TPS65218_CONFIG2_LS3ILIM_MASK,
NULL, 0, 0, 0, 0, 0),
diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
index 02ccdaa226a7..5ebb6ee73f07 100644
--- a/drivers/regulator/tps65910-regulator.c
+++ b/drivers/regulator/tps65910-regulator.c
@@ -1102,8 +1102,10 @@ static int tps65910_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, pmic);
/* Give control of all register to control port */
- tps65910_reg_set_bits(pmic->mfd, TPS65910_DEVCTRL,
+ err = tps65910_reg_set_bits(pmic->mfd, TPS65910_DEVCTRL,
DEVCTRL_SR_CTL_I2C_SEL_MASK);
+ if (err < 0)
+ return err;
switch (tps65910_chip_id(tps65910)) {
case TPS65910:
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 884c7505ed91..402ea43c77d1 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -576,14 +576,9 @@ static int twlreg_probe(struct platform_device *pdev)
struct regulator_init_data *initdata;
struct regulation_constraints *c;
struct regulator_dev *rdev;
- const struct of_device_id *match;
struct regulator_config config = { };
- match = of_match_device(twl_of_match, &pdev->dev);
- if (!match)
- return -ENODEV;
-
- template = match->data;
+ template = of_device_get_match_data(&pdev->dev);
if (!template)
return -ENODEV;
diff --git a/drivers/regulator/twl6030-regulator.c b/drivers/regulator/twl6030-regulator.c
index 219cbd910dbf..15f19df6bc5d 100644
--- a/drivers/regulator/twl6030-regulator.c
+++ b/drivers/regulator/twl6030-regulator.c
@@ -31,9 +31,6 @@ struct twlreg_info {
/* twl resource ID, for resource control state machine */
u8 id;
- /* chip constraints on regulator behavior */
- u16 min_mV;
-
u8 flags;
/* used by regulator core */
@@ -247,32 +244,11 @@ static int twl6030coresmps_get_voltage(struct regulator_dev *rdev)
return -ENODEV;
}
-static struct regulator_ops twl6030coresmps_ops = {
+static const struct regulator_ops twl6030coresmps_ops = {
.set_voltage = twl6030coresmps_set_voltage,
.get_voltage = twl6030coresmps_get_voltage,
};
-static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned sel)
-{
- struct twlreg_info *info = rdev_get_drvdata(rdev);
-
- switch (sel) {
- case 0:
- return 0;
- case 1 ... 24:
- /* Linear mapping from 00000001 to 00011000:
- * Absolute voltage value = 1.0 V + 0.1 V × (sel – 00000001)
- */
- return (info->min_mV + 100 * (sel - 1)) * 1000;
- case 25 ... 30:
- return -EINVAL;
- case 31:
- return 2750000;
- default:
- return -EINVAL;
- }
-}
-
static int
twl6030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
{
@@ -290,8 +266,8 @@ static int twl6030ldo_get_voltage_sel(struct regulator_dev *rdev)
return vsel;
}
-static struct regulator_ops twl6030ldo_ops = {
- .list_voltage = twl6030ldo_list_voltage,
+static const struct regulator_ops twl6030ldo_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
.set_voltage_sel = twl6030ldo_set_voltage_sel,
.get_voltage_sel = twl6030ldo_get_voltage_sel,
@@ -305,7 +281,7 @@ static struct regulator_ops twl6030ldo_ops = {
.get_status = twl6030reg_get_status,
};
-static struct regulator_ops twl6030fixed_ops = {
+static const struct regulator_ops twl6030fixed_ops = {
.list_voltage = regulator_list_voltage_linear,
.enable = twl6030reg_enable,
@@ -496,7 +472,7 @@ static int twl6030smps_get_voltage_sel(struct regulator_dev *rdev)
return twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS);
}
-static struct regulator_ops twlsmps_ops = {
+static const struct regulator_ops twlsmps_ops = {
.list_voltage = twl6030smps_list_voltage,
.map_voltage = twl6030smps_map_voltage,
@@ -513,6 +489,11 @@ static struct regulator_ops twlsmps_ops = {
};
/*----------------------------------------------------------------------*/
+static const struct regulator_linear_range twl6030ldo_linear_range[] = {
+ REGULATOR_LINEAR_RANGE(0, 0, 0, 0),
+ REGULATOR_LINEAR_RANGE(1000000, 1, 24, 100000),
+ REGULATOR_LINEAR_RANGE(2750000, 31, 31, 0),
+};
#define TWL6030_ADJUSTABLE_SMPS(label) \
static const struct twlreg_info TWL6030_INFO_##label = { \
@@ -525,28 +506,30 @@ static const struct twlreg_info TWL6030_INFO_##label = { \
}, \
}
-#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts) \
+#define TWL6030_ADJUSTABLE_LDO(label, offset) \
static const struct twlreg_info TWL6030_INFO_##label = { \
.base = offset, \
- .min_mV = min_mVolts, \
.desc = { \
.name = #label, \
.id = TWL6030_REG_##label, \
.n_voltages = 32, \
+ .linear_ranges = twl6030ldo_linear_range, \
+ .n_linear_ranges = ARRAY_SIZE(twl6030ldo_linear_range), \
.ops = &twl6030ldo_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
}, \
}
-#define TWL6032_ADJUSTABLE_LDO(label, offset, min_mVolts) \
+#define TWL6032_ADJUSTABLE_LDO(label, offset) \
static const struct twlreg_info TWL6032_INFO_##label = { \
.base = offset, \
- .min_mV = min_mVolts, \
.desc = { \
.name = #label, \
.id = TWL6032_REG_##label, \
.n_voltages = 32, \
+ .linear_ranges = twl6030ldo_linear_range, \
+ .n_linear_ranges = ARRAY_SIZE(twl6030ldo_linear_range), \
.ops = &twl6030ldo_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
@@ -557,7 +540,6 @@ static const struct twlreg_info TWL6032_INFO_##label = { \
static const struct twlreg_info TWLFIXED_INFO_##label = { \
.base = offset, \
.id = 0, \
- .min_mV = mVolts, \
.desc = { \
.name = #label, \
.id = TWL6030##_REG_##label, \
@@ -574,7 +556,6 @@ static const struct twlreg_info TWLFIXED_INFO_##label = { \
#define TWL6032_ADJUSTABLE_SMPS(label, offset) \
static const struct twlreg_info TWLSMPS_INFO_##label = { \
.base = offset, \
- .min_mV = 600, \
.desc = { \
.name = #label, \
.id = TWL6032_REG_##label, \
@@ -592,22 +573,22 @@ static const struct twlreg_info TWLSMPS_INFO_##label = { \
TWL6030_ADJUSTABLE_SMPS(VDD1);
TWL6030_ADJUSTABLE_SMPS(VDD2);
TWL6030_ADJUSTABLE_SMPS(VDD3);
-TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000);
-TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000);
-TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000);
-TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000);
-TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000);
-TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000);
+TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54);
+TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58);
+TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c);
+TWL6030_ADJUSTABLE_LDO(VMMC, 0x68);
+TWL6030_ADJUSTABLE_LDO(VPP, 0x6c);
+TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74);
/* 6025 are renamed compared to 6030 versions */
-TWL6032_ADJUSTABLE_LDO(LDO2, 0x54, 1000);
-TWL6032_ADJUSTABLE_LDO(LDO4, 0x58, 1000);
-TWL6032_ADJUSTABLE_LDO(LDO3, 0x5c, 1000);
-TWL6032_ADJUSTABLE_LDO(LDO5, 0x68, 1000);
-TWL6032_ADJUSTABLE_LDO(LDO1, 0x6c, 1000);
-TWL6032_ADJUSTABLE_LDO(LDO7, 0x74, 1000);
-TWL6032_ADJUSTABLE_LDO(LDO6, 0x60, 1000);
-TWL6032_ADJUSTABLE_LDO(LDOLN, 0x64, 1000);
-TWL6032_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000);
+TWL6032_ADJUSTABLE_LDO(LDO2, 0x54);
+TWL6032_ADJUSTABLE_LDO(LDO4, 0x58);
+TWL6032_ADJUSTABLE_LDO(LDO3, 0x5c);
+TWL6032_ADJUSTABLE_LDO(LDO5, 0x68);
+TWL6032_ADJUSTABLE_LDO(LDO1, 0x6c);
+TWL6032_ADJUSTABLE_LDO(LDO7, 0x74);
+TWL6032_ADJUSTABLE_LDO(LDO6, 0x60);
+TWL6032_ADJUSTABLE_LDO(LDOLN, 0x64);
+TWL6032_ADJUSTABLE_LDO(LDOUSB, 0x70);
TWL6030_FIXED_LDO(VANA, 0x50, 2100, 0);
TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 0);
TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0);
@@ -687,14 +668,9 @@ static int twlreg_probe(struct platform_device *pdev)
struct regulator_init_data *initdata;
struct regulation_constraints *c;
struct regulator_dev *rdev;
- const struct of_device_id *match;
struct regulator_config config = { };
- match = of_match_device(twl_of_match, &pdev->dev);
- if (!match)
- return -ENODEV;
-
- template = match->data;
+ template = of_device_get_match_data(&pdev->dev);
if (!template)
return -ENODEV;
diff --git a/drivers/regulator/uniphier-regulator.c b/drivers/regulator/uniphier-regulator.c
index abf22acbd13e..9026d5a3e964 100644
--- a/drivers/regulator/uniphier-regulator.c
+++ b/drivers/regulator/uniphier-regulator.c
@@ -32,7 +32,7 @@ struct uniphier_regulator_priv {
const struct uniphier_regulator_soc_data *data;
};
-static struct regulator_ops uniphier_regulator_ops = {
+static const struct regulator_ops uniphier_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@@ -87,8 +87,10 @@ static int uniphier_regulator_probe(struct platform_device *pdev)
}
regmap = devm_regmap_init_mmio(dev, base, priv->data->regconf);
- if (IS_ERR(regmap))
- return PTR_ERR(regmap);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ goto out_rst_assert;
+ }
config.dev = dev;
config.driver_data = priv;
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index 5a5bc4bb08d2..12b422373580 100644
--- a/drivers/regulator/wm831x-dcdc.c
+++ b/drivers/regulator/wm831x-dcdc.c
@@ -205,33 +205,10 @@ static irqreturn_t wm831x_dcdc_oc_irq(int irq, void *data)
* BUCKV specifics
*/
-static int wm831x_buckv_list_voltage(struct regulator_dev *rdev,
- unsigned selector)
-{
- if (selector <= 0x8)
- return 600000;
- if (selector <= WM831X_BUCKV_MAX_SELECTOR)
- return 600000 + ((selector - 0x8) * 12500);
- return -EINVAL;
-}
-
-static int wm831x_buckv_map_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV)
-{
- u16 vsel;
-
- if (min_uV < 600000)
- vsel = 0;
- else if (min_uV <= 1800000)
- vsel = DIV_ROUND_UP(min_uV - 600000, 12500) + 8;
- else
- return -EINVAL;
-
- if (wm831x_buckv_list_voltage(rdev, vsel) > max_uV)
- return -EINVAL;
-
- return vsel;
-}
+static const struct regulator_linear_range wm831x_buckv_ranges[] = {
+ REGULATOR_LINEAR_RANGE(600000, 0, 0x7, 0),
+ REGULATOR_LINEAR_RANGE(600000, 0x8, 0x68, 12500),
+};
static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state)
{
@@ -309,7 +286,7 @@ static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev,
u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;
int vsel;
- vsel = wm831x_buckv_map_voltage(rdev, uV, uV);
+ vsel = regulator_map_voltage_linear_range(rdev, uV, uV);
if (vsel < 0)
return vsel;
@@ -327,52 +304,18 @@ static int wm831x_buckv_get_voltage_sel(struct regulator_dev *rdev)
}
/* Current limit options */
-static u16 wm831x_dcdc_ilim[] = {
- 125, 250, 375, 500, 625, 750, 875, 1000
+static const unsigned int wm831x_dcdc_ilim[] = {
+ 125000, 250000, 375000, 500000, 625000, 750000, 875000, 1000000
};
-static int wm831x_buckv_set_current_limit(struct regulator_dev *rdev,
- int min_uA, int max_uA)
-{
- struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
- struct wm831x *wm831x = dcdc->wm831x;
- u16 reg = dcdc->base + WM831X_DCDC_CONTROL_2;
- int i;
-
- for (i = ARRAY_SIZE(wm831x_dcdc_ilim) - 1; i >= 0; i--) {
- if ((min_uA <= wm831x_dcdc_ilim[i]) &&
- (wm831x_dcdc_ilim[i] <= max_uA))
- return wm831x_set_bits(wm831x, reg,
- WM831X_DC1_HC_THR_MASK,
- i << WM831X_DC1_HC_THR_SHIFT);
- }
-
- return -EINVAL;
-}
-
-static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev)
-{
- struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
- struct wm831x *wm831x = dcdc->wm831x;
- u16 reg = dcdc->base + WM831X_DCDC_CONTROL_2;
- int val;
-
- val = wm831x_reg_read(wm831x, reg);
- if (val < 0)
- return val;
-
- val = (val & WM831X_DC1_HC_THR_MASK) >> WM831X_DC1_HC_THR_SHIFT;
- return wm831x_dcdc_ilim[val];
-}
-
static const struct regulator_ops wm831x_buckv_ops = {
.set_voltage_sel = wm831x_buckv_set_voltage_sel,
.get_voltage_sel = wm831x_buckv_get_voltage_sel,
- .list_voltage = wm831x_buckv_list_voltage,
- .map_voltage = wm831x_buckv_map_voltage,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
.set_suspend_voltage = wm831x_buckv_set_suspend_voltage,
- .set_current_limit = wm831x_buckv_set_current_limit,
- .get_current_limit = wm831x_buckv_get_current_limit,
+ .set_current_limit = regulator_set_current_limit_regmap,
+ .get_current_limit = regulator_get_current_limit_regmap,
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
@@ -492,10 +435,16 @@ static int wm831x_buckv_probe(struct platform_device *pdev)
dcdc->desc.id = id;
dcdc->desc.type = REGULATOR_VOLTAGE;
dcdc->desc.n_voltages = WM831X_BUCKV_MAX_SELECTOR + 1;
+ dcdc->desc.linear_ranges = wm831x_buckv_ranges;
+ dcdc->desc.n_linear_ranges = ARRAY_SIZE(wm831x_buckv_ranges);
dcdc->desc.ops = &wm831x_buckv_ops;
dcdc->desc.owner = THIS_MODULE;
dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;
dcdc->desc.enable_mask = 1 << id;
+ dcdc->desc.csel_reg = dcdc->base + WM831X_DCDC_CONTROL_2;
+ dcdc->desc.csel_mask = WM831X_DC1_HC_THR_MASK;
+ dcdc->desc.n_current_limits = ARRAY_SIZE(wm831x_dcdc_ilim);
+ dcdc->desc.curr_table = wm831x_dcdc_ilim;
ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG);
if (ret < 0) {
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index 8ad11b074b49..a1c7dfee5c37 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -1153,7 +1153,7 @@ static irqreturn_t pmic_uv_handler(int irq, void *data)
{
struct regulator_dev *rdev = (struct regulator_dev *)data;
- mutex_lock(&rdev->mutex);
+ regulator_lock(rdev);
if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2)
regulator_notifier_call_chain(rdev,
REGULATOR_EVENT_REGULATION_OUT,
@@ -1162,7 +1162,7 @@ static irqreturn_t pmic_uv_handler(int irq, void *data)
regulator_notifier_call_chain(rdev,
REGULATOR_EVENT_UNDER_VOLTAGE,
NULL);
- mutex_unlock(&rdev->mutex);
+ regulator_unlock(rdev);
return IRQ_HANDLED;
}
diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c
index 7a4ce6df4f22..38928cdcb6e6 100644
--- a/drivers/regulator/wm8994-regulator.c
+++ b/drivers/regulator/wm8994-regulator.c
@@ -19,7 +19,7 @@
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/slab.h>
#include <linux/mfd/wm8994/core.h>
@@ -129,6 +129,7 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
int id = pdev->id % ARRAY_SIZE(pdata->ldo);
struct regulator_config config = { };
struct wm8994_ldo *ldo;
+ struct gpio_desc *gpiod;
int ret;
dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
@@ -145,12 +146,18 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
config.driver_data = ldo;
config.regmap = wm8994->regmap;
config.init_data = &ldo->init_data;
- if (pdata) {
- config.ena_gpio = pdata->ldo[id].enable;
- } else if (wm8994->dev->of_node) {
- config.ena_gpio = wm8994->pdata.ldo[id].enable;
- config.ena_gpio_initialized = true;
- }
+
+ /*
+ * Look up LDO enable GPIO from the parent device node, we don't
+ * use devm because the regulator core will free the GPIO
+ */
+ gpiod = gpiod_get_optional(pdev->dev.parent,
+ id ? "wlf,ldo2ena" : "wlf,ldo1ena",
+ GPIOD_OUT_LOW |
+ GPIOD_FLAGS_BIT_NONEXCLUSIVE);
+ if (IS_ERR(gpiod))
+ return PTR_ERR(gpiod);
+ config.ena_gpiod = gpiod;
/* Use default constraints if none set up */
if (!pdata || !pdata->ldo[id].init_data || wm8994->dev->of_node) {
@@ -159,12 +166,17 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
ldo->init_data = wm8994_ldo_default[id];
ldo->init_data.consumer_supplies = &ldo->supply;
- if (!config.ena_gpio)
+ if (!gpiod)
ldo->init_data.constraints.valid_ops_mask = 0;
} else {
ldo->init_data = *pdata->ldo[id].init_data;
}
+ /*
+ * At this point the GPIO descriptor is handled over to the
+ * regulator core and we need not worry about it on the
+ * error path.
+ */
ldo->regulator = devm_regulator_register(&pdev->dev,
&wm8994_ldo_desc[id],
&config);
@@ -172,15 +184,12 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
ret = PTR_ERR(ldo->regulator);
dev_err(wm8994->dev, "Failed to register LDO%d: %d\n",
id + 1, ret);
- goto err;
+ return ret;
}
platform_set_drvdata(pdev, ldo);
return 0;
-
-err:
- return ret;
}
static struct platform_driver wm8994_ldo_driver = {