diff options
-rw-r--r-- | drivers/regulator/core.c | 56 |
1 files changed, 36 insertions, 20 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 60fcd986ff3f..dbf27bf028c4 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -1191,16 +1191,21 @@ void regulator_put(struct regulator *regulator) | |||
1191 | } | 1191 | } |
1192 | EXPORT_SYMBOL_GPL(regulator_put); | 1192 | EXPORT_SYMBOL_GPL(regulator_put); |
1193 | 1193 | ||
1194 | static int _regulator_can_change_status(struct regulator_dev *rdev) | ||
1195 | { | ||
1196 | if (!rdev->constraints) | ||
1197 | return 0; | ||
1198 | |||
1199 | if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS) | ||
1200 | return 1; | ||
1201 | else | ||
1202 | return 0; | ||
1203 | } | ||
1204 | |||
1194 | /* locks held by regulator_enable() */ | 1205 | /* locks held by regulator_enable() */ |
1195 | static int _regulator_enable(struct regulator_dev *rdev) | 1206 | static int _regulator_enable(struct regulator_dev *rdev) |
1196 | { | 1207 | { |
1197 | int ret = -EINVAL; | 1208 | int ret; |
1198 | |||
1199 | if (!rdev->constraints) { | ||
1200 | printk(KERN_ERR "%s: %s has no constraints\n", | ||
1201 | __func__, rdev->desc->name); | ||
1202 | return ret; | ||
1203 | } | ||
1204 | 1209 | ||
1205 | /* do we need to enable the supply regulator first */ | 1210 | /* do we need to enable the supply regulator first */ |
1206 | if (rdev->supply) { | 1211 | if (rdev->supply) { |
@@ -1213,24 +1218,34 @@ static int _regulator_enable(struct regulator_dev *rdev) | |||
1213 | } | 1218 | } |
1214 | 1219 | ||
1215 | /* check voltage and requested load before enabling */ | 1220 | /* check voltage and requested load before enabling */ |
1216 | if (rdev->desc->ops->enable) { | 1221 | if (rdev->constraints && |
1222 | (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) | ||
1223 | drms_uA_update(rdev); | ||
1217 | 1224 | ||
1218 | if (rdev->constraints && | 1225 | if (rdev->use_count == 0) { |
1219 | (rdev->constraints->valid_ops_mask & | 1226 | /* The regulator may on if it's not switchable or left on */ |
1220 | REGULATOR_CHANGE_DRMS)) | 1227 | ret = _regulator_is_enabled(rdev); |
1221 | drms_uA_update(rdev); | 1228 | if (ret == -EINVAL || ret == 0) { |
1222 | 1229 | if (!_regulator_can_change_status(rdev)) | |
1223 | ret = rdev->desc->ops->enable(rdev); | 1230 | return -EPERM; |
1224 | if (ret < 0) { | 1231 | |
1225 | printk(KERN_ERR "%s: failed to enable %s: %d\n", | 1232 | if (rdev->desc->ops->enable) { |
1233 | ret = rdev->desc->ops->enable(rdev); | ||
1234 | if (ret < 0) | ||
1235 | return ret; | ||
1236 | } else { | ||
1237 | return -EINVAL; | ||
1238 | } | ||
1239 | } else { | ||
1240 | printk(KERN_ERR "%s: is_enabled() failed for %s: %d\n", | ||
1226 | __func__, rdev->desc->name, ret); | 1241 | __func__, rdev->desc->name, ret); |
1227 | return ret; | 1242 | return ret; |
1228 | } | 1243 | } |
1229 | rdev->use_count++; | ||
1230 | return ret; | ||
1231 | } | 1244 | } |
1232 | 1245 | ||
1233 | return ret; | 1246 | rdev->use_count++; |
1247 | |||
1248 | return 0; | ||
1234 | } | 1249 | } |
1235 | 1250 | ||
1236 | /** | 1251 | /** |
@@ -1270,7 +1285,8 @@ static int _regulator_disable(struct regulator_dev *rdev) | |||
1270 | if (rdev->use_count == 1 && !rdev->constraints->always_on) { | 1285 | if (rdev->use_count == 1 && !rdev->constraints->always_on) { |
1271 | 1286 | ||
1272 | /* we are last user */ | 1287 | /* we are last user */ |
1273 | if (rdev->desc->ops->disable) { | 1288 | if (_regulator_can_change_status(rdev) && |
1289 | rdev->desc->ops->disable) { | ||
1274 | ret = rdev->desc->ops->disable(rdev); | 1290 | ret = rdev->desc->ops->disable(rdev); |
1275 | if (ret < 0) { | 1291 | if (ret < 0) { |
1276 | printk(KERN_ERR "%s: failed to disable %s\n", | 1292 | printk(KERN_ERR "%s: failed to disable %s\n", |