summaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/88pm8607.c3
-rw-r--r--drivers/regulator/Kconfig20
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/act8865-regulator.c31
-rw-r--r--drivers/regulator/anatop-regulator.c18
-rw-r--r--drivers/regulator/arizona-ldo1.c10
-rw-r--r--drivers/regulator/arizona-micsupp.c8
-rw-r--r--drivers/regulator/core.c23
-rw-r--r--drivers/regulator/da9052-regulator.c3
-rw-r--r--drivers/regulator/da9063-regulator.c19
-rw-r--r--drivers/regulator/da9210-regulator.c2
-rw-r--r--drivers/regulator/dummy.c2
-rw-r--r--drivers/regulator/fan53555.c17
-rw-r--r--drivers/regulator/fixed.c24
-rw-r--r--drivers/regulator/gpio-regulator.c115
-rw-r--r--drivers/regulator/max1586.c2
-rw-r--r--drivers/regulator/max77686.c172
-rw-r--r--drivers/regulator/max77693.c4
-rw-r--r--drivers/regulator/max77802.c254
-rw-r--r--drivers/regulator/max8660.c2
-rw-r--r--drivers/regulator/max8952.c4
-rw-r--r--drivers/regulator/max8973-regulator.c3
-rw-r--r--drivers/regulator/max8997.c3
-rw-r--r--drivers/regulator/max8998.c5
-rw-r--r--drivers/regulator/mc13xxx-regulator-core.c3
-rw-r--r--drivers/regulator/of_regulator.c90
-rw-r--r--drivers/regulator/pwm-regulator.c3
-rw-r--r--drivers/regulator/qcom_rpm-regulator.c28
-rw-r--r--drivers/regulator/rk808-regulator.c57
-rw-r--r--drivers/regulator/rn5t618-regulator.c51
-rw-r--r--drivers/regulator/rt5033-regulator.c123
-rw-r--r--drivers/regulator/s2mpa01.c4
-rw-r--r--drivers/regulator/s2mps11.c105
-rw-r--r--drivers/regulator/s5m8767.c4
-rw-r--r--drivers/regulator/sky81452-regulator.c46
-rw-r--r--drivers/regulator/stw481x-vmmc.c3
-rw-r--r--drivers/regulator/ti-abb-regulator.c3
-rw-r--r--drivers/regulator/tps51632-regulator.c43
-rw-r--r--drivers/regulator/tps62360-regulator.c31
-rw-r--r--drivers/regulator/tps65090-regulator.c4
-rw-r--r--drivers/regulator/tps65218-regulator.c3
-rw-r--r--drivers/regulator/twl-regulator.c3
-rw-r--r--drivers/regulator/vexpress.c3
-rw-r--r--drivers/regulator/wm8994-regulator.c6
44 files changed, 895 insertions, 463 deletions
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index 6d77dcd7dcf6..3fe47bd66153 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -330,7 +330,8 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev,
for_each_child_of_node(nproot, np) {
if (!of_node_cmp(np->name, info->desc.name)) {
config->init_data =
- of_get_regulator_init_data(&pdev->dev, np);
+ of_get_regulator_init_data(&pdev->dev, np,
+ &info->desc);
config->of_node = np;
break;
}
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 55d7b7b0f2e0..c3a60b57a865 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -521,6 +521,14 @@ config REGULATOR_RN5T618
help
Say y here to support the regulators found on Ricoh RN5T618 PMIC.
+config REGULATOR_RT5033
+ tristate "Richtek RT5033 Regulators"
+ depends on MFD_RT5033
+ help
+ This adds support for voltage and current regulators in Richtek
+ RT5033 PMIC. The device supports multiple regulators like
+ current source, LDO and Buck.
+
config REGULATOR_S2MPA01
tristate "Samsung S2MPA01 voltage regulator"
depends on MFD_SEC_CORE
@@ -529,13 +537,13 @@ config REGULATOR_S2MPA01
via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs.
config REGULATOR_S2MPS11
- tristate "Samsung S2MPS11/S2MPS14/S2MPU02 voltage regulator"
+ tristate "Samsung S2MPS11/S2MPS13/S2MPS14/S2MPU02 voltage regulator"
depends on MFD_SEC_CORE
help
- This driver supports a Samsung S2MPS11/S2MPS14/S2MPU02 voltage output
- regulator via I2C bus. The chip is comprised of high efficient Buck
- converters including Dual-Phase Buck converter, Buck-Boost converter,
- various LDOs.
+ This driver supports a Samsung S2MPS11/S2MPS13/S2MPS14/S2MPU02 voltage
+ output regulator via I2C bus. The chip is comprised of high efficient
+ Buck converters including Dual-Phase Buck converter, Buck-Boost
+ converter, various LDOs.
config REGULATOR_S5M8767
tristate "Samsung S5M8767A voltage regulator"
@@ -547,7 +555,7 @@ config REGULATOR_S5M8767
config REGULATOR_SKY81452
tristate "Skyworks Solutions SKY81452 voltage regulator"
- depends on SKY81452
+ depends on MFD_SKY81452
help
This driver supports Skyworks SKY81452 voltage output regulator
via I2C bus. SKY81452 has one voltage linear regulator can be
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 1029ed39c512..1f28ebfc6f3a 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
obj-$(CONFIG_REGULATOR_RK808) += rk808-regulator.o
obj-$(CONFIG_REGULATOR_RN5T618) += rn5t618-regulator.o
+obj-$(CONFIG_REGULATOR_RT5033) += rt5033-regulator.o
obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c
index afd06f92dfdf..9eec453b745d 100644
--- a/drivers/regulator/act8865-regulator.c
+++ b/drivers/regulator/act8865-regulator.c
@@ -61,6 +61,8 @@
#define ACT8846_REG12_VSET 0xa0
#define ACT8846_REG12_CTRL 0xa1
#define ACT8846_REG13_CTRL 0xb1
+#define ACT8846_GLB_OFF_CTRL 0xc3
+#define ACT8846_OFF_SYSMASK 0x18
/*
* ACT8865 Global Register Map.
@@ -84,6 +86,7 @@
#define ACT8865_LDO3_CTRL 0x61
#define ACT8865_LDO4_VSET 0x64
#define ACT8865_LDO4_CTRL 0x65
+#define ACT8865_MSTROFF 0x20
/*
* Field Definitions.
@@ -98,6 +101,8 @@
struct act8865 {
struct regmap *regmap;
+ int off_reg;
+ int off_mask;
};
static const struct regmap_config act8865_regmap_config = {
@@ -275,6 +280,16 @@ static struct regulator_init_data
return NULL;
}
+static struct i2c_client *act8865_i2c_client;
+static void act8865_power_off(void)
+{
+ struct act8865 *act8865;
+
+ act8865 = i2c_get_clientdata(act8865_i2c_client);
+ regmap_write(act8865->regmap, act8865->off_reg, act8865->off_mask);
+ while (1);
+}
+
static int act8865_pmic_probe(struct i2c_client *client,
const struct i2c_device_id *i2c_id)
{
@@ -285,6 +300,7 @@ static int act8865_pmic_probe(struct i2c_client *client,
int i, ret, num_regulators;
struct act8865 *act8865;
unsigned long type;
+ int off_reg, off_mask;
pdata = dev_get_platdata(dev);
@@ -304,10 +320,14 @@ static int act8865_pmic_probe(struct i2c_client *client,
case ACT8846:
regulators = act8846_regulators;
num_regulators = ARRAY_SIZE(act8846_regulators);
+ off_reg = ACT8846_GLB_OFF_CTRL;
+ off_mask = ACT8846_OFF_SYSMASK;
break;
case ACT8865:
regulators = act8865_regulators;
num_regulators = ARRAY_SIZE(act8865_regulators);
+ off_reg = ACT8865_SYS_CTRL;
+ off_mask = ACT8865_MSTROFF;
break;
default:
dev_err(dev, "invalid device id %lu\n", type);
@@ -345,6 +365,17 @@ static int act8865_pmic_probe(struct i2c_client *client,
return ret;
}
+ if (of_device_is_system_power_controller(dev->of_node)) {
+ if (!pm_power_off) {
+ act8865_i2c_client = client;
+ act8865->off_reg = off_reg;
+ act8865->off_mask = off_mask;
+ pm_power_off = act8865_power_off;
+ } else {
+ dev_err(dev, "Failed to set poweroff capability, already defined\n");
+ }
+ }
+
/* Finally register devices */
for (i = 0; i < num_regulators; i++) {
const struct regulator_desc *desc = &regulators[i];
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
index 4f730af70e7c..3586571814b2 100644
--- a/drivers/regulator/anatop-regulator.c
+++ b/drivers/regulator/anatop-regulator.c
@@ -189,17 +189,18 @@ static int anatop_regulator_probe(struct platform_device *pdev)
int ret = 0;
u32 val;
- initdata = of_get_regulator_init_data(dev, np);
sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL);
if (!sreg)
return -ENOMEM;
- sreg->initdata = initdata;
sreg->name = of_get_property(np, "regulator-name", NULL);
rdesc = &sreg->rdesc;
rdesc->name = sreg->name;
rdesc->type = REGULATOR_VOLTAGE;
rdesc->owner = THIS_MODULE;
+ initdata = of_get_regulator_init_data(dev, np, rdesc);
+ sreg->initdata = initdata;
+
anatop_np = of_get_parent(np);
if (!anatop_np)
return -ENODEV;
@@ -283,6 +284,19 @@ static int anatop_regulator_probe(struct platform_device *pdev)
sreg->sel = 0;
sreg->bypass = true;
}
+
+ /*
+ * In case vddpu was disabled by the bootloader, we need to set
+ * a sane default until imx6-cpufreq was probed and changes the
+ * voltage to the correct value. In this case we set 1.25V.
+ */
+ if (!sreg->sel && !strcmp(sreg->name, "vddpu"))
+ sreg->sel = 22;
+
+ if (!sreg->sel) {
+ dev_err(&pdev->dev, "Failed to read a valid default voltage selector.\n");
+ return -EINVAL;
+ }
} else {
rdesc->ops = &anatop_rops;
}
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
index 4c9db589f6c1..d071b2119a60 100644
--- a/drivers/regulator/arizona-ldo1.c
+++ b/drivers/regulator/arizona-ldo1.c
@@ -179,7 +179,8 @@ static const struct regulator_init_data arizona_ldo1_default = {
};
static int arizona_ldo1_of_get_pdata(struct arizona *arizona,
- struct regulator_config *config)
+ struct regulator_config *config,
+ const struct regulator_desc *desc)
{
struct arizona_pdata *pdata = &arizona->pdata;
struct arizona_ldo1 *ldo1 = config->driver_data;
@@ -194,7 +195,8 @@ static int arizona_ldo1_of_get_pdata(struct arizona *arizona,
if (init_node) {
config->of_node = init_node;
- init_data = of_get_regulator_init_data(arizona->dev, init_node);
+ init_data = of_get_regulator_init_data(arizona->dev, init_node,
+ desc);
if (init_data) {
init_data->consumer_supplies = &ldo1->supply;
@@ -257,9 +259,11 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
if (IS_ENABLED(CONFIG_OF)) {
if (!dev_get_platdata(arizona->dev)) {
- ret = arizona_ldo1_of_get_pdata(arizona, &config);
+ ret = arizona_ldo1_of_get_pdata(arizona, &config, desc);
if (ret < 0)
return ret;
+
+ config.ena_gpio_initialized = true;
}
}
diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c
index ce9aca5f8ee7..c313ef4c3a2f 100644
--- a/drivers/regulator/arizona-micsupp.c
+++ b/drivers/regulator/arizona-micsupp.c
@@ -198,7 +198,8 @@ static const struct regulator_init_data arizona_micsupp_ext_default = {
};
static int arizona_micsupp_of_get_pdata(struct arizona *arizona,
- struct regulator_config *config)
+ struct regulator_config *config,
+ const struct regulator_desc *desc)
{
struct arizona_pdata *pdata = &arizona->pdata;
struct arizona_micsupp *micsupp = config->driver_data;
@@ -210,7 +211,7 @@ static int arizona_micsupp_of_get_pdata(struct arizona *arizona,
if (np) {
config->of_node = np;
- init_data = of_get_regulator_init_data(arizona->dev, np);
+ init_data = of_get_regulator_init_data(arizona->dev, np, desc);
if (init_data) {
init_data->consumer_supplies = &micsupp->supply;
@@ -264,7 +265,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
if (IS_ENABLED(CONFIG_OF)) {
if (!dev_get_platdata(arizona->dev)) {
- ret = arizona_micsupp_of_get_pdata(arizona, &config);
+ ret = arizona_micsupp_of_get_pdata(arizona, &config,
+ desc);
if (ret < 0)
return ret;
}
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index cd87c0c37034..e225711bb8bc 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -828,7 +828,7 @@ static void print_constraints(struct regulator_dev *rdev)
if (!count)
sprintf(buf, "no parameters");
- rdev_info(rdev, "%s\n", buf);
+ rdev_dbg(rdev, "%s\n", buf);
if ((constraints->min_uV != constraints->max_uV) &&
!(constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE))
@@ -1713,6 +1713,8 @@ static void regulator_ena_gpio_free(struct regulator_dev *rdev)
gpiod_put(pin->gpiod);
list_del(&pin->list);
kfree(pin);
+ rdev->ena_pin = NULL;
+ return;
} else {
pin->request_count--;
}
@@ -1976,9 +1978,18 @@ static int _regulator_disable(struct regulator_dev *rdev)
/* we are last user */
if (_regulator_can_change_status(rdev)) {
+ ret = _notifier_call_chain(rdev,
+ REGULATOR_EVENT_PRE_DISABLE,
+ NULL);
+ if (ret & NOTIFY_STOP_MASK)
+ return -EINVAL;
+
ret = _regulator_do_disable(rdev);
if (ret < 0) {
rdev_err(rdev, "failed to disable\n");
+ _notifier_call_chain(rdev,
+ REGULATOR_EVENT_ABORT_DISABLE,
+ NULL);
return ret;
}
_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
@@ -2035,9 +2046,16 @@ static int _regulator_force_disable(struct regulator_dev *rdev)
{
int ret = 0;
+ ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
+ REGULATOR_EVENT_PRE_DISABLE, NULL);
+ if (ret & NOTIFY_STOP_MASK)
+ return -EINVAL;
+
ret = _regulator_do_disable(rdev);
if (ret < 0) {
rdev_err(rdev, "failed to force disable\n");
+ _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
+ REGULATOR_EVENT_ABORT_DISABLE, NULL);
return ret;
}
@@ -3650,7 +3668,8 @@ regulator_register(const struct regulator_desc *regulator_desc,
dev_set_drvdata(&rdev->dev, rdev);
- if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) {
+ if ((config->ena_gpio || config->ena_gpio_initialized) &&
+ gpio_is_valid(config->ena_gpio)) {
ret = regulator_ena_gpio_request(rdev, config);
if (ret != 0) {
rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c
index 00033625a09c..3945f1006d23 100644
--- a/drivers/regulator/da9052-regulator.c
+++ b/drivers/regulator/da9052-regulator.c
@@ -436,7 +436,8 @@ static int da9052_regulator_probe(struct platform_device *pdev)
if (!of_node_cmp(np->name,
regulator->info->reg_desc.name)) {
config.init_data = of_get_regulator_init_data(
- &pdev->dev, np);
+ &pdev->dev, np,
+ &regulator->info->reg_desc);
config.of_node = np;
break;
}
diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c
index 7c9461d13313..37dd42759ca9 100644
--- a/drivers/regulator/da9063-regulator.c
+++ b/drivers/regulator/da9063-regulator.c
@@ -867,17 +867,14 @@ static int da9063_regulator_probe(struct platform_device *pdev)
return irq;
}
- regulators->irq_ldo_lim = regmap_irq_get_virq(da9063->regmap_irq, irq);
- if (regulators->irq_ldo_lim >= 0) {
- ret = request_threaded_irq(regulators->irq_ldo_lim,
- NULL, da9063_ldo_lim_event,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- "LDO_LIM", regulators);
- if (ret) {
- dev_err(&pdev->dev,
- "Failed to request LDO_LIM IRQ.\n");
- regulators->irq_ldo_lim = -ENXIO;
- }
+ ret = request_threaded_irq(irq,
+ NULL, da9063_ldo_lim_event,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "LDO_LIM", regulators);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to request LDO_LIM IRQ.\n");
+ regulators->irq_ldo_lim = -ENXIO;
}
return 0;
diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c
index 7a320dd11c46..bc6100103f7f 100644
--- a/drivers/regulator/da9210-regulator.c
+++ b/drivers/regulator/da9210-regulator.c
@@ -147,7 +147,7 @@ static int da9210_i2c_probe(struct i2c_client *i2c,
config.dev = &i2c->dev;
config.init_data = pdata ? &pdata->da9210_constraints :
- of_get_regulator_init_data(dev, dev->of_node);
+ of_get_regulator_init_data(dev, dev->of_node, &da9210_reg);
config.driver_data = chip;
config.regmap = chip->regmap;
config.of_node = dev->of_node;
diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c
index 2436db9e2ca3..7aef9e4c6fbf 100644
--- a/drivers/regulator/dummy.c
+++ b/drivers/regulator/dummy.c
@@ -33,7 +33,7 @@ static struct regulator_init_data dummy_initdata = {
static struct regulator_ops dummy_ops;
-static struct regulator_desc dummy_desc = {
+static const struct regulator_desc dummy_desc = {
.name = "regulator-dummy",
.id = -1,
.type = REGULATOR_VOLTAGE,
diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
index f8e4257aef92..6c43ab2d5121 100644
--- a/drivers/regulator/fan53555.c
+++ b/drivers/regulator/fan53555.c
@@ -302,7 +302,8 @@ static struct regmap_config fan53555_regmap_config = {
};
static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev,
- struct device_node *np)
+ struct device_node *np,
+ const struct regulator_desc *desc)
{
struct fan53555_platform_data *pdata;
int ret;
@@ -312,7 +313,7 @@ static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev,
if (!pdata)
return NULL;
- pdata->regulator = of_get_regulator_init_data(dev, np);
+ pdata->regulator = of_get_regulator_init_data(dev, np, desc);
ret = of_property_read_u32(np, "fcs,suspend-voltage-selector",
&tmp);
@@ -347,20 +348,20 @@ static int fan53555_regulator_probe(struct i2c_client *client,
unsigned int val;
int ret;
+ di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info),
+ GFP_KERNEL);
+ if (!di)
+ return -ENOMEM;
+
pdata = dev_get_platdata(&client->dev);
if (!pdata)
- pdata = fan53555_parse_dt(&client->dev, np);
+ pdata = fan53555_parse_dt(&client->dev, np, &di->desc);
if (!pdata || !pdata->regulator) {
dev_err(&client->dev, "Platform data not found!\n");
return -ENODEV;
}
- di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info),
- GFP_KERNEL);
- if (!di)
- return -ENOMEM;
-
di->regulator = pdata->regulator;
if (client->dev.of_node) {
const struct of_device_id *match;
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index 354105eff1f8..d21da27c0eb6 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -40,13 +40,15 @@ struct fixed_voltage_data {
/**
* of_get_fixed_voltage_config - extract fixed_voltage_config structure info
* @dev: device requesting for fixed_voltage_config
+ * @desc: regulator description
*
* Populates fixed_voltage_config structure by extracting data from device
* tree node, returns a pointer to the populated structure of NULL if memory
* alloc fails.
*/
static struct fixed_voltage_config *
-of_get_fixed_voltage_config(struct device *dev)
+of_get_fixed_voltage_config(struct device *dev,
+ const struct regulator_desc *desc)
{
struct fixed_voltage_config *config;
struct device_node *np = dev->of_node;
@@ -57,7 +59,7 @@ of_get_fixed_voltage_config(struct device *dev)
if (!config)
return ERR_PTR(-ENOMEM);
- config->init_data = of_get_regulator_init_data(dev, dev->of_node);
+ config->init_data = of_get_regulator_init_data(dev, dev->of_node, desc);
if (!config->init_data)
return ERR_PTR(-EINVAL);
@@ -112,8 +114,14 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
struct regulator_config cfg = { };
int ret;
+ drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),
+ GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+
if (pdev->dev.of_node) {
- config = of_get_fixed_voltage_config(&pdev->dev);
+ config = of_get_fixed_voltage_config(&pdev->dev,
+ &drvdata->desc);
if (IS_ERR(config))
return PTR_ERR(config);
} else {
@@ -123,11 +131,6 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
if (!config)
return -ENOMEM;
- drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),
- GFP_KERNEL);
- if (!drvdata)
- return -ENOMEM;
-
drvdata->desc.name = devm_kstrdup(&pdev->dev,
config->supply_name,
GFP_KERNEL);
@@ -157,8 +160,11 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
drvdata->desc.fixed_uV = config->microvolts;
- if (config->gpio >= 0)
+ if (gpio_is_valid(config->gpio)) {
cfg.ena_gpio = config->gpio;
+ if (pdev->dev.of_node)
+ cfg.ena_gpio_initialized = true;
+ }
cfg.ena_gpio_invert = !config->enable_high;
if (config->enabled_at_boot) {
if (config->enable_high)
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
index 989b23b377c0..c888a9a9482c 100644
--- a/drivers/regulator/gpio-regulator.c
+++ b/drivers/regulator/gpio-regulator.c
@@ -133,7 +133,8 @@ static struct regulator_ops gpio_regulator_voltage_ops = {
};
static struct gpio_regulator_config *
-of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
+of_get_gpio_regulator_config(struct device *dev, struct device_node *np,
+ const struct regulator_desc *desc)
{
struct gpio_regulator_config *config;
const char *regtype;
@@ -146,7 +147,7 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
if (!config)
return ERR_PTR(-ENOMEM);
- config->init_data = of_get_regulator_init_data(dev, np);
+ config->init_data = of_get_regulator_init_data(dev, np, desc);
if (!config->init_data)
return ERR_PTR(-EINVAL);
@@ -162,34 +163,41 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
- /* Fetch GPIOs. */
- config->nr_gpios = of_gpio_count(np);
-
- config->gpios = devm_kzalloc(dev,
- sizeof(struct gpio) * config->nr_gpios,
- GFP_KERNEL);
- if (!config->gpios)
- return ERR_PTR(-ENOMEM);
-
- proplen = of_property_count_u32_elems(np, "gpios-states");
- /* optional property */
- if (proplen < 0)
- proplen = 0;
-
- if (proplen > 0 && proplen != config->nr_gpios) {
- dev_warn(dev, "gpios <-> gpios-states mismatch\n");
- proplen = 0;
- }
+ /* 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_kzalloc(dev,
+ sizeof(struct gpio) * config->nr_gpios,
+ GFP_KERNEL);
+ if (!config->gpios)
+ return ERR_PTR(-ENOMEM);
+
+ proplen = of_property_count_u32_elems(np, "gpios-states");
+ /* optional property */
+ if (proplen < 0)
+ proplen = 0;
+
+ if (proplen > 0 && proplen != config->nr_gpios) {
+ dev_warn(dev, "gpios <-> gpios-states mismatch\n");
+ proplen = 0;
+ }
- for (i = 0; i < config->nr_gpios; i++) {
- gpio = of_get_named_gpio(np, "gpios", i);
- if (gpio < 0)
- break;
- config->gpios[i].gpio = gpio;
- if (proplen > 0) {
- of_property_read_u32_index(np, "gpios-states", i, &ret);
- if (ret)
- config->gpios[i].flags = GPIOF_OUT_INIT_HIGH;
+ for (i = 0; i < config->nr_gpios; i++) {
+ gpio = of_get_named_gpio(np, "gpios", i);
+ if (gpio < 0)
+ break;
+ config->gpios[i].gpio = gpio;
+ if (proplen > 0) {
+ of_property_read_u32_index(np, "gpios-states",
+ i, &ret);
+ if (ret)
+ config->gpios[i].flags =
+ GPIOF_OUT_INIT_HIGH;
+ }
}
}
@@ -243,17 +251,18 @@ static int gpio_regulator_probe(struct platform_device *pdev)
struct regulator_config cfg = { };
int ptr, ret, state;
- if (np) {
- config = of_get_gpio_regulator_config(&pdev->dev, np);
- if (IS_ERR(config))
- return PTR_ERR(config);
- }
-
drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data),
GFP_KERNEL);
if (drvdata == NULL)
return -ENOMEM;
+ if (np) {
+ config = of_get_gpio_regulator_config(&pdev->dev, np,
+ &drvdata->desc);
+ if (IS_ERR(config))
+ return PTR_ERR(config);
+ }
+
drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL);
if (drvdata->desc.name == NULL) {
dev_err(&pdev->dev, "Failed to allocate supply name\n");
@@ -261,13 +270,23 @@ static int gpio_regulator_probe(struct platform_device *pdev)
goto err;
}
- 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;
+ 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) {
+ dev_err(&pdev->dev,
+ "Could not obtain regulator setting GPIOs: %d\n", ret);
+ goto err_memstate;
+ }
}
drvdata->states = kmemdup(config->states,
@@ -301,14 +320,6 @@ static int gpio_regulator_probe(struct platform_device *pdev)
goto err_memgpio;
}
- drvdata->nr_gpios = config->nr_gpios;
- ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios);
- if (ret) {
- dev_err(&pdev->dev,
- "Could not obtain regulator setting GPIOs: %d\n", ret);
- goto err_memstate;
- }
-
/* build initial state from gpio init data. */
state = 0;
for (ptr = 0; ptr < drvdata->nr_gpios; ptr++) {
@@ -322,8 +333,10 @@ static int gpio_regulator_probe(struct platform_device *pdev)
cfg.driver_data = drvdata;
cfg.of_node = np;
- if (config->enable_gpio >= 0)
+ 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)
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
index 86db310d5304..d2a8c64cae42 100644
--- a/drivers/regulator/max1586.c
+++ b/drivers/regulator/max1586.c
@@ -163,7 +163,7 @@ static int of_get_max1586_platform_data(struct device *dev,
struct max1586_platform_data *pdata)
{
struct max1586_subdev_data *sub;
- struct of_regulator_match rmatch[ARRAY_SIZE(max1586_reg)];
+ struct of_regulator_match rmatch[ARRAY_SIZE(max1586_reg)] = { };
struct device_node *np = dev->of_node;
int i, matched;
diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c
index ef1af2debbd2..871b96bcd2d0 100644
--- a/drivers/regulator/max77686.c
+++ b/drivers/regulator/max77686.c
@@ -45,6 +45,23 @@
#define MAX77686_DVS_MINUV 600000
#define MAX77686_DVS_UVSTEP 12500
+/*
+ * Values used for configuring LDOs and bucks.
+ * Forcing low power mode: LDO1, 3-5, 9, 13, 17-26
+ */
+#define MAX77686_LDO_LOWPOWER 0x1
+/*
+ * On/off controlled by PWRREQ:
+ * - LDO2, 6-8, 10-12, 14-16
+ * - buck[1234]
+ */
+#define MAX77686_OFF_PWRREQ 0x1
+/* Low power mode controlled by PWRREQ: All LDOs */
+#define MAX77686_LDO_LOWPOWER_PWRREQ 0x2
+/* Forcing low power mode: buck[234] */
+#define MAX77686_BUCK_LOWPOWER 0x2
+#define MAX77686_NORMAL 0x3
+
#define MAX77686_OPMODE_SHIFT 6
#define MAX77686_OPMODE_BUCK234_SHIFT 4
#define MAX77686_OPMODE_MASK 0x3
@@ -65,23 +82,36 @@ enum max77686_ramp_rate {
};
struct max77686_data {
+ /* Array indexed by regulator id */
unsigned int opmode[MAX77686_REGULATORS];
};
-/* Some BUCKS supports Normal[ON/OFF] mode during suspend */
-static int max77686_buck_set_suspend_disable(struct regulator_dev *rdev)
+static unsigned int max77686_get_opmode_shift(int id)
{
- unsigned int val;
+ switch (id) {
+ case MAX77686_BUCK1:
+ case MAX77686_BUCK5 ... MAX77686_BUCK9:
+ return 0;
+ case MAX77686_BUCK2 ... MAX77686_BUCK4:
+ return MAX77686_OPMODE_BUCK234_SHIFT;
+ default:
+ /* all LDOs */
+ return MAX77686_OPMODE_SHIFT;
+ }
+}
+
+/* Some BUCKs and LDOs supports Normal[ON/OFF] mode during suspend */
+static int max77686_set_suspend_disable(struct regulator_dev *rdev)
+{
+ unsigned int val, shift;
struct max77686_data *max77686 = rdev_get_drvdata(rdev);
int ret, id = rdev_get_id(rdev);
- if (id == MAX77686_BUCK1)
- val = 0x1;
- else
- val = 0x1 << MAX77686_OPMODE_BUCK234_SHIFT;
+ shift = max77686_get_opmode_shift(id);
+ val = MAX77686_OFF_PWRREQ;
ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
- rdev->desc->enable_mask, val);
+ rdev->desc->enable_mask, val << shift);
if (ret)
return ret;
@@ -103,10 +133,10 @@ static int max77686_set_suspend_mode(struct regulator_dev *rdev,
switch (mode) {
case REGULATOR_MODE_IDLE: /* ON in LP Mode */
- val = 0x2 << MAX77686_OPMODE_SHIFT;
+ val = MAX77686_LDO_LOWPOWER_PWRREQ;
break;
case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */
- val = 0x3 << MAX77686_OPMODE_SHIFT;
+ val = MAX77686_NORMAL;
break;
default:
pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
@@ -115,7 +145,8 @@ static int max77686_set_suspend_mode(struct regulator_dev *rdev,
}
ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
- rdev->desc->enable_mask, val);
+ rdev->desc->enable_mask,
+ val << MAX77686_OPMODE_SHIFT);
if (ret)
return ret;
@@ -133,13 +164,13 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
switch (mode) {
case REGULATOR_MODE_STANDBY: /* switch off */
- val = 0x1 << MAX77686_OPMODE_SHIFT;
+ val = MAX77686_OFF_PWRREQ;
break;
case REGULATOR_MODE_IDLE: /* ON in LP Mode */
- val = 0x2 << MAX77686_OPMODE_SHIFT;
+ val = MAX77686_LDO_LOWPOWER_PWRREQ;
break;
case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */
- val = 0x3 << MAX77686_OPMODE_SHIFT;
+ val = MAX77686_NORMAL;
break;
default:
pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
@@ -148,7 +179,8 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
}
ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
- rdev->desc->enable_mask, val);
+ rdev->desc->enable_mask,
+ val << MAX77686_OPMODE_SHIFT);
if (ret)
return ret;
@@ -159,10 +191,17 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
static int max77686_enable(struct regulator_dev *rdev)
{
struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+ unsigned int shift;
+ int id = rdev_get_id(rdev);
+
+ shift = max77686_get_opmode_shift(id);
+
+ if (max77686->opmode[id] == MAX77686_OFF_PWRREQ)
+ max77686->opmode[id] = MAX77686_NORMAL;
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask,
- max77686->opmode[rdev_get_id(rdev)]);
+ max77686->opmode[id] << shift);
}
static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
@@ -212,6 +251,7 @@ static struct regulator_ops max77686_ldo_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_suspend_mode = max77686_ldo_set_suspend_mode,
+ .set_suspend_disable = max77686_set_suspend_disable,
};
static struct regulator_ops max77686_buck1_ops = {
@@ -223,7 +263,7 @@ static struct regulator_ops max77686_buck1_ops = {
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
- .set_suspend_disable = max77686_buck_set_suspend_disable,
+ .set_suspend_disable = max77686_set_suspend_disable,
};
static struct regulator_ops max77686_buck_dvs_ops = {
@@ -236,11 +276,13 @@ static struct regulator_ops max77686_buck_dvs_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_ramp_delay = max77686_set_ramp_delay,
- .set_suspend_disable = max77686_buck_set_suspend_disable,
+ .set_suspend_disable = max77686_set_suspend_disable,
};
#define regulator_desc_ldo(num) { \
.name = "LDO"#num, \
+ .of_match = of_match_ptr("LDO"#num), \
+ .regulators_node = of_match_ptr("voltage-regulators"), \
.id = MAX77686_LDO##num, \
.ops = &max77686_ops, \
.type = REGULATOR_VOLTAGE, \
@@ -257,6 +299,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
}
#define regulator_desc_lpm_ldo(num) { \
.name = "LDO"#num, \
+ .of_match = of_match_ptr("LDO"#num), \
+ .regulators_node = of_match_ptr("voltage-regulators"), \
.id = MAX77686_LDO##num, \
.ops = &max77686_ldo_ops, \
.type = REGULATOR_VOLTAGE, \
@@ -273,6 +317,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
}
#define regulator_desc_ldo_low(num) { \
.name = "LDO"#num, \
+ .of_match = of_match_ptr("LDO"#num), \
+ .regulators_node = of_match_ptr("voltage-regulators"), \
.id = MAX77686_LDO##num, \
.ops = &max77686_ldo_ops, \
.type = REGULATOR_VOLTAGE, \
@@ -289,6 +335,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
}
#define regulator_desc_ldo1_low(num) { \
.name = "LDO"#num, \
+ .of_match = of_match_ptr("LDO"#num), \
+ .regulators_node = of_match_ptr("voltage-regulators"), \
.id = MAX77686_LDO##num, \
.ops = &max77686_ops, \
.type = REGULATOR_VOLTAGE, \
@@ -305,6 +353,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
}
#define regulator_desc_buck(num) { \
.name = "BUCK"#num, \
+ .of_match = of_match_ptr("BUCK"#num), \
+ .regulators_node = of_match_ptr("voltage-regulators"), \
.id = MAX77686_BUCK##num, \
.ops = &max77686_ops, \
.type = REGULATOR_VOLTAGE, \
@@ -320,6 +370,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
}
#define regulator_desc_buck1(num) { \
.name = "BUCK"#num, \
+ .of_match = of_match_ptr("BUCK"#num), \
+ .regulators_node = of_match_ptr("voltage-regulators"), \
.id = MAX77686_BUCK##num, \
.ops = &max77686_buck1_ops, \
.type = REGULATOR_VOLTAGE, \
@@ -335,6 +387,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
}
#define regulator_desc_buck_dvs(num) { \
.name = "BUCK"#num, \
+ .of_match = of_match_ptr("BUCK"#num), \
+ .regulators_node = of_match_ptr("voltage-regulators"), \
.id = MAX77686_BUCK##num, \
.ops = &max77686_buck_dvs_ops, \
.type = REGULATOR_VOLTAGE, \
@@ -350,7 +404,7 @@ static struct regulator_ops max77686_buck_dvs_ops = {
<< MAX77686_OPMODE_BUCK234_SHIFT, \
}
-static struct regulator_desc regulators[] = {
+static const struct regulator_desc regulators[] = {
regulator_desc_ldo1_low(1),
regulator_desc_ldo_low(2),
regulator_desc_ldo(3),
@@ -388,103 +442,37 @@ static struct regulator_desc regulators[] = {
regulator_desc_buck(9),
};
-#ifdef CONFIG_OF
-static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
- struct max77686_platform_data *pdata)
-{
- struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
- struct device_node *pmic_np, *regulators_np;
- struct max77686_regulator_data *rdata;
- struct of_regulator_match rmatch;
- unsigned int i;
-
- pmic_np = iodev->dev->of_node;
- regulators_np = of_get_child_by_name(pmic_np, "voltage-regulators");
- if (!regulators_np) {
- dev_err(&pdev->dev, "could not find regulators sub-node\n");
- return -EINVAL;
- }
-
- pdata->num_regulators = ARRAY_SIZE(regulators);
- rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
- pdata->num_regulators, GFP_KERNEL);
- if (!rdata) {
- of_node_put(regulators_np);
- return -ENOMEM;
- }
-
- for (i = 0; i < pdata->num_regulators; i++) {
- rmatch.name = regulators[i].name;
- rmatch.init_data = NULL;
- rmatch.of_node = NULL;
- of_regulator_match(&pdev->dev, regulators_np, &rmatch, 1);
- rdata[i].initdata = rmatch.init_data;
- rdata[i].of_node = rmatch.of_node;
- }
-
- pdata->regulators = rdata;
- of_node_put(regulators_np);
-
- return 0;
-}
-#else
-static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
- struct max77686_platform_data *pdata)
-{
- return 0;
-}
-#endif /* CONFIG_OF */
-
static int max77686_pmic_probe(struct platform_device *pdev)
{
struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
- struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
struct max77686_data *max77686;
- int i, ret = 0;
+ int i;
struct regulator_config config = { };
dev_dbg(&pdev->dev, "%s\n", __func__);
- if (!pdata) {
- dev_err(&pdev->dev, "no platform data found for regulator\n");
- return -ENODEV;
- }
-
- if (iodev->dev->of_node) {
- ret = max77686_pmic_dt_parse_pdata(pdev, pdata);
- if (ret)
- return ret;
- }
-
- if (pdata->num_regulators != MAX77686_REGULATORS) {
- dev_err(&pdev->dev,
- "Invalid initial data for regulator's initialiation\n");
- return -EINVAL;
- }
-
max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data),
GFP_KERNEL);
if (!max77686)
return -ENOMEM;
- config.dev = &pdev->dev;
+ config.dev = iodev->dev;
config.regmap = iodev->regmap;
config.driver_data = max77686;
platform_set_drvdata(pdev, max77686);
for (i = 0; i < MAX77686_REGULATORS; i++) {
struct regulator_dev *rdev;
+ int id = regulators[i].id;
- config.init_data = pdata->regulators[i].initdata;
- config.of_node = pdata->regulators[i].of_node;
-
- max77686->opmode[i] = regulators[i].enable_mask;
+ max77686->opmode[id] = MAX77686_NORMAL;
rdev = devm_regulator_register(&pdev->dev,
&regulators[i], &config);
if (IS_ERR(rdev)) {
+ int ret = PTR_ERR(rdev);
dev_err(&pdev->dev,
- "regulator init failed for %d\n", i);
- return PTR_ERR(rdev);
+ "regulator init failed for %d: %d\n", i, ret);
+ return ret;
}
}
diff --git a/drivers/regulator/max77693.c b/drivers/regulator/max77693.c
index c67ff05fc1dd..7b9755a6c3b5 100644
--- a/drivers/regulator/max77693.c
+++ b/drivers/regulator/max77693.c
@@ -139,7 +139,7 @@ static struct regulator_ops max77693_charger_ops = {
.enable_mask = SAFEOUT_CTRL_ENSAFEOUT##_num##_MASK , \
}
-static struct regulator_desc regulators[] = {
+static const struct regulator_desc regulators[] = {
regulator_desc_esafeout(1),
regulator_desc_esafeout(2),
{
@@ -227,7 +227,7 @@ static int max77693_pmic_probe(struct platform_device *pdev)
struct max77693_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct max77693_regulator_data *rdata = NULL;
int num_rdata, i;
- struct regulator_config config;
+ struct regulator_config config = { };
num_rdata = max77693_pmic_init_rdata(&pdev->dev, &rdata);
if (!rdata || num_rdata <= 0) {
diff --git a/drivers/regulator/max77802.c b/drivers/regulator/max77802.c
index d89792b084e9..0766615c60bc 100644
--- a/drivers/regulator/max77802.c
+++ b/drivers/regulator/max77802.c
@@ -33,6 +33,7 @@
#include <linux/regulator/of_regulator.h>
#include <linux/mfd/max77686.h>
#include <linux/mfd/max77686-private.h>
+#include <dt-bindings/regulator/maxim,max77802.h>
/* Default ramp delay in case it is not manually set */
#define MAX77802_RAMP_DELAY 100000 /* uV/us */
@@ -49,6 +50,10 @@
#define MAX77802_RAMP_RATE_MASK_4BIT 0xF0
#define MAX77802_RAMP_RATE_SHIFT_4BIT 4
+#define MAX77802_STATUS_OFF 0x0
+#define MAX77802_OFF_PWRREQ 0x1
+#define MAX77802_LP_PWRREQ 0x2
+
/* MAX77802 has two register formats: 2-bit and 4-bit */
static const unsigned int ramp_table_77802_2bit[] = {
12500,
@@ -65,9 +70,16 @@ static unsigned int ramp_table_77802_4bit[] = {
};
struct max77802_regulator_prv {
+ /* Array indexed by regulator id */
unsigned int opmode[MAX77802_REG_MAX];
};
+static inline unsigned int max77802_map_mode(unsigned int mode)
+{
+ return mode == MAX77802_OPMODE_NORMAL ?
+ REGULATOR_MODE_NORMAL : REGULATOR_MODE_STANDBY;
+}
+
static int max77802_get_opmode_shift(int id)
{
if (id == MAX77802_BUCK1 || (id >= MAX77802_BUCK5 &&
@@ -83,17 +95,16 @@ static int max77802_get_opmode_shift(int id)
return -EINVAL;
}
-/*
- * Some BUCKS supports Normal[ON/OFF] mode during suspend
+/**
+ * max77802_set_suspend_disable - Disable the regulator during system suspend
+ * @rdev: regulator to mark as disabled
*
- * BUCK 1, 6, 2-4, 5, 7-10 (all)
- *
- * The other mode (0x02) will make PWRREQ switch between normal
- * and low power.
+ * All regulators expect LDO 1, 3, 20 and 21 support OFF by PWRREQ.
+ * Configure the regulator so the PMIC will turn it OFF during system suspend.
*/
-static int max77802_buck_set_suspend_disable(struct regulator_dev *rdev)
+static int max77802_set_suspend_disable(struct regulator_dev *rdev)
{
- unsigned int val = MAX77802_OPMODE_STANDBY;
+ unsigned int val = MAX77802_OFF_PWRREQ;
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
int id = rdev_get_id(rdev);
int shift = max77802_get_opmode_shift(id);
@@ -104,14 +115,11 @@ static int max77802_buck_set_suspend_disable(struct regulator_dev *rdev)
}
/*
- * Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state
- * (Enable Control Logic1 by PWRREQ)
- *
- * LDOs 2, 4-19, 22-35.
+ * Some LDOs support Low Power Mode while the system is running.
*
+ * LDOs 1, 3, 20, 21.
*/
-static int max77802_ldo_set_suspend_mode_logic1(struct regulator_dev *rdev,
- unsigned int mode)
+static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
int id = rdev_get_id(rdev);
@@ -119,14 +127,11 @@ static int max77802_ldo_set_suspend_mode_logic1(struct regulator_dev *rdev,
int shift = max77802_get_opmode_shift(id);
switch (mode) {
- case REGULATOR_MODE_IDLE: /* ON in LP Mode */
- val = MAX77802_OPMODE_LP;
+ case REGULATOR_MODE_STANDBY:
+ val = MAX77802_OPMODE_LP; /* ON in Low Power Mode */
break;
- case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */
- val = MAX77802_OPMODE_NORMAL;
- break;
- case REGULATOR_MODE_STANDBY: /* ON/OFF by PWRREQ */
- val = MAX77802_OPMODE_STANDBY;
+ case REGULATOR_MODE_NORMAL:
+ val = MAX77802_OPMODE_NORMAL; /* ON in Normal Mode */
break;
default:
dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n",
@@ -139,35 +144,76 @@ static int max77802_ldo_set_suspend_mode_logic1(struct regulator_dev *rdev,
rdev->desc->enable_mask, val << shift);
}
-/*
- * Mode 1 (Output[ON/OFF] by PWRREQ) is not supported on some LDOs
- * (Enable Control Logic2 by PWRREQ)
+static unsigned max77802_get_mode(struct regulator_dev *rdev)
+{
+ struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+
+ return max77802_map_mode(max77802->opmode[id]);
+}
+
+/**
+ * max77802_set_suspend_mode - set regulator opmode when the system is suspended
+ * @rdev: regulator to change mode
+ * @mode: operating mode to be set
*
- * LDOs 1, 20, 21, and 3,
+ * Will set the operating mode for the regulators during system suspend.
+ * This function is valid for the three different enable control logics:
*
+ * Enable Control Logic1 by PWRREQ (BUCK 2-4 and LDOs 2, 4-19, 22-35)
+ * Enable Control Logic2 by PWRREQ (LDOs 1, 20, 21)
+ * Enable Control Logic3 by PWRREQ (LDO 3)
+ *
+ * If setting the regulator mode fails, the function only warns but does
+ * not return an error code to avoid the regulator core to stop setting
+ * the operating mode for the remaining regulators.
*/
-static int max77802_ldo_set_suspend_mode_logic2(struct regulator_dev *rdev,
- unsigned int mode)
+static int max77802_set_suspend_mode(struct regulator_dev *rdev,
+ unsigned int mode)
{
struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
int id = rdev_get_id(rdev);
unsigned int val;
int shift = max77802_get_opmode_shift(id);
+ /*
+ * If the regulator has been disabled for suspend
+ * then is invalid to try setting a suspend mode.
+ */
+ if (max77802->opmode[id] == MAX77802_OFF_PWRREQ) {
+ dev_warn(&rdev->dev, "%s: is disabled, mode: 0x%x not set\n",
+ rdev->desc->name, mode);
+ return 0;
+ }
+
switch (mode) {
- case REGULATOR_MODE_IDLE: /* ON in LP Mode */
- val = MAX77802_OPMODE_LP;
- break;
- case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */
- val = MAX77802_OPMODE_NORMAL;
+ case REGULATOR_MODE_STANDBY:
+ /*
+ * If the regulator opmode is normal then enable
+ * ON in Low Power Mode by PWRREQ. If the mode is
+ * already Low Power then no action is required.
+ */
+ if (max77802->opmode[id] == MAX77802_OPMODE_NORMAL)
+ val = MAX77802_LP_PWRREQ;
+ else
+ return 0;
break;
+ case REGULATOR_MODE_NORMAL:
+ /*
+ * If the regulator operating mode is Low Power then
+ * normal is not a valid opmode in suspend. If the
+ * mode is already normal then no action is required.
+ */
+ if (max77802->opmode[id] == MAX77802_OPMODE_LP)
+ dev_warn(&rdev->dev, "%s: in Low Power: 0x%x invalid\n",
+ rdev->desc->name, mode);
+ return 0;
default:
dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n",
rdev->desc->name, mode);
return -EINVAL;
}
- max77802->opmode[id] = val;
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, val << shift);
}
@@ -178,6 +224,9 @@ static int max77802_enable(struct regulator_dev *rdev)
int id = rdev_get_id(rdev);
int shift = max77802_get_opmode_shift(id);
+ if (max77802->opmode[id] == MAX77802_OFF_PWRREQ)
+ max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
+
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask,
max77802->opmode[id] << shift);
@@ -247,7 +296,8 @@ static struct regulator_ops max77802_ldo_ops_logic1 = {
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
- .set_suspend_mode = max77802_ldo_set_suspend_mode_logic1,
+ .set_suspend_disable = max77802_set_suspend_disable,
+ .set_suspend_mode = max77802_set_suspend_mode,
};
/*
@@ -262,7 +312,9 @@ static struct regulator_ops max77802_ldo_ops_logic2 = {
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
- .set_suspend_mode = max77802_ldo_set_suspend_mode_logic2,
+ .set_mode = max77802_set_mode,
+ .get_mode = max77802_get_mode,
+ .set_suspend_mode = max77802_set_suspend_mode,
};
/* BUCKS 1, 6 */
@@ -276,10 +328,25 @@ static struct regulator_ops max77802_buck_16_dvs_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_ramp_delay = max77802_set_ramp_delay_4bit,
- .set_suspend_disable = max77802_buck_set_suspend_disable,
+ .set_suspend_disable = max77802_set_suspend_disable,
};
-/* BUCKs 2-4, 5, 7-10 */
+/* BUCKs 2-4 */
+static struct regulator_ops max77802_buck_234_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = max77802_enable,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .set_ramp_delay = max77802_set_ramp_delay_2bit,
+ .set_suspend_disable = max77802_set_suspend_disable,
+ .set_suspend_mode = max77802_set_suspend_mode,
+};
+
+/* BUCKs 5, 7-10 */
static struct regulator_ops max77802_buck_dvs_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
@@ -290,12 +357,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_ramp_delay = max77802_set_ramp_delay_2bit,
- .set_suspend_disable = max77802_buck_set_suspend_disable,
+ .set_suspend_disable = max77802_set_suspend_disable,
};
/* LDOs 3-7, 9-14, 18-26, 28, 29, 32-34 */
#define regulator_77802_desc_p_ldo(num, supply, log) { \
.name = "LDO"#num, \
+ .of_match = of_match_ptr("LDO"#num), \
+ .regulators_node = of_match_ptr("regulators"), \
.id = MAX77802_LDO##num, \
.supply_name = "inl"#supply, \
.ops = &max77802_ldo_ops_logic##log, \
@@ -309,11 +378,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
.vsel_mask = MAX77802_VSEL_MASK, \
.enable_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \
.enable_mask = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \
+ .of_map_mode = max77802_map_mode, \
}
/* LDOs 1, 2, 8, 15, 17, 27, 30, 35 */
#define regulator_77802_desc_n_ldo(num, supply, log) { \
.name = "LDO"#num, \
+ .of_match = of_match_ptr("LDO"#num), \
+ .regulators_node = of_match_ptr("regulators"), \
.id = MAX77802_LDO##num, \
.supply_name = "inl"#supply, \
.ops = &max77802_ldo_ops_logic##log, \
@@ -327,11 +399,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
.vsel_mask = MAX77802_VSEL_MASK, \
.enable_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \
.enable_mask = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \
+ .of_map_mode = max77802_map_mode, \
}
/* BUCKs 1, 6 */
#define regulator_77802_desc_16_buck(num) { \
.name = "BUCK"#num, \
+ .of_match = of_match_ptr("BUCK"#num), \
+ .regulators_node = of_match_ptr("regulators"), \
.id = MAX77802_BUCK##num, \
.supply_name = "inb"#num, \
.ops = &max77802_buck_16_dvs_ops, \
@@ -345,14 +420,17 @@ static struct regulator_ops max77802_buck_dvs_ops = {
.vsel_mask = MAX77802_DVS_VSEL_MASK, \
.enable_reg = MAX77802_REG_BUCK ## num ## CTRL, \
.enable_mask = MAX77802_OPMODE_MASK, \
+ .of_map_mode = max77802_map_mode, \
}
/* BUCKS 2-4 */
#define regulator_77802_desc_234_buck(num) { \
.name = "BUCK"#num, \
+ .of_match = of_match_ptr("BUCK"#num), \
+ .regulators_node = of_match_ptr("regulators"), \
.id = MAX77802_BUCK##num, \
.supply_name = "inb"#num, \
- .ops = &max77802_buck_dvs_ops, \
+ .ops = &max77802_buck_234_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.min_uV = 600000, \
@@ -364,11 +442,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
.enable_reg = MAX77802_REG_BUCK ## num ## CTRL1, \
.enable_mask = MAX77802_OPMODE_MASK << \
MAX77802_OPMODE_BUCK234_SHIFT, \
+ .of_map_mode = max77802_map_mode, \
}
/* BUCK 5 */
#define regulator_77802_desc_buck5(num) { \
.name = "BUCK"#num, \
+ .of_match = of_match_ptr("BUCK"#num), \
+ .regulators_node = of_match_ptr("regulators"), \
.id = MAX77802_BUCK##num, \
.supply_name = "inb"#num, \
.ops = &max77802_buck_dvs_ops, \
@@ -382,11 +463,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
.vsel_mask = MAX77802_VSEL_MASK, \
.enable_reg = MAX77802_REG_BUCK5CTRL, \
.enable_mask = MAX77802_OPMODE_MASK, \
+ .of_map_mode = max77802_map_mode, \
}
/* BUCKs 7-10 */
#define regulator_77802_desc_buck7_10(num) { \
.name = "BUCK"#num, \
+ .of_match = of_match_ptr("BUCK"#num), \
+ .regulators_node = of_match_ptr("regulators"), \
.id = MAX77802_BUCK##num, \
.supply_name = "inb"#num, \
.ops = &max77802_buck_dvs_ops, \
@@ -400,9 +484,10 @@ static struct regulator_ops max77802_buck_dvs_ops = {
.vsel_mask = MAX77802_VSEL_MASK, \
.enable_reg = MAX77802_REG_BUCK7CTRL + (num - 7) * 3, \
.enable_mask = MAX77802_OPMODE_MASK, \
+ .of_map_mode = max77802_map_mode, \
}
-static struct regulator_desc regulators[] = {
+static const struct regulator_desc regulators[] = {
regulator_77802_desc_16_buck(1),
regulator_77802_desc_234_buck(2),
regulator_77802_desc_234_buck(3),
@@ -447,85 +532,19 @@ static struct regulator_desc regulators[] = {
regulator_77802_desc_n_ldo(35, 2, 1),
};
-#ifdef CONFIG_OF
-static int max77802_pmic_dt_parse_pdata(struct platform_device *pdev,
- struct max77686_platform_data *pdata)
-{
- struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
- struct device_node *pmic_np, *regulators_np;
- struct max77686_regulator_data *rdata;
- struct of_regulator_match rmatch;
- unsigned int i;
-
- pmic_np = iodev->dev->of_node;
- regulators_np = of_get_child_by_name(pmic_np, "regulators");
- if (!regulators_np) {
- dev_err(&pdev->dev, "could not find regulators sub-node\n");
- return -EINVAL;
- }
-
- pdata->num_regulators = ARRAY_SIZE(regulators);
- rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
- pdata->num_regulators, GFP_KERNEL);
- if (!rdata) {
- of_node_put(regulators_np);
- return -ENOMEM;
- }
-
- for (i = 0; i < pdata->num_regulators; i++) {
- rmatch.name = regulators[i].name;
- rmatch.init_data = NULL;
- rmatch.of_node = NULL;
- if (of_regulator_match(&pdev->dev, regulators_np, &rmatch,
- 1) != 1) {
- dev_warn(&pdev->dev, "No matching regulator for '%s'\n",
- rmatch.name);
- continue;
- }
- rdata[i].initdata = rmatch.init_data;
- rdata[i].of_node = rmatch.of_node;
- rdata[i].id = regulators[i].id;
- }
-
- pdata->regulators = rdata;
- of_node_put(regulators_np);
-
- return 0;
-}
-#else
-static int max77802_pmic_dt_parse_pdata(struct platform_device *pdev,
- struct max77686_platform_data *pdata)
-{
- return 0;
-}
-#endif /* CONFIG_OF */
-
static int max77802_pmic_probe(struct platform_device *pdev)
{
struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
- struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
struct max77802_regulator_prv *max77802;
- int i, ret = 0, val;
+ int i, val;
struct regulator_config config = { };
- /* This is allocated by the MFD driver */
- if (!pdata) {
- dev_err(&pdev->dev, "no platform data found for regulator\n");
- return -ENODEV;
- }
-
max77802 = devm_kzalloc(&pdev->dev,
sizeof(struct max77802_regulator_prv),
GFP_KERNEL);
if (!max77802)
return -ENOMEM;
- if (iodev->dev->of_node) {
- ret = max77802_pmic_dt_parse_pdata(pdev, pdata);
- if (ret)
- return ret;
- }
-
config.dev = iodev->dev;
config.regmap = iodev->regmap;
config.driver_data = max77802;
@@ -533,21 +552,25 @@ static int max77802_pmic_probe(struct platform_device *pdev)
for (i = 0; i < MAX77802_REG_MAX; i++) {
struct regulator_dev *rdev;
- int id = pdata->regulators[i].id;
+ int id = regulators[i].id;
int shift = max77802_get_opmode_shift(id);
-
- config.init_data = pdata->regulators[i].initdata;
- config.of_node = pdata->regulators[i].of_node;
+ int ret;
ret = regmap_read(iodev->regmap, regulators[i].enable_reg, &val);
- val = val >> shift & MAX77802_OPMODE_MASK;
+ if (ret < 0) {
+ dev_warn(&pdev->dev,
+ "cannot read current mode for %d\n", i);
+ val = MAX77802_OPMODE_NORMAL;
+ } else {
+ val = val >> shift & MAX77802_OPMODE_MASK;
+ }
/*
* If the regulator is disabled and the system warm rebooted,
* the hardware reports OFF as the regulator operating mode.
* Default to operating mode NORMAL in that case.
*/
- if (val == MAX77802_OPMODE_OFF)
+ if (val == MAX77802_STATUS_OFF)
max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
else
max77802->opmode[id] = val;
@@ -555,9 +578,10 @@ static int max77802_pmic_probe(struct platform_device *pdev)
rdev = devm_regulator_register(&pdev->dev,
&regulators[i], &config);
if (IS_ERR(rdev)) {
+ ret = PTR_ERR(rdev);
dev_err(&pdev->dev,
- "regulator init failed for %d\n", i);
- return PTR_ERR(rdev);
+ "regulator init failed for %d: %d\n", i, ret);
+ return ret;
}
}
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
index 2fc411188794..7eee2ca18541 100644
--- a/drivers/regulator/max8660.c
+++ b/drivers/regulator/max8660.c
@@ -335,7 +335,7 @@ static int max8660_pdata_from_dt(struct device *dev,
int matched, i;
struct device_node *np;
struct max8660_subdev_data *sub;
- struct of_regulator_match rmatch[ARRAY_SIZE(max8660_reg)];
+ struct of_regulator_match rmatch[ARRAY_SIZE(max8660_reg)] = { };
np = of_get_child_by_name(dev->of_node, "regulators");
if (!np) {
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c
index f7f9efcfedb7..1af8f4a2ab86 100644
--- a/drivers/regulator/max8952.c
+++ b/drivers/regulator/max8952.c
@@ -174,7 +174,7 @@ static struct max8952_platform_data *max8952_parse_dt(struct device *dev)
if (of_property_read_u32(np, "max8952,ramp-speed", &pd->ramp_speed))
dev_warn(dev, "max8952,ramp-speed property not specified, defaulting to 32mV/us\n");
- pd->reg_data = of_get_regulator_init_data(dev, np);
+ pd->reg_data = of_get_regulator_init_data(dev, np, &regulator);
if (!pd->reg_data) {
dev_err(dev, "Failed to parse regulator init data\n");
return NULL;
@@ -225,6 +225,8 @@ static int max8952_pmic_probe(struct i2c_client *client,
config.of_node = client->dev.of_node;
config.ena_gpio = pdata->gpio_en;
+ if (client->dev.of_node)
+ config.ena_gpio_initialized = true;
if (pdata->reg_data->constraints.boot_on)
config.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c
index dbedf1768db0..c3d55c2db593 100644
--- a/drivers/regulator/max8973-regulator.c
+++ b/drivers/regulator/max8973-regulator.c
@@ -458,7 +458,8 @@ static int max8973_probe(struct i2c_client *client,
config.dev = &client->dev;
config.init_data = pdata ? pdata->reg_init_data :
- of_get_regulator_init_data(&client->dev, client->dev.of_node);
+ of_get_regulator_init_data(&client->dev, client->dev.of_node,
+ &max->desc);
config.driver_data = max;
config.of_node = client->dev.of_node;
config.regmap = max->regmap;
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
index 9c31e215a521..726fde1d883e 100644
--- a/drivers/regulator/max8997.c
+++ b/drivers/regulator/max8997.c
@@ -953,7 +953,8 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
rdata->id = i;
rdata->initdata = of_get_regulator_init_data(&pdev->dev,
- reg_np);
+ reg_np,
+ &regulators[i]);
rdata->reg_node = reg_np;
rdata++;
}
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c
index 961091b46557..59e34a05a4a2 100644
--- a/drivers/regulator/max8998.c
+++ b/drivers/regulator/max8998.c
@@ -686,8 +686,9 @@ static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev,
continue;
rdata->id = regulators[i].id;
- rdata->initdata = of_get_regulator_init_data(
- iodev->dev, reg_np);
+ rdata->initdata = of_get_regulator_init_data(iodev->dev,
+ reg_np,
+ &regulators[i]);
rdata->reg_node = reg_np;
++rdata;
}
diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c
index afba024953e1..0281c31ae2ed 100644
--- a/drivers/regulator/mc13xxx-regulator-core.c
+++ b/drivers/regulator/mc13xxx-regulator-core.c
@@ -194,7 +194,8 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
regulators[i].desc.name)) {
p->id = i;
p->init_data = of_get_regulator_init_data(
- &pdev->dev, child);
+ &pdev->dev, child,
+ &regulators[i].desc);
p->node = child;
p++;
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 7a51814abdc5..91eaaf010524 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -19,12 +19,20 @@
#include "internal.h"
+static const char *const regulator_states[PM_SUSPEND_MAX + 1] = {
+ [PM_SUSPEND_MEM] = "regulator-state-mem",
+ [PM_SUSPEND_MAX] = "regulator-state-disk",
+};
+
static void of_get_regulation_constraints(struct device_node *np,
- struct regulator_init_data **init_data)
+ struct regulator_init_data **init_data,
+ const struct regulator_desc *desc)
{
const __be32 *min_uV, *max_uV;
struct regulation_constraints *constraints = &(*init_data)->constraints;
- int ret;
+ struct regulator_state *suspend_state;
+ struct device_node *suspend_np;
+ int ret, i;
u32 pval;
constraints->name = of_get_property(np, "regulator-name", NULL);
@@ -73,18 +81,84 @@ static void of_get_regulation_constraints(struct device_node *np,
ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval);
if (!ret)
constraints->enable_time = pval;
+
+ if (!of_property_read_u32(np, "regulator-initial-mode", &pval)) {
+ if (desc && desc->of_map_mode) {
+ ret = desc->of_map_mode(pval);
+ if (ret == -EINVAL)
+ pr_err("%s: invalid mode %u\n", np->name, pval);
+ else
+ constraints->initial_mode = ret;
+ } else {
+ pr_warn("%s: mapping for mode %d not defined\n",
+ np->name, pval);
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(regulator_states); i++) {
+ switch (i) {
+ case PM_SUSPEND_MEM:
+ suspend_state = &constraints->state_mem;
+ break;
+ case PM_SUSPEND_MAX:
+ suspend_state = &constraints->state_disk;
+ break;
+ case PM_SUSPEND_ON:
+ case PM_SUSPEND_FREEZE:
+ case PM_SUSPEND_STANDBY:
+ default:
+ continue;
+ };
+
+ suspend_np = of_get_child_by_name(np, regulator_states[i]);
+ if (!suspend_np || !suspend_state)
+ continue;
+
+ if (!of_property_read_u32(suspend_np, "regulator-mode",
+ &pval)) {
+ if (desc && desc->of_map_mode) {
+ ret = desc->of_map_mode(pval);
+ if (ret == -EINVAL)
+ pr_err("%s: invalid mode %u\n",
+ np->name, pval);
+ else
+ suspend_state->mode = ret;
+ } else {
+ pr_warn("%s: mapping for mode %d not defined\n",
+ np->name, pval);
+ }
+ }
+
+ if (of_property_read_bool(suspend_np,
+ "regulator-on-in-suspend"))
+ suspend_state->enabled = true;
+ else if (of_property_read_bool(suspend_np,
+ "regulator-off-in-suspend"))
+ suspend_state->disabled = true;
+
+ if (!of_property_read_u32(suspend_np,
+ "regulator-suspend-microvolt", &pval))
+ suspend_state->uV = pval;
+
+ of_node_put(suspend_np);
+ suspend_state = NULL;
+ suspend_np = NULL;
+ }
}
/**
* of_get_regulator_init_data - extract regulator_init_data structure info
* @dev: device requesting for regulator_init_data
+ * @node: regulator device node
+ * @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
* alloc fails.
*/
struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
- struct device_node *node)
+ struct device_node *node,
+ const struct regulator_desc *desc)
{
struct regulator_init_data *init_data;
@@ -95,7 +169,7 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
if (!init_data)
return NULL; /* Out of memory? */
- of_get_regulation_constraints(node, &init_data);
+ of_get_regulation_constraints(node, &init_data, desc);
return init_data;
}
EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
@@ -176,7 +250,8 @@ int of_regulator_match(struct device *dev, struct device_node *node,
continue;
match->init_data =
- of_get_regulator_init_data(dev, child);
+ of_get_regulator_init_data(dev, child,
+ match->desc);
if (!match->init_data) {
dev_err(dev,
"failed to parse DT for regulator %s\n",
@@ -211,7 +286,8 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
search = dev->of_node;
if (!search) {
- dev_err(dev, "Failed to find regulator container node\n");
+ dev_dbg(dev, "Failed to find regulator container node '%s'\n",
+ desc->regulators_node);
return NULL;
}
@@ -223,7 +299,7 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
if (strcmp(desc->of_match, name))
continue;
- init_data = of_get_regulator_init_data(dev, child);
+ init_data = of_get_regulator_init_data(dev, child, desc);
if (!init_data) {
dev_err(dev,
"failed to parse DT for regulator %s\n",
diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c
index d3f55eaea058..91f34ca3a9ac 100644
--- a/drivers/regulator/pwm-regulator.c
+++ b/drivers/regulator/pwm-regulator.c
@@ -149,7 +149,8 @@ static int pwm_regulator_probe(struct platform_device *pdev)
return ret;
}
- config.init_data = of_get_regulator_init_data(&pdev->dev, np);
+ config.init_data = of_get_regulator_init_data(&pdev->dev, np,
+ &drvdata->desc);
if (!config.init_data)
return -ENOMEM;
diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c
index b55cd5b50ebe..183598b111f9 100644
--- a/drivers/regulator/qcom_rpm-regulator.c
+++ b/drivers/regulator/qcom_rpm-regulator.c
@@ -183,6 +183,13 @@ static const struct regulator_linear_range ftsmps_ranges[] = {
REGULATOR_LINEAR_RANGE(1500000, 64, 100, 50000),
};
+static const struct regulator_linear_range smb208_ranges[] = {
+ REGULATOR_LINEAR_RANGE( 375000, 0, 29, 12500),
+ REGULATOR_LINEAR_RANGE( 750000, 30, 89, 12500),
+ REGULATOR_LINEAR_RANGE(1500000, 90, 153, 25000),
+ REGULATOR_LINEAR_RANGE(3100000, 154, 234, 25000),
+};
+
static const struct regulator_linear_range ncp_ranges[] = {
REGULATOR_LINEAR_RANGE(1500000, 0, 31, 50000),
};
@@ -559,6 +566,16 @@ static const struct qcom_rpm_reg pm8921_switch = {
.parts = &rpm8960_switch_parts,
};
+static const struct qcom_rpm_reg smb208_smps = {
+ .desc.linear_ranges = smb208_ranges,
+ .desc.n_linear_ranges = ARRAY_SIZE(smb208_ranges),
+ .desc.n_voltages = 235,
+ .desc.ops = &uV_ops,
+ .parts = &rpm8960_smps_parts,
+ .supports_force_mode_auto = false,
+ .supports_force_mode_bypass = false,
+};
+
static const struct of_device_id rpm_of_match[] = {
{ .compatible = "qcom,rpm-pm8058-pldo", .data = &pm8058_pldo },
{ .compatible = "qcom,rpm-pm8058-nldo", .data = &pm8058_nldo },
@@ -578,6 +595,8 @@ static const struct of_device_id rpm_of_match[] = {
{ .compatible = "qcom,rpm-pm8921-ftsmps", .data = &pm8921_ftsmps },
{ .compatible = "qcom,rpm-pm8921-ncp", .data = &pm8921_ncp },
{ .compatible = "qcom,rpm-pm8921-switch", .data = &pm8921_switch },
+
+ { .compatible = "qcom,rpm-smb208", .data = &smb208_smps },
{ }
};
MODULE_DEVICE_TABLE(of, rpm_of_match);
@@ -643,10 +662,6 @@ static int rpm_reg_probe(struct platform_device *pdev)
match = of_match_device(rpm_of_match, &pdev->dev);
template = match->data;
- initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
- if (!initdata)
- return -EINVAL;
-
vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
if (!vreg) {
dev_err(&pdev->dev, "failed to allocate vreg\n");
@@ -666,6 +681,11 @@ static int rpm_reg_probe(struct platform_device *pdev)
return -ENODEV;
}
+ initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
+ &vreg->desc);
+ if (!initdata)
+ return -EINVAL;
+
key = "reg";
ret = of_property_read_u32(pdev->dev.of_node, key, &val);
if (ret) {
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index 196a5c8838c4..ea9d05eabd0a 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -36,6 +36,12 @@
#define RK808_RAMP_RATE_6MV_PER_US (2 << RK808_RAMP_RATE_OFFSET)
#define RK808_RAMP_RATE_10MV_PER_US (3 << RK808_RAMP_RATE_OFFSET)
+/* Offset from XXX_ON_VSEL to XXX_SLP_VSEL */
+#define RK808_SLP_REG_OFFSET 1
+
+/* Offset from XXX_EN_REG to SLEEP_SET_OFF_XXX */
+#define RK808_SLP_SET_OFF_REG_OFFSET 2
+
static const int rk808_buck_config_regs[] = {
RK808_BUCK1_CONFIG_REG,
RK808_BUCK2_CONFIG_REG,
@@ -91,6 +97,43 @@ static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
RK808_RAMP_RATE_MASK, ramp_value);
}
+int rk808_set_suspend_voltage(struct regulator_dev *rdev, int uv)
+{
+ unsigned int reg;
+ int sel = regulator_map_voltage_linear_range(rdev, uv, uv);
+
+ if (sel < 0)
+ return -EINVAL;
+
+ reg = rdev->desc->vsel_reg + RK808_SLP_REG_OFFSET;
+
+ return regmap_update_bits(rdev->regmap, reg,
+ rdev->desc->vsel_mask,
+ sel);
+}
+
+int rk808_set_suspend_enable(struct regulator_dev *rdev)
+{
+ unsigned int reg;
+
+ reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET;
+
+ return regmap_update_bits(rdev->regmap, reg,
+ rdev->desc->enable_mask,
+ 0);
+}
+
+int rk808_set_suspend_disable(struct regulator_dev *rdev)
+{
+ unsigned int reg;
+
+ reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET;
+
+ return regmap_update_bits(rdev->regmap, reg,
+ rdev->desc->enable_mask,
+ rdev->desc->enable_mask);
+}
+
static struct regulator_ops rk808_buck1_2_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
@@ -100,6 +143,9 @@ static struct regulator_ops rk808_buck1_2_ops = {
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.set_ramp_delay = rk808_set_ramp_delay,
+ .set_suspend_voltage = rk808_set_suspend_voltage,
+ .set_suspend_enable = rk808_set_suspend_enable,
+ .set_suspend_disable = rk808_set_suspend_disable,
};
static struct regulator_ops rk808_reg_ops = {
@@ -110,12 +156,17 @@ static struct regulator_ops rk808_reg_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
+ .set_suspend_voltage = rk808_set_suspend_voltage,
+ .set_suspend_enable = rk808_set_suspend_enable,
+ .set_suspend_disable = rk808_set_suspend_disable,
};
static struct regulator_ops rk808_switch_ops = {
- .enable = regulator_enable_regmap,
- .disable = regulator_disable_regmap,
- .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .set_suspend_enable = rk808_set_suspend_enable,
+ .set_suspend_disable = rk808_set_suspend_disable,
};
static const struct regulator_desc rk808_reg[] = {
diff --git a/drivers/regulator/rn5t618-regulator.c b/drivers/regulator/rn5t618-regulator.c
index e58d79aeb393..b85ceb8ff911 100644
--- a/drivers/regulator/rn5t618-regulator.c
+++ b/drivers/regulator/rn5t618-regulator.c
@@ -31,6 +31,8 @@ static struct regulator_ops rn5t618_reg_ops = {
#define REG(rid, ereg, emask, vreg, vmask, min, max, step) \
[RN5T618_##rid] = { \
.name = #rid, \
+ .of_match = of_match_ptr(#rid), \
+ .regulators_node = of_match_ptr("regulators"), \
.id = RN5T618_##rid, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
@@ -60,60 +62,15 @@ static struct regulator_desc rn5t618_regulators[] = {
REG(LDORTC2, LDOEN2, BIT(5), LDORTC2DAC, 0x7f, 900000, 3500000, 25000),
};
-static struct of_regulator_match rn5t618_matches[] = {
- [RN5T618_DCDC1] = { .name = "DCDC1" },
- [RN5T618_DCDC2] = { .name = "DCDC2" },
- [RN5T618_DCDC3] = { .name = "DCDC3" },
- [RN5T618_LDO1] = { .name = "LDO1" },
- [RN5T618_LDO2] = { .name = "LDO2" },
- [RN5T618_LDO3] = { .name = "LDO3" },
- [RN5T618_LDO4] = { .name = "LDO4" },
- [RN5T618_LDO5] = { .name = "LDO5" },
- [RN5T618_LDORTC1] = { .name = "LDORTC1" },
- [RN5T618_LDORTC2] = { .name = "LDORTC2" },
-};
-
-static int rn5t618_regulator_parse_dt(struct platform_device *pdev)
-{
- struct device_node *np, *regulators;
- int ret;
-
- np = of_node_get(pdev->dev.parent->of_node);
- if (!np)
- return 0;
-
- regulators = of_get_child_by_name(np, "regulators");
- if (!regulators) {
- dev_err(&pdev->dev, "regulators node not found\n");
- return -EINVAL;
- }
-
- ret = of_regulator_match(&pdev->dev, regulators, rn5t618_matches,
- ARRAY_SIZE(rn5t618_matches));
- of_node_put(regulators);
- if (ret < 0) {
- dev_err(&pdev->dev, "error parsing regulator init data: %d\n",
- ret);
- }
-
- return 0;
-}
-
static int rn5t618_regulator_probe(struct platform_device *pdev)
{
struct rn5t618 *rn5t618 = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = { };
struct regulator_dev *rdev;
- int ret, i;
-
- ret = rn5t618_regulator_parse_dt(pdev);
- if (ret)
- return ret;
+ int i;
for (i = 0; i < RN5T618_REG_NUM; i++) {
- config.dev = &pdev->dev;
- config.init_data = rn5t618_matches[i].init_data;
- config.of_node = rn5t618_matches[i].of_node;
+ config.dev = pdev->dev.parent;
config.regmap = rn5t618->regmap;
rdev = devm_regulator_register(&pdev->dev,
diff --git a/drivers/regulator/rt5033-regulator.c b/drivers/regulator/rt5033-regulator.c
new file mode 100644
index 000000000000..870cc49438db
--- /dev/null
+++ b/drivers/regulator/rt5033-regulator.c
@@ -0,0 +1,123 @@
+/*
+ * Regulator driver for the Richtek RT5033
+ *
+ * Copyright (C) 2014 Samsung Electronics, Co., Ltd.
+ * Author: Beomho Seo <beomho.seo@samsung.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 bythe Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/mfd/rt5033.h>
+#include <linux/mfd/rt5033-private.h>
+#include <linux/regulator/of_regulator.h>
+
+static 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 = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+static const struct regulator_desc rt5033_supported_regulators[] = {
+ [RT5033_BUCK] = {
+ .name = "BUCK",
+ .id = RT5033_BUCK,
+ .ops = &rt5033_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .n_voltages = RT5033_REGULATOR_BUCK_VOLTAGE_STEP_NUM,
+ .min_uV = RT5033_REGULATOR_BUCK_VOLTAGE_MIN,
+ .uV_step = RT5033_REGULATOR_BUCK_VOLTAGE_STEP,
+ .enable_reg = RT5033_REG_CTRL,
+ .enable_mask = RT5033_CTRL_EN_BUCK_MASK,
+ .vsel_reg = RT5033_REG_BUCK_CTRL,
+ .vsel_mask = RT5033_BUCK_CTRL_MASK,
+ },
+ [RT5033_LDO] = {
+ .name = "LDO",
+ .id = RT5033_LDO,
+ .ops = &rt5033_buck_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .n_voltages = RT5033_REGULATOR_LDO_VOLTAGE_STEP_NUM,
+ .min_uV = RT5033_REGULATOR_LDO_VOLTAGE_MIN,
+ .uV_step = RT5033_REGULATOR_LDO_VOLTAGE_STEP,
+ .enable_reg = RT5033_REG_CTRL,
+ .enable_mask = RT5033_CTRL_EN_LDO_MASK,
+ .vsel_reg = RT5033_REG_LDO_CTRL,
+ .vsel_mask = RT5033_LDO_CTRL_MASK,
+ },
+ [RT5033_SAFE_LDO] = {
+ .name = "SAFE_LDO",
+ .id = RT5033_SAFE_LDO,
+ .ops = &rt5033_safe_ldo_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ .min_uV = RT5033_REGULATOR_SAFE_LDO_VOLTAGE,
+ .enable_reg = RT5033_REG_CTRL,
+ .enable_mask = RT5033_CTRL_EN_SAFE_LDO_MASK,
+ },
+};
+
+static int rt5033_regulator_probe(struct platform_device *pdev)
+{
+ struct rt5033_dev *rt5033 = dev_get_drvdata(pdev->dev.parent);
+ int ret, i;
+ struct regulator_config config = {};
+
+ config.dev = &pdev->dev;
+ config.driver_data = rt5033;
+
+ for (i = 0; i < ARRAY_SIZE(rt5033_supported_regulators); i++) {
+ struct regulator_dev *regulator;
+
+ config.regmap = rt5033->regmap;
+
+ regulator = devm_regulator_register(&pdev->dev,
+ &rt5033_supported_regulators[i], &config);
+ if (IS_ERR(regulator)) {
+ ret = PTR_ERR(regulator);
+ dev_err(&pdev->dev,
+ "Regulator init failed %d: with error: %d\n",
+ i, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static const struct platform_device_id rt5033_regulator_id[] = {
+ { "rt5033-regulator", },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, rt5033_regulator_id);
+
+static struct platform_driver rt5033_regulator_driver = {
+ .driver = {
+ .name = "rt5033-regulator",
+ },
+ .probe = rt5033_regulator_probe,
+ .id_table = rt5033_regulator_id,
+};
+module_platform_driver(rt5033_regulator_driver);
+
+MODULE_DESCRIPTION("Richtek RT5033 Regulator driver");
+MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/s2mpa01.c b/drivers/regulator/s2mpa01.c
index 4acefa6b462e..5db4e12a7e04 100644
--- a/drivers/regulator/s2mpa01.c
+++ b/drivers/regulator/s2mpa01.c
@@ -298,7 +298,7 @@ static struct regulator_ops s2mpa01_buck_ops = {
.enable_mask = S2MPA01_ENABLE_MASK \
}
-static struct regulator_desc regulators[] = {
+static const struct regulator_desc regulators[] = {
regulator_desc_ldo(1, STEP_25_MV),
regulator_desc_ldo(2, STEP_50_MV),
regulator_desc_ldo(3, STEP_50_MV),
@@ -341,7 +341,7 @@ static int s2mpa01_pmic_probe(struct platform_device *pdev)
{
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
- struct of_regulator_match rdata[S2MPA01_REGULATOR_MAX];
+ struct of_regulator_match rdata[S2MPA01_REGULATOR_MAX] = { };
struct device_node *reg_np = NULL;
struct regulator_config config = { };
struct s2mpa01_info *s2mpa01;
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index adab82d5279f..b345cf51225a 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -30,6 +30,7 @@
#include <linux/of_gpio.h>
#include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/s2mps11.h>
+#include <linux/mfd/samsung/s2mps13.h>
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s2mpu02.h>
@@ -45,10 +46,10 @@ struct s2mps11_info {
enum sec_device_type dev_type;
/*
- * One bit for each S2MPS14/S2MPU02 regulator whether the suspend mode
- * was enabled.
+ * One bit for each S2MPS13/S2MPS14/S2MPU02 regulator whether
+ * the suspend mode was enabled.
*/
- unsigned long long s2mps14_suspend_state:35;
+ unsigned long long s2mps14_suspend_state:50;
/* Array of size rdev_num with GPIO-s for external sleep control */
int *ext_control_gpio;
@@ -369,12 +370,101 @@ static const struct regulator_desc s2mps11_regulators[] = {
regulator_desc_s2mps11_buck6_10(10, MIN_750_MV, STEP_12_5_MV),
};
+static struct regulator_ops s2mps14_reg_ops;
+
+#define regulator_desc_s2mps13_ldo(num, min, step, min_sel) { \
+ .name = "LDO"#num, \
+ .id = S2MPS13_LDO##num, \
+ .ops = &s2mps14_reg_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = min, \
+ .uV_step = step, \
+ .linear_min_sel = min_sel, \
+ .n_voltages = S2MPS14_LDO_N_VOLTAGES, \
+ .vsel_reg = S2MPS13_REG_L1CTRL + num - 1, \
+ .vsel_mask = S2MPS14_LDO_VSEL_MASK, \
+ .enable_reg = S2MPS13_REG_L1CTRL + num - 1, \
+ .enable_mask = S2MPS14_ENABLE_MASK \
+}
+
+#define regulator_desc_s2mps13_buck(num, min, step, min_sel) { \
+ .name = "BUCK"#num, \
+ .id = S2MPS13_BUCK##num, \
+ .ops = &s2mps14_reg_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = min, \
+ .uV_step = step, \
+ .linear_min_sel = min_sel, \
+ .n_voltages = S2MPS14_BUCK_N_VOLTAGES, \
+ .ramp_delay = S2MPS13_BUCK_RAMP_DELAY, \
+ .vsel_reg = S2MPS13_REG_B1OUT + (num - 1) * 2, \
+ .vsel_mask = S2MPS14_BUCK_VSEL_MASK, \
+ .enable_reg = S2MPS13_REG_B1CTRL + (num - 1) * 2, \
+ .enable_mask = S2MPS14_ENABLE_MASK \
+}
+
+static const struct regulator_desc s2mps13_regulators[] = {
+ regulator_desc_s2mps13_ldo(1, MIN_800_MV, STEP_12_5_MV, 0x00),
+ regulator_desc_s2mps13_ldo(2, MIN_1400_MV, STEP_50_MV, 0x0C),
+ regulator_desc_s2mps13_ldo(3, MIN_1000_MV, STEP_25_MV, 0x08),
+ regulator_desc_s2mps13_ldo(4, MIN_800_MV, STEP_12_5_MV, 0x00),
+ regulator_desc_s2mps13_ldo(5, MIN_800_MV, STEP_12_5_MV, 0x00),
+ regulator_desc_s2mps13_ldo(6, MIN_800_MV, STEP_12_5_MV, 0x00),
+ regulator_desc_s2mps13_ldo(7, MIN_1000_MV, STEP_25_MV, 0x08),
+ regulator_desc_s2mps13_ldo(8, MIN_1000_MV, STEP_25_MV, 0x08),
+ regulator_desc_s2mps13_ldo(9, MIN_1000_MV, STEP_25_MV, 0x08),
+ regulator_desc_s2mps13_ldo(10, MIN_1400_MV, STEP_50_MV, 0x0C),
+ regulator_desc_s2mps13_ldo(11, MIN_800_MV, STEP_25_MV, 0x10),
+ regulator_desc_s2mps13_ldo(12, MIN_800_MV, STEP_25_MV, 0x10),
+ regulator_desc_s2mps13_ldo(13, MIN_800_MV, STEP_25_MV, 0x10),
+ regulator_desc_s2mps13_ldo(14, MIN_800_MV, STEP_12_5_MV, 0x00),
+ regulator_desc_s2mps13_ldo(15, MIN_800_MV, STEP_12_5_MV, 0x00),
+ regulator_desc_s2mps13_ldo(16, MIN_1400_MV, STEP_50_MV, 0x0C),
+ regulator_desc_s2mps13_ldo(17, MIN_1400_MV, STEP_50_MV, 0x0C),
+ regulator_desc_s2mps13_ldo(18, MIN_1000_MV, STEP_25_MV, 0x08),
+ regulator_desc_s2mps13_ldo(19, MIN_1000_MV, STEP_25_MV, 0x08),
+ regulator_desc_s2mps13_ldo(20, MIN_1400_MV, STEP_50_MV, 0x0C),
+ regulator_desc_s2mps13_ldo(21, MIN_1000_MV, STEP_25_MV, 0x08),
+ regulator_desc_s2mps13_ldo(22, MIN_1000_MV, STEP_25_MV, 0x08),
+ regulator_desc_s2mps13_ldo(23, MIN_800_MV, STEP_12_5_MV, 0x00),
+ regulator_desc_s2mps13_ldo(24, MIN_800_MV, STEP_12_5_MV, 0x00),
+ regulator_desc_s2mps13_ldo(25, MIN_1400_MV, STEP_50_MV, 0x0C),
+ regulator_desc_s2mps13_ldo(26, MIN_1400_MV, STEP_50_MV, 0x0C),
+ regulator_desc_s2mps13_ldo(27, MIN_1400_MV, STEP_50_MV, 0x0C),
+ regulator_desc_s2mps13_ldo(28, MIN_1000_MV, STEP_25_MV, 0x08),
+ regulator_desc_s2mps13_ldo(29, MIN_1400_MV, STEP_50_MV, 0x0C),
+ regulator_desc_s2mps13_ldo(30, MIN_1400_MV, STEP_50_MV, 0x0C),
+ regulator_desc_s2mps13_ldo(31, MIN_1000_MV, STEP_25_MV, 0x08),
+ regulator_desc_s2mps13_ldo(32, MIN_1000_MV, STEP_25_MV, 0x08),
+ regulator_desc_s2mps13_ldo(33, MIN_1400_MV, STEP_50_MV, 0x0C),
+ regulator_desc_s2mps13_ldo(34, MIN_1000_MV, STEP_25_MV, 0x08),
+ regulator_desc_s2mps13_ldo(35, MIN_1400_MV, STEP_50_MV, 0x0C),
+ regulator_desc_s2mps13_ldo(36, MIN_800_MV, STEP_12_5_MV, 0x00),
+ regulator_desc_s2mps13_ldo(37, MIN_1000_MV, STEP_25_MV, 0x08),
+ regulator_desc_s2mps13_ldo(38, MIN_1400_MV, STEP_50_MV, 0x0C),
+ regulator_desc_s2mps13_ldo(39, MIN_1000_MV, STEP_25_MV, 0x08),
+ regulator_desc_s2mps13_ldo(40, MIN_1400_MV, STEP_50_MV, 0x0C),
+ regulator_desc_s2mps13_buck(1, MIN_500_MV, STEP_6_25_MV, 0x10),
+ regulator_desc_s2mps13_buck(2, MIN_500_MV, STEP_6_25_MV, 0x10),
+ regulator_desc_s2mps13_buck(3, MIN_500_MV, STEP_6_25_MV, 0x10),
+ regulator_desc_s2mps13_buck(4, MIN_500_MV, STEP_6_25_MV, 0x10),
+ regulator_desc_s2mps13_buck(5, MIN_500_MV, STEP_6_25_MV, 0x10),
+ regulator_desc_s2mps13_buck(6, MIN_500_MV, STEP_6_25_MV, 0x10),
+ regulator_desc_s2mps13_buck(7, MIN_500_MV, STEP_6_25_MV, 0x10),
+ regulator_desc_s2mps13_buck(8, MIN_1000_MV, STEP_12_5_MV, 0x20),
+ regulator_desc_s2mps13_buck(9, MIN_1000_MV, STEP_12_5_MV, 0x20),
+ regulator_desc_s2mps13_buck(10, MIN_500_MV, STEP_6_25_MV, 0x10),
+};
+
static int s2mps14_regulator_enable(struct regulator_dev *rdev)
{
struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
unsigned int val;
switch (s2mps11->dev_type) {
+ case S2MPS13X:
case S2MPS14X:
if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
val = S2MPS14_ENABLE_SUSPEND;
@@ -406,6 +496,7 @@ static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev)
/* Below LDO should be always on or does not support suspend mode. */
switch (s2mps11->dev_type) {
+ case S2MPS13X:
case S2MPS14X:
switch (rdev_id) {
case S2MPS14_LDO3:
@@ -831,6 +922,10 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators);
regulators = s2mps11_regulators;
break;
+ case S2MPS13X:
+ s2mps11->rdev_num = ARRAY_SIZE(s2mps13_regulators);
+ regulators = s2mps13_regulators;
+ break;
case S2MPS14X:
s2mps11->rdev_num = ARRAY_SIZE(s2mps14_regulators);
regulators = s2mps14_regulators;
@@ -845,7 +940,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
return -EINVAL;
};
- s2mps11->ext_control_gpio = devm_kzalloc(&pdev->dev,
+ s2mps11->ext_control_gpio = devm_kmalloc(&pdev->dev,
sizeof(*s2mps11->ext_control_gpio) * s2mps11->rdev_num,
GFP_KERNEL);
if (!s2mps11->ext_control_gpio)
@@ -886,6 +981,7 @@ common_reg:
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 < s2mps11->rdev_num; i++) {
struct regulator_dev *regulator;
@@ -927,6 +1023,7 @@ out:
static const struct platform_device_id s2mps11_pmic_id[] = {
{ "s2mps11-pmic", S2MPS11X},
+ { "s2mps13-pmic", S2MPS13X},
{ "s2mps14-pmic", S2MPS14X},
{ "s2mpu02-pmic", S2MPU02},
{ },
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index 0ab5cbeeb797..dc1328c0c71c 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -581,7 +581,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
rdata->id = i;
rdata->initdata = of_get_regulator_init_data(
- &pdev->dev, reg_np);
+ &pdev->dev, reg_np,
+ &regulators[i]);
rdata->reg_node = reg_np;
rdata++;
rmode->id = i;
@@ -950,6 +951,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
config.of_node = pdata->regulators[i].reg_node;
config.ena_gpio = -EINVAL;
config.ena_gpio_flags = 0;
+ config.ena_gpio_initialized = true;
if (gpio_is_valid(pdata->regulators[i].ext_control_gpio))
s5m8767_regulator_config_ext_control(s5m8767,
&pdata->regulators[i], &config);
diff --git a/drivers/regulator/sky81452-regulator.c b/drivers/regulator/sky81452-regulator.c
index 97aff0ccd65f..647860611916 100644
--- a/drivers/regulator/sky81452-regulator.c
+++ b/drivers/regulator/sky81452-regulator.c
@@ -5,9 +5,8 @@
* Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
*
* This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -52,6 +51,8 @@ static const struct regulator_linear_range sky81452_reg_ranges[] = {
static const struct regulator_desc sky81452_reg = {
.name = "LOUT",
+ .of_match = of_match_ptr("lout"),
+ .regulators_node = of_match_ptr("regulator"),
.ops = &sky81452_reg_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
@@ -64,30 +65,6 @@ static const struct regulator_desc sky81452_reg = {
.enable_mask = SKY81452_LEN,
};
-#ifdef CONFIG_OF
-static struct regulator_init_data *sky81452_reg_parse_dt(struct device *dev)
-{
- struct regulator_init_data *init_data;
- struct device_node *np;
-
- np = of_get_child_by_name(dev->parent->of_node, "regulator");
- if (unlikely(!np)) {
- dev_err(dev, "regulator node not found");
- return NULL;
- }
-
- init_data = of_get_regulator_init_data(dev, np);
-
- of_node_put(np);
- return init_data;
-}
-#else
-static struct regulator_init_data *sky81452_reg_parse_dt(struct device *dev)
-{
- return ERR_PTR(-EINVAL);
-}
-#endif
-
static int sky81452_reg_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -95,20 +72,16 @@ static int sky81452_reg_probe(struct platform_device *pdev)
struct regulator_config config = { };
struct regulator_dev *rdev;
- if (!init_data) {
- init_data = sky81452_reg_parse_dt(dev);
- if (IS_ERR(init_data))
- return PTR_ERR(init_data);
- }
-
- config.dev = dev;
+ config.dev = dev->parent;
config.init_data = init_data;
config.of_node = dev->of_node;
config.regmap = dev_get_drvdata(dev->parent);
rdev = devm_regulator_register(dev, &sky81452_reg, &config);
- if (IS_ERR(rdev))
+ if (IS_ERR(rdev)) {
+ dev_err(dev, "failed to register. err=%ld\n", PTR_ERR(rdev));
return PTR_ERR(rdev);
+ }
platform_set_drvdata(pdev, rdev);
@@ -126,5 +99,4 @@ module_platform_driver(sky81452_reg_driver);
MODULE_DESCRIPTION("Skyworks SKY81452 Regulator driver");
MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@skyworksinc.com>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/stw481x-vmmc.c b/drivers/regulator/stw481x-vmmc.c
index a7e152696a02..b4f1696456a7 100644
--- a/drivers/regulator/stw481x-vmmc.c
+++ b/drivers/regulator/stw481x-vmmc.c
@@ -72,7 +72,8 @@ static int stw481x_vmmc_regulator_probe(struct platform_device *pdev)
config.regmap = stw481x->map;
config.of_node = pdev->dev.of_node;
config.init_data = of_get_regulator_init_data(&pdev->dev,
- pdev->dev.of_node);
+ pdev->dev.of_node,
+ &vmmc_regulator);
stw481x->vmmc_regulator = devm_regulator_register(&pdev->dev,
&vmmc_regulator, &config);
diff --git a/drivers/regulator/ti-abb-regulator.c b/drivers/regulator/ti-abb-regulator.c
index a2dabb575b97..1ef5aba96f17 100644
--- a/drivers/regulator/ti-abb-regulator.c
+++ b/drivers/regulator/ti-abb-regulator.c
@@ -837,7 +837,8 @@ skip_opt:
return -EINVAL;
}
- initdata = of_get_regulator_init_data(dev, pdev->dev.of_node);
+ initdata = of_get_regulator_init_data(dev, pdev->dev.of_node,
+ &abb->rdesc);
if (!initdata) {
dev_err(dev, "%s: Unable to alloc regulator init data\n",
__func__);
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
index f31f22e3e1bd..c213e37eb69e 100644
--- a/drivers/regulator/tps51632-regulator.c
+++ b/drivers/regulator/tps51632-regulator.c
@@ -221,7 +221,8 @@ static const struct of_device_id tps51632_of_match[] = {
MODULE_DEVICE_TABLE(of, tps51632_of_match);
static struct tps51632_regulator_platform_data *
- of_get_tps51632_platform_data(struct device *dev)
+ of_get_tps51632_platform_data(struct device *dev,
+ const struct regulator_desc *desc)
{
struct tps51632_regulator_platform_data *pdata;
struct device_node *np = dev->of_node;
@@ -230,7 +231,8 @@ static struct tps51632_regulator_platform_data *
if (!pdata)
return NULL;
- pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node);
+ pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node,
+ desc);
if (!pdata->reg_init_data) {
dev_err(dev, "Not able to get OF regulator init data\n");
return NULL;
@@ -248,7 +250,8 @@ static struct tps51632_regulator_platform_data *
}
#else
static struct tps51632_regulator_platform_data *
- of_get_tps51632_platform_data(struct device *dev)
+ of_get_tps51632_platform_data(struct device *dev,
+ const struct regulator_desc *desc)
{
return NULL;
}
@@ -273,9 +276,25 @@ static int tps51632_probe(struct i2c_client *client,
}
}
+ tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
+ if (!tps)
+ return -ENOMEM;
+
+ tps->dev = &client->dev;
+ tps->desc.name = client->name;
+ tps->desc.id = 0;
+ tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY;
+ tps->desc.min_uV = TPS51632_MIN_VOLTAGE;
+ tps->desc.uV_step = TPS51632_VOLTAGE_STEP_10mV;
+ tps->desc.linear_min_sel = TPS51632_MIN_VSEL;
+ tps->desc.n_voltages = TPS51632_MAX_VSEL + 1;
+ tps->desc.ops = &tps51632_dcdc_ops;
+ tps->desc.type = REGULATOR_VOLTAGE;
+ tps->desc.owner = THIS_MODULE;
+
pdata = dev_get_platdata(&client->dev);
if (!pdata && client->dev.of_node)
- pdata = of_get_tps51632_platform_data(&client->dev);
+ pdata = of_get_tps51632_platform_data(&client->dev, &tps->desc);
if (!pdata) {
dev_err(&client->dev, "No Platform data\n");
return -EINVAL;
@@ -296,22 +315,6 @@ static int tps51632_probe(struct i2c_client *client,
}
}
- tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
- if (!tps)
- return -ENOMEM;
-
- tps->dev = &client->dev;
- tps->desc.name = client->name;
- tps->desc.id = 0;
- tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY;
- tps->desc.min_uV = TPS51632_MIN_VOLTAGE;
- tps->desc.uV_step = TPS51632_VOLTAGE_STEP_10mV;
- tps->desc.linear_min_sel = TPS51632_MIN_VSEL;
- tps->desc.n_voltages = TPS51632_MAX_VSEL + 1;
- tps->desc.ops = &tps51632_dcdc_ops;
- tps->desc.type = REGULATOR_VOLTAGE;
- tps->desc.owner = THIS_MODULE;
-
if (pdata->enable_pwm_dvfs)
tps->desc.vsel_reg = TPS51632_VOLTAGE_BASE_REG;
else
diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c
index a1672044e519..a1fd626c6c96 100644
--- a/drivers/regulator/tps62360-regulator.c
+++ b/drivers/regulator/tps62360-regulator.c
@@ -293,7 +293,8 @@ static const struct regmap_config tps62360_regmap_config = {
};
static struct tps62360_regulator_platform_data *
- of_get_tps62360_platform_data(struct device *dev)
+ of_get_tps62360_platform_data(struct device *dev,
+ const struct regulator_desc *desc)
{
struct tps62360_regulator_platform_data *pdata;
struct device_node *np = dev->of_node;
@@ -302,7 +303,8 @@ static struct tps62360_regulator_platform_data *
if (!pdata)
return NULL;
- pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node);
+ pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node,
+ desc);
if (!pdata->reg_init_data) {
dev_err(dev, "Not able to get OF regulator init data\n");
return NULL;
@@ -350,6 +352,17 @@ static int tps62360_probe(struct i2c_client *client,
pdata = dev_get_platdata(&client->dev);
+ tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
+ if (!tps)
+ return -ENOMEM;
+
+ tps->desc.name = client->name;
+ tps->desc.id = 0;
+ tps->desc.ops = &tps62360_dcdc_ops;
+ tps->desc.type = REGULATOR_VOLTAGE;
+ tps->desc.owner = THIS_MODULE;
+ tps->desc.uV_step = 10000;
+
if (client->dev.of_node) {
const struct of_device_id *match;
match = of_match_device(of_match_ptr(tps62360_of_match),
@@ -360,7 +373,8 @@ static int tps62360_probe(struct i2c_client *client,
}
chip_id = (int)(long)match->data;
if (!pdata)
- pdata = of_get_tps62360_platform_data(&client->dev);
+ pdata = of_get_tps62360_platform_data(&client->dev,
+ &tps->desc);
} else if (id) {
chip_id = id->driver_data;
} else {
@@ -374,10 +388,6 @@ static int tps62360_probe(struct i2c_client *client,
return -EIO;
}
- tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
- if (!tps)
- return -ENOMEM;
-
tps->en_discharge = pdata->en_discharge;
tps->en_internal_pulldn = pdata->en_internal_pulldn;
tps->vsel0_gpio = pdata->vsel0_gpio;
@@ -401,13 +411,6 @@ static int tps62360_probe(struct i2c_client *client,
return -ENODEV;
}
- tps->desc.name = client->name;
- tps->desc.id = 0;
- tps->desc.ops = &tps62360_dcdc_ops;
- tps->desc.type = REGULATOR_VOLTAGE;
- tps->desc.owner = THIS_MODULE;
- tps->desc.uV_step = 10000;
-
tps->regmap = devm_regmap_init_i2c(client, &tps62360_regmap_config);
if (IS_ERR(tps->regmap)) {
ret = PTR_ERR(tps->regmap);
diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c
index d5df1e9ad1da..f1df4423d361 100644
--- a/drivers/regulator/tps65090-regulator.c
+++ b/drivers/regulator/tps65090-regulator.c
@@ -312,7 +312,11 @@ static void tps65090_configure_regulator_config(
gpio_flag = GPIOF_OUT_INIT_HIGH;
config->ena_gpio = tps_pdata->gpio;
+ config->ena_gpio_initialized = true;
config->ena_gpio_flags = gpio_flag;
+ } else {
+ config->ena_gpio = -EINVAL;
+ config->ena_gpio_initialized = false;
}
}
diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c
index f0a40281b9c1..263cc85d6202 100644
--- a/drivers/regulator/tps65218-regulator.c
+++ b/drivers/regulator/tps65218-regulator.c
@@ -231,7 +231,8 @@ static int tps65218_regulator_probe(struct platform_device *pdev)
template = match->data;
id = template->id;
- init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
+ init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
+ &regulators[id]);
platform_set_drvdata(pdev, tps);
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 0b4f8660fdb4..dd727bca1983 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -1104,7 +1104,8 @@ static int twlreg_probe(struct platform_device *pdev)
template = match->data;
id = template->desc.id;
initdata = of_get_regulator_init_data(&pdev->dev,
- pdev->dev.of_node);
+ pdev->dev.of_node,
+ &template->desc);
drvdata = NULL;
} else {
id = pdev->id;
diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c
index 02e7267ccf92..5e7c789023a9 100644
--- a/drivers/regulator/vexpress.c
+++ b/drivers/regulator/vexpress.c
@@ -74,7 +74,8 @@ static int vexpress_regulator_probe(struct platform_device *pdev)
reg->desc.owner = THIS_MODULE;
reg->desc.continuous_voltage_range = true;
- init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
+ init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
+ &reg->desc);
if (!init_data)
return -EINVAL;
diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c
index c24346db8a71..88f5064e412b 100644
--- a/drivers/regulator/wm8994-regulator.c
+++ b/drivers/regulator/wm8994-regulator.c
@@ -145,10 +145,12 @@ 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)
+ if (pdata) {
config.ena_gpio = pdata->ldo[id].enable;
- else if (wm8994->dev->of_node)
+ } else if (wm8994->dev->of_node) {
config.ena_gpio = wm8994->pdata.ldo[id].enable;
+ config.ena_gpio_initialized = true;
+ }
/* Use default constraints if none set up */
if (!pdata || !pdata->ldo[id].init_data || wm8994->dev->of_node) {