Commit 412aec61 authored by David Brownell's avatar David Brownell Committed by Liam Girdwood

regulator: enable/disable refcounting

Make the <linux/regulator.h> framework treat enable/disable call
pairs like the <linux/clk.h> and <linux/interrupt.h> frameworks do:
they're refcounted, so that different parts of a driver don't need
to put work into coordination that frameworks normally handle.
It's a minor object code shrink.

It also makes the regulator_is_disabled() kerneldoc say what it's
actually returning:  return value is not a refcount, and may report
an error (e.g. I/O error from I2C).

It also fixes some minor regulator_put() goofage:  removing unlocked
access to the enable state.  (But still not making regulator put/get
match the refcounting pattern they invoke.)
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarLiam Girdwood <lrg@slimlogic.co.uk>
parent 812460a9
...@@ -79,7 +79,7 @@ struct regulator { ...@@ -79,7 +79,7 @@ struct regulator {
int uA_load; int uA_load;
int min_uV; int min_uV;
int max_uV; int max_uV;
int enabled; /* client has called enabled */ int enabled; /* count of client enables */
char *supply_name; char *supply_name;
struct device_attribute dev_attr; struct device_attribute dev_attr;
struct regulator_dev *rdev; struct regulator_dev *rdev;
...@@ -963,16 +963,13 @@ void regulator_put(struct regulator *regulator) ...@@ -963,16 +963,13 @@ void regulator_put(struct regulator *regulator)
if (regulator == NULL || IS_ERR(regulator)) if (regulator == NULL || IS_ERR(regulator))
return; return;
if (regulator->enabled) {
printk(KERN_WARNING "Releasing supply %s while enabled\n",
regulator->supply_name);
WARN_ON(regulator->enabled);
regulator_disable(regulator);
}
mutex_lock(&regulator_list_mutex); mutex_lock(&regulator_list_mutex);
rdev = regulator->rdev; rdev = regulator->rdev;
if (WARN(regulator->enabled, "Releasing supply %s while enabled\n",
regulator->supply_name))
_regulator_disable(rdev);
/* remove any sysfs entries */ /* remove any sysfs entries */
if (regulator->dev) { if (regulator->dev) {
sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
...@@ -1042,21 +1039,17 @@ static int _regulator_enable(struct regulator_dev *rdev) ...@@ -1042,21 +1039,17 @@ static int _regulator_enable(struct regulator_dev *rdev)
*/ */
int regulator_enable(struct regulator *regulator) int regulator_enable(struct regulator *regulator)
{ {
int ret; struct regulator_dev *rdev = regulator->rdev;
int ret = 0;
if (regulator->enabled) {
printk(KERN_CRIT "Regulator %s already enabled\n",
regulator->supply_name);
WARN_ON(regulator->enabled);
return 0;
}
mutex_lock(&regulator->rdev->mutex); mutex_lock(&rdev->mutex);
regulator->enabled = 1; if (regulator->enabled == 0)
ret = _regulator_enable(regulator->rdev); ret = _regulator_enable(rdev);
if (ret != 0) else if (regulator->enabled < 0)
regulator->enabled = 0; ret = -EIO;
mutex_unlock(&regulator->rdev->mutex); if (ret == 0)
regulator->enabled++;
mutex_unlock(&rdev->mutex);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(regulator_enable); EXPORT_SYMBOL_GPL(regulator_enable);
...@@ -1108,19 +1101,21 @@ static int _regulator_disable(struct regulator_dev *rdev) ...@@ -1108,19 +1101,21 @@ static int _regulator_disable(struct regulator_dev *rdev)
*/ */
int regulator_disable(struct regulator *regulator) int regulator_disable(struct regulator *regulator)
{ {
int ret; struct regulator_dev *rdev = regulator->rdev;
int ret = 0;
if (!regulator->enabled) {
printk(KERN_ERR "%s: not in use by this consumer\n",
__func__);
return 0;
}
mutex_lock(&regulator->rdev->mutex); mutex_lock(&rdev->mutex);
regulator->enabled = 0; if (regulator->enabled == 1) {
ret = _regulator_disable(rdev);
if (ret == 0)
regulator->uA_load = 0; regulator->uA_load = 0;
ret = _regulator_disable(regulator->rdev); } else if (WARN(regulator->enabled <= 0,
mutex_unlock(&regulator->rdev->mutex); "unbalanced disables for supply %s\n",
regulator->supply_name))
ret = -EIO;
if (ret == 0)
regulator->enabled--;
mutex_unlock(&rdev->mutex);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(regulator_disable); EXPORT_SYMBOL_GPL(regulator_disable);
...@@ -1196,7 +1191,13 @@ static int _regulator_is_enabled(struct regulator_dev *rdev) ...@@ -1196,7 +1191,13 @@ static int _regulator_is_enabled(struct regulator_dev *rdev)
* regulator_is_enabled - is the regulator output enabled * regulator_is_enabled - is the regulator output enabled
* @regulator: regulator source * @regulator: regulator source
* *
* Returns zero for disabled otherwise return number of enable requests. * Returns positive if the regulator driver backing the source/client
* has requested that the device be enabled, zero if it hasn't, else a
* negative errno code.
*
* Note that the device backing this regulator handle can have multiple
* users, so it might be enabled even if regulator_enable() was never
* called for this particular source.
*/ */
int regulator_is_enabled(struct regulator *regulator) int regulator_is_enabled(struct regulator *regulator)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment