diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2013-10-21 12:32:58 +0530 |
---|---|---|
committer | Laxman Dewangan <ldewangan@nvidia.com> | 2013-10-21 00:12:55 -0700 |
commit | 7f656cd9788e2ed2856029c79a0ab7660130fb7e (patch) | |
tree | e9518b268648367980029f34c8703ffbb55ffa97 /drivers/regulator/core.c | |
parent | 594cb38d77435cae55aa0e9641f5f4a086011f7d (diff) |
regulator: core: introduce regulator disable time
It is observed that some regulators do not get re-enabled without
waiting for the duration of disable time to completely turn off
Introduce the regulator disable time to make sure regulators are
disabled before enabling it.
Bug 1346985
Change-Id: I0bfff8f32dab7986ffab901b735fad6b4ec79c6f
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Signed-off-by: Vineel Kumar Reddy Kovvuri <vineelkumarr@nvidia.com>
Reviewed-on: http://git-master/r/288742
Diffstat (limited to 'drivers/regulator/core.c')
-rw-r--r-- | drivers/regulator/core.c | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 869b19722692..442eb6a76c94 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -108,6 +108,7 @@ static int _regulator_is_enabled(struct regulator_dev *rdev); static int _regulator_disable(struct regulator_dev *rdev); static int _regulator_enable(struct regulator_dev *rdev); static int _regulator_get_enable_time(struct regulator_dev *rdev); +static int _regulator_get_disable_time(struct regulator_dev *rdev); static int _regulator_get_voltage(struct regulator_dev *rdev); static int _regulator_get_current_limit(struct regulator_dev *rdev); static unsigned int _regulator_get_mode(struct regulator_dev *rdev); @@ -481,15 +482,25 @@ static ssize_t regulator_state_set(struct device *dev, udelay(delay); } } else { + int delay = 0; if (!rdev->desc->ops->disable) { ret = -EINVAL; goto end; } + ret = _regulator_get_disable_time(rdev); + if (ret >= 0) + delay = ret; ret = rdev->desc->ops->disable(rdev); if (ret < 0) { rdev_warn(rdev, "disable() failed: %d\n", ret); goto end; } + if (delay >= 1000) { + mdelay(delay / 1000); + udelay(delay % 1000); + } else if (delay) { + udelay(delay); + } } end: @@ -1171,8 +1182,9 @@ static int set_machine_constraints(struct regulator_dev *rdev, if (ret >= 1000) { mdelay(ret / 1000); udelay(ret % 1000); - } else + } else { udelay(ret); + } } } @@ -1182,6 +1194,16 @@ static int set_machine_constraints(struct regulator_dev *rdev, rdev_err(rdev, "failed to disable\n"); goto out; } + + ret = _regulator_get_disable_time(rdev); + if (ret > 0) { + if (ret >= 1000) { + mdelay(ret / 1000); + udelay(ret % 1000); + } else { + udelay(ret); + } + } } if (rdev->constraints->ramp_delay && ops->set_ramp_delay) { @@ -1388,6 +1410,13 @@ static int _regulator_get_enable_time(struct regulator_dev *rdev) return rdev->desc->ops->enable_time(rdev); } +static int _regulator_get_disable_time(struct regulator_dev *rdev) +{ + if (rdev->constraints && rdev->constraints->disable_time) + return rdev->constraints->disable_time; + return rdev->desc->disable_time; +} + static struct regulator_dev *regulator_dev_lookup(struct device *dev, const char *supply, int *ret) @@ -1897,7 +1926,15 @@ EXPORT_SYMBOL_GPL(regulator_enable); static int _regulator_do_disable(struct regulator_dev *rdev) { - int ret; + int ret, delay; + + ret = _regulator_get_disable_time(rdev); + if (ret >= 0) { + delay = ret; + } else { + rdev_warn(rdev, "disable_time() failed: %d\n", ret); + delay = 0; + } trace_regulator_disable(rdev_get_name(rdev)); @@ -1915,6 +1952,13 @@ static int _regulator_do_disable(struct regulator_dev *rdev) trace_regulator_disable_complete(rdev_get_name(rdev)); + if (delay >= 1000) { + mdelay(delay / 1000); + udelay(delay % 1000); + } else if (delay) { + udelay(delay); + } + _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, NULL); return 0; |