summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOsvaldo Banuelos <osvaldob@codeaurora.org>2014-12-16 17:16:25 -0800
committerRohit Vaswani <rvaswani@codeaurora.org>2016-03-01 12:22:36 -0800
commitdb58e9bdc318201eca4eb5a457a6d4ea8d1857b5 (patch)
treedc3514a6a440930fd9c01002bfabbe3295068736
parent9a5aec1c9268ffe4c857c5298bf43a0ddb9553d7 (diff)
regulator: core: fix regulator bypass logic
Since the regulator debugfs consumer does not call regulator_allow_bypass() on its regulator handles, regulators will not be placed on bypass mode even if all other consumers request for this. Fix this by introducing an open offset count that can be used to selectively disregard the debugfs consumer. Also, introduce a debugfs file to allow or disallow bypass mode on each regulator by leveraging on the new open offset count. Change-Id: If12534dac5e6b1c82acac9b5250137b4f816b922 Signed-off-by: Osvaldo Banuelos <osvaldob@codeaurora.org>
-rw-r--r--drivers/regulator/core.c62
-rw-r--r--include/linux/regulator/driver.h1
2 files changed, 61 insertions, 2 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index bcc81c0d94fd..803bd385c01a 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -3398,7 +3398,8 @@ int regulator_allow_bypass(struct regulator *regulator, bool enable)
if (enable && !regulator->bypass) {
rdev->bypass_count++;
- if (rdev->bypass_count == rdev->open_count) {
+ if (rdev->bypass_count == rdev->open_count -
+ rdev->open_offset) {
ret = rdev->desc->ops->set_bypass(rdev, enable);
if (ret != 0)
rdev->bypass_count--;
@@ -3407,7 +3408,8 @@ int regulator_allow_bypass(struct regulator *regulator, bool enable)
} else if (!enable && regulator->bypass) {
rdev->bypass_count--;
- if (rdev->bypass_count != rdev->open_count) {
+ if (rdev->bypass_count != rdev->open_count -
+ rdev->open_offset) {
ret = rdev->desc->ops->set_bypass(rdev, enable);
if (ret != 0)
rdev->bypass_count++;
@@ -3908,6 +3910,46 @@ static int reg_debug_enable_get(void *data, u64 *val)
DEFINE_SIMPLE_ATTRIBUTE(reg_enable_fops, reg_debug_enable_get,
reg_debug_enable_set, "%llu\n");
+static int reg_debug_bypass_enable_get(void *data, u64 *val)
+{
+ struct regulator *regulator = data;
+ struct regulator_dev *rdev = regulator->rdev;
+ bool enable = false;
+ int rc = 0;
+
+ mutex_lock(&rdev->mutex);
+ if (rdev->desc->ops->get_bypass) {
+ rc = rdev->desc->ops->get_bypass(rdev, &enable);
+ if (rc)
+ pr_err("get_bypass() failed, rc=%d\n", rc);
+ } else {
+ enable = (rdev->bypass_count == rdev->open_count
+ - rdev->open_offset);
+ }
+ mutex_unlock(&rdev->mutex);
+
+ *val = enable;
+
+ return rc;
+}
+
+static int reg_debug_bypass_enable_set(void *data, u64 val)
+{
+ struct regulator *regulator = data;
+ struct regulator_dev *rdev = regulator->rdev;
+ int ret = 0;
+
+ mutex_lock(&rdev->mutex);
+ rdev->open_offset = 0;
+ mutex_unlock(&rdev->mutex);
+
+ ret = regulator_allow_bypass(data, val);
+
+ return ret;
+}
+DEFINE_SIMPLE_ATTRIBUTE(reg_bypass_enable_fops, reg_debug_bypass_enable_get,
+ reg_debug_bypass_enable_set, "%llu\n");
+
static int reg_debug_fdisable_set(void *data, u64 val)
{
int err_info;
@@ -4152,6 +4194,7 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
goto error;
}
+ rdev->open_offset = 1;
reg_ops = rdev->desc->ops;
mode = S_IRUGO | S_IWUSR;
/* Enabled File */
@@ -4165,6 +4208,21 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
}
mode = 0;
+ /* Bypass Enable File */
+ if (reg_ops->set_bypass)
+ mode = S_IWUSR | S_IRUGO;
+
+ if (mode)
+ err_ptr = debugfs_create_file("bypass", mode,
+ rdev->debugfs, reg,
+ &reg_bypass_enable_fops);
+ if (IS_ERR(err_ptr)) {
+ pr_err("Error-Could not create bypass enable file\n");
+ debugfs_remove_recursive(rdev->debugfs);
+ goto error;
+ }
+
+ mode = 0;
/* Force-Disable File */
if (reg_ops->is_enabled)
mode |= S_IRUGO;
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 143598e3bd7e..2593c9a44787 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -371,6 +371,7 @@ struct regulator_dev {
int exclusive;
u32 use_count;
u32 open_count;
+ u32 open_offset;
u32 bypass_count;
/* lists we belong to */