aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2008-11-16 14:44:46 -0500
committerLiam Girdwood <lrg@slimlogic.co.uk>2009-01-08 15:10:29 -0500
commit412aec610559bdb602a0a21ce149ba8ffbb6f983 (patch)
treeddc1e45080b94fdd791c244ab6f9cada712a52e5 /drivers
parent812460a927c1d0dc1fbdbec9aa07de1b04043d83 (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.c71
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(&regulator_list_mutex); 966 mutex_lock(&regulator_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 */
1043int regulator_enable(struct regulator *regulator) 1040int 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(&regulator->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(&regulator->rdev->mutex); 1050 if (ret == 0)
1051 regulator->enabled++;
1052 mutex_unlock(&rdev->mutex);
1060 return ret; 1053 return ret;
1061} 1054}
1062EXPORT_SYMBOL_GPL(regulator_enable); 1055EXPORT_SYMBOL_GPL(regulator_enable);
@@ -1108,19 +1101,21 @@ static int _regulator_disable(struct regulator_dev *rdev)
1108 */ 1101 */
1109int regulator_disable(struct regulator *regulator) 1102int 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(&regulator->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(&regulator->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}
1126EXPORT_SYMBOL_GPL(regulator_disable); 1121EXPORT_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 */
1201int regulator_is_enabled(struct regulator *regulator) 1202int regulator_is_enabled(struct regulator *regulator)
1202{ 1203{