From: David Brownell <david-b@pacbell.net>
To: Mark Brown <broonie@sirena.org.uk>
Cc: "Aggarwal, Anuj" <anuj.aggarwal@ti.com>,
"linux-omap@vger.kernel.org" <linux-omap@vger.kernel.org>
Subject: Re: Problems while designing TPS65023 regulator driver
Date: Sun, 8 Mar 2009 12:54:35 -0800 [thread overview]
Message-ID: <200903081354.36044.david-b@pacbell.net> (raw)
In-Reply-To: <20090307162233.GA12858@sirena.org.uk>
On Saturday 07 March 2009, Mark Brown wrote:
> What's happening here is that the kernel is making sure that the
> information it was given about the state of the regulator is actually
> true in case it was important ...
If that's a goal, then I suggest merging the appended patch,
which addresses a similar case: both boot_on and always_on
are clear, so the regulator should not be enabled.
This *can* be important, as e.g. if those flags are clear
but the bootloader turned the regulator on, then drivers
can't disable the regulator (on penalty of a stackdump!)
unless they issue a spurious/pointless/undesirable enable()
beforehand ...
- Dave
========== CUT HERE
From: David Brownell <dbrownell@users.sourceforge.net>
Make the regulator setup code simpler and more consistent:
- The only difference between "boot_on" and "always_on" is
that an "always_on" regulator won't be disabled. Both will
be active (and usecount will be 1) on return from setup.
- Regulators not marked as "boot_on" or "always_on" won't
be active (and usecount will be 0) on return from setup.
The exception to that simple policy is when there's a non-Linux
interface to the regulator ... e.g. if either a DSP or the CPU
running Linux can enable the regulator, and the DSP needs it to
be on, then it will be on.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
---
drivers/regulator/core.c | 62 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 47 insertions(+), 15 deletions(-)
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -711,6 +711,8 @@ static int set_machine_constraints(struc
int ret = 0;
const char *name;
struct regulator_ops *ops = rdev->desc->ops;
+ int enable = 0;
+ int is_enabled = -ENOSYS;
if (constraints->name)
name = constraints->name;
@@ -799,10 +801,6 @@ static int set_machine_constraints(struc
}
}
- /* are we enabled at boot time by firmware / bootloader */
- if (rdev->constraints->boot_on)
- rdev->use_count = 1;
-
/* do we need to setup our suspend state */
if (constraints->initial_state) {
ret = suspend_prepare(rdev, constraints->initial_state);
@@ -814,17 +812,51 @@ static int set_machine_constraints(struc
}
}
- /* if always_on is set then turn the regulator on if it's not
- * already on. */
- if (constraints->always_on && ops->enable &&
- ((ops->is_enabled && !ops->is_enabled(rdev)) ||
- (!ops->is_enabled && !constraints->boot_on))) {
- ret = ops->enable(rdev);
- if (ret < 0) {
- printk(KERN_ERR "%s: failed to enable %s\n",
- __func__, name);
- rdev->constraints = NULL;
- goto out;
+ /* Should this be enabled when we return from here? The difference
+ * between "boot_on" and "always_on" is that "always_on" regulators
+ * won't ever be disabled.
+ */
+ if (constraints->boot_on || constraints->always_on)
+ enable = 1;
+
+ /* Make sure the regulator isn't wrongly enabled or disabled.
+ * Bootloaders are often sloppy about leaving things on; and
+ * sometimes Linux wants to use a different model.
+ */
+ if (ops->is_enabled)
+ is_enabled = ops->is_enabled(rdev);
+ if (enable) {
+ if (ops->enable) {
+ /* forcibly enable if it's off or we can't tell */
+ if (is_enabled <= 0) {
+ ret = ops->enable(rdev);
+ pr_warning("%s: %s '%s' --> %d\n",
+ __func__, "enable", name, ret);
+ if (ret < 0) {
+ rdev->constraints = NULL;
+ goto out;
+ }
+ }
+ } else if (is_enabled < 0) {
+ pr_warning("%s: hoping regulator '%s' is %sd...\n",
+ __func__, name, "enable");
+ }
+ rdev->use_count = 1;
+ } else {
+ if (ops->disable) {
+ /* forcibly disable if it's on or we can't tell */
+ if (is_enabled != 0) {
+ ret = ops->disable(rdev);
+ pr_warning("%s: %s '%s' --> %d\n",
+ __func__, "disable", name, ret);
+ if (ret < 0) {
+ rdev->constraints = NULL;
+ goto out;
+ }
+ }
+ } else if (is_enabled < 0) {
+ pr_warning("%s: hoping regulator '%s' is %sd...\n",
+ __func__, name, "disable");
}
}
next prev parent reply other threads:[~2009-03-08 20:54 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-02-26 9:11 Problems while designing TPS65023 regulator driver Aggarwal, Anuj
2009-02-26 14:04 ` Mark Brown
2009-03-05 12:03 ` Aggarwal, Anuj
2009-03-06 13:34 ` Mark Brown
2009-03-07 0:07 ` David Brownell
2009-03-07 16:22 ` Mark Brown
2009-03-08 20:54 ` David Brownell [this message]
2009-03-08 22:41 ` Mark Brown
2009-03-10 0:45 ` David Brownell
2009-03-10 23:33 ` Mark Brown
2009-04-03 8:03 ` Aggarwal, Anuj
2009-04-03 8:53 ` Mark Brown
2009-04-04 0:05 ` Tony Lindgren
2009-04-23 13:30 ` Trilok Soni
2009-04-23 22:17 ` David Brownell
2009-04-24 6:01 ` Trilok Soni
2009-04-24 6:05 ` Aggarwal, Anuj
2009-04-24 6:32 ` David Brownell
2009-04-24 8:12 ` Aggarwal, Anuj
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200903081354.36044.david-b@pacbell.net \
--to=david-b@pacbell.net \
--cc=anuj.aggarwal@ti.com \
--cc=broonie@sirena.org.uk \
--cc=linux-omap@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox