summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-07-24 20:14:06 (GMT)
committerLinus Torvalds <torvalds@linux-foundation.org>2015-07-24 20:14:06 (GMT)
commitafdf0b91bdf04bc66ee64e1ac44f0979c55749b1 (patch)
tree995486dc2835b982264e329d702e1fe3a513b608
parent365c83c3f56e5c7b161c041a487170f9a4840523 (diff)
parent4c7d83e8a8106d90d4eff971c8d070f718ac4f9c (diff)
downloadlinux-afdf0b91bdf04bc66ee64e1ac44f0979c55749b1.tar.xz
Merge tag 'regulator-fix-v4.2-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator
Pull regulator fixes from Mark Brown: "As well as some driver specific fixes there's several fixes here for the core support for regulators supplying other regulators fixing both an issue with ACPI support (which had never been tested before) and some error handling and device removal issues that Javier noticed" * tag 'regulator-fix-v4.2-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: regulator: core: Fix memory leak in regulator_resolve_supply() regulator: core: Increase refcount for regulator supply's module regulator: core: Handle full constraints systems when resolving supplies regulator: 88pm800: fix LDO vsel_mask value regulator: max8973: Fix up control flag option for bias control regulator: s2mps11: Fix GPIO suspend enable shift wrapping bug
-rw-r--r--drivers/regulator/88pm800.c2
-rw-r--r--drivers/regulator/core.c19
-rw-r--r--drivers/regulator/max8973-regulator.c2
-rw-r--r--drivers/regulator/s2mps11.c14
4 files changed, 27 insertions, 10 deletions
diff --git a/drivers/regulator/88pm800.c b/drivers/regulator/88pm800.c
index 832932b..7fd4f51 100644
--- a/drivers/regulator/88pm800.c
+++ b/drivers/regulator/88pm800.c
@@ -130,7 +130,7 @@ struct pm800_regulators {
.owner = THIS_MODULE, \
.n_voltages = ARRAY_SIZE(ldo_volt_table), \
.vsel_reg = PM800_##vreg##_VOUT, \
- .vsel_mask = 0x1f, \
+ .vsel_mask = 0xf, \
.enable_reg = PM800_##ereg, \
.enable_mask = 1 << (ebit), \
.volt_table = ldo_volt_table, \
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index c9f7201..78387a6 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -109,6 +109,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
static struct regulator *create_regulator(struct regulator_dev *rdev,
struct device *dev,
const char *supply_name);
+static void _regulator_put(struct regulator *regulator);
static const char *rdev_get_name(struct regulator_dev *rdev)
{
@@ -1105,6 +1106,9 @@ static int set_supply(struct regulator_dev *rdev,
rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev));
+ if (!try_module_get(supply_rdev->owner))
+ return -ENODEV;
+
rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY");
if (rdev->supply == NULL) {
err = -ENOMEM;
@@ -1381,9 +1385,13 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
}
if (!r) {
- dev_err(dev, "Failed to resolve %s-supply for %s\n",
- rdev->supply_name, rdev->desc->name);
- return -EPROBE_DEFER;
+ if (have_full_constraints()) {
+ r = dummy_regulator_rdev;
+ } else {
+ dev_err(dev, "Failed to resolve %s-supply for %s\n",
+ rdev->supply_name, rdev->desc->name);
+ return -EPROBE_DEFER;
+ }
}
/* Recursively resolve the supply of the supply */
@@ -1398,8 +1406,11 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
/* Cascade always-on state to supply */
if (_regulator_is_enabled(rdev)) {
ret = regulator_enable(rdev->supply);
- if (ret < 0)
+ if (ret < 0) {
+ if (rdev->supply)
+ _regulator_put(rdev->supply);
return ret;
+ }
}
return 0;
diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c
index 6f2bdad..e94ddcf 100644
--- a/drivers/regulator/max8973-regulator.c
+++ b/drivers/regulator/max8973-regulator.c
@@ -450,7 +450,7 @@ static struct max8973_regulator_platform_data *max8973_parse_dt(
pdata->control_flags |= MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE;
if (of_property_read_bool(np, "maxim,enable-bias-control"))
- pdata->control_flags |= MAX8973_BIAS_ENABLE;
+ pdata->control_flags |= MAX8973_CONTROL_BIAS_ENABLE;
return pdata;
}
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 326ffb5..72fc3c3 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -34,6 +34,8 @@
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s2mpu02.h>
+/* The highest number of possible regulators for supported devices. */
+#define S2MPS_REGULATOR_MAX S2MPS13_REGULATOR_MAX
struct s2mps11_info {
unsigned int rdev_num;
int ramp_delay2;
@@ -49,7 +51,7 @@ struct s2mps11_info {
* One bit for each S2MPS13/S2MPS14/S2MPU02 regulator whether
* the suspend mode was enabled.
*/
- unsigned long long s2mps14_suspend_state:50;
+ DECLARE_BITMAP(suspend_state, S2MPS_REGULATOR_MAX);
/* Array of size rdev_num with GPIO-s for external sleep control */
int *ext_control_gpio;
@@ -500,7 +502,7 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev)
switch (s2mps11->dev_type) {
case S2MPS13X:
case S2MPS14X:
- if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
+ if (test_bit(rdev_get_id(rdev), s2mps11->suspend_state))
val = S2MPS14_ENABLE_SUSPEND;
else if (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)]))
val = S2MPS14_ENABLE_EXT_CONTROL;
@@ -508,7 +510,7 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev)
val = rdev->desc->enable_mask;
break;
case S2MPU02:
- if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
+ if (test_bit(rdev_get_id(rdev), s2mps11->suspend_state))
val = S2MPU02_ENABLE_SUSPEND;
else
val = rdev->desc->enable_mask;
@@ -562,7 +564,7 @@ static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev)
if (ret < 0)
return ret;
- s2mps11->s2mps14_suspend_state |= (1 << rdev_get_id(rdev));
+ set_bit(rdev_get_id(rdev), s2mps11->suspend_state);
/*
* Don't enable suspend mode if regulator is already disabled because
* this would effectively for a short time turn on the regulator after
@@ -960,18 +962,22 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
case S2MPS11X:
s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators);
regulators = s2mps11_regulators;
+ BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num);
break;
case S2MPS13X:
s2mps11->rdev_num = ARRAY_SIZE(s2mps13_regulators);
regulators = s2mps13_regulators;
+ BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num);
break;
case S2MPS14X:
s2mps11->rdev_num = ARRAY_SIZE(s2mps14_regulators);
regulators = s2mps14_regulators;
+ BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num);
break;
case S2MPU02:
s2mps11->rdev_num = ARRAY_SIZE(s2mpu02_regulators);
regulators = s2mpu02_regulators;
+ BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num);
break;
default:
dev_err(&pdev->dev, "Invalid device type: %u\n",