Hi Paul,<br><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Dec 9, 2012 at 6:53 PM, Paul Walmsley <span dir="ltr"><<a href="mailto:paul@pwsan.com" target="_blank">paul@pwsan.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
From: Jean Pihet <<a href="mailto:jean.pihet@newoldbits.com">jean.pihet@newoldbits.com</a>><br>
<br>
Introduce the functional states for power domains, which include<br>
the power states and the logic states.<br>
This patch provides the API functions to set and read the power<br>
domains functional state and internal functions to convert between<br>
the functional (i.e. logical) and the internal (or registers) values.<br>
<br>
In the new API only the functions pwrdm_set_next_fpwrst() and<br>
pwrdm_set_fpwrst() shall be used to change a power domain target<br>
state, along with the associated PWRDM_FUNC_* macros as the state<br>
parameters.<br>
<br>
Note about the power domains allowed states:<br>
Power domains have varied capabilities, as defined by the value of<br>
the pwrsts and pwrsts_logic_ret fields of the powerdomain struct.<br>
When reading or setting a low power state such as OFF/RET, a specific<br>
requested state may not be supported on the given power domain.<br>
In the states conversion functions a power or logic state is first<br>
looked for in the lower power states in order to maximize the power<br>
savings, then if not found in the higher power states. An iteration<br>
function is used, as suggested by Rajendra Nayak <<a href="mailto:rnayak@ti.com">rnayak@ti.com</a>><br>
This function is temporary and will be removed later in the series.<br>
<br>
This functionality brings consistency in the functional power states<br>
core code and acts as a guard against hardware implementations<br>
discrepancies, e.g. some power domains only support the RET logic<br>
state although reading the logic state registers (previous, current<br>
and next) always returns OFF. The DSS power domain on OMAP3 is an<br>
example.<br>
<br>
Signed-off-by: Jean Pihet <<a href="mailto:j-pihet@ti.com">j-pihet@ti.com</a>><br>
Cc: Tero Kristo <<a href="mailto:t-kristo@ti.com">t-kristo@ti.com</a>><br>
Cc: Rajendra Nayak <<a href="mailto:rnayak@ti.com">rnayak@ti.com</a>><br>
Cc: Nishanth Menon <<a href="mailto:nm@ti.com">nm@ti.com</a>><br>
[<a href="mailto:paul@pwsan.com">paul@pwsan.com</a>: add offset for functional powerstates so it's not<br>
possible to confuse them with the old API; use one fn to convert func<br>
pwrsts to low-level hardware bits; skip hardware reads when hardware<br>
logic retst and logic pwrst bits are missing; fix kerneldoc and<br>
commit message; remove unnecessary PWRDM_LOGIC_MEM_PWRST_* macros;<br>
combine spinlock patch into this patch; expand the number of operations<br>
which take the spinlock]<br>
Signed-off-by: Paul Walmsley <<a href="mailto:paul@pwsan.com">paul@pwsan.com</a>><br>
---<br>
arch/arm/mach-omap2/powerdomain.c | 525 +++++++++++++++++++++++++++++++++++++<br>
arch/arm/mach-omap2/powerdomain.h | 33 ++<br>
2 files changed, 553 insertions(+), 5 deletions(-)<br>
<br>
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c<br>
index 94b89a25..18f33de 100644<br>
--- a/arch/arm/mach-omap2/powerdomain.c<br>
+++ b/arch/arm/mach-omap2/powerdomain.c<br>
@@ -1,7 +1,7 @@<br>
</blockquote><div> <br>...<br><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">+/**<br>
+ * _match_pwrst: determine the closest supported power state<br>
+ * @pwrsts: list of allowed states, defined as a bitmask<br>
+ * @pwrst: initial state to be used as a starting point<br>
+ * @min: minimum (i.e. lowest consumption) allowed state<br>
+ * @max: maximum (i.e. highest consumption) allowed state<br>
+ *<br>
+ * Search down then up for a valid state from a list of allowed<br>
+ * states. Used by states conversion functions (_pwrdm_fpwrst_to_*)<br>
+ * to look for allowed power and logic states for a powerdomain.<br>
+ * Returns the matching allowed state. XXX Deprecated. The software<br>
+ * should not try to program unsupported powerstates.<br></blockquote><div><br>Why is this new code already deprecated? Does this require a rewrite?<br><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ */<br>
+static int _match_pwrst(u32 pwrsts, int pwrst, int min, int max)<br>
+{<br>
+ int found = 1, new_pwrst = pwrst;<br>
+<br>
+ /*<br>
+ * If the power domain does not allow any state programmation<br>
+ * return the max state which is always allowed<br>
+ */<br>
+ if (!pwrsts)<br>
+ return max;<br>
+<br>
+ /*<br>
+ * Search lower: if the requested state is not supported<br>
+ * try the lower states, stopping at the minimum allowed<br>
+ * state<br>
+ */<br>
+ while (!(pwrsts & (1 << new_pwrst))) {<br>
+ if (new_pwrst <= min) {<br>
+ found = 0;<br>
+ break;<br>
+ }<br>
+ new_pwrst--;<br>
+ }<br>
+<br>
+ /*<br>
+ * Search higher: if no lower state found fallback to the higher<br>
+ * states, stopping at the maximum allowed state<br>
+ */<br>
+ if (!found) {<br>
+ new_pwrst = pwrst;<br>
+ while (!(pwrsts & (1 << new_pwrst))) {<br>
+ if (new_pwrst >= max) {<br>
+ new_pwrst = max;<br>
+ break;<br>
+ }<br>
+ new_pwrst++;<br>
+ }<br>
+ }<br>
+<br>
+ return new_pwrst;<br>
+}<br>
+<br>
+/**<br>
+ * _pwrdm_fpwrst_to_pwrst - Convert functional (i.e. logical) to<br>
+ * internal (i.e. registers) values for the power domains states.<br>
+ * @pwrdm: struct powerdomain * to convert the values for<br>
+ * @fpwrst: functional power state<br>
+ * @pwrdm_pwrst: ptr to u8 to return the power state in<br>
+ * @logic_retst: ptr to u8 to return the logic retention state in<br>
+ *<br>
+ * Returns the internal power state value for the power domain, or<br>
+ * -EINVAL in case of invalid parameters passed in.<br>
+ */<br>
+static int _pwrdm_fpwrst_to_pwrst(struct powerdomain *pwrdm, u8 fpwrst,<br>
+ u8 *pwrdm_pwrst, u8 *logic_retst)<br>
+{<br>
+ if (!pwrdm || !pwrdm_pwrst || !logic_retst)<br>
+ return -EINVAL;<br>
+<br>
+ switch (fpwrst) {<br>
+ case PWRDM_FUNC_PWRST_ON:<br>
+ *pwrdm_pwrst = PWRDM_POWER_ON;<br>
+ *logic_retst = PWRDM_POWER_RET;<br>
+ break;<br>
+ case PWRDM_FUNC_PWRST_INACTIVE:<br>
+ *pwrdm_pwrst = PWRDM_POWER_INACTIVE;<br>
+ *logic_retst = PWRDM_POWER_RET;<br>
+ break;<br>
+ case PWRDM_FUNC_PWRST_CSWR:<br>
+ *pwrdm_pwrst = PWRDM_POWER_RET;<br>
+ *logic_retst = PWRDM_POWER_RET;<br>
+ break;<br>
+ case PWRDM_FUNC_PWRST_OSWR:<br>
+ *pwrdm_pwrst = PWRDM_POWER_RET;<br>
+ *logic_retst = PWRDM_POWER_OFF;<br>
+ break;<br>
+ case PWRDM_FUNC_PWRST_OFF:<br>
+ *pwrdm_pwrst = PWRDM_POWER_OFF;<br>
+ /*<br>
+ * logic_retst is set to PWRDM_POWER_RET in this case<br>
+ * since the actual value does not matter, and because<br>
+ * some powerdomains don't support a logic_retst of<br>
+ * OFF. XXX Maybe there's some way to indicate a<br>
+ * 'don't care' value here?<br>
+ */<br>
+ *logic_retst = PWRDM_POWER_RET;<br>
+ break;<br>
+ default:<br>
+ return -EINVAL;<br>
+ }<br>
+<br>
+ /* XXX deprecated */<br></blockquote><div><br>Same here<br> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ *pwrdm_pwrst = _match_pwrst(pwrdm->pwrsts, *pwrdm_pwrst,<br>
+ PWRDM_POWER_OFF, PWRDM_POWER_ON);<br>
+<br>
+ *logic_retst = _match_pwrst(pwrdm->pwrsts_logic_ret, *logic_retst,<br>
+ PWRDM_POWER_OFF, PWRDM_POWER_RET);<br>
+<br>
+ pr_debug("powerdomain %s: convert fpwrst %0x to pwrst %0x\n",<br>
+ pwrdm->name, fpwrst, *pwrdm_pwrst);<br>
+<br>
+ return 0;<br>
+}<br></blockquote><div><br> </div><div>Thanks & regards,<br>Jean<br><br></div></div></div>