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: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
This commit is contained in:
committed by
Liam Girdwood
parent
812460a927
commit
412aec6105
@@ -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)
|
|||||||
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(®ulator_list_mutex);
|
mutex_lock(®ulator_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)
|
|||||||
*/
|
*/
|
||||||
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) {
|
mutex_lock(&rdev->mutex);
|
||||||
printk(KERN_CRIT "Regulator %s already enabled\n",
|
if (regulator->enabled == 0)
|
||||||
regulator->supply_name);
|
ret = _regulator_enable(rdev);
|
||||||
WARN_ON(regulator->enabled);
|
else if (regulator->enabled < 0)
|
||||||
return 0;
|
ret = -EIO;
|
||||||
}
|
if (ret == 0)
|
||||||
|
regulator->enabled++;
|
||||||
mutex_lock(®ulator->rdev->mutex);
|
mutex_unlock(&rdev->mutex);
|
||||||
regulator->enabled = 1;
|
|
||||||
ret = _regulator_enable(regulator->rdev);
|
|
||||||
if (ret != 0)
|
|
||||||
regulator->enabled = 0;
|
|
||||||
mutex_unlock(®ulator->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)
|
|||||||
*/
|
*/
|
||||||
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) {
|
mutex_lock(&rdev->mutex);
|
||||||
printk(KERN_ERR "%s: not in use by this consumer\n",
|
if (regulator->enabled == 1) {
|
||||||
__func__);
|
ret = _regulator_disable(rdev);
|
||||||
return 0;
|
if (ret == 0)
|
||||||
}
|
regulator->uA_load = 0;
|
||||||
|
} else if (WARN(regulator->enabled <= 0,
|
||||||
mutex_lock(®ulator->rdev->mutex);
|
"unbalanced disables for supply %s\n",
|
||||||
regulator->enabled = 0;
|
regulator->supply_name))
|
||||||
regulator->uA_load = 0;
|
ret = -EIO;
|
||||||
ret = _regulator_disable(regulator->rdev);
|
if (ret == 0)
|
||||||
mutex_unlock(®ulator->rdev->mutex);
|
regulator->enabled--;
|
||||||
|
mutex_unlock(&rdev->mutex);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regulator_disable);
|
EXPORT_SYMBOL_GPL(regulator_disable);
|
||||||
@@ -1196,7 +1191,13 @@ out:
|
|||||||
* 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)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user