All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/8] ARM: OMAP2+: PM: introduce the power domains functional states
@ 2012-06-14 14:53 ` Jean Pihet
  0 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-omap, paul, linux-arm-kernel, khilman; +Cc: Jean Pihet

Here is a re-spin after some comments after an internal review and some testing on
OMAP4 with device OFF support.

Implement the functional states for the power domains:
- unify the API to use the functional states,
- protect the power domain state change by a mutex in
  omap_set_pwrdm_state,
- introduce the functional states for power domains power states and
  logic power states, and the conversion functions between the
  functional and internal states,
- program the logic power state of power domains from the functional
  states, in omap_set_pwrdm_state
- convert the OMAP2/3/4 PM code to use the updated API,
- provide the power domains statistics by functional states,
- provide ftrace tracepoints with the functional state.

Based on mainline kernel 3.5.0-rc2.

Tested on OMAP3 Beagleboard, with suspend and cpuidle in RET and
OFF modes.


History:
 v4:
 - reworked the code after internal review and testing with OMAP3&4 device
   OFF,
 - fixed the tracepoints generation code,
 - introduce a function that returns power domains achievable functional
   states, in order to return a valid state for power domains that only
   support some of the power states. Although it has been tested OK the
   code is in RFC state.

 v3:
 - fix a bug in OMAP3 cpuidle which prevented the IO wake-ups in PER

 v2:
 - add the logic power states,
 - provide the power domains statistics by functional states

 v1:
 - initial implementation, in RFC state
 

Jean Pihet (8):
  ARM: OMAP2+: PM: protect the power domain state change by a mutex
  ARM: OMAP2+: PM: introduce power domains functional states
  ARM: OMAP2+: PM: use the functional power states API
  ARM: OMAP2+: PM: introduce power domains logic and memory functional
    states
  ARM: OMAP2+: PM: introduce power domains achievable functional states
  ARM: OMAP2+: PM: use the functional power states API for logic and
    memory
  ARM: OMAP2+: PM: use power domain functional state in stats counters
  ARM: OMAP2+: PM debug: trace the functional power domains states

 arch/arm/mach-omap2/cpuidle34xx.c          |   61 +++---
 arch/arm/mach-omap2/cpuidle44xx.c          |   28 +--
 arch/arm/mach-omap2/omap-hotplug.c         |    2 +-
 arch/arm/mach-omap2/omap-mpuss-lowpower.c  |   39 ++--
 arch/arm/mach-omap2/pm-debug.c             |   15 +-
 arch/arm/mach-omap2/pm.c                   |   62 -----
 arch/arm/mach-omap2/pm.h                   |    1 -
 arch/arm/mach-omap2/pm24xx.c               |   15 +-
 arch/arm/mach-omap2/pm34xx.c               |   78 +++---
 arch/arm/mach-omap2/pm44xx.c               |   18 +-
 arch/arm/mach-omap2/powerdomain-common.c   |  100 ++++++++
 arch/arm/mach-omap2/powerdomain.c          |  367 ++++++++++++++++++++++++++--
 arch/arm/mach-omap2/powerdomain.h          |  101 ++++++--
 arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |    7 +
 arch/arm/mach-omap2/powerdomain44xx.c      |    3 +
 15 files changed, 653 insertions(+), 244 deletions(-)

-- 
1.7.7.6


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH v4 0/8] ARM: OMAP2+: PM: introduce the power domains functional states
@ 2012-06-14 14:53 ` Jean Pihet
  0 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-arm-kernel

Here is a re-spin after some comments after an internal review and some testing on
OMAP4 with device OFF support.

Implement the functional states for the power domains:
- unify the API to use the functional states,
- protect the power domain state change by a mutex in
  omap_set_pwrdm_state,
- introduce the functional states for power domains power states and
  logic power states, and the conversion functions between the
  functional and internal states,
- program the logic power state of power domains from the functional
  states, in omap_set_pwrdm_state
- convert the OMAP2/3/4 PM code to use the updated API,
- provide the power domains statistics by functional states,
- provide ftrace tracepoints with the functional state.

Based on mainline kernel 3.5.0-rc2.

Tested on OMAP3 Beagleboard, with suspend and cpuidle in RET and
OFF modes.


History:
 v4:
 - reworked the code after internal review and testing with OMAP3&4 device
   OFF,
 - fixed the tracepoints generation code,
 - introduce a function that returns power domains achievable functional
   states, in order to return a valid state for power domains that only
   support some of the power states. Although it has been tested OK the
   code is in RFC state.

 v3:
 - fix a bug in OMAP3 cpuidle which prevented the IO wake-ups in PER

 v2:
 - add the logic power states,
 - provide the power domains statistics by functional states

 v1:
 - initial implementation, in RFC state
 

Jean Pihet (8):
  ARM: OMAP2+: PM: protect the power domain state change by a mutex
  ARM: OMAP2+: PM: introduce power domains functional states
  ARM: OMAP2+: PM: use the functional power states API
  ARM: OMAP2+: PM: introduce power domains logic and memory functional
    states
  ARM: OMAP2+: PM: introduce power domains achievable functional states
  ARM: OMAP2+: PM: use the functional power states API for logic and
    memory
  ARM: OMAP2+: PM: use power domain functional state in stats counters
  ARM: OMAP2+: PM debug: trace the functional power domains states

 arch/arm/mach-omap2/cpuidle34xx.c          |   61 +++---
 arch/arm/mach-omap2/cpuidle44xx.c          |   28 +--
 arch/arm/mach-omap2/omap-hotplug.c         |    2 +-
 arch/arm/mach-omap2/omap-mpuss-lowpower.c  |   39 ++--
 arch/arm/mach-omap2/pm-debug.c             |   15 +-
 arch/arm/mach-omap2/pm.c                   |   62 -----
 arch/arm/mach-omap2/pm.h                   |    1 -
 arch/arm/mach-omap2/pm24xx.c               |   15 +-
 arch/arm/mach-omap2/pm34xx.c               |   78 +++---
 arch/arm/mach-omap2/pm44xx.c               |   18 +-
 arch/arm/mach-omap2/powerdomain-common.c   |  100 ++++++++
 arch/arm/mach-omap2/powerdomain.c          |  367 ++++++++++++++++++++++++++--
 arch/arm/mach-omap2/powerdomain.h          |  101 ++++++--
 arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |    7 +
 arch/arm/mach-omap2/powerdomain44xx.c      |    3 +
 15 files changed, 653 insertions(+), 244 deletions(-)

-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 1/8] ARM: OMAP2+: PM: protect the power domain state change by a mutex
  2012-06-14 14:53 ` Jean Pihet
@ 2012-06-14 14:53   ` Jean Pihet
  -1 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-omap, paul, linux-arm-kernel, khilman; +Cc: Jean Pihet

omap_set_pwrdm_state is intented to be the only API for changing
a power domain state.
This patch protects the power domains settings and structs from
concurrent accesses to the function by using a mutex.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/pm.c          |    8 ++++++--
 arch/arm/mach-omap2/powerdomain.c |    1 +
 arch/arm/mach-omap2/powerdomain.h |    3 ++-
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 9cb5ced..a05f00c 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -100,15 +100,17 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
 	if (!pwrdm || IS_ERR(pwrdm))
 		return -EINVAL;
 
+	mutex_lock(&pwrdm->lock);
+
 	while (!(pwrdm->pwrsts & (1 << pwrst))) {
 		if (pwrst == PWRDM_POWER_OFF)
-			return ret;
+			goto out;
 		pwrst--;
 	}
 
 	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
 	if (next_pwrst == pwrst)
-		return ret;
+		goto out;
 
 	curr_pwrst = pwrdm_read_pwrst(pwrdm);
 	if (curr_pwrst < PWRDM_POWER_ON) {
@@ -141,6 +143,8 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
 		break;
 	}
 
+out:
+	mutex_unlock(&pwrdm->lock);
 	return ret;
 }
 
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 9611490..1641e72 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -102,6 +102,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
 	INIT_LIST_HEAD(&pwrdm->voltdm_node);
 	voltdm_add_pwrdm(voltdm, pwrdm);
 
+	mutex_init(&pwrdm->lock);
 	list_add(&pwrdm->node, &pwrdm_list);
 
 	/* Initialize the powerdomain's state counter */
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index 8f88d65..bab84fc 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -19,7 +19,7 @@
 
 #include <linux/types.h>
 #include <linux/list.h>
-
+#include <linux/mutex.h>
 #include <linux/atomic.h>
 
 #include <plat/cpu.h>
@@ -116,6 +116,7 @@ struct powerdomain {
 	struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
 	struct list_head node;
 	struct list_head voltdm_node;
+	struct mutex lock;
 	int state;
 	unsigned state_counter[PWRDM_MAX_PWRSTS];
 	unsigned ret_logic_off_counter;
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 1/8] ARM: OMAP2+: PM: protect the power domain state change by a mutex
@ 2012-06-14 14:53   ` Jean Pihet
  0 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-arm-kernel

omap_set_pwrdm_state is intented to be the only API for changing
a power domain state.
This patch protects the power domains settings and structs from
concurrent accesses to the function by using a mutex.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/pm.c          |    8 ++++++--
 arch/arm/mach-omap2/powerdomain.c |    1 +
 arch/arm/mach-omap2/powerdomain.h |    3 ++-
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 9cb5ced..a05f00c 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -100,15 +100,17 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
 	if (!pwrdm || IS_ERR(pwrdm))
 		return -EINVAL;
 
+	mutex_lock(&pwrdm->lock);
+
 	while (!(pwrdm->pwrsts & (1 << pwrst))) {
 		if (pwrst == PWRDM_POWER_OFF)
-			return ret;
+			goto out;
 		pwrst--;
 	}
 
 	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
 	if (next_pwrst == pwrst)
-		return ret;
+		goto out;
 
 	curr_pwrst = pwrdm_read_pwrst(pwrdm);
 	if (curr_pwrst < PWRDM_POWER_ON) {
@@ -141,6 +143,8 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
 		break;
 	}
 
+out:
+	mutex_unlock(&pwrdm->lock);
 	return ret;
 }
 
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 9611490..1641e72 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -102,6 +102,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
 	INIT_LIST_HEAD(&pwrdm->voltdm_node);
 	voltdm_add_pwrdm(voltdm, pwrdm);
 
+	mutex_init(&pwrdm->lock);
 	list_add(&pwrdm->node, &pwrdm_list);
 
 	/* Initialize the powerdomain's state counter */
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index 8f88d65..bab84fc 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -19,7 +19,7 @@
 
 #include <linux/types.h>
 #include <linux/list.h>
-
+#include <linux/mutex.h>
 #include <linux/atomic.h>
 
 #include <plat/cpu.h>
@@ -116,6 +116,7 @@ struct powerdomain {
 	struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
 	struct list_head node;
 	struct list_head voltdm_node;
+	struct mutex lock;
 	int state;
 	unsigned state_counter[PWRDM_MAX_PWRSTS];
 	unsigned ret_logic_off_counter;
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
  2012-06-14 14:53 ` Jean Pihet
@ 2012-06-14 14:53   ` Jean Pihet
  -1 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-omap, paul, linux-arm-kernel, khilman; +Cc: Jean Pihet

Introduce functional (or logical) states for power domains and the
API functions to read the power domains settings and to convert
between the functional (i.e. logical) and the internal (or registers)
values.

OMAP2, OMAP3 and OMAP4 platforms are defining a conversion routine.

In the new API only the function omap_set_pwrdm_state shall be used
to change a power domain target state, along with the associated
PWRDM_FUNC_* macros as the state parameters.
While at it the function is moved to the power domains code.

The power domain API in powerdomain.h is split in the external and the
internal parts; only the external API functions and defines shall be used
by external code, the internal API is only to be used in powerdomain*.[ch]
files.

The memory and logic states are not using the functional states, this
comes as a subsequent patch.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/pm.c                   |   66 -----------
 arch/arm/mach-omap2/pm.h                   |    1 -
 arch/arm/mach-omap2/powerdomain-common.c   |   71 +++++++++++
 arch/arm/mach-omap2/powerdomain.c          |  174 ++++++++++++++++++++++++++++
 arch/arm/mach-omap2/powerdomain.h          |   77 +++++++++----
 arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |    5 +
 arch/arm/mach-omap2/powerdomain44xx.c      |    2 +
 7 files changed, 306 insertions(+), 90 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index a05f00c..dfe702b 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -74,10 +74,6 @@ static void __init omap2_init_processor_devices(void)
 	}
 }
 
-/* Types of sleep_switch used in omap_set_pwrdm_state */
-#define FORCEWAKEUP_SWITCH	0
-#define LOWPOWERSTATE_SWITCH	1
-
 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
 	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
@@ -89,68 +85,6 @@ int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 }
 
 /*
- * This sets pwrdm state (other than mpu & core. Currently only ON &
- * RET are supported.
- */
-int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
-{
-	u8 curr_pwrst, next_pwrst;
-	int sleep_switch = -1, ret = 0, hwsup = 0;
-
-	if (!pwrdm || IS_ERR(pwrdm))
-		return -EINVAL;
-
-	mutex_lock(&pwrdm->lock);
-
-	while (!(pwrdm->pwrsts & (1 << pwrst))) {
-		if (pwrst == PWRDM_POWER_OFF)
-			goto out;
-		pwrst--;
-	}
-
-	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
-	if (next_pwrst == pwrst)
-		goto out;
-
-	curr_pwrst = pwrdm_read_pwrst(pwrdm);
-	if (curr_pwrst < PWRDM_POWER_ON) {
-		if ((curr_pwrst > pwrst) &&
-			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
-			sleep_switch = LOWPOWERSTATE_SWITCH;
-		} else {
-			hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
-			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
-			sleep_switch = FORCEWAKEUP_SWITCH;
-		}
-	}
-
-	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
-	if (ret)
-		pr_err("%s: unable to set power state of powerdomain: %s\n",
-		       __func__, pwrdm->name);
-
-	switch (sleep_switch) {
-	case FORCEWAKEUP_SWITCH:
-		if (hwsup)
-			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
-		else
-			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
-		break;
-	case LOWPOWERSTATE_SWITCH:
-		pwrdm_set_lowpwrstchange(pwrdm);
-		pwrdm_wait_transition(pwrdm);
-		pwrdm_state_switch(pwrdm);
-		break;
-	}
-
-out:
-	mutex_unlock(&pwrdm->lock);
-	return ret;
-}
-
-
-
-/*
  * This API is to be called during init to set the various voltage
  * domains to the voltage as per the opp table. Typically we boot up
  * at the nominal voltage. So this function finds out the rate of
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 7856489..5bc0848 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -18,7 +18,6 @@
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
-extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap3_idle_init(void);
 extern int omap4_idle_init(void);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
diff --git a/arch/arm/mach-omap2/powerdomain-common.c b/arch/arm/mach-omap2/powerdomain-common.c
index c0aeabf..2973be7 100644
--- a/arch/arm/mach-omap2/powerdomain-common.c
+++ b/arch/arm/mach-omap2/powerdomain-common.c
@@ -108,3 +108,74 @@ u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank)
 	return 0;
 }
 
+/**
+ * omap2_pwrdm_func_to_pwrst - Convert functional (i.e. logical) to
+ * internal (i.e. registers) values for the power domains states.
+ * @struct powerdomain * to convert the values for
+ * @func_pwrst: functional power state
+ *
+ * Returns the internal power state value for the power domain, or
+ * -EINVAL in case of invalid parameters passed in.
+ */
+int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
+{
+	int ret;
+
+	switch (func_pwrst) {
+	case PWRDM_FUNC_PWRST_ON:
+		ret = PWRDM_POWER_ON;
+		break;
+	case PWRDM_FUNC_PWRST_INACTIVE:
+		ret = PWRDM_POWER_INACTIVE;
+		break;
+	case PWRDM_FUNC_PWRST_CSWR:
+	case PWRDM_FUNC_PWRST_OSWR:
+		ret = PWRDM_POWER_RET;
+		break;
+	case PWRDM_FUNC_PWRST_OFF:
+		ret = PWRDM_POWER_OFF;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/**
+ * omap2_pwrdm_pwrst_to_func - Convert internal (i.e. registers) to
+ * functional (i.e. logical) values for the power domains states.
+ * @struct powerdomain * to convert the values for
+ * @pwrst: internal power state
+ *
+ * Returns the functional power state value for the power domain, or
+ * -EINVAL in case of invalid parameters passed in.
+ */
+int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
+{
+	int ret;
+
+	switch (pwrst) {
+	case PWRDM_POWER_ON:
+		ret = PWRDM_FUNC_PWRST_ON;
+		break;
+	case PWRDM_POWER_INACTIVE:
+		ret = PWRDM_FUNC_PWRST_INACTIVE;
+		break;
+	case PWRDM_POWER_RET:
+		/*
+		 * XXX warning: return OSWR in case of pd in RET and
+		 * logic in OFF
+		 */
+		ret = PWRDM_FUNC_PWRST_CSWR;
+		break;
+	case PWRDM_POWER_OFF:
+		ret = PWRDM_FUNC_PWRST_OFF;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 1641e72..e79b5ae 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -466,6 +466,135 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
 }
 
 /**
+ * pwrdm_func_to_pwrst - get the internal (i.e. registers) value mapped
+ * to the functional state
+ * @pwrdm: struct powerdomain * to query
+ * @func_pwrst: functional power state
+ *
+ * Convert the functional power state to the platform specific power
+ * domain state value.
+ * Returns the internal power domain state value or -EINVAL in case
+ * of invalid parameters passed in.
+ */
+int pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
+{
+	int ret = func_pwrst;
+
+	if ((!pwrdm) || (func_pwrst >= PWRDM_MAX_FUNC_PWRSTS))
+		return -EINVAL;
+
+	if (arch_pwrdm && arch_pwrdm->pwrdm_func_to_pwrst)
+		ret = arch_pwrdm->pwrdm_func_to_pwrst(pwrdm, func_pwrst);
+
+	pr_debug("powerdomain: convert func %0x to pwrst %0x for %s\n",
+		 func_pwrst, ret, pwrdm->name);
+
+	return ret;
+}
+
+/**
+ * pwrdm_pwrst_to_func - get the functional (i.e. logical) value mapped
+ * to the internal state
+ * @pwrdm: struct powerdomain * to query
+ * @pwrst: internal power state
+ *
+ * Convert the internal power state to the power domain functional value.
+ * Returns the functional power domain state value or -EINVAL in case
+ * of invalid parameters passed in.
+ */
+int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
+{
+	int ret = pwrst;
+
+	if ((!pwrdm) || (pwrst >= PWRDM_MAX_PWRSTS))
+		return -EINVAL;
+
+	pr_debug("powerdomain: convert %0x pwrst to func for %s\n",
+		 pwrst, pwrdm->name);
+
+	if (arch_pwrdm && arch_pwrdm->pwrdm_pwrst_to_func)
+		ret = arch_pwrdm->pwrdm_pwrst_to_func(pwrdm, pwrst);
+
+	return ret;
+}
+
+/* Types of sleep_switch used in omap_set_pwrdm_state */
+#define FORCEWAKEUP_SWITCH	0
+#define LOWPOWERSTATE_SWITCH	1
+
+/**
+ * omap_set_pwrdm_state - program next powerdomain power state
+ * @pwrdm: struct powerdomain * to set
+ * @func_pwrst: power domain functional state, one of the PWRDM_FUNC_* macros
+ *
+ * This programs the pwrdm next functional state, sets the dependencies
+ * and waits for the state to be applied.
+ */
+int omap_set_pwrdm_state(struct powerdomain *pwrdm,
+			 enum pwrdm_func_state func_pwrst)
+{
+	u8 curr_pwrst, next_pwrst;
+	int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
+	int sleep_switch = -1, ret = 0, hwsup = 0;
+
+	if (!pwrdm || IS_ERR(pwrdm) || (pwrst < 0)) {
+		pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
+			 __func__, pwrdm, func_pwrst);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: set func_pwrst %0x to pwrdm %s\n",
+		 __func__, func_pwrst, pwrdm->name);
+
+	mutex_lock(&pwrdm->lock);
+
+	while (!(pwrdm->pwrsts & (1 << pwrst))) {
+		if (pwrst == PWRDM_POWER_OFF)
+			goto out;
+		pwrst--;
+	}
+
+	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
+	if (next_pwrst == pwrst)
+		goto out;
+
+	curr_pwrst = pwrdm_read_pwrst(pwrdm);
+	if (curr_pwrst < PWRDM_POWER_ON) {
+		if ((curr_pwrst > pwrst) &&
+			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
+			sleep_switch = LOWPOWERSTATE_SWITCH;
+		} else {
+			hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
+			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+			sleep_switch = FORCEWAKEUP_SWITCH;
+		}
+	}
+
+	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
+	if (ret)
+		pr_err("%s: unable to set power state of powerdomain: %s\n",
+		       __func__, pwrdm->name);
+
+	switch (sleep_switch) {
+	case FORCEWAKEUP_SWITCH:
+		if (hwsup)
+			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+		else
+			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
+		break;
+	case LOWPOWERSTATE_SWITCH:
+		pwrdm_set_lowpwrstchange(pwrdm);
+		pwrdm_wait_transition(pwrdm);
+		pwrdm_state_switch(pwrdm);
+		break;
+	}
+
+out:
+	mutex_unlock(&pwrdm->lock);
+	return ret;
+}
+
+/**
  * pwrdm_set_next_pwrst - set next powerdomain power state
  * @pwrdm: struct powerdomain * to set
  * @pwrst: one of the PWRDM_POWER_* macros
@@ -522,6 +651,21 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
 }
 
 /**
+ * pwrdm_read_next_func_pwrst - get next powerdomain functional power state
+ * @pwrdm: struct powerdomain * to get power state
+ *
+ * Return the powerdomain @pwrdm's next functional power state.
+ * Returns -EINVAL if the powerdomain pointer is null or returns
+ * the next power state upon success.
+ */
+int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm)
+{
+	int ret = pwrdm_read_next_pwrst(pwrdm);
+
+	return pwrdm_pwrst_to_func(pwrdm, ret);
+}
+
+/**
  * pwrdm_read_pwrst - get current powerdomain power state
  * @pwrdm: struct powerdomain * to get power state
  *
@@ -543,6 +687,21 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm)
 }
 
 /**
+ * pwrdm_read_func_pwrst - get current powerdomain functional power state
+ * @pwrdm: struct powerdomain * to get power state
+ *
+ * Return the powerdomain @pwrdm's current functional power state.
+ * Returns -EINVAL if the powerdomain pointer is null or returns
+ * the current power state upon success.
+ */
+int pwrdm_read_func_pwrst(struct powerdomain *pwrdm)
+{
+	int ret = pwrdm_read_pwrst(pwrdm);
+
+	return pwrdm_pwrst_to_func(pwrdm, ret);
+}
+
+/**
  * pwrdm_read_prev_pwrst - get previous powerdomain power state
  * @pwrdm: struct powerdomain * to get previous power state
  *
@@ -564,6 +723,21 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
 }
 
 /**
+ * pwrdm_read_prev_func_pwrst - get previous powerdomain functional power state
+ * @pwrdm: struct powerdomain * to get previous power state
+ *
+ * Return the powerdomain @pwrdm's previous functional power state.
+ * Returns -EINVAL if the powerdomain pointer is null or returns the
+ * previous power state upon success.
+ */
+int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm)
+{
+	int ret = pwrdm_read_prev_pwrst(pwrdm);
+
+	return pwrdm_pwrst_to_func(pwrdm, ret);
+}
+
+/**
  * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
  * @pwrdm: struct powerdomain * to set
  * @pwrst: one of the PWRDM_POWER_* macros
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index bab84fc..0404f9f 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -9,9 +9,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * XXX This should be moved to the mach-omap2/ directory at the earliest
- * opportunity.
  */
 
 #ifndef __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H
@@ -26,7 +23,51 @@
 
 #include "voltage.h"
 
-/* Powerdomain basic power states */
+/***************************************************************
+ * External API
+ ***************************************************************/
+
+/* Powerdomain functional power states, used by the external API functions */
+enum pwrdm_func_state {
+	PWRDM_FUNC_PWRST_OFF		= 0x0,
+	PWRDM_FUNC_PWRST_OSWR,
+	PWRDM_FUNC_PWRST_CSWR,
+	PWRDM_FUNC_PWRST_INACTIVE,
+	PWRDM_FUNC_PWRST_ON,
+	PWRDM_MAX_FUNC_PWRSTS		/* Last value, used as the max value */
+};
+
+struct clockdomain;
+struct powerdomain;
+
+struct powerdomain *pwrdm_lookup(const char *name);
+
+int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
+			void *user);
+int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
+			void *user);
+
+struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
+
+int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
+
+int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm);
+int pwrdm_read_func_pwrst(struct powerdomain *pwrdm);
+int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm);
+extern int omap_set_pwrdm_state(struct powerdomain *pwrdm,
+				enum pwrdm_func_state func_pwrst);
+
+extern void omap242x_powerdomains_init(void);
+extern void omap243x_powerdomains_init(void);
+extern void omap3xxx_powerdomains_init(void);
+extern void omap44xx_powerdomains_init(void);
+
+
+/***************************************************************
+ * Internal code, only used in powerdomain*.[ch]
+ ***************************************************************/
+
+/* Powerdomain internal power states, internal use only */
 #define PWRDM_POWER_OFF		0x0
 #define PWRDM_POWER_RET		0x1
 #define PWRDM_POWER_INACTIVE	0x2
@@ -45,7 +86,6 @@
 #define PWRSTS_RET_ON		(PWRSTS_RET | PWRSTS_ON)
 #define PWRSTS_OFF_RET_ON	(PWRSTS_OFF_RET | PWRSTS_ON)
 
-
 /* Powerdomain flags */
 #define PWRDM_HAS_HDWR_SAR	(1 << 0) /* hardware save-and-restore support */
 #define PWRDM_HAS_MPU_QUIRK	(1 << 1) /* MPU pwr domain has MEM bank 0 bits
@@ -74,9 +114,6 @@
 /* XXX A completely arbitrary number. What is reasonable here? */
 #define PWRDM_TRANSITION_BAILOUT 100000
 
-struct clockdomain;
-struct powerdomain;
-
 /**
  * struct powerdomain - OMAP powerdomain
  * @name: Powerdomain name
@@ -130,6 +167,10 @@ struct powerdomain {
 
 /**
  * struct pwrdm_ops - Arch specific function implementations
+ * @pwrdm_func_to_pwrst: Convert the pd functional power state to
+ *  the internal state
+ * @pwrdm_pwrst_to_func: Convert the pd internal power state to
+ *  the functional state
  * @pwrdm_set_next_pwrst: Set the target power state for a pd
  * @pwrdm_read_next_pwrst: Read the target power state set for a pd
  * @pwrdm_read_pwrst: Read the current power state of a pd
@@ -150,6 +191,8 @@ struct powerdomain {
  * @pwrdm_wait_transition: Wait for a pd state transition to complete
  */
 struct pwrdm_ops {
+	int	(*pwrdm_func_to_pwrst)(struct powerdomain *pwrdm, u8 func_pwrst);
+	int	(*pwrdm_pwrst_to_func)(struct powerdomain *pwrdm, u8 func_pwrst);
 	int	(*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst);
 	int	(*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm);
 	int	(*pwrdm_read_pwrst)(struct powerdomain *pwrdm);
@@ -174,21 +217,11 @@ int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
 int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list);
 int pwrdm_complete_init(void);
 
-struct powerdomain *pwrdm_lookup(const char *name);
-
-int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
-			void *user);
-int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
-			void *user);
-
 int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
 int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
 int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
 			 int (*fn)(struct powerdomain *pwrdm,
 				   struct clockdomain *clkdm));
-struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
-
-int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
 
 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
 int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
@@ -196,6 +229,9 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm);
 int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
 int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
 
+int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
+int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst);
+
 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
 int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
@@ -220,11 +256,6 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
-extern void omap242x_powerdomains_init(void);
-extern void omap243x_powerdomains_init(void);
-extern void omap3xxx_powerdomains_init(void);
-extern void omap44xx_powerdomains_init(void);
-
 extern struct pwrdm_ops omap2_pwrdm_operations;
 extern struct pwrdm_ops omap3_pwrdm_operations;
 extern struct pwrdm_ops omap4_pwrdm_operations;
diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
index 0f0a9f1..79c1293 100644
--- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
@@ -26,6 +26,7 @@
 
 
 /* Common functions across OMAP2 and OMAP3 */
+
 static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 {
 	omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
@@ -210,6 +211,8 @@ static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
 }
 
 struct pwrdm_ops omap2_pwrdm_operations = {
+	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
 	.pwrdm_read_pwrst	= omap2_pwrdm_read_pwrst,
@@ -222,6 +225,8 @@ struct pwrdm_ops omap2_pwrdm_operations = {
 };
 
 struct pwrdm_ops omap3_pwrdm_operations = {
+	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
 	.pwrdm_read_pwrst	= omap2_pwrdm_read_pwrst,
diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
index 601325b..538b528 100644
--- a/arch/arm/mach-omap2/powerdomain44xx.c
+++ b/arch/arm/mach-omap2/powerdomain44xx.c
@@ -209,6 +209,8 @@ static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
 }
 
 struct pwrdm_ops omap4_pwrdm_operations = {
+	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap4_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap4_pwrdm_read_next_pwrst,
 	.pwrdm_read_pwrst	= omap4_pwrdm_read_pwrst,
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
@ 2012-06-14 14:53   ` Jean Pihet
  0 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-arm-kernel

Introduce functional (or logical) states for power domains and the
API functions to read the power domains settings and to convert
between the functional (i.e. logical) and the internal (or registers)
values.

OMAP2, OMAP3 and OMAP4 platforms are defining a conversion routine.

In the new API only the function omap_set_pwrdm_state shall be used
to change a power domain target state, along with the associated
PWRDM_FUNC_* macros as the state parameters.
While at it the function is moved to the power domains code.

The power domain API in powerdomain.h is split in the external and the
internal parts; only the external API functions and defines shall be used
by external code, the internal API is only to be used in powerdomain*.[ch]
files.

The memory and logic states are not using the functional states, this
comes as a subsequent patch.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/pm.c                   |   66 -----------
 arch/arm/mach-omap2/pm.h                   |    1 -
 arch/arm/mach-omap2/powerdomain-common.c   |   71 +++++++++++
 arch/arm/mach-omap2/powerdomain.c          |  174 ++++++++++++++++++++++++++++
 arch/arm/mach-omap2/powerdomain.h          |   77 +++++++++----
 arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |    5 +
 arch/arm/mach-omap2/powerdomain44xx.c      |    2 +
 7 files changed, 306 insertions(+), 90 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index a05f00c..dfe702b 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -74,10 +74,6 @@ static void __init omap2_init_processor_devices(void)
 	}
 }
 
-/* Types of sleep_switch used in omap_set_pwrdm_state */
-#define FORCEWAKEUP_SWITCH	0
-#define LOWPOWERSTATE_SWITCH	1
-
 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
 	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
@@ -89,68 +85,6 @@ int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 }
 
 /*
- * This sets pwrdm state (other than mpu & core. Currently only ON &
- * RET are supported.
- */
-int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
-{
-	u8 curr_pwrst, next_pwrst;
-	int sleep_switch = -1, ret = 0, hwsup = 0;
-
-	if (!pwrdm || IS_ERR(pwrdm))
-		return -EINVAL;
-
-	mutex_lock(&pwrdm->lock);
-
-	while (!(pwrdm->pwrsts & (1 << pwrst))) {
-		if (pwrst == PWRDM_POWER_OFF)
-			goto out;
-		pwrst--;
-	}
-
-	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
-	if (next_pwrst == pwrst)
-		goto out;
-
-	curr_pwrst = pwrdm_read_pwrst(pwrdm);
-	if (curr_pwrst < PWRDM_POWER_ON) {
-		if ((curr_pwrst > pwrst) &&
-			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
-			sleep_switch = LOWPOWERSTATE_SWITCH;
-		} else {
-			hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
-			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
-			sleep_switch = FORCEWAKEUP_SWITCH;
-		}
-	}
-
-	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
-	if (ret)
-		pr_err("%s: unable to set power state of powerdomain: %s\n",
-		       __func__, pwrdm->name);
-
-	switch (sleep_switch) {
-	case FORCEWAKEUP_SWITCH:
-		if (hwsup)
-			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
-		else
-			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
-		break;
-	case LOWPOWERSTATE_SWITCH:
-		pwrdm_set_lowpwrstchange(pwrdm);
-		pwrdm_wait_transition(pwrdm);
-		pwrdm_state_switch(pwrdm);
-		break;
-	}
-
-out:
-	mutex_unlock(&pwrdm->lock);
-	return ret;
-}
-
-
-
-/*
  * This API is to be called during init to set the various voltage
  * domains to the voltage as per the opp table. Typically we boot up
  * at the nominal voltage. So this function finds out the rate of
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 7856489..5bc0848 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -18,7 +18,6 @@
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
-extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap3_idle_init(void);
 extern int omap4_idle_init(void);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
diff --git a/arch/arm/mach-omap2/powerdomain-common.c b/arch/arm/mach-omap2/powerdomain-common.c
index c0aeabf..2973be7 100644
--- a/arch/arm/mach-omap2/powerdomain-common.c
+++ b/arch/arm/mach-omap2/powerdomain-common.c
@@ -108,3 +108,74 @@ u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank)
 	return 0;
 }
 
+/**
+ * omap2_pwrdm_func_to_pwrst - Convert functional (i.e. logical) to
+ * internal (i.e. registers) values for the power domains states.
+ * @struct powerdomain * to convert the values for
+ * @func_pwrst: functional power state
+ *
+ * Returns the internal power state value for the power domain, or
+ * -EINVAL in case of invalid parameters passed in.
+ */
+int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
+{
+	int ret;
+
+	switch (func_pwrst) {
+	case PWRDM_FUNC_PWRST_ON:
+		ret = PWRDM_POWER_ON;
+		break;
+	case PWRDM_FUNC_PWRST_INACTIVE:
+		ret = PWRDM_POWER_INACTIVE;
+		break;
+	case PWRDM_FUNC_PWRST_CSWR:
+	case PWRDM_FUNC_PWRST_OSWR:
+		ret = PWRDM_POWER_RET;
+		break;
+	case PWRDM_FUNC_PWRST_OFF:
+		ret = PWRDM_POWER_OFF;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/**
+ * omap2_pwrdm_pwrst_to_func - Convert internal (i.e. registers) to
+ * functional (i.e. logical) values for the power domains states.
+ * @struct powerdomain * to convert the values for
+ * @pwrst: internal power state
+ *
+ * Returns the functional power state value for the power domain, or
+ * -EINVAL in case of invalid parameters passed in.
+ */
+int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
+{
+	int ret;
+
+	switch (pwrst) {
+	case PWRDM_POWER_ON:
+		ret = PWRDM_FUNC_PWRST_ON;
+		break;
+	case PWRDM_POWER_INACTIVE:
+		ret = PWRDM_FUNC_PWRST_INACTIVE;
+		break;
+	case PWRDM_POWER_RET:
+		/*
+		 * XXX warning: return OSWR in case of pd in RET and
+		 * logic in OFF
+		 */
+		ret = PWRDM_FUNC_PWRST_CSWR;
+		break;
+	case PWRDM_POWER_OFF:
+		ret = PWRDM_FUNC_PWRST_OFF;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 1641e72..e79b5ae 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -466,6 +466,135 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
 }
 
 /**
+ * pwrdm_func_to_pwrst - get the internal (i.e. registers) value mapped
+ * to the functional state
+ * @pwrdm: struct powerdomain * to query
+ * @func_pwrst: functional power state
+ *
+ * Convert the functional power state to the platform specific power
+ * domain state value.
+ * Returns the internal power domain state value or -EINVAL in case
+ * of invalid parameters passed in.
+ */
+int pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
+{
+	int ret = func_pwrst;
+
+	if ((!pwrdm) || (func_pwrst >= PWRDM_MAX_FUNC_PWRSTS))
+		return -EINVAL;
+
+	if (arch_pwrdm && arch_pwrdm->pwrdm_func_to_pwrst)
+		ret = arch_pwrdm->pwrdm_func_to_pwrst(pwrdm, func_pwrst);
+
+	pr_debug("powerdomain: convert func %0x to pwrst %0x for %s\n",
+		 func_pwrst, ret, pwrdm->name);
+
+	return ret;
+}
+
+/**
+ * pwrdm_pwrst_to_func - get the functional (i.e. logical) value mapped
+ * to the internal state
+ * @pwrdm: struct powerdomain * to query
+ * @pwrst: internal power state
+ *
+ * Convert the internal power state to the power domain functional value.
+ * Returns the functional power domain state value or -EINVAL in case
+ * of invalid parameters passed in.
+ */
+int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
+{
+	int ret = pwrst;
+
+	if ((!pwrdm) || (pwrst >= PWRDM_MAX_PWRSTS))
+		return -EINVAL;
+
+	pr_debug("powerdomain: convert %0x pwrst to func for %s\n",
+		 pwrst, pwrdm->name);
+
+	if (arch_pwrdm && arch_pwrdm->pwrdm_pwrst_to_func)
+		ret = arch_pwrdm->pwrdm_pwrst_to_func(pwrdm, pwrst);
+
+	return ret;
+}
+
+/* Types of sleep_switch used in omap_set_pwrdm_state */
+#define FORCEWAKEUP_SWITCH	0
+#define LOWPOWERSTATE_SWITCH	1
+
+/**
+ * omap_set_pwrdm_state - program next powerdomain power state
+ * @pwrdm: struct powerdomain * to set
+ * @func_pwrst: power domain functional state, one of the PWRDM_FUNC_* macros
+ *
+ * This programs the pwrdm next functional state, sets the dependencies
+ * and waits for the state to be applied.
+ */
+int omap_set_pwrdm_state(struct powerdomain *pwrdm,
+			 enum pwrdm_func_state func_pwrst)
+{
+	u8 curr_pwrst, next_pwrst;
+	int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
+	int sleep_switch = -1, ret = 0, hwsup = 0;
+
+	if (!pwrdm || IS_ERR(pwrdm) || (pwrst < 0)) {
+		pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
+			 __func__, pwrdm, func_pwrst);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: set func_pwrst %0x to pwrdm %s\n",
+		 __func__, func_pwrst, pwrdm->name);
+
+	mutex_lock(&pwrdm->lock);
+
+	while (!(pwrdm->pwrsts & (1 << pwrst))) {
+		if (pwrst == PWRDM_POWER_OFF)
+			goto out;
+		pwrst--;
+	}
+
+	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
+	if (next_pwrst == pwrst)
+		goto out;
+
+	curr_pwrst = pwrdm_read_pwrst(pwrdm);
+	if (curr_pwrst < PWRDM_POWER_ON) {
+		if ((curr_pwrst > pwrst) &&
+			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
+			sleep_switch = LOWPOWERSTATE_SWITCH;
+		} else {
+			hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
+			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+			sleep_switch = FORCEWAKEUP_SWITCH;
+		}
+	}
+
+	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
+	if (ret)
+		pr_err("%s: unable to set power state of powerdomain: %s\n",
+		       __func__, pwrdm->name);
+
+	switch (sleep_switch) {
+	case FORCEWAKEUP_SWITCH:
+		if (hwsup)
+			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+		else
+			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
+		break;
+	case LOWPOWERSTATE_SWITCH:
+		pwrdm_set_lowpwrstchange(pwrdm);
+		pwrdm_wait_transition(pwrdm);
+		pwrdm_state_switch(pwrdm);
+		break;
+	}
+
+out:
+	mutex_unlock(&pwrdm->lock);
+	return ret;
+}
+
+/**
  * pwrdm_set_next_pwrst - set next powerdomain power state
  * @pwrdm: struct powerdomain * to set
  * @pwrst: one of the PWRDM_POWER_* macros
@@ -522,6 +651,21 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
 }
 
 /**
+ * pwrdm_read_next_func_pwrst - get next powerdomain functional power state
+ * @pwrdm: struct powerdomain * to get power state
+ *
+ * Return the powerdomain @pwrdm's next functional power state.
+ * Returns -EINVAL if the powerdomain pointer is null or returns
+ * the next power state upon success.
+ */
+int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm)
+{
+	int ret = pwrdm_read_next_pwrst(pwrdm);
+
+	return pwrdm_pwrst_to_func(pwrdm, ret);
+}
+
+/**
  * pwrdm_read_pwrst - get current powerdomain power state
  * @pwrdm: struct powerdomain * to get power state
  *
@@ -543,6 +687,21 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm)
 }
 
 /**
+ * pwrdm_read_func_pwrst - get current powerdomain functional power state
+ * @pwrdm: struct powerdomain * to get power state
+ *
+ * Return the powerdomain @pwrdm's current functional power state.
+ * Returns -EINVAL if the powerdomain pointer is null or returns
+ * the current power state upon success.
+ */
+int pwrdm_read_func_pwrst(struct powerdomain *pwrdm)
+{
+	int ret = pwrdm_read_pwrst(pwrdm);
+
+	return pwrdm_pwrst_to_func(pwrdm, ret);
+}
+
+/**
  * pwrdm_read_prev_pwrst - get previous powerdomain power state
  * @pwrdm: struct powerdomain * to get previous power state
  *
@@ -564,6 +723,21 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
 }
 
 /**
+ * pwrdm_read_prev_func_pwrst - get previous powerdomain functional power state
+ * @pwrdm: struct powerdomain * to get previous power state
+ *
+ * Return the powerdomain @pwrdm's previous functional power state.
+ * Returns -EINVAL if the powerdomain pointer is null or returns the
+ * previous power state upon success.
+ */
+int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm)
+{
+	int ret = pwrdm_read_prev_pwrst(pwrdm);
+
+	return pwrdm_pwrst_to_func(pwrdm, ret);
+}
+
+/**
  * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
  * @pwrdm: struct powerdomain * to set
  * @pwrst: one of the PWRDM_POWER_* macros
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index bab84fc..0404f9f 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -9,9 +9,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * XXX This should be moved to the mach-omap2/ directory at the earliest
- * opportunity.
  */
 
 #ifndef __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H
@@ -26,7 +23,51 @@
 
 #include "voltage.h"
 
-/* Powerdomain basic power states */
+/***************************************************************
+ * External API
+ ***************************************************************/
+
+/* Powerdomain functional power states, used by the external API functions */
+enum pwrdm_func_state {
+	PWRDM_FUNC_PWRST_OFF		= 0x0,
+	PWRDM_FUNC_PWRST_OSWR,
+	PWRDM_FUNC_PWRST_CSWR,
+	PWRDM_FUNC_PWRST_INACTIVE,
+	PWRDM_FUNC_PWRST_ON,
+	PWRDM_MAX_FUNC_PWRSTS		/* Last value, used as the max value */
+};
+
+struct clockdomain;
+struct powerdomain;
+
+struct powerdomain *pwrdm_lookup(const char *name);
+
+int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
+			void *user);
+int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
+			void *user);
+
+struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
+
+int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
+
+int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm);
+int pwrdm_read_func_pwrst(struct powerdomain *pwrdm);
+int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm);
+extern int omap_set_pwrdm_state(struct powerdomain *pwrdm,
+				enum pwrdm_func_state func_pwrst);
+
+extern void omap242x_powerdomains_init(void);
+extern void omap243x_powerdomains_init(void);
+extern void omap3xxx_powerdomains_init(void);
+extern void omap44xx_powerdomains_init(void);
+
+
+/***************************************************************
+ * Internal code, only used in powerdomain*.[ch]
+ ***************************************************************/
+
+/* Powerdomain internal power states, internal use only */
 #define PWRDM_POWER_OFF		0x0
 #define PWRDM_POWER_RET		0x1
 #define PWRDM_POWER_INACTIVE	0x2
@@ -45,7 +86,6 @@
 #define PWRSTS_RET_ON		(PWRSTS_RET | PWRSTS_ON)
 #define PWRSTS_OFF_RET_ON	(PWRSTS_OFF_RET | PWRSTS_ON)
 
-
 /* Powerdomain flags */
 #define PWRDM_HAS_HDWR_SAR	(1 << 0) /* hardware save-and-restore support */
 #define PWRDM_HAS_MPU_QUIRK	(1 << 1) /* MPU pwr domain has MEM bank 0 bits
@@ -74,9 +114,6 @@
 /* XXX A completely arbitrary number. What is reasonable here? */
 #define PWRDM_TRANSITION_BAILOUT 100000
 
-struct clockdomain;
-struct powerdomain;
-
 /**
  * struct powerdomain - OMAP powerdomain
  * @name: Powerdomain name
@@ -130,6 +167,10 @@ struct powerdomain {
 
 /**
  * struct pwrdm_ops - Arch specific function implementations
+ * @pwrdm_func_to_pwrst: Convert the pd functional power state to
+ *  the internal state
+ * @pwrdm_pwrst_to_func: Convert the pd internal power state to
+ *  the functional state
  * @pwrdm_set_next_pwrst: Set the target power state for a pd
  * @pwrdm_read_next_pwrst: Read the target power state set for a pd
  * @pwrdm_read_pwrst: Read the current power state of a pd
@@ -150,6 +191,8 @@ struct powerdomain {
  * @pwrdm_wait_transition: Wait for a pd state transition to complete
  */
 struct pwrdm_ops {
+	int	(*pwrdm_func_to_pwrst)(struct powerdomain *pwrdm, u8 func_pwrst);
+	int	(*pwrdm_pwrst_to_func)(struct powerdomain *pwrdm, u8 func_pwrst);
 	int	(*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst);
 	int	(*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm);
 	int	(*pwrdm_read_pwrst)(struct powerdomain *pwrdm);
@@ -174,21 +217,11 @@ int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
 int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list);
 int pwrdm_complete_init(void);
 
-struct powerdomain *pwrdm_lookup(const char *name);
-
-int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
-			void *user);
-int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
-			void *user);
-
 int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
 int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
 int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
 			 int (*fn)(struct powerdomain *pwrdm,
 				   struct clockdomain *clkdm));
-struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
-
-int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
 
 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
 int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
@@ -196,6 +229,9 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm);
 int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
 int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
 
+int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
+int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst);
+
 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
 int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
@@ -220,11 +256,6 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
-extern void omap242x_powerdomains_init(void);
-extern void omap243x_powerdomains_init(void);
-extern void omap3xxx_powerdomains_init(void);
-extern void omap44xx_powerdomains_init(void);
-
 extern struct pwrdm_ops omap2_pwrdm_operations;
 extern struct pwrdm_ops omap3_pwrdm_operations;
 extern struct pwrdm_ops omap4_pwrdm_operations;
diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
index 0f0a9f1..79c1293 100644
--- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
@@ -26,6 +26,7 @@
 
 
 /* Common functions across OMAP2 and OMAP3 */
+
 static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 {
 	omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
@@ -210,6 +211,8 @@ static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
 }
 
 struct pwrdm_ops omap2_pwrdm_operations = {
+	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
 	.pwrdm_read_pwrst	= omap2_pwrdm_read_pwrst,
@@ -222,6 +225,8 @@ struct pwrdm_ops omap2_pwrdm_operations = {
 };
 
 struct pwrdm_ops omap3_pwrdm_operations = {
+	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
 	.pwrdm_read_pwrst	= omap2_pwrdm_read_pwrst,
diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
index 601325b..538b528 100644
--- a/arch/arm/mach-omap2/powerdomain44xx.c
+++ b/arch/arm/mach-omap2/powerdomain44xx.c
@@ -209,6 +209,8 @@ static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
 }
 
 struct pwrdm_ops omap4_pwrdm_operations = {
+	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap4_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap4_pwrdm_read_next_pwrst,
 	.pwrdm_read_pwrst	= omap4_pwrdm_read_pwrst,
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 3/8] ARM: OMAP2+: PM: use the functional power states API
  2012-06-14 14:53 ` Jean Pihet
@ 2012-06-14 14:53   ` Jean Pihet
  -1 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-omap, paul, linux-arm-kernel, khilman; +Cc: Jean Pihet

Use the functional power states as the API to control power domains.
The omap_set_pwrdm_state function shall be used instead of
pwrdm_set_next_pwrst to control the power domains next states.

Note: the internal code for power domains state management still
uses the internal power states.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/cpuidle34xx.c         |   61 +++++++++++-----------
 arch/arm/mach-omap2/cpuidle44xx.c         |   25 +++++-----
 arch/arm/mach-omap2/omap-hotplug.c        |    2 +-
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   43 +++++++++-------
 arch/arm/mach-omap2/pm24xx.c              |   10 ++--
 arch/arm/mach-omap2/pm34xx.c              |   78 +++++++++++++++--------------
 arch/arm/mach-omap2/pm44xx.c              |    8 ++--
 arch/arm/mach-omap2/powerdomain.c         |    2 +-
 8 files changed, 119 insertions(+), 110 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 207bc1c..ef8d7d4 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -46,32 +46,32 @@ struct omap3_idle_statedata {
 
 static struct omap3_idle_statedata omap3_idle_data[] = {
 	{
-		.mpu_state = PWRDM_POWER_ON,
-		.core_state = PWRDM_POWER_ON,
+		.mpu_state = PWRDM_FUNC_PWRST_ON,
+		.core_state = PWRDM_FUNC_PWRST_ON,
 	},
 	{
-		.mpu_state = PWRDM_POWER_ON,
-		.core_state = PWRDM_POWER_ON,
+		.mpu_state = PWRDM_FUNC_PWRST_ON,
+		.core_state = PWRDM_FUNC_PWRST_ON,
 	},
 	{
-		.mpu_state = PWRDM_POWER_RET,
-		.core_state = PWRDM_POWER_ON,
+		.mpu_state = PWRDM_FUNC_PWRST_CSWR,
+		.core_state = PWRDM_FUNC_PWRST_ON,
 	},
 	{
-		.mpu_state = PWRDM_POWER_OFF,
-		.core_state = PWRDM_POWER_ON,
+		.mpu_state = PWRDM_FUNC_PWRST_OFF,
+		.core_state = PWRDM_FUNC_PWRST_ON,
 	},
 	{
-		.mpu_state = PWRDM_POWER_RET,
-		.core_state = PWRDM_POWER_RET,
+		.mpu_state = PWRDM_FUNC_PWRST_CSWR,
+		.core_state = PWRDM_FUNC_PWRST_CSWR,
 	},
 	{
-		.mpu_state = PWRDM_POWER_OFF,
-		.core_state = PWRDM_POWER_RET,
+		.mpu_state = PWRDM_FUNC_PWRST_OFF,
+		.core_state = PWRDM_FUNC_PWRST_CSWR,
 	},
 	{
-		.mpu_state = PWRDM_POWER_OFF,
-		.core_state = PWRDM_POWER_OFF,
+		.mpu_state = PWRDM_FUNC_PWRST_OFF,
+		.core_state = PWRDM_FUNC_PWRST_OFF,
 	},
 };
 
@@ -100,8 +100,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 
 	local_fiq_disable();
 
-	pwrdm_set_next_pwrst(mpu_pd, mpu_state);
-	pwrdm_set_next_pwrst(core_pd, core_state);
+	omap_set_pwrdm_state(mpu_pd, mpu_state);
+	omap_set_pwrdm_state(core_pd, core_state);
 
 	if (omap_irq_pending() || need_resched())
 		goto return_sleep_time;
@@ -116,7 +116,7 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 	 * Call idle CPU PM enter notifier chain so that
 	 * VFP context is saved.
 	 */
-	if (mpu_state == PWRDM_POWER_OFF)
+	if (mpu_state == PWRDM_FUNC_PWRST_OFF)
 		cpu_pm_enter();
 
 	/* Execute ARM wfi */
@@ -126,7 +126,7 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 	 * Call idle CPU PM enter notifier chain to restore
 	 * VFP context.
 	 */
-	if (pwrdm_read_prev_pwrst(mpu_pd) == PWRDM_POWER_OFF)
+	if (pwrdm_read_prev_func_pwrst(mpu_pd) == PWRDM_FUNC_PWRST_OFF)
 		cpu_pm_exit();
 
 	/* Re-allow idle for C1 */
@@ -175,20 +175,20 @@ static int next_valid_state(struct cpuidle_device *dev,
 			    struct cpuidle_driver *drv, int index)
 {
 	struct omap3_idle_statedata *cx = &omap3_idle_data[index];
-	u32 mpu_deepest_state = PWRDM_POWER_RET;
-	u32 core_deepest_state = PWRDM_POWER_RET;
+	u32 mpu_deepest_state = PWRDM_FUNC_PWRST_CSWR;
+	u32 core_deepest_state = PWRDM_FUNC_PWRST_CSWR;
 	int idx;
 	int next_index = -1;
 
 	if (enable_off_mode) {
-		mpu_deepest_state = PWRDM_POWER_OFF;
+		mpu_deepest_state = PWRDM_FUNC_PWRST_OFF;
 		/*
 		 * Erratum i583: valable for ES rev < Es1.2 on 3630.
 		 * CORE OFF mode is not supported in a stable form, restrict
 		 * instead the CORE state to RET.
 		 */
 		if (!IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583))
-			core_deepest_state = PWRDM_POWER_OFF;
+			core_deepest_state = PWRDM_FUNC_PWRST_OFF;
 	}
 
 	/* Check if current state is valid */
@@ -232,7 +232,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 			       int index)
 {
 	int new_state_idx;
-	u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state;
+	u32 core_next_state, per_next_state = 0, per_saved_state = 0;
 	struct omap3_idle_statedata *cx;
 	int ret;
 
@@ -240,8 +240,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 	 * Prevent idle completely if CAM is active.
 	 * CAM does not have wakeup capability in OMAP3.
 	 */
-	cam_state = pwrdm_read_pwrst(cam_pd);
-	if (cam_state == PWRDM_POWER_ON) {
+	if (pwrdm_read_func_pwrst(cam_pd) == PWRDM_FUNC_PWRST_ON) {
 		new_state_idx = drv->safe_state_index;
 		goto select_state;
 	}
@@ -260,14 +259,14 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 	 */
 	cx = &omap3_idle_data[index];
 	core_next_state = cx->core_state;
-	per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
-	if ((per_next_state == PWRDM_POWER_OFF) &&
-	    (core_next_state > PWRDM_POWER_RET))
-		per_next_state = PWRDM_POWER_RET;
+	per_next_state = per_saved_state = pwrdm_read_next_func_pwrst(per_pd);
+	if ((per_next_state == PWRDM_FUNC_PWRST_OFF) &&
+	    (core_next_state > PWRDM_FUNC_PWRST_CSWR))
+		per_next_state = PWRDM_FUNC_PWRST_CSWR;
 
 	/* Are we changing PER target state? */
 	if (per_next_state != per_saved_state)
-		pwrdm_set_next_pwrst(per_pd, per_next_state);
+		omap_set_pwrdm_state(per_pd, per_next_state);
 
 	new_state_idx = next_valid_state(dev, drv, index);
 
@@ -276,7 +275,7 @@ select_state:
 
 	/* Restore original PER state if it was modified */
 	if (per_next_state != per_saved_state)
-		pwrdm_set_next_pwrst(per_pd, per_saved_state);
+		omap_set_pwrdm_state(per_pd, per_saved_state);
 
 	return ret;
 }
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index be1617c..50c9082 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -33,18 +33,18 @@ struct omap4_idle_statedata {
 
 static struct omap4_idle_statedata omap4_idle_data[] = {
 	{
-		.cpu_state = PWRDM_POWER_ON,
-		.mpu_state = PWRDM_POWER_ON,
+		.cpu_state = PWRDM_FUNC_PWRST_ON,
+		.mpu_state = PWRDM_FUNC_PWRST_ON,
 		.mpu_logic_state = PWRDM_POWER_RET,
 	},
 	{
-		.cpu_state = PWRDM_POWER_OFF,
-		.mpu_state = PWRDM_POWER_RET,
+		.cpu_state = PWRDM_FUNC_PWRST_OFF,
+		.mpu_state = PWRDM_FUNC_PWRST_CSWR,
 		.mpu_logic_state = PWRDM_POWER_RET,
 	},
 	{
-		.cpu_state = PWRDM_POWER_OFF,
-		.mpu_state = PWRDM_POWER_RET,
+		.cpu_state = PWRDM_FUNC_PWRST_OFF,
+		.mpu_state = PWRDM_FUNC_PWRST_CSWR,
 		.mpu_logic_state = PWRDM_POWER_OFF,
 	},
 };
@@ -79,8 +79,8 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
 	 * Update dev->last_state so that governor stats reflects right
 	 * data.
 	 */
-	cpu1_state = pwrdm_read_pwrst(cpu1_pd);
-	if (cpu1_state != PWRDM_POWER_OFF) {
+	cpu1_state = pwrdm_read_func_pwrst(cpu1_pd);
+	if (cpu1_state != PWRDM_FUNC_PWRST_OFF) {
 		index = drv->safe_state_index;
 		cx = &omap4_idle_data[index];
 	}
@@ -92,7 +92,7 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
 	 * Call idle CPU PM enter notifier chain so that
 	 * VFP and per CPU interrupt context is saved.
 	 */
-	if (cx->cpu_state == PWRDM_POWER_OFF)
+	if (cx->cpu_state == PWRDM_FUNC_PWRST_OFF)
 		cpu_pm_enter();
 
 	pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state);
@@ -102,8 +102,9 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
 	 * Call idle CPU cluster PM enter notifier chain
 	 * to save GIC and wakeupgen context.
 	 */
-	if ((cx->mpu_state == PWRDM_POWER_RET) &&
-		(cx->mpu_logic_state == PWRDM_POWER_OFF))
+	if (((cx->mpu_state == PWRDM_FUNC_PWRST_CSWR) ||
+	     (cx->mpu_state == PWRDM_FUNC_PWRST_OSWR)) &&
+	    (cx->mpu_logic_state == PWRDM_POWER_OFF))
 			cpu_cluster_pm_enter();
 
 	omap4_enter_lowpower(dev->cpu, cx->cpu_state);
@@ -113,7 +114,7 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
 	 * VFP and per CPU IRQ context. Only CPU0 state is
 	 * considered since CPU1 is managed by CPU hotplug.
 	 */
-	if (pwrdm_read_prev_pwrst(cpu0_pd) == PWRDM_POWER_OFF)
+	if (pwrdm_read_prev_func_pwrst(cpu0_pd) == PWRDM_FUNC_PWRST_OFF)
 		cpu_pm_exit();
 
 	/*
diff --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-omap2/omap-hotplug.c
index 56c345b..cb7a7eb 100644
--- a/arch/arm/mach-omap2/omap-hotplug.c
+++ b/arch/arm/mach-omap2/omap-hotplug.c
@@ -50,7 +50,7 @@ void __ref platform_cpu_die(unsigned int cpu)
 		/*
 		 * Enter into low power state
 		 */
-		omap4_hotplug_cpu(cpu, PWRDM_POWER_OFF);
+		omap4_hotplug_cpu(cpu, PWRDM_FUNC_PWRST_OFF);
 		this_cpu = smp_processor_id();
 		if (omap_read_auxcoreboot0() == this_cpu) {
 			/*
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index 13670aa..dd94a0e 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -86,14 +86,14 @@ static inline void set_cpu_wakeup_addr(unsigned int cpu_id, u32 addr)
 }
 
 /*
- * Set the CPUx powerdomain's previous power state
+ * Set the CPUx powerdomain's next functional power state
  */
 static inline void set_cpu_next_pwrst(unsigned int cpu_id,
 				unsigned int power_state)
 {
 	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
 
-	pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
+	omap_set_pwrdm_state(pm_info->pwrdm, power_state);
 }
 
 /*
@@ -103,7 +103,7 @@ static inline unsigned int read_cpu_prev_pwrst(unsigned int cpu_id)
 {
 	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
 
-	return pwrdm_read_prev_pwrst(pm_info->pwrdm);
+	return pwrdm_read_prev_func_pwrst(pm_info->pwrdm);
 }
 
 /*
@@ -125,14 +125,15 @@ static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state)
 	u32 scu_pwr_st;
 
 	switch (cpu_state) {
-	case PWRDM_POWER_RET:
+	case PWRDM_FUNC_PWRST_OSWR:
+	case PWRDM_FUNC_PWRST_CSWR:
 		scu_pwr_st = SCU_PM_DORMANT;
 		break;
-	case PWRDM_POWER_OFF:
+	case PWRDM_FUNC_PWRST_OFF:
 		scu_pwr_st = SCU_PM_POWEROFF;
 		break;
-	case PWRDM_POWER_ON:
-	case PWRDM_POWER_INACTIVE:
+	case PWRDM_FUNC_PWRST_ON:
+	case PWRDM_FUNC_PWRST_INACTIVE:
 	default:
 		scu_pwr_st = SCU_PM_NORMAL;
 		break;
@@ -231,19 +232,21 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 {
 	unsigned int save_state = 0;
 	unsigned int wakeup_cpu;
+	int mpuss_state;
 
 	if (omap_rev() == OMAP4430_REV_ES1_0)
 		return -ENXIO;
 
 	switch (power_state) {
-	case PWRDM_POWER_ON:
-	case PWRDM_POWER_INACTIVE:
+	case PWRDM_FUNC_PWRST_ON:
+	case PWRDM_FUNC_PWRST_INACTIVE:
 		save_state = 0;
 		break;
-	case PWRDM_POWER_OFF:
+	case PWRDM_FUNC_PWRST_OFF:
 		save_state = 1;
 		break;
-	case PWRDM_POWER_RET:
+	case PWRDM_FUNC_PWRST_OSWR:
+	case PWRDM_FUNC_PWRST_CSWR:
 	default:
 		/*
 		 * CPUx CSWR is invalid hardware state. Also CPUx OSWR
@@ -259,11 +262,13 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 
 	/*
 	 * Check MPUSS next state and save interrupt controller if needed.
-	 * In MPUSS OSWR or device OFF, interrupt controller  contest is lost.
+	 * In MPUSS OSWR or device OFF, interrupt controller context is lost.
 	 */
 	mpuss_clear_prev_logic_pwrst();
-	if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
-		(pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF))
+	mpuss_state = pwrdm_read_next_func_pwrst(mpuss_pd);
+	if (((mpuss_state == PWRDM_FUNC_PWRST_CSWR) ||
+	     (mpuss_state == PWRDM_FUNC_PWRST_OSWR)) &&
+	    (pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF))
 		save_state = 2;
 
 	cpu_clear_prev_logic_pwrst(cpu);
@@ -285,7 +290,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	 * domain transition
 	 */
 	wakeup_cpu = smp_processor_id();
-	set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
+	set_cpu_next_pwrst(wakeup_cpu, PWRDM_FUNC_PWRST_ON);
 
 	pwrdm_post_transition();
 
@@ -304,7 +309,7 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
 	if (omap_rev() == OMAP4430_REV_ES1_0)
 		return -ENXIO;
 
-	if (power_state == PWRDM_POWER_OFF)
+	if (power_state == PWRDM_FUNC_PWRST_OFF)
 		cpu_state = 1;
 
 	clear_cpu_prev_pwrst(cpu);
@@ -319,7 +324,7 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
 	 */
 	omap4_finish_suspend(cpu_state);
 
-	set_cpu_next_pwrst(cpu, PWRDM_POWER_ON);
+	set_cpu_next_pwrst(cpu, PWRDM_FUNC_PWRST_ON);
 	return 0;
 }
 
@@ -354,7 +359,7 @@ int __init omap4_mpuss_init(void)
 	cpu_clear_prev_logic_pwrst(0);
 
 	/* Initialise CPU0 power domain state to ON */
-	pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);
+	omap_set_pwrdm_state(pm_info->pwrdm, PWRDM_FUNC_PWRST_ON);
 
 	pm_info = &per_cpu(omap4_pm_info, 0x1);
 	pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
@@ -371,7 +376,7 @@ int __init omap4_mpuss_init(void)
 	cpu_clear_prev_logic_pwrst(1);
 
 	/* Initialise CPU1 power domain state to ON */
-	pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);
+	omap_set_pwrdm_state(pm_info->pwrdm, PWRDM_FUNC_PWRST_ON);
 
 	mpuss_pd = pwrdm_lookup("mpu_pwrdm");
 	if (!mpuss_pd) {
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 2edeffc..0bed51e 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -94,7 +94,7 @@ static int omap2_enter_full_retention(void)
 	 * preserve logic state during retention
 	 */
 	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
-	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
+	omap_set_pwrdm_state(mpu_pwrdm, PWRDM_FUNC_PWRST_CSWR);
 
 	/* Workaround to kill USB */
 	l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
@@ -251,23 +251,23 @@ static void __init prcm_setup_regs(void)
 		pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET);
 
 	/* Set CORE powerdomain's next power state to RETENTION */
-	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
+	omap_set_pwrdm_state(core_pwrdm, PWRDM_FUNC_PWRST_CSWR);
 
 	/*
 	 * Set MPU powerdomain's next power state to RETENTION;
 	 * preserve logic state during retention
 	 */
 	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
-	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
+	omap_set_pwrdm_state(mpu_pwrdm, PWRDM_FUNC_PWRST_CSWR);
 
 	/* Force-power down DSP, GFX powerdomains */
 
 	pwrdm = clkdm_get_pwrdm(dsp_clkdm);
-	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
+	omap_set_pwrdm_state(pwrdm, PWRDM_FUNC_PWRST_OFF);
 	clkdm_sleep(dsp_clkdm);
 
 	pwrdm = clkdm_get_pwrdm(gfx_clkdm);
-	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
+	omap_set_pwrdm_state(pwrdm, PWRDM_FUNC_PWRST_OFF);
 	clkdm_sleep(gfx_clkdm);
 
 	/* Enable hardware-supervised idle for all clkdms */
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index a34023d..b2fc786 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -139,7 +139,7 @@ static void omap3_core_restore_context(void)
 static void omap3_save_secure_ram_context(void)
 {
 	u32 ret;
-	int mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
+	int mpu_next_state = pwrdm_read_next_func_pwrst(mpu_pwrdm);
 
 	if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
 		/*
@@ -147,10 +147,10 @@ static void omap3_save_secure_ram_context(void)
 		 * otherwise the WFI executed inside the ROM code
 		 * will hang the system.
 		 */
-		pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
+		omap_set_pwrdm_state(mpu_pwrdm, PWRDM_FUNC_PWRST_ON);
 		ret = _omap_save_secure_sram((u32 *)
 				__pa(omap3_secure_ram_storage));
-		pwrdm_set_next_pwrst(mpu_pwrdm, mpu_next_state);
+		omap_set_pwrdm_state(mpu_pwrdm, mpu_next_state);
 		/* Following is for error tracking, it should not happen */
 		if (ret) {
 			pr_err("save_secure_sram() returns %08x\n", ret);
@@ -269,21 +269,23 @@ void omap_sram_idle(void)
 	/* save_state = 2 => Only L2 lost */
 	/* save_state = 3 => L1, L2 and logic lost */
 	int save_state = 0;
-	int mpu_next_state = PWRDM_POWER_ON;
-	int per_next_state = PWRDM_POWER_ON;
-	int core_next_state = PWRDM_POWER_ON;
+	int mpu_next_state = PWRDM_FUNC_PWRST_ON;
+	int per_next_state = PWRDM_FUNC_PWRST_ON;
+	int core_next_state = PWRDM_FUNC_PWRST_ON;
 	int per_going_off;
 	int core_prev_state;
 	u32 sdrc_pwr = 0;
 
-	mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
+	mpu_next_state = pwrdm_read_next_func_pwrst(mpu_pwrdm);
 	switch (mpu_next_state) {
-	case PWRDM_POWER_ON:
-	case PWRDM_POWER_RET:
+	case PWRDM_FUNC_PWRST_ON:
+	case PWRDM_FUNC_PWRST_INACTIVE:
+	case PWRDM_FUNC_PWRST_CSWR:
 		/* No need to save context */
 		save_state = 0;
 		break;
-	case PWRDM_POWER_OFF:
+	case PWRDM_FUNC_PWRST_OSWR:
+	case PWRDM_FUNC_PWRST_OFF:
 		save_state = 3;
 		break;
 	default:
@@ -293,16 +295,17 @@ void omap_sram_idle(void)
 	}
 
 	/* NEON control */
-	if (pwrdm_read_pwrst(neon_pwrdm) == PWRDM_POWER_ON)
-		pwrdm_set_next_pwrst(neon_pwrdm, mpu_next_state);
+	if (pwrdm_read_func_pwrst(neon_pwrdm) == PWRDM_FUNC_PWRST_ON)
+		omap_set_pwrdm_state(neon_pwrdm, mpu_next_state);
 
 	/* Enable IO-PAD and IO-CHAIN wakeups */
-	per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
-	core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
+	per_next_state = pwrdm_read_next_func_pwrst(per_pwrdm);
+	core_next_state = pwrdm_read_next_func_pwrst(core_pwrdm);
 	if (omap3_has_io_wakeup() &&
-	    (per_next_state < PWRDM_POWER_ON ||
-	     core_next_state < PWRDM_POWER_ON)) {
-		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
+	    (per_next_state < PWRDM_FUNC_PWRST_ON ||
+	     core_next_state < PWRDM_FUNC_PWRST_ON)) {
+		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
+					   PM_WKEN);
 		if (omap3_has_io_chain_ctrl())
 			omap3_enable_io_chain();
 	}
@@ -310,14 +313,15 @@ void omap_sram_idle(void)
 	pwrdm_pre_transition();
 
 	/* PER */
-	if (per_next_state < PWRDM_POWER_ON) {
-		per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
+	if (per_next_state < PWRDM_FUNC_PWRST_ON) {
+		per_going_off = (per_next_state == PWRDM_FUNC_PWRST_OFF) ?
+				1 : 0;
 		omap2_gpio_prepare_for_idle(per_going_off);
 	}
 
 	/* CORE */
-	if (core_next_state < PWRDM_POWER_ON) {
-		if (core_next_state == PWRDM_POWER_OFF) {
+	if (core_next_state < PWRDM_FUNC_PWRST_ON) {
+		if (core_next_state == PWRDM_FUNC_PWRST_OFF) {
 			omap3_core_save_context();
 			omap3_cm_save_context();
 		}
@@ -334,7 +338,7 @@ void omap_sram_idle(void)
 	if (cpu_is_omap3430() && omap_rev() >= OMAP3430_REV_ES3_0 &&
 	    (omap_type() == OMAP2_DEVICE_TYPE_EMU ||
 	     omap_type() == OMAP2_DEVICE_TYPE_SEC) &&
-	    core_next_state == PWRDM_POWER_OFF)
+	    core_next_state == PWRDM_FUNC_PWRST_OFF)
 		sdrc_pwr = sdrc_read_reg(SDRC_POWER);
 
 	/*
@@ -353,19 +357,19 @@ void omap_sram_idle(void)
 	if (cpu_is_omap3430() && omap_rev() >= OMAP3430_REV_ES3_0 &&
 	    (omap_type() == OMAP2_DEVICE_TYPE_EMU ||
 	     omap_type() == OMAP2_DEVICE_TYPE_SEC) &&
-	    core_next_state == PWRDM_POWER_OFF)
+	    core_next_state == PWRDM_FUNC_PWRST_OFF)
 		sdrc_write_reg(sdrc_pwr, SDRC_POWER);
 
 	/* CORE */
-	if (core_next_state < PWRDM_POWER_ON) {
-		core_prev_state = pwrdm_read_prev_pwrst(core_pwrdm);
-		if (core_prev_state == PWRDM_POWER_OFF) {
+	if (core_next_state < PWRDM_FUNC_PWRST_ON) {
+		core_prev_state = pwrdm_read_prev_func_pwrst(core_pwrdm);
+		if (core_prev_state == PWRDM_FUNC_PWRST_OFF) {
 			omap3_core_restore_context();
 			omap3_cm_restore_context();
 			omap3_sram_restore_context();
 			omap2_sms_restore_context();
 		}
-		if (core_next_state == PWRDM_POWER_OFF)
+		if (core_next_state == PWRDM_FUNC_PWRST_OFF)
 			omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
 					       OMAP3430_GR_MOD,
 					       OMAP3_PRM_VOLTCTRL_OFFSET);
@@ -375,13 +379,13 @@ void omap_sram_idle(void)
 	pwrdm_post_transition();
 
 	/* PER */
-	if (per_next_state < PWRDM_POWER_ON)
+	if (per_next_state < PWRDM_FUNC_PWRST_ON)
 		omap2_gpio_resume_after_idle();
 
 	/* Disable IO-PAD and IO-CHAIN wakeup */
 	if (omap3_has_io_wakeup() &&
-	    (per_next_state < PWRDM_POWER_ON ||
-	     core_next_state < PWRDM_POWER_ON)) {
+	    (per_next_state < PWRDM_FUNC_PWRST_ON ||
+	     core_next_state < PWRDM_FUNC_PWRST_ON)) {
 		omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
 					     PM_WKEN);
 		if (omap3_has_io_chain_ctrl())
@@ -418,7 +422,7 @@ static int omap3_pm_suspend(void)
 
 	/* Read current next_pwrsts */
 	list_for_each_entry(pwrst, &pwrst_list, node)
-		pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
+		pwrst->saved_state = pwrdm_read_next_func_pwrst(pwrst->pwrdm);
 	/* Set ones wanted by suspend */
 	list_for_each_entry(pwrst, &pwrst_list, node) {
 		if (omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state))
@@ -434,7 +438,7 @@ static int omap3_pm_suspend(void)
 restore:
 	/* Restore next_pwrsts */
 	list_for_each_entry(pwrst, &pwrst_list, node) {
-		state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
+		state = pwrdm_read_prev_func_pwrst(pwrst->pwrdm);
 		if (state > pwrst->next_state) {
 			pr_info("Powerdomain (%s) didn't enter "
 				"target state %d\n",
@@ -608,15 +612,15 @@ void omap3_pm_off_mode_enable(int enable)
 	u32 state;
 
 	if (enable)
-		state = PWRDM_POWER_OFF;
+		state = PWRDM_FUNC_PWRST_OFF;
 	else
-		state = PWRDM_POWER_RET;
+		state = PWRDM_FUNC_PWRST_CSWR;
 
 	list_for_each_entry(pwrst, &pwrst_list, node) {
 		if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583) &&
 				pwrst->pwrdm == core_pwrdm &&
-				state == PWRDM_POWER_OFF) {
-			pwrst->next_state = PWRDM_POWER_RET;
+				state == PWRDM_FUNC_PWRST_OFF) {
+			pwrst->next_state = PWRDM_FUNC_PWRST_CSWR;
 			pr_warn("%s: Core OFF disabled due to errata i583\n",
 				__func__);
 		} else {
@@ -661,7 +665,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 	if (!pwrst)
 		return -ENOMEM;
 	pwrst->pwrdm = pwrdm;
-	pwrst->next_state = PWRDM_POWER_RET;
+	pwrst->next_state = PWRDM_FUNC_PWRST_CSWR;
 	list_add(&pwrst->node, &pwrst_list);
 
 	if (pwrdm_has_hdwr_sar(pwrdm))
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index ea24174..98bb699 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -44,7 +44,7 @@ static int omap4_pm_suspend(void)
 
 	/* Save current powerdomain state */
 	list_for_each_entry(pwrst, &pwrst_list, node) {
-		pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
+		pwrst->saved_state = pwrdm_read_next_func_pwrst(pwrst->pwrdm);
 		pwrst->saved_logic_state = pwrdm_read_logic_retst(pwrst->pwrdm);
 	}
 
@@ -63,11 +63,11 @@ static int omap4_pm_suspend(void)
 	 * domain CSWR is not supported by hardware.
 	 * More details can be found in OMAP4430 TRM section 4.3.4.2.
 	 */
-	omap4_enter_lowpower(cpu_id, PWRDM_POWER_OFF);
+	omap4_enter_lowpower(cpu_id, PWRDM_FUNC_PWRST_OFF);
 
 	/* Restore next powerdomain state */
 	list_for_each_entry(pwrst, &pwrst_list, node) {
-		state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
+		state = pwrdm_read_prev_func_pwrst(pwrst->pwrdm);
 		if (state > pwrst->next_state) {
 			pr_info("Powerdomain (%s) didn't enter "
 			       "target state %d\n",
@@ -113,7 +113,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 		return -ENOMEM;
 
 	pwrst->pwrdm = pwrdm;
-	pwrst->next_state = PWRDM_POWER_RET;
+	pwrst->next_state = PWRDM_FUNC_PWRST_CSWR;
 	list_add(&pwrst->node, &pwrst_list);
 
 	return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index e79b5ae..ec2b21c 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -270,7 +270,7 @@ int pwrdm_complete_init(void)
 		return -EACCES;
 
 	list_for_each_entry(temp_p, &pwrdm_list, node)
-		pwrdm_set_next_pwrst(temp_p, PWRDM_POWER_ON);
+		omap_set_pwrdm_state(temp_p, PWRDM_FUNC_PWRST_ON);
 
 	return 0;
 }
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 3/8] ARM: OMAP2+: PM: use the functional power states API
@ 2012-06-14 14:53   ` Jean Pihet
  0 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-arm-kernel

Use the functional power states as the API to control power domains.
The omap_set_pwrdm_state function shall be used instead of
pwrdm_set_next_pwrst to control the power domains next states.

Note: the internal code for power domains state management still
uses the internal power states.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/cpuidle34xx.c         |   61 +++++++++++-----------
 arch/arm/mach-omap2/cpuidle44xx.c         |   25 +++++-----
 arch/arm/mach-omap2/omap-hotplug.c        |    2 +-
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   43 +++++++++-------
 arch/arm/mach-omap2/pm24xx.c              |   10 ++--
 arch/arm/mach-omap2/pm34xx.c              |   78 +++++++++++++++--------------
 arch/arm/mach-omap2/pm44xx.c              |    8 ++--
 arch/arm/mach-omap2/powerdomain.c         |    2 +-
 8 files changed, 119 insertions(+), 110 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 207bc1c..ef8d7d4 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -46,32 +46,32 @@ struct omap3_idle_statedata {
 
 static struct omap3_idle_statedata omap3_idle_data[] = {
 	{
-		.mpu_state = PWRDM_POWER_ON,
-		.core_state = PWRDM_POWER_ON,
+		.mpu_state = PWRDM_FUNC_PWRST_ON,
+		.core_state = PWRDM_FUNC_PWRST_ON,
 	},
 	{
-		.mpu_state = PWRDM_POWER_ON,
-		.core_state = PWRDM_POWER_ON,
+		.mpu_state = PWRDM_FUNC_PWRST_ON,
+		.core_state = PWRDM_FUNC_PWRST_ON,
 	},
 	{
-		.mpu_state = PWRDM_POWER_RET,
-		.core_state = PWRDM_POWER_ON,
+		.mpu_state = PWRDM_FUNC_PWRST_CSWR,
+		.core_state = PWRDM_FUNC_PWRST_ON,
 	},
 	{
-		.mpu_state = PWRDM_POWER_OFF,
-		.core_state = PWRDM_POWER_ON,
+		.mpu_state = PWRDM_FUNC_PWRST_OFF,
+		.core_state = PWRDM_FUNC_PWRST_ON,
 	},
 	{
-		.mpu_state = PWRDM_POWER_RET,
-		.core_state = PWRDM_POWER_RET,
+		.mpu_state = PWRDM_FUNC_PWRST_CSWR,
+		.core_state = PWRDM_FUNC_PWRST_CSWR,
 	},
 	{
-		.mpu_state = PWRDM_POWER_OFF,
-		.core_state = PWRDM_POWER_RET,
+		.mpu_state = PWRDM_FUNC_PWRST_OFF,
+		.core_state = PWRDM_FUNC_PWRST_CSWR,
 	},
 	{
-		.mpu_state = PWRDM_POWER_OFF,
-		.core_state = PWRDM_POWER_OFF,
+		.mpu_state = PWRDM_FUNC_PWRST_OFF,
+		.core_state = PWRDM_FUNC_PWRST_OFF,
 	},
 };
 
@@ -100,8 +100,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 
 	local_fiq_disable();
 
-	pwrdm_set_next_pwrst(mpu_pd, mpu_state);
-	pwrdm_set_next_pwrst(core_pd, core_state);
+	omap_set_pwrdm_state(mpu_pd, mpu_state);
+	omap_set_pwrdm_state(core_pd, core_state);
 
 	if (omap_irq_pending() || need_resched())
 		goto return_sleep_time;
@@ -116,7 +116,7 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 	 * Call idle CPU PM enter notifier chain so that
 	 * VFP context is saved.
 	 */
-	if (mpu_state == PWRDM_POWER_OFF)
+	if (mpu_state == PWRDM_FUNC_PWRST_OFF)
 		cpu_pm_enter();
 
 	/* Execute ARM wfi */
@@ -126,7 +126,7 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 	 * Call idle CPU PM enter notifier chain to restore
 	 * VFP context.
 	 */
-	if (pwrdm_read_prev_pwrst(mpu_pd) == PWRDM_POWER_OFF)
+	if (pwrdm_read_prev_func_pwrst(mpu_pd) == PWRDM_FUNC_PWRST_OFF)
 		cpu_pm_exit();
 
 	/* Re-allow idle for C1 */
@@ -175,20 +175,20 @@ static int next_valid_state(struct cpuidle_device *dev,
 			    struct cpuidle_driver *drv, int index)
 {
 	struct omap3_idle_statedata *cx = &omap3_idle_data[index];
-	u32 mpu_deepest_state = PWRDM_POWER_RET;
-	u32 core_deepest_state = PWRDM_POWER_RET;
+	u32 mpu_deepest_state = PWRDM_FUNC_PWRST_CSWR;
+	u32 core_deepest_state = PWRDM_FUNC_PWRST_CSWR;
 	int idx;
 	int next_index = -1;
 
 	if (enable_off_mode) {
-		mpu_deepest_state = PWRDM_POWER_OFF;
+		mpu_deepest_state = PWRDM_FUNC_PWRST_OFF;
 		/*
 		 * Erratum i583: valable for ES rev < Es1.2 on 3630.
 		 * CORE OFF mode is not supported in a stable form, restrict
 		 * instead the CORE state to RET.
 		 */
 		if (!IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583))
-			core_deepest_state = PWRDM_POWER_OFF;
+			core_deepest_state = PWRDM_FUNC_PWRST_OFF;
 	}
 
 	/* Check if current state is valid */
@@ -232,7 +232,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 			       int index)
 {
 	int new_state_idx;
-	u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state;
+	u32 core_next_state, per_next_state = 0, per_saved_state = 0;
 	struct omap3_idle_statedata *cx;
 	int ret;
 
@@ -240,8 +240,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 	 * Prevent idle completely if CAM is active.
 	 * CAM does not have wakeup capability in OMAP3.
 	 */
-	cam_state = pwrdm_read_pwrst(cam_pd);
-	if (cam_state == PWRDM_POWER_ON) {
+	if (pwrdm_read_func_pwrst(cam_pd) == PWRDM_FUNC_PWRST_ON) {
 		new_state_idx = drv->safe_state_index;
 		goto select_state;
 	}
@@ -260,14 +259,14 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 	 */
 	cx = &omap3_idle_data[index];
 	core_next_state = cx->core_state;
-	per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
-	if ((per_next_state == PWRDM_POWER_OFF) &&
-	    (core_next_state > PWRDM_POWER_RET))
-		per_next_state = PWRDM_POWER_RET;
+	per_next_state = per_saved_state = pwrdm_read_next_func_pwrst(per_pd);
+	if ((per_next_state == PWRDM_FUNC_PWRST_OFF) &&
+	    (core_next_state > PWRDM_FUNC_PWRST_CSWR))
+		per_next_state = PWRDM_FUNC_PWRST_CSWR;
 
 	/* Are we changing PER target state? */
 	if (per_next_state != per_saved_state)
-		pwrdm_set_next_pwrst(per_pd, per_next_state);
+		omap_set_pwrdm_state(per_pd, per_next_state);
 
 	new_state_idx = next_valid_state(dev, drv, index);
 
@@ -276,7 +275,7 @@ select_state:
 
 	/* Restore original PER state if it was modified */
 	if (per_next_state != per_saved_state)
-		pwrdm_set_next_pwrst(per_pd, per_saved_state);
+		omap_set_pwrdm_state(per_pd, per_saved_state);
 
 	return ret;
 }
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index be1617c..50c9082 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -33,18 +33,18 @@ struct omap4_idle_statedata {
 
 static struct omap4_idle_statedata omap4_idle_data[] = {
 	{
-		.cpu_state = PWRDM_POWER_ON,
-		.mpu_state = PWRDM_POWER_ON,
+		.cpu_state = PWRDM_FUNC_PWRST_ON,
+		.mpu_state = PWRDM_FUNC_PWRST_ON,
 		.mpu_logic_state = PWRDM_POWER_RET,
 	},
 	{
-		.cpu_state = PWRDM_POWER_OFF,
-		.mpu_state = PWRDM_POWER_RET,
+		.cpu_state = PWRDM_FUNC_PWRST_OFF,
+		.mpu_state = PWRDM_FUNC_PWRST_CSWR,
 		.mpu_logic_state = PWRDM_POWER_RET,
 	},
 	{
-		.cpu_state = PWRDM_POWER_OFF,
-		.mpu_state = PWRDM_POWER_RET,
+		.cpu_state = PWRDM_FUNC_PWRST_OFF,
+		.mpu_state = PWRDM_FUNC_PWRST_CSWR,
 		.mpu_logic_state = PWRDM_POWER_OFF,
 	},
 };
@@ -79,8 +79,8 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
 	 * Update dev->last_state so that governor stats reflects right
 	 * data.
 	 */
-	cpu1_state = pwrdm_read_pwrst(cpu1_pd);
-	if (cpu1_state != PWRDM_POWER_OFF) {
+	cpu1_state = pwrdm_read_func_pwrst(cpu1_pd);
+	if (cpu1_state != PWRDM_FUNC_PWRST_OFF) {
 		index = drv->safe_state_index;
 		cx = &omap4_idle_data[index];
 	}
@@ -92,7 +92,7 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
 	 * Call idle CPU PM enter notifier chain so that
 	 * VFP and per CPU interrupt context is saved.
 	 */
-	if (cx->cpu_state == PWRDM_POWER_OFF)
+	if (cx->cpu_state == PWRDM_FUNC_PWRST_OFF)
 		cpu_pm_enter();
 
 	pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state);
@@ -102,8 +102,9 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
 	 * Call idle CPU cluster PM enter notifier chain
 	 * to save GIC and wakeupgen context.
 	 */
-	if ((cx->mpu_state == PWRDM_POWER_RET) &&
-		(cx->mpu_logic_state == PWRDM_POWER_OFF))
+	if (((cx->mpu_state == PWRDM_FUNC_PWRST_CSWR) ||
+	     (cx->mpu_state == PWRDM_FUNC_PWRST_OSWR)) &&
+	    (cx->mpu_logic_state == PWRDM_POWER_OFF))
 			cpu_cluster_pm_enter();
 
 	omap4_enter_lowpower(dev->cpu, cx->cpu_state);
@@ -113,7 +114,7 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
 	 * VFP and per CPU IRQ context. Only CPU0 state is
 	 * considered since CPU1 is managed by CPU hotplug.
 	 */
-	if (pwrdm_read_prev_pwrst(cpu0_pd) == PWRDM_POWER_OFF)
+	if (pwrdm_read_prev_func_pwrst(cpu0_pd) == PWRDM_FUNC_PWRST_OFF)
 		cpu_pm_exit();
 
 	/*
diff --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-omap2/omap-hotplug.c
index 56c345b..cb7a7eb 100644
--- a/arch/arm/mach-omap2/omap-hotplug.c
+++ b/arch/arm/mach-omap2/omap-hotplug.c
@@ -50,7 +50,7 @@ void __ref platform_cpu_die(unsigned int cpu)
 		/*
 		 * Enter into low power state
 		 */
-		omap4_hotplug_cpu(cpu, PWRDM_POWER_OFF);
+		omap4_hotplug_cpu(cpu, PWRDM_FUNC_PWRST_OFF);
 		this_cpu = smp_processor_id();
 		if (omap_read_auxcoreboot0() == this_cpu) {
 			/*
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index 13670aa..dd94a0e 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -86,14 +86,14 @@ static inline void set_cpu_wakeup_addr(unsigned int cpu_id, u32 addr)
 }
 
 /*
- * Set the CPUx powerdomain's previous power state
+ * Set the CPUx powerdomain's next functional power state
  */
 static inline void set_cpu_next_pwrst(unsigned int cpu_id,
 				unsigned int power_state)
 {
 	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
 
-	pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
+	omap_set_pwrdm_state(pm_info->pwrdm, power_state);
 }
 
 /*
@@ -103,7 +103,7 @@ static inline unsigned int read_cpu_prev_pwrst(unsigned int cpu_id)
 {
 	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
 
-	return pwrdm_read_prev_pwrst(pm_info->pwrdm);
+	return pwrdm_read_prev_func_pwrst(pm_info->pwrdm);
 }
 
 /*
@@ -125,14 +125,15 @@ static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state)
 	u32 scu_pwr_st;
 
 	switch (cpu_state) {
-	case PWRDM_POWER_RET:
+	case PWRDM_FUNC_PWRST_OSWR:
+	case PWRDM_FUNC_PWRST_CSWR:
 		scu_pwr_st = SCU_PM_DORMANT;
 		break;
-	case PWRDM_POWER_OFF:
+	case PWRDM_FUNC_PWRST_OFF:
 		scu_pwr_st = SCU_PM_POWEROFF;
 		break;
-	case PWRDM_POWER_ON:
-	case PWRDM_POWER_INACTIVE:
+	case PWRDM_FUNC_PWRST_ON:
+	case PWRDM_FUNC_PWRST_INACTIVE:
 	default:
 		scu_pwr_st = SCU_PM_NORMAL;
 		break;
@@ -231,19 +232,21 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 {
 	unsigned int save_state = 0;
 	unsigned int wakeup_cpu;
+	int mpuss_state;
 
 	if (omap_rev() == OMAP4430_REV_ES1_0)
 		return -ENXIO;
 
 	switch (power_state) {
-	case PWRDM_POWER_ON:
-	case PWRDM_POWER_INACTIVE:
+	case PWRDM_FUNC_PWRST_ON:
+	case PWRDM_FUNC_PWRST_INACTIVE:
 		save_state = 0;
 		break;
-	case PWRDM_POWER_OFF:
+	case PWRDM_FUNC_PWRST_OFF:
 		save_state = 1;
 		break;
-	case PWRDM_POWER_RET:
+	case PWRDM_FUNC_PWRST_OSWR:
+	case PWRDM_FUNC_PWRST_CSWR:
 	default:
 		/*
 		 * CPUx CSWR is invalid hardware state. Also CPUx OSWR
@@ -259,11 +262,13 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 
 	/*
 	 * Check MPUSS next state and save interrupt controller if needed.
-	 * In MPUSS OSWR or device OFF, interrupt controller  contest is lost.
+	 * In MPUSS OSWR or device OFF, interrupt controller context is lost.
 	 */
 	mpuss_clear_prev_logic_pwrst();
-	if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
-		(pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF))
+	mpuss_state = pwrdm_read_next_func_pwrst(mpuss_pd);
+	if (((mpuss_state == PWRDM_FUNC_PWRST_CSWR) ||
+	     (mpuss_state == PWRDM_FUNC_PWRST_OSWR)) &&
+	    (pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF))
 		save_state = 2;
 
 	cpu_clear_prev_logic_pwrst(cpu);
@@ -285,7 +290,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	 * domain transition
 	 */
 	wakeup_cpu = smp_processor_id();
-	set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
+	set_cpu_next_pwrst(wakeup_cpu, PWRDM_FUNC_PWRST_ON);
 
 	pwrdm_post_transition();
 
@@ -304,7 +309,7 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
 	if (omap_rev() == OMAP4430_REV_ES1_0)
 		return -ENXIO;
 
-	if (power_state == PWRDM_POWER_OFF)
+	if (power_state == PWRDM_FUNC_PWRST_OFF)
 		cpu_state = 1;
 
 	clear_cpu_prev_pwrst(cpu);
@@ -319,7 +324,7 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
 	 */
 	omap4_finish_suspend(cpu_state);
 
-	set_cpu_next_pwrst(cpu, PWRDM_POWER_ON);
+	set_cpu_next_pwrst(cpu, PWRDM_FUNC_PWRST_ON);
 	return 0;
 }
 
@@ -354,7 +359,7 @@ int __init omap4_mpuss_init(void)
 	cpu_clear_prev_logic_pwrst(0);
 
 	/* Initialise CPU0 power domain state to ON */
-	pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);
+	omap_set_pwrdm_state(pm_info->pwrdm, PWRDM_FUNC_PWRST_ON);
 
 	pm_info = &per_cpu(omap4_pm_info, 0x1);
 	pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
@@ -371,7 +376,7 @@ int __init omap4_mpuss_init(void)
 	cpu_clear_prev_logic_pwrst(1);
 
 	/* Initialise CPU1 power domain state to ON */
-	pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);
+	omap_set_pwrdm_state(pm_info->pwrdm, PWRDM_FUNC_PWRST_ON);
 
 	mpuss_pd = pwrdm_lookup("mpu_pwrdm");
 	if (!mpuss_pd) {
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 2edeffc..0bed51e 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -94,7 +94,7 @@ static int omap2_enter_full_retention(void)
 	 * preserve logic state during retention
 	 */
 	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
-	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
+	omap_set_pwrdm_state(mpu_pwrdm, PWRDM_FUNC_PWRST_CSWR);
 
 	/* Workaround to kill USB */
 	l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
@@ -251,23 +251,23 @@ static void __init prcm_setup_regs(void)
 		pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET);
 
 	/* Set CORE powerdomain's next power state to RETENTION */
-	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
+	omap_set_pwrdm_state(core_pwrdm, PWRDM_FUNC_PWRST_CSWR);
 
 	/*
 	 * Set MPU powerdomain's next power state to RETENTION;
 	 * preserve logic state during retention
 	 */
 	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
-	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
+	omap_set_pwrdm_state(mpu_pwrdm, PWRDM_FUNC_PWRST_CSWR);
 
 	/* Force-power down DSP, GFX powerdomains */
 
 	pwrdm = clkdm_get_pwrdm(dsp_clkdm);
-	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
+	omap_set_pwrdm_state(pwrdm, PWRDM_FUNC_PWRST_OFF);
 	clkdm_sleep(dsp_clkdm);
 
 	pwrdm = clkdm_get_pwrdm(gfx_clkdm);
-	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
+	omap_set_pwrdm_state(pwrdm, PWRDM_FUNC_PWRST_OFF);
 	clkdm_sleep(gfx_clkdm);
 
 	/* Enable hardware-supervised idle for all clkdms */
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index a34023d..b2fc786 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -139,7 +139,7 @@ static void omap3_core_restore_context(void)
 static void omap3_save_secure_ram_context(void)
 {
 	u32 ret;
-	int mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
+	int mpu_next_state = pwrdm_read_next_func_pwrst(mpu_pwrdm);
 
 	if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
 		/*
@@ -147,10 +147,10 @@ static void omap3_save_secure_ram_context(void)
 		 * otherwise the WFI executed inside the ROM code
 		 * will hang the system.
 		 */
-		pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
+		omap_set_pwrdm_state(mpu_pwrdm, PWRDM_FUNC_PWRST_ON);
 		ret = _omap_save_secure_sram((u32 *)
 				__pa(omap3_secure_ram_storage));
-		pwrdm_set_next_pwrst(mpu_pwrdm, mpu_next_state);
+		omap_set_pwrdm_state(mpu_pwrdm, mpu_next_state);
 		/* Following is for error tracking, it should not happen */
 		if (ret) {
 			pr_err("save_secure_sram() returns %08x\n", ret);
@@ -269,21 +269,23 @@ void omap_sram_idle(void)
 	/* save_state = 2 => Only L2 lost */
 	/* save_state = 3 => L1, L2 and logic lost */
 	int save_state = 0;
-	int mpu_next_state = PWRDM_POWER_ON;
-	int per_next_state = PWRDM_POWER_ON;
-	int core_next_state = PWRDM_POWER_ON;
+	int mpu_next_state = PWRDM_FUNC_PWRST_ON;
+	int per_next_state = PWRDM_FUNC_PWRST_ON;
+	int core_next_state = PWRDM_FUNC_PWRST_ON;
 	int per_going_off;
 	int core_prev_state;
 	u32 sdrc_pwr = 0;
 
-	mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
+	mpu_next_state = pwrdm_read_next_func_pwrst(mpu_pwrdm);
 	switch (mpu_next_state) {
-	case PWRDM_POWER_ON:
-	case PWRDM_POWER_RET:
+	case PWRDM_FUNC_PWRST_ON:
+	case PWRDM_FUNC_PWRST_INACTIVE:
+	case PWRDM_FUNC_PWRST_CSWR:
 		/* No need to save context */
 		save_state = 0;
 		break;
-	case PWRDM_POWER_OFF:
+	case PWRDM_FUNC_PWRST_OSWR:
+	case PWRDM_FUNC_PWRST_OFF:
 		save_state = 3;
 		break;
 	default:
@@ -293,16 +295,17 @@ void omap_sram_idle(void)
 	}
 
 	/* NEON control */
-	if (pwrdm_read_pwrst(neon_pwrdm) == PWRDM_POWER_ON)
-		pwrdm_set_next_pwrst(neon_pwrdm, mpu_next_state);
+	if (pwrdm_read_func_pwrst(neon_pwrdm) == PWRDM_FUNC_PWRST_ON)
+		omap_set_pwrdm_state(neon_pwrdm, mpu_next_state);
 
 	/* Enable IO-PAD and IO-CHAIN wakeups */
-	per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
-	core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
+	per_next_state = pwrdm_read_next_func_pwrst(per_pwrdm);
+	core_next_state = pwrdm_read_next_func_pwrst(core_pwrdm);
 	if (omap3_has_io_wakeup() &&
-	    (per_next_state < PWRDM_POWER_ON ||
-	     core_next_state < PWRDM_POWER_ON)) {
-		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
+	    (per_next_state < PWRDM_FUNC_PWRST_ON ||
+	     core_next_state < PWRDM_FUNC_PWRST_ON)) {
+		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
+					   PM_WKEN);
 		if (omap3_has_io_chain_ctrl())
 			omap3_enable_io_chain();
 	}
@@ -310,14 +313,15 @@ void omap_sram_idle(void)
 	pwrdm_pre_transition();
 
 	/* PER */
-	if (per_next_state < PWRDM_POWER_ON) {
-		per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
+	if (per_next_state < PWRDM_FUNC_PWRST_ON) {
+		per_going_off = (per_next_state == PWRDM_FUNC_PWRST_OFF) ?
+				1 : 0;
 		omap2_gpio_prepare_for_idle(per_going_off);
 	}
 
 	/* CORE */
-	if (core_next_state < PWRDM_POWER_ON) {
-		if (core_next_state == PWRDM_POWER_OFF) {
+	if (core_next_state < PWRDM_FUNC_PWRST_ON) {
+		if (core_next_state == PWRDM_FUNC_PWRST_OFF) {
 			omap3_core_save_context();
 			omap3_cm_save_context();
 		}
@@ -334,7 +338,7 @@ void omap_sram_idle(void)
 	if (cpu_is_omap3430() && omap_rev() >= OMAP3430_REV_ES3_0 &&
 	    (omap_type() == OMAP2_DEVICE_TYPE_EMU ||
 	     omap_type() == OMAP2_DEVICE_TYPE_SEC) &&
-	    core_next_state == PWRDM_POWER_OFF)
+	    core_next_state == PWRDM_FUNC_PWRST_OFF)
 		sdrc_pwr = sdrc_read_reg(SDRC_POWER);
 
 	/*
@@ -353,19 +357,19 @@ void omap_sram_idle(void)
 	if (cpu_is_omap3430() && omap_rev() >= OMAP3430_REV_ES3_0 &&
 	    (omap_type() == OMAP2_DEVICE_TYPE_EMU ||
 	     omap_type() == OMAP2_DEVICE_TYPE_SEC) &&
-	    core_next_state == PWRDM_POWER_OFF)
+	    core_next_state == PWRDM_FUNC_PWRST_OFF)
 		sdrc_write_reg(sdrc_pwr, SDRC_POWER);
 
 	/* CORE */
-	if (core_next_state < PWRDM_POWER_ON) {
-		core_prev_state = pwrdm_read_prev_pwrst(core_pwrdm);
-		if (core_prev_state == PWRDM_POWER_OFF) {
+	if (core_next_state < PWRDM_FUNC_PWRST_ON) {
+		core_prev_state = pwrdm_read_prev_func_pwrst(core_pwrdm);
+		if (core_prev_state == PWRDM_FUNC_PWRST_OFF) {
 			omap3_core_restore_context();
 			omap3_cm_restore_context();
 			omap3_sram_restore_context();
 			omap2_sms_restore_context();
 		}
-		if (core_next_state == PWRDM_POWER_OFF)
+		if (core_next_state == PWRDM_FUNC_PWRST_OFF)
 			omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
 					       OMAP3430_GR_MOD,
 					       OMAP3_PRM_VOLTCTRL_OFFSET);
@@ -375,13 +379,13 @@ void omap_sram_idle(void)
 	pwrdm_post_transition();
 
 	/* PER */
-	if (per_next_state < PWRDM_POWER_ON)
+	if (per_next_state < PWRDM_FUNC_PWRST_ON)
 		omap2_gpio_resume_after_idle();
 
 	/* Disable IO-PAD and IO-CHAIN wakeup */
 	if (omap3_has_io_wakeup() &&
-	    (per_next_state < PWRDM_POWER_ON ||
-	     core_next_state < PWRDM_POWER_ON)) {
+	    (per_next_state < PWRDM_FUNC_PWRST_ON ||
+	     core_next_state < PWRDM_FUNC_PWRST_ON)) {
 		omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
 					     PM_WKEN);
 		if (omap3_has_io_chain_ctrl())
@@ -418,7 +422,7 @@ static int omap3_pm_suspend(void)
 
 	/* Read current next_pwrsts */
 	list_for_each_entry(pwrst, &pwrst_list, node)
-		pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
+		pwrst->saved_state = pwrdm_read_next_func_pwrst(pwrst->pwrdm);
 	/* Set ones wanted by suspend */
 	list_for_each_entry(pwrst, &pwrst_list, node) {
 		if (omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state))
@@ -434,7 +438,7 @@ static int omap3_pm_suspend(void)
 restore:
 	/* Restore next_pwrsts */
 	list_for_each_entry(pwrst, &pwrst_list, node) {
-		state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
+		state = pwrdm_read_prev_func_pwrst(pwrst->pwrdm);
 		if (state > pwrst->next_state) {
 			pr_info("Powerdomain (%s) didn't enter "
 				"target state %d\n",
@@ -608,15 +612,15 @@ void omap3_pm_off_mode_enable(int enable)
 	u32 state;
 
 	if (enable)
-		state = PWRDM_POWER_OFF;
+		state = PWRDM_FUNC_PWRST_OFF;
 	else
-		state = PWRDM_POWER_RET;
+		state = PWRDM_FUNC_PWRST_CSWR;
 
 	list_for_each_entry(pwrst, &pwrst_list, node) {
 		if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583) &&
 				pwrst->pwrdm == core_pwrdm &&
-				state == PWRDM_POWER_OFF) {
-			pwrst->next_state = PWRDM_POWER_RET;
+				state == PWRDM_FUNC_PWRST_OFF) {
+			pwrst->next_state = PWRDM_FUNC_PWRST_CSWR;
 			pr_warn("%s: Core OFF disabled due to errata i583\n",
 				__func__);
 		} else {
@@ -661,7 +665,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 	if (!pwrst)
 		return -ENOMEM;
 	pwrst->pwrdm = pwrdm;
-	pwrst->next_state = PWRDM_POWER_RET;
+	pwrst->next_state = PWRDM_FUNC_PWRST_CSWR;
 	list_add(&pwrst->node, &pwrst_list);
 
 	if (pwrdm_has_hdwr_sar(pwrdm))
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index ea24174..98bb699 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -44,7 +44,7 @@ static int omap4_pm_suspend(void)
 
 	/* Save current powerdomain state */
 	list_for_each_entry(pwrst, &pwrst_list, node) {
-		pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
+		pwrst->saved_state = pwrdm_read_next_func_pwrst(pwrst->pwrdm);
 		pwrst->saved_logic_state = pwrdm_read_logic_retst(pwrst->pwrdm);
 	}
 
@@ -63,11 +63,11 @@ static int omap4_pm_suspend(void)
 	 * domain CSWR is not supported by hardware.
 	 * More details can be found in OMAP4430 TRM section 4.3.4.2.
 	 */
-	omap4_enter_lowpower(cpu_id, PWRDM_POWER_OFF);
+	omap4_enter_lowpower(cpu_id, PWRDM_FUNC_PWRST_OFF);
 
 	/* Restore next powerdomain state */
 	list_for_each_entry(pwrst, &pwrst_list, node) {
-		state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
+		state = pwrdm_read_prev_func_pwrst(pwrst->pwrdm);
 		if (state > pwrst->next_state) {
 			pr_info("Powerdomain (%s) didn't enter "
 			       "target state %d\n",
@@ -113,7 +113,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 		return -ENOMEM;
 
 	pwrst->pwrdm = pwrdm;
-	pwrst->next_state = PWRDM_POWER_RET;
+	pwrst->next_state = PWRDM_FUNC_PWRST_CSWR;
 	list_add(&pwrst->node, &pwrst_list);
 
 	return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index e79b5ae..ec2b21c 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -270,7 +270,7 @@ int pwrdm_complete_init(void)
 		return -EACCES;
 
 	list_for_each_entry(temp_p, &pwrdm_list, node)
-		pwrdm_set_next_pwrst(temp_p, PWRDM_POWER_ON);
+		omap_set_pwrdm_state(temp_p, PWRDM_FUNC_PWRST_ON);
 
 	return 0;
 }
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 4/8] ARM: OMAP2+: PM: introduce power domains logic and memory functional states
  2012-06-14 14:53 ` Jean Pihet
@ 2012-06-14 14:53   ` Jean Pihet
  -1 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-omap, paul, linux-arm-kernel, khilman; +Cc: Jean Pihet

In the new API the functions pwrdm_*_logic_* and pwrdm_*_mem_* take the
functional states as parameter.

OMAP2, OMAP3 and OMAP4 platforms are defining a conversion routine
between the functional state and the logic power state.

The power domains logic state is now derived from the functional
state and the logic state is programmed from omap_set_pwrdm_state.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/powerdomain-common.c   |   41 ++++++++++++--
 arch/arm/mach-omap2/powerdomain.c          |   79 +++++++++++++++++++++------
 arch/arm/mach-omap2/powerdomain.h          |   22 +++++++-
 arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |    2 +
 arch/arm/mach-omap2/powerdomain44xx.c      |    1 +
 5 files changed, 118 insertions(+), 27 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain-common.c b/arch/arm/mach-omap2/powerdomain-common.c
index 2973be7..1ae3659 100644
--- a/arch/arm/mach-omap2/powerdomain-common.c
+++ b/arch/arm/mach-omap2/powerdomain-common.c
@@ -143,6 +143,36 @@ int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
 }
 
 /**
+ * omap2_pwrdm_func_to_logic_pwrst - Convert functional (i.e. logical) to
+ * internal (i.e. registers) values for the power domains logic states.
+ * @struct powerdomain * to convert the values for
+ * @func_pwrst: functional power state
+ *
+ * Returns the internal logic state value for the power domain, or
+ * -EINVAL in case of invalid parameters passed in.
+ */
+int omap2_pwrdm_func_to_logic_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
+{
+	int ret;
+
+	switch (func_pwrst) {
+	case PWRDM_FUNC_PWRST_ON:
+	case PWRDM_FUNC_PWRST_INACTIVE:
+	case PWRDM_FUNC_PWRST_CSWR:
+		ret = PWRDM_LOGIC_MEM_PWRST_RET;
+		break;
+	case PWRDM_FUNC_PWRST_OSWR:
+	case PWRDM_FUNC_PWRST_OFF:
+		ret = PWRDM_LOGIC_MEM_PWRST_OFF;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/**
  * omap2_pwrdm_pwrst_to_func - Convert internal (i.e. registers) to
  * functional (i.e. logical) values for the power domains states.
  * @struct powerdomain * to convert the values for
@@ -151,7 +181,7 @@ int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
  * Returns the functional power state value for the power domain, or
  * -EINVAL in case of invalid parameters passed in.
  */
-int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
+int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic)
 {
 	int ret;
 
@@ -163,11 +193,10 @@ int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
 		ret = PWRDM_FUNC_PWRST_INACTIVE;
 		break;
 	case PWRDM_POWER_RET:
-		/*
-		 * XXX warning: return OSWR in case of pd in RET and
-		 * logic in OFF
-		 */
-		ret = PWRDM_FUNC_PWRST_CSWR;
+		if (logic == PWRDM_LOGIC_MEM_PWRST_RET)
+			ret = PWRDM_FUNC_PWRST_CSWR;
+		else
+			ret = PWRDM_FUNC_PWRST_OSWR;
 		break;
 	case PWRDM_POWER_OFF:
 		ret = PWRDM_FUNC_PWRST_OFF;
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index ec2b21c..ce2685a 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -129,14 +129,14 @@ static void _update_logic_membank_counters(struct powerdomain *pwrdm)
 
 	prev_logic_pwrst = pwrdm_read_prev_logic_pwrst(pwrdm);
 	if ((pwrdm->pwrsts_logic_ret == PWRSTS_OFF_RET) &&
-	    (prev_logic_pwrst == PWRDM_POWER_OFF))
+	    (prev_logic_pwrst == PWRDM_LOGIC_MEM_PWRST_OFF))
 		pwrdm->ret_logic_off_counter++;
 
 	for (i = 0; i < pwrdm->banks; i++) {
 		prev_mem_pwrst = pwrdm_read_prev_mem_pwrst(pwrdm, i);
 
 		if ((pwrdm->pwrsts_mem_ret[i] == PWRSTS_OFF_RET) &&
-		    (prev_mem_pwrst == PWRDM_POWER_OFF))
+		    (prev_mem_pwrst == PWRDM_LOGIC_MEM_PWRST_OFF))
 			pwrdm->ret_mem_off_counter[i]++;
 	}
 }
@@ -493,27 +493,63 @@ int pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
 }
 
 /**
+ * pwrdm_func_to_logic_pwrst - get the internal (i.e. registers) value
+ * of the logic state mapped to the functional state
+ * @pwrdm: struct powerdomain * to query
+ * @func_pwrst: functional power state
+ *
+ * Convert the functional power state to the platform specific power
+ * domain logic state value.
+ * Returns the internal power domain logic state value or -EINVAL in
+ * case of invalid parameters passed in.
+ */
+int pwrdm_func_to_logic_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
+{
+	int ret = func_pwrst;
+
+	if ((!pwrdm) || (func_pwrst >= PWRDM_MAX_FUNC_PWRSTS))
+		return -EINVAL;
+
+	if (arch_pwrdm && arch_pwrdm->pwrdm_func_to_logic_pwrst)
+		ret = arch_pwrdm->pwrdm_func_to_logic_pwrst(pwrdm, func_pwrst);
+
+	pr_debug("powerdomain: convert func %0x to logic %0x pwrst for %s\n",
+		 func_pwrst, ret, pwrdm->name);
+
+	return ret;
+}
+
+/**
  * pwrdm_pwrst_to_func - get the functional (i.e. logical) value mapped
  * to the internal state
  * @pwrdm: struct powerdomain * to query
  * @pwrst: internal power state
+ * @logic: internal logic state
  *
- * Convert the internal power state to the power domain functional value.
+ * Convert the internal power state and logic power state
+ * to the power domain functional value.
  * Returns the functional power domain state value or -EINVAL in case
  * of invalid parameters passed in.
  */
-int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
+int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic)
 {
 	int ret = pwrst;
 
-	if ((!pwrdm) || (pwrst >= PWRDM_MAX_PWRSTS))
+	if ((!pwrdm) || (pwrst >= PWRDM_MAX_PWRSTS) ||
+	    (logic >= PWRDM_MAX_LOGIC_MEM_PWRST))
 		return -EINVAL;
 
-	pr_debug("powerdomain: convert %0x pwrst to func for %s\n",
-		 pwrst, pwrdm->name);
+	while (!(pwrdm->pwrsts_logic_ret & (1 << logic))) {
+		if (logic == PWRDM_LOGIC_MEM_PWRST_RET)
+			break;
+		logic++;
+	}
 
 	if (arch_pwrdm && arch_pwrdm->pwrdm_pwrst_to_func)
-		ret = arch_pwrdm->pwrdm_pwrst_to_func(pwrdm, pwrst);
+		ret = arch_pwrdm->pwrdm_pwrst_to_func(pwrdm, pwrst, logic);
+
+	pr_debug("powerdomain: convert pwrst (%0x,%0x) to func %0x for %s\n",
+		 pwrst, logic, ret, pwrdm->name);
 
 	return ret;
 }
@@ -535,9 +571,10 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm,
 {
 	u8 curr_pwrst, next_pwrst;
 	int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
+	int logic = pwrdm_func_to_logic_pwrst(pwrdm, func_pwrst);
 	int sleep_switch = -1, ret = 0, hwsup = 0;
 
-	if (!pwrdm || IS_ERR(pwrdm) || (pwrst < 0)) {
+	if (!pwrdm || IS_ERR(pwrdm) || (pwrst < 0) || (logic < 0)) {
 		pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
 			 __func__, pwrdm, func_pwrst);
 		return -EINVAL;
@@ -570,6 +607,9 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm,
 		}
 	}
 
+	if (logic != pwrdm_read_logic_retst(pwrdm))
+		pwrdm_set_logic_retst(pwrdm, logic);
+
 	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
 	if (ret)
 		pr_err("%s: unable to set power state of powerdomain: %s\n",
@@ -660,9 +700,10 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
  */
 int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm)
 {
-	int ret = pwrdm_read_next_pwrst(pwrdm);
+	int next_pwrst = pwrdm_read_next_pwrst(pwrdm);
+	int next_logic = pwrdm_read_logic_retst(pwrdm);
 
-	return pwrdm_pwrst_to_func(pwrdm, ret);
+	return pwrdm_pwrst_to_func(pwrdm, next_pwrst, next_logic);
 }
 
 /**
@@ -696,9 +737,10 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm)
  */
 int pwrdm_read_func_pwrst(struct powerdomain *pwrdm)
 {
-	int ret = pwrdm_read_pwrst(pwrdm);
+	int pwrst = pwrdm_read_pwrst(pwrdm);
+	int logic = pwrdm_read_logic_pwrst(pwrdm);
 
-	return pwrdm_pwrst_to_func(pwrdm, ret);
+	return pwrdm_pwrst_to_func(pwrdm, pwrst, logic);
 }
 
 /**
@@ -732,15 +774,16 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
  */
 int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm)
 {
-	int ret = pwrdm_read_prev_pwrst(pwrdm);
+	int prev_pwrst = pwrdm_read_prev_pwrst(pwrdm);
+	int prev_logic = pwrdm_read_prev_logic_pwrst(pwrdm);
 
-	return pwrdm_pwrst_to_func(pwrdm, ret);
+	return pwrdm_pwrst_to_func(pwrdm, prev_pwrst, prev_logic);
 }
 
 /**
  * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
  * @pwrdm: struct powerdomain * to set
- * @pwrst: one of the PWRDM_POWER_* macros
+ * @pwrst: one of the PWRDM_LOGIC_MEM_PWRST_* macros
  *
  * Set the next power state @pwrst that the logic portion of the
  * powerdomain @pwrdm will enter when the powerdomain enters retention.
@@ -771,7 +814,7 @@ int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
  * pwrdm_set_mem_onst - set memory power state while powerdomain ON
  * @pwrdm: struct powerdomain * to set
  * @bank: memory bank number to set (0-3)
- * @pwrst: one of the PWRDM_POWER_* macros
+ * @pwrst: one of the PWRDM_LOGIC_MEM_PWRST_* macros
  *
  * Set the next power state @pwrst that memory bank @bank of the
  * powerdomain @pwrdm will enter when the powerdomain enters the ON
@@ -808,7 +851,7 @@ int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
  * pwrdm_set_mem_retst - set memory power state while powerdomain in RET
  * @pwrdm: struct powerdomain * to set
  * @bank: memory bank number to set (0-3)
- * @pwrst: one of the PWRDM_POWER_* macros
+ * @pwrst: one of the PWRDM_LOGIC_MEM_PWRST_* macros
  *
  * Set the next power state @pwrst that memory bank @bank of the
  * powerdomain @pwrdm will enter when the powerdomain enters the
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index 0404f9f..d08c25d 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -37,6 +37,16 @@ enum pwrdm_func_state {
 	PWRDM_MAX_FUNC_PWRSTS		/* Last value, used as the max value */
 };
 
+/*
+ * Powerdomains logic and memory functional power states,
+ * used by the external API functions
+ */
+enum pwrdm_logic_mem_state {
+	PWRDM_LOGIC_MEM_PWRST_OFF	= 0x0,
+	PWRDM_LOGIC_MEM_PWRST_RET,
+	PWRDM_MAX_LOGIC_MEM_PWRST	/* Last value, used as the max value */
+};
+
 struct clockdomain;
 struct powerdomain;
 
@@ -169,7 +179,9 @@ struct powerdomain {
  * struct pwrdm_ops - Arch specific function implementations
  * @pwrdm_func_to_pwrst: Convert the pd functional power state to
  *  the internal state
- * @pwrdm_pwrst_to_func: Convert the pd internal power state to
+ * @pwrdm_func_to_logic_pwrst: Convert the pd functional power state
+ *  to the internal logic state
+ * @pwrdm_pwrst_to_func: Convert the pd internal and logic power state to
  *  the functional state
  * @pwrdm_set_next_pwrst: Set the target power state for a pd
  * @pwrdm_read_next_pwrst: Read the target power state set for a pd
@@ -192,7 +204,10 @@ struct powerdomain {
  */
 struct pwrdm_ops {
 	int	(*pwrdm_func_to_pwrst)(struct powerdomain *pwrdm, u8 func_pwrst);
-	int	(*pwrdm_pwrst_to_func)(struct powerdomain *pwrdm, u8 func_pwrst);
+	int	(*pwrdm_func_to_logic_pwrst)(struct powerdomain *pwrdm,
+					     u8 func_pwrst);
+	int	(*pwrdm_pwrst_to_func)(struct powerdomain *pwrdm, u8 func_pwrst,
+				       u8 logic);
 	int	(*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst);
 	int	(*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm);
 	int	(*pwrdm_read_pwrst)(struct powerdomain *pwrdm);
@@ -230,7 +245,8 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
 int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
 
 int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
-int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst);
+int omap2_pwrdm_func_to_logic_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
+int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic);
 
 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
index 79c1293..6a3ea3d 100644
--- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
@@ -212,6 +212,7 @@ static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
 
 struct pwrdm_ops omap2_pwrdm_operations = {
 	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_func_to_logic_pwrst	= omap2_pwrdm_func_to_logic_pwrst,
 	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
@@ -226,6 +227,7 @@ struct pwrdm_ops omap2_pwrdm_operations = {
 
 struct pwrdm_ops omap3_pwrdm_operations = {
 	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_func_to_logic_pwrst	= omap2_pwrdm_func_to_logic_pwrst,
 	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
index 538b528..030d10c 100644
--- a/arch/arm/mach-omap2/powerdomain44xx.c
+++ b/arch/arm/mach-omap2/powerdomain44xx.c
@@ -210,6 +210,7 @@ static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
 
 struct pwrdm_ops omap4_pwrdm_operations = {
 	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_func_to_logic_pwrst	= omap2_pwrdm_func_to_logic_pwrst,
 	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap4_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap4_pwrdm_read_next_pwrst,
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 4/8] ARM: OMAP2+: PM: introduce power domains logic and memory functional states
@ 2012-06-14 14:53   ` Jean Pihet
  0 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-arm-kernel

In the new API the functions pwrdm_*_logic_* and pwrdm_*_mem_* take the
functional states as parameter.

OMAP2, OMAP3 and OMAP4 platforms are defining a conversion routine
between the functional state and the logic power state.

The power domains logic state is now derived from the functional
state and the logic state is programmed from omap_set_pwrdm_state.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/powerdomain-common.c   |   41 ++++++++++++--
 arch/arm/mach-omap2/powerdomain.c          |   79 +++++++++++++++++++++------
 arch/arm/mach-omap2/powerdomain.h          |   22 +++++++-
 arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |    2 +
 arch/arm/mach-omap2/powerdomain44xx.c      |    1 +
 5 files changed, 118 insertions(+), 27 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain-common.c b/arch/arm/mach-omap2/powerdomain-common.c
index 2973be7..1ae3659 100644
--- a/arch/arm/mach-omap2/powerdomain-common.c
+++ b/arch/arm/mach-omap2/powerdomain-common.c
@@ -143,6 +143,36 @@ int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
 }
 
 /**
+ * omap2_pwrdm_func_to_logic_pwrst - Convert functional (i.e. logical) to
+ * internal (i.e. registers) values for the power domains logic states.
+ * @struct powerdomain * to convert the values for
+ * @func_pwrst: functional power state
+ *
+ * Returns the internal logic state value for the power domain, or
+ * -EINVAL in case of invalid parameters passed in.
+ */
+int omap2_pwrdm_func_to_logic_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
+{
+	int ret;
+
+	switch (func_pwrst) {
+	case PWRDM_FUNC_PWRST_ON:
+	case PWRDM_FUNC_PWRST_INACTIVE:
+	case PWRDM_FUNC_PWRST_CSWR:
+		ret = PWRDM_LOGIC_MEM_PWRST_RET;
+		break;
+	case PWRDM_FUNC_PWRST_OSWR:
+	case PWRDM_FUNC_PWRST_OFF:
+		ret = PWRDM_LOGIC_MEM_PWRST_OFF;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/**
  * omap2_pwrdm_pwrst_to_func - Convert internal (i.e. registers) to
  * functional (i.e. logical) values for the power domains states.
  * @struct powerdomain * to convert the values for
@@ -151,7 +181,7 @@ int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
  * Returns the functional power state value for the power domain, or
  * -EINVAL in case of invalid parameters passed in.
  */
-int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
+int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic)
 {
 	int ret;
 
@@ -163,11 +193,10 @@ int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
 		ret = PWRDM_FUNC_PWRST_INACTIVE;
 		break;
 	case PWRDM_POWER_RET:
-		/*
-		 * XXX warning: return OSWR in case of pd in RET and
-		 * logic in OFF
-		 */
-		ret = PWRDM_FUNC_PWRST_CSWR;
+		if (logic == PWRDM_LOGIC_MEM_PWRST_RET)
+			ret = PWRDM_FUNC_PWRST_CSWR;
+		else
+			ret = PWRDM_FUNC_PWRST_OSWR;
 		break;
 	case PWRDM_POWER_OFF:
 		ret = PWRDM_FUNC_PWRST_OFF;
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index ec2b21c..ce2685a 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -129,14 +129,14 @@ static void _update_logic_membank_counters(struct powerdomain *pwrdm)
 
 	prev_logic_pwrst = pwrdm_read_prev_logic_pwrst(pwrdm);
 	if ((pwrdm->pwrsts_logic_ret == PWRSTS_OFF_RET) &&
-	    (prev_logic_pwrst == PWRDM_POWER_OFF))
+	    (prev_logic_pwrst == PWRDM_LOGIC_MEM_PWRST_OFF))
 		pwrdm->ret_logic_off_counter++;
 
 	for (i = 0; i < pwrdm->banks; i++) {
 		prev_mem_pwrst = pwrdm_read_prev_mem_pwrst(pwrdm, i);
 
 		if ((pwrdm->pwrsts_mem_ret[i] == PWRSTS_OFF_RET) &&
-		    (prev_mem_pwrst == PWRDM_POWER_OFF))
+		    (prev_mem_pwrst == PWRDM_LOGIC_MEM_PWRST_OFF))
 			pwrdm->ret_mem_off_counter[i]++;
 	}
 }
@@ -493,27 +493,63 @@ int pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
 }
 
 /**
+ * pwrdm_func_to_logic_pwrst - get the internal (i.e. registers) value
+ * of the logic state mapped to the functional state
+ * @pwrdm: struct powerdomain * to query
+ * @func_pwrst: functional power state
+ *
+ * Convert the functional power state to the platform specific power
+ * domain logic state value.
+ * Returns the internal power domain logic state value or -EINVAL in
+ * case of invalid parameters passed in.
+ */
+int pwrdm_func_to_logic_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
+{
+	int ret = func_pwrst;
+
+	if ((!pwrdm) || (func_pwrst >= PWRDM_MAX_FUNC_PWRSTS))
+		return -EINVAL;
+
+	if (arch_pwrdm && arch_pwrdm->pwrdm_func_to_logic_pwrst)
+		ret = arch_pwrdm->pwrdm_func_to_logic_pwrst(pwrdm, func_pwrst);
+
+	pr_debug("powerdomain: convert func %0x to logic %0x pwrst for %s\n",
+		 func_pwrst, ret, pwrdm->name);
+
+	return ret;
+}
+
+/**
  * pwrdm_pwrst_to_func - get the functional (i.e. logical) value mapped
  * to the internal state
  * @pwrdm: struct powerdomain * to query
  * @pwrst: internal power state
+ * @logic: internal logic state
  *
- * Convert the internal power state to the power domain functional value.
+ * Convert the internal power state and logic power state
+ * to the power domain functional value.
  * Returns the functional power domain state value or -EINVAL in case
  * of invalid parameters passed in.
  */
-int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
+int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic)
 {
 	int ret = pwrst;
 
-	if ((!pwrdm) || (pwrst >= PWRDM_MAX_PWRSTS))
+	if ((!pwrdm) || (pwrst >= PWRDM_MAX_PWRSTS) ||
+	    (logic >= PWRDM_MAX_LOGIC_MEM_PWRST))
 		return -EINVAL;
 
-	pr_debug("powerdomain: convert %0x pwrst to func for %s\n",
-		 pwrst, pwrdm->name);
+	while (!(pwrdm->pwrsts_logic_ret & (1 << logic))) {
+		if (logic == PWRDM_LOGIC_MEM_PWRST_RET)
+			break;
+		logic++;
+	}
 
 	if (arch_pwrdm && arch_pwrdm->pwrdm_pwrst_to_func)
-		ret = arch_pwrdm->pwrdm_pwrst_to_func(pwrdm, pwrst);
+		ret = arch_pwrdm->pwrdm_pwrst_to_func(pwrdm, pwrst, logic);
+
+	pr_debug("powerdomain: convert pwrst (%0x,%0x) to func %0x for %s\n",
+		 pwrst, logic, ret, pwrdm->name);
 
 	return ret;
 }
@@ -535,9 +571,10 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm,
 {
 	u8 curr_pwrst, next_pwrst;
 	int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
+	int logic = pwrdm_func_to_logic_pwrst(pwrdm, func_pwrst);
 	int sleep_switch = -1, ret = 0, hwsup = 0;
 
-	if (!pwrdm || IS_ERR(pwrdm) || (pwrst < 0)) {
+	if (!pwrdm || IS_ERR(pwrdm) || (pwrst < 0) || (logic < 0)) {
 		pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
 			 __func__, pwrdm, func_pwrst);
 		return -EINVAL;
@@ -570,6 +607,9 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm,
 		}
 	}
 
+	if (logic != pwrdm_read_logic_retst(pwrdm))
+		pwrdm_set_logic_retst(pwrdm, logic);
+
 	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
 	if (ret)
 		pr_err("%s: unable to set power state of powerdomain: %s\n",
@@ -660,9 +700,10 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
  */
 int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm)
 {
-	int ret = pwrdm_read_next_pwrst(pwrdm);
+	int next_pwrst = pwrdm_read_next_pwrst(pwrdm);
+	int next_logic = pwrdm_read_logic_retst(pwrdm);
 
-	return pwrdm_pwrst_to_func(pwrdm, ret);
+	return pwrdm_pwrst_to_func(pwrdm, next_pwrst, next_logic);
 }
 
 /**
@@ -696,9 +737,10 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm)
  */
 int pwrdm_read_func_pwrst(struct powerdomain *pwrdm)
 {
-	int ret = pwrdm_read_pwrst(pwrdm);
+	int pwrst = pwrdm_read_pwrst(pwrdm);
+	int logic = pwrdm_read_logic_pwrst(pwrdm);
 
-	return pwrdm_pwrst_to_func(pwrdm, ret);
+	return pwrdm_pwrst_to_func(pwrdm, pwrst, logic);
 }
 
 /**
@@ -732,15 +774,16 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
  */
 int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm)
 {
-	int ret = pwrdm_read_prev_pwrst(pwrdm);
+	int prev_pwrst = pwrdm_read_prev_pwrst(pwrdm);
+	int prev_logic = pwrdm_read_prev_logic_pwrst(pwrdm);
 
-	return pwrdm_pwrst_to_func(pwrdm, ret);
+	return pwrdm_pwrst_to_func(pwrdm, prev_pwrst, prev_logic);
 }
 
 /**
  * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
  * @pwrdm: struct powerdomain * to set
- * @pwrst: one of the PWRDM_POWER_* macros
+ * @pwrst: one of the PWRDM_LOGIC_MEM_PWRST_* macros
  *
  * Set the next power state @pwrst that the logic portion of the
  * powerdomain @pwrdm will enter when the powerdomain enters retention.
@@ -771,7 +814,7 @@ int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
  * pwrdm_set_mem_onst - set memory power state while powerdomain ON
  * @pwrdm: struct powerdomain * to set
  * @bank: memory bank number to set (0-3)
- * @pwrst: one of the PWRDM_POWER_* macros
+ * @pwrst: one of the PWRDM_LOGIC_MEM_PWRST_* macros
  *
  * Set the next power state @pwrst that memory bank @bank of the
  * powerdomain @pwrdm will enter when the powerdomain enters the ON
@@ -808,7 +851,7 @@ int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
  * pwrdm_set_mem_retst - set memory power state while powerdomain in RET
  * @pwrdm: struct powerdomain * to set
  * @bank: memory bank number to set (0-3)
- * @pwrst: one of the PWRDM_POWER_* macros
+ * @pwrst: one of the PWRDM_LOGIC_MEM_PWRST_* macros
  *
  * Set the next power state @pwrst that memory bank @bank of the
  * powerdomain @pwrdm will enter when the powerdomain enters the
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index 0404f9f..d08c25d 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -37,6 +37,16 @@ enum pwrdm_func_state {
 	PWRDM_MAX_FUNC_PWRSTS		/* Last value, used as the max value */
 };
 
+/*
+ * Powerdomains logic and memory functional power states,
+ * used by the external API functions
+ */
+enum pwrdm_logic_mem_state {
+	PWRDM_LOGIC_MEM_PWRST_OFF	= 0x0,
+	PWRDM_LOGIC_MEM_PWRST_RET,
+	PWRDM_MAX_LOGIC_MEM_PWRST	/* Last value, used as the max value */
+};
+
 struct clockdomain;
 struct powerdomain;
 
@@ -169,7 +179,9 @@ struct powerdomain {
  * struct pwrdm_ops - Arch specific function implementations
  * @pwrdm_func_to_pwrst: Convert the pd functional power state to
  *  the internal state
- * @pwrdm_pwrst_to_func: Convert the pd internal power state to
+ * @pwrdm_func_to_logic_pwrst: Convert the pd functional power state
+ *  to the internal logic state
+ * @pwrdm_pwrst_to_func: Convert the pd internal and logic power state to
  *  the functional state
  * @pwrdm_set_next_pwrst: Set the target power state for a pd
  * @pwrdm_read_next_pwrst: Read the target power state set for a pd
@@ -192,7 +204,10 @@ struct powerdomain {
  */
 struct pwrdm_ops {
 	int	(*pwrdm_func_to_pwrst)(struct powerdomain *pwrdm, u8 func_pwrst);
-	int	(*pwrdm_pwrst_to_func)(struct powerdomain *pwrdm, u8 func_pwrst);
+	int	(*pwrdm_func_to_logic_pwrst)(struct powerdomain *pwrdm,
+					     u8 func_pwrst);
+	int	(*pwrdm_pwrst_to_func)(struct powerdomain *pwrdm, u8 func_pwrst,
+				       u8 logic);
 	int	(*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst);
 	int	(*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm);
 	int	(*pwrdm_read_pwrst)(struct powerdomain *pwrdm);
@@ -230,7 +245,8 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
 int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
 
 int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
-int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst);
+int omap2_pwrdm_func_to_logic_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
+int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic);
 
 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
index 79c1293..6a3ea3d 100644
--- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
@@ -212,6 +212,7 @@ static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
 
 struct pwrdm_ops omap2_pwrdm_operations = {
 	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_func_to_logic_pwrst	= omap2_pwrdm_func_to_logic_pwrst,
 	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
@@ -226,6 +227,7 @@ struct pwrdm_ops omap2_pwrdm_operations = {
 
 struct pwrdm_ops omap3_pwrdm_operations = {
 	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_func_to_logic_pwrst	= omap2_pwrdm_func_to_logic_pwrst,
 	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
index 538b528..030d10c 100644
--- a/arch/arm/mach-omap2/powerdomain44xx.c
+++ b/arch/arm/mach-omap2/powerdomain44xx.c
@@ -210,6 +210,7 @@ static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
 
 struct pwrdm_ops omap4_pwrdm_operations = {
 	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_func_to_logic_pwrst	= omap2_pwrdm_func_to_logic_pwrst,
 	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap4_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap4_pwrdm_read_next_pwrst,
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 5/8] ARM: OMAP2+: PM: introduce power domains achievable functional states
  2012-06-14 14:53 ` Jean Pihet
@ 2012-06-14 14:53   ` Jean Pihet
  -1 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-omap, paul, linux-arm-kernel, khilman; +Cc: Jean Pihet, Tero Kristo

Note: the patch is in RFC state because the state machine for setting
the next power domain states needs more discussion. Validated on OMAP3&4
with cpuidle and suspend/resume, though.

Power domains have varied capabilities. When attempting a low power
state such as OFF/RET, a specific min requested state may not be
supported on the power domain. This is because a combination
of system power states where the parent PD's state is not in line
with expectation can result in system instabilities.

This patch provides a function that returns the achievable functional
power state for a power domain and its use by omap_set_pwrdm_state.
The achievable power state is first looked for in the lower power
states in order to maximize the power savings, then if not found
in the higher power states.

Inspired from Tero's work on OMAP4 device OFF support and generalized
to the functional power states.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
Cc: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/powerdomain.c |  156 +++++++++++++++++++++++++++++++------
 arch/arm/mach-omap2/powerdomain.h |    1 +
 2 files changed, 134 insertions(+), 23 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index ce2685a..f94174b 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -554,6 +554,108 @@ int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic)
 	return ret;
 }
 
+/**
+ * pwrdm_get_achievable_func_pwrst() - Provide achievable functional state
+ * @pwrdm: struct powerdomain * to set
+ * @func_pwrst: minimum functional state we would like to hit
+ * (one of the PWRDM_FUNC_* macros)
+ *
+ * Power domains have varied capabilities. When attempting a low power
+ * state such as OFF/RET, a specific min requested state may not be
+ * supported on the power domain. This is because a combination
+ * of system power states where the parent PD's state is not in line
+ * with expectation can result in system instabilities.
+ *
+ * The achievable power state is first looked for in the lower power
+ * states in order to maximize the power savings, then if not found
+ * in the higher power states.
+ *
+ * Returns the achievable functional power state, or -EINVAL in case of
+ * invalid parameters.
+ */
+int pwrdm_get_achievable_func_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
+{
+	int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
+	int logic = pwrdm_func_to_logic_pwrst(pwrdm, func_pwrst);
+	int new_func_pwrst, new_pwrst, new_logic;
+	int found;
+
+	if (!pwrdm || IS_ERR(pwrdm)) {
+		pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
+			 __func__, pwrdm, func_pwrst);
+		return -EINVAL;
+	}
+
+	if ((pwrst < 0) || (logic < 0)) {
+		pr_debug("%s: invalid params for pwrdm %s, func_pwrst=%0x\n",
+			 __func__, pwrdm->name, func_pwrst);
+		return PWRDM_FUNC_PWRST_ON;
+	}
+
+	/*
+	 * Power state: if the requested state is not supported,
+	 * try the lower power states.
+	 */
+	found = 1;
+	new_pwrst = pwrst;
+	while (!(pwrdm->pwrsts & (1 << new_pwrst))) {
+		if (new_pwrst == PWRDM_POWER_OFF) {
+			found = 0;
+			break;
+		}
+		new_pwrst--;
+	}
+
+	/*
+	 * If no lower power state found, fallback to the higher
+	 * power states.
+	 * PWRDM_POWER_ON is always valid.
+	 */
+	if (!found) {
+		new_pwrst = pwrst;
+		while (!(pwrdm->pwrsts & (1 << new_pwrst))) {
+			if (new_pwrst == PWRDM_POWER_ON)
+				break;
+			new_pwrst++;
+		}
+	}
+
+	/*
+	 * Logic RET state: if the requested state is not supported,
+	 * try the lower logic states.
+	 */
+	found = 1;
+	new_logic = logic;
+	while (!(pwrdm->pwrsts_logic_ret & (1 << new_logic))) {
+		if (new_logic == PWRDM_LOGIC_MEM_PWRST_OFF) {
+			found = 0;
+			break;
+		}
+		new_logic--;
+	}
+
+	/*
+	 * If no lower logic state found, fallback to the higher
+	 * logic states.
+	 * PWRDM_LOGIC_MEM_PWRST_RET is always valid.
+	 */
+	if (!found) {
+		new_logic = logic;
+		while (!(pwrdm->pwrsts_logic_ret & (1 << new_logic))) {
+			if (new_logic == PWRDM_LOGIC_MEM_PWRST_RET)
+				break;
+			new_logic++;
+		}
+	}
+
+	new_func_pwrst = pwrdm_pwrst_to_func(pwrdm, new_pwrst, new_logic);
+
+	pr_debug("%s(%s, func_pwrst=%0x) returns %0x\n", __func__,
+		 pwrdm->name, func_pwrst, new_func_pwrst);
+
+	return new_func_pwrst;
+}
+
 /* Types of sleep_switch used in omap_set_pwrdm_state */
 #define FORCEWAKEUP_SWITCH	0
 #define LOWPOWERSTATE_SWITCH	1
@@ -563,36 +665,32 @@ int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic)
  * @pwrdm: struct powerdomain * to set
  * @func_pwrst: power domain functional state, one of the PWRDM_FUNC_* macros
  *
- * This programs the pwrdm next functional state, sets the dependencies
- * and waits for the state to be applied.
+ * This looks for the more suited (or achievable) next functional power
+ * state, programs it, sets the dependencies and waits for the state to
+ * be applied to the power domain.
  */
 int omap_set_pwrdm_state(struct powerdomain *pwrdm,
 			 enum pwrdm_func_state func_pwrst)
 {
-	u8 curr_pwrst, next_pwrst;
-	int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
-	int logic = pwrdm_func_to_logic_pwrst(pwrdm, func_pwrst);
 	int sleep_switch = -1, ret = 0, hwsup = 0;
+	int new_func_pwrst, next_func_pwrst, pwrst, logic;
+	u8 curr_pwrst;
 
-	if (!pwrdm || IS_ERR(pwrdm) || (pwrst < 0) || (logic < 0)) {
-		pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
-			 __func__, pwrdm, func_pwrst);
+	if (!pwrdm || IS_ERR(pwrdm)) {
+		pr_debug("%s: invalid params: pwrdm=%p\n", __func__, pwrdm);
 		return -EINVAL;
 	}
 
-	pr_debug("%s: set func_pwrst %0x to pwrdm %s\n",
-		 __func__, func_pwrst, pwrdm->name);
+	pr_debug("%s(%s, func_pwrst=%0x)\n", __func__, pwrdm->name, func_pwrst);
 
 	mutex_lock(&pwrdm->lock);
 
-	while (!(pwrdm->pwrsts & (1 << pwrst))) {
-		if (pwrst == PWRDM_POWER_OFF)
-			goto out;
-		pwrst--;
-	}
+	new_func_pwrst = pwrdm_get_achievable_func_pwrst(pwrdm, func_pwrst);
+	pwrst = pwrdm_func_to_pwrst(pwrdm, new_func_pwrst);
+	logic = pwrdm_func_to_logic_pwrst(pwrdm, new_func_pwrst);
 
-	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
-	if (next_pwrst == pwrst)
+	next_func_pwrst = pwrdm_read_next_func_pwrst(pwrdm);
+	if (new_func_pwrst == next_func_pwrst)
 		goto out;
 
 	curr_pwrst = pwrdm_read_pwrst(pwrdm);
@@ -607,13 +705,25 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm,
 		}
 	}
 
-	if (logic != pwrdm_read_logic_retst(pwrdm))
-		pwrdm_set_logic_retst(pwrdm, logic);
+	pr_debug("%s: set func_pwrst %0x (%0x,%0x) to pwrdm %s\n",
+		 __func__, new_func_pwrst, pwrst, logic, pwrdm->name);
+
+	/* Trace the pwrdm desired target state */
+	trace_power_domain_target(pwrdm->name, new_func_pwrst,
+				  smp_processor_id());
+
+	/* Program next power state */
+	if (pwrst != pwrdm_func_to_pwrst(pwrdm, next_func_pwrst)) {
+		ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
+		if (ret)
+			pr_err("%s: unable to set power state of powerdomain: %s\n",
+			       __func__, pwrdm->name);
+	}
 
-	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
-	if (ret)
-		pr_err("%s: unable to set power state of powerdomain: %s\n",
-		       __func__, pwrdm->name);
+	/* Program RET logic state */
+	if ((pwrst == PWRDM_POWER_RET) &&
+	    (logic != pwrdm_func_to_logic_pwrst(pwrdm, next_func_pwrst)))
+		pwrdm_set_logic_retst(pwrdm, logic);
 
 	switch (sleep_switch) {
 	case FORCEWAKEUP_SWITCH:
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index d08c25d..9dd68ab 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -247,6 +247,7 @@ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
 int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
 int omap2_pwrdm_func_to_logic_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
 int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic);
+int pwrdm_get_achievable_func_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
 
 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 5/8] ARM: OMAP2+: PM: introduce power domains achievable functional states
@ 2012-06-14 14:53   ` Jean Pihet
  0 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-arm-kernel

Note: the patch is in RFC state because the state machine for setting
the next power domain states needs more discussion. Validated on OMAP3&4
with cpuidle and suspend/resume, though.

Power domains have varied capabilities. When attempting a low power
state such as OFF/RET, a specific min requested state may not be
supported on the power domain. This is because a combination
of system power states where the parent PD's state is not in line
with expectation can result in system instabilities.

This patch provides a function that returns the achievable functional
power state for a power domain and its use by omap_set_pwrdm_state.
The achievable power state is first looked for in the lower power
states in order to maximize the power savings, then if not found
in the higher power states.

Inspired from Tero's work on OMAP4 device OFF support and generalized
to the functional power states.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
Cc: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/powerdomain.c |  156 +++++++++++++++++++++++++++++++------
 arch/arm/mach-omap2/powerdomain.h |    1 +
 2 files changed, 134 insertions(+), 23 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index ce2685a..f94174b 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -554,6 +554,108 @@ int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic)
 	return ret;
 }
 
+/**
+ * pwrdm_get_achievable_func_pwrst() - Provide achievable functional state
+ * @pwrdm: struct powerdomain * to set
+ * @func_pwrst: minimum functional state we would like to hit
+ * (one of the PWRDM_FUNC_* macros)
+ *
+ * Power domains have varied capabilities. When attempting a low power
+ * state such as OFF/RET, a specific min requested state may not be
+ * supported on the power domain. This is because a combination
+ * of system power states where the parent PD's state is not in line
+ * with expectation can result in system instabilities.
+ *
+ * The achievable power state is first looked for in the lower power
+ * states in order to maximize the power savings, then if not found
+ * in the higher power states.
+ *
+ * Returns the achievable functional power state, or -EINVAL in case of
+ * invalid parameters.
+ */
+int pwrdm_get_achievable_func_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
+{
+	int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
+	int logic = pwrdm_func_to_logic_pwrst(pwrdm, func_pwrst);
+	int new_func_pwrst, new_pwrst, new_logic;
+	int found;
+
+	if (!pwrdm || IS_ERR(pwrdm)) {
+		pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
+			 __func__, pwrdm, func_pwrst);
+		return -EINVAL;
+	}
+
+	if ((pwrst < 0) || (logic < 0)) {
+		pr_debug("%s: invalid params for pwrdm %s, func_pwrst=%0x\n",
+			 __func__, pwrdm->name, func_pwrst);
+		return PWRDM_FUNC_PWRST_ON;
+	}
+
+	/*
+	 * Power state: if the requested state is not supported,
+	 * try the lower power states.
+	 */
+	found = 1;
+	new_pwrst = pwrst;
+	while (!(pwrdm->pwrsts & (1 << new_pwrst))) {
+		if (new_pwrst == PWRDM_POWER_OFF) {
+			found = 0;
+			break;
+		}
+		new_pwrst--;
+	}
+
+	/*
+	 * If no lower power state found, fallback to the higher
+	 * power states.
+	 * PWRDM_POWER_ON is always valid.
+	 */
+	if (!found) {
+		new_pwrst = pwrst;
+		while (!(pwrdm->pwrsts & (1 << new_pwrst))) {
+			if (new_pwrst == PWRDM_POWER_ON)
+				break;
+			new_pwrst++;
+		}
+	}
+
+	/*
+	 * Logic RET state: if the requested state is not supported,
+	 * try the lower logic states.
+	 */
+	found = 1;
+	new_logic = logic;
+	while (!(pwrdm->pwrsts_logic_ret & (1 << new_logic))) {
+		if (new_logic == PWRDM_LOGIC_MEM_PWRST_OFF) {
+			found = 0;
+			break;
+		}
+		new_logic--;
+	}
+
+	/*
+	 * If no lower logic state found, fallback to the higher
+	 * logic states.
+	 * PWRDM_LOGIC_MEM_PWRST_RET is always valid.
+	 */
+	if (!found) {
+		new_logic = logic;
+		while (!(pwrdm->pwrsts_logic_ret & (1 << new_logic))) {
+			if (new_logic == PWRDM_LOGIC_MEM_PWRST_RET)
+				break;
+			new_logic++;
+		}
+	}
+
+	new_func_pwrst = pwrdm_pwrst_to_func(pwrdm, new_pwrst, new_logic);
+
+	pr_debug("%s(%s, func_pwrst=%0x) returns %0x\n", __func__,
+		 pwrdm->name, func_pwrst, new_func_pwrst);
+
+	return new_func_pwrst;
+}
+
 /* Types of sleep_switch used in omap_set_pwrdm_state */
 #define FORCEWAKEUP_SWITCH	0
 #define LOWPOWERSTATE_SWITCH	1
@@ -563,36 +665,32 @@ int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic)
  * @pwrdm: struct powerdomain * to set
  * @func_pwrst: power domain functional state, one of the PWRDM_FUNC_* macros
  *
- * This programs the pwrdm next functional state, sets the dependencies
- * and waits for the state to be applied.
+ * This looks for the more suited (or achievable) next functional power
+ * state, programs it, sets the dependencies and waits for the state to
+ * be applied to the power domain.
  */
 int omap_set_pwrdm_state(struct powerdomain *pwrdm,
 			 enum pwrdm_func_state func_pwrst)
 {
-	u8 curr_pwrst, next_pwrst;
-	int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
-	int logic = pwrdm_func_to_logic_pwrst(pwrdm, func_pwrst);
 	int sleep_switch = -1, ret = 0, hwsup = 0;
+	int new_func_pwrst, next_func_pwrst, pwrst, logic;
+	u8 curr_pwrst;
 
-	if (!pwrdm || IS_ERR(pwrdm) || (pwrst < 0) || (logic < 0)) {
-		pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
-			 __func__, pwrdm, func_pwrst);
+	if (!pwrdm || IS_ERR(pwrdm)) {
+		pr_debug("%s: invalid params: pwrdm=%p\n", __func__, pwrdm);
 		return -EINVAL;
 	}
 
-	pr_debug("%s: set func_pwrst %0x to pwrdm %s\n",
-		 __func__, func_pwrst, pwrdm->name);
+	pr_debug("%s(%s, func_pwrst=%0x)\n", __func__, pwrdm->name, func_pwrst);
 
 	mutex_lock(&pwrdm->lock);
 
-	while (!(pwrdm->pwrsts & (1 << pwrst))) {
-		if (pwrst == PWRDM_POWER_OFF)
-			goto out;
-		pwrst--;
-	}
+	new_func_pwrst = pwrdm_get_achievable_func_pwrst(pwrdm, func_pwrst);
+	pwrst = pwrdm_func_to_pwrst(pwrdm, new_func_pwrst);
+	logic = pwrdm_func_to_logic_pwrst(pwrdm, new_func_pwrst);
 
-	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
-	if (next_pwrst == pwrst)
+	next_func_pwrst = pwrdm_read_next_func_pwrst(pwrdm);
+	if (new_func_pwrst == next_func_pwrst)
 		goto out;
 
 	curr_pwrst = pwrdm_read_pwrst(pwrdm);
@@ -607,13 +705,25 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm,
 		}
 	}
 
-	if (logic != pwrdm_read_logic_retst(pwrdm))
-		pwrdm_set_logic_retst(pwrdm, logic);
+	pr_debug("%s: set func_pwrst %0x (%0x,%0x) to pwrdm %s\n",
+		 __func__, new_func_pwrst, pwrst, logic, pwrdm->name);
+
+	/* Trace the pwrdm desired target state */
+	trace_power_domain_target(pwrdm->name, new_func_pwrst,
+				  smp_processor_id());
+
+	/* Program next power state */
+	if (pwrst != pwrdm_func_to_pwrst(pwrdm, next_func_pwrst)) {
+		ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
+		if (ret)
+			pr_err("%s: unable to set power state of powerdomain: %s\n",
+			       __func__, pwrdm->name);
+	}
 
-	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
-	if (ret)
-		pr_err("%s: unable to set power state of powerdomain: %s\n",
-		       __func__, pwrdm->name);
+	/* Program RET logic state */
+	if ((pwrst == PWRDM_POWER_RET) &&
+	    (logic != pwrdm_func_to_logic_pwrst(pwrdm, next_func_pwrst)))
+		pwrdm_set_logic_retst(pwrdm, logic);
 
 	switch (sleep_switch) {
 	case FORCEWAKEUP_SWITCH:
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index d08c25d..9dd68ab 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -247,6 +247,7 @@ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
 int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
 int omap2_pwrdm_func_to_logic_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
 int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic);
+int pwrdm_get_achievable_func_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
 
 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 6/8] ARM: OMAP2+: PM: use the functional power states API for logic and memory
  2012-06-14 14:53 ` Jean Pihet
@ 2012-06-14 14:53   ` Jean Pihet
  -1 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-omap, paul, linux-arm-kernel, khilman; +Cc: Jean Pihet

Since the power domains logic state is derived from the power domain
functional state and is now programmed from omap_set_pwrdm_state,
the calls to pwrdm_set_logic_retst are removed and the mpu_logic_state
field is removed from the private data of the cpuidle and suspend code.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/cpuidle44xx.c         |   11 ++---------
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |    6 +-----
 arch/arm/mach-omap2/pm24xx.c              |    5 +----
 arch/arm/mach-omap2/pm44xx.c              |   10 ++--------
 4 files changed, 6 insertions(+), 26 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index 50c9082..221039a 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -27,7 +27,6 @@
 /* Machine specific information */
 struct omap4_idle_statedata {
 	u32 cpu_state;
-	u32 mpu_logic_state;
 	u32 mpu_state;
 };
 
@@ -35,17 +34,14 @@ static struct omap4_idle_statedata omap4_idle_data[] = {
 	{
 		.cpu_state = PWRDM_FUNC_PWRST_ON,
 		.mpu_state = PWRDM_FUNC_PWRST_ON,
-		.mpu_logic_state = PWRDM_POWER_RET,
 	},
 	{
 		.cpu_state = PWRDM_FUNC_PWRST_OFF,
 		.mpu_state = PWRDM_FUNC_PWRST_CSWR,
-		.mpu_logic_state = PWRDM_POWER_RET,
 	},
 	{
 		.cpu_state = PWRDM_FUNC_PWRST_OFF,
-		.mpu_state = PWRDM_FUNC_PWRST_CSWR,
-		.mpu_logic_state = PWRDM_POWER_OFF,
+		.mpu_state = PWRDM_FUNC_PWRST_OSWR,
 	},
 };
 
@@ -95,16 +91,13 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
 	if (cx->cpu_state == PWRDM_FUNC_PWRST_OFF)
 		cpu_pm_enter();
 
-	pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state);
 	omap_set_pwrdm_state(mpu_pd, cx->mpu_state);
 
 	/*
 	 * Call idle CPU cluster PM enter notifier chain
 	 * to save GIC and wakeupgen context.
 	 */
-	if (((cx->mpu_state == PWRDM_FUNC_PWRST_CSWR) ||
-	     (cx->mpu_state == PWRDM_FUNC_PWRST_OSWR)) &&
-	    (cx->mpu_logic_state == PWRDM_POWER_OFF))
+	if (cx->mpu_state == PWRDM_FUNC_PWRST_OSWR)
 			cpu_cluster_pm_enter();
 
 	omap4_enter_lowpower(dev->cpu, cx->cpu_state);
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index dd94a0e..c79cc0f 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -232,7 +232,6 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 {
 	unsigned int save_state = 0;
 	unsigned int wakeup_cpu;
-	int mpuss_state;
 
 	if (omap_rev() == OMAP4430_REV_ES1_0)
 		return -ENXIO;
@@ -265,10 +264,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	 * In MPUSS OSWR or device OFF, interrupt controller context is lost.
 	 */
 	mpuss_clear_prev_logic_pwrst();
-	mpuss_state = pwrdm_read_next_func_pwrst(mpuss_pd);
-	if (((mpuss_state == PWRDM_FUNC_PWRST_CSWR) ||
-	     (mpuss_state == PWRDM_FUNC_PWRST_OSWR)) &&
-	    (pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF))
+	if (pwrdm_read_next_func_pwrst(mpuss_pd) == PWRDM_FUNC_PWRST_OSWR)
 		save_state = 2;
 
 	cpu_clear_prev_logic_pwrst(cpu);
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 0bed51e..fdb0767 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -93,7 +93,6 @@ static int omap2_enter_full_retention(void)
 	 * Set MPU powerdomain's next power state to RETENTION;
 	 * preserve logic state during retention
 	 */
-	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
 	omap_set_pwrdm_state(mpu_pwrdm, PWRDM_FUNC_PWRST_CSWR);
 
 	/* Workaround to kill USB */
@@ -248,7 +247,7 @@ static void __init prcm_setup_regs(void)
 	 */
 	num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm);
 	for (i = 0; i < num_mem_banks; i++)
-		pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET);
+		pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_LOGIC_MEM_PWRST_RET);
 
 	/* Set CORE powerdomain's next power state to RETENTION */
 	omap_set_pwrdm_state(core_pwrdm, PWRDM_FUNC_PWRST_CSWR);
@@ -257,11 +256,9 @@ static void __init prcm_setup_regs(void)
 	 * Set MPU powerdomain's next power state to RETENTION;
 	 * preserve logic state during retention
 	 */
-	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
 	omap_set_pwrdm_state(mpu_pwrdm, PWRDM_FUNC_PWRST_CSWR);
 
 	/* Force-power down DSP, GFX powerdomains */
-
 	pwrdm = clkdm_get_pwrdm(dsp_clkdm);
 	omap_set_pwrdm_state(pwrdm, PWRDM_FUNC_PWRST_OFF);
 	clkdm_sleep(dsp_clkdm);
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 98bb699..eb12d25 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -28,7 +28,6 @@ struct power_state {
 	u32 next_state;
 #ifdef CONFIG_SUSPEND
 	u32 saved_state;
-	u32 saved_logic_state;
 #endif
 	struct list_head node;
 };
@@ -43,16 +42,12 @@ static int omap4_pm_suspend(void)
 	u32 cpu_id = smp_processor_id();
 
 	/* Save current powerdomain state */
-	list_for_each_entry(pwrst, &pwrst_list, node) {
+	list_for_each_entry(pwrst, &pwrst_list, node)
 		pwrst->saved_state = pwrdm_read_next_func_pwrst(pwrst->pwrdm);
-		pwrst->saved_logic_state = pwrdm_read_logic_retst(pwrst->pwrdm);
-	}
 
 	/* Set targeted power domain states by suspend */
-	list_for_each_entry(pwrst, &pwrst_list, node) {
+	list_for_each_entry(pwrst, &pwrst_list, node)
 		omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
-		pwrdm_set_logic_retst(pwrst->pwrdm, PWRDM_POWER_OFF);
-	}
 
 	/*
 	 * For MPUSS to hit power domain retention(CSWR or OSWR),
@@ -75,7 +70,6 @@ static int omap4_pm_suspend(void)
 			ret = -1;
 		}
 		omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
-		pwrdm_set_logic_retst(pwrst->pwrdm, pwrst->saved_logic_state);
 	}
 	if (ret)
 		pr_crit("Could not enter target state in pm_suspend\n");
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 6/8] ARM: OMAP2+: PM: use the functional power states API for logic and memory
@ 2012-06-14 14:53   ` Jean Pihet
  0 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-arm-kernel

Since the power domains logic state is derived from the power domain
functional state and is now programmed from omap_set_pwrdm_state,
the calls to pwrdm_set_logic_retst are removed and the mpu_logic_state
field is removed from the private data of the cpuidle and suspend code.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/cpuidle44xx.c         |   11 ++---------
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |    6 +-----
 arch/arm/mach-omap2/pm24xx.c              |    5 +----
 arch/arm/mach-omap2/pm44xx.c              |   10 ++--------
 4 files changed, 6 insertions(+), 26 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index 50c9082..221039a 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -27,7 +27,6 @@
 /* Machine specific information */
 struct omap4_idle_statedata {
 	u32 cpu_state;
-	u32 mpu_logic_state;
 	u32 mpu_state;
 };
 
@@ -35,17 +34,14 @@ static struct omap4_idle_statedata omap4_idle_data[] = {
 	{
 		.cpu_state = PWRDM_FUNC_PWRST_ON,
 		.mpu_state = PWRDM_FUNC_PWRST_ON,
-		.mpu_logic_state = PWRDM_POWER_RET,
 	},
 	{
 		.cpu_state = PWRDM_FUNC_PWRST_OFF,
 		.mpu_state = PWRDM_FUNC_PWRST_CSWR,
-		.mpu_logic_state = PWRDM_POWER_RET,
 	},
 	{
 		.cpu_state = PWRDM_FUNC_PWRST_OFF,
-		.mpu_state = PWRDM_FUNC_PWRST_CSWR,
-		.mpu_logic_state = PWRDM_POWER_OFF,
+		.mpu_state = PWRDM_FUNC_PWRST_OSWR,
 	},
 };
 
@@ -95,16 +91,13 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
 	if (cx->cpu_state == PWRDM_FUNC_PWRST_OFF)
 		cpu_pm_enter();
 
-	pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state);
 	omap_set_pwrdm_state(mpu_pd, cx->mpu_state);
 
 	/*
 	 * Call idle CPU cluster PM enter notifier chain
 	 * to save GIC and wakeupgen context.
 	 */
-	if (((cx->mpu_state == PWRDM_FUNC_PWRST_CSWR) ||
-	     (cx->mpu_state == PWRDM_FUNC_PWRST_OSWR)) &&
-	    (cx->mpu_logic_state == PWRDM_POWER_OFF))
+	if (cx->mpu_state == PWRDM_FUNC_PWRST_OSWR)
 			cpu_cluster_pm_enter();
 
 	omap4_enter_lowpower(dev->cpu, cx->cpu_state);
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index dd94a0e..c79cc0f 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -232,7 +232,6 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 {
 	unsigned int save_state = 0;
 	unsigned int wakeup_cpu;
-	int mpuss_state;
 
 	if (omap_rev() == OMAP4430_REV_ES1_0)
 		return -ENXIO;
@@ -265,10 +264,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	 * In MPUSS OSWR or device OFF, interrupt controller context is lost.
 	 */
 	mpuss_clear_prev_logic_pwrst();
-	mpuss_state = pwrdm_read_next_func_pwrst(mpuss_pd);
-	if (((mpuss_state == PWRDM_FUNC_PWRST_CSWR) ||
-	     (mpuss_state == PWRDM_FUNC_PWRST_OSWR)) &&
-	    (pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF))
+	if (pwrdm_read_next_func_pwrst(mpuss_pd) == PWRDM_FUNC_PWRST_OSWR)
 		save_state = 2;
 
 	cpu_clear_prev_logic_pwrst(cpu);
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 0bed51e..fdb0767 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -93,7 +93,6 @@ static int omap2_enter_full_retention(void)
 	 * Set MPU powerdomain's next power state to RETENTION;
 	 * preserve logic state during retention
 	 */
-	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
 	omap_set_pwrdm_state(mpu_pwrdm, PWRDM_FUNC_PWRST_CSWR);
 
 	/* Workaround to kill USB */
@@ -248,7 +247,7 @@ static void __init prcm_setup_regs(void)
 	 */
 	num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm);
 	for (i = 0; i < num_mem_banks; i++)
-		pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET);
+		pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_LOGIC_MEM_PWRST_RET);
 
 	/* Set CORE powerdomain's next power state to RETENTION */
 	omap_set_pwrdm_state(core_pwrdm, PWRDM_FUNC_PWRST_CSWR);
@@ -257,11 +256,9 @@ static void __init prcm_setup_regs(void)
 	 * Set MPU powerdomain's next power state to RETENTION;
 	 * preserve logic state during retention
 	 */
-	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
 	omap_set_pwrdm_state(mpu_pwrdm, PWRDM_FUNC_PWRST_CSWR);
 
 	/* Force-power down DSP, GFX powerdomains */
-
 	pwrdm = clkdm_get_pwrdm(dsp_clkdm);
 	omap_set_pwrdm_state(pwrdm, PWRDM_FUNC_PWRST_OFF);
 	clkdm_sleep(dsp_clkdm);
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 98bb699..eb12d25 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -28,7 +28,6 @@ struct power_state {
 	u32 next_state;
 #ifdef CONFIG_SUSPEND
 	u32 saved_state;
-	u32 saved_logic_state;
 #endif
 	struct list_head node;
 };
@@ -43,16 +42,12 @@ static int omap4_pm_suspend(void)
 	u32 cpu_id = smp_processor_id();
 
 	/* Save current powerdomain state */
-	list_for_each_entry(pwrst, &pwrst_list, node) {
+	list_for_each_entry(pwrst, &pwrst_list, node)
 		pwrst->saved_state = pwrdm_read_next_func_pwrst(pwrst->pwrdm);
-		pwrst->saved_logic_state = pwrdm_read_logic_retst(pwrst->pwrdm);
-	}
 
 	/* Set targeted power domain states by suspend */
-	list_for_each_entry(pwrst, &pwrst_list, node) {
+	list_for_each_entry(pwrst, &pwrst_list, node)
 		omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
-		pwrdm_set_logic_retst(pwrst->pwrdm, PWRDM_POWER_OFF);
-	}
 
 	/*
 	 * For MPUSS to hit power domain retention(CSWR or OSWR),
@@ -75,7 +70,6 @@ static int omap4_pm_suspend(void)
 			ret = -1;
 		}
 		omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
-		pwrdm_set_logic_retst(pwrst->pwrdm, pwrst->saved_logic_state);
 	}
 	if (ret)
 		pr_crit("Could not enter target state in pm_suspend\n");
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 7/8] ARM: OMAP2+: PM: use power domain functional state in stats counters
  2012-06-14 14:53 ` Jean Pihet
@ 2012-06-14 14:53   ` Jean Pihet
  -1 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-omap, paul, linux-arm-kernel, khilman; +Cc: Jean Pihet

The PM code uses some counters to keep track of the power domains
transitions, in order to provide the information to drivers (in
pwrdm_get_context_loss_count) and to expose the information to
sysfs for debug purpose.

This patch provides the information for each functional state.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/pm-debug.c    |   15 ++++++++-------
 arch/arm/mach-omap2/powerdomain.c |   12 ++++++------
 arch/arm/mach-omap2/powerdomain.h |    4 ++--
 3 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 814bcd9..13c00fb 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -53,9 +53,10 @@ enum {
 	DEBUG_FILE_TIMERS,
 };
 
-static const char pwrdm_state_names[][PWRDM_MAX_PWRSTS] = {
+static const char pwrdm_state_names[][PWRDM_MAX_FUNC_PWRSTS] = {
 	"OFF",
-	"RET",
+	"OSWR",
+	"CSWR",
 	"INA",
 	"ON"
 };
@@ -102,13 +103,13 @@ static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user)
 		strncmp(pwrdm->name, "dpll", 4) == 0)
 		return 0;
 
-	if (pwrdm->state != pwrdm_read_pwrst(pwrdm))
+	if (pwrdm->state != pwrdm_read_func_pwrst(pwrdm))
 		printk(KERN_ERR "pwrdm state mismatch(%s) %d != %d\n",
-			pwrdm->name, pwrdm->state, pwrdm_read_pwrst(pwrdm));
+		       pwrdm->name, pwrdm->state, pwrdm_read_func_pwrst(pwrdm));
 
 	seq_printf(s, "%s (%s)", pwrdm->name,
 			pwrdm_state_names[pwrdm->state]);
-	for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
+	for (i = 0; i < PWRDM_MAX_FUNC_PWRSTS; i++)
 		seq_printf(s, ",%s:%d", pwrdm_state_names[i],
 			pwrdm->state_counter[i]);
 
@@ -137,7 +138,7 @@ static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user)
 	seq_printf(s, "%s (%s)", pwrdm->name,
 		pwrdm_state_names[pwrdm->state]);
 
-	for (i = 0; i < 4; i++)
+	for (i = 0; i < PWRDM_MAX_FUNC_PWRSTS; i++)
 		seq_printf(s, ",%s:%lld", pwrdm_state_names[i],
 			pwrdm->state_timer[i]);
 
@@ -211,7 +212,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *dir)
 
 	t = sched_clock();
 
-	for (i = 0; i < 4; i++)
+	for (i = 0; i < PWRDM_MAX_FUNC_PWRSTS; i++)
 		pwrdm->state_timer[i] = 0;
 
 	pwrdm->timer = t;
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index f94174b..875c6c4 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -106,7 +106,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
 	list_add(&pwrdm->node, &pwrdm_list);
 
 	/* Initialize the powerdomain's state counter */
-	for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
+	for (i = 0; i < PWRDM_MAX_FUNC_PWRSTS; i++)
 		pwrdm->state_counter[i] = 0;
 
 	pwrdm->ret_logic_off_counter = 0;
@@ -114,7 +114,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
 		pwrdm->ret_mem_off_counter[i] = 0;
 
 	pwrdm_wait_transition(pwrdm);
-	pwrdm->state = pwrdm_read_pwrst(pwrdm);
+	pwrdm->state = pwrdm_read_func_pwrst(pwrdm);
 	pwrdm->state_counter[pwrdm->state] = 1;
 
 	pr_debug("powerdomain: registered %s\n", pwrdm->name);
@@ -149,17 +149,17 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 	if (pwrdm == NULL)
 		return -EINVAL;
 
-	state = pwrdm_read_pwrst(pwrdm);
+	state = pwrdm_read_func_pwrst(pwrdm);
 
 	switch (flag) {
 	case PWRDM_STATE_NOW:
 		prev = pwrdm->state;
 		break;
 	case PWRDM_STATE_PREV:
-		prev = pwrdm_read_prev_pwrst(pwrdm);
+		prev = pwrdm_read_prev_func_pwrst(pwrdm);
 		if (pwrdm->state != prev)
 			pwrdm->state_counter[prev]++;
-		if (prev == PWRDM_POWER_RET)
+		if (prev == PWRDM_FUNC_PWRST_OSWR)
 			_update_logic_membank_counters(pwrdm);
 		/*
 		 * If the power domain did not hit the desired state,
@@ -1338,7 +1338,7 @@ int pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
 		return -ENODEV;
 	}
 
-	count = pwrdm->state_counter[PWRDM_POWER_OFF];
+	count = pwrdm->state_counter[PWRDM_FUNC_PWRST_OFF];
 	count += pwrdm->ret_logic_off_counter;
 
 	for (i = 0; i < pwrdm->banks; i++)
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index 9dd68ab..06fb396 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -165,13 +165,13 @@ struct powerdomain {
 	struct list_head voltdm_node;
 	struct mutex lock;
 	int state;
-	unsigned state_counter[PWRDM_MAX_PWRSTS];
+	unsigned state_counter[PWRDM_MAX_FUNC_PWRSTS];
 	unsigned ret_logic_off_counter;
 	unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS];
 
 #ifdef CONFIG_PM_DEBUG
 	s64 timer;
-	s64 state_timer[PWRDM_MAX_PWRSTS];
+	s64 state_timer[PWRDM_MAX_FUNC_PWRSTS];
 #endif
 };
 
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 7/8] ARM: OMAP2+: PM: use power domain functional state in stats counters
@ 2012-06-14 14:53   ` Jean Pihet
  0 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-arm-kernel

The PM code uses some counters to keep track of the power domains
transitions, in order to provide the information to drivers (in
pwrdm_get_context_loss_count) and to expose the information to
sysfs for debug purpose.

This patch provides the information for each functional state.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/pm-debug.c    |   15 ++++++++-------
 arch/arm/mach-omap2/powerdomain.c |   12 ++++++------
 arch/arm/mach-omap2/powerdomain.h |    4 ++--
 3 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 814bcd9..13c00fb 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -53,9 +53,10 @@ enum {
 	DEBUG_FILE_TIMERS,
 };
 
-static const char pwrdm_state_names[][PWRDM_MAX_PWRSTS] = {
+static const char pwrdm_state_names[][PWRDM_MAX_FUNC_PWRSTS] = {
 	"OFF",
-	"RET",
+	"OSWR",
+	"CSWR",
 	"INA",
 	"ON"
 };
@@ -102,13 +103,13 @@ static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user)
 		strncmp(pwrdm->name, "dpll", 4) == 0)
 		return 0;
 
-	if (pwrdm->state != pwrdm_read_pwrst(pwrdm))
+	if (pwrdm->state != pwrdm_read_func_pwrst(pwrdm))
 		printk(KERN_ERR "pwrdm state mismatch(%s) %d != %d\n",
-			pwrdm->name, pwrdm->state, pwrdm_read_pwrst(pwrdm));
+		       pwrdm->name, pwrdm->state, pwrdm_read_func_pwrst(pwrdm));
 
 	seq_printf(s, "%s (%s)", pwrdm->name,
 			pwrdm_state_names[pwrdm->state]);
-	for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
+	for (i = 0; i < PWRDM_MAX_FUNC_PWRSTS; i++)
 		seq_printf(s, ",%s:%d", pwrdm_state_names[i],
 			pwrdm->state_counter[i]);
 
@@ -137,7 +138,7 @@ static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user)
 	seq_printf(s, "%s (%s)", pwrdm->name,
 		pwrdm_state_names[pwrdm->state]);
 
-	for (i = 0; i < 4; i++)
+	for (i = 0; i < PWRDM_MAX_FUNC_PWRSTS; i++)
 		seq_printf(s, ",%s:%lld", pwrdm_state_names[i],
 			pwrdm->state_timer[i]);
 
@@ -211,7 +212,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *dir)
 
 	t = sched_clock();
 
-	for (i = 0; i < 4; i++)
+	for (i = 0; i < PWRDM_MAX_FUNC_PWRSTS; i++)
 		pwrdm->state_timer[i] = 0;
 
 	pwrdm->timer = t;
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index f94174b..875c6c4 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -106,7 +106,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
 	list_add(&pwrdm->node, &pwrdm_list);
 
 	/* Initialize the powerdomain's state counter */
-	for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
+	for (i = 0; i < PWRDM_MAX_FUNC_PWRSTS; i++)
 		pwrdm->state_counter[i] = 0;
 
 	pwrdm->ret_logic_off_counter = 0;
@@ -114,7 +114,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
 		pwrdm->ret_mem_off_counter[i] = 0;
 
 	pwrdm_wait_transition(pwrdm);
-	pwrdm->state = pwrdm_read_pwrst(pwrdm);
+	pwrdm->state = pwrdm_read_func_pwrst(pwrdm);
 	pwrdm->state_counter[pwrdm->state] = 1;
 
 	pr_debug("powerdomain: registered %s\n", pwrdm->name);
@@ -149,17 +149,17 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 	if (pwrdm == NULL)
 		return -EINVAL;
 
-	state = pwrdm_read_pwrst(pwrdm);
+	state = pwrdm_read_func_pwrst(pwrdm);
 
 	switch (flag) {
 	case PWRDM_STATE_NOW:
 		prev = pwrdm->state;
 		break;
 	case PWRDM_STATE_PREV:
-		prev = pwrdm_read_prev_pwrst(pwrdm);
+		prev = pwrdm_read_prev_func_pwrst(pwrdm);
 		if (pwrdm->state != prev)
 			pwrdm->state_counter[prev]++;
-		if (prev == PWRDM_POWER_RET)
+		if (prev == PWRDM_FUNC_PWRST_OSWR)
 			_update_logic_membank_counters(pwrdm);
 		/*
 		 * If the power domain did not hit the desired state,
@@ -1338,7 +1338,7 @@ int pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
 		return -ENODEV;
 	}
 
-	count = pwrdm->state_counter[PWRDM_POWER_OFF];
+	count = pwrdm->state_counter[PWRDM_FUNC_PWRST_OFF];
 	count += pwrdm->ret_logic_off_counter;
 
 	for (i = 0; i < pwrdm->banks; i++)
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index 9dd68ab..06fb396 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -165,13 +165,13 @@ struct powerdomain {
 	struct list_head voltdm_node;
 	struct mutex lock;
 	int state;
-	unsigned state_counter[PWRDM_MAX_PWRSTS];
+	unsigned state_counter[PWRDM_MAX_FUNC_PWRSTS];
 	unsigned ret_logic_off_counter;
 	unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS];
 
 #ifdef CONFIG_PM_DEBUG
 	s64 timer;
-	s64 state_timer[PWRDM_MAX_PWRSTS];
+	s64 state_timer[PWRDM_MAX_FUNC_PWRSTS];
 #endif
 };
 
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 8/8] ARM: OMAP2+: PM debug: trace the functional power domains states
  2012-06-14 14:53 ` Jean Pihet
@ 2012-06-14 14:53   ` Jean Pihet
  -1 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-omap, paul, linux-arm-kernel, khilman; +Cc: Jean Pihet

Trace the power domain transitions using the functional power states,
which include the power and logic states.

While at it, fix the trace in the case a power domain did not hit
the desired state, as reported by Paul Walmsley.

Reported-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/powerdomain.c |   15 +++++----------
 1 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 875c6c4..f6885f9 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -144,7 +144,7 @@ static void _update_logic_membank_counters(struct powerdomain *pwrdm)
 static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 {
 
-	int prev, state, trace_state = 0;
+	int prev, next, state, trace_state;
 
 	if (pwrdm == NULL)
 		return -EINVAL;
@@ -165,10 +165,10 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 		 * If the power domain did not hit the desired state,
 		 * generate a trace event with both the desired and hit states
 		 */
-		if (state != prev) {
+		next = pwrdm_read_next_func_pwrst(pwrdm);
+		if (next != prev) {
 			trace_state = (PWRDM_TRACE_STATES_FLAG |
-				       ((state & OMAP_POWERSTATE_MASK) << 8) |
-				       ((prev & OMAP_POWERSTATE_MASK) << 0));
+				       (next << 8) | (prev << 0));
 			trace_power_domain_target(pwrdm->name, trace_state,
 						  smp_processor_id());
 		}
@@ -768,13 +768,8 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 	pr_debug("powerdomain: setting next powerstate for %s to %0x\n",
 		 pwrdm->name, pwrst);
 
-	if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) {
-		/* Trace the pwrdm desired target state */
-		trace_power_domain_target(pwrdm->name, pwrst,
-					  smp_processor_id());
-		/* Program the pwrdm desired target state */
+	if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst)
 		ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst);
-	}
 
 	return ret;
 }
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 8/8] ARM: OMAP2+: PM debug: trace the functional power domains states
@ 2012-06-14 14:53   ` Jean Pihet
  0 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-14 14:53 UTC (permalink / raw)
  To: linux-arm-kernel

Trace the power domain transitions using the functional power states,
which include the power and logic states.

While at it, fix the trace in the case a power domain did not hit
the desired state, as reported by Paul Walmsley.

Reported-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/powerdomain.c |   15 +++++----------
 1 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 875c6c4..f6885f9 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -144,7 +144,7 @@ static void _update_logic_membank_counters(struct powerdomain *pwrdm)
 static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 {
 
-	int prev, state, trace_state = 0;
+	int prev, next, state, trace_state;
 
 	if (pwrdm == NULL)
 		return -EINVAL;
@@ -165,10 +165,10 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 		 * If the power domain did not hit the desired state,
 		 * generate a trace event with both the desired and hit states
 		 */
-		if (state != prev) {
+		next = pwrdm_read_next_func_pwrst(pwrdm);
+		if (next != prev) {
 			trace_state = (PWRDM_TRACE_STATES_FLAG |
-				       ((state & OMAP_POWERSTATE_MASK) << 8) |
-				       ((prev & OMAP_POWERSTATE_MASK) << 0));
+				       (next << 8) | (prev << 0));
 			trace_power_domain_target(pwrdm->name, trace_state,
 						  smp_processor_id());
 		}
@@ -768,13 +768,8 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 	pr_debug("powerdomain: setting next powerstate for %s to %0x\n",
 		 pwrdm->name, pwrst);
 
-	if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) {
-		/* Trace the pwrdm desired target state */
-		trace_power_domain_target(pwrdm->name, pwrst,
-					  smp_processor_id());
-		/* Program the pwrdm desired target state */
+	if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst)
 		ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst);
-	}
 
 	return ret;
 }
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
  2012-06-14 14:53   ` Jean Pihet
@ 2012-06-15 11:20     ` Jean Pihet
  -1 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-15 11:20 UTC (permalink / raw)
  To: linux-omap, paul, linux-arm-kernel, khilman; +Cc: Jean Pihet, Nishanth Menon

Hi,

Here are some remarks I got after an internal review. I think those
points need to be discussed with a broader audience.

On Thu, Jun 14, 2012 at 4:53 PM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
> Introduce functional (or logical) states for power domains and the
> API functions to read the power domains settings and to convert
> between the functional (i.e. logical) and the internal (or registers)
> values.
>
> OMAP2, OMAP3 and OMAP4 platforms are defining a conversion routine.
>
> In the new API only the function omap_set_pwrdm_state shall be used
> to change a power domain target state, along with the associated
> PWRDM_FUNC_* macros as the state parameters.
> While at it the function is moved to the power domains code.
>
> The power domain API in powerdomain.h is split in the external and the
> internal parts; only the external API functions and defines shall be used
> by external code, the internal API is only to be used in powerdomain*.[ch]
> files.
>
> The memory and logic states are not using the functional states, this
> comes as a subsequent patch.
>
> Signed-off-by: Jean Pihet <j-pihet@ti.com>
> ---
>  arch/arm/mach-omap2/pm.c                   |   66 -----------
>  arch/arm/mach-omap2/pm.h                   |    1 -
>  arch/arm/mach-omap2/powerdomain-common.c   |   71 +++++++++++
>  arch/arm/mach-omap2/powerdomain.c          |  174 ++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/powerdomain.h          |   77 +++++++++----
>  arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |    5 +
>  arch/arm/mach-omap2/powerdomain44xx.c      |    2 +
>  7 files changed, 306 insertions(+), 90 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
> index a05f00c..dfe702b 100644
> --- a/arch/arm/mach-omap2/pm.c
> +++ b/arch/arm/mach-omap2/pm.c
> @@ -74,10 +74,6 @@ static void __init omap2_init_processor_devices(void)
>        }
>  }
>
> -/* Types of sleep_switch used in omap_set_pwrdm_state */
> -#define FORCEWAKEUP_SWITCH     0
> -#define LOWPOWERSTATE_SWITCH   1
> -
>  int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
>  {
>        if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
> @@ -89,68 +85,6 @@ int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
>  }
>
>  /*
> - * This sets pwrdm state (other than mpu & core. Currently only ON &
> - * RET are supported.
> - */
> -int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
> -{
> -       u8 curr_pwrst, next_pwrst;
> -       int sleep_switch = -1, ret = 0, hwsup = 0;
> -
> -       if (!pwrdm || IS_ERR(pwrdm))
> -               return -EINVAL;
> -
> -       mutex_lock(&pwrdm->lock);
> -
> -       while (!(pwrdm->pwrsts & (1 << pwrst))) {
> -               if (pwrst == PWRDM_POWER_OFF)
> -                       goto out;
> -               pwrst--;
> -       }
> -
> -       next_pwrst = pwrdm_read_next_pwrst(pwrdm);
> -       if (next_pwrst == pwrst)
> -               goto out;
> -
> -       curr_pwrst = pwrdm_read_pwrst(pwrdm);
> -       if (curr_pwrst < PWRDM_POWER_ON) {
> -               if ((curr_pwrst > pwrst) &&
> -                       (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
> -                       sleep_switch = LOWPOWERSTATE_SWITCH;
> -               } else {
> -                       hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
> -                       clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
> -                       sleep_switch = FORCEWAKEUP_SWITCH;
> -               }
> -       }
> -
> -       ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
> -       if (ret)
> -               pr_err("%s: unable to set power state of powerdomain: %s\n",
> -                      __func__, pwrdm->name);
> -
> -       switch (sleep_switch) {
> -       case FORCEWAKEUP_SWITCH:
> -               if (hwsup)
> -                       clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
> -               else
> -                       clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
> -               break;
> -       case LOWPOWERSTATE_SWITCH:
> -               pwrdm_set_lowpwrstchange(pwrdm);
> -               pwrdm_wait_transition(pwrdm);
> -               pwrdm_state_switch(pwrdm);
> -               break;
> -       }
> -
> -out:
> -       mutex_unlock(&pwrdm->lock);
> -       return ret;
> -}
> -
> -
> -
> -/*
>  * This API is to be called during init to set the various voltage
>  * domains to the voltage as per the opp table. Typically we boot up
>  * at the nominal voltage. So this function finds out the rate of
> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> index 7856489..5bc0848 100644
> --- a/arch/arm/mach-omap2/pm.h
> +++ b/arch/arm/mach-omap2/pm.h
> @@ -18,7 +18,6 @@
>  extern void *omap3_secure_ram_storage;
>  extern void omap3_pm_off_mode_enable(int);
>  extern void omap_sram_idle(void);
> -extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
>  extern int omap3_idle_init(void);
>  extern int omap4_idle_init(void);
>  extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
> diff --git a/arch/arm/mach-omap2/powerdomain-common.c b/arch/arm/mach-omap2/powerdomain-common.c
> index c0aeabf..2973be7 100644
> --- a/arch/arm/mach-omap2/powerdomain-common.c
> +++ b/arch/arm/mach-omap2/powerdomain-common.c
> @@ -108,3 +108,74 @@ u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank)
>        return 0;
>  }
>
> +/**
> + * omap2_pwrdm_func_to_pwrst - Convert functional (i.e. logical) to
> + * internal (i.e. registers) values for the power domains states.
> + * @struct powerdomain * to convert the values for
> + * @func_pwrst: functional power state
> + *
> + * Returns the internal power state value for the power domain, or
> + * -EINVAL in case of invalid parameters passed in.
> + */
> +int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
> +{
> +       int ret;
> +
> +       switch (func_pwrst) {
> +       case PWRDM_FUNC_PWRST_ON:
> +               ret = PWRDM_POWER_ON;
> +               break;
> +       case PWRDM_FUNC_PWRST_INACTIVE:
> +               ret = PWRDM_POWER_INACTIVE;
> +               break;
> +       case PWRDM_FUNC_PWRST_CSWR:
> +       case PWRDM_FUNC_PWRST_OSWR:
> +               ret = PWRDM_POWER_RET;
> +               break;
> +       case PWRDM_FUNC_PWRST_OFF:
> +               ret = PWRDM_POWER_OFF;
> +               break;
> +       default:
> +               ret = -EINVAL;
> +       }
> +
> +       return ret;
> +}
> +
> +/**
> + * omap2_pwrdm_pwrst_to_func - Convert internal (i.e. registers) to
> + * functional (i.e. logical) values for the power domains states.
> + * @struct powerdomain * to convert the values for
> + * @pwrst: internal power state
> + *
> + * Returns the functional power state value for the power domain, or
> + * -EINVAL in case of invalid parameters passed in.
> + */
> +int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
> +{
> +       int ret;
> +
> +       switch (pwrst) {
> +       case PWRDM_POWER_ON:
> +               ret = PWRDM_FUNC_PWRST_ON;
> +               break;
> +       case PWRDM_POWER_INACTIVE:
> +               ret = PWRDM_FUNC_PWRST_INACTIVE;
> +               break;
> +       case PWRDM_POWER_RET:
> +               /*
> +                * XXX warning: return OSWR in case of pd in RET and
> +                * logic in OFF
> +                */
> +               ret = PWRDM_FUNC_PWRST_CSWR;
> +               break;
> +       case PWRDM_POWER_OFF:
> +               ret = PWRDM_FUNC_PWRST_OFF;
> +               break;
> +       default:
> +               ret = -EINVAL;
> +       }
> +
> +       return ret;
> +}
> +
> diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
> index 1641e72..e79b5ae 100644
> --- a/arch/arm/mach-omap2/powerdomain.c
> +++ b/arch/arm/mach-omap2/powerdomain.c
> @@ -466,6 +466,135 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
>  }
>
>  /**
> + * pwrdm_func_to_pwrst - get the internal (i.e. registers) value mapped
> + * to the functional state
> + * @pwrdm: struct powerdomain * to query
> + * @func_pwrst: functional power state
> + *
> + * Convert the functional power state to the platform specific power
> + * domain state value.
> + * Returns the internal power domain state value or -EINVAL in case
> + * of invalid parameters passed in.
> + */
> +int pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
> +{
> +       int ret = func_pwrst;
> +
> +       if ((!pwrdm) || (func_pwrst >= PWRDM_MAX_FUNC_PWRSTS))
> +               return -EINVAL;
> +
> +       if (arch_pwrdm && arch_pwrdm->pwrdm_func_to_pwrst)
> +               ret = arch_pwrdm->pwrdm_func_to_pwrst(pwrdm, func_pwrst);
> +
> +       pr_debug("powerdomain: convert func %0x to pwrst %0x for %s\n",
> +                func_pwrst, ret, pwrdm->name);
> +
> +       return ret;
> +}
> +
> +/**
> + * pwrdm_pwrst_to_func - get the functional (i.e. logical) value mapped
> + * to the internal state
> + * @pwrdm: struct powerdomain * to query
> + * @pwrst: internal power state
> + *
> + * Convert the internal power state to the power domain functional value.
> + * Returns the functional power domain state value or -EINVAL in case
> + * of invalid parameters passed in.
> + */
> +int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
> +{
> +       int ret = pwrst;
> +
> +       if ((!pwrdm) || (pwrst >= PWRDM_MAX_PWRSTS))
> +               return -EINVAL;
> +
> +       pr_debug("powerdomain: convert %0x pwrst to func for %s\n",
> +                pwrst, pwrdm->name);
> +
> +       if (arch_pwrdm && arch_pwrdm->pwrdm_pwrst_to_func)
> +               ret = arch_pwrdm->pwrdm_pwrst_to_func(pwrdm, pwrst);
> +
> +       return ret;
> +}
> +
> +/* Types of sleep_switch used in omap_set_pwrdm_state */
> +#define FORCEWAKEUP_SWITCH     0
> +#define LOWPOWERSTATE_SWITCH   1
> +
> +/**
> + * omap_set_pwrdm_state - program next powerdomain power state
> + * @pwrdm: struct powerdomain * to set
> + * @func_pwrst: power domain functional state, one of the PWRDM_FUNC_* macros
> + *
> + * This programs the pwrdm next functional state, sets the dependencies
> + * and waits for the state to be applied.
> + */
> +int omap_set_pwrdm_state(struct powerdomain *pwrdm,
> +                        enum pwrdm_func_state func_pwrst)
> +{
> +       u8 curr_pwrst, next_pwrst;
> +       int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
> +       int sleep_switch = -1, ret = 0, hwsup = 0;
> +
> +       if (!pwrdm || IS_ERR(pwrdm) || (pwrst < 0)) {
> +               pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
> +                        __func__, pwrdm, func_pwrst);
> +               return -EINVAL;
> +       }
> +
> +       pr_debug("%s: set func_pwrst %0x to pwrdm %s\n",
> +                __func__, func_pwrst, pwrdm->name);
> +
> +       mutex_lock(&pwrdm->lock);
> +
> +       while (!(pwrdm->pwrsts & (1 << pwrst))) {
> +               if (pwrst == PWRDM_POWER_OFF)
> +                       goto out;
> +               pwrst--;
> +       }
> +
> +       next_pwrst = pwrdm_read_next_pwrst(pwrdm);
> +       if (next_pwrst == pwrst)
> +               goto out;
> +
> +       curr_pwrst = pwrdm_read_pwrst(pwrdm);
> +       if (curr_pwrst < PWRDM_POWER_ON) {
> +               if ((curr_pwrst > pwrst) &&
> +                       (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
> +                       sleep_switch = LOWPOWERSTATE_SWITCH;
> +               } else {
> +                       hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
> +                       clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
> +                       sleep_switch = FORCEWAKEUP_SWITCH;
> +               }
> +       }
> +
> +       ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
> +       if (ret)
> +               pr_err("%s: unable to set power state of powerdomain: %s\n",
> +                      __func__, pwrdm->name);
> +
> +       switch (sleep_switch) {
> +       case FORCEWAKEUP_SWITCH:
> +               if (hwsup)
> +                       clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
> +               else
> +                       clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
> +               break;
> +       case LOWPOWERSTATE_SWITCH:
> +               pwrdm_set_lowpwrstchange(pwrdm);
> +               pwrdm_wait_transition(pwrdm);
> +               pwrdm_state_switch(pwrdm);
> +               break;
> +       }
> +
> +out:
> +       mutex_unlock(&pwrdm->lock);
> +       return ret;
> +}
> +
> +/**
>  * pwrdm_set_next_pwrst - set next powerdomain power state
>  * @pwrdm: struct powerdomain * to set
>  * @pwrst: one of the PWRDM_POWER_* macros
> @@ -522,6 +651,21 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
>  }
>
>  /**
> + * pwrdm_read_next_func_pwrst - get next powerdomain functional power state
> + * @pwrdm: struct powerdomain * to get power state
> + *
> + * Return the powerdomain @pwrdm's next functional power state.
> + * Returns -EINVAL if the powerdomain pointer is null or returns
> + * the next power state upon success.
> + */
> +int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm)
> +{
> +       int ret = pwrdm_read_next_pwrst(pwrdm);
> +
> +       return pwrdm_pwrst_to_func(pwrdm, ret);
> +}
> +
> +/**
>  * pwrdm_read_pwrst - get current powerdomain power state
>  * @pwrdm: struct powerdomain * to get power state
>  *
> @@ -543,6 +687,21 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm)
>  }
>
>  /**
> + * pwrdm_read_func_pwrst - get current powerdomain functional power state
> + * @pwrdm: struct powerdomain * to get power state
> + *
> + * Return the powerdomain @pwrdm's current functional power state.
> + * Returns -EINVAL if the powerdomain pointer is null or returns
> + * the current power state upon success.
> + */
> +int pwrdm_read_func_pwrst(struct powerdomain *pwrdm)
> +{
> +       int ret = pwrdm_read_pwrst(pwrdm);
> +
> +       return pwrdm_pwrst_to_func(pwrdm, ret);
> +}
> +
> +/**
>  * pwrdm_read_prev_pwrst - get previous powerdomain power state
>  * @pwrdm: struct powerdomain * to get previous power state
>  *
> @@ -564,6 +723,21 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
>  }
>
>  /**
> + * pwrdm_read_prev_func_pwrst - get previous powerdomain functional power state
> + * @pwrdm: struct powerdomain * to get previous power state
> + *
> + * Return the powerdomain @pwrdm's previous functional power state.
> + * Returns -EINVAL if the powerdomain pointer is null or returns the
> + * previous power state upon success.
> + */
> +int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm)
> +{
> +       int ret = pwrdm_read_prev_pwrst(pwrdm);
> +
> +       return pwrdm_pwrst_to_func(pwrdm, ret);
> +}
> +
> +/**
>  * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
>  * @pwrdm: struct powerdomain * to set
>  * @pwrst: one of the PWRDM_POWER_* macros
> diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
> index bab84fc..0404f9f 100644
> --- a/arch/arm/mach-omap2/powerdomain.h
> +++ b/arch/arm/mach-omap2/powerdomain.h
> @@ -9,9 +9,6 @@
>  * This program is free software; you can redistribute it and/or modify
>  * it under the terms of the GNU General Public License version 2 as
>  * published by the Free Software Foundation.
> - *
> - * XXX This should be moved to the mach-omap2/ directory at the earliest
> - * opportunity.
>  */
>
>  #ifndef __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H
> @@ -26,7 +23,51 @@
>
>  #include "voltage.h"
>
> -/* Powerdomain basic power states */
> +/***************************************************************
> + * External API
> + ***************************************************************/
> +
> +/* Powerdomain functional power states, used by the external API functions */
> +enum pwrdm_func_state {
> +       PWRDM_FUNC_PWRST_OFF            = 0x0,
> +       PWRDM_FUNC_PWRST_OSWR,
> +       PWRDM_FUNC_PWRST_CSWR,
> +       PWRDM_FUNC_PWRST_INACTIVE,
> +       PWRDM_FUNC_PWRST_ON,
> +       PWRDM_MAX_FUNC_PWRSTS           /* Last value, used as the max value */
> +};
"
There could be potential driver issues using wrong values etc. To be
on a safe side, those could probably define as:
/* Powerdomain functional power states, used by the external API functions */
#define PWRDM_FUNC_PWRST_OFF 0x10
#define PWRDM_FUNC_PWRST_OSWR 0x11
#define PWRDM_FUNC_PWRST_CSWR 0x12
#define PWRDM_FUNC_PWRST_INACTIVE 0x13
#define PWRDM_FUNC_PWRST_ON 0x14
This should expose any wrong handling in code and any cross
assumptions It is highly critical to ensure that PWRDM_FUNC is
different from PWRDM_POWER
"
The argument is valid regarding the API definition (internal vs
external) and its usage.
The possible options are described in the thread at
http://marc.info/?l=linux-omap&m=133975893730191&w=2

Any feedback is appreciated.

Regards,
Jean

> +
> +struct clockdomain;
> +struct powerdomain;
> +
> +struct powerdomain *pwrdm_lookup(const char *name);
> +
> +int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
> +                       void *user);
> +int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
> +                       void *user);
> +
> +struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
> +
> +int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
> +
> +int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm);
> +int pwrdm_read_func_pwrst(struct powerdomain *pwrdm);
> +int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm);
> +extern int omap_set_pwrdm_state(struct powerdomain *pwrdm,
> +                               enum pwrdm_func_state func_pwrst);
> +
> +extern void omap242x_powerdomains_init(void);
> +extern void omap243x_powerdomains_init(void);
> +extern void omap3xxx_powerdomains_init(void);
> +extern void omap44xx_powerdomains_init(void);
> +
> +
> +/***************************************************************
> + * Internal code, only used in powerdomain*.[ch]
> + ***************************************************************/
> +
> +/* Powerdomain internal power states, internal use only */
>  #define PWRDM_POWER_OFF                0x0
>  #define PWRDM_POWER_RET                0x1
>  #define PWRDM_POWER_INACTIVE   0x2
> @@ -45,7 +86,6 @@
>  #define PWRSTS_RET_ON          (PWRSTS_RET | PWRSTS_ON)
>  #define PWRSTS_OFF_RET_ON      (PWRSTS_OFF_RET | PWRSTS_ON)
>
> -
>  /* Powerdomain flags */
>  #define PWRDM_HAS_HDWR_SAR     (1 << 0) /* hardware save-and-restore support */
>  #define PWRDM_HAS_MPU_QUIRK    (1 << 1) /* MPU pwr domain has MEM bank 0 bits
> @@ -74,9 +114,6 @@
>  /* XXX A completely arbitrary number. What is reasonable here? */
>  #define PWRDM_TRANSITION_BAILOUT 100000
>
> -struct clockdomain;
> -struct powerdomain;
> -
>  /**
>  * struct powerdomain - OMAP powerdomain
>  * @name: Powerdomain name
> @@ -130,6 +167,10 @@ struct powerdomain {
>
>  /**
>  * struct pwrdm_ops - Arch specific function implementations
> + * @pwrdm_func_to_pwrst: Convert the pd functional power state to
> + *  the internal state
> + * @pwrdm_pwrst_to_func: Convert the pd internal power state to
> + *  the functional state
>  * @pwrdm_set_next_pwrst: Set the target power state for a pd
>  * @pwrdm_read_next_pwrst: Read the target power state set for a pd
>  * @pwrdm_read_pwrst: Read the current power state of a pd
> @@ -150,6 +191,8 @@ struct powerdomain {
>  * @pwrdm_wait_transition: Wait for a pd state transition to complete
>  */
>  struct pwrdm_ops {
> +       int     (*pwrdm_func_to_pwrst)(struct powerdomain *pwrdm, u8 func_pwrst);
> +       int     (*pwrdm_pwrst_to_func)(struct powerdomain *pwrdm, u8 func_pwrst);
>        int     (*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst);
>        int     (*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm);
>        int     (*pwrdm_read_pwrst)(struct powerdomain *pwrdm);
> @@ -174,21 +217,11 @@ int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
>  int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list);
>  int pwrdm_complete_init(void);
>
> -struct powerdomain *pwrdm_lookup(const char *name);
> -
> -int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
> -                       void *user);
> -int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
> -                       void *user);
> -
>  int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
>  int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
>  int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
>                         int (*fn)(struct powerdomain *pwrdm,
>                                   struct clockdomain *clkdm));
> -struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
> -
> -int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
>
>  int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
>  int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
> @@ -196,6 +229,9 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm);
>  int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
>  int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
>
> +int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
> +int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst);
> +
>  int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
>  int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
>  int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
> @@ -220,11 +256,6 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
>  int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
>  bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
>
> -extern void omap242x_powerdomains_init(void);
> -extern void omap243x_powerdomains_init(void);
> -extern void omap3xxx_powerdomains_init(void);
> -extern void omap44xx_powerdomains_init(void);
> -
>  extern struct pwrdm_ops omap2_pwrdm_operations;
>  extern struct pwrdm_ops omap3_pwrdm_operations;
>  extern struct pwrdm_ops omap4_pwrdm_operations;
> diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
> index 0f0a9f1..79c1293 100644
> --- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
> +++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
> @@ -26,6 +26,7 @@
>
>
>  /* Common functions across OMAP2 and OMAP3 */
> +
>  static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
>  {
>        omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
> @@ -210,6 +211,8 @@ static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
>  }
>
>  struct pwrdm_ops omap2_pwrdm_operations = {
> +       .pwrdm_func_to_pwrst    = omap2_pwrdm_func_to_pwrst,
> +       .pwrdm_pwrst_to_func    = omap2_pwrdm_pwrst_to_func,
>        .pwrdm_set_next_pwrst   = omap2_pwrdm_set_next_pwrst,
>        .pwrdm_read_next_pwrst  = omap2_pwrdm_read_next_pwrst,
>        .pwrdm_read_pwrst       = omap2_pwrdm_read_pwrst,
> @@ -222,6 +225,8 @@ struct pwrdm_ops omap2_pwrdm_operations = {
>  };
>
>  struct pwrdm_ops omap3_pwrdm_operations = {
> +       .pwrdm_func_to_pwrst    = omap2_pwrdm_func_to_pwrst,
> +       .pwrdm_pwrst_to_func    = omap2_pwrdm_pwrst_to_func,
>        .pwrdm_set_next_pwrst   = omap2_pwrdm_set_next_pwrst,
>        .pwrdm_read_next_pwrst  = omap2_pwrdm_read_next_pwrst,
>        .pwrdm_read_pwrst       = omap2_pwrdm_read_pwrst,
> diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
> index 601325b..538b528 100644
> --- a/arch/arm/mach-omap2/powerdomain44xx.c
> +++ b/arch/arm/mach-omap2/powerdomain44xx.c
> @@ -209,6 +209,8 @@ static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
>  }
>
>  struct pwrdm_ops omap4_pwrdm_operations = {
> +       .pwrdm_func_to_pwrst    = omap2_pwrdm_func_to_pwrst,
> +       .pwrdm_pwrst_to_func    = omap2_pwrdm_pwrst_to_func,
>        .pwrdm_set_next_pwrst   = omap4_pwrdm_set_next_pwrst,
>        .pwrdm_read_next_pwrst  = omap4_pwrdm_read_next_pwrst,
>        .pwrdm_read_pwrst       = omap4_pwrdm_read_pwrst,
> --
> 1.7.7.6
>
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
@ 2012-06-15 11:20     ` Jean Pihet
  0 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-15 11:20 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Here are some remarks I got after an internal review. I think those
points need to be discussed with a broader audience.

On Thu, Jun 14, 2012 at 4:53 PM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
> Introduce functional (or logical) states for power domains and the
> API functions to read the power domains settings and to convert
> between the functional (i.e. logical) and the internal (or registers)
> values.
>
> OMAP2, OMAP3 and OMAP4 platforms are defining a conversion routine.
>
> In the new API only the function omap_set_pwrdm_state shall be used
> to change a power domain target state, along with the associated
> PWRDM_FUNC_* macros as the state parameters.
> While at it the function is moved to the power domains code.
>
> The power domain API in powerdomain.h is split in the external and the
> internal parts; only the external API functions and defines shall be used
> by external code, the internal API is only to be used in powerdomain*.[ch]
> files.
>
> The memory and logic states are not using the functional states, this
> comes as a subsequent patch.
>
> Signed-off-by: Jean Pihet <j-pihet@ti.com>
> ---
> ?arch/arm/mach-omap2/pm.c ? ? ? ? ? ? ? ? ? | ? 66 -----------
> ?arch/arm/mach-omap2/pm.h ? ? ? ? ? ? ? ? ? | ? ?1 -
> ?arch/arm/mach-omap2/powerdomain-common.c ? | ? 71 +++++++++++
> ?arch/arm/mach-omap2/powerdomain.c ? ? ? ? ?| ?174 ++++++++++++++++++++++++++++
> ?arch/arm/mach-omap2/powerdomain.h ? ? ? ? ?| ? 77 +++++++++----
> ?arch/arm/mach-omap2/powerdomain2xxx_3xxx.c | ? ?5 +
> ?arch/arm/mach-omap2/powerdomain44xx.c ? ? ?| ? ?2 +
> ?7 files changed, 306 insertions(+), 90 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
> index a05f00c..dfe702b 100644
> --- a/arch/arm/mach-omap2/pm.c
> +++ b/arch/arm/mach-omap2/pm.c
> @@ -74,10 +74,6 @@ static void __init omap2_init_processor_devices(void)
> ? ? ? ?}
> ?}
>
> -/* Types of sleep_switch used in omap_set_pwrdm_state */
> -#define FORCEWAKEUP_SWITCH ? ? 0
> -#define LOWPOWERSTATE_SWITCH ? 1
> -
> ?int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
> ?{
> ? ? ? ?if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
> @@ -89,68 +85,6 @@ int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
> ?}
>
> ?/*
> - * This sets pwrdm state (other than mpu & core. Currently only ON &
> - * RET are supported.
> - */
> -int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
> -{
> - ? ? ? u8 curr_pwrst, next_pwrst;
> - ? ? ? int sleep_switch = -1, ret = 0, hwsup = 0;
> -
> - ? ? ? if (!pwrdm || IS_ERR(pwrdm))
> - ? ? ? ? ? ? ? return -EINVAL;
> -
> - ? ? ? mutex_lock(&pwrdm->lock);
> -
> - ? ? ? while (!(pwrdm->pwrsts & (1 << pwrst))) {
> - ? ? ? ? ? ? ? if (pwrst == PWRDM_POWER_OFF)
> - ? ? ? ? ? ? ? ? ? ? ? goto out;
> - ? ? ? ? ? ? ? pwrst--;
> - ? ? ? }
> -
> - ? ? ? next_pwrst = pwrdm_read_next_pwrst(pwrdm);
> - ? ? ? if (next_pwrst == pwrst)
> - ? ? ? ? ? ? ? goto out;
> -
> - ? ? ? curr_pwrst = pwrdm_read_pwrst(pwrdm);
> - ? ? ? if (curr_pwrst < PWRDM_POWER_ON) {
> - ? ? ? ? ? ? ? if ((curr_pwrst > pwrst) &&
> - ? ? ? ? ? ? ? ? ? ? ? (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
> - ? ? ? ? ? ? ? ? ? ? ? sleep_switch = LOWPOWERSTATE_SWITCH;
> - ? ? ? ? ? ? ? } else {
> - ? ? ? ? ? ? ? ? ? ? ? hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
> - ? ? ? ? ? ? ? ? ? ? ? clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
> - ? ? ? ? ? ? ? ? ? ? ? sleep_switch = FORCEWAKEUP_SWITCH;
> - ? ? ? ? ? ? ? }
> - ? ? ? }
> -
> - ? ? ? ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
> - ? ? ? if (ret)
> - ? ? ? ? ? ? ? pr_err("%s: unable to set power state of powerdomain: %s\n",
> - ? ? ? ? ? ? ? ? ? ? ?__func__, pwrdm->name);
> -
> - ? ? ? switch (sleep_switch) {
> - ? ? ? case FORCEWAKEUP_SWITCH:
> - ? ? ? ? ? ? ? if (hwsup)
> - ? ? ? ? ? ? ? ? ? ? ? clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
> - ? ? ? ? ? ? ? else
> - ? ? ? ? ? ? ? ? ? ? ? clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
> - ? ? ? ? ? ? ? break;
> - ? ? ? case LOWPOWERSTATE_SWITCH:
> - ? ? ? ? ? ? ? pwrdm_set_lowpwrstchange(pwrdm);
> - ? ? ? ? ? ? ? pwrdm_wait_transition(pwrdm);
> - ? ? ? ? ? ? ? pwrdm_state_switch(pwrdm);
> - ? ? ? ? ? ? ? break;
> - ? ? ? }
> -
> -out:
> - ? ? ? mutex_unlock(&pwrdm->lock);
> - ? ? ? return ret;
> -}
> -
> -
> -
> -/*
> ?* This API is to be called during init to set the various voltage
> ?* domains to the voltage as per the opp table. Typically we boot up
> ?* at the nominal voltage. So this function finds out the rate of
> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> index 7856489..5bc0848 100644
> --- a/arch/arm/mach-omap2/pm.h
> +++ b/arch/arm/mach-omap2/pm.h
> @@ -18,7 +18,6 @@
> ?extern void *omap3_secure_ram_storage;
> ?extern void omap3_pm_off_mode_enable(int);
> ?extern void omap_sram_idle(void);
> -extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
> ?extern int omap3_idle_init(void);
> ?extern int omap4_idle_init(void);
> ?extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
> diff --git a/arch/arm/mach-omap2/powerdomain-common.c b/arch/arm/mach-omap2/powerdomain-common.c
> index c0aeabf..2973be7 100644
> --- a/arch/arm/mach-omap2/powerdomain-common.c
> +++ b/arch/arm/mach-omap2/powerdomain-common.c
> @@ -108,3 +108,74 @@ u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank)
> ? ? ? ?return 0;
> ?}
>
> +/**
> + * omap2_pwrdm_func_to_pwrst - Convert functional (i.e. logical) to
> + * internal (i.e. registers) values for the power domains states.
> + * @struct powerdomain * to convert the values for
> + * @func_pwrst: functional power state
> + *
> + * Returns the internal power state value for the power domain, or
> + * -EINVAL in case of invalid parameters passed in.
> + */
> +int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
> +{
> + ? ? ? int ret;
> +
> + ? ? ? switch (func_pwrst) {
> + ? ? ? case PWRDM_FUNC_PWRST_ON:
> + ? ? ? ? ? ? ? ret = PWRDM_POWER_ON;
> + ? ? ? ? ? ? ? break;
> + ? ? ? case PWRDM_FUNC_PWRST_INACTIVE:
> + ? ? ? ? ? ? ? ret = PWRDM_POWER_INACTIVE;
> + ? ? ? ? ? ? ? break;
> + ? ? ? case PWRDM_FUNC_PWRST_CSWR:
> + ? ? ? case PWRDM_FUNC_PWRST_OSWR:
> + ? ? ? ? ? ? ? ret = PWRDM_POWER_RET;
> + ? ? ? ? ? ? ? break;
> + ? ? ? case PWRDM_FUNC_PWRST_OFF:
> + ? ? ? ? ? ? ? ret = PWRDM_POWER_OFF;
> + ? ? ? ? ? ? ? break;
> + ? ? ? default:
> + ? ? ? ? ? ? ? ret = -EINVAL;
> + ? ? ? }
> +
> + ? ? ? return ret;
> +}
> +
> +/**
> + * omap2_pwrdm_pwrst_to_func - Convert internal (i.e. registers) to
> + * functional (i.e. logical) values for the power domains states.
> + * @struct powerdomain * to convert the values for
> + * @pwrst: internal power state
> + *
> + * Returns the functional power state value for the power domain, or
> + * -EINVAL in case of invalid parameters passed in.
> + */
> +int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
> +{
> + ? ? ? int ret;
> +
> + ? ? ? switch (pwrst) {
> + ? ? ? case PWRDM_POWER_ON:
> + ? ? ? ? ? ? ? ret = PWRDM_FUNC_PWRST_ON;
> + ? ? ? ? ? ? ? break;
> + ? ? ? case PWRDM_POWER_INACTIVE:
> + ? ? ? ? ? ? ? ret = PWRDM_FUNC_PWRST_INACTIVE;
> + ? ? ? ? ? ? ? break;
> + ? ? ? case PWRDM_POWER_RET:
> + ? ? ? ? ? ? ? /*
> + ? ? ? ? ? ? ? ?* XXX warning: return OSWR in case of pd in RET and
> + ? ? ? ? ? ? ? ?* logic in OFF
> + ? ? ? ? ? ? ? ?*/
> + ? ? ? ? ? ? ? ret = PWRDM_FUNC_PWRST_CSWR;
> + ? ? ? ? ? ? ? break;
> + ? ? ? case PWRDM_POWER_OFF:
> + ? ? ? ? ? ? ? ret = PWRDM_FUNC_PWRST_OFF;
> + ? ? ? ? ? ? ? break;
> + ? ? ? default:
> + ? ? ? ? ? ? ? ret = -EINVAL;
> + ? ? ? }
> +
> + ? ? ? return ret;
> +}
> +
> diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
> index 1641e72..e79b5ae 100644
> --- a/arch/arm/mach-omap2/powerdomain.c
> +++ b/arch/arm/mach-omap2/powerdomain.c
> @@ -466,6 +466,135 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
> ?}
>
> ?/**
> + * pwrdm_func_to_pwrst - get the internal (i.e. registers) value mapped
> + * to the functional state
> + * @pwrdm: struct powerdomain * to query
> + * @func_pwrst: functional power state
> + *
> + * Convert the functional power state to the platform specific power
> + * domain state value.
> + * Returns the internal power domain state value or -EINVAL in case
> + * of invalid parameters passed in.
> + */
> +int pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
> +{
> + ? ? ? int ret = func_pwrst;
> +
> + ? ? ? if ((!pwrdm) || (func_pwrst >= PWRDM_MAX_FUNC_PWRSTS))
> + ? ? ? ? ? ? ? return -EINVAL;
> +
> + ? ? ? if (arch_pwrdm && arch_pwrdm->pwrdm_func_to_pwrst)
> + ? ? ? ? ? ? ? ret = arch_pwrdm->pwrdm_func_to_pwrst(pwrdm, func_pwrst);
> +
> + ? ? ? pr_debug("powerdomain: convert func %0x to pwrst %0x for %s\n",
> + ? ? ? ? ? ? ? ?func_pwrst, ret, pwrdm->name);
> +
> + ? ? ? return ret;
> +}
> +
> +/**
> + * pwrdm_pwrst_to_func - get the functional (i.e. logical) value mapped
> + * to the internal state
> + * @pwrdm: struct powerdomain * to query
> + * @pwrst: internal power state
> + *
> + * Convert the internal power state to the power domain functional value.
> + * Returns the functional power domain state value or -EINVAL in case
> + * of invalid parameters passed in.
> + */
> +int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
> +{
> + ? ? ? int ret = pwrst;
> +
> + ? ? ? if ((!pwrdm) || (pwrst >= PWRDM_MAX_PWRSTS))
> + ? ? ? ? ? ? ? return -EINVAL;
> +
> + ? ? ? pr_debug("powerdomain: convert %0x pwrst to func for %s\n",
> + ? ? ? ? ? ? ? ?pwrst, pwrdm->name);
> +
> + ? ? ? if (arch_pwrdm && arch_pwrdm->pwrdm_pwrst_to_func)
> + ? ? ? ? ? ? ? ret = arch_pwrdm->pwrdm_pwrst_to_func(pwrdm, pwrst);
> +
> + ? ? ? return ret;
> +}
> +
> +/* Types of sleep_switch used in omap_set_pwrdm_state */
> +#define FORCEWAKEUP_SWITCH ? ? 0
> +#define LOWPOWERSTATE_SWITCH ? 1
> +
> +/**
> + * omap_set_pwrdm_state - program next powerdomain power state
> + * @pwrdm: struct powerdomain * to set
> + * @func_pwrst: power domain functional state, one of the PWRDM_FUNC_* macros
> + *
> + * This programs the pwrdm next functional state, sets the dependencies
> + * and waits for the state to be applied.
> + */
> +int omap_set_pwrdm_state(struct powerdomain *pwrdm,
> + ? ? ? ? ? ? ? ? ? ? ? ?enum pwrdm_func_state func_pwrst)
> +{
> + ? ? ? u8 curr_pwrst, next_pwrst;
> + ? ? ? int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
> + ? ? ? int sleep_switch = -1, ret = 0, hwsup = 0;
> +
> + ? ? ? if (!pwrdm || IS_ERR(pwrdm) || (pwrst < 0)) {
> + ? ? ? ? ? ? ? pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
> + ? ? ? ? ? ? ? ? ? ? ? ?__func__, pwrdm, func_pwrst);
> + ? ? ? ? ? ? ? return -EINVAL;
> + ? ? ? }
> +
> + ? ? ? pr_debug("%s: set func_pwrst %0x to pwrdm %s\n",
> + ? ? ? ? ? ? ? ?__func__, func_pwrst, pwrdm->name);
> +
> + ? ? ? mutex_lock(&pwrdm->lock);
> +
> + ? ? ? while (!(pwrdm->pwrsts & (1 << pwrst))) {
> + ? ? ? ? ? ? ? if (pwrst == PWRDM_POWER_OFF)
> + ? ? ? ? ? ? ? ? ? ? ? goto out;
> + ? ? ? ? ? ? ? pwrst--;
> + ? ? ? }
> +
> + ? ? ? next_pwrst = pwrdm_read_next_pwrst(pwrdm);
> + ? ? ? if (next_pwrst == pwrst)
> + ? ? ? ? ? ? ? goto out;
> +
> + ? ? ? curr_pwrst = pwrdm_read_pwrst(pwrdm);
> + ? ? ? if (curr_pwrst < PWRDM_POWER_ON) {
> + ? ? ? ? ? ? ? if ((curr_pwrst > pwrst) &&
> + ? ? ? ? ? ? ? ? ? ? ? (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
> + ? ? ? ? ? ? ? ? ? ? ? sleep_switch = LOWPOWERSTATE_SWITCH;
> + ? ? ? ? ? ? ? } else {
> + ? ? ? ? ? ? ? ? ? ? ? hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
> + ? ? ? ? ? ? ? ? ? ? ? clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
> + ? ? ? ? ? ? ? ? ? ? ? sleep_switch = FORCEWAKEUP_SWITCH;
> + ? ? ? ? ? ? ? }
> + ? ? ? }
> +
> + ? ? ? ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
> + ? ? ? if (ret)
> + ? ? ? ? ? ? ? pr_err("%s: unable to set power state of powerdomain: %s\n",
> + ? ? ? ? ? ? ? ? ? ? ?__func__, pwrdm->name);
> +
> + ? ? ? switch (sleep_switch) {
> + ? ? ? case FORCEWAKEUP_SWITCH:
> + ? ? ? ? ? ? ? if (hwsup)
> + ? ? ? ? ? ? ? ? ? ? ? clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
> + ? ? ? ? ? ? ? else
> + ? ? ? ? ? ? ? ? ? ? ? clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
> + ? ? ? ? ? ? ? break;
> + ? ? ? case LOWPOWERSTATE_SWITCH:
> + ? ? ? ? ? ? ? pwrdm_set_lowpwrstchange(pwrdm);
> + ? ? ? ? ? ? ? pwrdm_wait_transition(pwrdm);
> + ? ? ? ? ? ? ? pwrdm_state_switch(pwrdm);
> + ? ? ? ? ? ? ? break;
> + ? ? ? }
> +
> +out:
> + ? ? ? mutex_unlock(&pwrdm->lock);
> + ? ? ? return ret;
> +}
> +
> +/**
> ?* pwrdm_set_next_pwrst - set next powerdomain power state
> ?* @pwrdm: struct powerdomain * to set
> ?* @pwrst: one of the PWRDM_POWER_* macros
> @@ -522,6 +651,21 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
> ?}
>
> ?/**
> + * pwrdm_read_next_func_pwrst - get next powerdomain functional power state
> + * @pwrdm: struct powerdomain * to get power state
> + *
> + * Return the powerdomain @pwrdm's next functional power state.
> + * Returns -EINVAL if the powerdomain pointer is null or returns
> + * the next power state upon success.
> + */
> +int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm)
> +{
> + ? ? ? int ret = pwrdm_read_next_pwrst(pwrdm);
> +
> + ? ? ? return pwrdm_pwrst_to_func(pwrdm, ret);
> +}
> +
> +/**
> ?* pwrdm_read_pwrst - get current powerdomain power state
> ?* @pwrdm: struct powerdomain * to get power state
> ?*
> @@ -543,6 +687,21 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm)
> ?}
>
> ?/**
> + * pwrdm_read_func_pwrst - get current powerdomain functional power state
> + * @pwrdm: struct powerdomain * to get power state
> + *
> + * Return the powerdomain @pwrdm's current functional power state.
> + * Returns -EINVAL if the powerdomain pointer is null or returns
> + * the current power state upon success.
> + */
> +int pwrdm_read_func_pwrst(struct powerdomain *pwrdm)
> +{
> + ? ? ? int ret = pwrdm_read_pwrst(pwrdm);
> +
> + ? ? ? return pwrdm_pwrst_to_func(pwrdm, ret);
> +}
> +
> +/**
> ?* pwrdm_read_prev_pwrst - get previous powerdomain power state
> ?* @pwrdm: struct powerdomain * to get previous power state
> ?*
> @@ -564,6 +723,21 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
> ?}
>
> ?/**
> + * pwrdm_read_prev_func_pwrst - get previous powerdomain functional power state
> + * @pwrdm: struct powerdomain * to get previous power state
> + *
> + * Return the powerdomain @pwrdm's previous functional power state.
> + * Returns -EINVAL if the powerdomain pointer is null or returns the
> + * previous power state upon success.
> + */
> +int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm)
> +{
> + ? ? ? int ret = pwrdm_read_prev_pwrst(pwrdm);
> +
> + ? ? ? return pwrdm_pwrst_to_func(pwrdm, ret);
> +}
> +
> +/**
> ?* pwrdm_set_logic_retst - set powerdomain logic power state upon retention
> ?* @pwrdm: struct powerdomain * to set
> ?* @pwrst: one of the PWRDM_POWER_* macros
> diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
> index bab84fc..0404f9f 100644
> --- a/arch/arm/mach-omap2/powerdomain.h
> +++ b/arch/arm/mach-omap2/powerdomain.h
> @@ -9,9 +9,6 @@
> ?* This program is free software; you can redistribute it and/or modify
> ?* it under the terms of the GNU General Public License version 2 as
> ?* published by the Free Software Foundation.
> - *
> - * XXX This should be moved to the mach-omap2/ directory at the earliest
> - * opportunity.
> ?*/
>
> ?#ifndef __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H
> @@ -26,7 +23,51 @@
>
> ?#include "voltage.h"
>
> -/* Powerdomain basic power states */
> +/***************************************************************
> + * External API
> + ***************************************************************/
> +
> +/* Powerdomain functional power states, used by the external API functions */
> +enum pwrdm_func_state {
> + ? ? ? PWRDM_FUNC_PWRST_OFF ? ? ? ? ? ?= 0x0,
> + ? ? ? PWRDM_FUNC_PWRST_OSWR,
> + ? ? ? PWRDM_FUNC_PWRST_CSWR,
> + ? ? ? PWRDM_FUNC_PWRST_INACTIVE,
> + ? ? ? PWRDM_FUNC_PWRST_ON,
> + ? ? ? PWRDM_MAX_FUNC_PWRSTS ? ? ? ? ? /* Last value, used as the max value */
> +};
"
There could be potential driver issues using wrong values etc. To be
on a safe side, those could probably define as:
/* Powerdomain functional power states, used by the external API functions */
#define PWRDM_FUNC_PWRST_OFF 0x10
#define PWRDM_FUNC_PWRST_OSWR 0x11
#define PWRDM_FUNC_PWRST_CSWR 0x12
#define PWRDM_FUNC_PWRST_INACTIVE 0x13
#define PWRDM_FUNC_PWRST_ON 0x14
This should expose any wrong handling in code and any cross
assumptions It is highly critical to ensure that PWRDM_FUNC is
different from PWRDM_POWER
"
The argument is valid regarding the API definition (internal vs
external) and its usage.
The possible options are described in the thread at
http://marc.info/?l=linux-omap&m=133975893730191&w=2

Any feedback is appreciated.

Regards,
Jean

> +
> +struct clockdomain;
> +struct powerdomain;
> +
> +struct powerdomain *pwrdm_lookup(const char *name);
> +
> +int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
> + ? ? ? ? ? ? ? ? ? ? ? void *user);
> +int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
> + ? ? ? ? ? ? ? ? ? ? ? void *user);
> +
> +struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
> +
> +int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
> +
> +int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm);
> +int pwrdm_read_func_pwrst(struct powerdomain *pwrdm);
> +int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm);
> +extern int omap_set_pwrdm_state(struct powerdomain *pwrdm,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? enum pwrdm_func_state func_pwrst);
> +
> +extern void omap242x_powerdomains_init(void);
> +extern void omap243x_powerdomains_init(void);
> +extern void omap3xxx_powerdomains_init(void);
> +extern void omap44xx_powerdomains_init(void);
> +
> +
> +/***************************************************************
> + * Internal code, only used in powerdomain*.[ch]
> + ***************************************************************/
> +
> +/* Powerdomain internal power states, internal use only */
> ?#define PWRDM_POWER_OFF ? ? ? ? ? ? ? ?0x0
> ?#define PWRDM_POWER_RET ? ? ? ? ? ? ? ?0x1
> ?#define PWRDM_POWER_INACTIVE ? 0x2
> @@ -45,7 +86,6 @@
> ?#define PWRSTS_RET_ON ? ? ? ? ?(PWRSTS_RET | PWRSTS_ON)
> ?#define PWRSTS_OFF_RET_ON ? ? ?(PWRSTS_OFF_RET | PWRSTS_ON)
>
> -
> ?/* Powerdomain flags */
> ?#define PWRDM_HAS_HDWR_SAR ? ? (1 << 0) /* hardware save-and-restore support */
> ?#define PWRDM_HAS_MPU_QUIRK ? ?(1 << 1) /* MPU pwr domain has MEM bank 0 bits
> @@ -74,9 +114,6 @@
> ?/* XXX A completely arbitrary number. What is reasonable here? */
> ?#define PWRDM_TRANSITION_BAILOUT 100000
>
> -struct clockdomain;
> -struct powerdomain;
> -
> ?/**
> ?* struct powerdomain - OMAP powerdomain
> ?* @name: Powerdomain name
> @@ -130,6 +167,10 @@ struct powerdomain {
>
> ?/**
> ?* struct pwrdm_ops - Arch specific function implementations
> + * @pwrdm_func_to_pwrst: Convert the pd functional power state to
> + * ?the internal state
> + * @pwrdm_pwrst_to_func: Convert the pd internal power state to
> + * ?the functional state
> ?* @pwrdm_set_next_pwrst: Set the target power state for a pd
> ?* @pwrdm_read_next_pwrst: Read the target power state set for a pd
> ?* @pwrdm_read_pwrst: Read the current power state of a pd
> @@ -150,6 +191,8 @@ struct powerdomain {
> ?* @pwrdm_wait_transition: Wait for a pd state transition to complete
> ?*/
> ?struct pwrdm_ops {
> + ? ? ? int ? ? (*pwrdm_func_to_pwrst)(struct powerdomain *pwrdm, u8 func_pwrst);
> + ? ? ? int ? ? (*pwrdm_pwrst_to_func)(struct powerdomain *pwrdm, u8 func_pwrst);
> ? ? ? ?int ? ? (*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst);
> ? ? ? ?int ? ? (*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm);
> ? ? ? ?int ? ? (*pwrdm_read_pwrst)(struct powerdomain *pwrdm);
> @@ -174,21 +217,11 @@ int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
> ?int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list);
> ?int pwrdm_complete_init(void);
>
> -struct powerdomain *pwrdm_lookup(const char *name);
> -
> -int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
> - ? ? ? ? ? ? ? ? ? ? ? void *user);
> -int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
> - ? ? ? ? ? ? ? ? ? ? ? void *user);
> -
> ?int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
> ?int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
> ?int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
> ? ? ? ? ? ? ? ? ? ? ? ? int (*fn)(struct powerdomain *pwrdm,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct clockdomain *clkdm));
> -struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
> -
> -int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
>
> ?int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
> ?int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
> @@ -196,6 +229,9 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm);
> ?int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
> ?int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
>
> +int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
> +int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst);
> +
> ?int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
> ?int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
> ?int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
> @@ -220,11 +256,6 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
> ?int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
> ?bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
>
> -extern void omap242x_powerdomains_init(void);
> -extern void omap243x_powerdomains_init(void);
> -extern void omap3xxx_powerdomains_init(void);
> -extern void omap44xx_powerdomains_init(void);
> -
> ?extern struct pwrdm_ops omap2_pwrdm_operations;
> ?extern struct pwrdm_ops omap3_pwrdm_operations;
> ?extern struct pwrdm_ops omap4_pwrdm_operations;
> diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
> index 0f0a9f1..79c1293 100644
> --- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
> +++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
> @@ -26,6 +26,7 @@
>
>
> ?/* Common functions across OMAP2 and OMAP3 */
> +
> ?static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
> ?{
> ? ? ? ?omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
> @@ -210,6 +211,8 @@ static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
> ?}
>
> ?struct pwrdm_ops omap2_pwrdm_operations = {
> + ? ? ? .pwrdm_func_to_pwrst ? ?= omap2_pwrdm_func_to_pwrst,
> + ? ? ? .pwrdm_pwrst_to_func ? ?= omap2_pwrdm_pwrst_to_func,
> ? ? ? ?.pwrdm_set_next_pwrst ? = omap2_pwrdm_set_next_pwrst,
> ? ? ? ?.pwrdm_read_next_pwrst ?= omap2_pwrdm_read_next_pwrst,
> ? ? ? ?.pwrdm_read_pwrst ? ? ? = omap2_pwrdm_read_pwrst,
> @@ -222,6 +225,8 @@ struct pwrdm_ops omap2_pwrdm_operations = {
> ?};
>
> ?struct pwrdm_ops omap3_pwrdm_operations = {
> + ? ? ? .pwrdm_func_to_pwrst ? ?= omap2_pwrdm_func_to_pwrst,
> + ? ? ? .pwrdm_pwrst_to_func ? ?= omap2_pwrdm_pwrst_to_func,
> ? ? ? ?.pwrdm_set_next_pwrst ? = omap2_pwrdm_set_next_pwrst,
> ? ? ? ?.pwrdm_read_next_pwrst ?= omap2_pwrdm_read_next_pwrst,
> ? ? ? ?.pwrdm_read_pwrst ? ? ? = omap2_pwrdm_read_pwrst,
> diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
> index 601325b..538b528 100644
> --- a/arch/arm/mach-omap2/powerdomain44xx.c
> +++ b/arch/arm/mach-omap2/powerdomain44xx.c
> @@ -209,6 +209,8 @@ static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
> ?}
>
> ?struct pwrdm_ops omap4_pwrdm_operations = {
> + ? ? ? .pwrdm_func_to_pwrst ? ?= omap2_pwrdm_func_to_pwrst,
> + ? ? ? .pwrdm_pwrst_to_func ? ?= omap2_pwrdm_pwrst_to_func,
> ? ? ? ?.pwrdm_set_next_pwrst ? = omap4_pwrdm_set_next_pwrst,
> ? ? ? ?.pwrdm_read_next_pwrst ?= omap4_pwrdm_read_next_pwrst,
> ? ? ? ?.pwrdm_read_pwrst ? ? ? = omap4_pwrdm_read_pwrst,
> --
> 1.7.7.6
>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 5/8] ARM: OMAP2+: PM: introduce power domains achievable functional states
  2012-06-14 14:53   ` Jean Pihet
@ 2012-06-15 11:28     ` Jean Pihet
  -1 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-15 11:28 UTC (permalink / raw)
  To: linux-omap, paul, linux-arm-kernel, khilman
  Cc: Jean Pihet, Tero Kristo, Nishanth Menon

Hi,

Here are some remarks I got after an internal review. I think those
points need to be discussed with a broader audience.

On Thu, Jun 14, 2012 at 4:53 PM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
> Note: the patch is in RFC state because the state machine for setting
> the next power domain states needs more discussion. Validated on OMAP3&4
> with cpuidle and suspend/resume, though.
>
> Power domains have varied capabilities. When attempting a low power
> state such as OFF/RET, a specific min requested state may not be
> supported on the power domain. This is because a combination
> of system power states where the parent PD's state is not in line
> with expectation can result in system instabilities.
>
> This patch provides a function that returns the achievable functional
> power state for a power domain and its use by omap_set_pwrdm_state.
> The achievable power state is first looked for in the lower power
> states in order to maximize the power savings, then if not found
> in the higher power states.
>
> Inspired from Tero's work on OMAP4 device OFF support and generalized
> to the functional power states.
>
> Signed-off-by: Jean Pihet <j-pihet@ti.com>
> Cc: Tero Kristo <t-kristo@ti.com>
> ---
>  arch/arm/mach-omap2/powerdomain.c |  156 +++++++++++++++++++++++++++++++------
>  arch/arm/mach-omap2/powerdomain.h |    1 +
>  2 files changed, 134 insertions(+), 23 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
> index ce2685a..f94174b 100644
> --- a/arch/arm/mach-omap2/powerdomain.c
> +++ b/arch/arm/mach-omap2/powerdomain.c
> @@ -554,6 +554,108 @@ int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic)
>        return ret;
>  }
>
> +/**
> + * pwrdm_get_achievable_func_pwrst() - Provide achievable functional state
> + * @pwrdm: struct powerdomain * to set
> + * @func_pwrst: minimum functional state we would like to hit
> + * (one of the PWRDM_FUNC_* macros)
> + *
> + * Power domains have varied capabilities. When attempting a low power
> + * state such as OFF/RET, a specific min requested state may not be
> + * supported on the power domain. This is because a combination
> + * of system power states where the parent PD's state is not in line
> + * with expectation can result in system instabilities.
> + *
> + * The achievable power state is first looked for in the lower power
> + * states in order to maximize the power savings, then if not found
> + * in the higher power states.
> + *
> + * Returns the achievable functional power state, or -EINVAL in case of
> + * invalid parameters.
> + */
> +int pwrdm_get_achievable_func_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
> +{
> +       int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
> +       int logic = pwrdm_func_to_logic_pwrst(pwrdm, func_pwrst);
> +       int new_func_pwrst, new_pwrst, new_logic;
> +       int found;
> +
> +       if (!pwrdm || IS_ERR(pwrdm)) {
> +               pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
> +                        __func__, pwrdm, func_pwrst);
> +               return -EINVAL;
> +       }
> +
> +       if ((pwrst < 0) || (logic < 0)) {
> +               pr_debug("%s: invalid params for pwrdm %s, func_pwrst=%0x\n",
> +                        __func__, pwrdm->name, func_pwrst);
> +               return PWRDM_FUNC_PWRST_ON;
> +       }
> +
> +       /*
> +        * Power state: if the requested state is not supported,
> +        * try the lower power states.
> +        */
> +       found = 1;
> +       new_pwrst = pwrst;
> +       while (!(pwrdm->pwrsts & (1 << new_pwrst))) {
> +               if (new_pwrst == PWRDM_POWER_OFF) {
> +                       found = 0;
> +                       break;
> +               }
> +               new_pwrst--;
> +       }
> +
> +       /*
> +        * If no lower power state found, fallback to the higher
> +        * power states.
> +        * PWRDM_POWER_ON is always valid.
> +        */
> +       if (!found) {
> +               new_pwrst = pwrst;
> +               while (!(pwrdm->pwrsts & (1 << new_pwrst))) {
> +                       if (new_pwrst == PWRDM_POWER_ON)
> +                               break;
> +                       new_pwrst++;
> +               }
> +       }
> +
> +       /*
> +        * Logic RET state: if the requested state is not supported,
> +        * try the lower logic states.
> +        */
> +       found = 1;
> +       new_logic = logic;
> +       while (!(pwrdm->pwrsts_logic_ret & (1 << new_logic))) {
> +               if (new_logic == PWRDM_LOGIC_MEM_PWRST_OFF) {
> +                       found = 0;
> +                       break;
> +               }
> +               new_logic--;
> +       }
> +
> +       /*
> +        * If no lower logic state found, fallback to the higher
> +        * logic states.
> +        * PWRDM_LOGIC_MEM_PWRST_RET is always valid.
> +        */
> +       if (!found) {
> +               new_logic = logic;
> +               while (!(pwrdm->pwrsts_logic_ret & (1 << new_logic))) {
> +                       if (new_logic == PWRDM_LOGIC_MEM_PWRST_RET)
> +                               break;
> +                       new_logic++;
> +               }
> +       }
> +

"
1. The while loops need optimization. - This can definitely be
simplified and made non-risky; this also needs some more error
handling
2. About the power domains state machine: you have only one power
state to move in and out of: it is called ON. If you do ON->CSWR->ON
etc. attempting to program ON->CSWR->OSWR is NOT supported in OMAP and
is an invitation for production team to sit and debug for a while
before finding the use of invalid power states
"

Point 2 is a good point. The solution would be to implement a state
machine in this function and/or omap_set_pwrdm_state, possibly using a
platform specific handling function.

Any thought?

Regards,
Jean

> +       new_func_pwrst = pwrdm_pwrst_to_func(pwrdm, new_pwrst, new_logic);
> +
> +       pr_debug("%s(%s, func_pwrst=%0x) returns %0x\n", __func__,
> +                pwrdm->name, func_pwrst, new_func_pwrst);
> +
> +       return new_func_pwrst;
> +}
> +
>  /* Types of sleep_switch used in omap_set_pwrdm_state */
>  #define FORCEWAKEUP_SWITCH     0
>  #define LOWPOWERSTATE_SWITCH   1
> @@ -563,36 +665,32 @@ int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic)
>  * @pwrdm: struct powerdomain * to set
>  * @func_pwrst: power domain functional state, one of the PWRDM_FUNC_* macros
>  *
> - * This programs the pwrdm next functional state, sets the dependencies
> - * and waits for the state to be applied.
> + * This looks for the more suited (or achievable) next functional power
> + * state, programs it, sets the dependencies and waits for the state to
> + * be applied to the power domain.
>  */
>  int omap_set_pwrdm_state(struct powerdomain *pwrdm,
>                         enum pwrdm_func_state func_pwrst)
>  {
> -       u8 curr_pwrst, next_pwrst;
> -       int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
> -       int logic = pwrdm_func_to_logic_pwrst(pwrdm, func_pwrst);
>        int sleep_switch = -1, ret = 0, hwsup = 0;
> +       int new_func_pwrst, next_func_pwrst, pwrst, logic;
> +       u8 curr_pwrst;
>
> -       if (!pwrdm || IS_ERR(pwrdm) || (pwrst < 0) || (logic < 0)) {
> -               pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
> -                        __func__, pwrdm, func_pwrst);
> +       if (!pwrdm || IS_ERR(pwrdm)) {
> +               pr_debug("%s: invalid params: pwrdm=%p\n", __func__, pwrdm);
>                return -EINVAL;
>        }
>
> -       pr_debug("%s: set func_pwrst %0x to pwrdm %s\n",
> -                __func__, func_pwrst, pwrdm->name);
> +       pr_debug("%s(%s, func_pwrst=%0x)\n", __func__, pwrdm->name, func_pwrst);
>
>        mutex_lock(&pwrdm->lock);
>
> -       while (!(pwrdm->pwrsts & (1 << pwrst))) {
> -               if (pwrst == PWRDM_POWER_OFF)
> -                       goto out;
> -               pwrst--;
> -       }
> +       new_func_pwrst = pwrdm_get_achievable_func_pwrst(pwrdm, func_pwrst);
> +       pwrst = pwrdm_func_to_pwrst(pwrdm, new_func_pwrst);
> +       logic = pwrdm_func_to_logic_pwrst(pwrdm, new_func_pwrst);
>
> -       next_pwrst = pwrdm_read_next_pwrst(pwrdm);
> -       if (next_pwrst == pwrst)
> +       next_func_pwrst = pwrdm_read_next_func_pwrst(pwrdm);
> +       if (new_func_pwrst == next_func_pwrst)
>                goto out;
>
>        curr_pwrst = pwrdm_read_pwrst(pwrdm);
> @@ -607,13 +705,25 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm,
>                }
>        }
>
> -       if (logic != pwrdm_read_logic_retst(pwrdm))
> -               pwrdm_set_logic_retst(pwrdm, logic);
> +       pr_debug("%s: set func_pwrst %0x (%0x,%0x) to pwrdm %s\n",
> +                __func__, new_func_pwrst, pwrst, logic, pwrdm->name);
> +
> +       /* Trace the pwrdm desired target state */
> +       trace_power_domain_target(pwrdm->name, new_func_pwrst,
> +                                 smp_processor_id());
> +
> +       /* Program next power state */
> +       if (pwrst != pwrdm_func_to_pwrst(pwrdm, next_func_pwrst)) {
> +               ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
> +               if (ret)
> +                       pr_err("%s: unable to set power state of powerdomain: %s\n",
> +                              __func__, pwrdm->name);
> +       }
>
> -       ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
> -       if (ret)
> -               pr_err("%s: unable to set power state of powerdomain: %s\n",
> -                      __func__, pwrdm->name);
> +       /* Program RET logic state */
> +       if ((pwrst == PWRDM_POWER_RET) &&
> +           (logic != pwrdm_func_to_logic_pwrst(pwrdm, next_func_pwrst)))
> +               pwrdm_set_logic_retst(pwrdm, logic);
>
>        switch (sleep_switch) {
>        case FORCEWAKEUP_SWITCH:
> diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
> index d08c25d..9dd68ab 100644
> --- a/arch/arm/mach-omap2/powerdomain.h
> +++ b/arch/arm/mach-omap2/powerdomain.h
> @@ -247,6 +247,7 @@ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
>  int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
>  int omap2_pwrdm_func_to_logic_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
>  int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic);
> +int pwrdm_get_achievable_func_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
>
>  int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
>  int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
> --
> 1.7.7.6
>
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 5/8] ARM: OMAP2+: PM: introduce power domains achievable functional states
@ 2012-06-15 11:28     ` Jean Pihet
  0 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-06-15 11:28 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Here are some remarks I got after an internal review. I think those
points need to be discussed with a broader audience.

On Thu, Jun 14, 2012 at 4:53 PM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
> Note: the patch is in RFC state because the state machine for setting
> the next power domain states needs more discussion. Validated on OMAP3&4
> with cpuidle and suspend/resume, though.
>
> Power domains have varied capabilities. When attempting a low power
> state such as OFF/RET, a specific min requested state may not be
> supported on the power domain. This is because a combination
> of system power states where the parent PD's state is not in line
> with expectation can result in system instabilities.
>
> This patch provides a function that returns the achievable functional
> power state for a power domain and its use by omap_set_pwrdm_state.
> The achievable power state is first looked for in the lower power
> states in order to maximize the power savings, then if not found
> in the higher power states.
>
> Inspired from Tero's work on OMAP4 device OFF support and generalized
> to the functional power states.
>
> Signed-off-by: Jean Pihet <j-pihet@ti.com>
> Cc: Tero Kristo <t-kristo@ti.com>
> ---
> ?arch/arm/mach-omap2/powerdomain.c | ?156 +++++++++++++++++++++++++++++++------
> ?arch/arm/mach-omap2/powerdomain.h | ? ?1 +
> ?2 files changed, 134 insertions(+), 23 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
> index ce2685a..f94174b 100644
> --- a/arch/arm/mach-omap2/powerdomain.c
> +++ b/arch/arm/mach-omap2/powerdomain.c
> @@ -554,6 +554,108 @@ int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic)
> ? ? ? ?return ret;
> ?}
>
> +/**
> + * pwrdm_get_achievable_func_pwrst() - Provide achievable functional state
> + * @pwrdm: struct powerdomain * to set
> + * @func_pwrst: minimum functional state we would like to hit
> + * (one of the PWRDM_FUNC_* macros)
> + *
> + * Power domains have varied capabilities. When attempting a low power
> + * state such as OFF/RET, a specific min requested state may not be
> + * supported on the power domain. This is because a combination
> + * of system power states where the parent PD's state is not in line
> + * with expectation can result in system instabilities.
> + *
> + * The achievable power state is first looked for in the lower power
> + * states in order to maximize the power savings, then if not found
> + * in the higher power states.
> + *
> + * Returns the achievable functional power state, or -EINVAL in case of
> + * invalid parameters.
> + */
> +int pwrdm_get_achievable_func_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
> +{
> + ? ? ? int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
> + ? ? ? int logic = pwrdm_func_to_logic_pwrst(pwrdm, func_pwrst);
> + ? ? ? int new_func_pwrst, new_pwrst, new_logic;
> + ? ? ? int found;
> +
> + ? ? ? if (!pwrdm || IS_ERR(pwrdm)) {
> + ? ? ? ? ? ? ? pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
> + ? ? ? ? ? ? ? ? ? ? ? ?__func__, pwrdm, func_pwrst);
> + ? ? ? ? ? ? ? return -EINVAL;
> + ? ? ? }
> +
> + ? ? ? if ((pwrst < 0) || (logic < 0)) {
> + ? ? ? ? ? ? ? pr_debug("%s: invalid params for pwrdm %s, func_pwrst=%0x\n",
> + ? ? ? ? ? ? ? ? ? ? ? ?__func__, pwrdm->name, func_pwrst);
> + ? ? ? ? ? ? ? return PWRDM_FUNC_PWRST_ON;
> + ? ? ? }
> +
> + ? ? ? /*
> + ? ? ? ?* Power state: if the requested state is not supported,
> + ? ? ? ?* try the lower power states.
> + ? ? ? ?*/
> + ? ? ? found = 1;
> + ? ? ? new_pwrst = pwrst;
> + ? ? ? while (!(pwrdm->pwrsts & (1 << new_pwrst))) {
> + ? ? ? ? ? ? ? if (new_pwrst == PWRDM_POWER_OFF) {
> + ? ? ? ? ? ? ? ? ? ? ? found = 0;
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? new_pwrst--;
> + ? ? ? }
> +
> + ? ? ? /*
> + ? ? ? ?* If no lower power state found, fallback to the higher
> + ? ? ? ?* power states.
> + ? ? ? ?* PWRDM_POWER_ON is always valid.
> + ? ? ? ?*/
> + ? ? ? if (!found) {
> + ? ? ? ? ? ? ? new_pwrst = pwrst;
> + ? ? ? ? ? ? ? while (!(pwrdm->pwrsts & (1 << new_pwrst))) {
> + ? ? ? ? ? ? ? ? ? ? ? if (new_pwrst == PWRDM_POWER_ON)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? ? ? ? ? new_pwrst++;
> + ? ? ? ? ? ? ? }
> + ? ? ? }
> +
> + ? ? ? /*
> + ? ? ? ?* Logic RET state: if the requested state is not supported,
> + ? ? ? ?* try the lower logic states.
> + ? ? ? ?*/
> + ? ? ? found = 1;
> + ? ? ? new_logic = logic;
> + ? ? ? while (!(pwrdm->pwrsts_logic_ret & (1 << new_logic))) {
> + ? ? ? ? ? ? ? if (new_logic == PWRDM_LOGIC_MEM_PWRST_OFF) {
> + ? ? ? ? ? ? ? ? ? ? ? found = 0;
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? new_logic--;
> + ? ? ? }
> +
> + ? ? ? /*
> + ? ? ? ?* If no lower logic state found, fallback to the higher
> + ? ? ? ?* logic states.
> + ? ? ? ?* PWRDM_LOGIC_MEM_PWRST_RET is always valid.
> + ? ? ? ?*/
> + ? ? ? if (!found) {
> + ? ? ? ? ? ? ? new_logic = logic;
> + ? ? ? ? ? ? ? while (!(pwrdm->pwrsts_logic_ret & (1 << new_logic))) {
> + ? ? ? ? ? ? ? ? ? ? ? if (new_logic == PWRDM_LOGIC_MEM_PWRST_RET)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? ? ? ? ? new_logic++;
> + ? ? ? ? ? ? ? }
> + ? ? ? }
> +

"
1. The while loops need optimization. - This can definitely be
simplified and made non-risky; this also needs some more error
handling
2. About the power domains state machine: you have only one power
state to move in and out of: it is called ON. If you do ON->CSWR->ON
etc. attempting to program ON->CSWR->OSWR is NOT supported in OMAP and
is an invitation for production team to sit and debug for a while
before finding the use of invalid power states
"

Point 2 is a good point. The solution would be to implement a state
machine in this function and/or omap_set_pwrdm_state, possibly using a
platform specific handling function.

Any thought?

Regards,
Jean

> + ? ? ? new_func_pwrst = pwrdm_pwrst_to_func(pwrdm, new_pwrst, new_logic);
> +
> + ? ? ? pr_debug("%s(%s, func_pwrst=%0x) returns %0x\n", __func__,
> + ? ? ? ? ? ? ? ?pwrdm->name, func_pwrst, new_func_pwrst);
> +
> + ? ? ? return new_func_pwrst;
> +}
> +
> ?/* Types of sleep_switch used in omap_set_pwrdm_state */
> ?#define FORCEWAKEUP_SWITCH ? ? 0
> ?#define LOWPOWERSTATE_SWITCH ? 1
> @@ -563,36 +665,32 @@ int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic)
> ?* @pwrdm: struct powerdomain * to set
> ?* @func_pwrst: power domain functional state, one of the PWRDM_FUNC_* macros
> ?*
> - * This programs the pwrdm next functional state, sets the dependencies
> - * and waits for the state to be applied.
> + * This looks for the more suited (or achievable) next functional power
> + * state, programs it, sets the dependencies and waits for the state to
> + * be applied to the power domain.
> ?*/
> ?int omap_set_pwrdm_state(struct powerdomain *pwrdm,
> ? ? ? ? ? ? ? ? ? ? ? ? enum pwrdm_func_state func_pwrst)
> ?{
> - ? ? ? u8 curr_pwrst, next_pwrst;
> - ? ? ? int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
> - ? ? ? int logic = pwrdm_func_to_logic_pwrst(pwrdm, func_pwrst);
> ? ? ? ?int sleep_switch = -1, ret = 0, hwsup = 0;
> + ? ? ? int new_func_pwrst, next_func_pwrst, pwrst, logic;
> + ? ? ? u8 curr_pwrst;
>
> - ? ? ? if (!pwrdm || IS_ERR(pwrdm) || (pwrst < 0) || (logic < 0)) {
> - ? ? ? ? ? ? ? pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
> - ? ? ? ? ? ? ? ? ? ? ? ?__func__, pwrdm, func_pwrst);
> + ? ? ? if (!pwrdm || IS_ERR(pwrdm)) {
> + ? ? ? ? ? ? ? pr_debug("%s: invalid params: pwrdm=%p\n", __func__, pwrdm);
> ? ? ? ? ? ? ? ?return -EINVAL;
> ? ? ? ?}
>
> - ? ? ? pr_debug("%s: set func_pwrst %0x to pwrdm %s\n",
> - ? ? ? ? ? ? ? ?__func__, func_pwrst, pwrdm->name);
> + ? ? ? pr_debug("%s(%s, func_pwrst=%0x)\n", __func__, pwrdm->name, func_pwrst);
>
> ? ? ? ?mutex_lock(&pwrdm->lock);
>
> - ? ? ? while (!(pwrdm->pwrsts & (1 << pwrst))) {
> - ? ? ? ? ? ? ? if (pwrst == PWRDM_POWER_OFF)
> - ? ? ? ? ? ? ? ? ? ? ? goto out;
> - ? ? ? ? ? ? ? pwrst--;
> - ? ? ? }
> + ? ? ? new_func_pwrst = pwrdm_get_achievable_func_pwrst(pwrdm, func_pwrst);
> + ? ? ? pwrst = pwrdm_func_to_pwrst(pwrdm, new_func_pwrst);
> + ? ? ? logic = pwrdm_func_to_logic_pwrst(pwrdm, new_func_pwrst);
>
> - ? ? ? next_pwrst = pwrdm_read_next_pwrst(pwrdm);
> - ? ? ? if (next_pwrst == pwrst)
> + ? ? ? next_func_pwrst = pwrdm_read_next_func_pwrst(pwrdm);
> + ? ? ? if (new_func_pwrst == next_func_pwrst)
> ? ? ? ? ? ? ? ?goto out;
>
> ? ? ? ?curr_pwrst = pwrdm_read_pwrst(pwrdm);
> @@ -607,13 +705,25 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm,
> ? ? ? ? ? ? ? ?}
> ? ? ? ?}
>
> - ? ? ? if (logic != pwrdm_read_logic_retst(pwrdm))
> - ? ? ? ? ? ? ? pwrdm_set_logic_retst(pwrdm, logic);
> + ? ? ? pr_debug("%s: set func_pwrst %0x (%0x,%0x) to pwrdm %s\n",
> + ? ? ? ? ? ? ? ?__func__, new_func_pwrst, pwrst, logic, pwrdm->name);
> +
> + ? ? ? /* Trace the pwrdm desired target state */
> + ? ? ? trace_power_domain_target(pwrdm->name, new_func_pwrst,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? smp_processor_id());
> +
> + ? ? ? /* Program next power state */
> + ? ? ? if (pwrst != pwrdm_func_to_pwrst(pwrdm, next_func_pwrst)) {
> + ? ? ? ? ? ? ? ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
> + ? ? ? ? ? ? ? if (ret)
> + ? ? ? ? ? ? ? ? ? ? ? pr_err("%s: unable to set power state of powerdomain: %s\n",
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?__func__, pwrdm->name);
> + ? ? ? }
>
> - ? ? ? ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
> - ? ? ? if (ret)
> - ? ? ? ? ? ? ? pr_err("%s: unable to set power state of powerdomain: %s\n",
> - ? ? ? ? ? ? ? ? ? ? ?__func__, pwrdm->name);
> + ? ? ? /* Program RET logic state */
> + ? ? ? if ((pwrst == PWRDM_POWER_RET) &&
> + ? ? ? ? ? (logic != pwrdm_func_to_logic_pwrst(pwrdm, next_func_pwrst)))
> + ? ? ? ? ? ? ? pwrdm_set_logic_retst(pwrdm, logic);
>
> ? ? ? ?switch (sleep_switch) {
> ? ? ? ?case FORCEWAKEUP_SWITCH:
> diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
> index d08c25d..9dd68ab 100644
> --- a/arch/arm/mach-omap2/powerdomain.h
> +++ b/arch/arm/mach-omap2/powerdomain.h
> @@ -247,6 +247,7 @@ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
> ?int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
> ?int omap2_pwrdm_func_to_logic_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
> ?int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst, u8 logic);
> +int pwrdm_get_achievable_func_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
>
> ?int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
> ?int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
> --
> 1.7.7.6
>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 1/8] ARM: OMAP2+: PM: protect the power domain state change by a mutex
  2012-06-14 14:53   ` Jean Pihet
@ 2012-06-20  9:17     ` Rajendra Nayak
  -1 siblings, 0 replies; 44+ messages in thread
From: Rajendra Nayak @ 2012-06-20  9:17 UTC (permalink / raw)
  To: Jean Pihet; +Cc: linux-omap, paul, linux-arm-kernel, khilman, Jean Pihet

On Thursday 14 June 2012 08:23 PM, Jean Pihet wrote:
> omap_set_pwrdm_state is intented to be the only API for changing
> a power domain state.

Yes, but there are others which are used to _read_ the power domain
state. Shouldn't those be protected too?

> This patch protects the power domains settings and structs from
> concurrent accesses to the function by using a mutex.
>
> Signed-off-by: Jean Pihet<j-pihet@ti.com>
> ---
>   arch/arm/mach-omap2/pm.c          |    8 ++++++--
>   arch/arm/mach-omap2/powerdomain.c |    1 +
>   arch/arm/mach-omap2/powerdomain.h |    3 ++-
>   3 files changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
> index 9cb5ced..a05f00c 100644
> --- a/arch/arm/mach-omap2/pm.c
> +++ b/arch/arm/mach-omap2/pm.c
> @@ -100,15 +100,17 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
>   	if (!pwrdm || IS_ERR(pwrdm))
>   		return -EINVAL;
>
> +	mutex_lock(&pwrdm->lock);
> +
>   	while (!(pwrdm->pwrsts&  (1<<  pwrst))) {
>   		if (pwrst == PWRDM_POWER_OFF)
> -			return ret;
> +			goto out;
>   		pwrst--;
>   	}
>
>   	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
>   	if (next_pwrst == pwrst)
> -		return ret;
> +		goto out;
>
>   	curr_pwrst = pwrdm_read_pwrst(pwrdm);
>   	if (curr_pwrst<  PWRDM_POWER_ON) {
> @@ -141,6 +143,8 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
>   		break;
>   	}
>
> +out:
> +	mutex_unlock(&pwrdm->lock);
>   	return ret;
>   }
>
> diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
> index 9611490..1641e72 100644
> --- a/arch/arm/mach-omap2/powerdomain.c
> +++ b/arch/arm/mach-omap2/powerdomain.c
> @@ -102,6 +102,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
>   	INIT_LIST_HEAD(&pwrdm->voltdm_node);
>   	voltdm_add_pwrdm(voltdm, pwrdm);
>
> +	mutex_init(&pwrdm->lock);
>   	list_add(&pwrdm->node,&pwrdm_list);
>
>   	/* Initialize the powerdomain's state counter */
> diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
> index 8f88d65..bab84fc 100644
> --- a/arch/arm/mach-omap2/powerdomain.h
> +++ b/arch/arm/mach-omap2/powerdomain.h
> @@ -19,7 +19,7 @@
>
>   #include<linux/types.h>
>   #include<linux/list.h>
> -
> +#include<linux/mutex.h>
>   #include<linux/atomic.h>
>
>   #include<plat/cpu.h>
> @@ -116,6 +116,7 @@ struct powerdomain {
>   	struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
>   	struct list_head node;
>   	struct list_head voltdm_node;
> +	struct mutex lock;
>   	int state;
>   	unsigned state_counter[PWRDM_MAX_PWRSTS];
>   	unsigned ret_logic_off_counter;


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 1/8] ARM: OMAP2+: PM: protect the power domain state change by a mutex
@ 2012-06-20  9:17     ` Rajendra Nayak
  0 siblings, 0 replies; 44+ messages in thread
From: Rajendra Nayak @ 2012-06-20  9:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 14 June 2012 08:23 PM, Jean Pihet wrote:
> omap_set_pwrdm_state is intented to be the only API for changing
> a power domain state.

Yes, but there are others which are used to _read_ the power domain
state. Shouldn't those be protected too?

> This patch protects the power domains settings and structs from
> concurrent accesses to the function by using a mutex.
>
> Signed-off-by: Jean Pihet<j-pihet@ti.com>
> ---
>   arch/arm/mach-omap2/pm.c          |    8 ++++++--
>   arch/arm/mach-omap2/powerdomain.c |    1 +
>   arch/arm/mach-omap2/powerdomain.h |    3 ++-
>   3 files changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
> index 9cb5ced..a05f00c 100644
> --- a/arch/arm/mach-omap2/pm.c
> +++ b/arch/arm/mach-omap2/pm.c
> @@ -100,15 +100,17 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
>   	if (!pwrdm || IS_ERR(pwrdm))
>   		return -EINVAL;
>
> +	mutex_lock(&pwrdm->lock);
> +
>   	while (!(pwrdm->pwrsts&  (1<<  pwrst))) {
>   		if (pwrst == PWRDM_POWER_OFF)
> -			return ret;
> +			goto out;
>   		pwrst--;
>   	}
>
>   	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
>   	if (next_pwrst == pwrst)
> -		return ret;
> +		goto out;
>
>   	curr_pwrst = pwrdm_read_pwrst(pwrdm);
>   	if (curr_pwrst<  PWRDM_POWER_ON) {
> @@ -141,6 +143,8 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
>   		break;
>   	}
>
> +out:
> +	mutex_unlock(&pwrdm->lock);
>   	return ret;
>   }
>
> diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
> index 9611490..1641e72 100644
> --- a/arch/arm/mach-omap2/powerdomain.c
> +++ b/arch/arm/mach-omap2/powerdomain.c
> @@ -102,6 +102,7 @@ static int _pwrdm_register(struct powerdomain *pwrdm)
>   	INIT_LIST_HEAD(&pwrdm->voltdm_node);
>   	voltdm_add_pwrdm(voltdm, pwrdm);
>
> +	mutex_init(&pwrdm->lock);
>   	list_add(&pwrdm->node,&pwrdm_list);
>
>   	/* Initialize the powerdomain's state counter */
> diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
> index 8f88d65..bab84fc 100644
> --- a/arch/arm/mach-omap2/powerdomain.h
> +++ b/arch/arm/mach-omap2/powerdomain.h
> @@ -19,7 +19,7 @@
>
>   #include<linux/types.h>
>   #include<linux/list.h>
> -
> +#include<linux/mutex.h>
>   #include<linux/atomic.h>
>
>   #include<plat/cpu.h>
> @@ -116,6 +116,7 @@ struct powerdomain {
>   	struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
>   	struct list_head node;
>   	struct list_head voltdm_node;
> +	struct mutex lock;
>   	int state;
>   	unsigned state_counter[PWRDM_MAX_PWRSTS];
>   	unsigned ret_logic_off_counter;

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
  2012-06-14 14:53   ` Jean Pihet
@ 2012-07-13  3:01     ` Menon, Nishanth
  -1 siblings, 0 replies; 44+ messages in thread
From: Menon, Nishanth @ 2012-07-13  3:01 UTC (permalink / raw)
  To: Jean Pihet; +Cc: linux-omap, paul, linux-arm-kernel, khilman, Jean Pihet

On Thu, Jun 14, 2012 at 9:53 AM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
[..]
> --- a/arch/arm/mach-omap2/powerdomain-common.c
> +++ b/arch/arm/mach-omap2/powerdomain-common.c
> @@ -108,3 +108,74 @@ u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank)
>         return 0;
>  }
>
> +/**
> + * omap2_pwrdm_func_to_pwrst - Convert functional (i.e. logical) to
> + * internal (i.e. registers) values for the power domains states.
> + * @struct powerdomain * to convert the values for
> + * @func_pwrst: functional power state
> + *
> + * Returns the internal power state value for the power domain, or
> + * -EINVAL in case of invalid parameters passed in.
> + */
> +int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)

Unless we handle logicpwst and pwst here, it makes it hard for non
arch/arm/mach-omap2/powerdomain* files to use this properly.

> +{
> +       int ret;
> +
> +       switch (func_pwrst) {
> +       case PWRDM_FUNC_PWRST_ON:
> +               ret = PWRDM_POWER_ON;
> +               break;
> +       case PWRDM_FUNC_PWRST_INACTIVE:
> +               ret = PWRDM_POWER_INACTIVE;
> +               break;
> +       case PWRDM_FUNC_PWRST_CSWR:
> +       case PWRDM_FUNC_PWRST_OSWR:
> +               ret = PWRDM_POWER_RET;

logic power state?

> +               break;
> +       case PWRDM_FUNC_PWRST_OFF:
> +               ret = PWRDM_POWER_OFF;
> +               break;
> +       default:
> +               ret = -EINVAL;
> +       }
> +
> +       return ret;
> +}
> +
> +/**
> + * omap2_pwrdm_pwrst_to_func - Convert internal (i.e. registers) to
> + * functional (i.e. logical) values for the power domains states.
> + * @struct powerdomain * to convert the values for
> + * @pwrst: internal power state
> + *
> + * Returns the functional power state value for the power domain, or
> + * -EINVAL in case of invalid parameters passed in.
> + */
> +int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
Same here as well..
> +{
> +       int ret;
> +
> +       switch (pwrst) {
> +       case PWRDM_POWER_ON:
> +               ret = PWRDM_FUNC_PWRST_ON;
> +               break;
> +       case PWRDM_POWER_INACTIVE:
> +               ret = PWRDM_FUNC_PWRST_INACTIVE;
> +               break;
> +       case PWRDM_POWER_RET:
> +               /*
> +                * XXX warning: return OSWR in case of pd in RET and
> +                * logic in OFF
> +                */
We need to be able to pass in logic pwst to be able to make that determination.

> +               ret = PWRDM_FUNC_PWRST_CSWR;
> +               break;
> +       case PWRDM_POWER_OFF:
> +               ret = PWRDM_FUNC_PWRST_OFF;
> +               break;
> +       default:
> +               ret = -EINVAL;
> +       }
> +
> +       return ret;
> +}
> +
> diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
> index 1641e72..e79b5ae 100644
> --- a/arch/arm/mach-omap2/powerdomain.c
> +++ b/arch/arm/mach-omap2/powerdomain.c
> @@ -466,6 +466,135 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
>  }
>
>  /**
> + * pwrdm_func_to_pwrst - get the internal (i.e. registers) value mapped
> + * to the functional state
> + * @pwrdm: struct powerdomain * to query
> + * @func_pwrst: functional power state
> + *
> + * Convert the functional power state to the platform specific power
> + * domain state value.
> + * Returns the internal power domain state value or -EINVAL in case
> + * of invalid parameters passed in.
> + */
> +int pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
should take enum pwrdm_func_state func_pwrst

> +{
> +       int ret = func_pwrst;
> +
> +       if ((!pwrdm) || (func_pwrst >= PWRDM_MAX_FUNC_PWRSTS))
> +               return -EINVAL;
> +
> +       if (arch_pwrdm && arch_pwrdm->pwrdm_func_to_pwrst)
> +               ret = arch_pwrdm->pwrdm_func_to_pwrst(pwrdm, func_pwrst);

Should we not return an error if the function pointer is not available
for the arch?
on platforms without func_pwrst pointer converter routing hooked on,
we return func_pwrst back to caller, which expects pwrst!

> +
> +       pr_debug("powerdomain: convert func %0x to pwrst %0x for %s\n",
> +                func_pwrst, ret, pwrdm->name);
> +
> +       return ret;
> +}
> +
> +/**
> + * pwrdm_pwrst_to_func - get the functional (i.e. logical) value mapped
> + * to the internal state
> + * @pwrdm: struct powerdomain * to query
> + * @pwrst: internal power state
> + *
> + * Convert the internal power state to the power domain functional value.
> + * Returns the functional power domain state value or -EINVAL in case
> + * of invalid parameters passed in.
> + */
> +int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
should return enum pwrdm_func_state

> +{
> +       int ret = pwrst;
> +
> +       if ((!pwrdm) || (pwrst >= PWRDM_MAX_PWRSTS))
> +               return -EINVAL;
> +
> +       pr_debug("powerdomain: convert %0x pwrst to func for %s\n",
> +                pwrst, pwrdm->name);
> +
> +       if (arch_pwrdm && arch_pwrdm->pwrdm_pwrst_to_func)
> +               ret = arch_pwrdm->pwrdm_pwrst_to_func(pwrdm, pwrst);

same in reverse here.

> +
> +       return ret;
> +}
> +
> +/* Types of sleep_switch used in omap_set_pwrdm_state */
> +#define FORCEWAKEUP_SWITCH     0
> +#define LOWPOWERSTATE_SWITCH   1
> +
> +/**
> + * omap_set_pwrdm_state - program next powerdomain power state
> + * @pwrdm: struct powerdomain * to set
> + * @func_pwrst: power domain functional state, one of the PWRDM_FUNC_* macros
> + *
> + * This programs the pwrdm next functional state, sets the dependencies
> + * and waits for the state to be applied.
> + */
> +int omap_set_pwrdm_state(struct powerdomain *pwrdm,
> +                        enum pwrdm_func_state func_pwrst)
> +{
> +       u8 curr_pwrst, next_pwrst;
> +       int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
> +       int sleep_switch = -1, ret = 0, hwsup = 0;
> +
> +       if (!pwrdm || IS_ERR(pwrdm) || (pwrst < 0)) {
> +               pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
> +                        __func__, pwrdm, func_pwrst);
> +               return -EINVAL;
> +       }
> +
> +       pr_debug("%s: set func_pwrst %0x to pwrdm %s\n",
> +                __func__, func_pwrst, pwrdm->name);
> +
> +       mutex_lock(&pwrdm->lock);
This should be  a spinlock (previous patch i believe) - hurts cpuidle otherwise.

> +
> +       while (!(pwrdm->pwrsts & (1 << pwrst))) {
> +               if (pwrst == PWRDM_POWER_OFF)
> +                       goto out;
> +               pwrst--;
> +       }
> +

if we like to handle a single API for OSWR and CSWR, then it needs to
handle logic power state as well here.

> +       next_pwrst = pwrdm_read_next_pwrst(pwrdm);
> +       if (next_pwrst == pwrst)
> +               goto out;
> +
> +       curr_pwrst = pwrdm_read_pwrst(pwrdm);
> +       if (curr_pwrst < PWRDM_POWER_ON) {
> +               if ((curr_pwrst > pwrst) &&
> +                       (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
> +                       sleep_switch = LOWPOWERSTATE_SWITCH;
> +               } else {
> +                       hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
> +                       clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
> +                       sleep_switch = FORCEWAKEUP_SWITCH;
> +               }
> +       }
> +
> +       ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
> +       if (ret)
> +               pr_err("%s: unable to set power state of powerdomain: %s\n",
> +                      __func__, pwrdm->name);
> +
> +       switch (sleep_switch) {
> +       case FORCEWAKEUP_SWITCH:
> +               if (hwsup)
> +                       clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
> +               else
> +                       clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
> +               break;
> +       case LOWPOWERSTATE_SWITCH:
> +               pwrdm_set_lowpwrstchange(pwrdm);
> +               pwrdm_wait_transition(pwrdm);
> +               pwrdm_state_switch(pwrdm);
> +               break;
> +       }
> +
> +out:
> +       mutex_unlock(&pwrdm->lock);
> +       return ret;
> +}
> +
> +/**
>   * pwrdm_set_next_pwrst - set next powerdomain power state
>   * @pwrdm: struct powerdomain * to set
>   * @pwrst: one of the PWRDM_POWER_* macros
> @@ -522,6 +651,21 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
>  }
>
>  /**
> + * pwrdm_read_next_func_pwrst - get next powerdomain functional power state
> + * @pwrdm: struct powerdomain * to get power state
> + *
> + * Return the powerdomain @pwrdm's next functional power state.
> + * Returns -EINVAL if the powerdomain pointer is null or returns
> + * the next power state upon success.
> + */
> +int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm)
should return enum pwrdm_func_state
> +{
> +       int ret = pwrdm_read_next_pwrst(pwrdm);
> +
> +       return pwrdm_pwrst_to_func(pwrdm, ret);
> +}
> +
> +/**
>   * pwrdm_read_pwrst - get current powerdomain power state
>   * @pwrdm: struct powerdomain * to get power state
>   *
> @@ -543,6 +687,21 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm)
>  }
>
>  /**
> + * pwrdm_read_func_pwrst - get current powerdomain functional power state
> + * @pwrdm: struct powerdomain * to get power state
> + *
> + * Return the powerdomain @pwrdm's current functional power state.
> + * Returns -EINVAL if the powerdomain pointer is null or returns
> + * the current power state upon success.
> + */
> +int pwrdm_read_func_pwrst(struct powerdomain *pwrdm)
should return enum pwrdm_func_state
> +{
> +       int ret = pwrdm_read_pwrst(pwrdm);
> +
> +       return pwrdm_pwrst_to_func(pwrdm, ret);
> +}

my Crib about the above apis are lack of logic power state handling :(
which forces code like cpuidle to use different apis for logic
power state and force them to use these apis just for pwrst.


> +
> +/**
>   * pwrdm_read_prev_pwrst - get previous powerdomain power state
>   * @pwrdm: struct powerdomain * to get previous power state
>   *
> @@ -564,6 +723,21 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
>  }
>
>  /**
> + * pwrdm_read_prev_func_pwrst - get previous powerdomain functional power state
> + * @pwrdm: struct powerdomain * to get previous power state
> + *
> + * Return the powerdomain @pwrdm's previous functional power state.
> + * Returns -EINVAL if the powerdomain pointer is null or returns the
> + * previous power state upon success.
> + */
> +int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm)
should return enum pwrdm_func_state
> +{
> +       int ret = pwrdm_read_prev_pwrst(pwrdm);
> +
> +       return pwrdm_pwrst_to_func(pwrdm, ret);
> +}
again here.

> +
> +/**
>   * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
>   * @pwrdm: struct powerdomain * to set
>   * @pwrst: one of the PWRDM_POWER_* macros
> diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
> index bab84fc..0404f9f 100644
> --- a/arch/arm/mach-omap2/powerdomain.h
> +++ b/arch/arm/mach-omap2/powerdomain.h
> @@ -9,9 +9,6 @@
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
>   * published by the Free Software Foundation.
> - *
> - * XXX This should be moved to the mach-omap2/ directory at the earliest
> - * opportunity.
>   */
>
>  #ifndef __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H
> @@ -26,7 +23,51 @@
>
>  #include "voltage.h"
>
> -/* Powerdomain basic power states */
> +/***************************************************************
> + * External API
> + ***************************************************************/
> +
> +/* Powerdomain functional power states, used by the external API functions */
> +enum pwrdm_func_state {
> +       PWRDM_FUNC_PWRST_OFF            = 0x0,
> +       PWRDM_FUNC_PWRST_OSWR,
> +       PWRDM_FUNC_PWRST_CSWR,
> +       PWRDM_FUNC_PWRST_INACTIVE,
> +       PWRDM_FUNC_PWRST_ON,
> +       PWRDM_MAX_FUNC_PWRSTS           /* Last value, used as the max value */
> +};
> +
> +struct clockdomain;
> +struct powerdomain;
> +
> +struct powerdomain *pwrdm_lookup(const char *name);
> +
> +int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
> +                       void *user);
> +int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
> +                       void *user);
> +
> +struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
> +
> +int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
> +
> +int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm);
> +int pwrdm_read_func_pwrst(struct powerdomain *pwrdm);
> +int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm);
> +extern int omap_set_pwrdm_state(struct powerdomain *pwrdm,
> +                               enum pwrdm_func_state func_pwrst);
> +
> +extern void omap242x_powerdomains_init(void);
> +extern void omap243x_powerdomains_init(void);
> +extern void omap3xxx_powerdomains_init(void);
> +extern void omap44xx_powerdomains_init(void);
> +
> +

We should split the following out to a separate header which is not to
be used by anyone else other than powerdomain*.[ch]

> +/***************************************************************
> + * Internal code, only used in powerdomain*.[ch]
> + ***************************************************************/
> +
> +/* Powerdomain internal power states, internal use only */
>  #define PWRDM_POWER_OFF                0x0
>  #define PWRDM_POWER_RET                0x1
>  #define PWRDM_POWER_INACTIVE   0x2
> @@ -45,7 +86,6 @@
>  #define PWRSTS_RET_ON          (PWRSTS_RET | PWRSTS_ON)
>  #define PWRSTS_OFF_RET_ON      (PWRSTS_OFF_RET | PWRSTS_ON)
>
> -
>  /* Powerdomain flags */
>  #define PWRDM_HAS_HDWR_SAR     (1 << 0) /* hardware save-and-restore support */
>  #define PWRDM_HAS_MPU_QUIRK    (1 << 1) /* MPU pwr domain has MEM bank 0 bits
> @@ -74,9 +114,6 @@
>  /* XXX A completely arbitrary number. What is reasonable here? */
>  #define PWRDM_TRANSITION_BAILOUT 100000
>
> -struct clockdomain;
> -struct powerdomain;
> -
>  /**
>   * struct powerdomain - OMAP powerdomain
>   * @name: Powerdomain name
> @@ -130,6 +167,10 @@ struct powerdomain {
>
>  /**
>   * struct pwrdm_ops - Arch specific function implementations
> + * @pwrdm_func_to_pwrst: Convert the pd functional power state to
> + *  the internal state
> + * @pwrdm_pwrst_to_func: Convert the pd internal power state to
> + *  the functional state
>   * @pwrdm_set_next_pwrst: Set the target power state for a pd
>   * @pwrdm_read_next_pwrst: Read the target power state set for a pd
>   * @pwrdm_read_pwrst: Read the current power state of a pd
> @@ -150,6 +191,8 @@ struct powerdomain {
>   * @pwrdm_wait_transition: Wait for a pd state transition to complete
>   */
>  struct pwrdm_ops {
> +       int     (*pwrdm_func_to_pwrst)(struct powerdomain *pwrdm, u8 func_pwrst);
should take in enum pwrdm_func_state
> +       int     (*pwrdm_pwrst_to_func)(struct powerdomain *pwrdm, u8 func_pwrst);
should return enum pwrdm_func_state

>         int     (*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst);
>         int     (*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm);
>         int     (*pwrdm_read_pwrst)(struct powerdomain *pwrdm);
> @@ -174,21 +217,11 @@ int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
>  int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list);
>  int pwrdm_complete_init(void);
>
> -struct powerdomain *pwrdm_lookup(const char *name);
> -
> -int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
> -                       void *user);
> -int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
> -                       void *user);
> -
>  int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
>  int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
>  int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
>                          int (*fn)(struct powerdomain *pwrdm,
>                                    struct clockdomain *clkdm));
> -struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
> -
> -int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
>
>  int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
>  int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
> @@ -196,6 +229,9 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm);
>  int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
>  int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
>
> +int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
> +int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst);
> +
>  int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
>  int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
>  int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
> @@ -220,11 +256,6 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
>  int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
>  bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
>
> -extern void omap242x_powerdomains_init(void);
> -extern void omap243x_powerdomains_init(void);
> -extern void omap3xxx_powerdomains_init(void);
> -extern void omap44xx_powerdomains_init(void);
> -
>  extern struct pwrdm_ops omap2_pwrdm_operations;
>  extern struct pwrdm_ops omap3_pwrdm_operations;
>  extern struct pwrdm_ops omap4_pwrdm_operations;
> diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
> index 0f0a9f1..79c1293 100644
> --- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
> +++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
> @@ -26,6 +26,7 @@
>
>
>  /* Common functions across OMAP2 and OMAP3 */
> +
>  static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
>  {
>         omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
> @@ -210,6 +211,8 @@ static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
>  }
>
>  struct pwrdm_ops omap2_pwrdm_operations = {
> +       .pwrdm_func_to_pwrst    = omap2_pwrdm_func_to_pwrst,
> +       .pwrdm_pwrst_to_func    = omap2_pwrdm_pwrst_to_func,
>         .pwrdm_set_next_pwrst   = omap2_pwrdm_set_next_pwrst,
>         .pwrdm_read_next_pwrst  = omap2_pwrdm_read_next_pwrst,
>         .pwrdm_read_pwrst       = omap2_pwrdm_read_pwrst,
> @@ -222,6 +225,8 @@ struct pwrdm_ops omap2_pwrdm_operations = {
>  };
>
>  struct pwrdm_ops omap3_pwrdm_operations = {
> +       .pwrdm_func_to_pwrst    = omap2_pwrdm_func_to_pwrst,
> +       .pwrdm_pwrst_to_func    = omap2_pwrdm_pwrst_to_func,
>         .pwrdm_set_next_pwrst   = omap2_pwrdm_set_next_pwrst,
>         .pwrdm_read_next_pwrst  = omap2_pwrdm_read_next_pwrst,
>         .pwrdm_read_pwrst       = omap2_pwrdm_read_pwrst,
> diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
> index 601325b..538b528 100644
> --- a/arch/arm/mach-omap2/powerdomain44xx.c
> +++ b/arch/arm/mach-omap2/powerdomain44xx.c
> @@ -209,6 +209,8 @@ static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
>  }
>
>  struct pwrdm_ops omap4_pwrdm_operations = {
> +       .pwrdm_func_to_pwrst    = omap2_pwrdm_func_to_pwrst,
> +       .pwrdm_pwrst_to_func    = omap2_pwrdm_pwrst_to_func,
>         .pwrdm_set_next_pwrst   = omap4_pwrdm_set_next_pwrst,
>         .pwrdm_read_next_pwrst  = omap4_pwrdm_read_next_pwrst,
>         .pwrdm_read_pwrst       = omap4_pwrdm_read_pwrst,

otherwise, this is a nice concept
--
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
@ 2012-07-13  3:01     ` Menon, Nishanth
  0 siblings, 0 replies; 44+ messages in thread
From: Menon, Nishanth @ 2012-07-13  3:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jun 14, 2012 at 9:53 AM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
[..]
> --- a/arch/arm/mach-omap2/powerdomain-common.c
> +++ b/arch/arm/mach-omap2/powerdomain-common.c
> @@ -108,3 +108,74 @@ u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank)
>         return 0;
>  }
>
> +/**
> + * omap2_pwrdm_func_to_pwrst - Convert functional (i.e. logical) to
> + * internal (i.e. registers) values for the power domains states.
> + * @struct powerdomain * to convert the values for
> + * @func_pwrst: functional power state
> + *
> + * Returns the internal power state value for the power domain, or
> + * -EINVAL in case of invalid parameters passed in.
> + */
> +int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)

Unless we handle logicpwst and pwst here, it makes it hard for non
arch/arm/mach-omap2/powerdomain* files to use this properly.

> +{
> +       int ret;
> +
> +       switch (func_pwrst) {
> +       case PWRDM_FUNC_PWRST_ON:
> +               ret = PWRDM_POWER_ON;
> +               break;
> +       case PWRDM_FUNC_PWRST_INACTIVE:
> +               ret = PWRDM_POWER_INACTIVE;
> +               break;
> +       case PWRDM_FUNC_PWRST_CSWR:
> +       case PWRDM_FUNC_PWRST_OSWR:
> +               ret = PWRDM_POWER_RET;

logic power state?

> +               break;
> +       case PWRDM_FUNC_PWRST_OFF:
> +               ret = PWRDM_POWER_OFF;
> +               break;
> +       default:
> +               ret = -EINVAL;
> +       }
> +
> +       return ret;
> +}
> +
> +/**
> + * omap2_pwrdm_pwrst_to_func - Convert internal (i.e. registers) to
> + * functional (i.e. logical) values for the power domains states.
> + * @struct powerdomain * to convert the values for
> + * @pwrst: internal power state
> + *
> + * Returns the functional power state value for the power domain, or
> + * -EINVAL in case of invalid parameters passed in.
> + */
> +int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
Same here as well..
> +{
> +       int ret;
> +
> +       switch (pwrst) {
> +       case PWRDM_POWER_ON:
> +               ret = PWRDM_FUNC_PWRST_ON;
> +               break;
> +       case PWRDM_POWER_INACTIVE:
> +               ret = PWRDM_FUNC_PWRST_INACTIVE;
> +               break;
> +       case PWRDM_POWER_RET:
> +               /*
> +                * XXX warning: return OSWR in case of pd in RET and
> +                * logic in OFF
> +                */
We need to be able to pass in logic pwst to be able to make that determination.

> +               ret = PWRDM_FUNC_PWRST_CSWR;
> +               break;
> +       case PWRDM_POWER_OFF:
> +               ret = PWRDM_FUNC_PWRST_OFF;
> +               break;
> +       default:
> +               ret = -EINVAL;
> +       }
> +
> +       return ret;
> +}
> +
> diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
> index 1641e72..e79b5ae 100644
> --- a/arch/arm/mach-omap2/powerdomain.c
> +++ b/arch/arm/mach-omap2/powerdomain.c
> @@ -466,6 +466,135 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
>  }
>
>  /**
> + * pwrdm_func_to_pwrst - get the internal (i.e. registers) value mapped
> + * to the functional state
> + * @pwrdm: struct powerdomain * to query
> + * @func_pwrst: functional power state
> + *
> + * Convert the functional power state to the platform specific power
> + * domain state value.
> + * Returns the internal power domain state value or -EINVAL in case
> + * of invalid parameters passed in.
> + */
> +int pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
should take enum pwrdm_func_state func_pwrst

> +{
> +       int ret = func_pwrst;
> +
> +       if ((!pwrdm) || (func_pwrst >= PWRDM_MAX_FUNC_PWRSTS))
> +               return -EINVAL;
> +
> +       if (arch_pwrdm && arch_pwrdm->pwrdm_func_to_pwrst)
> +               ret = arch_pwrdm->pwrdm_func_to_pwrst(pwrdm, func_pwrst);

Should we not return an error if the function pointer is not available
for the arch?
on platforms without func_pwrst pointer converter routing hooked on,
we return func_pwrst back to caller, which expects pwrst!

> +
> +       pr_debug("powerdomain: convert func %0x to pwrst %0x for %s\n",
> +                func_pwrst, ret, pwrdm->name);
> +
> +       return ret;
> +}
> +
> +/**
> + * pwrdm_pwrst_to_func - get the functional (i.e. logical) value mapped
> + * to the internal state
> + * @pwrdm: struct powerdomain * to query
> + * @pwrst: internal power state
> + *
> + * Convert the internal power state to the power domain functional value.
> + * Returns the functional power domain state value or -EINVAL in case
> + * of invalid parameters passed in.
> + */
> +int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
should return enum pwrdm_func_state

> +{
> +       int ret = pwrst;
> +
> +       if ((!pwrdm) || (pwrst >= PWRDM_MAX_PWRSTS))
> +               return -EINVAL;
> +
> +       pr_debug("powerdomain: convert %0x pwrst to func for %s\n",
> +                pwrst, pwrdm->name);
> +
> +       if (arch_pwrdm && arch_pwrdm->pwrdm_pwrst_to_func)
> +               ret = arch_pwrdm->pwrdm_pwrst_to_func(pwrdm, pwrst);

same in reverse here.

> +
> +       return ret;
> +}
> +
> +/* Types of sleep_switch used in omap_set_pwrdm_state */
> +#define FORCEWAKEUP_SWITCH     0
> +#define LOWPOWERSTATE_SWITCH   1
> +
> +/**
> + * omap_set_pwrdm_state - program next powerdomain power state
> + * @pwrdm: struct powerdomain * to set
> + * @func_pwrst: power domain functional state, one of the PWRDM_FUNC_* macros
> + *
> + * This programs the pwrdm next functional state, sets the dependencies
> + * and waits for the state to be applied.
> + */
> +int omap_set_pwrdm_state(struct powerdomain *pwrdm,
> +                        enum pwrdm_func_state func_pwrst)
> +{
> +       u8 curr_pwrst, next_pwrst;
> +       int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
> +       int sleep_switch = -1, ret = 0, hwsup = 0;
> +
> +       if (!pwrdm || IS_ERR(pwrdm) || (pwrst < 0)) {
> +               pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
> +                        __func__, pwrdm, func_pwrst);
> +               return -EINVAL;
> +       }
> +
> +       pr_debug("%s: set func_pwrst %0x to pwrdm %s\n",
> +                __func__, func_pwrst, pwrdm->name);
> +
> +       mutex_lock(&pwrdm->lock);
This should be  a spinlock (previous patch i believe) - hurts cpuidle otherwise.

> +
> +       while (!(pwrdm->pwrsts & (1 << pwrst))) {
> +               if (pwrst == PWRDM_POWER_OFF)
> +                       goto out;
> +               pwrst--;
> +       }
> +

if we like to handle a single API for OSWR and CSWR, then it needs to
handle logic power state as well here.

> +       next_pwrst = pwrdm_read_next_pwrst(pwrdm);
> +       if (next_pwrst == pwrst)
> +               goto out;
> +
> +       curr_pwrst = pwrdm_read_pwrst(pwrdm);
> +       if (curr_pwrst < PWRDM_POWER_ON) {
> +               if ((curr_pwrst > pwrst) &&
> +                       (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
> +                       sleep_switch = LOWPOWERSTATE_SWITCH;
> +               } else {
> +                       hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
> +                       clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
> +                       sleep_switch = FORCEWAKEUP_SWITCH;
> +               }
> +       }
> +
> +       ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
> +       if (ret)
> +               pr_err("%s: unable to set power state of powerdomain: %s\n",
> +                      __func__, pwrdm->name);
> +
> +       switch (sleep_switch) {
> +       case FORCEWAKEUP_SWITCH:
> +               if (hwsup)
> +                       clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
> +               else
> +                       clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
> +               break;
> +       case LOWPOWERSTATE_SWITCH:
> +               pwrdm_set_lowpwrstchange(pwrdm);
> +               pwrdm_wait_transition(pwrdm);
> +               pwrdm_state_switch(pwrdm);
> +               break;
> +       }
> +
> +out:
> +       mutex_unlock(&pwrdm->lock);
> +       return ret;
> +}
> +
> +/**
>   * pwrdm_set_next_pwrst - set next powerdomain power state
>   * @pwrdm: struct powerdomain * to set
>   * @pwrst: one of the PWRDM_POWER_* macros
> @@ -522,6 +651,21 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
>  }
>
>  /**
> + * pwrdm_read_next_func_pwrst - get next powerdomain functional power state
> + * @pwrdm: struct powerdomain * to get power state
> + *
> + * Return the powerdomain @pwrdm's next functional power state.
> + * Returns -EINVAL if the powerdomain pointer is null or returns
> + * the next power state upon success.
> + */
> +int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm)
should return enum pwrdm_func_state
> +{
> +       int ret = pwrdm_read_next_pwrst(pwrdm);
> +
> +       return pwrdm_pwrst_to_func(pwrdm, ret);
> +}
> +
> +/**
>   * pwrdm_read_pwrst - get current powerdomain power state
>   * @pwrdm: struct powerdomain * to get power state
>   *
> @@ -543,6 +687,21 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm)
>  }
>
>  /**
> + * pwrdm_read_func_pwrst - get current powerdomain functional power state
> + * @pwrdm: struct powerdomain * to get power state
> + *
> + * Return the powerdomain @pwrdm's current functional power state.
> + * Returns -EINVAL if the powerdomain pointer is null or returns
> + * the current power state upon success.
> + */
> +int pwrdm_read_func_pwrst(struct powerdomain *pwrdm)
should return enum pwrdm_func_state
> +{
> +       int ret = pwrdm_read_pwrst(pwrdm);
> +
> +       return pwrdm_pwrst_to_func(pwrdm, ret);
> +}

my Crib about the above apis are lack of logic power state handling :(
which forces code like cpuidle to use different apis for logic
power state and force them to use these apis just for pwrst.


> +
> +/**
>   * pwrdm_read_prev_pwrst - get previous powerdomain power state
>   * @pwrdm: struct powerdomain * to get previous power state
>   *
> @@ -564,6 +723,21 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
>  }
>
>  /**
> + * pwrdm_read_prev_func_pwrst - get previous powerdomain functional power state
> + * @pwrdm: struct powerdomain * to get previous power state
> + *
> + * Return the powerdomain @pwrdm's previous functional power state.
> + * Returns -EINVAL if the powerdomain pointer is null or returns the
> + * previous power state upon success.
> + */
> +int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm)
should return enum pwrdm_func_state
> +{
> +       int ret = pwrdm_read_prev_pwrst(pwrdm);
> +
> +       return pwrdm_pwrst_to_func(pwrdm, ret);
> +}
again here.

> +
> +/**
>   * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
>   * @pwrdm: struct powerdomain * to set
>   * @pwrst: one of the PWRDM_POWER_* macros
> diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
> index bab84fc..0404f9f 100644
> --- a/arch/arm/mach-omap2/powerdomain.h
> +++ b/arch/arm/mach-omap2/powerdomain.h
> @@ -9,9 +9,6 @@
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
>   * published by the Free Software Foundation.
> - *
> - * XXX This should be moved to the mach-omap2/ directory at the earliest
> - * opportunity.
>   */
>
>  #ifndef __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H
> @@ -26,7 +23,51 @@
>
>  #include "voltage.h"
>
> -/* Powerdomain basic power states */
> +/***************************************************************
> + * External API
> + ***************************************************************/
> +
> +/* Powerdomain functional power states, used by the external API functions */
> +enum pwrdm_func_state {
> +       PWRDM_FUNC_PWRST_OFF            = 0x0,
> +       PWRDM_FUNC_PWRST_OSWR,
> +       PWRDM_FUNC_PWRST_CSWR,
> +       PWRDM_FUNC_PWRST_INACTIVE,
> +       PWRDM_FUNC_PWRST_ON,
> +       PWRDM_MAX_FUNC_PWRSTS           /* Last value, used as the max value */
> +};
> +
> +struct clockdomain;
> +struct powerdomain;
> +
> +struct powerdomain *pwrdm_lookup(const char *name);
> +
> +int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
> +                       void *user);
> +int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
> +                       void *user);
> +
> +struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
> +
> +int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
> +
> +int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm);
> +int pwrdm_read_func_pwrst(struct powerdomain *pwrdm);
> +int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm);
> +extern int omap_set_pwrdm_state(struct powerdomain *pwrdm,
> +                               enum pwrdm_func_state func_pwrst);
> +
> +extern void omap242x_powerdomains_init(void);
> +extern void omap243x_powerdomains_init(void);
> +extern void omap3xxx_powerdomains_init(void);
> +extern void omap44xx_powerdomains_init(void);
> +
> +

We should split the following out to a separate header which is not to
be used by anyone else other than powerdomain*.[ch]

> +/***************************************************************
> + * Internal code, only used in powerdomain*.[ch]
> + ***************************************************************/
> +
> +/* Powerdomain internal power states, internal use only */
>  #define PWRDM_POWER_OFF                0x0
>  #define PWRDM_POWER_RET                0x1
>  #define PWRDM_POWER_INACTIVE   0x2
> @@ -45,7 +86,6 @@
>  #define PWRSTS_RET_ON          (PWRSTS_RET | PWRSTS_ON)
>  #define PWRSTS_OFF_RET_ON      (PWRSTS_OFF_RET | PWRSTS_ON)
>
> -
>  /* Powerdomain flags */
>  #define PWRDM_HAS_HDWR_SAR     (1 << 0) /* hardware save-and-restore support */
>  #define PWRDM_HAS_MPU_QUIRK    (1 << 1) /* MPU pwr domain has MEM bank 0 bits
> @@ -74,9 +114,6 @@
>  /* XXX A completely arbitrary number. What is reasonable here? */
>  #define PWRDM_TRANSITION_BAILOUT 100000
>
> -struct clockdomain;
> -struct powerdomain;
> -
>  /**
>   * struct powerdomain - OMAP powerdomain
>   * @name: Powerdomain name
> @@ -130,6 +167,10 @@ struct powerdomain {
>
>  /**
>   * struct pwrdm_ops - Arch specific function implementations
> + * @pwrdm_func_to_pwrst: Convert the pd functional power state to
> + *  the internal state
> + * @pwrdm_pwrst_to_func: Convert the pd internal power state to
> + *  the functional state
>   * @pwrdm_set_next_pwrst: Set the target power state for a pd
>   * @pwrdm_read_next_pwrst: Read the target power state set for a pd
>   * @pwrdm_read_pwrst: Read the current power state of a pd
> @@ -150,6 +191,8 @@ struct powerdomain {
>   * @pwrdm_wait_transition: Wait for a pd state transition to complete
>   */
>  struct pwrdm_ops {
> +       int     (*pwrdm_func_to_pwrst)(struct powerdomain *pwrdm, u8 func_pwrst);
should take in enum pwrdm_func_state
> +       int     (*pwrdm_pwrst_to_func)(struct powerdomain *pwrdm, u8 func_pwrst);
should return enum pwrdm_func_state

>         int     (*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst);
>         int     (*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm);
>         int     (*pwrdm_read_pwrst)(struct powerdomain *pwrdm);
> @@ -174,21 +217,11 @@ int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
>  int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list);
>  int pwrdm_complete_init(void);
>
> -struct powerdomain *pwrdm_lookup(const char *name);
> -
> -int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
> -                       void *user);
> -int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
> -                       void *user);
> -
>  int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
>  int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
>  int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
>                          int (*fn)(struct powerdomain *pwrdm,
>                                    struct clockdomain *clkdm));
> -struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
> -
> -int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
>
>  int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
>  int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
> @@ -196,6 +229,9 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm);
>  int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
>  int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
>
> +int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
> +int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst);
> +
>  int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
>  int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
>  int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
> @@ -220,11 +256,6 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
>  int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
>  bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
>
> -extern void omap242x_powerdomains_init(void);
> -extern void omap243x_powerdomains_init(void);
> -extern void omap3xxx_powerdomains_init(void);
> -extern void omap44xx_powerdomains_init(void);
> -
>  extern struct pwrdm_ops omap2_pwrdm_operations;
>  extern struct pwrdm_ops omap3_pwrdm_operations;
>  extern struct pwrdm_ops omap4_pwrdm_operations;
> diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
> index 0f0a9f1..79c1293 100644
> --- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
> +++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
> @@ -26,6 +26,7 @@
>
>
>  /* Common functions across OMAP2 and OMAP3 */
> +
>  static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
>  {
>         omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
> @@ -210,6 +211,8 @@ static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
>  }
>
>  struct pwrdm_ops omap2_pwrdm_operations = {
> +       .pwrdm_func_to_pwrst    = omap2_pwrdm_func_to_pwrst,
> +       .pwrdm_pwrst_to_func    = omap2_pwrdm_pwrst_to_func,
>         .pwrdm_set_next_pwrst   = omap2_pwrdm_set_next_pwrst,
>         .pwrdm_read_next_pwrst  = omap2_pwrdm_read_next_pwrst,
>         .pwrdm_read_pwrst       = omap2_pwrdm_read_pwrst,
> @@ -222,6 +225,8 @@ struct pwrdm_ops omap2_pwrdm_operations = {
>  };
>
>  struct pwrdm_ops omap3_pwrdm_operations = {
> +       .pwrdm_func_to_pwrst    = omap2_pwrdm_func_to_pwrst,
> +       .pwrdm_pwrst_to_func    = omap2_pwrdm_pwrst_to_func,
>         .pwrdm_set_next_pwrst   = omap2_pwrdm_set_next_pwrst,
>         .pwrdm_read_next_pwrst  = omap2_pwrdm_read_next_pwrst,
>         .pwrdm_read_pwrst       = omap2_pwrdm_read_pwrst,
> diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
> index 601325b..538b528 100644
> --- a/arch/arm/mach-omap2/powerdomain44xx.c
> +++ b/arch/arm/mach-omap2/powerdomain44xx.c
> @@ -209,6 +209,8 @@ static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
>  }
>
>  struct pwrdm_ops omap4_pwrdm_operations = {
> +       .pwrdm_func_to_pwrst    = omap2_pwrdm_func_to_pwrst,
> +       .pwrdm_pwrst_to_func    = omap2_pwrdm_pwrst_to_func,
>         .pwrdm_set_next_pwrst   = omap4_pwrdm_set_next_pwrst,
>         .pwrdm_read_next_pwrst  = omap4_pwrdm_read_next_pwrst,
>         .pwrdm_read_pwrst       = omap4_pwrdm_read_pwrst,

otherwise, this is a nice concept
--
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
  2012-07-13  3:01     ` Menon, Nishanth
@ 2012-07-13  4:39       ` Nishanth Menon
  -1 siblings, 0 replies; 44+ messages in thread
From: Nishanth Menon @ 2012-07-13  4:39 UTC (permalink / raw)
  To: Jean Pihet; +Cc: linux-omap, paul, linux-arm-kernel, khilman, Jean Pihet

On 22:01-20120712, Menon, Nishanth wrote:
> On Thu, Jun 14, 2012 at 9:53 AM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
> [..]
> > +int pwrdm_read_func_pwrst(struct powerdomain *pwrdm)
> should return enum pwrdm_func_state
> > +{
> > +       int ret = pwrdm_read_pwrst(pwrdm);
> > +
> > +       return pwrdm_pwrst_to_func(pwrdm, ret);
> > +}
> 
> my Crib about the above apis are lack of logic power state handling :(
> which forces code like cpuidle to use different apis for logic
> power state and force them to use these apis just for pwrst.
> 
[..]
> > +extern void omap242x_powerdomains_init(void);
> > +extern void omap243x_powerdomains_init(void);
> > +extern void omap3xxx_powerdomains_init(void);
> > +extern void omap44xx_powerdomains_init(void);
> > +
> > +
> 
> We should split the following out to a separate header which is not to
> be used by anyone else other than powerdomain*.[ch]
without doing this..
[..]
> >   */
> >  struct pwrdm_ops {
> > +       int     (*pwrdm_func_to_pwrst)(struct powerdomain *pwrdm, u8 func_pwrst);
> should take in enum pwrdm_func_state
> > +       int     (*pwrdm_pwrst_to_func)(struct powerdomain *pwrdm, u8 func_pwrst);
> should return enum pwrdm_func_state
> 
[...]
> otherwise, this is a nice concept

Here is how it might look like: (baseline internal tree)


diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index c426dc4..30a4bb1 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -129,10 +129,6 @@ static void __init omap2_init_processor_devices(void)
 	}
 }
 
-/* Types of sleep_switch used in omap_set_pwrdm_state */
-#define FORCEWAKEUP_SWITCH	0
-#define LOWPOWERSTATE_SWITCH	1
-
 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
 	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
@@ -144,68 +140,6 @@ int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 }
 
 /*
- * This sets pwrdm state (other than mpu & core. Currently only ON &
- * RET are supported.
- */
-int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
-{
-	u8 curr_pwrst, next_pwrst;
-	int sleep_switch = -1, ret = 0, hwsup = 0;
-
-	if (!pwrdm || IS_ERR(pwrdm))
-		return -EINVAL;
-
-	spin_lock(&pwrdm->lock);
-
-	while (!(pwrdm->pwrsts & (1 << pwrst))) {
-		if (pwrst == PWRDM_POWER_OFF)
-			goto out;
-		pwrst--;
-	}
-
-	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
-	if (next_pwrst == pwrst)
-		goto out;
-
-	curr_pwrst = pwrdm_read_pwrst(pwrdm);
-	if (curr_pwrst < PWRDM_POWER_ON) {
-		if ((curr_pwrst > pwrst) &&
-			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
-			sleep_switch = LOWPOWERSTATE_SWITCH;
-		} else {
-			hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
-			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
-			sleep_switch = FORCEWAKEUP_SWITCH;
-		}
-	}
-
-	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
-	if (ret)
-		pr_err("%s: unable to set power state of powerdomain: %s\n",
-		       __func__, pwrdm->name);
-
-	switch (sleep_switch) {
-	case FORCEWAKEUP_SWITCH:
-		if (hwsup)
-			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
-		else
-			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
-		break;
-	case LOWPOWERSTATE_SWITCH:
-		pwrdm_set_lowpwrstchange(pwrdm);
-		pwrdm_wait_transition(pwrdm);
-		pwrdm_state_switch(pwrdm);
-		break;
-	}
-
-out:
-	spin_unlock(&pwrdm->lock);
-	return ret;
-}
-
-
-
-/*
  * This API is to be called during init to set the various voltage
  * domains to the voltage as per the opp table. Typically we boot up
  * at the nominal voltage. So this function finds out the rate of
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 2741a9b..5f255c5 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -18,7 +18,6 @@
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
-extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap3_idle_init(void);
 extern int omap4_idle_init(void);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
diff --git a/arch/arm/mach-omap2/powerdomain-common.c b/arch/arm/mach-omap2/powerdomain-common.c
index c0aeabf..57c135e 100644
--- a/arch/arm/mach-omap2/powerdomain-common.c
+++ b/arch/arm/mach-omap2/powerdomain-common.c
@@ -108,3 +108,93 @@ u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank)
 	return 0;
 }
 
+/**
+ * omap2_pwrdm_func_to_pwrst - Convert functional (i.e. logical) to
+ * internal (i.e. registers) values for the power domains states.
+ * @pwrdm: struct powerdomain * to convert values for
+ * @func_pwrst: functional power state
+ * @pwrst:	returned with power state
+ * @logic_pwrst: returned with logic power state
+ *
+ * Returns the internal power state value for the power domain, or
+ * -EINVAL in case of invalid parameters passed in.
+ */
+int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm,
+			      enum pwrdm_func_state func_pwrst,
+			      u8 *pwrst, u8 *logic_pwrst)
+{
+	int ret = 0;
+
+	if (!pwrst || !logic_pwrst) {
+		WARN(1, "bad pointer passage\n");
+		return -EINVAL;
+	}
+
+	switch (func_pwrst) {
+	case PWRDM_FUNC_PWRST_ON:
+		*pwrst = PWRDM_POWER_ON;
+		/* Does not matter which - RET is max which is configurable */
+		*logic_pwrst = PWRDM_POWER_RET;
+		break;
+	case PWRDM_FUNC_PWRST_INACTIVE:
+		*pwrst = PWRDM_POWER_INACTIVE;
+		/* Does not matter which - RET is max which is configurable */
+		*logic_pwrst = PWRDM_POWER_RET;
+		break;
+	case PWRDM_FUNC_PWRST_CSWR:
+		*pwrst = PWRDM_POWER_RET;
+		*logic_pwrst = PWRDM_POWER_RET;
+		break;
+	case PWRDM_FUNC_PWRST_OSWR:
+		*pwrst = PWRDM_POWER_RET;
+		*logic_pwrst = PWRDM_POWER_OFF;
+		break;
+	case PWRDM_FUNC_PWRST_OFF:
+		*pwrst = PWRDM_POWER_OFF;
+		/* Does not matter which here.. */
+		*logic_pwrst = PWRDM_POWER_OFF;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/**
+ * omap2_pwrdm_pwrst_to_func - Convert internal (i.e. registers) to
+ * functional (i.e. logical) values for the power domains states.
+ * @pwrdm: struct powerdomain * to convert values for
+ * @pwrst: internal power state
+ * @logic_pwrst: internal logic power state
+ *
+ * Returns the functional power state value for the power domain, or
+ * -EINVAL in case of invalid parameters passed in.
+ */
+enum pwrdm_func_state omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm,
+						u8 pwrst, u8 logic_pwrst)
+{
+	enum pwrdm_func_state ret;
+
+	switch (pwrst) {
+	case PWRDM_POWER_ON:
+		ret = PWRDM_FUNC_PWRST_ON;
+		break;
+	case PWRDM_POWER_INACTIVE:
+		ret = PWRDM_FUNC_PWRST_INACTIVE;
+		break;
+	case PWRDM_POWER_RET:
+		if (logic_pwrst == PWRDM_POWER_OFF)
+			ret = PWRDM_FUNC_PWRST_OSWR;
+		else
+			ret = PWRDM_FUNC_PWRST_CSWR;
+		break;
+	case PWRDM_POWER_OFF:
+		ret = PWRDM_FUNC_PWRST_OFF;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 624db97..319a863 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -468,6 +468,156 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
 }
 
 /**
+ * pwrdm_func_to_pwrst - get the internal (i.e. registers) value mapped
+ * to the functional state
+ * @pwrdm:	struct powerdomain * to query
+ * @func_pwrst:	functional power state
+ * @pwrst:	returned with power state
+ * @logic_pwrst: returned with logic power state
+ *
+ * Convert the functional power state to the platform specific power
+ * domain state value.
+ * Returns the internal power domain state value or -EINVAL in case
+ * of invalid parameters passed in.
+ */
+int pwrdm_func_to_pwrst(struct powerdomain *pwrdm,
+			enum pwrdm_func_state func_pwrst,
+			u8 *pwrst, u8 *logic_pwrst)
+{
+	int ret = -EEXIST;
+
+	if ((!pwrdm) || (func_pwrst >= PWRDM_MAX_FUNC_PWRSTS))
+		return -EINVAL;
+
+	if (arch_pwrdm && arch_pwrdm->pwrdm_func_to_pwrst)
+		ret = arch_pwrdm->pwrdm_func_to_pwrst(pwrdm, func_pwrst,
+						      pwrst, logic_pwrst);
+
+	pr_debug("powerdomain: convert func %0x to pwrst %0x for %s\n",
+		 func_pwrst, ret, pwrdm->name);
+
+	return ret;
+}
+
+/**
+ * pwrdm_pwrst_to_func - get the functional (i.e. logical) value mapped
+ * to the internal state
+ * @pwrdm:	struct powerdomain * to query
+ * @pwrst:	internal power state
+ * @pwrst:	power state
+ * @logic_pwrst: logic power state
+ *
+ * Convert the internal power state to the power domain functional value.
+ * Returns the functional power domain state value or -EINVAL in case
+ * of invalid parameters passed in.
+ */
+enum pwrdm_func_state pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst,
+					  u8 logic_pwrst)
+{
+	int ret = -EEXIST;
+
+	if ((!pwrdm) || (pwrst >= PWRDM_MAX_PWRSTS))
+		return -EINVAL;
+
+	pr_debug("powerdomain: convert %0x pwrst to func for %s\n",
+		 pwrst, pwrdm->name);
+
+	if (arch_pwrdm && arch_pwrdm->pwrdm_pwrst_to_func)
+		ret = arch_pwrdm->pwrdm_pwrst_to_func(pwrdm, pwrst,
+						      logic_pwrst);
+
+	return ret;
+}
+
+/* Types of sleep_switch used in omap_set_pwrdm_state */
+#define FORCEWAKEUP_SWITCH	0
+#define LOWPOWERSTATE_SWITCH	1
+
+/**
+ * omap_set_pwrdm_state - program next powerdomain power state
+ * @pwrdm: struct powerdomain * to set
+ * @func_pwrst: power domain functional state, one of the PWRDM_FUNC_* macros
+ *
+ * This programs the pwrdm next functional state, sets the dependencies
+ * and waits for the state to be applied.
+ */
+int omap_set_pwrdm_state(struct powerdomain *pwrdm,
+			 enum pwrdm_func_state func_pwrst)
+{
+	u8 curr_pwrst, next_pwrst;
+	u8 pwrst, logic_pwrst;
+	int sleep_switch = -1, ret = 0, hwsup = 0;
+
+	if (!pwrdm || IS_ERR(pwrdm)) {
+		pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
+			 __func__, pwrdm, func_pwrst);
+		return -EINVAL;
+	}
+
+	ret = pwrdm_func_to_pwrst(pwrdm, func_pwrst, &pwrst, &logic_pwrst);
+	if (ret < 0) {
+		pr_debug("%s: invalid params: pwrdm=%s, func_pwrst=%0x\n",
+			 __func__, pwrdm->name, func_pwrst);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: set func_pwrst %0x to pwrdm %s\n",
+		 __func__, func_pwrst, pwrdm->name);
+
+	spin_lock(&pwrdm->lock);
+
+	while (!(pwrdm->pwrsts & (1 << pwrst))) {
+		if (pwrst == PWRDM_POWER_OFF)
+			goto out;
+		pwrst--;
+	}
+
+	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
+	if (next_pwrst == pwrst)
+		goto out;
+
+	curr_pwrst = pwrdm_read_pwrst(pwrdm);
+	if (curr_pwrst < PWRDM_POWER_ON) {
+		if ((curr_pwrst > pwrst) &&
+		    (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
+			sleep_switch = LOWPOWERSTATE_SWITCH;
+		} else {
+			hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
+			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+			sleep_switch = FORCEWAKEUP_SWITCH;
+		}
+	}
+
+	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
+	if (ret)
+		pr_err("%s: unable to set power state of powerdomain: %s (%d)\n",
+		       __func__, pwrdm->name, ret);
+	ret = pwrdm_set_logic_retst(pwrdm, logic_pwrst);
+	if (ret)
+		pr_err("%s: unable to set logic power state of powerdomain: %s (%d)\n",
+		       __func__, pwrdm->name, ret);
+
+
+	switch (sleep_switch) {
+	case FORCEWAKEUP_SWITCH:
+		if (hwsup)
+			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+		else
+			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
+		break;
+	case LOWPOWERSTATE_SWITCH:
+		pwrdm_set_lowpwrstchange(pwrdm);
+		pwrdm_wait_transition(pwrdm);
+		pwrdm_state_switch(pwrdm);
+		break;
+	}
+
+out:
+	spin_unlock(&pwrdm->lock);
+	return ret;
+}
+
+/**
  * pwrdm_set_next_pwrst - set next powerdomain power state
  * @pwrdm: struct powerdomain * to set
  * @pwrst: one of the PWRDM_POWER_* macros
@@ -524,6 +674,22 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
 }
 
 /**
+ * pwrdm_read_next_func_pwrst - get next powerdomain functional power state
+ * @pwrdm: struct powerdomain * to get power state
+ *
+ * Return the powerdomain @pwrdm's next functional power state.
+ * Returns -EINVAL if the powerdomain pointer is null or returns
+ * the next power state upon success.
+ */
+enum pwrdm_func_state pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm)
+{
+	int pwrst = pwrdm_read_next_pwrst(pwrdm);
+	int logic_st = pwrdm_read_logic_retst(pwrdm);
+
+	return pwrdm_pwrst_to_func(pwrdm, pwrst, logic_st);
+}
+
+/**
  * pwrdm_read_pwrst - get current powerdomain power state
  * @pwrdm: struct powerdomain * to get power state
  *
@@ -549,6 +715,22 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm)
 }
 
 /**
+ * pwrdm_read_func_pwrst - get current powerdomain functional power state
+ * @pwrdm: struct powerdomain * to get power state
+ *
+ * Return the powerdomain @pwrdm's current functional power state.
+ * Returns -EINVAL if the powerdomain pointer is null or returns
+ * the current power state upon success.
+ */
+enum pwrdm_func_state pwrdm_read_func_pwrst(struct powerdomain *pwrdm)
+{
+	int pwrst = pwrdm_read_pwrst(pwrdm);
+	int logic_pwrst = pwrdm_read_logic_pwrst(pwrdm);
+
+	return pwrdm_pwrst_to_func(pwrdm, pwrst, logic_pwrst);
+}
+
+/**
  * pwrdm_read_prev_pwrst - get previous powerdomain power state
  * @pwrdm: struct powerdomain * to get previous power state
  *
@@ -570,6 +752,31 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
 }
 
 /**
+ * pwrdm_read_prev_func_pwrst - get previous powerdomain functional power state
+ * @pwrdm: struct powerdomain * to get previous power state
+ *
+ * Return the powerdomain @pwrdm's previous functional power state.
+ * Returns -EINVAL if the powerdomain pointer is null or returns the
+ * previous power state upon success.
+ */
+enum pwrdm_func_state pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm)
+{
+	int pwrst = pwrdm_read_prev_pwrst(pwrdm);
+	int logic_pwrst = pwrdm_read_prev_logic_pwrst(pwrdm);
+
+	/* Fake Logic off if SoC has no such state register */
+	if (logic_pwrst < 0 && pwrdm) {
+		if (pwrdm->pwrsts_logic_ret & PWRDM_POWER_OFF &&
+		    pwrdm_read_logic_retst(pwrdm) == PWRDM_POWER_OFF)
+			logic_pwrst = PWRDM_POWER_OFF;
+		else
+			logic_pwrst = PWRDM_POWER_RET;
+	}
+
+	return pwrdm_pwrst_to_func(pwrdm, pwrst, logic_pwrst);
+}
+
+/**
  * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
  * @pwrdm: struct powerdomain * to set
  * @pwrst: one of the PWRDM_POWER_* macros
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index 20fcb06..bdb6c0f 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -9,9 +9,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * XXX This should be moved to the mach-omap2/ directory at the earliest
- * opportunity.
  */
 
 #ifndef __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H
@@ -26,7 +23,51 @@
 
 #include "voltage.h"
 
-/* Powerdomain basic power states */
+/***************************************************************
+ * External API
+ ***************************************************************/
+
+/* Powerdomain functional power states, used by the external API functions */
+enum pwrdm_func_state {
+	PWRDM_FUNC_PWRST_OFF		= 0x0,
+	PWRDM_FUNC_PWRST_OSWR,
+	PWRDM_FUNC_PWRST_CSWR,
+	PWRDM_FUNC_PWRST_INACTIVE,
+	PWRDM_FUNC_PWRST_ON,
+	PWRDM_MAX_FUNC_PWRSTS		/* Last value, used as the max value */
+};
+
+struct clockdomain;
+struct powerdomain;
+
+struct powerdomain *pwrdm_lookup(const char *name);
+
+int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
+			void *user);
+int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
+			void *user);
+
+struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
+
+int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
+
+enum pwrdm_func_state pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm);
+enum pwrdm_func_state pwrdm_read_func_pwrst(struct powerdomain *pwrdm);
+enum pwrdm_func_state pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm);
+extern int omap_set_pwrdm_state(struct powerdomain *pwrdm,
+				enum pwrdm_func_state func_pwrst);
+
+extern void omap242x_powerdomains_init(void);
+extern void omap243x_powerdomains_init(void);
+extern void omap3xxx_powerdomains_init(void);
+extern void omap44xx_powerdomains_init(void);
+extern void omap54xx_powerdomains_init(void);
+
+/***************************************************************
+ * Internal code, only used in powerdomain*.[ch]
+ ***************************************************************/
+
+/* Powerdomain internal power states, internal use only */
 #define PWRDM_POWER_OFF		0x0
 #define PWRDM_POWER_RET		0x1
 #define PWRDM_POWER_INACTIVE	0x2
@@ -85,9 +126,6 @@
 #define PWRDM_TRANSITION_BAILOUT 100000
 #endif
 
-struct clockdomain;
-struct powerdomain;
-
 /**
  * struct powerdomain - OMAP powerdomain
  * @name: Powerdomain name
@@ -143,6 +181,10 @@ struct powerdomain {
 
 /**
  * struct pwrdm_ops - Arch specific function implementations
+ * @pwrdm_func_to_pwrst: Convert the pd functional power state to
+ *  the internal state
+ * @pwrdm_pwrst_to_func: Convert the pd internal power state to
+ *  the functional state
  * @pwrdm_set_next_pwrst: Set the target power state for a pd
  * @pwrdm_read_next_pwrst: Read the target power state set for a pd
  * @pwrdm_read_pwrst: Read the current power state of a pd
@@ -165,6 +207,8 @@ struct powerdomain {
  * @pwrdm_disable_force_off: Disable force off transition feature for the pd
  */
 struct pwrdm_ops {
+	int	(*pwrdm_func_to_pwrst)(struct powerdomain *pwrdm, enum pwrdm_func_state  func_pwrst, u8 *pwrst, u8 *logic_pwrst);
+	enum pwrdm_func_state (*pwrdm_pwrst_to_func)(struct powerdomain *pwrdm, u8 pwrst, u8 logic_pwrst);
 	int	(*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst);
 	int	(*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm);
 	int	(*pwrdm_read_pwrst)(struct powerdomain *pwrdm);
@@ -191,21 +235,11 @@ int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
 int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list);
 int pwrdm_complete_init(void);
 
-struct powerdomain *pwrdm_lookup(const char *name);
-
-int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
-			void *user);
-int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
-			void *user);
-
 int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
 int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
 int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
 			 int (*fn)(struct powerdomain *pwrdm,
 				   struct clockdomain *clkdm));
-struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
-
-int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
 
 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
 int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
@@ -213,6 +247,12 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm);
 int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
 int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
 
+int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm,
+			      enum pwrdm_func_state func_pwrst, u8 *pwrst,
+			      u8 *logic_pwrst);
+enum pwrdm_func_state omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm,
+						u8 pwrst, u8 logic_pwrst);
+
 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
 int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
@@ -240,11 +280,11 @@ bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 int pwrdm_enable_force_off(struct powerdomain *pwrdm);
 int pwrdm_disable_force_off(struct powerdomain *pwrdm);
 
-extern void omap242x_powerdomains_init(void);
-extern void omap243x_powerdomains_init(void);
-extern void omap3xxx_powerdomains_init(void);
-extern void omap44xx_powerdomains_init(void);
-extern void omap54xx_powerdomains_init(void);
+enum pwrdm_func_state pwrdm_pwrst_to_func(struct powerdomain *pwrdm,
+					  u8 pwrst, u8 logic_pwrst);
+int pwrdm_func_to_pwrst(struct powerdomain *pwrdm,
+			enum pwrdm_func_state func_pwrst,
+			u8 *pwrst, u8 *logic_pwrst);
 
 extern struct pwrdm_ops omap2_pwrdm_operations;
 extern struct pwrdm_ops omap3_pwrdm_operations;
diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
index 0f0a9f1..79c1293 100644
--- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
@@ -26,6 +26,7 @@
 
 
 /* Common functions across OMAP2 and OMAP3 */
+
 static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 {
 	omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
@@ -210,6 +211,8 @@ static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
 }
 
 struct pwrdm_ops omap2_pwrdm_operations = {
+	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
 	.pwrdm_read_pwrst	= omap2_pwrdm_read_pwrst,
@@ -222,6 +225,8 @@ struct pwrdm_ops omap2_pwrdm_operations = {
 };
 
 struct pwrdm_ops omap3_pwrdm_operations = {
+	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
 	.pwrdm_read_pwrst	= omap2_pwrdm_read_pwrst,
diff --git a/arch/arm/mach-omap2/powerdomain4xxx_5xxx.c b/arch/arm/mach-omap2/powerdomain4xxx_5xxx.c
index e1e7d44..ad32f70 100644
--- a/arch/arm/mach-omap2/powerdomain4xxx_5xxx.c
+++ b/arch/arm/mach-omap2/powerdomain4xxx_5xxx.c
@@ -229,6 +229,8 @@ static int omap5_pwrdm_disable_force_off(struct powerdomain *pwrdm)
 
 
 struct pwrdm_ops omap4_pwrdm_operations = {
+	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap4_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap4_pwrdm_read_next_pwrst,
 	.pwrdm_read_pwrst	= omap4_pwrdm_read_pwrst,
@@ -246,6 +248,8 @@ struct pwrdm_ops omap4_pwrdm_operations = {
 };
 
 struct pwrdm_ops omap5_pwrdm_operations = {
+	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap4_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap4_pwrdm_read_next_pwrst,
 	.pwrdm_read_pwrst	= omap4_pwrdm_read_pwrst,
-- 
1.7.9.5

-- 
Regards,
Nishanth Menon

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
@ 2012-07-13  4:39       ` Nishanth Menon
  0 siblings, 0 replies; 44+ messages in thread
From: Nishanth Menon @ 2012-07-13  4:39 UTC (permalink / raw)
  To: linux-arm-kernel

On 22:01-20120712, Menon, Nishanth wrote:
> On Thu, Jun 14, 2012 at 9:53 AM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
> [..]
> > +int pwrdm_read_func_pwrst(struct powerdomain *pwrdm)
> should return enum pwrdm_func_state
> > +{
> > +       int ret = pwrdm_read_pwrst(pwrdm);
> > +
> > +       return pwrdm_pwrst_to_func(pwrdm, ret);
> > +}
> 
> my Crib about the above apis are lack of logic power state handling :(
> which forces code like cpuidle to use different apis for logic
> power state and force them to use these apis just for pwrst.
> 
[..]
> > +extern void omap242x_powerdomains_init(void);
> > +extern void omap243x_powerdomains_init(void);
> > +extern void omap3xxx_powerdomains_init(void);
> > +extern void omap44xx_powerdomains_init(void);
> > +
> > +
> 
> We should split the following out to a separate header which is not to
> be used by anyone else other than powerdomain*.[ch]
without doing this..
[..]
> >   */
> >  struct pwrdm_ops {
> > +       int     (*pwrdm_func_to_pwrst)(struct powerdomain *pwrdm, u8 func_pwrst);
> should take in enum pwrdm_func_state
> > +       int     (*pwrdm_pwrst_to_func)(struct powerdomain *pwrdm, u8 func_pwrst);
> should return enum pwrdm_func_state
> 
[...]
> otherwise, this is a nice concept

Here is how it might look like: (baseline internal tree)


diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index c426dc4..30a4bb1 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -129,10 +129,6 @@ static void __init omap2_init_processor_devices(void)
 	}
 }
 
-/* Types of sleep_switch used in omap_set_pwrdm_state */
-#define FORCEWAKEUP_SWITCH	0
-#define LOWPOWERSTATE_SWITCH	1
-
 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
 	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
@@ -144,68 +140,6 @@ int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 }
 
 /*
- * This sets pwrdm state (other than mpu & core. Currently only ON &
- * RET are supported.
- */
-int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
-{
-	u8 curr_pwrst, next_pwrst;
-	int sleep_switch = -1, ret = 0, hwsup = 0;
-
-	if (!pwrdm || IS_ERR(pwrdm))
-		return -EINVAL;
-
-	spin_lock(&pwrdm->lock);
-
-	while (!(pwrdm->pwrsts & (1 << pwrst))) {
-		if (pwrst == PWRDM_POWER_OFF)
-			goto out;
-		pwrst--;
-	}
-
-	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
-	if (next_pwrst == pwrst)
-		goto out;
-
-	curr_pwrst = pwrdm_read_pwrst(pwrdm);
-	if (curr_pwrst < PWRDM_POWER_ON) {
-		if ((curr_pwrst > pwrst) &&
-			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
-			sleep_switch = LOWPOWERSTATE_SWITCH;
-		} else {
-			hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
-			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
-			sleep_switch = FORCEWAKEUP_SWITCH;
-		}
-	}
-
-	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
-	if (ret)
-		pr_err("%s: unable to set power state of powerdomain: %s\n",
-		       __func__, pwrdm->name);
-
-	switch (sleep_switch) {
-	case FORCEWAKEUP_SWITCH:
-		if (hwsup)
-			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
-		else
-			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
-		break;
-	case LOWPOWERSTATE_SWITCH:
-		pwrdm_set_lowpwrstchange(pwrdm);
-		pwrdm_wait_transition(pwrdm);
-		pwrdm_state_switch(pwrdm);
-		break;
-	}
-
-out:
-	spin_unlock(&pwrdm->lock);
-	return ret;
-}
-
-
-
-/*
  * This API is to be called during init to set the various voltage
  * domains to the voltage as per the opp table. Typically we boot up
  * at the nominal voltage. So this function finds out the rate of
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 2741a9b..5f255c5 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -18,7 +18,6 @@
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
-extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap3_idle_init(void);
 extern int omap4_idle_init(void);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
diff --git a/arch/arm/mach-omap2/powerdomain-common.c b/arch/arm/mach-omap2/powerdomain-common.c
index c0aeabf..57c135e 100644
--- a/arch/arm/mach-omap2/powerdomain-common.c
+++ b/arch/arm/mach-omap2/powerdomain-common.c
@@ -108,3 +108,93 @@ u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank)
 	return 0;
 }
 
+/**
+ * omap2_pwrdm_func_to_pwrst - Convert functional (i.e. logical) to
+ * internal (i.e. registers) values for the power domains states.
+ * @pwrdm: struct powerdomain * to convert values for
+ * @func_pwrst: functional power state
+ * @pwrst:	returned with power state
+ * @logic_pwrst: returned with logic power state
+ *
+ * Returns the internal power state value for the power domain, or
+ * -EINVAL in case of invalid parameters passed in.
+ */
+int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm,
+			      enum pwrdm_func_state func_pwrst,
+			      u8 *pwrst, u8 *logic_pwrst)
+{
+	int ret = 0;
+
+	if (!pwrst || !logic_pwrst) {
+		WARN(1, "bad pointer passage\n");
+		return -EINVAL;
+	}
+
+	switch (func_pwrst) {
+	case PWRDM_FUNC_PWRST_ON:
+		*pwrst = PWRDM_POWER_ON;
+		/* Does not matter which - RET is max which is configurable */
+		*logic_pwrst = PWRDM_POWER_RET;
+		break;
+	case PWRDM_FUNC_PWRST_INACTIVE:
+		*pwrst = PWRDM_POWER_INACTIVE;
+		/* Does not matter which - RET is max which is configurable */
+		*logic_pwrst = PWRDM_POWER_RET;
+		break;
+	case PWRDM_FUNC_PWRST_CSWR:
+		*pwrst = PWRDM_POWER_RET;
+		*logic_pwrst = PWRDM_POWER_RET;
+		break;
+	case PWRDM_FUNC_PWRST_OSWR:
+		*pwrst = PWRDM_POWER_RET;
+		*logic_pwrst = PWRDM_POWER_OFF;
+		break;
+	case PWRDM_FUNC_PWRST_OFF:
+		*pwrst = PWRDM_POWER_OFF;
+		/* Does not matter which here.. */
+		*logic_pwrst = PWRDM_POWER_OFF;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/**
+ * omap2_pwrdm_pwrst_to_func - Convert internal (i.e. registers) to
+ * functional (i.e. logical) values for the power domains states.
+ * @pwrdm: struct powerdomain * to convert values for
+ * @pwrst: internal power state
+ * @logic_pwrst: internal logic power state
+ *
+ * Returns the functional power state value for the power domain, or
+ * -EINVAL in case of invalid parameters passed in.
+ */
+enum pwrdm_func_state omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm,
+						u8 pwrst, u8 logic_pwrst)
+{
+	enum pwrdm_func_state ret;
+
+	switch (pwrst) {
+	case PWRDM_POWER_ON:
+		ret = PWRDM_FUNC_PWRST_ON;
+		break;
+	case PWRDM_POWER_INACTIVE:
+		ret = PWRDM_FUNC_PWRST_INACTIVE;
+		break;
+	case PWRDM_POWER_RET:
+		if (logic_pwrst == PWRDM_POWER_OFF)
+			ret = PWRDM_FUNC_PWRST_OSWR;
+		else
+			ret = PWRDM_FUNC_PWRST_CSWR;
+		break;
+	case PWRDM_POWER_OFF:
+		ret = PWRDM_FUNC_PWRST_OFF;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 624db97..319a863 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -468,6 +468,156 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
 }
 
 /**
+ * pwrdm_func_to_pwrst - get the internal (i.e. registers) value mapped
+ * to the functional state
+ * @pwrdm:	struct powerdomain * to query
+ * @func_pwrst:	functional power state
+ * @pwrst:	returned with power state
+ * @logic_pwrst: returned with logic power state
+ *
+ * Convert the functional power state to the platform specific power
+ * domain state value.
+ * Returns the internal power domain state value or -EINVAL in case
+ * of invalid parameters passed in.
+ */
+int pwrdm_func_to_pwrst(struct powerdomain *pwrdm,
+			enum pwrdm_func_state func_pwrst,
+			u8 *pwrst, u8 *logic_pwrst)
+{
+	int ret = -EEXIST;
+
+	if ((!pwrdm) || (func_pwrst >= PWRDM_MAX_FUNC_PWRSTS))
+		return -EINVAL;
+
+	if (arch_pwrdm && arch_pwrdm->pwrdm_func_to_pwrst)
+		ret = arch_pwrdm->pwrdm_func_to_pwrst(pwrdm, func_pwrst,
+						      pwrst, logic_pwrst);
+
+	pr_debug("powerdomain: convert func %0x to pwrst %0x for %s\n",
+		 func_pwrst, ret, pwrdm->name);
+
+	return ret;
+}
+
+/**
+ * pwrdm_pwrst_to_func - get the functional (i.e. logical) value mapped
+ * to the internal state
+ * @pwrdm:	struct powerdomain * to query
+ * @pwrst:	internal power state
+ * @pwrst:	power state
+ * @logic_pwrst: logic power state
+ *
+ * Convert the internal power state to the power domain functional value.
+ * Returns the functional power domain state value or -EINVAL in case
+ * of invalid parameters passed in.
+ */
+enum pwrdm_func_state pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst,
+					  u8 logic_pwrst)
+{
+	int ret = -EEXIST;
+
+	if ((!pwrdm) || (pwrst >= PWRDM_MAX_PWRSTS))
+		return -EINVAL;
+
+	pr_debug("powerdomain: convert %0x pwrst to func for %s\n",
+		 pwrst, pwrdm->name);
+
+	if (arch_pwrdm && arch_pwrdm->pwrdm_pwrst_to_func)
+		ret = arch_pwrdm->pwrdm_pwrst_to_func(pwrdm, pwrst,
+						      logic_pwrst);
+
+	return ret;
+}
+
+/* Types of sleep_switch used in omap_set_pwrdm_state */
+#define FORCEWAKEUP_SWITCH	0
+#define LOWPOWERSTATE_SWITCH	1
+
+/**
+ * omap_set_pwrdm_state - program next powerdomain power state
+ * @pwrdm: struct powerdomain * to set
+ * @func_pwrst: power domain functional state, one of the PWRDM_FUNC_* macros
+ *
+ * This programs the pwrdm next functional state, sets the dependencies
+ * and waits for the state to be applied.
+ */
+int omap_set_pwrdm_state(struct powerdomain *pwrdm,
+			 enum pwrdm_func_state func_pwrst)
+{
+	u8 curr_pwrst, next_pwrst;
+	u8 pwrst, logic_pwrst;
+	int sleep_switch = -1, ret = 0, hwsup = 0;
+
+	if (!pwrdm || IS_ERR(pwrdm)) {
+		pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
+			 __func__, pwrdm, func_pwrst);
+		return -EINVAL;
+	}
+
+	ret = pwrdm_func_to_pwrst(pwrdm, func_pwrst, &pwrst, &logic_pwrst);
+	if (ret < 0) {
+		pr_debug("%s: invalid params: pwrdm=%s, func_pwrst=%0x\n",
+			 __func__, pwrdm->name, func_pwrst);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: set func_pwrst %0x to pwrdm %s\n",
+		 __func__, func_pwrst, pwrdm->name);
+
+	spin_lock(&pwrdm->lock);
+
+	while (!(pwrdm->pwrsts & (1 << pwrst))) {
+		if (pwrst == PWRDM_POWER_OFF)
+			goto out;
+		pwrst--;
+	}
+
+	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
+	if (next_pwrst == pwrst)
+		goto out;
+
+	curr_pwrst = pwrdm_read_pwrst(pwrdm);
+	if (curr_pwrst < PWRDM_POWER_ON) {
+		if ((curr_pwrst > pwrst) &&
+		    (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
+			sleep_switch = LOWPOWERSTATE_SWITCH;
+		} else {
+			hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
+			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+			sleep_switch = FORCEWAKEUP_SWITCH;
+		}
+	}
+
+	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
+	if (ret)
+		pr_err("%s: unable to set power state of powerdomain: %s (%d)\n",
+		       __func__, pwrdm->name, ret);
+	ret = pwrdm_set_logic_retst(pwrdm, logic_pwrst);
+	if (ret)
+		pr_err("%s: unable to set logic power state of powerdomain: %s (%d)\n",
+		       __func__, pwrdm->name, ret);
+
+
+	switch (sleep_switch) {
+	case FORCEWAKEUP_SWITCH:
+		if (hwsup)
+			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+		else
+			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
+		break;
+	case LOWPOWERSTATE_SWITCH:
+		pwrdm_set_lowpwrstchange(pwrdm);
+		pwrdm_wait_transition(pwrdm);
+		pwrdm_state_switch(pwrdm);
+		break;
+	}
+
+out:
+	spin_unlock(&pwrdm->lock);
+	return ret;
+}
+
+/**
  * pwrdm_set_next_pwrst - set next powerdomain power state
  * @pwrdm: struct powerdomain * to set
  * @pwrst: one of the PWRDM_POWER_* macros
@@ -524,6 +674,22 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
 }
 
 /**
+ * pwrdm_read_next_func_pwrst - get next powerdomain functional power state
+ * @pwrdm: struct powerdomain * to get power state
+ *
+ * Return the powerdomain @pwrdm's next functional power state.
+ * Returns -EINVAL if the powerdomain pointer is null or returns
+ * the next power state upon success.
+ */
+enum pwrdm_func_state pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm)
+{
+	int pwrst = pwrdm_read_next_pwrst(pwrdm);
+	int logic_st = pwrdm_read_logic_retst(pwrdm);
+
+	return pwrdm_pwrst_to_func(pwrdm, pwrst, logic_st);
+}
+
+/**
  * pwrdm_read_pwrst - get current powerdomain power state
  * @pwrdm: struct powerdomain * to get power state
  *
@@ -549,6 +715,22 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm)
 }
 
 /**
+ * pwrdm_read_func_pwrst - get current powerdomain functional power state
+ * @pwrdm: struct powerdomain * to get power state
+ *
+ * Return the powerdomain @pwrdm's current functional power state.
+ * Returns -EINVAL if the powerdomain pointer is null or returns
+ * the current power state upon success.
+ */
+enum pwrdm_func_state pwrdm_read_func_pwrst(struct powerdomain *pwrdm)
+{
+	int pwrst = pwrdm_read_pwrst(pwrdm);
+	int logic_pwrst = pwrdm_read_logic_pwrst(pwrdm);
+
+	return pwrdm_pwrst_to_func(pwrdm, pwrst, logic_pwrst);
+}
+
+/**
  * pwrdm_read_prev_pwrst - get previous powerdomain power state
  * @pwrdm: struct powerdomain * to get previous power state
  *
@@ -570,6 +752,31 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
 }
 
 /**
+ * pwrdm_read_prev_func_pwrst - get previous powerdomain functional power state
+ * @pwrdm: struct powerdomain * to get previous power state
+ *
+ * Return the powerdomain @pwrdm's previous functional power state.
+ * Returns -EINVAL if the powerdomain pointer is null or returns the
+ * previous power state upon success.
+ */
+enum pwrdm_func_state pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm)
+{
+	int pwrst = pwrdm_read_prev_pwrst(pwrdm);
+	int logic_pwrst = pwrdm_read_prev_logic_pwrst(pwrdm);
+
+	/* Fake Logic off if SoC has no such state register */
+	if (logic_pwrst < 0 && pwrdm) {
+		if (pwrdm->pwrsts_logic_ret & PWRDM_POWER_OFF &&
+		    pwrdm_read_logic_retst(pwrdm) == PWRDM_POWER_OFF)
+			logic_pwrst = PWRDM_POWER_OFF;
+		else
+			logic_pwrst = PWRDM_POWER_RET;
+	}
+
+	return pwrdm_pwrst_to_func(pwrdm, pwrst, logic_pwrst);
+}
+
+/**
  * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
  * @pwrdm: struct powerdomain * to set
  * @pwrst: one of the PWRDM_POWER_* macros
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index 20fcb06..bdb6c0f 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -9,9 +9,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * XXX This should be moved to the mach-omap2/ directory at the earliest
- * opportunity.
  */
 
 #ifndef __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H
@@ -26,7 +23,51 @@
 
 #include "voltage.h"
 
-/* Powerdomain basic power states */
+/***************************************************************
+ * External API
+ ***************************************************************/
+
+/* Powerdomain functional power states, used by the external API functions */
+enum pwrdm_func_state {
+	PWRDM_FUNC_PWRST_OFF		= 0x0,
+	PWRDM_FUNC_PWRST_OSWR,
+	PWRDM_FUNC_PWRST_CSWR,
+	PWRDM_FUNC_PWRST_INACTIVE,
+	PWRDM_FUNC_PWRST_ON,
+	PWRDM_MAX_FUNC_PWRSTS		/* Last value, used as the max value */
+};
+
+struct clockdomain;
+struct powerdomain;
+
+struct powerdomain *pwrdm_lookup(const char *name);
+
+int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
+			void *user);
+int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
+			void *user);
+
+struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
+
+int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
+
+enum pwrdm_func_state pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm);
+enum pwrdm_func_state pwrdm_read_func_pwrst(struct powerdomain *pwrdm);
+enum pwrdm_func_state pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm);
+extern int omap_set_pwrdm_state(struct powerdomain *pwrdm,
+				enum pwrdm_func_state func_pwrst);
+
+extern void omap242x_powerdomains_init(void);
+extern void omap243x_powerdomains_init(void);
+extern void omap3xxx_powerdomains_init(void);
+extern void omap44xx_powerdomains_init(void);
+extern void omap54xx_powerdomains_init(void);
+
+/***************************************************************
+ * Internal code, only used in powerdomain*.[ch]
+ ***************************************************************/
+
+/* Powerdomain internal power states, internal use only */
 #define PWRDM_POWER_OFF		0x0
 #define PWRDM_POWER_RET		0x1
 #define PWRDM_POWER_INACTIVE	0x2
@@ -85,9 +126,6 @@
 #define PWRDM_TRANSITION_BAILOUT 100000
 #endif
 
-struct clockdomain;
-struct powerdomain;
-
 /**
  * struct powerdomain - OMAP powerdomain
  * @name: Powerdomain name
@@ -143,6 +181,10 @@ struct powerdomain {
 
 /**
  * struct pwrdm_ops - Arch specific function implementations
+ * @pwrdm_func_to_pwrst: Convert the pd functional power state to
+ *  the internal state
+ * @pwrdm_pwrst_to_func: Convert the pd internal power state to
+ *  the functional state
  * @pwrdm_set_next_pwrst: Set the target power state for a pd
  * @pwrdm_read_next_pwrst: Read the target power state set for a pd
  * @pwrdm_read_pwrst: Read the current power state of a pd
@@ -165,6 +207,8 @@ struct powerdomain {
  * @pwrdm_disable_force_off: Disable force off transition feature for the pd
  */
 struct pwrdm_ops {
+	int	(*pwrdm_func_to_pwrst)(struct powerdomain *pwrdm, enum pwrdm_func_state  func_pwrst, u8 *pwrst, u8 *logic_pwrst);
+	enum pwrdm_func_state (*pwrdm_pwrst_to_func)(struct powerdomain *pwrdm, u8 pwrst, u8 logic_pwrst);
 	int	(*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst);
 	int	(*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm);
 	int	(*pwrdm_read_pwrst)(struct powerdomain *pwrdm);
@@ -191,21 +235,11 @@ int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
 int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list);
 int pwrdm_complete_init(void);
 
-struct powerdomain *pwrdm_lookup(const char *name);
-
-int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
-			void *user);
-int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
-			void *user);
-
 int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
 int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
 int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
 			 int (*fn)(struct powerdomain *pwrdm,
 				   struct clockdomain *clkdm));
-struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
-
-int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
 
 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
 int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
@@ -213,6 +247,12 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm);
 int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
 int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
 
+int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm,
+			      enum pwrdm_func_state func_pwrst, u8 *pwrst,
+			      u8 *logic_pwrst);
+enum pwrdm_func_state omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm,
+						u8 pwrst, u8 logic_pwrst);
+
 int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
 int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
 int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
@@ -240,11 +280,11 @@ bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 int pwrdm_enable_force_off(struct powerdomain *pwrdm);
 int pwrdm_disable_force_off(struct powerdomain *pwrdm);
 
-extern void omap242x_powerdomains_init(void);
-extern void omap243x_powerdomains_init(void);
-extern void omap3xxx_powerdomains_init(void);
-extern void omap44xx_powerdomains_init(void);
-extern void omap54xx_powerdomains_init(void);
+enum pwrdm_func_state pwrdm_pwrst_to_func(struct powerdomain *pwrdm,
+					  u8 pwrst, u8 logic_pwrst);
+int pwrdm_func_to_pwrst(struct powerdomain *pwrdm,
+			enum pwrdm_func_state func_pwrst,
+			u8 *pwrst, u8 *logic_pwrst);
 
 extern struct pwrdm_ops omap2_pwrdm_operations;
 extern struct pwrdm_ops omap3_pwrdm_operations;
diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
index 0f0a9f1..79c1293 100644
--- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
@@ -26,6 +26,7 @@
 
 
 /* Common functions across OMAP2 and OMAP3 */
+
 static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 {
 	omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
@@ -210,6 +211,8 @@ static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
 }
 
 struct pwrdm_ops omap2_pwrdm_operations = {
+	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
 	.pwrdm_read_pwrst	= omap2_pwrdm_read_pwrst,
@@ -222,6 +225,8 @@ struct pwrdm_ops omap2_pwrdm_operations = {
 };
 
 struct pwrdm_ops omap3_pwrdm_operations = {
+	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap2_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap2_pwrdm_read_next_pwrst,
 	.pwrdm_read_pwrst	= omap2_pwrdm_read_pwrst,
diff --git a/arch/arm/mach-omap2/powerdomain4xxx_5xxx.c b/arch/arm/mach-omap2/powerdomain4xxx_5xxx.c
index e1e7d44..ad32f70 100644
--- a/arch/arm/mach-omap2/powerdomain4xxx_5xxx.c
+++ b/arch/arm/mach-omap2/powerdomain4xxx_5xxx.c
@@ -229,6 +229,8 @@ static int omap5_pwrdm_disable_force_off(struct powerdomain *pwrdm)
 
 
 struct pwrdm_ops omap4_pwrdm_operations = {
+	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap4_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap4_pwrdm_read_next_pwrst,
 	.pwrdm_read_pwrst	= omap4_pwrdm_read_pwrst,
@@ -246,6 +248,8 @@ struct pwrdm_ops omap4_pwrdm_operations = {
 };
 
 struct pwrdm_ops omap5_pwrdm_operations = {
+	.pwrdm_func_to_pwrst	= omap2_pwrdm_func_to_pwrst,
+	.pwrdm_pwrst_to_func	= omap2_pwrdm_pwrst_to_func,
 	.pwrdm_set_next_pwrst	= omap4_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap4_pwrdm_read_next_pwrst,
 	.pwrdm_read_pwrst	= omap4_pwrdm_read_pwrst,
-- 
1.7.9.5

-- 
Regards,
Nishanth Menon

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
  2012-07-13  3:01     ` Menon, Nishanth
@ 2012-07-13  5:26       ` Rajendra Nayak
  -1 siblings, 0 replies; 44+ messages in thread
From: Rajendra Nayak @ 2012-07-13  5:26 UTC (permalink / raw)
  To: Menon, Nishanth
  Cc: Jean Pihet, linux-omap, paul, linux-arm-kernel, khilman, Jean Pihet

On Friday 13 July 2012 08:31 AM, Menon, Nishanth wrote:
> my Crib about the above apis are lack of logic power state handling:(
> which forces code like cpuidle to use different apis for logic
> power state and force them to use these apis just for pwrst.

Have you looked at an alternate approach that was proposed here..
https://patchwork.kernel.org/patch/1160431/


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
@ 2012-07-13  5:26       ` Rajendra Nayak
  0 siblings, 0 replies; 44+ messages in thread
From: Rajendra Nayak @ 2012-07-13  5:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 13 July 2012 08:31 AM, Menon, Nishanth wrote:
> my Crib about the above apis are lack of logic power state handling:(
> which forces code like cpuidle to use different apis for logic
> power state and force them to use these apis just for pwrst.

Have you looked at an alternate approach that was proposed here..
https://patchwork.kernel.org/patch/1160431/

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
  2012-07-13  5:26       ` Rajendra Nayak
@ 2012-07-13  5:29         ` Menon, Nishanth
  -1 siblings, 0 replies; 44+ messages in thread
From: Menon, Nishanth @ 2012-07-13  5:29 UTC (permalink / raw)
  To: Rajendra Nayak
  Cc: Jean Pihet, linux-omap, paul, linux-arm-kernel, khilman, Jean Pihet

On Fri, Jul 13, 2012 at 12:26 AM, Rajendra Nayak <rnayak@ti.com> wrote:
> On Friday 13 July 2012 08:31 AM, Menon, Nishanth wrote:
>>
>> my Crib about the above apis are lack of logic power state handling:(
>> which forces code like cpuidle to use different apis for logic
>> power state and force them to use these apis just for pwrst.
>
>
> Have you looked at an alternate approach that was proposed here..
> https://patchwork.kernel.org/patch/1160431/
>
Santosh pointed me to the thread offline. This is indeed a much better
approach IMHO than having 3 conflicting options inside powerdomain
framework.

Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
@ 2012-07-13  5:29         ` Menon, Nishanth
  0 siblings, 0 replies; 44+ messages in thread
From: Menon, Nishanth @ 2012-07-13  5:29 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jul 13, 2012 at 12:26 AM, Rajendra Nayak <rnayak@ti.com> wrote:
> On Friday 13 July 2012 08:31 AM, Menon, Nishanth wrote:
>>
>> my Crib about the above apis are lack of logic power state handling:(
>> which forces code like cpuidle to use different apis for logic
>> power state and force them to use these apis just for pwrst.
>
>
> Have you looked at an alternate approach that was proposed here..
> https://patchwork.kernel.org/patch/1160431/
>
Santosh pointed me to the thread offline. This is indeed a much better
approach IMHO than having 3 conflicting options inside powerdomain
framework.

Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
  2012-07-13  3:01     ` Menon, Nishanth
@ 2012-07-13  7:07       ` Jean Pihet
  -1 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-07-13  7:07 UTC (permalink / raw)
  To: Menon, Nishanth, Paul Walmsley
  Cc: linux-omap, linux-arm-kernel, khilman, Jean Pihet

Hi Nishant,

On Fri, Jul 13, 2012 at 5:01 AM, Menon, Nishanth <nm@ti.com> wrote:
> On Thu, Jun 14, 2012 at 9:53 AM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
> [..]
>> --- a/arch/arm/mach-omap2/powerdomain-common.c
>> +++ b/arch/arm/mach-omap2/powerdomain-common.c
>> @@ -108,3 +108,74 @@ u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank)
>>         return 0;
>>  }
>>
>> +/**
>> + * omap2_pwrdm_func_to_pwrst - Convert functional (i.e. logical) to
>> + * internal (i.e. registers) values for the power domains states.
>> + * @struct powerdomain * to convert the values for
>> + * @func_pwrst: functional power state
>> + *
>> + * Returns the internal power state value for the power domain, or
>> + * -EINVAL in case of invalid parameters passed in.
>> + */
>> +int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
>
> Unless we handle logicpwst and pwst here, it makes it hard for non
> arch/arm/mach-omap2/powerdomain* files to use this properly.
The logic and mem states support is coming in another patch in the
series. I think I should merge the patches together since I got the
same remarks a few times already

>
>> +{
>> +       int ret;
>> +
>> +       switch (func_pwrst) {
>> +       case PWRDM_FUNC_PWRST_ON:
>> +               ret = PWRDM_POWER_ON;
>> +               break;
>> +       case PWRDM_FUNC_PWRST_INACTIVE:
>> +               ret = PWRDM_POWER_INACTIVE;
>> +               break;
>> +       case PWRDM_FUNC_PWRST_CSWR:
>> +       case PWRDM_FUNC_PWRST_OSWR:
>> +               ret = PWRDM_POWER_RET;
>
> logic power state?
>
>> +               break;
>> +       case PWRDM_FUNC_PWRST_OFF:
>> +               ret = PWRDM_POWER_OFF;
>> +               break;
>> +       default:
>> +               ret = -EINVAL;
>> +       }
>> +
>> +       return ret;
>> +}
>> +
>> +/**
>> + * omap2_pwrdm_pwrst_to_func - Convert internal (i.e. registers) to
>> + * functional (i.e. logical) values for the power domains states.
>> + * @struct powerdomain * to convert the values for
>> + * @pwrst: internal power state
>> + *
>> + * Returns the functional power state value for the power domain, or
>> + * -EINVAL in case of invalid parameters passed in.
>> + */
>> +int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
> Same here as well..
>> +{
>> +       int ret;
>> +
>> +       switch (pwrst) {
>> +       case PWRDM_POWER_ON:
>> +               ret = PWRDM_FUNC_PWRST_ON;
>> +               break;
>> +       case PWRDM_POWER_INACTIVE:
>> +               ret = PWRDM_FUNC_PWRST_INACTIVE;
>> +               break;
>> +       case PWRDM_POWER_RET:
>> +               /*
>> +                * XXX warning: return OSWR in case of pd in RET and
>> +                * logic in OFF
>> +                */
> We need to be able to pass in logic pwst to be able to make that determination.
>
>> +               ret = PWRDM_FUNC_PWRST_CSWR;
>> +               break;
>> +       case PWRDM_POWER_OFF:
>> +               ret = PWRDM_FUNC_PWRST_OFF;
>> +               break;
>> +       default:
>> +               ret = -EINVAL;
>> +       }
>> +
>> +       return ret;
>> +}
>> +
>> diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
>> index 1641e72..e79b5ae 100644
>> --- a/arch/arm/mach-omap2/powerdomain.c
>> +++ b/arch/arm/mach-omap2/powerdomain.c
>> @@ -466,6 +466,135 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
>>  }
>>
>>  /**
>> + * pwrdm_func_to_pwrst - get the internal (i.e. registers) value mapped
>> + * to the functional state
>> + * @pwrdm: struct powerdomain * to query
>> + * @func_pwrst: functional power state
>> + *
>> + * Convert the functional power state to the platform specific power
>> + * domain state value.
>> + * Returns the internal power domain state value or -EINVAL in case
>> + * of invalid parameters passed in.
>> + */
>> +int pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
> should take enum pwrdm_func_state func_pwrst
Ok

>
>> +{
>> +       int ret = func_pwrst;
>> +
>> +       if ((!pwrdm) || (func_pwrst >= PWRDM_MAX_FUNC_PWRSTS))
>> +               return -EINVAL;
>> +
>> +       if (arch_pwrdm && arch_pwrdm->pwrdm_func_to_pwrst)
>> +               ret = arch_pwrdm->pwrdm_func_to_pwrst(pwrdm, func_pwrst);
>
> Should we not return an error if the function pointer is not available
> for the arch?
> on platforms without func_pwrst pointer converter routing hooked on,
> we return func_pwrst back to caller, which expects pwrst!
This is what the code does, cf. the first line of the function 'int
ret = func_pwrst;'. Is that what you mean?

>
>> +
>> +       pr_debug("powerdomain: convert func %0x to pwrst %0x for %s\n",
>> +                func_pwrst, ret, pwrdm->name);
>> +
>> +       return ret;
>> +}
>> +
>> +/**
>> + * pwrdm_pwrst_to_func - get the functional (i.e. logical) value mapped
>> + * to the internal state
>> + * @pwrdm: struct powerdomain * to query
>> + * @pwrst: internal power state
>> + *
>> + * Convert the internal power state to the power domain functional value.
>> + * Returns the functional power domain state value or -EINVAL in case
>> + * of invalid parameters passed in.
>> + */
>> +int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
> should return enum pwrdm_func_state
Ok

>
>> +{
>> +       int ret = pwrst;
>> +
>> +       if ((!pwrdm) || (pwrst >= PWRDM_MAX_PWRSTS))
>> +               return -EINVAL;
>> +
>> +       pr_debug("powerdomain: convert %0x pwrst to func for %s\n",
>> +                pwrst, pwrdm->name);
>> +
>> +       if (arch_pwrdm && arch_pwrdm->pwrdm_pwrst_to_func)
>> +               ret = arch_pwrdm->pwrdm_pwrst_to_func(pwrdm, pwrst);
>
> same in reverse here.
>
>> +
>> +       return ret;
>> +}
>> +
>> +/* Types of sleep_switch used in omap_set_pwrdm_state */
>> +#define FORCEWAKEUP_SWITCH     0
>> +#define LOWPOWERSTATE_SWITCH   1
>> +
>> +/**
>> + * omap_set_pwrdm_state - program next powerdomain power state
>> + * @pwrdm: struct powerdomain * to set
>> + * @func_pwrst: power domain functional state, one of the PWRDM_FUNC_* macros
>> + *
>> + * This programs the pwrdm next functional state, sets the dependencies
>> + * and waits for the state to be applied.
>> + */
>> +int omap_set_pwrdm_state(struct powerdomain *pwrdm,
>> +                        enum pwrdm_func_state func_pwrst)
>> +{
>> +       u8 curr_pwrst, next_pwrst;
>> +       int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
>> +       int sleep_switch = -1, ret = 0, hwsup = 0;
>> +
>> +       if (!pwrdm || IS_ERR(pwrdm) || (pwrst < 0)) {
>> +               pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
>> +                        __func__, pwrdm, func_pwrst);
>> +               return -EINVAL;
>> +       }
>> +
>> +       pr_debug("%s: set func_pwrst %0x to pwrdm %s\n",
>> +                __func__, func_pwrst, pwrdm->name);
>> +
>> +       mutex_lock(&pwrdm->lock);
> This should be  a spinlock (previous patch i believe) - hurts cpuidle otherwise.
Ok that had been reported by Ambresh. I have a fix ready for that.

>
>> +
>> +       while (!(pwrdm->pwrsts & (1 << pwrst))) {
>> +               if (pwrst == PWRDM_POWER_OFF)
>> +                       goto out;
>> +               pwrst--;
>> +       }
>> +
>
> if we like to handle a single API for OSWR and CSWR, then it needs to
> handle logic power state as well here.
>
>> +       next_pwrst = pwrdm_read_next_pwrst(pwrdm);
>> +       if (next_pwrst == pwrst)
>> +               goto out;
>> +
>> +       curr_pwrst = pwrdm_read_pwrst(pwrdm);
>> +       if (curr_pwrst < PWRDM_POWER_ON) {
>> +               if ((curr_pwrst > pwrst) &&
>> +                       (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
>> +                       sleep_switch = LOWPOWERSTATE_SWITCH;
>> +               } else {
>> +                       hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
>> +                       clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
>> +                       sleep_switch = FORCEWAKEUP_SWITCH;
>> +               }
>> +       }
>> +
>> +       ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
>> +       if (ret)
>> +               pr_err("%s: unable to set power state of powerdomain: %s\n",
>> +                      __func__, pwrdm->name);
>> +
>> +       switch (sleep_switch) {
>> +       case FORCEWAKEUP_SWITCH:
>> +               if (hwsup)
>> +                       clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
>> +               else
>> +                       clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
>> +               break;
>> +       case LOWPOWERSTATE_SWITCH:
>> +               pwrdm_set_lowpwrstchange(pwrdm);
>> +               pwrdm_wait_transition(pwrdm);
>> +               pwrdm_state_switch(pwrdm);
>> +               break;
>> +       }
>> +
>> +out:
>> +       mutex_unlock(&pwrdm->lock);
>> +       return ret;
>> +}
>> +
>> +/**
>>   * pwrdm_set_next_pwrst - set next powerdomain power state
>>   * @pwrdm: struct powerdomain * to set
>>   * @pwrst: one of the PWRDM_POWER_* macros
>> @@ -522,6 +651,21 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
>>  }
>>
>>  /**
>> + * pwrdm_read_next_func_pwrst - get next powerdomain functional power state
>> + * @pwrdm: struct powerdomain * to get power state
>> + *
>> + * Return the powerdomain @pwrdm's next functional power state.
>> + * Returns -EINVAL if the powerdomain pointer is null or returns
>> + * the next power state upon success.
>> + */
>> +int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm)
> should return enum pwrdm_func_state
>> +{
>> +       int ret = pwrdm_read_next_pwrst(pwrdm);
>> +
>> +       return pwrdm_pwrst_to_func(pwrdm, ret);
>> +}
>> +
>> +/**
>>   * pwrdm_read_pwrst - get current powerdomain power state
>>   * @pwrdm: struct powerdomain * to get power state
>>   *
>> @@ -543,6 +687,21 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm)
>>  }
>>
>>  /**
>> + * pwrdm_read_func_pwrst - get current powerdomain functional power state
>> + * @pwrdm: struct powerdomain * to get power state
>> + *
>> + * Return the powerdomain @pwrdm's current functional power state.
>> + * Returns -EINVAL if the powerdomain pointer is null or returns
>> + * the current power state upon success.
>> + */
>> +int pwrdm_read_func_pwrst(struct powerdomain *pwrdm)
> should return enum pwrdm_func_state
>> +{
>> +       int ret = pwrdm_read_pwrst(pwrdm);
>> +
>> +       return pwrdm_pwrst_to_func(pwrdm, ret);
>> +}
>
> my Crib about the above apis are lack of logic power state handling :(
> which forces code like cpuidle to use different apis for logic
> power state and force them to use these apis just for pwrst.
Please look at the rest of the series.

>> +
>> +/**
>>   * pwrdm_read_prev_pwrst - get previous powerdomain power state
>>   * @pwrdm: struct powerdomain * to get previous power state
>>   *
>> @@ -564,6 +723,21 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
>>  }
>>
>>  /**
>> + * pwrdm_read_prev_func_pwrst - get previous powerdomain functional power state
>> + * @pwrdm: struct powerdomain * to get previous power state
>> + *
>> + * Return the powerdomain @pwrdm's previous functional power state.
>> + * Returns -EINVAL if the powerdomain pointer is null or returns the
>> + * previous power state upon success.
>> + */
>> +int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm)
> should return enum pwrdm_func_state
>> +{
>> +       int ret = pwrdm_read_prev_pwrst(pwrdm);
>> +
>> +       return pwrdm_pwrst_to_func(pwrdm, ret);
>> +}
> again here.
>
>> +
>> +/**
>>   * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
>>   * @pwrdm: struct powerdomain * to set
>>   * @pwrst: one of the PWRDM_POWER_* macros
>> diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
>> index bab84fc..0404f9f 100644
>> --- a/arch/arm/mach-omap2/powerdomain.h
>> +++ b/arch/arm/mach-omap2/powerdomain.h
>> @@ -9,9 +9,6 @@
>>   * This program is free software; you can redistribute it and/or modify
>>   * it under the terms of the GNU General Public License version 2 as
>>   * published by the Free Software Foundation.
>> - *
>> - * XXX This should be moved to the mach-omap2/ directory at the earliest
>> - * opportunity.
>>   */
>>
>>  #ifndef __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H
>> @@ -26,7 +23,51 @@
>>
>>  #include "voltage.h"
>>
>> -/* Powerdomain basic power states */
>> +/***************************************************************
>> + * External API
>> + ***************************************************************/
>> +
>> +/* Powerdomain functional power states, used by the external API functions */
>> +enum pwrdm_func_state {
>> +       PWRDM_FUNC_PWRST_OFF            = 0x0,
>> +       PWRDM_FUNC_PWRST_OSWR,
>> +       PWRDM_FUNC_PWRST_CSWR,
>> +       PWRDM_FUNC_PWRST_INACTIVE,
>> +       PWRDM_FUNC_PWRST_ON,
>> +       PWRDM_MAX_FUNC_PWRSTS           /* Last value, used as the max value */
>> +};
>> +
>> +struct clockdomain;
>> +struct powerdomain;
>> +
>> +struct powerdomain *pwrdm_lookup(const char *name);
>> +
>> +int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
>> +                       void *user);
>> +int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
>> +                       void *user);
>> +
>> +struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
>> +
>> +int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
>> +
>> +int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm);
>> +int pwrdm_read_func_pwrst(struct powerdomain *pwrdm);
>> +int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm);
>> +extern int omap_set_pwrdm_state(struct powerdomain *pwrdm,
>> +                               enum pwrdm_func_state func_pwrst);
>> +
>> +extern void omap242x_powerdomains_init(void);
>> +extern void omap243x_powerdomains_init(void);
>> +extern void omap3xxx_powerdomains_init(void);
>> +extern void omap44xx_powerdomains_init(void);
>> +
>> +
>
> We should split the following out to a separate header which is not to
> be used by anyone else other than powerdomain*.[ch]
>
>> +/***************************************************************
>> + * Internal code, only used in powerdomain*.[ch]
>> + ***************************************************************/
>> +
>> +/* Powerdomain internal power states, internal use only */
>>  #define PWRDM_POWER_OFF                0x0
>>  #define PWRDM_POWER_RET                0x1
>>  #define PWRDM_POWER_INACTIVE   0x2
>> @@ -45,7 +86,6 @@
>>  #define PWRSTS_RET_ON          (PWRSTS_RET | PWRSTS_ON)
>>  #define PWRSTS_OFF_RET_ON      (PWRSTS_OFF_RET | PWRSTS_ON)
>>
>> -
>>  /* Powerdomain flags */
>>  #define PWRDM_HAS_HDWR_SAR     (1 << 0) /* hardware save-and-restore support */
>>  #define PWRDM_HAS_MPU_QUIRK    (1 << 1) /* MPU pwr domain has MEM bank 0 bits
>> @@ -74,9 +114,6 @@
>>  /* XXX A completely arbitrary number. What is reasonable here? */
>>  #define PWRDM_TRANSITION_BAILOUT 100000
>>
>> -struct clockdomain;
>> -struct powerdomain;
>> -
>>  /**
>>   * struct powerdomain - OMAP powerdomain
>>   * @name: Powerdomain name
>> @@ -130,6 +167,10 @@ struct powerdomain {
>>
>>  /**
>>   * struct pwrdm_ops - Arch specific function implementations
>> + * @pwrdm_func_to_pwrst: Convert the pd functional power state to
>> + *  the internal state
>> + * @pwrdm_pwrst_to_func: Convert the pd internal power state to
>> + *  the functional state
>>   * @pwrdm_set_next_pwrst: Set the target power state for a pd
>>   * @pwrdm_read_next_pwrst: Read the target power state set for a pd
>>   * @pwrdm_read_pwrst: Read the current power state of a pd
>> @@ -150,6 +191,8 @@ struct powerdomain {
>>   * @pwrdm_wait_transition: Wait for a pd state transition to complete
>>   */
>>  struct pwrdm_ops {
>> +       int     (*pwrdm_func_to_pwrst)(struct powerdomain *pwrdm, u8 func_pwrst);
> should take in enum pwrdm_func_state
>> +       int     (*pwrdm_pwrst_to_func)(struct powerdomain *pwrdm, u8 func_pwrst);
> should return enum pwrdm_func_state
>
>>         int     (*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst);
>>         int     (*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm);
>>         int     (*pwrdm_read_pwrst)(struct powerdomain *pwrdm);
>> @@ -174,21 +217,11 @@ int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
>>  int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list);
>>  int pwrdm_complete_init(void);
>>
>> -struct powerdomain *pwrdm_lookup(const char *name);
>> -
>> -int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
>> -                       void *user);
>> -int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
>> -                       void *user);
>> -
>>  int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
>>  int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
>>  int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
>>                          int (*fn)(struct powerdomain *pwrdm,
>>                                    struct clockdomain *clkdm));
>> -struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
>> -
>> -int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
>>
>>  int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
>>  int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
>> @@ -196,6 +229,9 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm);
>>  int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
>>  int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
>>
>> +int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
>> +int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst);
>> +
>>  int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
>>  int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
>>  int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
>> @@ -220,11 +256,6 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
>>  int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
>>  bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
>>
>> -extern void omap242x_powerdomains_init(void);
>> -extern void omap243x_powerdomains_init(void);
>> -extern void omap3xxx_powerdomains_init(void);
>> -extern void omap44xx_powerdomains_init(void);
>> -
>>  extern struct pwrdm_ops omap2_pwrdm_operations;
>>  extern struct pwrdm_ops omap3_pwrdm_operations;
>>  extern struct pwrdm_ops omap4_pwrdm_operations;
>> diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
>> index 0f0a9f1..79c1293 100644
>> --- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
>> +++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
>> @@ -26,6 +26,7 @@
>>
>>
>>  /* Common functions across OMAP2 and OMAP3 */
>> +
>>  static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
>>  {
>>         omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
>> @@ -210,6 +211,8 @@ static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
>>  }
>>
>>  struct pwrdm_ops omap2_pwrdm_operations = {
>> +       .pwrdm_func_to_pwrst    = omap2_pwrdm_func_to_pwrst,
>> +       .pwrdm_pwrst_to_func    = omap2_pwrdm_pwrst_to_func,
>>         .pwrdm_set_next_pwrst   = omap2_pwrdm_set_next_pwrst,
>>         .pwrdm_read_next_pwrst  = omap2_pwrdm_read_next_pwrst,
>>         .pwrdm_read_pwrst       = omap2_pwrdm_read_pwrst,
>> @@ -222,6 +225,8 @@ struct pwrdm_ops omap2_pwrdm_operations = {
>>  };
>>
>>  struct pwrdm_ops omap3_pwrdm_operations = {
>> +       .pwrdm_func_to_pwrst    = omap2_pwrdm_func_to_pwrst,
>> +       .pwrdm_pwrst_to_func    = omap2_pwrdm_pwrst_to_func,
>>         .pwrdm_set_next_pwrst   = omap2_pwrdm_set_next_pwrst,
>>         .pwrdm_read_next_pwrst  = omap2_pwrdm_read_next_pwrst,
>>         .pwrdm_read_pwrst       = omap2_pwrdm_read_pwrst,
>> diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
>> index 601325b..538b528 100644
>> --- a/arch/arm/mach-omap2/powerdomain44xx.c
>> +++ b/arch/arm/mach-omap2/powerdomain44xx.c
>> @@ -209,6 +209,8 @@ static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
>>  }
>>
>>  struct pwrdm_ops omap4_pwrdm_operations = {
>> +       .pwrdm_func_to_pwrst    = omap2_pwrdm_func_to_pwrst,
>> +       .pwrdm_pwrst_to_func    = omap2_pwrdm_pwrst_to_func,
>>         .pwrdm_set_next_pwrst   = omap4_pwrdm_set_next_pwrst,
>>         .pwrdm_read_next_pwrst  = omap4_pwrdm_read_next_pwrst,
>>         .pwrdm_read_pwrst       = omap4_pwrdm_read_pwrst,
>
> otherwise, this is a nice concept
Great! Thanks for the review.

> --
> Regards,
> Nishanth Menon

Regards,
Jean

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
@ 2012-07-13  7:07       ` Jean Pihet
  0 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-07-13  7:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Nishant,

On Fri, Jul 13, 2012 at 5:01 AM, Menon, Nishanth <nm@ti.com> wrote:
> On Thu, Jun 14, 2012 at 9:53 AM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
> [..]
>> --- a/arch/arm/mach-omap2/powerdomain-common.c
>> +++ b/arch/arm/mach-omap2/powerdomain-common.c
>> @@ -108,3 +108,74 @@ u32 omap2_pwrdm_get_mem_bank_stst_mask(u8 bank)
>>         return 0;
>>  }
>>
>> +/**
>> + * omap2_pwrdm_func_to_pwrst - Convert functional (i.e. logical) to
>> + * internal (i.e. registers) values for the power domains states.
>> + * @struct powerdomain * to convert the values for
>> + * @func_pwrst: functional power state
>> + *
>> + * Returns the internal power state value for the power domain, or
>> + * -EINVAL in case of invalid parameters passed in.
>> + */
>> +int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
>
> Unless we handle logicpwst and pwst here, it makes it hard for non
> arch/arm/mach-omap2/powerdomain* files to use this properly.
The logic and mem states support is coming in another patch in the
series. I think I should merge the patches together since I got the
same remarks a few times already

>
>> +{
>> +       int ret;
>> +
>> +       switch (func_pwrst) {
>> +       case PWRDM_FUNC_PWRST_ON:
>> +               ret = PWRDM_POWER_ON;
>> +               break;
>> +       case PWRDM_FUNC_PWRST_INACTIVE:
>> +               ret = PWRDM_POWER_INACTIVE;
>> +               break;
>> +       case PWRDM_FUNC_PWRST_CSWR:
>> +       case PWRDM_FUNC_PWRST_OSWR:
>> +               ret = PWRDM_POWER_RET;
>
> logic power state?
>
>> +               break;
>> +       case PWRDM_FUNC_PWRST_OFF:
>> +               ret = PWRDM_POWER_OFF;
>> +               break;
>> +       default:
>> +               ret = -EINVAL;
>> +       }
>> +
>> +       return ret;
>> +}
>> +
>> +/**
>> + * omap2_pwrdm_pwrst_to_func - Convert internal (i.e. registers) to
>> + * functional (i.e. logical) values for the power domains states.
>> + * @struct powerdomain * to convert the values for
>> + * @pwrst: internal power state
>> + *
>> + * Returns the functional power state value for the power domain, or
>> + * -EINVAL in case of invalid parameters passed in.
>> + */
>> +int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
> Same here as well..
>> +{
>> +       int ret;
>> +
>> +       switch (pwrst) {
>> +       case PWRDM_POWER_ON:
>> +               ret = PWRDM_FUNC_PWRST_ON;
>> +               break;
>> +       case PWRDM_POWER_INACTIVE:
>> +               ret = PWRDM_FUNC_PWRST_INACTIVE;
>> +               break;
>> +       case PWRDM_POWER_RET:
>> +               /*
>> +                * XXX warning: return OSWR in case of pd in RET and
>> +                * logic in OFF
>> +                */
> We need to be able to pass in logic pwst to be able to make that determination.
>
>> +               ret = PWRDM_FUNC_PWRST_CSWR;
>> +               break;
>> +       case PWRDM_POWER_OFF:
>> +               ret = PWRDM_FUNC_PWRST_OFF;
>> +               break;
>> +       default:
>> +               ret = -EINVAL;
>> +       }
>> +
>> +       return ret;
>> +}
>> +
>> diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
>> index 1641e72..e79b5ae 100644
>> --- a/arch/arm/mach-omap2/powerdomain.c
>> +++ b/arch/arm/mach-omap2/powerdomain.c
>> @@ -466,6 +466,135 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
>>  }
>>
>>  /**
>> + * pwrdm_func_to_pwrst - get the internal (i.e. registers) value mapped
>> + * to the functional state
>> + * @pwrdm: struct powerdomain * to query
>> + * @func_pwrst: functional power state
>> + *
>> + * Convert the functional power state to the platform specific power
>> + * domain state value.
>> + * Returns the internal power domain state value or -EINVAL in case
>> + * of invalid parameters passed in.
>> + */
>> +int pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst)
> should take enum pwrdm_func_state func_pwrst
Ok

>
>> +{
>> +       int ret = func_pwrst;
>> +
>> +       if ((!pwrdm) || (func_pwrst >= PWRDM_MAX_FUNC_PWRSTS))
>> +               return -EINVAL;
>> +
>> +       if (arch_pwrdm && arch_pwrdm->pwrdm_func_to_pwrst)
>> +               ret = arch_pwrdm->pwrdm_func_to_pwrst(pwrdm, func_pwrst);
>
> Should we not return an error if the function pointer is not available
> for the arch?
> on platforms without func_pwrst pointer converter routing hooked on,
> we return func_pwrst back to caller, which expects pwrst!
This is what the code does, cf. the first line of the function 'int
ret = func_pwrst;'. Is that what you mean?

>
>> +
>> +       pr_debug("powerdomain: convert func %0x to pwrst %0x for %s\n",
>> +                func_pwrst, ret, pwrdm->name);
>> +
>> +       return ret;
>> +}
>> +
>> +/**
>> + * pwrdm_pwrst_to_func - get the functional (i.e. logical) value mapped
>> + * to the internal state
>> + * @pwrdm: struct powerdomain * to query
>> + * @pwrst: internal power state
>> + *
>> + * Convert the internal power state to the power domain functional value.
>> + * Returns the functional power domain state value or -EINVAL in case
>> + * of invalid parameters passed in.
>> + */
>> +int pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst)
> should return enum pwrdm_func_state
Ok

>
>> +{
>> +       int ret = pwrst;
>> +
>> +       if ((!pwrdm) || (pwrst >= PWRDM_MAX_PWRSTS))
>> +               return -EINVAL;
>> +
>> +       pr_debug("powerdomain: convert %0x pwrst to func for %s\n",
>> +                pwrst, pwrdm->name);
>> +
>> +       if (arch_pwrdm && arch_pwrdm->pwrdm_pwrst_to_func)
>> +               ret = arch_pwrdm->pwrdm_pwrst_to_func(pwrdm, pwrst);
>
> same in reverse here.
>
>> +
>> +       return ret;
>> +}
>> +
>> +/* Types of sleep_switch used in omap_set_pwrdm_state */
>> +#define FORCEWAKEUP_SWITCH     0
>> +#define LOWPOWERSTATE_SWITCH   1
>> +
>> +/**
>> + * omap_set_pwrdm_state - program next powerdomain power state
>> + * @pwrdm: struct powerdomain * to set
>> + * @func_pwrst: power domain functional state, one of the PWRDM_FUNC_* macros
>> + *
>> + * This programs the pwrdm next functional state, sets the dependencies
>> + * and waits for the state to be applied.
>> + */
>> +int omap_set_pwrdm_state(struct powerdomain *pwrdm,
>> +                        enum pwrdm_func_state func_pwrst)
>> +{
>> +       u8 curr_pwrst, next_pwrst;
>> +       int pwrst = pwrdm_func_to_pwrst(pwrdm, func_pwrst);
>> +       int sleep_switch = -1, ret = 0, hwsup = 0;
>> +
>> +       if (!pwrdm || IS_ERR(pwrdm) || (pwrst < 0)) {
>> +               pr_debug("%s: invalid params: pwrdm=%p, func_pwrst=%0x\n",
>> +                        __func__, pwrdm, func_pwrst);
>> +               return -EINVAL;
>> +       }
>> +
>> +       pr_debug("%s: set func_pwrst %0x to pwrdm %s\n",
>> +                __func__, func_pwrst, pwrdm->name);
>> +
>> +       mutex_lock(&pwrdm->lock);
> This should be  a spinlock (previous patch i believe) - hurts cpuidle otherwise.
Ok that had been reported by Ambresh. I have a fix ready for that.

>
>> +
>> +       while (!(pwrdm->pwrsts & (1 << pwrst))) {
>> +               if (pwrst == PWRDM_POWER_OFF)
>> +                       goto out;
>> +               pwrst--;
>> +       }
>> +
>
> if we like to handle a single API for OSWR and CSWR, then it needs to
> handle logic power state as well here.
>
>> +       next_pwrst = pwrdm_read_next_pwrst(pwrdm);
>> +       if (next_pwrst == pwrst)
>> +               goto out;
>> +
>> +       curr_pwrst = pwrdm_read_pwrst(pwrdm);
>> +       if (curr_pwrst < PWRDM_POWER_ON) {
>> +               if ((curr_pwrst > pwrst) &&
>> +                       (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
>> +                       sleep_switch = LOWPOWERSTATE_SWITCH;
>> +               } else {
>> +                       hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
>> +                       clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
>> +                       sleep_switch = FORCEWAKEUP_SWITCH;
>> +               }
>> +       }
>> +
>> +       ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
>> +       if (ret)
>> +               pr_err("%s: unable to set power state of powerdomain: %s\n",
>> +                      __func__, pwrdm->name);
>> +
>> +       switch (sleep_switch) {
>> +       case FORCEWAKEUP_SWITCH:
>> +               if (hwsup)
>> +                       clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
>> +               else
>> +                       clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
>> +               break;
>> +       case LOWPOWERSTATE_SWITCH:
>> +               pwrdm_set_lowpwrstchange(pwrdm);
>> +               pwrdm_wait_transition(pwrdm);
>> +               pwrdm_state_switch(pwrdm);
>> +               break;
>> +       }
>> +
>> +out:
>> +       mutex_unlock(&pwrdm->lock);
>> +       return ret;
>> +}
>> +
>> +/**
>>   * pwrdm_set_next_pwrst - set next powerdomain power state
>>   * @pwrdm: struct powerdomain * to set
>>   * @pwrst: one of the PWRDM_POWER_* macros
>> @@ -522,6 +651,21 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
>>  }
>>
>>  /**
>> + * pwrdm_read_next_func_pwrst - get next powerdomain functional power state
>> + * @pwrdm: struct powerdomain * to get power state
>> + *
>> + * Return the powerdomain @pwrdm's next functional power state.
>> + * Returns -EINVAL if the powerdomain pointer is null or returns
>> + * the next power state upon success.
>> + */
>> +int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm)
> should return enum pwrdm_func_state
>> +{
>> +       int ret = pwrdm_read_next_pwrst(pwrdm);
>> +
>> +       return pwrdm_pwrst_to_func(pwrdm, ret);
>> +}
>> +
>> +/**
>>   * pwrdm_read_pwrst - get current powerdomain power state
>>   * @pwrdm: struct powerdomain * to get power state
>>   *
>> @@ -543,6 +687,21 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm)
>>  }
>>
>>  /**
>> + * pwrdm_read_func_pwrst - get current powerdomain functional power state
>> + * @pwrdm: struct powerdomain * to get power state
>> + *
>> + * Return the powerdomain @pwrdm's current functional power state.
>> + * Returns -EINVAL if the powerdomain pointer is null or returns
>> + * the current power state upon success.
>> + */
>> +int pwrdm_read_func_pwrst(struct powerdomain *pwrdm)
> should return enum pwrdm_func_state
>> +{
>> +       int ret = pwrdm_read_pwrst(pwrdm);
>> +
>> +       return pwrdm_pwrst_to_func(pwrdm, ret);
>> +}
>
> my Crib about the above apis are lack of logic power state handling :(
> which forces code like cpuidle to use different apis for logic
> power state and force them to use these apis just for pwrst.
Please look at the rest of the series.

>> +
>> +/**
>>   * pwrdm_read_prev_pwrst - get previous powerdomain power state
>>   * @pwrdm: struct powerdomain * to get previous power state
>>   *
>> @@ -564,6 +723,21 @@ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
>>  }
>>
>>  /**
>> + * pwrdm_read_prev_func_pwrst - get previous powerdomain functional power state
>> + * @pwrdm: struct powerdomain * to get previous power state
>> + *
>> + * Return the powerdomain @pwrdm's previous functional power state.
>> + * Returns -EINVAL if the powerdomain pointer is null or returns the
>> + * previous power state upon success.
>> + */
>> +int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm)
> should return enum pwrdm_func_state
>> +{
>> +       int ret = pwrdm_read_prev_pwrst(pwrdm);
>> +
>> +       return pwrdm_pwrst_to_func(pwrdm, ret);
>> +}
> again here.
>
>> +
>> +/**
>>   * pwrdm_set_logic_retst - set powerdomain logic power state upon retention
>>   * @pwrdm: struct powerdomain * to set
>>   * @pwrst: one of the PWRDM_POWER_* macros
>> diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
>> index bab84fc..0404f9f 100644
>> --- a/arch/arm/mach-omap2/powerdomain.h
>> +++ b/arch/arm/mach-omap2/powerdomain.h
>> @@ -9,9 +9,6 @@
>>   * This program is free software; you can redistribute it and/or modify
>>   * it under the terms of the GNU General Public License version 2 as
>>   * published by the Free Software Foundation.
>> - *
>> - * XXX This should be moved to the mach-omap2/ directory at the earliest
>> - * opportunity.
>>   */
>>
>>  #ifndef __ARCH_ARM_MACH_OMAP2_POWERDOMAIN_H
>> @@ -26,7 +23,51 @@
>>
>>  #include "voltage.h"
>>
>> -/* Powerdomain basic power states */
>> +/***************************************************************
>> + * External API
>> + ***************************************************************/
>> +
>> +/* Powerdomain functional power states, used by the external API functions */
>> +enum pwrdm_func_state {
>> +       PWRDM_FUNC_PWRST_OFF            = 0x0,
>> +       PWRDM_FUNC_PWRST_OSWR,
>> +       PWRDM_FUNC_PWRST_CSWR,
>> +       PWRDM_FUNC_PWRST_INACTIVE,
>> +       PWRDM_FUNC_PWRST_ON,
>> +       PWRDM_MAX_FUNC_PWRSTS           /* Last value, used as the max value */
>> +};
>> +
>> +struct clockdomain;
>> +struct powerdomain;
>> +
>> +struct powerdomain *pwrdm_lookup(const char *name);
>> +
>> +int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
>> +                       void *user);
>> +int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
>> +                       void *user);
>> +
>> +struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
>> +
>> +int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
>> +
>> +int pwrdm_read_prev_func_pwrst(struct powerdomain *pwrdm);
>> +int pwrdm_read_func_pwrst(struct powerdomain *pwrdm);
>> +int pwrdm_read_next_func_pwrst(struct powerdomain *pwrdm);
>> +extern int omap_set_pwrdm_state(struct powerdomain *pwrdm,
>> +                               enum pwrdm_func_state func_pwrst);
>> +
>> +extern void omap242x_powerdomains_init(void);
>> +extern void omap243x_powerdomains_init(void);
>> +extern void omap3xxx_powerdomains_init(void);
>> +extern void omap44xx_powerdomains_init(void);
>> +
>> +
>
> We should split the following out to a separate header which is not to
> be used by anyone else other than powerdomain*.[ch]
>
>> +/***************************************************************
>> + * Internal code, only used in powerdomain*.[ch]
>> + ***************************************************************/
>> +
>> +/* Powerdomain internal power states, internal use only */
>>  #define PWRDM_POWER_OFF                0x0
>>  #define PWRDM_POWER_RET                0x1
>>  #define PWRDM_POWER_INACTIVE   0x2
>> @@ -45,7 +86,6 @@
>>  #define PWRSTS_RET_ON          (PWRSTS_RET | PWRSTS_ON)
>>  #define PWRSTS_OFF_RET_ON      (PWRSTS_OFF_RET | PWRSTS_ON)
>>
>> -
>>  /* Powerdomain flags */
>>  #define PWRDM_HAS_HDWR_SAR     (1 << 0) /* hardware save-and-restore support */
>>  #define PWRDM_HAS_MPU_QUIRK    (1 << 1) /* MPU pwr domain has MEM bank 0 bits
>> @@ -74,9 +114,6 @@
>>  /* XXX A completely arbitrary number. What is reasonable here? */
>>  #define PWRDM_TRANSITION_BAILOUT 100000
>>
>> -struct clockdomain;
>> -struct powerdomain;
>> -
>>  /**
>>   * struct powerdomain - OMAP powerdomain
>>   * @name: Powerdomain name
>> @@ -130,6 +167,10 @@ struct powerdomain {
>>
>>  /**
>>   * struct pwrdm_ops - Arch specific function implementations
>> + * @pwrdm_func_to_pwrst: Convert the pd functional power state to
>> + *  the internal state
>> + * @pwrdm_pwrst_to_func: Convert the pd internal power state to
>> + *  the functional state
>>   * @pwrdm_set_next_pwrst: Set the target power state for a pd
>>   * @pwrdm_read_next_pwrst: Read the target power state set for a pd
>>   * @pwrdm_read_pwrst: Read the current power state of a pd
>> @@ -150,6 +191,8 @@ struct powerdomain {
>>   * @pwrdm_wait_transition: Wait for a pd state transition to complete
>>   */
>>  struct pwrdm_ops {
>> +       int     (*pwrdm_func_to_pwrst)(struct powerdomain *pwrdm, u8 func_pwrst);
> should take in enum pwrdm_func_state
>> +       int     (*pwrdm_pwrst_to_func)(struct powerdomain *pwrdm, u8 func_pwrst);
> should return enum pwrdm_func_state
>
>>         int     (*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst);
>>         int     (*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm);
>>         int     (*pwrdm_read_pwrst)(struct powerdomain *pwrdm);
>> @@ -174,21 +217,11 @@ int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
>>  int pwrdm_register_pwrdms(struct powerdomain **pwrdm_list);
>>  int pwrdm_complete_init(void);
>>
>> -struct powerdomain *pwrdm_lookup(const char *name);
>> -
>> -int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
>> -                       void *user);
>> -int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
>> -                       void *user);
>> -
>>  int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
>>  int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
>>  int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
>>                          int (*fn)(struct powerdomain *pwrdm,
>>                                    struct clockdomain *clkdm));
>> -struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm);
>> -
>> -int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
>>
>>  int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
>>  int pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
>> @@ -196,6 +229,9 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm);
>>  int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
>>  int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
>>
>> +int omap2_pwrdm_func_to_pwrst(struct powerdomain *pwrdm, u8 func_pwrst);
>> +int omap2_pwrdm_pwrst_to_func(struct powerdomain *pwrdm, u8 pwrst);
>> +
>>  int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
>>  int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
>>  int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
>> @@ -220,11 +256,6 @@ int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
>>  int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
>>  bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
>>
>> -extern void omap242x_powerdomains_init(void);
>> -extern void omap243x_powerdomains_init(void);
>> -extern void omap3xxx_powerdomains_init(void);
>> -extern void omap44xx_powerdomains_init(void);
>> -
>>  extern struct pwrdm_ops omap2_pwrdm_operations;
>>  extern struct pwrdm_ops omap3_pwrdm_operations;
>>  extern struct pwrdm_ops omap4_pwrdm_operations;
>> diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
>> index 0f0a9f1..79c1293 100644
>> --- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
>> +++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
>> @@ -26,6 +26,7 @@
>>
>>
>>  /* Common functions across OMAP2 and OMAP3 */
>> +
>>  static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
>>  {
>>         omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
>> @@ -210,6 +211,8 @@ static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
>>  }
>>
>>  struct pwrdm_ops omap2_pwrdm_operations = {
>> +       .pwrdm_func_to_pwrst    = omap2_pwrdm_func_to_pwrst,
>> +       .pwrdm_pwrst_to_func    = omap2_pwrdm_pwrst_to_func,
>>         .pwrdm_set_next_pwrst   = omap2_pwrdm_set_next_pwrst,
>>         .pwrdm_read_next_pwrst  = omap2_pwrdm_read_next_pwrst,
>>         .pwrdm_read_pwrst       = omap2_pwrdm_read_pwrst,
>> @@ -222,6 +225,8 @@ struct pwrdm_ops omap2_pwrdm_operations = {
>>  };
>>
>>  struct pwrdm_ops omap3_pwrdm_operations = {
>> +       .pwrdm_func_to_pwrst    = omap2_pwrdm_func_to_pwrst,
>> +       .pwrdm_pwrst_to_func    = omap2_pwrdm_pwrst_to_func,
>>         .pwrdm_set_next_pwrst   = omap2_pwrdm_set_next_pwrst,
>>         .pwrdm_read_next_pwrst  = omap2_pwrdm_read_next_pwrst,
>>         .pwrdm_read_pwrst       = omap2_pwrdm_read_pwrst,
>> diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
>> index 601325b..538b528 100644
>> --- a/arch/arm/mach-omap2/powerdomain44xx.c
>> +++ b/arch/arm/mach-omap2/powerdomain44xx.c
>> @@ -209,6 +209,8 @@ static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
>>  }
>>
>>  struct pwrdm_ops omap4_pwrdm_operations = {
>> +       .pwrdm_func_to_pwrst    = omap2_pwrdm_func_to_pwrst,
>> +       .pwrdm_pwrst_to_func    = omap2_pwrdm_pwrst_to_func,
>>         .pwrdm_set_next_pwrst   = omap4_pwrdm_set_next_pwrst,
>>         .pwrdm_read_next_pwrst  = omap4_pwrdm_read_next_pwrst,
>>         .pwrdm_read_pwrst       = omap4_pwrdm_read_pwrst,
>
> otherwise, this is a nice concept
Great! Thanks for the review.

> --
> Regards,
> Nishanth Menon

Regards,
Jean

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
  2012-07-13  7:07       ` Jean Pihet
@ 2012-07-13  7:14         ` Menon, Nishanth
  -1 siblings, 0 replies; 44+ messages in thread
From: Menon, Nishanth @ 2012-07-13  7:14 UTC (permalink / raw)
  To: Jean Pihet
  Cc: Paul Walmsley, linux-omap, linux-arm-kernel, khilman, Jean Pihet

On Fri, Jul 13, 2012 at 2:07 AM, Jean Pihet <jean.pihet@newoldbits.com> wrote:

>> my Crib about the above apis are lack of logic power state handling :(
>> which forces code like cpuidle to use different apis for logic
>> power state and force them to use these apis just for pwrst.
> Please look at the rest of the series.

Thanks for doing these, but with
https://patchwork.kernel.org/patch/1160431/ in context, my comments on
this patch is redundant and i think we should go with Rajendra's patch
instead of this. I am currently dropping this patch in my internal
tree. Will comment further as i get to next set of patches in this
series.

Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
@ 2012-07-13  7:14         ` Menon, Nishanth
  0 siblings, 0 replies; 44+ messages in thread
From: Menon, Nishanth @ 2012-07-13  7:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jul 13, 2012 at 2:07 AM, Jean Pihet <jean.pihet@newoldbits.com> wrote:

>> my Crib about the above apis are lack of logic power state handling :(
>> which forces code like cpuidle to use different apis for logic
>> power state and force them to use these apis just for pwrst.
> Please look at the rest of the series.

Thanks for doing these, but with
https://patchwork.kernel.org/patch/1160431/ in context, my comments on
this patch is redundant and i think we should go with Rajendra's patch
instead of this. I am currently dropping this patch in my internal
tree. Will comment further as i get to next set of patches in this
series.

Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
  2012-07-13  5:29         ` Menon, Nishanth
@ 2012-07-13  7:18           ` Jean Pihet
  -1 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-07-13  7:18 UTC (permalink / raw)
  To: Menon, Nishanth
  Cc: Rajendra Nayak, linux-omap, paul, linux-arm-kernel, khilman, Jean Pihet

Hi!

On Fri, Jul 13, 2012 at 7:29 AM, Menon, Nishanth <nm@ti.com> wrote:
> On Fri, Jul 13, 2012 at 12:26 AM, Rajendra Nayak <rnayak@ti.com> wrote:
>> On Friday 13 July 2012 08:31 AM, Menon, Nishanth wrote:
>>>
>>> my Crib about the above apis are lack of logic power state handling:(
>>> which forces code like cpuidle to use different apis for logic
>>> power state and force them to use these apis just for pwrst.
>>
>>
>> Have you looked at an alternate approach that was proposed here..
>> https://patchwork.kernel.org/patch/1160431/
>>
> Santosh pointed me to the thread offline. This is indeed a much better
> approach IMHO than having 3 conflicting options inside powerdomain
> framework.
After looking at the code and having sent my comments, I like it ...
mainly because it is really similar to my proposal ;-p
Can you elaborate more on 'having 3 conflicting options inside
powerdomain framework'?

Here are the main differences in the implementation:
- the RFC code provides a _private header file, which forces the
external users (cpuidle, pmXXXX.c etc.),
- the RFC code still uses the same function names while my code
renames them to '*_func_*'. This makes the code look more complicated
than it really is.

> Regards,
> Nishanth Menon

We are having a discussion on the best way to have the feature in. More to come!

Thanks!
Jean

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
@ 2012-07-13  7:18           ` Jean Pihet
  0 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-07-13  7:18 UTC (permalink / raw)
  To: linux-arm-kernel

Hi!

On Fri, Jul 13, 2012 at 7:29 AM, Menon, Nishanth <nm@ti.com> wrote:
> On Fri, Jul 13, 2012 at 12:26 AM, Rajendra Nayak <rnayak@ti.com> wrote:
>> On Friday 13 July 2012 08:31 AM, Menon, Nishanth wrote:
>>>
>>> my Crib about the above apis are lack of logic power state handling:(
>>> which forces code like cpuidle to use different apis for logic
>>> power state and force them to use these apis just for pwrst.
>>
>>
>> Have you looked at an alternate approach that was proposed here..
>> https://patchwork.kernel.org/patch/1160431/
>>
> Santosh pointed me to the thread offline. This is indeed a much better
> approach IMHO than having 3 conflicting options inside powerdomain
> framework.
After looking at the code and having sent my comments, I like it ...
mainly because it is really similar to my proposal ;-p
Can you elaborate more on 'having 3 conflicting options inside
powerdomain framework'?

Here are the main differences in the implementation:
- the RFC code provides a _private header file, which forces the
external users (cpuidle, pmXXXX.c etc.),
- the RFC code still uses the same function names while my code
renames them to '*_func_*'. This makes the code look more complicated
than it really is.

> Regards,
> Nishanth Menon

We are having a discussion on the best way to have the feature in. More to come!

Thanks!
Jean

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
  2012-07-13  7:18           ` Jean Pihet
@ 2012-07-13  7:27             ` Menon, Nishanth
  -1 siblings, 0 replies; 44+ messages in thread
From: Menon, Nishanth @ 2012-07-13  7:27 UTC (permalink / raw)
  To: Jean Pihet
  Cc: Rajendra Nayak, linux-omap, paul, linux-arm-kernel, khilman, Jean Pihet

On Fri, Jul 13, 2012 at 2:18 AM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
[..]
>> Santosh pointed me to the thread offline. This is indeed a much better
>> approach IMHO than having 3 conflicting options inside powerdomain
>> framework.
> After looking at the code and having sent my comments, I like it ...
> mainly because it is really similar to my proposal ;-p
> Can you elaborate more on 'having 3 conflicting options inside
> powerdomain framework'?
Current code has:
a) PWRDM_POWER_XYZ -> describe power state
b) PWRSTS_XYZ ->meant to describe supported states for each pwrdm

this patch introduces:
a) PWRDM_POWER_XYZ -> describe power state (only for powerdomain*.[ch])
b) PWRSTS_XYZ ->meant to describe supported states for each pwrdm
c) PWRDM_FUNC_XYZ -> for files other than powerdomain*.[ch]

https://patchwork.kernel.org/patch/1160431/
maintains
a) PWRDM_POWER_XYZ -> describe power state
b) PWRSTS_XYZ ->meant to describe supported states for each pwrdm

i) reduces code churn
ii) supports logic pwr handling within existing framework
iii) no conflicting usage beyond known definition and usage. (though
personally, I;d like to see PWRSTS_XYZ dissappear into private
header..


> Here are the main differences in the implementation:
> - the RFC code provides a _private header file, which forces the
> external users (cpuidle, pmXXXX.c etc.),
That is one of the reasons I like it. I need to have a code which will
be maintained beyond the original code creators - reduced ability to
mess up the code by "not-well-informed" developers is paramount
importance for me.

> - the RFC code still uses the same function names while my code
> renames them to '*_func_*'. This makes the code look more complicated
> than it really is.

True. But, it paves the way to move all functions that is not intended
to be used beyond powerdomain files to a private power domain header -
which achieves the same objective without code churn.

Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states
@ 2012-07-13  7:27             ` Menon, Nishanth
  0 siblings, 0 replies; 44+ messages in thread
From: Menon, Nishanth @ 2012-07-13  7:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jul 13, 2012 at 2:18 AM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
[..]
>> Santosh pointed me to the thread offline. This is indeed a much better
>> approach IMHO than having 3 conflicting options inside powerdomain
>> framework.
> After looking at the code and having sent my comments, I like it ...
> mainly because it is really similar to my proposal ;-p
> Can you elaborate more on 'having 3 conflicting options inside
> powerdomain framework'?
Current code has:
a) PWRDM_POWER_XYZ -> describe power state
b) PWRSTS_XYZ ->meant to describe supported states for each pwrdm

this patch introduces:
a) PWRDM_POWER_XYZ -> describe power state (only for powerdomain*.[ch])
b) PWRSTS_XYZ ->meant to describe supported states for each pwrdm
c) PWRDM_FUNC_XYZ -> for files other than powerdomain*.[ch]

https://patchwork.kernel.org/patch/1160431/
maintains
a) PWRDM_POWER_XYZ -> describe power state
b) PWRSTS_XYZ ->meant to describe supported states for each pwrdm

i) reduces code churn
ii) supports logic pwr handling within existing framework
iii) no conflicting usage beyond known definition and usage. (though
personally, I;d like to see PWRSTS_XYZ dissappear into private
header..


> Here are the main differences in the implementation:
> - the RFC code provides a _private header file, which forces the
> external users (cpuidle, pmXXXX.c etc.),
That is one of the reasons I like it. I need to have a code which will
be maintained beyond the original code creators - reduced ability to
mess up the code by "not-well-informed" developers is paramount
importance for me.

> - the RFC code still uses the same function names while my code
> renames them to '*_func_*'. This makes the code look more complicated
> than it really is.

True. But, it paves the way to move all functions that is not intended
to be used beyond powerdomain files to a private power domain header -
which achieves the same objective without code churn.

Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v4 0/8] ARM: OMAP2+: PM: introduce the power domains functional states
  2012-06-14 14:53 ` Jean Pihet
@ 2012-07-13 13:41   ` Jean Pihet
  -1 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-07-13 13:41 UTC (permalink / raw)
  To: linux-omap, paul, linux-arm-kernel, khilman; +Cc: Jean Pihet

Hi!

On Thu, Jun 14, 2012 at 4:53 PM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
> Here is a re-spin after some comments after an internal review and some testing on
> OMAP4 with device OFF support.
>
> Implement the functional states for the power domains:
> - unify the API to use the functional states,
> - protect the power domain state change by a mutex in
>   omap_set_pwrdm_state,
> - introduce the functional states for power domains power states and
>   logic power states, and the conversion functions between the
>   functional and internal states,
> - program the logic power state of power domains from the functional
>   states, in omap_set_pwrdm_state
> - convert the OMAP2/3/4 PM code to use the updated API,
> - provide the power domains statistics by functional states,
> - provide ftrace tracepoints with the functional state.
>
> Based on mainline kernel 3.5.0-rc2.
>
> Tested on OMAP3 Beagleboard, with suspend and cpuidle in RET and
> OFF modes.

Here is the latest version for anyone willing to look at it, or even
better review and test it.

The latest code can be fetched from https://gitorious.org/jpihet/linux.
Please note that the tree also contains branches for the per-device PM
QoS, OMAP4 device OFF and the misc fixes needed to allow OMAP4 to
enter the low power modes.

Based on 3.5.0-rc6; tested with OMAP3&4 suspend/resume and OMAP3
cpuidle, using CSWR and OFF modes.

Here are the changes since the last version:
- changed the locking to a spinlock. Thanks to Ambresh K for reporting
the issue,
- extended the locking to the next power state read
(pwrdm_read_next_func_pwrst) and write (omap_set_pwrdm_state).

Regards,
Jean

>
>
> History:
>  v4:
>  - reworked the code after internal review and testing with OMAP3&4 device
>    OFF,
>  - fixed the tracepoints generation code,
>  - introduce a function that returns power domains achievable functional
>    states, in order to return a valid state for power domains that only
>    support some of the power states. Although it has been tested OK the
>    code is in RFC state.
>
>  v3:
>  - fix a bug in OMAP3 cpuidle which prevented the IO wake-ups in PER
>
>  v2:
>  - add the logic power states,
>  - provide the power domains statistics by functional states
>
>  v1:
>  - initial implementation, in RFC state
>
>
> Jean Pihet (8):
>   ARM: OMAP2+: PM: protect the power domain state change by a mutex
>   ARM: OMAP2+: PM: introduce power domains functional states
>   ARM: OMAP2+: PM: use the functional power states API
>   ARM: OMAP2+: PM: introduce power domains logic and memory functional
>     states
>   ARM: OMAP2+: PM: introduce power domains achievable functional states
>   ARM: OMAP2+: PM: use the functional power states API for logic and
>     memory
>   ARM: OMAP2+: PM: use power domain functional state in stats counters
>   ARM: OMAP2+: PM debug: trace the functional power domains states
>
>  arch/arm/mach-omap2/cpuidle34xx.c          |   61 +++---
>  arch/arm/mach-omap2/cpuidle44xx.c          |   28 +--
>  arch/arm/mach-omap2/omap-hotplug.c         |    2 +-
>  arch/arm/mach-omap2/omap-mpuss-lowpower.c  |   39 ++--
>  arch/arm/mach-omap2/pm-debug.c             |   15 +-
>  arch/arm/mach-omap2/pm.c                   |   62 -----
>  arch/arm/mach-omap2/pm.h                   |    1 -
>  arch/arm/mach-omap2/pm24xx.c               |   15 +-
>  arch/arm/mach-omap2/pm34xx.c               |   78 +++---
>  arch/arm/mach-omap2/pm44xx.c               |   18 +-
>  arch/arm/mach-omap2/powerdomain-common.c   |  100 ++++++++
>  arch/arm/mach-omap2/powerdomain.c          |  367 ++++++++++++++++++++++++++--
>  arch/arm/mach-omap2/powerdomain.h          |  101 ++++++--
>  arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |    7 +
>  arch/arm/mach-omap2/powerdomain44xx.c      |    3 +
>  15 files changed, 653 insertions(+), 244 deletions(-)
>
> --
> 1.7.7.6
>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH v4 0/8] ARM: OMAP2+: PM: introduce the power domains functional states
@ 2012-07-13 13:41   ` Jean Pihet
  0 siblings, 0 replies; 44+ messages in thread
From: Jean Pihet @ 2012-07-13 13:41 UTC (permalink / raw)
  To: linux-arm-kernel

Hi!

On Thu, Jun 14, 2012 at 4:53 PM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
> Here is a re-spin after some comments after an internal review and some testing on
> OMAP4 with device OFF support.
>
> Implement the functional states for the power domains:
> - unify the API to use the functional states,
> - protect the power domain state change by a mutex in
>   omap_set_pwrdm_state,
> - introduce the functional states for power domains power states and
>   logic power states, and the conversion functions between the
>   functional and internal states,
> - program the logic power state of power domains from the functional
>   states, in omap_set_pwrdm_state
> - convert the OMAP2/3/4 PM code to use the updated API,
> - provide the power domains statistics by functional states,
> - provide ftrace tracepoints with the functional state.
>
> Based on mainline kernel 3.5.0-rc2.
>
> Tested on OMAP3 Beagleboard, with suspend and cpuidle in RET and
> OFF modes.

Here is the latest version for anyone willing to look at it, or even
better review and test it.

The latest code can be fetched from https://gitorious.org/jpihet/linux.
Please note that the tree also contains branches for the per-device PM
QoS, OMAP4 device OFF and the misc fixes needed to allow OMAP4 to
enter the low power modes.

Based on 3.5.0-rc6; tested with OMAP3&4 suspend/resume and OMAP3
cpuidle, using CSWR and OFF modes.

Here are the changes since the last version:
- changed the locking to a spinlock. Thanks to Ambresh K for reporting
the issue,
- extended the locking to the next power state read
(pwrdm_read_next_func_pwrst) and write (omap_set_pwrdm_state).

Regards,
Jean

>
>
> History:
>  v4:
>  - reworked the code after internal review and testing with OMAP3&4 device
>    OFF,
>  - fixed the tracepoints generation code,
>  - introduce a function that returns power domains achievable functional
>    states, in order to return a valid state for power domains that only
>    support some of the power states. Although it has been tested OK the
>    code is in RFC state.
>
>  v3:
>  - fix a bug in OMAP3 cpuidle which prevented the IO wake-ups in PER
>
>  v2:
>  - add the logic power states,
>  - provide the power domains statistics by functional states
>
>  v1:
>  - initial implementation, in RFC state
>
>
> Jean Pihet (8):
>   ARM: OMAP2+: PM: protect the power domain state change by a mutex
>   ARM: OMAP2+: PM: introduce power domains functional states
>   ARM: OMAP2+: PM: use the functional power states API
>   ARM: OMAP2+: PM: introduce power domains logic and memory functional
>     states
>   ARM: OMAP2+: PM: introduce power domains achievable functional states
>   ARM: OMAP2+: PM: use the functional power states API for logic and
>     memory
>   ARM: OMAP2+: PM: use power domain functional state in stats counters
>   ARM: OMAP2+: PM debug: trace the functional power domains states
>
>  arch/arm/mach-omap2/cpuidle34xx.c          |   61 +++---
>  arch/arm/mach-omap2/cpuidle44xx.c          |   28 +--
>  arch/arm/mach-omap2/omap-hotplug.c         |    2 +-
>  arch/arm/mach-omap2/omap-mpuss-lowpower.c  |   39 ++--
>  arch/arm/mach-omap2/pm-debug.c             |   15 +-
>  arch/arm/mach-omap2/pm.c                   |   62 -----
>  arch/arm/mach-omap2/pm.h                   |    1 -
>  arch/arm/mach-omap2/pm24xx.c               |   15 +-
>  arch/arm/mach-omap2/pm34xx.c               |   78 +++---
>  arch/arm/mach-omap2/pm44xx.c               |   18 +-
>  arch/arm/mach-omap2/powerdomain-common.c   |  100 ++++++++
>  arch/arm/mach-omap2/powerdomain.c          |  367 ++++++++++++++++++++++++++--
>  arch/arm/mach-omap2/powerdomain.h          |  101 ++++++--
>  arch/arm/mach-omap2/powerdomain2xxx_3xxx.c |    7 +
>  arch/arm/mach-omap2/powerdomain44xx.c      |    3 +
>  15 files changed, 653 insertions(+), 244 deletions(-)
>
> --
> 1.7.7.6
>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 5/8] ARM: OMAP2+: PM: introduce power domains achievable functional states
  2012-06-15 11:28     ` Jean Pihet
@ 2012-07-19  6:57       ` Menon, Nishanth
  -1 siblings, 0 replies; 44+ messages in thread
From: Menon, Nishanth @ 2012-07-19  6:57 UTC (permalink / raw)
  To: Jean Pihet
  Cc: linux-omap, paul, linux-arm-kernel, khilman, Jean Pihet, Tero Kristo

On Fri, Jun 15, 2012 at 6:28 AM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
>
> "
> 1. The while loops need optimization. - This can definitely be
> simplified and made non-risky; this also needs some more error
> handling
If you are interested using something like the following
static int _match_pwrst(u32 pwrsts, u8 pwrst, u8 default_pwrst)
{
       bool found = true;
       int new_pwrst = pwrst;

       /* Search down */
       while (!(pwrsts & (1 << new_pwrst))) {
               if (new_pwrst == PWRDM_POWER_OFF) {
                       found = false;
                       break;
               }
               new_pwrst--;
       }

       if (found)
               goto done;

       /* Search up */
       new_pwrst = pwrst;
       while (!(pwrsts & (1 << new_pwrst))) {
               if (new_pwrst == default_pwrst)
                       break;
               new_pwrst++;
       }
done:
       return new_pwrst;
}


new_pwrst = _match_pwrst(pwrdm->pwrsts, pwrst,
                         PWRDM_POWER_ON);
new_logic = _match_pwrst(pwrdm->pwrsts_logic_ret, logic,
                         PWRDM_POWER_RET);
to achieve the same code..
> 2. About the power domains state machine: you have only one power
> state to move in and out of: it is called ON. If you do ON->CSWR->ON
> etc. attempting to program ON->CSWR->OSWR is NOT supported in OMAP and
> is an invitation for production team to sit and debug for a while
> before finding the use of invalid power states
> "
>
> Point 2 is a good point. The solution would be to implement a state
> machine in this function and/or omap_set_pwrdm_state, possibly using a
> platform specific handling function.

Point 2 is not completely accurate -> Lower pwr state transitions can
indeed and is indeed
supported on OMAP4+. CSWR->OSWR->OFF is possible and omap_setpwrdm_state does
indeed handle this. however going to OSWR->CSWR is possible only by
OSWR->ON->CSWR.
this is again supported in code, however, in practice, we have found
that certain IP blocks(in
personal experience, it was DSS) need IP specific additional work
which is not easily doable..
so when we come out of suspend state, if the IP block has achieved a
lower powerstate than
what was programmed, we just leave it as is.

Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 5/8] ARM: OMAP2+: PM: introduce power domains achievable functional states
@ 2012-07-19  6:57       ` Menon, Nishanth
  0 siblings, 0 replies; 44+ messages in thread
From: Menon, Nishanth @ 2012-07-19  6:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jun 15, 2012 at 6:28 AM, Jean Pihet <jean.pihet@newoldbits.com> wrote:
>
> "
> 1. The while loops need optimization. - This can definitely be
> simplified and made non-risky; this also needs some more error
> handling
If you are interested using something like the following
static int _match_pwrst(u32 pwrsts, u8 pwrst, u8 default_pwrst)
{
       bool found = true;
       int new_pwrst = pwrst;

       /* Search down */
       while (!(pwrsts & (1 << new_pwrst))) {
               if (new_pwrst == PWRDM_POWER_OFF) {
                       found = false;
                       break;
               }
               new_pwrst--;
       }

       if (found)
               goto done;

       /* Search up */
       new_pwrst = pwrst;
       while (!(pwrsts & (1 << new_pwrst))) {
               if (new_pwrst == default_pwrst)
                       break;
               new_pwrst++;
       }
done:
       return new_pwrst;
}


new_pwrst = _match_pwrst(pwrdm->pwrsts, pwrst,
                         PWRDM_POWER_ON);
new_logic = _match_pwrst(pwrdm->pwrsts_logic_ret, logic,
                         PWRDM_POWER_RET);
to achieve the same code..
> 2. About the power domains state machine: you have only one power
> state to move in and out of: it is called ON. If you do ON->CSWR->ON
> etc. attempting to program ON->CSWR->OSWR is NOT supported in OMAP and
> is an invitation for production team to sit and debug for a while
> before finding the use of invalid power states
> "
>
> Point 2 is a good point. The solution would be to implement a state
> machine in this function and/or omap_set_pwrdm_state, possibly using a
> platform specific handling function.

Point 2 is not completely accurate -> Lower pwr state transitions can
indeed and is indeed
supported on OMAP4+. CSWR->OSWR->OFF is possible and omap_setpwrdm_state does
indeed handle this. however going to OSWR->CSWR is possible only by
OSWR->ON->CSWR.
this is again supported in code, however, in practice, we have found
that certain IP blocks(in
personal experience, it was DSS) need IP specific additional work
which is not easily doable..
so when we come out of suspend state, if the IP block has achieved a
lower powerstate than
what was programmed, we just leave it as is.

Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2012-07-19  6:58 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-14 14:53 [PATCH v4 0/8] ARM: OMAP2+: PM: introduce the power domains functional states Jean Pihet
2012-06-14 14:53 ` Jean Pihet
2012-06-14 14:53 ` [PATCH 1/8] ARM: OMAP2+: PM: protect the power domain state change by a mutex Jean Pihet
2012-06-14 14:53   ` Jean Pihet
2012-06-20  9:17   ` Rajendra Nayak
2012-06-20  9:17     ` Rajendra Nayak
2012-06-14 14:53 ` [PATCH 2/8] ARM: OMAP2+: PM: introduce power domains functional states Jean Pihet
2012-06-14 14:53   ` Jean Pihet
2012-06-15 11:20   ` Jean Pihet
2012-06-15 11:20     ` Jean Pihet
2012-07-13  3:01   ` Menon, Nishanth
2012-07-13  3:01     ` Menon, Nishanth
2012-07-13  4:39     ` Nishanth Menon
2012-07-13  4:39       ` Nishanth Menon
2012-07-13  5:26     ` Rajendra Nayak
2012-07-13  5:26       ` Rajendra Nayak
2012-07-13  5:29       ` Menon, Nishanth
2012-07-13  5:29         ` Menon, Nishanth
2012-07-13  7:18         ` Jean Pihet
2012-07-13  7:18           ` Jean Pihet
2012-07-13  7:27           ` Menon, Nishanth
2012-07-13  7:27             ` Menon, Nishanth
2012-07-13  7:07     ` Jean Pihet
2012-07-13  7:07       ` Jean Pihet
2012-07-13  7:14       ` Menon, Nishanth
2012-07-13  7:14         ` Menon, Nishanth
2012-06-14 14:53 ` [PATCH 3/8] ARM: OMAP2+: PM: use the functional power states API Jean Pihet
2012-06-14 14:53   ` Jean Pihet
2012-06-14 14:53 ` [PATCH 4/8] ARM: OMAP2+: PM: introduce power domains logic and memory functional states Jean Pihet
2012-06-14 14:53   ` Jean Pihet
2012-06-14 14:53 ` [PATCH 5/8] ARM: OMAP2+: PM: introduce power domains achievable " Jean Pihet
2012-06-14 14:53   ` Jean Pihet
2012-06-15 11:28   ` Jean Pihet
2012-06-15 11:28     ` Jean Pihet
2012-07-19  6:57     ` Menon, Nishanth
2012-07-19  6:57       ` Menon, Nishanth
2012-06-14 14:53 ` [PATCH 6/8] ARM: OMAP2+: PM: use the functional power states API for logic and memory Jean Pihet
2012-06-14 14:53   ` Jean Pihet
2012-06-14 14:53 ` [PATCH 7/8] ARM: OMAP2+: PM: use power domain functional state in stats counters Jean Pihet
2012-06-14 14:53   ` Jean Pihet
2012-06-14 14:53 ` [PATCH 8/8] ARM: OMAP2+: PM debug: trace the functional power domains states Jean Pihet
2012-06-14 14:53   ` Jean Pihet
2012-07-13 13:41 ` [PATCH v4 0/8] ARM: OMAP2+: PM: introduce the power domains functional states Jean Pihet
2012-07-13 13:41   ` Jean Pihet

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.