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 9a644d41b81..c2b7ec90103 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 | { |
