From: Mark Brown on
On Mon, May 10, 2010 at 07:16:06PM +0530, Deepak Sikri wrote:

> In our System on chip we have several power domains. As such there is no
> generic framework for the Power Domains in linux , and I find huge potential
> in the software to control the domains and exploit the power management
> capabilities.

> There is one very small model that I could think of, something on the lines
> of clock framework.

Might be worth looking at what the OMAP and SH Mobile CPUs are doing
here, they have existing handling for power domains. Off-SoC the
regulator API should already cope with a lot of this stuff.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Sundar on
Hi All,

The regulator framework documentation already refers to the concept of
power domains and I think the framework *can* be extended more to
support on-SoC power domains as well.

I have been working with the regulator framework for on-chip power
domains too and....

>2. Maintain a list of the different power domains present.
>3. The devices in a specific power domain, as per the requirements would get the power
>domain...
>4. Typically a usage count of zero for any power domai..
>5. The same could be mapped on to the PM framework..
>6. The model could further be build upon to check any dependency in the power domains

the above requirements can be leveraged through the current regulator
framework itself.

However, for working with power domains within the framework, I feel that,
- support must be added to allow additional domain-specific states
like retention, idle etc.
- controlling operating points for regulators, unlike setting optimal modes.
- controlling regulator modes via constraints enforced by clients and
managing transition to various states through the client requests and
pushing the client states up to the parent regulator.

>7. The advantages of the framework could be leveraged in the CPU idle time, by switching >off the Power domains with zero usage counts.

Yes. A simple platform specific list of all regulators ( and power
domains ) can be easily used in the CPUIdle driver for determining low
power states. Further, enforcing run time PM can club together any
peripheral's power sources in terms of external regulators, on-chip
domains ( and clock sources possibly).

i have a very primitive implementation for adding operating points and
constraints into the framework and currently i am able to control
regulator aka domain states based on various child domains and
contraints.

However, with more inputs, I think we can make the regulator framework
easily manage power sources, whether on-chip domains or external
conventional regulators...

Waiting for opinions and views,

Regards,
Sundar

Mon, May 10, 2010 at 7:35 PM, Mark Brown
<broonie(a)opensource.wolfsonmicro.com> wrote:
> On Mon, May 10, 2010 at 07:16:06PM +0530, Deepak Sikri wrote:
>
>> In our System on chip we have several power domains. As such there is no
>> generic framework for the Power Domains in linux , and I find huge potential
>> in the software to control the domains and exploit the power management
>> capabilities.
>
>> There is one very small model that I could think of, something on the lines
>> of clock framework.
>
> Might be worth looking at what the OMAP and SH Mobile CPUs are doing
> here, they have existing handling for power domains. �Off-SoC the
> regulator API should already cope with a lot of this stuff.
> _______________________________________________
> linux-pm mailing list
> linux-pm(a)lists.linux-foundation.org
> https://lists.linux-foundation.org/mailman/listinfo/linux-pm
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Mark Brown on
On Sun, May 16, 2010 at 04:43:52PM +0530, Sundar wrote:

Please don't top post, it breaks the thread of discussion.

> However, for working with power domains within the framework, I feel that,
> - support must be added to allow additional domain-specific states
> like retention, idle etc.

I'm really not convinced that this is a good idea. Generally I suspect
the implementations of these concepts that I've seen would introduce
layering violations if done via the regulator API - from what I've seen
the power domains can end up knowing rather more about the things that
are being powered than is healthy for the regulator API and...

> - controlling operating points for regulators, unlike setting optimal modes.
> - controlling regulator modes via constraints enforced by clients and
> managing transition to various states through the client requests and
> pushing the client states up to the parent regulator.

....knowing a lot about the specifics of the internal structures of the
device you're trying to model. Cross talk with the clock API also seems
fairly common here.

I do think it's likely that you'll want something that looks like the
regulator API at the edges, but that a separate implementation that
avoids having to shoehorn through the abstractions of the regulator API
for the on-chip work seems much more sensible (and is what OMAP and SH
are already doing). This is fairly similar to the relationship between
the clock and regulator APIs - they look a lot alike, especially from a
user point of view, but they are separate because there are enough
differences in what they are trying to represent to make it sensible to
keep them apart.

However, if you have patches it's probably easier to talk about those
than architecture astronauting; perhaps your implementation avoids my
concerns.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Sundar R Iyer on
On Mon, 2010-05-17 at 18:23 +0200, Sundar wrote:
> P.S : Let me post out the patch set following on.

Sorry to change the email-ID; didnt want to would break patch
readability.

The implementation follows:

The regulator framework states that any source which supplies
power to a peripheral can be modeled as a regulator. However,
in new SoCs where peripherals apart from being powered through
the conventional regulators, peripherals are also powered through
on-chip domains. These on-chip domains control enabling/disabling
and also controlling the output to the peripheral as full mode
or idle mode (retention). These power sources don.t allow control
of parameters like DRMS, current, voltage etc.

Also, in such designs, often individual domains are clubbed under
a unified domain. In such a case, smaller domains need to communicate
to the parent domain in case of a constraining request from its peripheral(s).

Domain ABC
|---Periph Domain A, (100OPP/50OPP),
to run at 100OPP, parent to run at 100OPP
|---Periph Domain B, (100OPP),
to run at 100OPP, parent to run at 100OPP
|---Periph Domain C, (100OPP/50OPP),
to run at 100OPP, parent to run at 100OPP

Thus, for ideal power saving modes, the Domain ABC can be turned
to a lower OPP if
- Periph B is not running
- Periph A/C are running at 50OPP only.

This patch set adds a function for controlling the OPPs,
not touching the existing voltage/mode functions, as they
are needed in their own way for conventional regulators.

Sundar R Iyer (1):
regulators : Regulator Operating Points

---
drivers/regulator/core.c | 79 ++++++++++++++++++++++++++++++++++++
include/linux/regulator/consumer.h | 27 ++++++++++++
include/linux/regulator/driver.h | 5 ++
include/linux/regulator/machine.h | 6 +++
4 files changed, 117 insertions(+), 0 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
old mode 100644
new mode 100755
index 2248087..7c6c5af
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1898,6 +1898,85 @@ out:
}
EXPORT_SYMBOL_GPL(regulator_set_optimum_mode);

+/* locks held by regulator_set_operating_point() */
+static int _regulator_set_operating_point(struct regulator_dev *rdev,
+ unsigned int opp)
+{
+ int ret, regulator_curr_opp = 0;
+
+ if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_OPP)) {
+ printk(KERN_ERR "%s: operation not allowed for %s\n",
+ __func__, rdev->desc->name);
+ return -EPERM;
+ }
+
+ /* sanity checks */
+ if (!rdev->desc->ops->set_operating_point) {
+ return -EINVAL;
+ }
+
+ if (rdev->desc->ops->get_operating_point)
+ regulator_curr_opp = rdev->desc->ops->get_operating_point(rdev);
+
+ /* we have no issues with upgrading the opp */
+ if (opp == REGULATOR_OPERATINGPOINT_FULL) {
+ if (rdev->constraints->opp_constraint_count < 1) {
+ if (rdev->supply)
+ ret = _regulator_set_operating_point(rdev->supply, opp);
+ ret = rdev->desc->ops->set_operating_point(rdev, opp);
+ }
+ rdev->constraints->opp_constraint_count++;
+ }
+
+ if (opp == REGULATOR_OPERATINGPOINT_IDLE) {
+ rdev->constraints->opp_constraint_count--;
+ /* if there r no constraints */
+ if (rdev->constraints->opp_constraint_count == 0) {
+ if (rdev->supply)
+ ret = _regulator_set_operating_point(rdev->supply, opp);
+
+ ret = rdev->desc->ops->set_operating_point(rdev, opp);
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * regulator_set_operating_point - set regulator operating point
+ * @regulator: regulator source
+ * @opp: operating point to set
+ *
+ * sets the operating point for a regulator.
+ * this is not to be confused the regulator modes. For smart regulators
+ * that can run at varied operating points, clients can request simply
+ * operating points rather than notional load values.
+ *
+ * For eg, an on-chip regulator source for a peripheral like multimedia can
+ * - run at a full operating point for a full 1020p,
+ * - run at half the operating point for something like QVGA.
+ *
+ * All on-chip power domains can be modelled as regulators, and their controls
+ * through this function.
+ *
+ * Returns the new regulator operating point or error.
+ */
+int regulator_set_operating_point(struct regulator *regulator, unsigned int opp)
+{
+ struct regulator_dev *rdev = regulator->rdev;
+ int ret;
+
+ mutex_lock(&rdev->mutex);
+ ret = _regulator_set_operating_point(rdev, opp);
+ mutex_unlock(&rdev->mutex);
+
+ return ret;
+
+}
+EXPORT_SYMBOL_GPL(regulator_set_operating_point);
+
+
+
/**
* regulator_register_notifier - register regulator event notifier
* @regulator: regulator source
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
old mode 100644
new mode 100755
index ebd7472..680ec30
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -82,6 +82,30 @@
#define REGULATOR_MODE_STANDBY 0x8

/*
+ * Regulator operating points
+ *
+ * Fast, switchable supplies for peripherals which are controlled
+ * via on-chip power domains are different from normal regulators
+ * which control voltages, current, drms etc. For such power domain
+ * supplies aka regulators, all that can be controlled is the operating
+ * point, OPP. Such regulators can be either on with full voltage, or
+ * partially on at retention/normal voltages (specific to SoC settings)
+ *
+ * these flags can be used to model "power domains" on SoCs in the main
+ * regulator framework
+ *
+ * Also, for such power domains, turning on/off can be handled through
+ * the regulator enable/disable calls
+ *
+ * FULL Regulator runs at the full output
+ * HALF Regulator runs at the half output
+ *
+ * these OPPs can be OR'ed together to make a mask of valid regulator OPPs
+ */
+#define REGULATOR_OPERATINGPOINT_FULL 0x1
+#define REGULATOR_OPERATINGPOINT_IDLE 0x2
+
+/*
* Regulator notifier events.
*
* UNDER_VOLTAGE Regulator output is under voltage.
@@ -160,6 +184,9 @@ int regulator_get_current_limit(struct regulator *regulator);

int regulator_set_mode(struct regulator *regulator, unsigned int mode);
unsigned int regulator_get_mode(struct regulator *regulator);
+
+int regulator_set_operating_point(struct regulator *regulator, unsigned int opp);
+
int regulator_set_optimum_mode(struct regulator *regulator, int load_uA);

/* regulator notifier block */
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
old mode 100644
new mode 100755
index 592cd7c..e5be16b
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -122,6 +122,11 @@ struct regulator_ops {

/* set regulator suspend operating mode (defined in regulator.h) */
int (*set_suspend_mode) (struct regulator_dev *, unsigned int mode);
+
+ /* set regulator operating point */
+ int (*set_operating_point) (struct regulator_dev *, int opp);
+ int (*get_operating_point) (struct regulator_dev *);
+
};

/*
diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h
old mode 100644
new mode 100755
index e298028..185a5d5
--- a/include/linux/regulator/machine.h
+++ b/include/linux/regulator/machine.h
@@ -39,6 +39,7 @@ struct regulator;
#define REGULATOR_CHANGE_MODE 0x4
#define REGULATOR_CHANGE_STATUS 0x8
#define REGULATOR_CHANGE_DRMS 0x10
+#define REGULATOR_CHANGE_OPP 0x20

/**
* struct regulator_state - regulator state during low power system states
@@ -109,6 +110,9 @@ struct regulation_constraints {
/* valid operations for regulator on this machine */
unsigned int valid_ops_mask;

+ /* valid operating point ranges for this regulator */
+ unsigned int valid_opp_mask;
+
/* regulator input voltage - only if supply is another regulator */
int input_uV;

@@ -125,6 +129,8 @@ struct regulation_constraints {
unsigned always_on:1; /* regulator never off when system is on */
unsigned boot_on:1; /* bootloader/firmware enabled regulator */
unsigned apply_uV:1; /* apply uV constraint if min == max */
+ unsigned int opp_constraint_count; /* clients enforcing a constraint */
+
};

/**
--
1.7.0



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
From: Mark Brown on
On Mon, 2010-05-17 at 22:05 +0530, Sundar R Iyer wrote:

> +/* locks held by regulator_set_operating_point() */
> +static int _regulator_set_operating_point(struct regulator_dev *rdev,
> + unsigned int opp)
> +{
> + int ret, regulator_curr_opp = 0;
> +
> + if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_OPP)) {
> + printk(KERN_ERR "%s: operation not allowed for %s\n",
> + __func__, rdev->desc->name);
> + return -EPERM;
> + }
> +
> + /* sanity checks */
> + if (!rdev->desc->ops->set_operating_point) {
> + return -EINVAL;
> + }
> +
> + if (rdev->desc->ops->get_operating_point)
> + regulator_curr_opp = rdev->desc->ops->get_operating_point(rdev);
> +
> + /* we have no issues with upgrading the opp */
> + if (opp == REGULATOR_OPERATINGPOINT_FULL) {
> + if (rdev->constraints->opp_constraint_count < 1) {
> + if (rdev->supply)
> + ret = _regulator_set_operating_point(rdev->supply, opp);
> + ret = rdev->desc->ops->set_operating_point(rdev, opp);
> + }
> + rdev->constraints->opp_constraint_count++;
> + }

This implementation is assuming that the implementation in hardware only
has two levels, and that the decision to go to the higher level is done
by a simple or of requests for the full level from the consumers. I'm
not convinced that this will be true in general, or that it's always
going to be true that the different power domains are all isolated from
each other. There doesn't seem to be any immediate reason why hardware
won't ever implement more than two modes, and I'm not convinced that the
straight or of requests will always be sufficient to determine the
operating mode for the entire power domain. For example, I can see
hardware requiring that if more than a given number of blocks are
enabled at any level a higher operating point is selected.

Are you sure that this interface is sufficiently general to work with
all hardware, not just your own? How does this map on to the OMAP or SH
hardware, for example?

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/