diff options
author | David Brownell <dbrownell@users.sourceforge.net> | 2008-11-16 14:44:46 -0500 |
---|---|---|
committer | Liam Girdwood <lrg@slimlogic.co.uk> | 2009-01-08 15:10:29 -0500 |
commit | 412aec610559bdb602a0a21ce149ba8ffbb6f983 (patch) | |
tree | ddc1e45080b94fdd791c244ab6f9cada712a52e5 /drivers | |
parent | 812460a927c1d0dc1fbdbec9aa07de1b04043d83 (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/regulator/core.c | 71 |
1 files changed, 36 insertions, 35 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 9a644d41b813..c2b7ec901036 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -79,7 +79,7 @@ struct regulator { | |||
79 | int uA_load; | 79 | int uA_load; |
80 | int min_uV; | 80 | int min_uV; |
81 | int max_uV; | 81 | int max_uV; |
82 | int enabled; /* client has called enabled */ | 82 | int enabled; /* count of client enables */ |
83 | char *supply_name; | 83 | char *supply_name; |
84 | struct device_attribute dev_attr; | 84 | struct device_attribute dev_attr; |
85 | struct regulator_dev *rdev; | 85 | struct regulator_dev *rdev; |
@@ -963,16 +963,13 @@ void regulator_put(struct regulator *regulator) | |||
963 | if (regulator == NULL || IS_ERR(regulator)) | 963 | if (regulator == NULL || IS_ERR(regulator)) |
964 | return; | 964 | return; |
965 | 965 | ||
966 | if (regulator->enabled) { | ||
967 | printk(KERN_WARNING "Releasing supply %s while enabled\n", | ||
968 | regulator->supply_name); | ||
969 | WARN_ON(regulator->enabled); | ||
970 | regulator_disable(regulator); | ||
971 | } | ||
972 | |||
973 | mutex_lock(®ulator_list_mutex); | 966 | mutex_lock(®ulator_list_mutex); |
974 | rdev = regulator->rdev; | 967 | rdev = regulator->rdev; |
975 | 968 | ||
969 | if (WARN(regulator->enabled, "Releasing supply %s while enabled\n", | ||
970 | regulator->supply_name)) | ||
971 | _regulator_disable(rdev); | ||
972 | |||
976 | /* remove any sysfs entries */ | 973 | /* remove any sysfs entries */ |
977 | if (regulator->dev) { | 974 | if (regulator->dev) { |
978 | sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); | 975 | sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); |
@@ -1042,21 +1039,17 @@ static int _regulator_enable(struct regulator_dev *rdev) | |||
1042 | */ | 1039 | */ |
1043 | int regulator_enable(struct regulator *regulator) | 1040 | int regulator_enable(struct regulator *regulator) |
1044 | { | 1041 | { |
1045 | int ret; | 1042 | struct regulator_dev *rdev = regulator->rdev; |
1046 | 1043 | int ret = 0; | |
1047 | if (regulator->enabled) { | ||
1048 | printk(KERN_CRIT "Regulator %s already enabled\n", | ||
1049 | regulator->supply_name); | ||
1050 | WARN_ON(regulator->enabled); | ||
1051 | return 0; | ||
1052 | } | ||
1053 | 1044 | ||
1054 | mutex_lock(®ulator->rdev->mutex); | 1045 | mutex_lock(&rdev->mutex); |
1055 | regulator->enabled = 1; | 1046 | if (regulator->enabled == 0) |
1056 | ret = _regulator_enable(regulator->rdev); | 1047 | ret = _regulator_enable(rdev); |
1057 | if (ret != 0) | 1048 | else if (regulator->enabled < 0) |
1058 | regulator->enabled = 0; | 1049 | ret = -EIO; |
1059 | mutex_unlock(®ulator->rdev->mutex); | 1050 | if (ret == 0) |
1051 | regulator->enabled++; | ||
1052 | mutex_unlock(&rdev->mutex); | ||
1060 | return ret; | 1053 | return ret; |
1061 | } | 1054 | } |
1062 | EXPORT_SYMBOL_GPL(regulator_enable); | 1055 | EXPORT_SYMBOL_GPL(regulator_enable); |
@@ -1108,19 +1101,21 @@ static int _regulator_disable(struct regulator_dev *rdev) | |||
1108 | */ | 1101 | */ |
1109 | int regulator_disable(struct regulator *regulator) | 1102 | int regulator_disable(struct regulator *regulator) |
1110 | { | 1103 | { |
1111 | int ret; | 1104 | struct regulator_dev *rdev = regulator->rdev; |
1112 | 1105 | int ret = 0; | |
1113 | if (!regulator->enabled) { | ||
1114 | printk(KERN_ERR "%s: not in use by this consumer\n", | ||
1115 | __func__); | ||
1116 | return 0; | ||
1117 | } | ||
1118 | 1106 | ||
1119 | mutex_lock(®ulator->rdev->mutex); | 1107 | mutex_lock(&rdev->mutex); |
1120 | regulator->enabled = 0; | 1108 | if (regulator->enabled == 1) { |
1121 | regulator->uA_load = 0; | 1109 | ret = _regulator_disable(rdev); |
1122 | ret = _regulator_disable(regulator->rdev); | 1110 | if (ret == 0) |
1123 | mutex_unlock(®ulator->rdev->mutex); | 1111 | regulator->uA_load = 0; |
1112 | } else if (WARN(regulator->enabled <= 0, | ||
1113 | "unbalanced disables for supply %s\n", | ||
1114 | regulator->supply_name)) | ||
1115 | ret = -EIO; | ||
1116 | if (ret == 0) | ||
1117 | regulator->enabled--; | ||
1118 | mutex_unlock(&rdev->mutex); | ||
1124 | return ret; | 1119 | return ret; |
1125 | } | 1120 | } |
1126 | EXPORT_SYMBOL_GPL(regulator_disable); | 1121 | EXPORT_SYMBOL_GPL(regulator_disable); |
@@ -1196,7 +1191,13 @@ out: | |||
1196 | * regulator_is_enabled - is the regulator output enabled | 1191 | * regulator_is_enabled - is the regulator output enabled |
1197 | * @regulator: regulator source | 1192 | * @regulator: regulator source |
1198 | * | 1193 | * |
1199 | * Returns zero for disabled otherwise return number of enable requests. | 1194 | * Returns positive if the regulator driver backing the source/client |
1195 | * has requested that the device be enabled, zero if it hasn't, else a | ||
1196 | * negative errno code. | ||
1197 | * | ||
1198 | * Note that the device backing this regulator handle can have multiple | ||
1199 | * users, so it might be enabled even if regulator_enable() was never | ||
1200 | * called for this particular source. | ||
1200 | */ | 1201 | */ |
1201 | int regulator_is_enabled(struct regulator *regulator) | 1202 | int regulator_is_enabled(struct regulator *regulator) |
1202 | { | 1203 | { |