summaryrefslogtreecommitdiff
path: root/drivers/regulator/core.c
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2013-10-21 12:32:58 +0530
committerLaxman Dewangan <ldewangan@nvidia.com>2013-10-21 00:12:55 -0700
commit7f656cd9788e2ed2856029c79a0ab7660130fb7e (patch)
treee9518b268648367980029f34c8703ffbb55ffa97 /drivers/regulator/core.c
parent594cb38d77435cae55aa0e9641f5f4a086011f7d (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.c48
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;