From 4d4f3f0462b5ca43e9f09254dd415c64502871a5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 3 Aug 2009 18:49:57 +0100 Subject: [PATCH] --- yaml --- r: 165389 b: refs/heads/master c: 9a2372fa7a403ba327873d0208a619d781a8a150 h: refs/heads/master i: 165387: d278dec6b15ca9b47c349408ce8b311eb721fbbb v: v3 --- [refs] | 2 +- trunk/drivers/regulator/core.c | 56 ++++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/[refs] b/[refs] index 46e091572177..9a761d474d69 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9332546fe88fa88bf6a7d9b1dce53ff5d314934e +refs/heads/master: 9a2372fa7a403ba327873d0208a619d781a8a150 diff --git a/trunk/drivers/regulator/core.c b/trunk/drivers/regulator/core.c index 60fcd986ff3f..dbf27bf028c4 100644 --- a/trunk/drivers/regulator/core.c +++ b/trunk/drivers/regulator/core.c @@ -1191,16 +1191,21 @@ void regulator_put(struct regulator *regulator) } EXPORT_SYMBOL_GPL(regulator_put); +static int _regulator_can_change_status(struct regulator_dev *rdev) +{ + if (!rdev->constraints) + return 0; + + if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS) + return 1; + else + return 0; +} + /* locks held by regulator_enable() */ static int _regulator_enable(struct regulator_dev *rdev) { - int ret = -EINVAL; - - if (!rdev->constraints) { - printk(KERN_ERR "%s: %s has no constraints\n", - __func__, rdev->desc->name); - return ret; - } + int ret; /* do we need to enable the supply regulator first */ if (rdev->supply) { @@ -1213,24 +1218,34 @@ static int _regulator_enable(struct regulator_dev *rdev) } /* check voltage and requested load before enabling */ - if (rdev->desc->ops->enable) { + if (rdev->constraints && + (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) + drms_uA_update(rdev); - if (rdev->constraints && - (rdev->constraints->valid_ops_mask & - REGULATOR_CHANGE_DRMS)) - drms_uA_update(rdev); - - ret = rdev->desc->ops->enable(rdev); - if (ret < 0) { - printk(KERN_ERR "%s: failed to enable %s: %d\n", + if (rdev->use_count == 0) { + /* The regulator may on if it's not switchable or left on */ + ret = _regulator_is_enabled(rdev); + if (ret == -EINVAL || ret == 0) { + if (!_regulator_can_change_status(rdev)) + return -EPERM; + + if (rdev->desc->ops->enable) { + ret = rdev->desc->ops->enable(rdev); + if (ret < 0) + return ret; + } else { + return -EINVAL; + } + } else { + printk(KERN_ERR "%s: is_enabled() failed for %s: %d\n", __func__, rdev->desc->name, ret); return ret; } - rdev->use_count++; - return ret; } - return ret; + rdev->use_count++; + + return 0; } /** @@ -1270,7 +1285,8 @@ static int _regulator_disable(struct regulator_dev *rdev) if (rdev->use_count == 1 && !rdev->constraints->always_on) { /* we are last user */ - if (rdev->desc->ops->disable) { + if (_regulator_can_change_status(rdev) && + rdev->desc->ops->disable) { ret = rdev->desc->ops->disable(rdev); if (ret < 0) { printk(KERN_ERR "%s: failed to disable %s\n",