aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-08-03 13:49:57 -0400
committerLiam Girdwood <lrg@slimlogic.co.uk>2009-09-22 08:32:41 -0400
commit9a2372fa7a403ba327873d0208a619d781a8a150 (patch)
treea9b3b932420563fdebc9be6f7451aefb1df7fb6f /drivers/regulator
parent9332546fe88fa88bf6a7d9b1dce53ff5d314934e (diff)
regulator: regulator_enable() permission checking
The regulator_enable() code wasn't actually checking that the machine constraints had given permission to enable the regulator. Add code to do that, but only if the regulator is not already on due to something like always_on or being left on at startup since in those cases there's no physical change being introduced and the constraint wouldn't make any sense. Also add matching code for disable(). We need to do less there since either regulator_enable() should have succeeded first or the board setup makes no sense. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/core.c56
1 files changed, 36 insertions, 20 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 60fcd986ff3..dbf27bf028c 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1191,16 +1191,21 @@ void regulator_put(struct regulator *regulator)
1191} 1191}
1192EXPORT_SYMBOL_GPL(regulator_put); 1192EXPORT_SYMBOL_GPL(regulator_put);
1193 1193
1194static 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() */
1195static int _regulator_enable(struct regulator_dev *rdev) 1206static 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",