RE: [PATCH 6/6] OMAP3: CPUidle: Added peripheral pwrdm checks into bm check

2009-11-17 Thread Tero.Kristo
 

-Original Message-
From: ext Kevin Hilman [mailto:khil...@deeprootsystems.com] 
Sent: 16 November, 2009 21:59
To: Kristo Tero (Nokia-D/Tampere)
Cc: linux-omap@vger.kernel.org
Subject: Re: [PATCH 6/6] OMAP3: CPUidle: Added peripheral 
pwrdm checks into bm check

Tero Kristo tero.kri...@nokia.com writes:

 From: Tero Kristo tero.kri...@nokia.com

 Following checks are made (and their reasoning):

 - If CAM domain is active, prevent idle completely
   * CAM pwrdm does not have HW wakeup capability
 - If PER is likely to remain on, prevent PER off
   * Saves on unnecessary context save/restore
 - If CORE domain is active, prevent PER off-mode
   * PER off in this case would prevent wakeups from PER completely
 - Only allow CORE off, if all peripheral domains are off
   * CORE off will cause a chipwide reset

 Also, enabled CHECK_BM flag for C2, as this is needed for 
the camera case.

 Signed-off-by: Tero Kristo tero.kri...@nokia.com

Some questions and a couple minor style comments below...

Will do the style changes, answers below.


 ---
  arch/arm/mach-omap2/cpuidle34xx.c |  105 
++---
  1 files changed, 98 insertions(+), 7 deletions(-)

 diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
 index e46345f..4654e87 100644
 --- a/arch/arm/mach-omap2/cpuidle34xx.c
 +++ b/arch/arm/mach-omap2/cpuidle34xx.c
 @@ -58,7 +58,8 @@ struct omap3_processor_cx {
  
  struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES];
  struct omap3_processor_cx current_cx_state;
 -struct powerdomain *mpu_pd, *core_pd;
 +struct powerdomain *mpu_pd, *core_pd, *per_pd, *iva2_pd;
 +struct powerdomain *sgx_pd, *usb_pd, *cam_pd, *dss_pd;
  
  /*
   * The latencies/thresholds for various C states have
 @@ -91,6 +92,13 @@ static int omap3_idle_bm_check(void)
  return 0;
  }

 +static int pwrdm_get_idle_state(struct powerdomain *pwrdm)

could use a function comment

Ok.


 +{
 +if (pwrdm_can_idle(pwrdm))
 +return pwrdm_read_next_pwrst(pwrdm);
 +return PWRDM_POWER_ON;
 +}
 +

Possible candidate for powerdomain API?

Candidate yes, if we would need this somewhere else. I did not want to make an 
API change that is not needed anywhere else at the moment. Maybe Paul has some 
comments on this?


  /**
   * omap3_enter_idle - Programs OMAP3 to enter the specified state
   * @dev: cpuidle device
 @@ -153,14 +161,90 @@ static int omap3_enter_idle_bm(struct 
cpuidle_device *dev,
 struct cpuidle_state *state)
  {
  struct cpuidle_state *new_state = state;
 -
 -if ((state-flags  CPUIDLE_FLAG_CHECK_BM)  
omap3_idle_bm_check()) {
 -BUG_ON(!dev-safe_state);
 -new_state = dev-safe_state;
 +u32 per_state = 0, saved_per_state = 0, cam_state, usb_state;
 +u32 iva2_state, sgx_state, dss_state, new_core_state;
 +struct omap3_processor_cx *cx;
 +int ret;
 +
 +if (state-flags  CPUIDLE_FLAG_CHECK_BM) {
 +if (omap3_idle_bm_check()) {
 +BUG_ON(!dev-safe_state);
 +new_state = dev-safe_state;
 +goto select_state;
 +}
 +cx = cpuidle_get_statedata(state);
 +new_core_state = cx-core_state;
 +
 +/* Check if CORE is active, if yes, fallback to 
inactive */
 +if (!pwrdm_can_idle(core_pd))
 +new_core_state = PWRDM_POWER_INACTIVE;
 +
 +/*
 + * Prevent idle completely if CAM is active.
 + * CAM does not have wakeup capability in OMAP3.
 + */
 +cam_state = pwrdm_get_idle_state(cam_pd);
 +if (cam_state == PWRDM_POWER_ON) {
 +new_state = dev-safe_state;
 +goto select_state;
 +}
 +
 +/*
 + * Check if PER can idle or not. If we are not likely
 + * to idle, deny PER off. This prevents unnecessary
 + * context save/restore.
 + */
 +saved_per_state = pwrdm_read_next_pwrst(per_pd);
 +if (pwrdm_can_idle(per_pd)) {
 +per_state = saved_per_state;
 +/*
 + * Prevent PER off if CORE is active as this
 + * would disable PER wakeups completely
 + */
 +if (per_state == PWRDM_POWER_OFF 
 +new_core_state  PWRDM_POWER_RET)
 +per_state = PWRDM_POWER_RET;
 +
 +} else if (saved_per_state == PWRDM_POWER_OFF)
 +per_state = PWRDM_POWER_RET;
 +
 +/*
 + * If we are attempting CORE off, check if any other
 + * powerdomains are at retention or higher. 
CORE off causes
 + * chipwide reset which would reset these domains also.
 + */
 +if (new_core_state == PWRDM_POWER_OFF

Re: [PATCH 6/6] OMAP3: CPUidle: Added peripheral pwrdm checks into bm check

2009-11-16 Thread Kevin Hilman
Tero Kristo tero.kri...@nokia.com writes:

 From: Tero Kristo tero.kri...@nokia.com

 Following checks are made (and their reasoning):

 - If CAM domain is active, prevent idle completely
   * CAM pwrdm does not have HW wakeup capability
 - If PER is likely to remain on, prevent PER off
   * Saves on unnecessary context save/restore
 - If CORE domain is active, prevent PER off-mode
   * PER off in this case would prevent wakeups from PER completely
 - Only allow CORE off, if all peripheral domains are off
   * CORE off will cause a chipwide reset

 Also, enabled CHECK_BM flag for C2, as this is needed for the camera case.

 Signed-off-by: Tero Kristo tero.kri...@nokia.com

Some questions and a couple minor style comments below...

 ---
  arch/arm/mach-omap2/cpuidle34xx.c |  105 
 ++---
  1 files changed, 98 insertions(+), 7 deletions(-)

 diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
 b/arch/arm/mach-omap2/cpuidle34xx.c
 index e46345f..4654e87 100644
 --- a/arch/arm/mach-omap2/cpuidle34xx.c
 +++ b/arch/arm/mach-omap2/cpuidle34xx.c
 @@ -58,7 +58,8 @@ struct omap3_processor_cx {
  
  struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES];
  struct omap3_processor_cx current_cx_state;
 -struct powerdomain *mpu_pd, *core_pd;
 +struct powerdomain *mpu_pd, *core_pd, *per_pd, *iva2_pd;
 +struct powerdomain *sgx_pd, *usb_pd, *cam_pd, *dss_pd;
  
  /*
   * The latencies/thresholds for various C states have
 @@ -91,6 +92,13 @@ static int omap3_idle_bm_check(void)
   return 0;
  }

 +static int pwrdm_get_idle_state(struct powerdomain *pwrdm)

could use a function comment

 +{
 + if (pwrdm_can_idle(pwrdm))
 + return pwrdm_read_next_pwrst(pwrdm);
 + return PWRDM_POWER_ON;
 +}
 +

Possible candidate for powerdomain API?

  /**
   * omap3_enter_idle - Programs OMAP3 to enter the specified state
   * @dev: cpuidle device
 @@ -153,14 +161,90 @@ static int omap3_enter_idle_bm(struct cpuidle_device 
 *dev,
  struct cpuidle_state *state)
  {
   struct cpuidle_state *new_state = state;
 -
 - if ((state-flags  CPUIDLE_FLAG_CHECK_BM)  omap3_idle_bm_check()) {
 - BUG_ON(!dev-safe_state);
 - new_state = dev-safe_state;
 + u32 per_state = 0, saved_per_state = 0, cam_state, usb_state;
 + u32 iva2_state, sgx_state, dss_state, new_core_state;
 + struct omap3_processor_cx *cx;
 + int ret;
 +
 + if (state-flags  CPUIDLE_FLAG_CHECK_BM) {
 + if (omap3_idle_bm_check()) {
 + BUG_ON(!dev-safe_state);
 + new_state = dev-safe_state;
 + goto select_state;
 + }
 + cx = cpuidle_get_statedata(state);
 + new_core_state = cx-core_state;
 +
 + /* Check if CORE is active, if yes, fallback to inactive */
 + if (!pwrdm_can_idle(core_pd))
 + new_core_state = PWRDM_POWER_INACTIVE;
 +
 + /*
 +  * Prevent idle completely if CAM is active.
 +  * CAM does not have wakeup capability in OMAP3.
 +  */
 + cam_state = pwrdm_get_idle_state(cam_pd);
 + if (cam_state == PWRDM_POWER_ON) {
 + new_state = dev-safe_state;
 + goto select_state;
 + }
 +
 + /*
 +  * Check if PER can idle or not. If we are not likely
 +  * to idle, deny PER off. This prevents unnecessary
 +  * context save/restore.
 +  */
 + saved_per_state = pwrdm_read_next_pwrst(per_pd);
 + if (pwrdm_can_idle(per_pd)) {
 + per_state = saved_per_state;
 + /*
 +  * Prevent PER off if CORE is active as this
 +  * would disable PER wakeups completely
 +  */
 + if (per_state == PWRDM_POWER_OFF 
 + new_core_state  PWRDM_POWER_RET)
 + per_state = PWRDM_POWER_RET;
 +
 + } else if (saved_per_state == PWRDM_POWER_OFF)
 + per_state = PWRDM_POWER_RET;
 +
 + /*
 +  * If we are attempting CORE off, check if any other
 +  * powerdomains are at retention or higher. CORE off causes
 +  * chipwide reset which would reset these domains also.
 +  */
 + if (new_core_state == PWRDM_POWER_OFF) {
 + dss_state = pwrdm_get_idle_state(dss_pd);
 + iva2_state = pwrdm_get_idle_state(iva2_pd);
 + sgx_state = pwrdm_get_idle_state(sgx_pd);
 + usb_state = pwrdm_get_idle_state(usb_pd);
 +
 + if (cam_state  PWRDM_POWER_OFF ||
 + dss_state  PWRDM_POWER_OFF ||
 + iva2_state  PWRDM_POWER_OFF ||
 + per_state  

[PATCH 6/6] OMAP3: CPUidle: Added peripheral pwrdm checks into bm check

2009-11-12 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Following checks are made (and their reasoning):

- If CAM domain is active, prevent idle completely
  * CAM pwrdm does not have HW wakeup capability
- If PER is likely to remain on, prevent PER off
  * Saves on unnecessary context save/restore
- If CORE domain is active, prevent PER off-mode
  * PER off in this case would prevent wakeups from PER completely
- Only allow CORE off, if all peripheral domains are off
  * CORE off will cause a chipwide reset

Also, enabled CHECK_BM flag for C2, as this is needed for the camera case.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/cpuidle34xx.c |  105 ++---
 1 files changed, 98 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index e46345f..4654e87 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -58,7 +58,8 @@ struct omap3_processor_cx {
 
 struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES];
 struct omap3_processor_cx current_cx_state;
-struct powerdomain *mpu_pd, *core_pd;
+struct powerdomain *mpu_pd, *core_pd, *per_pd, *iva2_pd;
+struct powerdomain *sgx_pd, *usb_pd, *cam_pd, *dss_pd;
 
 /*
  * The latencies/thresholds for various C states have
@@ -91,6 +92,13 @@ static int omap3_idle_bm_check(void)
return 0;
 }
 
+static int pwrdm_get_idle_state(struct powerdomain *pwrdm)
+{
+   if (pwrdm_can_idle(pwrdm))
+   return pwrdm_read_next_pwrst(pwrdm);
+   return PWRDM_POWER_ON;
+}
+
 /**
  * omap3_enter_idle - Programs OMAP3 to enter the specified state
  * @dev: cpuidle device
@@ -153,14 +161,90 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
   struct cpuidle_state *state)
 {
struct cpuidle_state *new_state = state;
-
-   if ((state-flags  CPUIDLE_FLAG_CHECK_BM)  omap3_idle_bm_check()) {
-   BUG_ON(!dev-safe_state);
-   new_state = dev-safe_state;
+   u32 per_state = 0, saved_per_state = 0, cam_state, usb_state;
+   u32 iva2_state, sgx_state, dss_state, new_core_state;
+   struct omap3_processor_cx *cx;
+   int ret;
+
+   if (state-flags  CPUIDLE_FLAG_CHECK_BM) {
+   if (omap3_idle_bm_check()) {
+   BUG_ON(!dev-safe_state);
+   new_state = dev-safe_state;
+   goto select_state;
+   }
+   cx = cpuidle_get_statedata(state);
+   new_core_state = cx-core_state;
+
+   /* Check if CORE is active, if yes, fallback to inactive */
+   if (!pwrdm_can_idle(core_pd))
+   new_core_state = PWRDM_POWER_INACTIVE;
+
+   /*
+* Prevent idle completely if CAM is active.
+* CAM does not have wakeup capability in OMAP3.
+*/
+   cam_state = pwrdm_get_idle_state(cam_pd);
+   if (cam_state == PWRDM_POWER_ON) {
+   new_state = dev-safe_state;
+   goto select_state;
+   }
+
+   /*
+* Check if PER can idle or not. If we are not likely
+* to idle, deny PER off. This prevents unnecessary
+* context save/restore.
+*/
+   saved_per_state = pwrdm_read_next_pwrst(per_pd);
+   if (pwrdm_can_idle(per_pd)) {
+   per_state = saved_per_state;
+   /*
+* Prevent PER off if CORE is active as this
+* would disable PER wakeups completely
+*/
+   if (per_state == PWRDM_POWER_OFF 
+   new_core_state  PWRDM_POWER_RET)
+   per_state = PWRDM_POWER_RET;
+
+   } else if (saved_per_state == PWRDM_POWER_OFF)
+   per_state = PWRDM_POWER_RET;
+
+   /*
+* If we are attempting CORE off, check if any other
+* powerdomains are at retention or higher. CORE off causes
+* chipwide reset which would reset these domains also.
+*/
+   if (new_core_state == PWRDM_POWER_OFF) {
+   dss_state = pwrdm_get_idle_state(dss_pd);
+   iva2_state = pwrdm_get_idle_state(iva2_pd);
+   sgx_state = pwrdm_get_idle_state(sgx_pd);
+   usb_state = pwrdm_get_idle_state(usb_pd);
+
+   if (cam_state  PWRDM_POWER_OFF ||
+   dss_state  PWRDM_POWER_OFF ||
+   iva2_state  PWRDM_POWER_OFF ||
+   per_state  PWRDM_POWER_OFF ||
+   sgx_state  PWRDM_POWER_OFF ||
+   usb_state  PWRDM_POWER_OFF)
+