[PATCH 1/1] Added sleep support to UART

2008-05-29 Thread Tero Kristo
UART usage (e.g. serial console) now denies sleep for 5 seconds. This
makes it possible to use serial console when dynamic idle is enabled.

Also moved code from pm-debug.c to serial.c, and made pm24xx.c use this
new implementation.

Signed-off-by: Tero Kristo [EMAIL PROTECTED]
---
 arch/arm/mach-omap2/pm-debug.c |  132 
 arch/arm/mach-omap2/pm.h   |8 --
 arch/arm/mach-omap2/pm24xx.c   |   53 ++-
 arch/arm/mach-omap2/pm34xx.c   |8 ++-
 arch/arm/mach-omap2/serial.c   |  118 
 include/asm-arm/arch-omap/common.h |3 +
 6 files changed, 163 insertions(+), 159 deletions(-)

diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 8a9f3c4..c20fa3b 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -34,138 +34,6 @@
 #ifdef CONFIG_PM_DEBUG
 int omap2_pm_debug = 0;
 
-static int serial_console_clock_disabled;
-static int serial_console_uart;
-static unsigned int serial_console_next_disable;
-
-static struct clk *console_iclk, *console_fclk;
-
-static void serial_console_kick(void)
-{
-   serial_console_next_disable = omap2_read_32k_sync_counter();
-   /* Keep the clocks on for 4 secs */
-   serial_console_next_disable += 4 * 32768;
-}
-
-static void serial_wait_tx(void)
-{
-   static const unsigned long uart_bases[3] = {
-   0x4806a000, 0x4806c000, 0x4806e000
-   };
-   unsigned long lsr_reg;
-   int looped = 0;
-
-   /* Wait for TX FIFO and THR to get empty */
-   lsr_reg = IO_ADDRESS(uart_bases[serial_console_uart - 1] + (5  2));
-   while ((__raw_readb(lsr_reg)  0x60) != 0x60)
-   looped = 1;
-   if (looped)
-   serial_console_kick();
-}
-
-u32 omap2_read_32k_sync_counter(void)
-{
-return omap_readl(OMAP2_32KSYNCT_BASE + 0x0010);
-}
-
-void serial_console_fclk_mask(u32 *f1, u32 *f2)
-{
-   switch (serial_console_uart)  {
-   case 1:
-   *f1 = ~(1  21);
-   break;
-   case 2:
-   *f1 = ~(1  22);
-   break;
-   case 3:
-   *f2 = ~(1  2);
-   break;
-   }
-}
-
-void serial_console_sleep(int enable)
-{
-   if (console_iclk == NULL || console_fclk == NULL)
-   return;
-
-   if (enable) {
-   BUG_ON(serial_console_clock_disabled);
-   if (clk_get_usecount(console_fclk) == 0)
-   return;
-   if ((int) serial_console_next_disable - (int) 
omap2_read_32k_sync_counter() = 0)
-   return;
-   serial_wait_tx();
-   clk_disable(console_iclk);
-   clk_disable(console_fclk);
-   serial_console_clock_disabled = 1;
-   } else {
-   int serial_wakeup = 0;
-   u32 l;
-
-   switch (serial_console_uart)  {
-   case 1:
-   l = prm_read_mod_reg(CORE_MOD, PM_WKST1);
-   if (l  OMAP24XX_ST_UART1)
-   serial_wakeup = 1;
-   break;
-   case 2:
-   l = prm_read_mod_reg(CORE_MOD, PM_WKST1);
-   if (l  OMAP24XX_ST_UART2)
-   serial_wakeup = 1;
-   break;
-   case 3:
-   l = prm_read_mod_reg(CORE_MOD, OMAP24XX_PM_WKST2);
-   if (l  OMAP24XX_ST_UART3)
-   serial_wakeup = 1;
-   break;
-   }
-   if (serial_wakeup)
-   serial_console_kick();
-   if (!serial_console_clock_disabled)
-   return;
-   clk_enable(console_iclk);
-   clk_enable(console_fclk);
-   serial_console_clock_disabled = 0;
-   }
-}
-
-void pm_init_serial_console(void)
-{
-   const struct omap_serial_console_config *conf;
-   char name[16];
-
-   conf = omap_get_config(OMAP_TAG_SERIAL_CONSOLE,
-  struct omap_serial_console_config);
-   if (conf == NULL)
-   return;
-   if (conf-console_uart  3 || conf-console_uart  1)
-   return;
-   serial_console_uart = conf-console_uart;
-   sprintf(name, uart%d_fck, conf-console_uart);
-   console_fclk = clk_get(NULL, name);
-   if (IS_ERR(console_fclk))
-   console_fclk = NULL;
-   name[6] = 'i';
-   console_iclk = clk_get(NULL, name);
-   if (IS_ERR(console_fclk))
-   console_iclk = NULL;
-   if (console_fclk == NULL || console_iclk == NULL) {
-   serial_console_uart = 0;
-   return;
-   }
-   switch (serial_console_uart) {
-   case 1:
-   prm_set_mod_reg_bits(OMAP24XX_ST_UART1, CORE_MOD, PM_WKEN1);
-   break

Dynamic idle support for UART

2008-05-29 Thread Tero Kristo
This hack will most importantly allow serial console usage when dynamic
idle is enabled.

Note! Functionality under 24xx configuration has not been verified!
  There may be some problems with CONFIG_PM_DEBUG flag enabled,
  most likely during the PM debug information dumps after / before
  sleep. Without this debugging flag this patch should not affect 24xx
  devices. Todo: Someone to check functionality under 24xx
  configuration and to enable functionality by default on that
  platform also.


--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Second part for the UART hack (dependency)

2008-06-03 Thread Tero Kristo
This patch depends on the PM patch set sent by Jouni Hogander. Basically just a 
cosmetic modification to make fclk mask look more nice inside pm34xx.c.


--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/1] omap3_fclks_active() now uses generic serial clock check

2008-06-03 Thread Tero Kristo
Signed-off-by: Tero Kristo [EMAIL PROTECTED]
---
 arch/arm/mach-omap2/pm34xx.c |3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index ada87ba..2574586 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -245,8 +245,7 @@ static int omap3_fclks_active(void)
fck_per = cm_read_mod_reg(OMAP3430_PER_MOD,
  CM_FCLKEN);
gpio_fclk_mask(fck_per);
-   fck_core1 = ~(0x3  13);
-   fck_per = ~(0x1  11);
+   omap_serial_fclk_mask(fck_core1, fck_per);
if (fck_core1 | fck_core3 | fck_sgx | fck_dss |
fck_cam | fck_per | fck_usbhost)
return 1;
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


34xx off-mode support fixes

2008-07-03 Thread Tero Kristo
Hi,

This patch set contains some experimental fixes for the cpu-idle support from
Rajendra Nayak. With this patch set, all power domains enter OFF mode and
recover from it, at least while using suspend and/or dynamic idle. If you
are using these patches, you should disable CPU_IDLE support from kernel
config as I am not certain it works with this patch set yet. The last patch
contains some trial fix to cpuidle code, so it might work also if you are
lucky enough.

-Tero


--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] OMAP3: CPUIdle: prevent CORE from going off if doing so would reset an active clockdomain

2011-01-18 Thread Tero Kristo
On OMAP3 SoCs, if the CORE powerdomain enters off-mode, many other
parts of the chip will be reset.  If those parts of the chip are busy,
the reset will disrupt them, causing unpredictable and generally
undesirable results.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
Cc: Paul Walmsley p...@pwsan.com
Cc: Kevin Hilman khil...@deeprootsystems.com
---
 arch/arm/mach-omap2/cpuidle34xx.c |   40 +++-
 1 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index f3e043f..d31b858 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -61,7 +61,7 @@ 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, *per_pd;
-struct powerdomain *cam_pd;
+struct powerdomain *cam_pd, *dss_pd, *iva2_pd, *sgx_pd, *usb_pd;
 
 /*
  * The latencies/thresholds for various C states have
@@ -235,7 +235,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 {
struct cpuidle_state *new_state = next_valid_state(dev, state);
u32 core_next_state, per_next_state = 0, per_saved_state = 0;
-   u32 cam_state;
+   u32 cam_state, dss_state, iva2_state, sgx_state, usb_state;
struct omap3_processor_cx *cx;
int ret;
 
@@ -256,6 +256,8 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 *its own code.
 */
 
+   /* XXX Add CORE-active check here */
+
/*
 * Prevent idle completely if CAM is active.
 * CAM does not have wakeup capability in OMAP3.
@@ -275,6 +277,36 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
(core_next_state  PWRDM_POWER_RET))
per_next_state = PWRDM_POWER_RET;
 
+   /* XXX Add prevent-PER-off check here */
+
+   /*
+* 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 (core_next_state == PWRDM_POWER_OFF) {
+   iva2_state = pwrdm_read_pwrst(iva2_pd);
+   sgx_state = pwrdm_read_pwrst(sgx_pd);
+   usb_state = pwrdm_read_pwrst(usb_pd);
+   dss_state = pwrdm_read_pwrst(dss_pd);
+
+   if (cam_state  PWRDM_POWER_OFF ||
+   dss_state  PWRDM_POWER_OFF ||
+   iva2_state  PWRDM_POWER_OFF ||
+   per_next_state  PWRDM_POWER_OFF ||
+   sgx_state  PWRDM_POWER_OFF ||
+   usb_state  PWRDM_POWER_OFF)
+   core_next_state = PWRDM_POWER_RET;
+   }
+
+   /* Fallback to new target core/mpu state */
+   while (cx-core_state  core_next_state) {
+   state--;
+   cx = cpuidle_get_statedata(state);
+   }
+
+   new_state = state;
+
/* Are we changing PER target state? */
if (per_next_state != per_saved_state)
pwrdm_set_next_pwrst(per_pd, per_next_state);
@@ -489,6 +521,10 @@ int __init omap3_idle_init(void)
core_pd = pwrdm_lookup(core_pwrdm);
per_pd = pwrdm_lookup(per_pwrdm);
cam_pd = pwrdm_lookup(cam_pwrdm);
+   dss_pd = pwrdm_lookup(dss_pwrdm);
+   iva2_pd = pwrdm_lookup(iva2_pwrdm);
+   sgx_pd = pwrdm_lookup(sgx_pwrdm);
+   usb_pd = pwrdm_lookup(usbhost_pwrdm);
 
omap_init_power_states();
cpuidle_register_driver(omap3_idle_driver);
-- 
1.7.1

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv2] OMAP3: CPUIdle: prevent CORE from going off if doing so would reset an active clockdomain

2011-01-21 Thread Tero Kristo
On OMAP3 SoCs, if the CORE powerdomain enters off-mode, many other
parts of the chip will be reset.  If those parts of the chip are busy,
the reset will disrupt them, causing unpredictable and generally
undesirable results. This reset is caused by the core domain wakeup
(COREDOMAINWKUP_RST), and it can occur for example in a case where
some peripheral domain is in retention or inactive state and core
enters off. This will result in the peripheral domain being reset.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
Cc: Paul Walmsley p...@pwsan.com
Cc: Kevin Hilman khil...@deeprootsystems.com
Cc: Santosh Shilimkar santosh.shilim...@ti.com
Cc: Vishwanath Sripathy vishwanath...@ti.com
---
 arch/arm/mach-omap2/cpuidle34xx.c |   40 +++-
 1 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index f3e043f..d31b858 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -61,7 +61,7 @@ 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, *per_pd;
-struct powerdomain *cam_pd;
+struct powerdomain *cam_pd, *dss_pd, *iva2_pd, *sgx_pd, *usb_pd;
 
 /*
  * The latencies/thresholds for various C states have
@@ -235,7 +235,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 {
struct cpuidle_state *new_state = next_valid_state(dev, state);
u32 core_next_state, per_next_state = 0, per_saved_state = 0;
-   u32 cam_state;
+   u32 cam_state, dss_state, iva2_state, sgx_state, usb_state;
struct omap3_processor_cx *cx;
int ret;
 
@@ -256,6 +256,8 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 *its own code.
 */
 
+   /* XXX Add CORE-active check here */
+
/*
 * Prevent idle completely if CAM is active.
 * CAM does not have wakeup capability in OMAP3.
@@ -275,6 +277,36 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
(core_next_state  PWRDM_POWER_RET))
per_next_state = PWRDM_POWER_RET;
 
+   /* XXX Add prevent-PER-off check here */
+
+   /*
+* 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 (core_next_state == PWRDM_POWER_OFF) {
+   iva2_state = pwrdm_read_pwrst(iva2_pd);
+   sgx_state = pwrdm_read_pwrst(sgx_pd);
+   usb_state = pwrdm_read_pwrst(usb_pd);
+   dss_state = pwrdm_read_pwrst(dss_pd);
+
+   if (cam_state  PWRDM_POWER_OFF ||
+   dss_state  PWRDM_POWER_OFF ||
+   iva2_state  PWRDM_POWER_OFF ||
+   per_next_state  PWRDM_POWER_OFF ||
+   sgx_state  PWRDM_POWER_OFF ||
+   usb_state  PWRDM_POWER_OFF)
+   core_next_state = PWRDM_POWER_RET;
+   }
+
+   /* Fallback to new target core/mpu state */
+   while (cx-core_state  core_next_state) {
+   state--;
+   cx = cpuidle_get_statedata(state);
+   }
+
+   new_state = state;
+
/* Are we changing PER target state? */
if (per_next_state != per_saved_state)
pwrdm_set_next_pwrst(per_pd, per_next_state);
@@ -489,6 +521,10 @@ int __init omap3_idle_init(void)
core_pd = pwrdm_lookup(core_pwrdm);
per_pd = pwrdm_lookup(per_pwrdm);
cam_pd = pwrdm_lookup(cam_pwrdm);
+   dss_pd = pwrdm_lookup(dss_pwrdm);
+   iva2_pd = pwrdm_lookup(iva2_pwrdm);
+   sgx_pd = pwrdm_lookup(sgx_pwrdm);
+   usb_pd = pwrdm_lookup(usbhost_pwrdm);
 
omap_init_power_states();
cpuidle_register_driver(omap3_idle_driver);
-- 
1.7.1

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv3 2/6] OMAP3: PM: Added support for INACTIVE and ON states for powerdomains

2010-01-15 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Previously omap_sram_idle() did not know about the difference between ON and
INACTIVE states, which complicated the state handling in these cases. Now,
the following changes are done in the idle logic:

- Check for IO-chain arming is changed to reflect desired state (RET)
- UART clocks will be disabled if we attempt to enter INACTIVE (this allows
  the state change to actually happen)

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

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index a5335f9..7cc3293 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -386,6 +386,7 @@ void omap_sram_idle(void)
mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
switch (mpu_next_state) {
case PWRDM_POWER_ON:
+   case PWRDM_POWER_INACTIVE:
case PWRDM_POWER_RET:
/* No need to save context */
save_state = 0;
@@ -452,9 +453,11 @@ void omap_sram_idle(void)
OMAP3430_GR_MOD,
OMAP3_PRM_VOLTCTRL_OFFSET);
}
-   /* Enable IO-PAD and IO-CHAIN wakeups */
-   prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
-   omap3_enable_io_chain();
+   if (core_next_state = PWRDM_POWER_RET) {
+   /* Enable IO-PAD and IO-CHAIN wakeups */
+   prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
+   omap3_enable_io_chain();
+   }
}
omap3_intc_prepare_idle();
 
@@ -555,15 +558,13 @@ void omap_sram_idle(void)
}
 
/* Disable IO-PAD and IO-CHAIN wakeup */
-   if (core_next_state  PWRDM_POWER_ON) {
+   if (core_next_state = PWRDM_POWER_RET) {
prm_clear_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
omap3_disable_io_chain();
}
 
 
pwrdm_post_transition();
-
-   omap2_clkdm_allow_idle(mpu_pwrdm-pwrdm_clkdms[0]);
 }
 
 int omap3_can_sleep(void)
@@ -611,7 +612,6 @@ int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
}
 
if (sleep_switch) {
-   omap2_clkdm_allow_idle(pwrdm-pwrdm_clkdms[0]);
pwrdm_wait_transition(pwrdm);
pwrdm_state_switch(pwrdm);
}
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv3 5/6] OMAP: Powerdomains: Add support for checking if pwrdm/clkdm can idle

2010-01-15 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

pwrdm_can_idle(pwrdm) will check if the specified powerdomain can enter
idle. This is done by checking all clockdomains under the powerdomain
if they can idle also.

omap2_clkdm_can_idle(clkdm) will check if the specified clockdomain can
enter idle. This checks the functional clocks and idle status bits of the
domain according to following rules:
1) get inverse of idlest and mask against idle_def.mask
  * this gives a bitmask with non-idle bits high
2) bitwise OR active functional clocks from the domain to the result
  * in some cases FCLK can be active but idlest still shows module in idle
3) disable bits defined in idle_def.mask
  * some bits should be ignored, like UART clocks which are dynamically
switched inside sleep loop

These calls can be used e.g. inside cpuidle to decide which power states
core and mpu should enter during idle, as there are certain dependencies
between wakeup capabilities and reset logic.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/clockdomain.c |   27 
 arch/arm/mach-omap2/clockdomains.h|   54 +
 arch/arm/mach-omap2/powerdomain.c |   25 +++
 arch/arm/plat-omap/include/plat/clockdomain.h |   17 
 arch/arm/plat-omap/include/plat/powerdomain.h |1 +
 5 files changed, 124 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c 
b/arch/arm/mach-omap2/clockdomain.c
index dd285f0..f42111a 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -472,6 +472,33 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm)
return 0;
 }
 
+
+/**
+ * omap2_clkdm_can_idle - check if clockdomain has any active clocks or not
+ * @clkdm: struct clockdomain *
+ *
+ * Checks if the clockdomain has any active clock or not, i.e. whether it
+ * can enter idle. Returns -EINVAL if clkdm is NULL; 0 if unable to idle;
+ * 1 if can idle.
+ */
+int omap2_clkdm_can_idle(struct clockdomain *clkdm)
+{
+   int i;
+
+   if (!clkdm)
+   return -EINVAL;
+
+   for (i = 0; i  clkdm-clk_reg_amt; i++)
+   if (((~cm_read_mod_reg(clkdm-pwrdm.ptr-prcm_offs,
+   CM_IDLEST + 4 * i) 
+   clkdm-idle_def[i].mask) |
+   cm_read_mod_reg(clkdm-pwrdm.ptr-prcm_offs,
+   CM_FCLKEN + 4 * i)) 
+   ~clkdm-idle_def[i].ignore)
+   return 0;
+   return 1;
+}
+
 /**
  * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm
  * @clkdm: struct clockdomain *
diff --git a/arch/arm/mach-omap2/clockdomains.h 
b/arch/arm/mach-omap2/clockdomains.h
index c4ee076..2c1f2eb 100644
--- a/arch/arm/mach-omap2/clockdomains.h
+++ b/arch/arm/mach-omap2/clockdomains.h
@@ -167,6 +167,12 @@ static struct clockdomain iva2_clkdm = {
.flags  = CLKDM_CAN_HWSUP_SWSUP,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+   .clk_reg_amt= 1,
+   .idle_def   = {
+   [0] = {
+   .mask = 0x1,
+   },
+   },
 };
 
 static struct clockdomain gfx_3430es1_clkdm = {
@@ -183,6 +189,12 @@ static struct clockdomain sgx_clkdm = {
.flags  = CLKDM_CAN_HWSUP_SWSUP,
.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
+   .clk_reg_amt= 1,
+   .idle_def   = {
+   [0] = {
+   .mask = 0x1,
+   },
+   },
 };
 
 /*
@@ -206,6 +218,23 @@ static struct clockdomain core_l3_34xx_clkdm = {
.flags  = CLKDM_CAN_HWSUP,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+   .clk_reg_amt= 3,
+   .idle_def   = {
+   [0] = {
+   .ignore = OMAP3430_ST_UART2_MASK |
+   OMAP3430_ST_UART1_MASK |
+   OMAP3430_ST_SDRC_MASK |
+   OMAP3430_ST_OMAPCTRL_MASK |
+   OMAP3430ES2_ST_HSOTGUSB_IDLE_MASK,
+   .mask = 0x,
+   },
+   [1] = {
+   .mask = 0x1f,
+   },
+   [2] = {
+   .mask = 0x4,
+   },
+   },
 };
 
 static struct clockdomain core_l4_34xx_clkdm = {
@@ -222,6 +251,12 @@ static struct clockdomain dss_34xx_clkdm = {
.flags  = CLKDM_CAN_HWSUP_SWSUP,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+   .clk_reg_amt= 1,
+   .idle_def   = {
+   [0] = {
+   .mask = 0x1

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

2010-01-15 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 |  118 ++--
 1 files changed, 111 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 4a81ef1..dad64a9 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
@@ -92,6 +93,22 @@ static int omap3_idle_bm_check(void)
 }
 
 /**
+ * pwrdm_get_idle_state - Get the power state a pwrdm will enter during idle
+ * @pwrdm: powerdomain to check state for
+ *
+ * Checks if the powerdomain can enter idle or not, if yes, will return
+ * the programmed target state for the domain. Otherwise will indicate
+ * that the domain will stay on.
+ * Returns the power state the pwrdm will enter.
+ */
+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
  * @state: The target state to be programmed
@@ -153,14 +170,94 @@ 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

[PATCHv3 3/6] OMAP3: CPUidle: Fixed support for ON / INACTIVE states

2010-01-15 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

New powerdomain code support for INACTIVE state removes the need to control
clockdomains directly from cpuidle. Also, cpuidle state definitions can now
directly support ON / INACTIVE simplifying the implementation.

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

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 1cfa5a6..4a81ef1 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -91,20 +91,6 @@ static int omap3_idle_bm_check(void)
return 0;
 }
 
-static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
-{
-   omap2_clkdm_allow_idle(clkdm);
-   return 0;
-}
-
-static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
-{
-   omap2_clkdm_deny_idle(clkdm);
-   return 0;
-}
-
 /**
  * omap3_enter_idle - Programs OMAP3 to enter the specified state
  * @dev: cpuidle device
@@ -141,19 +127,9 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
if (omap_irq_pending() || need_resched())
goto return_sleep_time;
 
-   if (cx-type == OMAP3_STATE_C1) {
-   pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
-   pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
-   }
-
/* Execute ARM wfi */
omap_sram_idle();
 
-   if (cx-type == OMAP3_STATE_C1) {
-   pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
-   pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
-   }
-
 return_sleep_time:
getnstimeofday(ts_postidle);
ts_idle = timespec_sub(ts_postidle, ts_preidle);
@@ -246,8 +222,8 @@ void omap_init_power_states(void)
cpuidle_params_table[OMAP3_STATE_C2].wake_latency;
omap3_power_states[OMAP3_STATE_C2].threshold =
cpuidle_params_table[OMAP3_STATE_C2].threshold;
-   omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON;
-   omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_INACTIVE;
+   omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID;
 
/* C3 . MPU CSWR + Core inactive */
@@ -261,7 +237,7 @@ void omap_init_power_states(void)
omap3_power_states[OMAP3_STATE_C3].threshold =
cpuidle_params_table[OMAP3_STATE_C3].threshold;
omap3_power_states[OMAP3_STATE_C3].mpu_state = PWRDM_POWER_RET;
-   omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
 
@@ -276,7 +252,7 @@ void omap_init_power_states(void)
omap3_power_states[OMAP3_STATE_C4].threshold =
cpuidle_params_table[OMAP3_STATE_C4].threshold;
omap3_power_states[OMAP3_STATE_C4].mpu_state = PWRDM_POWER_OFF;
-   omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
 
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv3 0/6] Idle status patches revisited again

2010-01-15 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Improvements / fixes compared to previous version:

- Added pwrdm next_state cache initialization to patch 1
- Fixed changelog for patch 1
- Added FCLK checks to patch 5 (now checks both idlest and fclk)
- Added more info to changelog for patch 5

-Tero


--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv3 4/6] OMAP3: PM: Removed pwrdm state hacking from omap_sram_idle

2010-01-15 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Following hacks will be moved inside cpuidle in subsequent patch:

- CAM domain prevents idle completely
- PER should not go OFF if core remains active

This simplifies the design and allows cpuidle to keep better track of which
power states system will actually enter.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/pm34xx.c |   18 ++
 1 files changed, 2 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 7cc3293..549be95 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -93,7 +93,6 @@ static int (*_omap_save_secure_sram)(u32 *addr);
 
 static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
-static struct powerdomain *cam_pwrdm;
 
 static struct prm_setup_vc prm_setup = {
.clksetup = 0xff,
@@ -373,7 +372,6 @@ void omap_sram_idle(void)
int core_next_state = PWRDM_POWER_ON;
int core_prev_state, per_prev_state;
u32 sdrc_pwr = 0;
-   int per_state_modified = 0;
 
if (!_omap_sram_idle)
return;
@@ -411,20 +409,11 @@ void omap_sram_idle(void)
core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
if (per_next_state  PWRDM_POWER_ON) {
omap2_gpio_prepare_for_idle(per_next_state);
-   if (per_next_state == PWRDM_POWER_OFF) {
-   if (core_next_state == PWRDM_POWER_ON) {
-   per_next_state = PWRDM_POWER_RET;
-   pwrdm_set_next_pwrst(per_pwrdm, per_next_state);
-   per_state_modified = 1;
-   } else
-   omap3_per_save_context();
-   }
+   if (per_next_state == PWRDM_POWER_OFF)
+   omap3_per_save_context();
omap_uart_prepare_idle(2);
}
 
-   if (pwrdm_read_pwrst(cam_pwrdm) == PWRDM_POWER_ON)
-   omap2_clkdm_deny_idle(mpu_pwrdm-pwrdm_clkdms[0]);
-
/*
 * Disable smartreflex before entering WFI.
 * Only needed if we are going to enter retention or off.
@@ -553,8 +542,6 @@ void omap_sram_idle(void)
}
omap2_gpio_resume_after_idle();
omap_uart_resume_idle(2);
-   if (per_state_modified)
-   pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
}
 
/* Disable IO-PAD and IO-CHAIN wakeup */
@@ -1171,7 +1158,6 @@ static int __init omap3_pm_init(void)
neon_pwrdm = pwrdm_lookup(neon_pwrdm);
per_pwrdm = pwrdm_lookup(per_pwrdm);
core_pwrdm = pwrdm_lookup(core_pwrdm);
-   cam_pwrdm = pwrdm_lookup(cam_pwrdm);
 
omap_push_sram_idle();
 #ifdef CONFIG_SUSPEND
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv3 1/6] OMAP: Powerdomains: Add support for INACTIVE state on pwrdm level

2010-01-15 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Currently only ON, RET and OFF are supported, and ON is arguably broken as it
allows the powerdomain to enter INACTIVE state unless idle is prevented.
Now, pwrdm code prevents idle if ON is selected, and also adds support for
INACTIVE. This simplifies the control needed inside sleep code.

This patch also requires caching of next power state inside powerdomain code,
as INACTIVE is not directly supported by hardware. Next powerstate is thus
now stored for each powerdomain in next_state.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/powerdomain.c |   32 
 arch/arm/mach-omap2/powerdomains34xx.h|   26 ++--
 arch/arm/plat-omap/include/plat/powerdomain.h |4 +++
 3 files changed, 43 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 26b3f3e..a08d596 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -110,8 +110,8 @@ static struct powerdomain *_pwrdm_deps_lookup(struct 
powerdomain *pwrdm,
 static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 {
 
-   int prev;
-   int state;
+   u8 prev;
+   u8 state;
 
if (pwrdm == NULL)
return -EINVAL;
@@ -218,7 +218,9 @@ int pwrdm_register(struct powerdomain *pwrdm)
 
pr_debug(powerdomain: registered %s\n, pwrdm-name);
ret = 0;
-
+   pwrdm-next_state =
+   prm_read_mod_bits_shift(pwrdm-prcm_offs, PM_PWSTCTRL,
+   OMAP_POWERSTATE_MASK);
 pr_unlock:
write_unlock_irqrestore(pwrdm_rwlock, flags);
 
@@ -699,19 +701,38 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
  */
 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 {
+   u8 prg_pwrst;
+
if (!pwrdm)
return -EINVAL;
 
+   if (pwrdm-next_state == pwrst)
+   return 0;
+
if (!(pwrdm-pwrsts  (1  pwrst)))
return -EINVAL;
 
pr_debug(powerdomain: setting next powerstate for %s to %0x\n,
 pwrdm-name, pwrst);
 
+   /* INACTIVE is reserved, so we program pwrdm as ON */
+   if (pwrst == PWRDM_POWER_INACTIVE)
+   prg_pwrst = PWRDM_POWER_ON;
+   else
+   prg_pwrst = pwrst;
+
prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
-(pwrst  OMAP_POWERSTATE_SHIFT),
+(prg_pwrst  OMAP_POWERSTATE_SHIFT),
 pwrdm-prcm_offs, PM_PWSTCTRL);
 
+   /* If next state is ON, prevent idle */
+   if (pwrst == PWRDM_POWER_ON)
+   omap2_clkdm_deny_idle(pwrdm-pwrdm_clkdms[0]);
+   else
+   omap2_clkdm_allow_idle(pwrdm-pwrdm_clkdms[0]);
+
+   pwrdm-next_state = pwrst;
+
return 0;
 }
 
@@ -728,8 +749,7 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
if (!pwrdm)
return -EINVAL;
 
-   return prm_read_mod_bits_shift(pwrdm-prcm_offs, PM_PWSTCTRL,
-   OMAP_POWERSTATE_MASK);
+   return pwrdm-next_state;
 }
 
 /**
diff --git a/arch/arm/mach-omap2/powerdomains34xx.h 
b/arch/arm/mach-omap2/powerdomains34xx.h
index 588f7e0..f50a3f2 100644
--- a/arch/arm/mach-omap2/powerdomains34xx.h
+++ b/arch/arm/mach-omap2/powerdomains34xx.h
@@ -165,7 +165,7 @@ static struct powerdomain iva2_pwrdm = {
.omap_chip= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.dep_bit  = OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
.wkdep_srcs   = iva2_wkdeps,
-   .pwrsts   = PWRSTS_OFF_RET_ON,
+   .pwrsts   = PWRSTS_OFF_RET_INA_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks= 4,
.pwrsts_mem_ret   = {
@@ -188,7 +188,7 @@ static struct powerdomain mpu_34xx_pwrdm = {
.omap_chip= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.dep_bit  = OMAP3430_EN_MPU_SHIFT,
.wkdep_srcs   = mpu_34xx_wkdeps,
-   .pwrsts   = PWRSTS_OFF_RET_ON,
+   .pwrsts   = PWRSTS_OFF_RET_INA_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.flags= PWRDM_HAS_MPU_QUIRK,
.banks= 1,
@@ -207,7 +207,7 @@ static struct powerdomain core_34xx_pre_es3_1_pwrdm = {
.omap_chip= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
   CHIP_IS_OMAP3430ES2 |
   CHIP_IS_OMAP3430ES3_0),
-   .pwrsts   = PWRSTS_OFF_RET_ON,
+   .pwrsts   = PWRSTS_OFF_RET_INA_ON,
.dep_bit  = OMAP3430_EN_CORE_SHIFT,
.banks= 2,
.pwrsts_mem_ret   = {
@@ -215,8 +215,8 @@ static struct powerdomain core_34xx_pre_es3_1_pwrdm = {
[1] = PWRSTS_OFF_RET,/* MEM2RETSTATE */
},
.pwrsts_mem_on= {
-   [0

[PATCHv4 5/8] OMAP3: PM: Removed pwrdm state hacking from omap_sram_idle

2010-01-22 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Following hacks will be moved inside cpuidle in subsequent patch:

- CAM domain prevents idle completely
- PER should not go OFF if core remains active

This simplifies the design and allows cpuidle to keep better track of which
power states system will actually enter.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/pm34xx.c |   18 ++
 1 files changed, 2 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index dceb18f..f7bb5c7 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -93,7 +93,6 @@ static int (*_omap_save_secure_sram)(u32 *addr);
 
 static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
-static struct powerdomain *cam_pwrdm;
 
 static struct prm_setup_vc prm_setup = {
.clksetup = 0xff,
@@ -373,7 +372,6 @@ void omap_sram_idle(void)
int core_next_state = PWRDM_POWER_ON;
int core_prev_state, per_prev_state;
u32 sdrc_pwr = 0;
-   int per_state_modified = 0;
 
if (!_omap_sram_idle)
return;
@@ -411,20 +409,11 @@ void omap_sram_idle(void)
core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
if (per_next_state  PWRDM_POWER_ON) {
omap2_gpio_prepare_for_idle(per_next_state);
-   if (per_next_state == PWRDM_POWER_OFF) {
-   if (core_next_state == PWRDM_POWER_ON) {
-   per_next_state = PWRDM_POWER_RET;
-   pwrdm_set_next_pwrst(per_pwrdm, per_next_state);
-   per_state_modified = 1;
-   } else
-   omap3_per_save_context();
-   }
+   if (per_next_state == PWRDM_POWER_OFF)
+   omap3_per_save_context();
omap_uart_prepare_idle(2);
}
 
-   if (pwrdm_read_pwrst(cam_pwrdm) == PWRDM_POWER_ON)
-   omap2_clkdm_deny_idle(mpu_pwrdm-pwrdm_clkdms[0]);
-
/*
 * Disable smartreflex before entering WFI.
 * Only needed if we are going to enter retention or off.
@@ -554,8 +543,6 @@ void omap_sram_idle(void)
}
omap2_gpio_resume_after_idle();
omap_uart_resume_idle(2);
-   if (per_state_modified)
-   pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
}
 
/* Disable IO-PAD and IO-CHAIN wakeup */
@@ -1175,7 +1162,6 @@ static int __init omap3_pm_init(void)
neon_pwrdm = pwrdm_lookup(neon_pwrdm);
per_pwrdm = pwrdm_lookup(per_pwrdm);
core_pwrdm = pwrdm_lookup(core_pwrdm);
-   cam_pwrdm = pwrdm_lookup(cam_pwrdm);
 
omap_push_sram_idle();
 #ifdef CONFIG_SUSPEND
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv4 8/8] OMAP3: CPUidle: Added peripheral pwrdm checks into bm check

2010-01-22 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 |  118 ++--
 1 files changed, 111 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 4a81ef1..dad64a9 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
@@ -92,6 +93,22 @@ static int omap3_idle_bm_check(void)
 }
 
 /**
+ * pwrdm_get_idle_state - Get the power state a pwrdm will enter during idle
+ * @pwrdm: powerdomain to check state for
+ *
+ * Checks if the powerdomain can enter idle or not, if yes, will return
+ * the programmed target state for the domain. Otherwise will indicate
+ * that the domain will stay on.
+ * Returns the power state the pwrdm will enter.
+ */
+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
  * @state: The target state to be programmed
@@ -153,14 +170,94 @@ 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

[PATCHv4 4/8] OMAP3: CPUidle: Fixed support for ON / INACTIVE states

2010-01-22 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

New powerdomain code support for INACTIVE state removes the need to control
clockdomains directly from cpuidle. Also, cpuidle state definitions can now
directly support ON / INACTIVE simplifying the implementation.

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

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 1cfa5a6..4a81ef1 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -91,20 +91,6 @@ static int omap3_idle_bm_check(void)
return 0;
 }
 
-static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
-{
-   omap2_clkdm_allow_idle(clkdm);
-   return 0;
-}
-
-static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
-{
-   omap2_clkdm_deny_idle(clkdm);
-   return 0;
-}
-
 /**
  * omap3_enter_idle - Programs OMAP3 to enter the specified state
  * @dev: cpuidle device
@@ -141,19 +127,9 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
if (omap_irq_pending() || need_resched())
goto return_sleep_time;
 
-   if (cx-type == OMAP3_STATE_C1) {
-   pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
-   pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
-   }
-
/* Execute ARM wfi */
omap_sram_idle();
 
-   if (cx-type == OMAP3_STATE_C1) {
-   pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
-   pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
-   }
-
 return_sleep_time:
getnstimeofday(ts_postidle);
ts_idle = timespec_sub(ts_postidle, ts_preidle);
@@ -246,8 +222,8 @@ void omap_init_power_states(void)
cpuidle_params_table[OMAP3_STATE_C2].wake_latency;
omap3_power_states[OMAP3_STATE_C2].threshold =
cpuidle_params_table[OMAP3_STATE_C2].threshold;
-   omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON;
-   omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_INACTIVE;
+   omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID;
 
/* C3 . MPU CSWR + Core inactive */
@@ -261,7 +237,7 @@ void omap_init_power_states(void)
omap3_power_states[OMAP3_STATE_C3].threshold =
cpuidle_params_table[OMAP3_STATE_C3].threshold;
omap3_power_states[OMAP3_STATE_C3].mpu_state = PWRDM_POWER_RET;
-   omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
 
@@ -276,7 +252,7 @@ void omap_init_power_states(void)
omap3_power_states[OMAP3_STATE_C4].threshold =
cpuidle_params_table[OMAP3_STATE_C4].threshold;
omap3_power_states[OMAP3_STATE_C4].mpu_state = PWRDM_POWER_OFF;
-   omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
 
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv4 1/8] OMAP3: Clockdomain: Added API for checking if HWSUP is enabled

2010-01-22 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

omap2_clkdm_get_hwsup(clkdm) can be used to check if automatic HW
transitions for the domain are enabled or not. This is needed for the
powerdomain code that adds support for INACTIVE state, as it needs to
disable HWSUP on the fly for ON state, and re-enable it after returning
to some other state.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/clockdomain.c |   27 +
 arch/arm/plat-omap/include/plat/clockdomain.h |1 +
 2 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c 
b/arch/arm/mach-omap2/clockdomain.c
index dd285f0..728d1b0 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -472,6 +472,33 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm)
return 0;
 }
 
+/*
+ * omap2_clkdm_get_hwsup - get the hwsup idle transition bit
+ * @clkdm: struct clockdomain *
+ *
+ * Checks whether hardware is allowed to switch the clockdomain
+ * automatically into active or idle states. Returns 1 if yes,
+ * 0 otherwise.
+ */
+int omap2_clkdm_get_hwsup(struct clockdomain *clkdm)
+{
+   u32 v;
+
+   if (cpu_is_omap24xx())
+   v = OMAP24XX_CLKSTCTRL_ENABLE_AUTO;
+   else if (cpu_is_omap34xx())
+   v = OMAP34XX_CLKSTCTRL_ENABLE_AUTO;
+   else
+   BUG();
+
+   if ((cm_read_mod_reg(clkdm-pwrdm.ptr-prcm_offs, CM_CLKSTCTRL) 
+   clkdm-clktrctrl_mask) ==
+   (v  __ffs(clkdm-clktrctrl_mask)))
+   return 1;
+
+   return 0;
+}
+
 /**
  * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm
  * @clkdm: struct clockdomain *
diff --git a/arch/arm/plat-omap/include/plat/clockdomain.h 
b/arch/arm/plat-omap/include/plat/clockdomain.h
index eb73482..9127459 100644
--- a/arch/arm/plat-omap/include/plat/clockdomain.h
+++ b/arch/arm/plat-omap/include/plat/clockdomain.h
@@ -99,6 +99,7 @@ int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void 
*user),
void *user);
 struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm);
 
+int omap2_clkdm_get_hwsup(struct clockdomain *clkdm);
 void omap2_clkdm_allow_idle(struct clockdomain *clkdm);
 void omap2_clkdm_deny_idle(struct clockdomain *clkdm);
 
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv4 2/8] OMAP: Powerdomains: Add support for INACTIVE state on pwrdm level

2010-01-22 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Currently only ON, RET and OFF are supported, and ON is arguably broken as it
allows the powerdomain to enter INACTIVE state unless idle is prevented.
Now, pwrdm code prevents idle if ON is selected and hardware supervised
mode for the underlying clockdomain is enabled, and also adds support for
INACTIVE. This simplifies the control needed inside sleep code.

This patch also requires caching of next power state inside powerdomain code,
as INACTIVE is not directly supported by hardware. Next powerstate is thus
now stored for each powerdomain in next_state.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/powerdomain.c |   37 +
 arch/arm/mach-omap2/powerdomains34xx.h|   18 ++--
 arch/arm/plat-omap/include/plat/powerdomain.h |5 +++
 3 files changed, 45 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 26b3f3e..bdfbbea 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -110,8 +110,8 @@ static struct powerdomain *_pwrdm_deps_lookup(struct 
powerdomain *pwrdm,
 static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 {
 
-   int prev;
-   int state;
+   u8 prev;
+   u8 state;
 
if (pwrdm == NULL)
return -EINVAL;
@@ -218,7 +218,9 @@ int pwrdm_register(struct powerdomain *pwrdm)
 
pr_debug(powerdomain: registered %s\n, pwrdm-name);
ret = 0;
-
+   pwrdm-next_state =
+   prm_read_mod_bits_shift(pwrdm-prcm_offs, PM_PWSTCTRL,
+   OMAP_POWERSTATE_MASK);
 pr_unlock:
write_unlock_irqrestore(pwrdm_rwlock, flags);
 
@@ -699,19 +701,43 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
  */
 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 {
+   u8 prg_pwrst;
+
if (!pwrdm)
return -EINVAL;
 
+   if (pwrdm-next_state == pwrst)
+   return 0;
+
if (!(pwrdm-pwrsts  (1  pwrst)))
return -EINVAL;
 
pr_debug(powerdomain: setting next powerstate for %s to %0x\n,
 pwrdm-name, pwrst);
 
+   /* INACTIVE is reserved, so we program pwrdm as ON */
+   if (pwrst == PWRDM_POWER_INACTIVE)
+   prg_pwrst = PWRDM_POWER_ON;
+   else
+   prg_pwrst = pwrst;
+
prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
-(pwrst  OMAP_POWERSTATE_SHIFT),
+(prg_pwrst  OMAP_POWERSTATE_SHIFT),
 pwrdm-prcm_offs, PM_PWSTCTRL);
 
+   /* If next state is ON, prevent idle */
+   if (pwrst == PWRDM_POWER_ON) {
+   if (omap2_clkdm_get_hwsup(pwrdm-pwrdm_clkdms[0])) {
+   omap2_clkdm_deny_idle(pwrdm-pwrdm_clkdms[0]);
+   pwrdm-hwsup_changed = 1;
+   }
+   } else if (pwrdm-hwsup_changed) {
+   omap2_clkdm_allow_idle(pwrdm-pwrdm_clkdms[0]);
+   pwrdm-hwsup_changed = 0;
+   }
+
+   pwrdm-next_state = pwrst;
+
return 0;
 }
 
@@ -728,8 +754,7 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
if (!pwrdm)
return -EINVAL;
 
-   return prm_read_mod_bits_shift(pwrdm-prcm_offs, PM_PWSTCTRL,
-   OMAP_POWERSTATE_MASK);
+   return pwrdm-next_state;
 }
 
 /**
diff --git a/arch/arm/mach-omap2/powerdomains34xx.h 
b/arch/arm/mach-omap2/powerdomains34xx.h
index 588f7e0..7a7d8d3 100644
--- a/arch/arm/mach-omap2/powerdomains34xx.h
+++ b/arch/arm/mach-omap2/powerdomains34xx.h
@@ -165,7 +165,7 @@ static struct powerdomain iva2_pwrdm = {
.omap_chip= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.dep_bit  = OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
.wkdep_srcs   = iva2_wkdeps,
-   .pwrsts   = PWRSTS_OFF_RET_ON,
+   .pwrsts   = PWRSTS_OFF_RET_INA_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks= 4,
.pwrsts_mem_ret   = {
@@ -188,7 +188,7 @@ static struct powerdomain mpu_34xx_pwrdm = {
.omap_chip= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.dep_bit  = OMAP3430_EN_MPU_SHIFT,
.wkdep_srcs   = mpu_34xx_wkdeps,
-   .pwrsts   = PWRSTS_OFF_RET_ON,
+   .pwrsts   = PWRSTS_OFF_RET_INA_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.flags= PWRDM_HAS_MPU_QUIRK,
.banks= 1,
@@ -207,7 +207,7 @@ static struct powerdomain core_34xx_pre_es3_1_pwrdm = {
.omap_chip= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
   CHIP_IS_OMAP3430ES2 |
   CHIP_IS_OMAP3430ES3_0),
-   .pwrsts   = PWRSTS_OFF_RET_ON,
+   .pwrsts   = PWRSTS_OFF_RET_INA_ON,
.dep_bit

[PATCHv4 6/8] OMAP3: Clock: Added IDLEST definitions for SGX

2010-01-22 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Added definitions for OMAP3430ES2_ST_SGX_SHIFT and OMAP3430ES2_ST_SGX_MASK
as these were missing.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/cm-regbits-34xx.h |4 
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h 
b/arch/arm/mach-omap2/cm-regbits-34xx.h
index a76e835..d18da47 100644
--- a/arch/arm/mach-omap2/cm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-34xx.h
@@ -379,6 +379,10 @@
 #define OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_SHIFT 1
 #define OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_MASK  (1  1)
 
+/* CM_IDLEST_SGX */
+#define OMAP3430ES2_ST_SGX_SHIFT   1
+#define OMAP3430ES2_ST_SGX_MASK(1  1)
+
 /* CM_ICLKEN_SGX */
 #define OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_SHIFT 0
 #define OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_MASK  (1  0)
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv4 3/8] OMAP3: PM: Added support for INACTIVE and ON states for powerdomains

2010-01-22 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Previously omap_sram_idle() did not know about the difference between ON and
INACTIVE states, which complicated the state handling in these cases. Now,
the following changes are done in the idle logic:

- Check for IO-chain arming is changed to reflect desired state (RET)
- UART clocks will be disabled if we attempt to enter INACTIVE (this allows
  the state change to actually happen)

Also, due to changes to pwrdm_set_next_pwrst() the behavior of
set_pwrdm_state() is modified accordingly.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/pm34xx.c |   29 ++---
 1 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 190f25c..dceb18f 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -386,6 +386,7 @@ void omap_sram_idle(void)
mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
switch (mpu_next_state) {
case PWRDM_POWER_ON:
+   case PWRDM_POWER_INACTIVE:
case PWRDM_POWER_RET:
/* No need to save context */
save_state = 0;
@@ -452,9 +453,11 @@ void omap_sram_idle(void)
OMAP3430_GR_MOD,
OMAP3_PRM_VOLTCTRL_OFFSET);
}
-   /* Enable IO-PAD and IO-CHAIN wakeups */
-   prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
-   omap3_enable_io_chain();
+   if (core_next_state = PWRDM_POWER_RET) {
+   /* Enable IO-PAD and IO-CHAIN wakeups */
+   prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
+   omap3_enable_io_chain();
+   }
}
omap3_intc_prepare_idle();
 
@@ -556,15 +559,13 @@ void omap_sram_idle(void)
}
 
/* Disable IO-PAD and IO-CHAIN wakeup */
-   if (core_next_state  PWRDM_POWER_ON) {
+   if (core_next_state = PWRDM_POWER_RET) {
prm_clear_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
omap3_disable_io_chain();
}
 
 
pwrdm_post_transition();
-
-   omap2_clkdm_allow_idle(mpu_pwrdm-pwrdm_clkdms[0]);
 }
 
 int omap3_can_sleep(void)
@@ -582,7 +583,6 @@ int omap3_can_sleep(void)
 int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
 {
u32 cur_state;
-   int sleep_switch = 0;
int ret = 0;
 
if (pwrdm == NULL || IS_ERR(pwrdm))
@@ -598,12 +598,6 @@ int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
if (cur_state == state)
return ret;
 
-   if (pwrdm_read_pwrst(pwrdm)  PWRDM_POWER_ON) {
-   omap2_clkdm_wakeup(pwrdm-pwrdm_clkdms[0]);
-   sleep_switch = 1;
-   pwrdm_wait_transition(pwrdm);
-   }
-
ret = pwrdm_set_next_pwrst(pwrdm, state);
if (ret) {
printk(KERN_ERR Unable to set state of powerdomain: %s\n,
@@ -611,8 +605,13 @@ int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
goto err;
}
 
-   if (sleep_switch) {
-   omap2_clkdm_allow_idle(pwrdm-pwrdm_clkdms[0]);
+   cur_state = pwrdm_read_pwrst(pwrdm);
+   if (cur_state  PWRDM_POWER_ON  cur_state != state) {
+   /* Force wakeup */
+   omap2_clkdm_wakeup(pwrdm-pwrdm_clkdms[0]);
+   pwrdm_wait_transition(pwrdm);
+   if (state  PWRDM_POWER_ON)
+   omap2_clkdm_allow_idle(pwrdm-pwrdm_clkdms[0]);
pwrdm_wait_transition(pwrdm);
pwrdm_state_switch(pwrdm);
}
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv4 7/8] OMAP: Powerdomains: Add support for checking if pwrdm/clkdm can idle

2010-01-22 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

pwrdm_can_idle(pwrdm) will check if the specified powerdomain can enter
idle. This is done by checking all clockdomains under the powerdomain
if they can idle also.

omap2_clkdm_can_idle(clkdm) will check if the specified clockdomain can
enter idle. This checks the functional clocks and idle status bits of the
domain according to following rules:
1) functional clock check
  * get FCLK register content
  * ignore all clocks defined in idle_def.fclk_ignore
  * if any active functional clocks remain, domain can't idle
2) idle status check
  * get IDLEST register content
  * inverse it (any non-idle blocks are now as 1)
  * mask against idle_def.idlest_mask
  * if any bits remain high, domain can't idle

These calls can be used e.g. inside cpuidle to decide which power states
core and mpu should enter during idle, as there are certain dependencies
between wakeup capabilities and reset logic.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/clockdomain.c |   32 
 arch/arm/mach-omap2/clockdomains.h|  106 +
 arch/arm/mach-omap2/powerdomain.c |   25 ++
 arch/arm/plat-omap/include/plat/clockdomain.h |   17 
 arch/arm/plat-omap/include/plat/powerdomain.h |1 +
 5 files changed, 181 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c 
b/arch/arm/mach-omap2/clockdomain.c
index 728d1b0..5665755 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -499,6 +499,38 @@ int omap2_clkdm_get_hwsup(struct clockdomain *clkdm)
return 0;
 }
 
+
+/**
+ * omap2_clkdm_can_idle - check if clockdomain has any active clocks or not
+ * @clkdm: struct clockdomain *
+ *
+ * Checks if the clockdomain has any active clock or not, i.e. whether it
+ * can enter idle. Returns -EINVAL if clkdm is NULL; 0 if unable to idle;
+ * 1 if can idle.
+ */
+int omap2_clkdm_can_idle(struct clockdomain *clkdm)
+{
+   int i;
+
+   if (!clkdm)
+   return -EINVAL;
+
+   for (i = 0; i  clkdm-clk_reg_num; i++) {
+   u32 idlest, fclk;
+
+   fclk = cm_read_mod_reg(clkdm-pwrdm.ptr-prcm_offs,
+   CM_FCLKEN + 4 * i);
+   if (fclk  ~clkdm-idle_def[i].fclk_ignore)
+   return 0;
+
+   idlest = cm_read_mod_reg(clkdm-pwrdm.ptr-prcm_offs,
+   CM_IDLEST + 4 * i);
+   if (~idlest  clkdm-idle_def[i].idlest_mask)
+   return 0;
+   }
+   return 1;
+}
+
 /**
  * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm
  * @clkdm: struct clockdomain *
diff --git a/arch/arm/mach-omap2/clockdomains.h 
b/arch/arm/mach-omap2/clockdomains.h
index c4ee076..91efc60 100644
--- a/arch/arm/mach-omap2/clockdomains.h
+++ b/arch/arm/mach-omap2/clockdomains.h
@@ -167,6 +167,12 @@ static struct clockdomain iva2_clkdm = {
.flags  = CLKDM_CAN_HWSUP_SWSUP,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+   .clk_reg_num= 1,
+   .idle_def   = {
+   [0] = {
+   .idlest_mask = OMAP3430_ST_IVA2,
+   },
+   },
 };
 
 static struct clockdomain gfx_3430es1_clkdm = {
@@ -183,6 +189,12 @@ static struct clockdomain sgx_clkdm = {
.flags  = CLKDM_CAN_HWSUP_SWSUP,
.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
+   .clk_reg_num= 1,
+   .idle_def   = {
+   [0] = {
+   .idlest_mask = OMAP3430ES2_ST_SGX_SHIFT,
+   },
+   },
 };
 
 /*
@@ -206,6 +218,57 @@ static struct clockdomain core_l3_34xx_clkdm = {
.flags  = CLKDM_CAN_HWSUP,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+   .clk_reg_num= 3,
+   .idle_def   = {
+   [0] = {
+   /* UARTs are controlled by idle loop so ignore */
+   .fclk_ignore = OMAP3430_EN_UART2 |
+   OMAP3430_EN_UART1,
+   /*
+* Reason for IDLEST ignores:
+* - SDRC and OMAPCTRL controlled by HW
+* - HSOTGUSB_IDLE bit is autoidled by HW
+*/
+   .idlest_mask =
+   OMAP3430ES2_ST_MMC3_MASK |
+   OMAP3430_ST_ICR_MASK |
+   OMAP3430_ST_AES2_MASK |
+   OMAP3430_ST_SHA12_MASK |
+   OMAP3430_ST_DES2_MASK |
+   OMAP3430_ST_MMC2_MASK |
+   OMAP3430_ST_MMC1_MASK

[PATCH] OMAP3: Serial: Improved sleep logic

2010-02-02 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Only RX interrupt will now kick the sleep prevent timer. In addition, TX
fifo status is checked before disabling clocks, this will prevent occasional
garbage being printed on serial line. Smartidle is also disabled while
entering idle if we have data in the transmit buffer, because having this
enabled will prevent wakeups from the TX interrupt, and this causes
pauses while sending large blocks of data.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/serial.c |   19 +++
 1 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 777e802..e11dfe9 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -317,7 +317,8 @@ static void omap_uart_allow_sleep(struct omap_uart_state 
*uart)
if (!uart-clocked)
return;
 
-   omap_uart_smart_idle_enable(uart, 1);
+   if (serial_read_reg(uart-p, UART_LSR)  UART_LSR_TEMT)
+   omap_uart_smart_idle_enable(uart, 1);
uart-can_sleep = 1;
del_timer(uart-timer);
 }
@@ -335,7 +336,11 @@ void omap_uart_prepare_idle(int num)
 
list_for_each_entry(uart, uart_list, node) {
if (num == uart-num  uart-can_sleep) {
-   omap_uart_disable_clocks(uart);
+   if (serial_read_reg(uart-p, UART_LSR) 
+   UART_LSR_TEMT)
+   omap_uart_disable_clocks(uart);
+   else
+   omap_uart_smart_idle_enable(uart, 0);
return;
}
}
@@ -407,8 +412,14 @@ int omap_uart_can_sleep(void)
 static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
 {
struct omap_uart_state *uart = dev_id;
+   u8 lsr;
 
-   omap_uart_block_sleep(uart);
+   lsr = serial_read_reg(uart-p, UART_LSR);
+   /* Check for receive interrupt */
+   if (lsr  UART_LSR_DR)
+   omap_uart_block_sleep(uart);
+   if (lsr  UART_LSR_TEMT  uart-can_sleep)
+   omap_uart_smart_idle_enable(uart, 1);
 
return IRQ_NONE;
 }
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv5 0/9] Idlestatus patches

2010-02-02 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Improvements compared to previous version:

- Removed hacks from generic powerdomain code, instead added support
  routines for OMAP3, which are used by pm34xx.c and cpuidle34xx.c, these
  support routines only touch mpu, core and neon powerdomains
- Bug fix: comparison in cpuidle fallback loop was incorrect
- Changed peripheral can_idle checks into direct checks for the current
  power state
- Fixed support for off-mode enabling as part of this set, cpuidle now
  selects proper state when off-mode is disabled
- Added support for INACTIVE states for suspend code (mpu, core, neon only)


--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv5 2/9] OMAP3: PM: Added support for INACTIVE and ON states in omap_sram_idle

2010-02-02 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Previously omap_sram_idle() did not know about the difference between ON and
INACTIVE states, which complicated the state handling in these cases. Now,
the following changes are done in the idle logic:

- Check for IO-chain arming is changed to reflect desired state (RET)
- UART clocks will be disabled if we attempt to enter INACTIVE (this allows
  the state change to actually happen)

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/pm34xx.c |   23 ---
 1 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 256ed18..fa9ff9b 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -383,9 +383,10 @@ void omap_sram_idle(void)
pwrdm_clear_all_prev_pwrst(core_pwrdm);
pwrdm_clear_all_prev_pwrst(per_pwrdm);
 
-   mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
+   mpu_next_state = omap3_pwrdm_read_next_pwrst(mpu_pwrdm);
switch (mpu_next_state) {
case PWRDM_POWER_ON:
+   case PWRDM_POWER_INACTIVE:
case PWRDM_POWER_RET:
/* No need to save context */
save_state = 0;
@@ -403,11 +404,11 @@ 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);
+   omap3_pwrdm_set_next_pwrst(neon_pwrdm, mpu_next_state);
 
/* PER */
-   per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
-   core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
+   per_next_state = omap3_pwrdm_read_next_pwrst(per_pwrdm);
+   core_next_state = omap3_pwrdm_read_next_pwrst(core_pwrdm);
if (per_next_state  PWRDM_POWER_ON) {
omap2_gpio_prepare_for_idle(per_next_state);
if (per_next_state == PWRDM_POWER_OFF) {
@@ -452,9 +453,11 @@ void omap_sram_idle(void)
OMAP3430_GR_MOD,
OMAP3_PRM_VOLTCTRL_OFFSET);
}
-   /* Enable IO-PAD and IO-CHAIN wakeups */
-   prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
-   omap3_enable_io_chain();
+   if (core_next_state = PWRDM_POWER_RET) {
+   /* Enable IO-PAD and IO-CHAIN wakeups */
+   prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
+   omap3_enable_io_chain();
+   }
}
omap3_intc_prepare_idle();
 
@@ -556,15 +559,13 @@ void omap_sram_idle(void)
}
 
/* Disable IO-PAD and IO-CHAIN wakeup */
-   if (core_next_state  PWRDM_POWER_ON) {
+   if (core_next_state = PWRDM_POWER_RET) {
prm_clear_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
omap3_disable_io_chain();
}
 
 
pwrdm_post_transition();
-
-   omap2_clkdm_allow_idle(mpu_pwrdm-pwrdm_clkdms[0]);
 }
 
 int omap3_can_sleep(void)
@@ -730,7 +731,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 = omap3_pwrdm_read_next_pwrst(pwrst-pwrdm);
/* Set ones wanted by suspend */
list_for_each_entry(pwrst, pwrst_list, node) {
if (set_pwrdm_state(pwrst-pwrdm, pwrst-next_state))
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv5 1/9] OMAP3: PM: Added support functions for omap3 pwrdm handling

2010-02-02 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Added omap3_pwrdm_set_next_pwrst and omap3_pwrdm_read_next_pwrst. These
functions add support for INACTIVE and ON states to the standard OMAP
powerdomain functions, and add caching logic for the next state. These
functions are used in subsequent patches to simplify the logic of the idle
loop.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/pm.h |2 +
 arch/arm/mach-omap2/pm34xx.c |   60 +-
 2 files changed, 61 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 75aa685..1d9a740 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -67,6 +67,8 @@ static inline void omap3_pm_init_vc(struct prm_setup_vc 
*setup_vc)
 
 extern int omap3_pm_get_suspend_state(struct powerdomain *pwrdm);
 extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state);
+extern int omap3_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
+extern int omap3_pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
 
 extern u32 wakeup_timer_seconds;
 extern struct omap_dm_timer *gptimer_wakeup;
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 190f25c..256ed18 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -576,6 +576,64 @@ int omap3_can_sleep(void)
return 1;
 }
 
+struct powerdomain_data {
+   u8 next_state;
+   u8 init_done;
+};
+
+static struct powerdomain_data mpu_pwrdm_data;
+static struct powerdomain_data core_pwrdm_data;
+static struct powerdomain_data neon_pwrdm_data;
+
+static struct powerdomain_data *get_pwrdm_data(struct powerdomain *pwrdm)
+{
+   if (pwrdm == mpu_pwrdm)
+   return mpu_pwrdm_data;
+   else if (pwrdm == core_pwrdm)
+   return core_pwrdm_data;
+   else if (pwrdm == neon_pwrdm)
+   return neon_pwrdm_data;
+   return NULL;
+}
+
+int omap3_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
+{
+   struct powerdomain_data *data = get_pwrdm_data(pwrdm);
+   u8 prg_pwrst;
+
+   if (!data)
+   return pwrdm_set_next_pwrst(pwrdm, pwrst);
+
+   if (!data-init_done)
+   data-init_done = 1;
+   else if (data-next_state == pwrst)
+   return 0;
+
+   if (pwrst == PWRDM_POWER_INACTIVE)
+   prg_pwrst = PWRDM_POWER_ON;
+   else
+   prg_pwrst = pwrst;
+
+   pwrdm_set_next_pwrst(pwrdm, prg_pwrst);
+
+   if (pwrst == PWRDM_POWER_ON)
+   omap2_clkdm_deny_idle(pwrdm-pwrdm_clkdms[0]);
+   else
+   omap2_clkdm_allow_idle(pwrdm-pwrdm_clkdms[0]);
+
+   data-next_state = pwrst;
+   return 0;
+}
+
+int omap3_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
+{
+   struct powerdomain_data *data = get_pwrdm_data(pwrdm);
+
+   if (!data || !data-init_done)
+   return pwrdm_read_next_pwrst(pwrdm);
+   return data-next_state;
+}
+
 /* This sets pwrdm state (other than mpu  core. Currently only ON 
  * RET are supported. Function is assuming that clkdm doesn't have
  * hw_sup mode enabled. */
@@ -604,7 +662,7 @@ int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
pwrdm_wait_transition(pwrdm);
}
 
-   ret = pwrdm_set_next_pwrst(pwrdm, state);
+   ret = omap3_pwrdm_set_next_pwrst(pwrdm, state);
if (ret) {
printk(KERN_ERR Unable to set state of powerdomain: %s\n,
   pwrdm-name);
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv5 6/9] OMAP: Powerdomains: Add support for checking if pwrdm/clkdm can idle

2010-02-02 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

pwrdm_can_idle(pwrdm) will check if the specified powerdomain can enter
idle. This is done by checking all clockdomains under the powerdomain
if they can idle also.

omap2_clkdm_can_idle(clkdm) will check if the specified clockdomain can
enter idle. This checks the functional clocks and idle status bits of the
domain according to following rules:
1) functional clock check
  * get FCLK register content
  * ignore all clocks defined in idle_def.fclk_ignore
  * if any active functional clocks remain, domain can't idle
2) idle status check
  * get IDLEST register content
  * inverse it (any non-idle blocks are now as 1)
  * mask against idle_def.idlest_mask
  * if any bits remain high, domain can't idle

These calls can be used e.g. inside cpuidle to decide which power states
core and mpu should enter during idle, as there are certain dependencies
between wakeup capabilities and reset logic.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/clockdomain.c |   32 
 arch/arm/mach-omap2/clockdomains.h|  106 +
 arch/arm/mach-omap2/powerdomain.c |   25 ++
 arch/arm/plat-omap/include/plat/clockdomain.h |   17 
 arch/arm/plat-omap/include/plat/powerdomain.h |1 +
 5 files changed, 181 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c 
b/arch/arm/mach-omap2/clockdomain.c
index dd285f0..63020d4 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -472,6 +472,38 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm)
return 0;
 }
 
+
+/**
+ * omap2_clkdm_can_idle - check if clockdomain has any active clocks or not
+ * @clkdm: struct clockdomain *
+ *
+ * Checks if the clockdomain has any active clock or not, i.e. whether it
+ * can enter idle. Returns -EINVAL if clkdm is NULL; 0 if unable to idle;
+ * 1 if can idle.
+ */
+int omap2_clkdm_can_idle(struct clockdomain *clkdm)
+{
+   int i;
+
+   if (!clkdm)
+   return -EINVAL;
+
+   for (i = 0; i  clkdm-clk_reg_num; i++) {
+   u32 idlest, fclk;
+
+   fclk = cm_read_mod_reg(clkdm-pwrdm.ptr-prcm_offs,
+   CM_FCLKEN + 4 * i);
+   if (fclk  ~clkdm-idle_def[i].fclk_ignore)
+   return 0;
+
+   idlest = cm_read_mod_reg(clkdm-pwrdm.ptr-prcm_offs,
+   CM_IDLEST + 4 * i);
+   if (~idlest  clkdm-idle_def[i].idlest_mask)
+   return 0;
+   }
+   return 1;
+}
+
 /**
  * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm
  * @clkdm: struct clockdomain *
diff --git a/arch/arm/mach-omap2/clockdomains.h 
b/arch/arm/mach-omap2/clockdomains.h
index c4ee076..65e2f69 100644
--- a/arch/arm/mach-omap2/clockdomains.h
+++ b/arch/arm/mach-omap2/clockdomains.h
@@ -167,6 +167,12 @@ static struct clockdomain iva2_clkdm = {
.flags  = CLKDM_CAN_HWSUP_SWSUP,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+   .clk_reg_num= 1,
+   .idle_def   = {
+   [0] = {
+   .idlest_mask = OMAP3430_ST_IVA2,
+   },
+   },
 };
 
 static struct clockdomain gfx_3430es1_clkdm = {
@@ -183,6 +189,12 @@ static struct clockdomain sgx_clkdm = {
.flags  = CLKDM_CAN_HWSUP_SWSUP,
.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
+   .clk_reg_num= 1,
+   .idle_def   = {
+   [0] = {
+   .idlest_mask = OMAP3430ES2_ST_SGX_SHIFT,
+   },
+   },
 };
 
 /*
@@ -206,6 +218,57 @@ static struct clockdomain core_l3_34xx_clkdm = {
.flags  = CLKDM_CAN_HWSUP,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+   .clk_reg_num= 3,
+   .idle_def   = {
+   [0] = {
+   /* UARTs are controlled by idle loop so ignore */
+   .fclk_ignore = OMAP3430_EN_UART2 |
+   OMAP3430_EN_UART1,
+   /*
+* Reason for IDLEST ignores:
+* - SDRC and OMAPCTRL controlled by HW
+* - HSOTGUSB_IDLE bit is autoidled by HW
+* - MAILBOX is controlled by HW
+*/
+   .idlest_mask =
+   OMAP3430ES2_ST_MMC3_MASK |
+   OMAP3430_ST_ICR_MASK |
+   OMAP3430_ST_AES2_MASK |
+   OMAP3430_ST_SHA12_MASK |
+   OMAP3430_ST_DES2_MASK |
+   OMAP3430_ST_MMC2_MASK

[PATCHv5 3/9] OMAP3: CPUidle: Fixed support for ON / INACTIVE states

2010-02-02 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

New powerdomain support code for INACTIVE state removes the need to control
clockdomains directly from cpuidle. Also, cpuidle state definitions can now
directly support ON / INACTIVE simplifying the implementation.

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

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 1cfa5a6..86f580b 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -91,20 +91,6 @@ static int omap3_idle_bm_check(void)
return 0;
 }
 
-static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
-{
-   omap2_clkdm_allow_idle(clkdm);
-   return 0;
-}
-
-static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
-{
-   omap2_clkdm_deny_idle(clkdm);
-   return 0;
-}
-
 /**
  * omap3_enter_idle - Programs OMAP3 to enter the specified state
  * @dev: cpuidle device
@@ -135,25 +121,15 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
core_state = PWRDM_POWER_RET;
}
 
-   pwrdm_set_next_pwrst(mpu_pd, mpu_state);
-   pwrdm_set_next_pwrst(core_pd, core_state);
+   omap3_pwrdm_set_next_pwrst(mpu_pd, mpu_state);
+   omap3_pwrdm_set_next_pwrst(core_pd, core_state);
 
if (omap_irq_pending() || need_resched())
goto return_sleep_time;
 
-   if (cx-type == OMAP3_STATE_C1) {
-   pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
-   pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
-   }
-
/* Execute ARM wfi */
omap_sram_idle();
 
-   if (cx-type == OMAP3_STATE_C1) {
-   pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
-   pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
-   }
-
 return_sleep_time:
getnstimeofday(ts_postidle);
ts_idle = timespec_sub(ts_postidle, ts_preidle);
@@ -246,8 +222,8 @@ void omap_init_power_states(void)
cpuidle_params_table[OMAP3_STATE_C2].wake_latency;
omap3_power_states[OMAP3_STATE_C2].threshold =
cpuidle_params_table[OMAP3_STATE_C2].threshold;
-   omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON;
-   omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_INACTIVE;
+   omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID;
 
/* C3 . MPU CSWR + Core inactive */
@@ -261,7 +237,7 @@ void omap_init_power_states(void)
omap3_power_states[OMAP3_STATE_C3].threshold =
cpuidle_params_table[OMAP3_STATE_C3].threshold;
omap3_power_states[OMAP3_STATE_C3].mpu_state = PWRDM_POWER_RET;
-   omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
 
@@ -276,7 +252,7 @@ void omap_init_power_states(void)
omap3_power_states[OMAP3_STATE_C4].threshold =
cpuidle_params_table[OMAP3_STATE_C4].threshold;
omap3_power_states[OMAP3_STATE_C4].mpu_state = PWRDM_POWER_OFF;
-   omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
 
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv5 5/9] OMAP3: Clock: Added IDLEST definitions for SGX

2010-02-02 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Added definitions for OMAP3430ES2_ST_SGX_SHIFT and OMAP3430ES2_ST_SGX_MASK
as these were missing.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/cm-regbits-34xx.h |4 
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h 
b/arch/arm/mach-omap2/cm-regbits-34xx.h
index a76e835..d18da47 100644
--- a/arch/arm/mach-omap2/cm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-34xx.h
@@ -379,6 +379,10 @@
 #define OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_SHIFT 1
 #define OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_MASK  (1  1)
 
+/* CM_IDLEST_SGX */
+#define OMAP3430ES2_ST_SGX_SHIFT   1
+#define OMAP3430ES2_ST_SGX_MASK(1  1)
+
 /* CM_ICLKEN_SGX */
 #define OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_SHIFT 0
 #define OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_MASK  (1  0)
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv5 7/9] OMAP3: CPUidle: Added peripheral pwrdm checks into bm check

2010-02-02 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 |  102 ++---
 1 files changed, 95 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 86f580b..38bd70c 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;
+static struct powerdomain *mpu_pd, *core_pd, *per_pd, *iva2_pd;
+static struct powerdomain *sgx_pd, *usb_pd, *cam_pd, *dss_pd;
 
 /*
  * The latencies/thresholds for various C states have
@@ -153,14 +154,94 @@ 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_read_pwrst(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 = omap3_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_read_pwrst(dss_pd);
+   iva2_state = pwrdm_read_pwrst(iva2_pd);
+   sgx_state = pwrdm_read_pwrst(sgx_pd);
+   usb_state = pwrdm_read_pwrst(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)
+   new_core_state = PWRDM_POWER_RET;
+   }
+
+   /* Fallback to new target core state */
+   while (cx-core_state  new_core_state) {
+   state--;
+   cx = cpuidle_get_statedata(state);
+   }
+   new_state = state;
+
+   /* Are we changing PER target

[PATCHv5 9/9] OMAP3: PM: Added support for suspending to INACTIVE state

2010-02-02 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

With the new support functions this is now possible. Suspending to INACTIVE
is useful for testing purposes.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/pm34xx.c |   11 ++-
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 7946b70..b0911f2 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -633,11 +633,12 @@ int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
if (pwrdm == NULL || IS_ERR(pwrdm))
return -EINVAL;
 
-   while (!(pwrdm-pwrsts  (1  state))) {
-   if (state == PWRDM_POWER_OFF)
-   return ret;
-   state--;
-   }
+   if (state != PWRDM_POWER_INACTIVE)
+   while (!(pwrdm-pwrsts  (1  state))) {
+   if (state == PWRDM_POWER_OFF)
+   return ret;
+   state--;
+   }
 
cur_state = pwrdm_read_next_pwrst(pwrdm);
if (cur_state == state)
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv5 4/9] OMAP3: PM: Removed pwrdm state hacking from omap_sram_idle

2010-02-02 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Following hacks will be moved inside cpuidle in subsequent patch:

 - CAM domain prevents idle completely
 - PER should not go OFF if core remains active

This simplifies the design and allows cpuidle to keep better track of which
power states system will actually enter.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/pm34xx.c |   19 ++-
 1 files changed, 2 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index fa9ff9b..7946b70 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -93,7 +93,6 @@ static int (*_omap_save_secure_sram)(u32 *addr);
 
 static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
-static struct powerdomain *cam_pwrdm;
 
 static struct prm_setup_vc prm_setup = {
.clksetup = 0xff,
@@ -373,7 +372,6 @@ void omap_sram_idle(void)
int core_next_state = PWRDM_POWER_ON;
int core_prev_state, per_prev_state;
u32 sdrc_pwr = 0;
-   int per_state_modified = 0;
 
if (!_omap_sram_idle)
return;
@@ -411,20 +409,11 @@ void omap_sram_idle(void)
core_next_state = omap3_pwrdm_read_next_pwrst(core_pwrdm);
if (per_next_state  PWRDM_POWER_ON) {
omap2_gpio_prepare_for_idle(per_next_state);
-   if (per_next_state == PWRDM_POWER_OFF) {
-   if (core_next_state == PWRDM_POWER_ON) {
-   per_next_state = PWRDM_POWER_RET;
-   pwrdm_set_next_pwrst(per_pwrdm, per_next_state);
-   per_state_modified = 1;
-   } else
-   omap3_per_save_context();
-   }
+   if (per_next_state == PWRDM_POWER_OFF)
+   omap3_per_save_context();
omap_uart_prepare_idle(2);
}
 
-   if (pwrdm_read_pwrst(cam_pwrdm) == PWRDM_POWER_ON)
-   omap2_clkdm_deny_idle(mpu_pwrdm-pwrdm_clkdms[0]);
-
/*
 * Disable smartreflex before entering WFI.
 * Only needed if we are going to enter retention or off.
@@ -554,8 +543,6 @@ void omap_sram_idle(void)
}
omap2_gpio_resume_after_idle();
omap_uart_resume_idle(2);
-   if (per_state_modified)
-   pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
}
 
/* Disable IO-PAD and IO-CHAIN wakeup */
@@ -564,7 +551,6 @@ void omap_sram_idle(void)
omap3_disable_io_chain();
}
 
-
pwrdm_post_transition();
 }
 
@@ -1235,7 +1221,6 @@ static int __init omap3_pm_init(void)
neon_pwrdm = pwrdm_lookup(neon_pwrdm);
per_pwrdm = pwrdm_lookup(per_pwrdm);
core_pwrdm = pwrdm_lookup(core_pwrdm);
-   cam_pwrdm = pwrdm_lookup(cam_pwrdm);
 
omap_push_sram_idle();
 #ifdef CONFIG_SUSPEND
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv5 8/9] OMAP3: CPUidle: Fixed off-mode support to fall-back to proper C state

2010-02-02 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

If off-mode is disabled, cpuidle now falls back to proper C state. Previously
the state was just simply hacked inside omap3_enter_idle which resulted
in wrong state residencies to be reported.

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

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 38bd70c..dbb7315 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -115,13 +115,6 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
local_irq_disable();
local_fiq_disable();
 
-   if (!enable_off_mode) {
-   if (mpu_state  PWRDM_POWER_RET)
-   mpu_state = PWRDM_POWER_RET;
-   if (core_state  PWRDM_POWER_RET)
-   core_state = PWRDM_POWER_RET;
-   }
-
omap3_pwrdm_set_next_pwrst(mpu_pd, mpu_state);
omap3_pwrdm_set_next_pwrst(core_pd, core_state);
 
@@ -155,7 +148,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
 {
struct cpuidle_state *new_state = state;
u32 per_state = 0, saved_per_state = 0, cam_state, usb_state;
-   u32 iva2_state, sgx_state, dss_state, new_core_state;
+   u32 iva2_state, sgx_state, dss_state, new_core_state, new_mpu_state;
struct omap3_processor_cx *cx;
int ret;
 
@@ -167,6 +160,14 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
}
cx = cpuidle_get_statedata(state);
new_core_state = cx-core_state;
+   new_mpu_state = cx-mpu_state;
+
+   if (!enable_off_mode) {
+   if (new_mpu_state  PWRDM_POWER_RET)
+   new_mpu_state = PWRDM_POWER_RET;
+   if (new_core_state  PWRDM_POWER_RET)
+   new_core_state = PWRDM_POWER_RET;
+   }
 
/* Check if CORE is active, if yes, fallback to inactive */
if (!pwrdm_can_idle(core_pd))
@@ -221,8 +222,9 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
new_core_state = PWRDM_POWER_RET;
}
 
-   /* Fallback to new target core state */
-   while (cx-core_state  new_core_state) {
+   /* Fallback to new target core/mpu state */
+   while (cx-core_state  new_core_state ||
+  cx-mpu_state  new_mpu_state) {
state--;
cx = cpuidle_get_statedata(state);
}
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] OMAP3: Serial: Improved sleep logic

2010-02-10 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

This patch contains following improvements:
- Only RX interrupt will now kick the sleep prevent timer
- TX fifo status is checked before disabling clocks, this will prevent
  on-going transmission to be cut
- Smartidle is disabled while entering idle if we have data in the transmit
  buffer because having this enabled would prevent wakeups from the TX
  interrupt and this would cause pauses while sending large blocks of data
- Sleep prevent timer is changed to use ktime_get() instead of a jiffy timer
  as jiffy timers are not valid within idle loop (tick scheduler is stopped)
- RX and TX fifos are cleared when clocks are enabled, this will purge the
  first character from RX fifo, which is most likely garbage

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/serial.c |   70 +++---
 1 files changed, 45 insertions(+), 25 deletions(-)

diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 837b347..d7d96ba 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -23,12 +23,15 @@
 #include linux/serial_reg.h
 #include linux/clk.h
 #include linux/io.h
+#include linux/delay.h
 
 #include plat/common.h
 #include plat/board.h
 #include plat/clock.h
 #include plat/control.h
 
+#include asm/div64.h
+
 #include prm.h
 #include pm.h
 #include prm-regbits-34xx.h
@@ -36,13 +39,13 @@
 #define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV0x52
 #define UART_OMAP_WER  0x17/* Wake-up enable register */
 
-#define DEFAULT_TIMEOUT (5 * HZ)
+#define DEFAULT_TIMEOUT (5LL * NSEC_PER_SEC)
 
 struct omap_uart_state {
int num;
int can_sleep;
-   struct timer_list timer;
-   u32 timeout;
+   ktime_t expire_time;
+   u64 timeout;
 
void __iomem *wk_st;
void __iomem *wk_en;
@@ -231,6 +234,9 @@ static inline void omap_uart_enable_clocks(struct 
omap_uart_state *uart)
clk_enable(uart-fck);
uart-clocked = 1;
omap_uart_restore_context(uart);
+
+   /* Clear RX and TX fifos, as they contain garbage at this point */
+   serial_write_reg(uart-p, UART_FCR, 0xa7);
 }
 
 #ifdef CONFIG_PM
@@ -302,9 +308,7 @@ static void omap_uart_block_sleep(struct omap_uart_state 
*uart)
omap_uart_smart_idle_enable(uart, 0);
uart-can_sleep = 0;
if (uart-timeout)
-   mod_timer(uart-timer, jiffies + uart-timeout);
-   else
-   del_timer(uart-timer);
+   uart-expire_time = ktime_add_ns(ktime_get(), uart-timeout);
 }
 
 static void omap_uart_allow_sleep(struct omap_uart_state *uart)
@@ -317,25 +321,28 @@ static void omap_uart_allow_sleep(struct omap_uart_state 
*uart)
if (!uart-clocked)
return;
 
-   omap_uart_smart_idle_enable(uart, 1);
+   if (serial_read_reg(uart-p, UART_LSR)  UART_LSR_TEMT)
+   omap_uart_smart_idle_enable(uart, 1);
uart-can_sleep = 1;
-   del_timer(uart-timer);
-}
-
-static void omap_uart_idle_timer(unsigned long data)
-{
-   struct omap_uart_state *uart = (struct omap_uart_state *)data;
-
-   omap_uart_allow_sleep(uart);
 }
 
 void omap_uart_prepare_idle(int num)
 {
struct omap_uart_state *uart;
+   ktime_t t;
 
list_for_each_entry(uart, uart_list, node) {
+   if (num == uart-num  !uart-can_sleep) {
+   t = ktime_get();
+   if (t.tv64  uart-expire_time.tv64)
+   uart-can_sleep = 1;
+   }
if (num == uart-num  uart-can_sleep) {
-   omap_uart_disable_clocks(uart);
+   if (serial_read_reg(uart-p, UART_LSR) 
+   UART_LSR_TEMT)
+   omap_uart_disable_clocks(uart);
+   else
+   omap_uart_smart_idle_enable(uart, 0);
return;
}
}
@@ -360,6 +367,7 @@ void omap_uart_resume_idle(int num)
/* Check for normal UART wakeup */
if (__raw_readl(uart-wk_st)  uart-wk_mask)
omap_uart_block_sleep(uart);
+
return;
}
}
@@ -407,8 +415,14 @@ int omap_uart_can_sleep(void)
 static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
 {
struct omap_uart_state *uart = dev_id;
+   u8 lsr;
 
-   omap_uart_block_sleep(uart);
+   lsr = serial_read_reg(uart-p, UART_LSR);
+   /* Check for receive interrupt */
+   if (lsr  UART_LSR_DR)
+   omap_uart_block_sleep(uart);
+   if (lsr  UART_LSR_TEMT  uart-can_sleep)
+   omap_uart_smart_idle_enable(uart, 1);
 
return IRQ_NONE;
 }
@@ -420,9 +434,9 @@ static void omap_uart_idle_init(struct omap_uart_state 
*uart)
 
uart-can_sleep = 0;
uart-timeout

[PATCHv3] OMAP3: Serial: Improved sleep logic

2010-02-11 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

This patch contains following improvements:
- Only RX interrupt will now kick the sleep prevent timer
- TX fifo status is checked before disabling clocks, this will prevent
  on-going transmission to be cut
- Smartidle is disabled while entering idle if we have data in the transmit
  buffer because having this enabled would prevent wakeups from the TX
  interrupt and this would cause pauses while sending large blocks of data
- Sleep prevent timer is changed to use ktime_get() instead of a jiffy timer
  as jiffy timers are not valid within idle loop (tick scheduler is stopped)
- Added RX ignore timer for ignoring the first character received during
  first millisecond of wakeup, this prevents garbage character to be received
  in low sleep states

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/serial.c |   81 -
 1 files changed, 55 insertions(+), 26 deletions(-)

diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 837b347..75ce549 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -23,12 +23,15 @@
 #include linux/serial_reg.h
 #include linux/clk.h
 #include linux/io.h
+#include linux/delay.h
 
 #include plat/common.h
 #include plat/board.h
 #include plat/clock.h
 #include plat/control.h
 
+#include asm/div64.h
+
 #include prm.h
 #include pm.h
 #include prm-regbits-34xx.h
@@ -36,13 +39,14 @@
 #define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV0x52
 #define UART_OMAP_WER  0x17/* Wake-up enable register */
 
-#define DEFAULT_TIMEOUT (5 * HZ)
+#define DEFAULT_TIMEOUT (5LL * NSEC_PER_SEC)
 
 struct omap_uart_state {
int num;
int can_sleep;
-   struct timer_list timer;
-   u32 timeout;
+   ktime_t expire_time;
+   ktime_t garbage_time;
+   u64 timeout;
 
void __iomem *wk_st;
void __iomem *wk_en;
@@ -231,6 +235,9 @@ static inline void omap_uart_enable_clocks(struct 
omap_uart_state *uart)
clk_enable(uart-fck);
uart-clocked = 1;
omap_uart_restore_context(uart);
+
+   /* Set up garbage timer to ignore RX during first 1ms */
+   uart-garbage_time = ktime_add_ns(ktime_get(), NSEC_PER_MSEC);
 }
 
 #ifdef CONFIG_PM
@@ -302,9 +309,7 @@ static void omap_uart_block_sleep(struct omap_uart_state 
*uart)
omap_uart_smart_idle_enable(uart, 0);
uart-can_sleep = 0;
if (uart-timeout)
-   mod_timer(uart-timer, jiffies + uart-timeout);
-   else
-   del_timer(uart-timer);
+   uart-expire_time = ktime_add_ns(ktime_get(), uart-timeout);
 }
 
 static void omap_uart_allow_sleep(struct omap_uart_state *uart)
@@ -317,25 +322,28 @@ static void omap_uart_allow_sleep(struct omap_uart_state 
*uart)
if (!uart-clocked)
return;
 
-   omap_uart_smart_idle_enable(uart, 1);
+   if (serial_read_reg(uart-p, UART_LSR)  UART_LSR_TEMT)
+   omap_uart_smart_idle_enable(uart, 1);
uart-can_sleep = 1;
-   del_timer(uart-timer);
-}
-
-static void omap_uart_idle_timer(unsigned long data)
-{
-   struct omap_uart_state *uart = (struct omap_uart_state *)data;
-
-   omap_uart_allow_sleep(uart);
 }
 
 void omap_uart_prepare_idle(int num)
 {
struct omap_uart_state *uart;
+   ktime_t t;
 
list_for_each_entry(uart, uart_list, node) {
+   if (num == uart-num  !uart-can_sleep) {
+   t = ktime_get();
+   if (t.tv64  uart-expire_time.tv64)
+   uart-can_sleep = 1;
+   }
if (num == uart-num  uart-can_sleep) {
-   omap_uart_disable_clocks(uart);
+   if (serial_read_reg(uart-p, UART_LSR) 
+   UART_LSR_TEMT)
+   omap_uart_disable_clocks(uart);
+   else
+   omap_uart_smart_idle_enable(uart, 0);
return;
}
}
@@ -360,6 +368,7 @@ void omap_uart_resume_idle(int num)
/* Check for normal UART wakeup */
if (__raw_readl(uart-wk_st)  uart-wk_mask)
omap_uart_block_sleep(uart);
+
return;
}
}
@@ -407,10 +416,24 @@ int omap_uart_can_sleep(void)
 static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
 {
struct omap_uart_state *uart = dev_id;
+   u8 lsr;
+   int ret = IRQ_NONE;
 
-   omap_uart_block_sleep(uart);
+   lsr = serial_read_reg(uart-p, UART_LSR);
+   /* Check for receive interrupt */
+   if (lsr  UART_LSR_DR) {
+   omap_uart_block_sleep(uart);
+   if (uart-garbage_time.tv64 
+   ktime_get().tv64  uart-garbage_time.tv64) {
+   serial_read_reg(uart-p, UART_RX

[PATCHv4] OMAP3: Serial: Improved sleep logic

2010-02-12 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

This patch contains following improvements:
- Only RX interrupt will now kick the sleep prevent timer
- TX fifo status is checked before disabling clocks, this will prevent
  on-going transmission to be cut
- Smartidle is now enabled/disabled only while switching clocks, as having
  smartidle enabled while RX/TX prevents any wakeups from being
  received from UART module
- Sleep prevent timer is changed to use ktime_get() instead of a jiffy timer
  as jiffy timers are not valid within idle loop (tick scheduler is stopped)
- Added RX ignore timer for ignoring the first character received during
  first millisecond of wakeup, this prevents garbage character to be receive
  in low sleep states

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/serial.c |   79 +++--
 1 files changed, 52 insertions(+), 27 deletions(-)

diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 5f3035e..4be9ace 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -29,6 +29,8 @@
 #include plat/clock.h
 #include plat/control.h
 
+#include asm/div64.h
+
 #include prm.h
 #include pm.h
 #include prm-regbits-34xx.h
@@ -42,13 +44,14 @@
  * disabled via sysfs. This also causes that any deeper omap sleep states are
  * blocked. 
  */
-#define DEFAULT_TIMEOUT 0
+#define DEFAULT_TIMEOUT (0LL * NSEC_PER_SEC)
 
 struct omap_uart_state {
int num;
int can_sleep;
-   struct timer_list timer;
-   u32 timeout;
+   ktime_t expire_time;
+   ktime_t garbage_time;
+   u64 timeout;
 
void __iomem *wk_st;
void __iomem *wk_en;
@@ -243,6 +246,9 @@ static inline void omap_uart_save_context(struct 
omap_uart_state *uart) {}
 static inline void omap_uart_restore_context(struct omap_uart_state *uart) {}
 #endif /* CONFIG_PM  CONFIG_ARCH_OMAP3 */
 
+static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
+   int enable);
+
 static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
 {
if (uart-clocked)
@@ -250,8 +256,12 @@ static inline void omap_uart_enable_clocks(struct 
omap_uart_state *uart)
 
clk_enable(uart-ick);
clk_enable(uart-fck);
+   omap_uart_smart_idle_enable(uart, 0);
uart-clocked = 1;
omap_uart_restore_context(uart);
+
+   /* Set up garbage timer to ignore RX during first 1ms */
+   uart-garbage_time = ktime_add_ns(ktime_get(), NSEC_PER_MSEC);
 }
 
 #ifdef CONFIG_PM
@@ -263,6 +273,7 @@ static inline void omap_uart_disable_clocks(struct 
omap_uart_state *uart)
 
omap_uart_save_context(uart);
uart-clocked = 0;
+   omap_uart_smart_idle_enable(uart, 1);
clk_disable(uart-ick);
clk_disable(uart-fck);
 }
@@ -320,12 +331,9 @@ static void omap_uart_block_sleep(struct omap_uart_state 
*uart)
 {
omap_uart_enable_clocks(uart);
 
-   omap_uart_smart_idle_enable(uart, 0);
uart-can_sleep = 0;
if (uart-timeout)
-   mod_timer(uart-timer, jiffies + uart-timeout);
-   else
-   del_timer(uart-timer);
+   uart-expire_time = ktime_add_ns(ktime_get(), uart-timeout);
 }
 
 static void omap_uart_allow_sleep(struct omap_uart_state *uart)
@@ -338,16 +346,7 @@ static void omap_uart_allow_sleep(struct omap_uart_state 
*uart)
if (!uart-clocked)
return;
 
-   omap_uart_smart_idle_enable(uart, 1);
uart-can_sleep = 1;
-   del_timer(uart-timer);
-}
-
-static void omap_uart_idle_timer(unsigned long data)
-{
-   struct omap_uart_state *uart = (struct omap_uart_state *)data;
-
-   omap_uart_allow_sleep(uart);
 }
 
 void omap_uart_prepare_idle(int num)
@@ -355,8 +354,14 @@ void omap_uart_prepare_idle(int num)
struct omap_uart_state *uart;
 
list_for_each_entry(uart, uart_list, node) {
+   if (num == uart-num  !uart-can_sleep  uart-timeout)
+   if (ktime_get().tv64  uart-expire_time.tv64)
+   uart-can_sleep = 1;
+
if (num == uart-num  uart-can_sleep) {
-   omap_uart_disable_clocks(uart);
+   if (serial_read_reg(uart-p, UART_LSR) 
+   UART_LSR_TEMT)
+   omap_uart_disable_clocks(uart);
return;
}
}
@@ -404,6 +409,10 @@ int omap_uart_can_sleep(void)
if (!uart-clocked)
continue;
 
+   if (!uart-can_sleep  uart-timeout 
+   ktime_get().tv64  uart-expire_time.tv64)
+   uart-can_sleep = 1;
+
if (!uart-can_sleep) {
can_sleep = 0;
continue;
@@ -428,10 +437,22 @@ int omap_uart_can_sleep(void)
 static irqreturn_t omap_uart_interrupt(int irq, void *dev_id

[PATCHv6 2/9] OMAP3: PM: Added support for INACTIVE and ON states in omap_sram_idle

2010-02-12 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Previously omap_sram_idle() did not know about the difference between ON and
INACTIVE states, which complicated the state handling in these cases. Now,
the following changes are done in the idle logic:

- Check for IO-chain arming is changed to reflect desired state (RET)
- UART clocks will be disabled if we attempt to enter INACTIVE (this allows
  the state change to actually happen)

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/pm34xx.c |   23 ---
 1 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index f20d3d8..c2d80fc 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -383,9 +383,10 @@ void omap_sram_idle(void)
pwrdm_clear_all_prev_pwrst(core_pwrdm);
pwrdm_clear_all_prev_pwrst(per_pwrdm);
 
-   mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
+   mpu_next_state = omap3_pwrdm_read_next_pwrst(mpu_pwrdm);
switch (mpu_next_state) {
case PWRDM_POWER_ON:
+   case PWRDM_POWER_INACTIVE:
case PWRDM_POWER_RET:
/* No need to save context */
save_state = 0;
@@ -403,11 +404,11 @@ 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);
+   omap3_pwrdm_set_next_pwrst(neon_pwrdm, mpu_next_state);
 
/* PER */
-   per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
-   core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
+   per_next_state = omap3_pwrdm_read_next_pwrst(per_pwrdm);
+   core_next_state = omap3_pwrdm_read_next_pwrst(core_pwrdm);
if (per_next_state  PWRDM_POWER_ON) {
omap2_gpio_prepare_for_idle(per_next_state);
if (per_next_state == PWRDM_POWER_OFF) {
@@ -452,9 +453,11 @@ void omap_sram_idle(void)
OMAP3430_GR_MOD,
OMAP3_PRM_VOLTCTRL_OFFSET);
}
-   /* Enable IO-PAD and IO-CHAIN wakeups */
-   prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
-   omap3_enable_io_chain();
+   if (core_next_state = PWRDM_POWER_RET) {
+   /* Enable IO-PAD and IO-CHAIN wakeups */
+   prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
+   omap3_enable_io_chain();
+   }
}
omap3_intc_prepare_idle();
 
@@ -556,15 +559,13 @@ void omap_sram_idle(void)
}
 
/* Disable IO-PAD and IO-CHAIN wakeup */
-   if (core_next_state  PWRDM_POWER_ON) {
+   if (core_next_state = PWRDM_POWER_RET) {
prm_clear_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
omap3_disable_io_chain();
}
 
 
pwrdm_post_transition();
-
-   omap2_clkdm_allow_idle(mpu_pwrdm-pwrdm_clkdms[0]);
 }
 
 int omap3_can_sleep(void)
@@ -730,7 +731,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 = omap3_pwrdm_read_next_pwrst(pwrst-pwrdm);
/* Set ones wanted by suspend */
list_for_each_entry(pwrst, pwrst_list, node) {
if (set_pwrdm_state(pwrst-pwrdm, pwrst-next_state))
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv6 3/9] OMAP3: CPUidle: Fixed support for ON / INACTIVE states

2010-02-12 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

New powerdomain support code for INACTIVE state removes the need to control
clockdomains directly from cpuidle. Also, cpuidle state definitions can now
directly support ON / INACTIVE simplifying the implementation.

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

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 1cfa5a6..86f580b 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -91,20 +91,6 @@ static int omap3_idle_bm_check(void)
return 0;
 }
 
-static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
-{
-   omap2_clkdm_allow_idle(clkdm);
-   return 0;
-}
-
-static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
-{
-   omap2_clkdm_deny_idle(clkdm);
-   return 0;
-}
-
 /**
  * omap3_enter_idle - Programs OMAP3 to enter the specified state
  * @dev: cpuidle device
@@ -135,25 +121,15 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
core_state = PWRDM_POWER_RET;
}
 
-   pwrdm_set_next_pwrst(mpu_pd, mpu_state);
-   pwrdm_set_next_pwrst(core_pd, core_state);
+   omap3_pwrdm_set_next_pwrst(mpu_pd, mpu_state);
+   omap3_pwrdm_set_next_pwrst(core_pd, core_state);
 
if (omap_irq_pending() || need_resched())
goto return_sleep_time;
 
-   if (cx-type == OMAP3_STATE_C1) {
-   pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
-   pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
-   }
-
/* Execute ARM wfi */
omap_sram_idle();
 
-   if (cx-type == OMAP3_STATE_C1) {
-   pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
-   pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
-   }
-
 return_sleep_time:
getnstimeofday(ts_postidle);
ts_idle = timespec_sub(ts_postidle, ts_preidle);
@@ -246,8 +222,8 @@ void omap_init_power_states(void)
cpuidle_params_table[OMAP3_STATE_C2].wake_latency;
omap3_power_states[OMAP3_STATE_C2].threshold =
cpuidle_params_table[OMAP3_STATE_C2].threshold;
-   omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON;
-   omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_INACTIVE;
+   omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID;
 
/* C3 . MPU CSWR + Core inactive */
@@ -261,7 +237,7 @@ void omap_init_power_states(void)
omap3_power_states[OMAP3_STATE_C3].threshold =
cpuidle_params_table[OMAP3_STATE_C3].threshold;
omap3_power_states[OMAP3_STATE_C3].mpu_state = PWRDM_POWER_RET;
-   omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
 
@@ -276,7 +252,7 @@ void omap_init_power_states(void)
omap3_power_states[OMAP3_STATE_C4].threshold =
cpuidle_params_table[OMAP3_STATE_C4].threshold;
omap3_power_states[OMAP3_STATE_C4].mpu_state = PWRDM_POWER_OFF;
-   omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
 
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv6 5/9] OMAP3: Clock: Added IDLEST definitions for SGX

2010-02-12 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Added definitions for OMAP3430ES2_ST_SGX_SHIFT and OMAP3430ES2_ST_SGX_MASK
as these were missing.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/cm-regbits-34xx.h |4 
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h 
b/arch/arm/mach-omap2/cm-regbits-34xx.h
index 6923deb..60f9b16 100644
--- a/arch/arm/mach-omap2/cm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-34xx.h
@@ -379,6 +379,10 @@
 #define OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_SHIFT 1
 #define OMAP3430ES2_CM_FCLKEN_SGX_EN_SGX_MASK  (1  1)
 
+/* CM_IDLEST_SGX */
+#define OMAP3430ES2_ST_SGX_SHIFT   1
+#define OMAP3430ES2_ST_SGX_MASK(1  1)
+
 /* CM_ICLKEN_SGX */
 #define OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_SHIFT 0
 #define OMAP3430ES2_CM_ICLKEN_SGX_EN_SGX_MASK  (1  0)
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv6 4/9] OMAP3: PM: Removed pwrdm state hacking from omap_sram_idle

2010-02-12 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Following hacks will be moved inside cpuidle in subsequent patch:

- CAM domain prevents idle completely
- PER should not go OFF if core remains active

This simplifies the design and allows cpuidle to keep better track of which
power states system will actually enter.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/pm34xx.c |   19 ++-
 1 files changed, 2 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index c2d80fc..cdbedcf 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -93,7 +93,6 @@ static int (*_omap_save_secure_sram)(u32 *addr);
 
 static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
-static struct powerdomain *cam_pwrdm;
 
 static struct prm_setup_vc prm_setup = {
.clksetup = 0xff,
@@ -373,7 +372,6 @@ void omap_sram_idle(void)
int core_next_state = PWRDM_POWER_ON;
int core_prev_state, per_prev_state;
u32 sdrc_pwr = 0;
-   int per_state_modified = 0;
 
if (!_omap_sram_idle)
return;
@@ -411,20 +409,11 @@ void omap_sram_idle(void)
core_next_state = omap3_pwrdm_read_next_pwrst(core_pwrdm);
if (per_next_state  PWRDM_POWER_ON) {
omap2_gpio_prepare_for_idle(per_next_state);
-   if (per_next_state == PWRDM_POWER_OFF) {
-   if (core_next_state == PWRDM_POWER_ON) {
-   per_next_state = PWRDM_POWER_RET;
-   pwrdm_set_next_pwrst(per_pwrdm, per_next_state);
-   per_state_modified = 1;
-   } else
-   omap3_per_save_context();
-   }
+   if (per_next_state == PWRDM_POWER_OFF)
+   omap3_per_save_context();
omap_uart_prepare_idle(2);
}
 
-   if (pwrdm_read_pwrst(cam_pwrdm) == PWRDM_POWER_ON)
-   omap2_clkdm_deny_idle(mpu_pwrdm-pwrdm_clkdms[0]);
-
/*
 * Disable smartreflex before entering WFI.
 * Only needed if we are going to enter retention or off.
@@ -554,8 +543,6 @@ void omap_sram_idle(void)
}
omap2_gpio_resume_after_idle();
omap_uart_resume_idle(2);
-   if (per_state_modified)
-   pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
}
 
/* Disable IO-PAD and IO-CHAIN wakeup */
@@ -564,7 +551,6 @@ void omap_sram_idle(void)
omap3_disable_io_chain();
}
 
-
pwrdm_post_transition();
 }
 
@@ -1239,7 +1225,6 @@ static int __init omap3_pm_init(void)
neon_pwrdm = pwrdm_lookup(neon_pwrdm);
per_pwrdm = pwrdm_lookup(per_pwrdm);
core_pwrdm = pwrdm_lookup(core_pwrdm);
-   cam_pwrdm = pwrdm_lookup(cam_pwrdm);
 
neon_clkdm = clkdm_lookup(neon_clkdm);
mpu_clkdm = clkdm_lookup(mpu_clkdm);
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv6 6/9] OMAP: Powerdomains: Add support for checking if pwrdm/clkdm can idle

2010-02-12 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

pwrdm_can_idle(pwrdm) will check if the specified powerdomain can enter
idle. This is done by checking all clockdomains under the powerdomain
if they can idle also.

omap2_clkdm_can_idle(clkdm) will check if the specified clockdomain can
enter idle. This checks the functional clocks and idle status bits of the
domain according to following rules:
1) functional clock check
  * get FCLK register content
  * ignore all clocks defined in idle_def.fclk_ignore
  * if any active functional clocks remain, domain can't idle
2) idle status check
  * get IDLEST register content
  * inverse it (any non-idle blocks are now as 1)
  * mask against idle_def.idlest_mask
  * if any bits remain high, domain can't idle

These calls can be used e.g. inside cpuidle to decide which power states
core and mpu should enter during idle, as there are certain dependencies
between wakeup capabilities and reset logic.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/clockdomain.c |   32 
 arch/arm/mach-omap2/clockdomains.h|  106 +
 arch/arm/mach-omap2/powerdomain.c |   20 +
 arch/arm/plat-omap/include/plat/clockdomain.h |   17 
 arch/arm/plat-omap/include/plat/powerdomain.h |1 +
 5 files changed, 176 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c 
b/arch/arm/mach-omap2/clockdomain.c
index a38a615..9ebff51 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -867,6 +867,38 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm)
return 0;
 }
 
+
+/**
+ * omap2_clkdm_can_idle - check if clockdomain has any active clocks or not
+ * @clkdm: struct clockdomain *
+ *
+ * Checks if the clockdomain has any active clock or not, i.e. whether it
+ * can enter idle. Returns -EINVAL if clkdm is NULL; 0 if unable to idle;
+ * 1 if can idle.
+ */
+int omap2_clkdm_can_idle(struct clockdomain *clkdm)
+{
+   int i;
+
+   if (!clkdm)
+   return -EINVAL;
+
+   for (i = 0; i  clkdm-clk_reg_num; i++) {
+   u32 idlest, fclk;
+
+   fclk = cm_read_mod_reg(clkdm-pwrdm.ptr-prcm_offs,
+   CM_FCLKEN + 4 * i);
+   if (fclk  ~clkdm-idle_def[i].fclk_ignore)
+   return 0;
+
+   idlest = cm_read_mod_reg(clkdm-pwrdm.ptr-prcm_offs,
+   CM_IDLEST + 4 * i);
+   if (~idlest  clkdm-idle_def[i].idlest_mask)
+   return 0;
+   }
+   return 1;
+}
+
 /**
  * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm
  * @clkdm: struct clockdomain *
diff --git a/arch/arm/mach-omap2/clockdomains.h 
b/arch/arm/mach-omap2/clockdomains.h
index 8fc19ff..5e29de8 100644
--- a/arch/arm/mach-omap2/clockdomains.h
+++ b/arch/arm/mach-omap2/clockdomains.h
@@ -663,6 +663,12 @@ static struct clockdomain iva2_clkdm = {
.wkdep_srcs = iva2_wkdeps,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+   .clk_reg_num= 1,
+   .idle_def   = {
+   [0] = {
+   .idlest_mask = OMAP3430_ST_IVA2,
+   },
+   },
 };
 
 static struct clockdomain gfx_3430es1_clkdm = {
@@ -686,6 +692,12 @@ static struct clockdomain sgx_clkdm = {
.sleepdep_srcs  = gfx_sgx_sleepdeps,
.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
+   .clk_reg_num= 1,
+   .idle_def   = {
+   [0] = {
+   .idlest_mask = OMAP3430ES2_ST_SGX_SHIFT,
+   },
+   },
 };
 
 /*
@@ -717,6 +729,57 @@ static struct clockdomain core_l3_3xxx_clkdm = {
.dep_bit= OMAP3430_EN_CORE_SHIFT,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+   .clk_reg_num= 3,
+   .idle_def   = {
+   [0] = {
+   /* UARTs are controlled by idle loop so ignore */
+   .fclk_ignore = OMAP3430_EN_UART2 |
+   OMAP3430_EN_UART1,
+   /*
+* Reason for IDLEST ignores:
+* - SDRC and OMAPCTRL controlled by HW
+* - HSOTGUSB_IDLE bit is autoidled by HW
+* - MAILBOX is controlled by HW
+*/
+   .idlest_mask =
+   OMAP3430ES2_ST_MMC3_MASK |
+   OMAP3430_ST_ICR_MASK |
+   OMAP3430_ST_AES2_MASK |
+   OMAP3430_ST_SHA12_MASK |
+   OMAP3430_ST_DES2_MASK |
+   OMAP3430_ST_MMC2_MASK

[PATCHv6 9/9] OMAP3: PM: Added support for suspending to INACTIVE state

2010-02-12 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

With the new support functions this is now possible. Suspending to INACTIVE
is useful for testing purposes.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/pm34xx.c |   11 ++-
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index cdbedcf..41d6cc3 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -633,11 +633,12 @@ int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
if (pwrdm == NULL || IS_ERR(pwrdm))
return -EINVAL;
 
-   while (!(pwrdm-pwrsts  (1  state))) {
-   if (state == PWRDM_POWER_OFF)
-   return ret;
-   state--;
-   }
+   if (state != PWRDM_POWER_INACTIVE)
+   while (!(pwrdm-pwrsts  (1  state))) {
+   if (state == PWRDM_POWER_OFF)
+   return ret;
+   state--;
+   }
 
cur_state = pwrdm_read_next_pwrst(pwrdm);
if (cur_state == state)
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv6 7/9] OMAP3: CPUidle: Added peripheral pwrdm checks into bm check

2010-02-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 |  104 ++---
 1 files changed, 97 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 86f580b..914022f 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;
+static struct powerdomain *mpu_pd, *core_pd, *per_pd;
+static struct powerdomain *sgx_pd, *usb_pd, *cam_pd, *dss_pd;
 
 /*
  * The latencies/thresholds for various C states have
@@ -153,14 +154,96 @@ 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_read_pwrst(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 = omap3_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;
+   else
+   per_state = saved_per_state;
+
+   /*
+* 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_read_pwrst(dss_pd);
+   iva2_state = pwrdm_read_pwrst(iva2_pd);
+   sgx_state = pwrdm_read_pwrst(sgx_pd);
+   usb_state = pwrdm_read_pwrst(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)
+   new_core_state = PWRDM_POWER_RET;
+   }
+
+   /* Fallback to new target core state */
+   while (cx-core_state  new_core_state) {
+   state--;
+   cx = cpuidle_get_statedata(state

[PATCHv5] OMAP3: Serial: Improved sleep logic

2010-02-17 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

This patch contains following improvements:
- Only RX interrupt will now kick the sleep prevent timer
- TX fifo status is checked before disabling clocks, this will prevent
  on-going transmission to be cut
- Smartidle is now enabled/disabled only while switching clocks, as having
  smartidle enabled while RX/TX prevents any interrupts from being
  received from UART module
- Sleep prevent timer is changed to use timespec instead of a jiffy timer
  as jiffy timers are not valid within idle loop (tick scheduler is stopped)
- Added RX ignore timer for ignoring the first character received during
  first millisecond of wakeup, this prevents garbage character to be receive
  in low sleep states

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

diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 5f3035e..f49c465 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -29,6 +29,8 @@
 #include plat/clock.h
 #include plat/control.h
 
+#include asm/div64.h
+
 #include prm.h
 #include pm.h
 #include prm-regbits-34xx.h
@@ -42,13 +44,14 @@
  * disabled via sysfs. This also causes that any deeper omap sleep states are
  * blocked. 
  */
-#define DEFAULT_TIMEOUT 0
+#define DEFAULT_TIMEOUT (0LL * NSEC_PER_SEC)
 
 struct omap_uart_state {
int num;
int can_sleep;
-   struct timer_list timer;
-   u32 timeout;
+   struct timespec expire_time;
+   struct timespec garbage_time;
+   u64 timeout;
 
void __iomem *wk_st;
void __iomem *wk_en;
@@ -243,6 +246,9 @@ static inline void omap_uart_save_context(struct 
omap_uart_state *uart) {}
 static inline void omap_uart_restore_context(struct omap_uart_state *uart) {}
 #endif /* CONFIG_PM  CONFIG_ARCH_OMAP3 */
 
+static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
+   int enable);
+
 static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
 {
if (uart-clocked)
@@ -250,8 +256,13 @@ static inline void omap_uart_enable_clocks(struct 
omap_uart_state *uart)
 
clk_enable(uart-ick);
clk_enable(uart-fck);
+   omap_uart_smart_idle_enable(uart, 0);
uart-clocked = 1;
omap_uart_restore_context(uart);
+
+   /* Set up garbage timer to ignore RX during first 1ms */
+   getrawmonotonic(uart-garbage_time);
+   timespec_add_ns(uart-garbage_time, NSEC_PER_MSEC);
 }
 
 #ifdef CONFIG_PM
@@ -263,6 +274,7 @@ static inline void omap_uart_disable_clocks(struct 
omap_uart_state *uart)
 
omap_uart_save_context(uart);
uart-clocked = 0;
+   omap_uart_smart_idle_enable(uart, 1);
clk_disable(uart-ick);
clk_disable(uart-fck);
 }
@@ -320,12 +332,11 @@ static void omap_uart_block_sleep(struct omap_uart_state 
*uart)
 {
omap_uart_enable_clocks(uart);
 
-   omap_uart_smart_idle_enable(uart, 0);
uart-can_sleep = 0;
-   if (uart-timeout)
-   mod_timer(uart-timer, jiffies + uart-timeout);
-   else
-   del_timer(uart-timer);
+   if (uart-timeout) {
+   getrawmonotonic(uart-expire_time);
+   timespec_add_ns(uart-expire_time, uart-timeout);
+   }
 }
 
 static void omap_uart_allow_sleep(struct omap_uart_state *uart)
@@ -338,25 +349,24 @@ static void omap_uart_allow_sleep(struct omap_uart_state 
*uart)
if (!uart-clocked)
return;
 
-   omap_uart_smart_idle_enable(uart, 1);
uart-can_sleep = 1;
-   del_timer(uart-timer);
-}
-
-static void omap_uart_idle_timer(unsigned long data)
-{
-   struct omap_uart_state *uart = (struct omap_uart_state *)data;
-
-   omap_uart_allow_sleep(uart);
 }
 
 void omap_uart_prepare_idle(int num)
 {
struct omap_uart_state *uart;
+   struct timespec t;
 
list_for_each_entry(uart, uart_list, node) {
+   if (num == uart-num  !uart-can_sleep  uart-timeout) {
+   getrawmonotonic(t);
+   if (timespec_compare(t, uart-expire_time)  0)
+   uart-can_sleep = 1;
+   }
if (num == uart-num  uart-can_sleep) {
-   omap_uart_disable_clocks(uart);
+   if (serial_read_reg(uart-p, UART_LSR) 
+   UART_LSR_TEMT)
+   omap_uart_disable_clocks(uart);
return;
}
}
@@ -381,6 +391,7 @@ void omap_uart_resume_idle(int num)
/* Check for normal UART wakeup */
if (__raw_readl(uart-wk_st)  uart-wk_mask)
omap_uart_block_sleep(uart);
+
return;
}
}
@@ -399,11 +410,18 @@ int omap_uart_can_sleep(void

[PATCHv6] OMAP3: Serial: Improved sleep logic

2010-02-25 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

This patch contains following improvements:
- Only RX interrupt will now kick the sleep prevent timer
- TX fifo status is checked before disabling clocks, this will prevent
  on-going transmission to be cut
- Smartidle is now enabled/disabled only while switching clocks, as having
  smartidle enabled while RX/TX prevents any wakeups from being received
  from UART module
- Added workqueue for wakeup checks, as jiffy timer access within the
  idle loop results into skewed timers as jiffy timers are stopped
- Added garbage_timer for ignoring the first character received during
  the first tick after clock enable, this prevents garbage characters to be
  received in low sleep states
- omap_uart_enable_irqs() changed to use enable_irq / disable_irq instead
  of request / free. Using request/free changes the behavior after first
  suspend due to reversed interrupt handler ordering

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/serial.c |   67 +++---
 1 files changed, 56 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 5f3035e..06d18f5 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -23,6 +23,7 @@
 #include linux/serial_reg.h
 #include linux/clk.h
 #include linux/io.h
+#include linux/workqueue.h
 
 #include plat/common.h
 #include plat/board.h
@@ -48,7 +49,10 @@ struct omap_uart_state {
int num;
int can_sleep;
struct timer_list timer;
+   struct timer_list garbage_timer;
+   struct work_struct wakeup_work;
u32 timeout;
+   u8 garbage_ignore;
 
void __iomem *wk_st;
void __iomem *wk_en;
@@ -243,6 +247,11 @@ static inline void omap_uart_save_context(struct 
omap_uart_state *uart) {}
 static inline void omap_uart_restore_context(struct omap_uart_state *uart) {}
 #endif /* CONFIG_PM  CONFIG_ARCH_OMAP3 */
 
+#ifdef CONFIG_PM
+static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
+   int enable);
+#endif
+
 static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
 {
if (uart-clocked)
@@ -252,6 +261,15 @@ static inline void omap_uart_enable_clocks(struct 
omap_uart_state *uart)
clk_enable(uart-fck);
uart-clocked = 1;
omap_uart_restore_context(uart);
+#ifdef CONFIG_PM
+   omap_uart_smart_idle_enable(uart, 0);
+#endif
+
+   /* Set up garbage timer to ignore RX during first jiffy */
+   if (uart-timeout) {
+   mod_timer(uart-garbage_timer, jiffies + 1);
+   uart-garbage_ignore = 1;
+   }
 }
 
 #ifdef CONFIG_PM
@@ -263,6 +281,7 @@ static inline void omap_uart_disable_clocks(struct 
omap_uart_state *uart)
 
omap_uart_save_context(uart);
uart-clocked = 0;
+   omap_uart_smart_idle_enable(uart, 1);
clk_disable(uart-ick);
clk_disable(uart-fck);
 }
@@ -320,7 +339,6 @@ static void omap_uart_block_sleep(struct omap_uart_state 
*uart)
 {
omap_uart_enable_clocks(uart);
 
-   omap_uart_smart_idle_enable(uart, 0);
uart-can_sleep = 0;
if (uart-timeout)
mod_timer(uart-timer, jiffies + uart-timeout);
@@ -338,7 +356,6 @@ static void omap_uart_allow_sleep(struct omap_uart_state 
*uart)
if (!uart-clocked)
return;
 
-   omap_uart_smart_idle_enable(uart, 1);
uart-can_sleep = 1;
del_timer(uart-timer);
 }
@@ -350,13 +367,30 @@ static void omap_uart_idle_timer(unsigned long data)
omap_uart_allow_sleep(uart);
 }
 
+static void omap_uart_garbage_timer(unsigned long data)
+{
+   struct omap_uart_state *uart = (struct omap_uart_state *)data;
+
+   uart-garbage_ignore = 0;
+}
+
+static void omap_uart_wakeup_work(struct work_struct *work)
+{
+   struct omap_uart_state *uart =
+   container_of(work, struct omap_uart_state, wakeup_work);
+
+   omap_uart_block_sleep(uart);
+}
+
 void omap_uart_prepare_idle(int num)
 {
struct omap_uart_state *uart;
 
list_for_each_entry(uart, uart_list, node) {
if (num == uart-num  uart-can_sleep) {
-   omap_uart_disable_clocks(uart);
+   if (serial_read_reg(uart-p, UART_LSR) 
+   UART_LSR_TEMT)
+   omap_uart_disable_clocks(uart);
return;
}
}
@@ -375,12 +409,12 @@ void omap_uart_resume_idle(int num)
u16 p = omap_ctrl_readw(uart-padconf);
 
if (p  OMAP3_PADCONF_WAKEUPEVENT0)
-   omap_uart_block_sleep(uart);
+   schedule_work(uart-wakeup_work);
}
 
/* Check for normal UART wakeup */
if (__raw_readl(uart-wk_st

[PATCHv2 0/11] Misc fixes [for PM branch]

2009-10-23 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

This set is now missing following patches compared to the previous set:

- IVA2 suspend fix
- Dynamic check for core target state
- Block core off when DSS active
- Next state check for IVA2, USB and PER
- USBHOST powerdomain force to sleep after warm reset

Also removed one of the patches Kevin already applied.

I am still trying to figure out what to do with the remaining patches, but
I decided I would send this partial set which I have modified according to
comments already.

-Tero


--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 02/11] OMAP3: Disable Smartreflex before pwrdm enters RET

2009-10-23 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Smartreflex for the corresponding powerdomain (MPU/CORE) must be disabled
before the domain enters retention, otherwise the device may hang. This is
caused by overlapping smartreflex / auto retention command on the voltage
channel resulting in incorrect voltage.

This fix has been confirmed from TI.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/pm34xx.c |   22 +-
 1 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 8353764..6782792 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -403,11 +403,17 @@ void omap_sram_idle(void)
if (pwrdm_read_pwrst(cam_pwrdm) == PWRDM_POWER_ON)
omap2_clkdm_deny_idle(mpu_pwrdm-pwrdm_clkdms[0]);
 
-   /* CORE */
-   if (core_next_state  PWRDM_POWER_ON) {
-   /* Disable smartreflex before entering WFI */
+   /*
+* Disable smartreflex before entering WFI.
+* Only needed if we are going to enter retention or off.
+*/
+   if (mpu_next_state = PWRDM_POWER_RET)
disable_smartreflex(SR1);
+   if (core_next_state = PWRDM_POWER_RET)
disable_smartreflex(SR2);
+
+   /* CORE */
+   if (core_next_state  PWRDM_POWER_ON) {
omap_uart_prepare_idle(0);
omap_uart_prepare_idle(1);
if (core_next_state == PWRDM_POWER_OFF) {
@@ -480,10 +486,16 @@ void omap_sram_idle(void)
prm_clear_mod_reg_bits(OMAP3430_AUTO_RET,
OMAP3430_GR_MOD,
OMAP3_PRM_VOLTCTRL_OFFSET);
-   /* Enable smartreflex after WFI */
+   }
+
+   /*
+* Enable smartreflex after WFI. Only needed if we entered
+* retention or off
+*/
+   if (mpu_next_state = PWRDM_POWER_RET)
enable_smartreflex(SR1);
+   if (core_next_state = PWRDM_POWER_RET)
enable_smartreflex(SR2);
-   }
 
/* PER */
if (per_next_state  PWRDM_POWER_ON) {
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 04/11] OMAP3: PM: Ack pending interrupts before entering suspend

2009-10-23 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Suspending drivers may still generate interrupts just before their suspend is
completed. Any pending interrupts here will prevent sleep.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/irq.c  |6 ++
 arch/arm/mach-omap2/pm34xx.c   |2 +-
 arch/arm/plat-omap/include/mach/irqs.h |1 +
 3 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index aceedd8..ee8c68a 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -266,4 +266,10 @@ void omap3_intc_restore_context(void)
}
/* MIRs are saved and restore with other PRCM registers */
 }
+
+void omap3_intc_suspend(void)
+{
+   /* A pending interrupt would prevent OMAP from entering suspend */
+   omap_ack_irq(0);
+}
 #endif /* CONFIG_ARCH_OMAP3 */
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 6782792..53544d3 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -640,7 +640,7 @@ static int omap3_pm_suspend(void)
}
 
omap_uart_prepare_suspend();
-
+   omap3_intc_suspend();
regset_save_on_suspend = 1;
omap_sram_idle();
regset_save_on_suspend = 0;
diff --git a/arch/arm/plat-omap/include/mach/irqs.h 
b/arch/arm/plat-omap/include/mach/irqs.h
index 2473910..ff1faa8 100644
--- a/arch/arm/plat-omap/include/mach/irqs.h
+++ b/arch/arm/plat-omap/include/mach/irqs.h
@@ -485,6 +485,7 @@ extern void omap_init_irq(void);
 extern int omap_irq_pending(void);
 void omap3_intc_save_context(void);
 void omap3_intc_restore_context(void);
+void omap3_intc_suspend(void);
 #endif
 
 #include mach/hardware.h
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 03/11] OMAP2/3: DMTIMER: Clear pending interrupts when stopping a timer

2009-10-23 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

OMAP GP timers keep running for a few cycles after they are stopped,
which can cause the timer to expire and generate an interrupt. The pending
interrupt will prevent e.g. OMAP from entering suspend, thus we ack it
manually.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/plat-omap/dmtimer.c |   10 ++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 830b072..09a623d 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -551,6 +551,16 @@ void omap_dm_timer_stop(struct omap_dm_timer *timer)
if (l  OMAP_TIMER_CTRL_ST) {
l = ~0x1;
omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+   /* Readback to make sure write has completed */
+   omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+/*
+ * Wait for functional clock period x 3.5 to make sure that
+ * timer is stopped
+ */
+   udelay(350 / clk_get_rate(timer-fclk) + 1);
+   /* Ack possibly pending interrupt */
+   omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
+   OMAP_TIMER_INT_OVERFLOW);
}
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 06/11] OMAP3: PM: Disable interrupt controller AUTOIDLE before WFI

2009-10-23 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

OMAP interrupt controller goes to unknown state when there is right
combination of l3,l4 sleep/wake-up transitions, l4 autoidle in
interrupt controller and some interrupt. When this happens, interrupts
are not delivered to ARM anymore and ARM will remain in WFI (wait for
interrupt) until interrupt controller is forced to wake-up
(i.e. lauterbach).

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/irq.c  |   12 
 arch/arm/mach-omap2/pm34xx.c   |2 ++
 arch/arm/plat-omap/include/mach/irqs.h |2 ++
 3 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index ee8c68a..9241b87 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -272,4 +272,16 @@ void omap3_intc_suspend(void)
/* A pending interrupt would prevent OMAP from entering suspend */
omap_ack_irq(0);
 }
+
+void omap3_intc_prepare_idle(void)
+{
+   /* Disable autoidle as it can stall interrupt controller */
+   intc_bank_write_reg(0, irq_banks[0], INTC_SYSCONFIG);
+}
+
+void omap3_intc_resume_idle(void)
+{
+   /* Re-enable autoidle */
+   intc_bank_write_reg(1, irq_banks[0], INTC_SYSCONFIG);
+}
 #endif /* CONFIG_ARCH_OMAP3 */
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 492458e..fec9c38 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -431,6 +431,7 @@ void omap_sram_idle(void)
prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
omap3_enable_io_chain();
}
+   omap3_intc_prepare_idle();
 
/*
* On EMU/HS devices ROM code restores a SRDC value
@@ -487,6 +488,7 @@ void omap_sram_idle(void)
OMAP3430_GR_MOD,
OMAP3_PRM_VOLTCTRL_OFFSET);
}
+   omap3_intc_resume_idle();
 
/*
 * Enable smartreflex after WFI. Only needed if we entered
diff --git a/arch/arm/plat-omap/include/mach/irqs.h 
b/arch/arm/plat-omap/include/mach/irqs.h
index ff1faa8..b736c5d 100644
--- a/arch/arm/plat-omap/include/mach/irqs.h
+++ b/arch/arm/plat-omap/include/mach/irqs.h
@@ -486,6 +486,8 @@ extern int omap_irq_pending(void);
 void omap3_intc_save_context(void);
 void omap3_intc_restore_context(void);
 void omap3_intc_suspend(void);
+void omap3_intc_prepare_idle(void);
+void omap3_intc_resume_idle(void);
 #endif
 
 #include mach/hardware.h
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 07/11] OMAP3: Fixed ARM aux ctrl register save/restore

2009-10-23 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Current value is stored on SDRAM and it is written back during wakeup.
Previously a static value of 0x72 was written there.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
Signed-off-by: Jouni Hogander jouni.hogan...@nokia.com
---
 arch/arm/mach-omap2/control.c   |1 +
 arch/arm/mach-omap2/sleep34xx.S |   23 ---
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index 296f2c2..730fc53 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -94,6 +94,7 @@ void *omap3_secure_ram_storage;
  * during the restore path.
  */
 u32 omap3_arm_context[128];
+u32 omap3_aux_ctrl[2] = { 0x1, 0x0 };
 
 struct omap3_control_regs {
u32 sysconfig;
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index f4f5ebe..0b03bf9 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -26,6 +26,7 @@
  */
 #include linux/linkage.h
 #include asm/assembler.h
+#include asm/memory.h
 #include mach/io.h
 #include mach/control.h
 
@@ -278,7 +279,11 @@ restore:
mov r1, #0  @ set task id for ROM code in r1
mov r2, #4  @ set some flags in r2, r6
mov r6, #0xff
-   adr r3, write_aux_control_params@ r3 points to parameters
+   ldr r3, write_aux_control_params@ r3 points to parameters
+   ldr r4, phys_offset
+   addsr3, r3, r4
+   ldr r4, page_offset
+   subsr3, r3, r4
mcr p15, 0, r0, c7, c10, 4  @ data write barrier
mcr p15, 0, r0, c7, c10, 5  @ data memory barrier
.word   0xE1600071  @ call SMI monitor (smi #1)
@@ -287,13 +292,18 @@ restore:
 l2_inv_api_params:
.word   0x1, 0x00
 write_aux_control_params:
-   .word   0x1, 0x72
+   .word   omap3_aux_ctrl
 l2_inv_gp:
/* Execute smi to invalidate L2 cache */
mov r12, #0x1 @ set up to invalide L2
 smi:.word 0xE1600070   @ Call SMI monitor (smieq)
/* Write to Aux control register to set some bits */
-   mov r0, #0x72
+   ldr r1, write_aux_control_params
+   ldr r0, phys_offset
+   addsr1, r1, r0
+   ldr r0, page_offset
+   subsr1, r1, r0
+   ldr r0, [r1, #4]
mov r12, #0x3
.word 0xE1600070@ Call SMI monitor (smieq)
 logic_l1_restore:
@@ -420,6 +430,9 @@ usettbr0:
 save_context_wfi:
/*b save_context_wfi*/  @ enable to debug save code
mov r8, r0 /* Store SDRAM address in r8 */
+   mrc p15, 0, r4, c1, c0, 1   @ Read Auxiliary Control Register
+   ldr r5, write_aux_control_params
+   str r4, [r5, #4]
 /* Check what that target sleep state is:stored in r1*/
 /* 1 - Only L1 and logic lost */
 /* 2 - Only L2 lost */
@@ -605,6 +618,10 @@ wait_dll_lock:
 bne wait_dll_lock
 bx  lr
 
+phys_offset:
+   .word   PHYS_OFFSET
+page_offset:
+   .word   PAGE_OFFSET
 cm_idlest1_core:
.word   CM_IDLEST1_CORE_V
 sdrc_dlla_status:
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 08/11] OMAP3: PM: Disabled I2C4 repeated start operation mode

2009-10-23 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Repeated start forces I2C4 pads low during idle, which increases power
consumption through external pull-ups. On the other hand, this change
increases I2C4 command latencies a bit.

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

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index fec9c38..154cd31 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -1219,7 +1219,7 @@ static void __init configure_vc(void)
prm_write_mod_reg(OMAP3430_CMD1 | OMAP3430_RAV1, OMAP3430_GR_MOD,
  OMAP3_PRM_VC_CH_CONF_OFFSET);
 
-   prm_write_mod_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN | OMAP3430_SREN,
+   prm_write_mod_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN,
  OMAP3430_GR_MOD,
  OMAP3_PRM_VC_I2C_CFG_OFFSET);
 
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 05/11] OMAP3: PM: Enable system control module autoidle

2009-10-23 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

This saves some power.

Signed-off-by: Mika Westerberg ext-mika.1.westerb...@nokia.com
---
 arch/arm/mach-omap2/pm34xx.c |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 53544d3..492458e 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -900,6 +900,8 @@ static void __init prcm_setup_regs(void)
CM_AUTOIDLE);
}
 
+   omap_ctrl_writel(OMAP3430_AUTOIDLE, OMAP2_CONTROL_SYSCONFIG);
+
/*
 * Set all plls to autoidle. This is needed until autoidle is
 * enabled by clockfw
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 09/11] OMAP3: PM: Added support for L2 aux ctrl register save and restore

2009-10-23 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

This patch adds a save and restore mechanism for ARM L2 auxiliary control
register. This feature is enabled via Kconfig option
OMAP3_L2_AUX_SECURE_SAVE_RESTORE and the service ID for PPA can be provided
via option OMAP3_L2_AUX_SECURE_SERVICE_SET_ID. If bootloader does not modify
L2 aux register, using this save and restore logic for it is not needed.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/control.c   |1 +
 arch/arm/mach-omap2/sleep34xx.S |   31 +++
 arch/arm/plat-omap/Kconfig  |   17 +
 3 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index 730fc53..82d8f1a 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -95,6 +95,7 @@ void *omap3_secure_ram_storage;
  */
 u32 omap3_arm_context[128];
 u32 omap3_aux_ctrl[2] = { 0x1, 0x0 };
+u32 omap3_l2_aux_ctrl[2] = { 0x1, 0x0 };
 
 struct omap3_control_regs {
u32 sysconfig;
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index 0b03bf9..e291d6d 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -288,11 +288,30 @@ restore:
mcr p15, 0, r0, c7, c10, 5  @ data memory barrier
.word   0xE1600071  @ call SMI monitor (smi #1)
 
+#ifdef CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE
+   /* Restore L2 aux control register */
+   @ set service ID for PPA
+   mov r0, #CONFIG_OMAP3_L2_AUX_SECURE_SERVICE_SET_ID
+   mov r12, r0 @ copy service ID in r12
+   mov r1, #0  @ set task ID for ROM code in r1
+   mov r2, #4  @ set some flags in r2, r6
+   mov r6, #0xff
+   ldr r3, write_l2_aux_control_params @ r3 points to parameters
+   ldr r4, phys_offset
+   addsr3, r3, r4
+   ldr r4, page_offset
+   subsr3, r3, r4
+   mcr p15, 0, r0, c7, c10, 4  @ data write barrier
+   mcr p15, 0, r0, c7, c10, 5  @ data memory barrier
+   .word   0xE1600071  @ call SMI monitor (smi #1)
+#endif
b   logic_l1_restore
 l2_inv_api_params:
.word   0x1, 0x00
 write_aux_control_params:
.word   omap3_aux_ctrl
+write_l2_aux_control_params:
+   .word   omap3_l2_aux_ctrl
 l2_inv_gp:
/* Execute smi to invalidate L2 cache */
mov r12, #0x1 @ set up to invalide L2
@@ -306,6 +325,15 @@ smi:.word 0xE1600070   @ Call SMI monitor 
(smieq)
ldr r0, [r1, #4]
mov r12, #0x3
.word 0xE1600070@ Call SMI monitor (smieq)
+   /* Restore L2 AUX control register */
+   ldr r1, write_l2_aux_control_params
+   ldr r0, phys_offset
+   addsr1, r1, r0
+   ldr r0, page_offset
+   subsr1, r1, r0
+   ldr r0, [r1, #4]
+   mov r12, #0x2
+   .word 0xE1600070@ Call SMI monitor (smieq)
 logic_l1_restore:
mov r1, #0
/* Invalidate all instruction caches to PoU
@@ -433,6 +461,9 @@ save_context_wfi:
mrc p15, 0, r4, c1, c0, 1   @ Read Auxiliary Control Register
ldr r5, write_aux_control_params
str r4, [r5, #4]
+   mrc p15, 1, r4, c9, c0, 2   @ Read L2 AUX ctrl register
+   ldr r5, write_l2_aux_control_params
+   str r4, [r5, #4]
 /* Check what that target sleep state is:stored in r1*/
 /* 1 - Only L1 and logic lost */
 /* 2 - Only L2 lost */
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 2143db5..3ff1a5f 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -185,6 +185,23 @@ config OMAP3_DEBOBS
help
  Use ETK pads for debug observability
 
+config OMAP3_L2_AUX_SECURE_SAVE_RESTORE
+   bool OMAP3 HS/EMU save and restore for L2 AUX control register
+   depends on ARCH_OMAP3  PM
+   default n
+   help
+ Without this option, L2 Auxiliary control register contents are
+ lost during off-mode entry on HS/EMU devices. This feature
+ requires support from PPA / boot-loader in HS/EMU devices, which
+ currently does not exist by default.
+
+config OMAP3_L2_AUX_SECURE_SERVICE_SET_ID
+   int Service ID for the support routine to set L2 AUX control
+   depends on OMAP3_L2_AUX_SECURE_SAVE_RESTORE
+   default 43
+   help
+ PPA routine service ID for setting L2 auxiliary control register.
+
 config OMAP_32K_TIMER_HZ
int Kernel internal timer frequency for 32KHz timer
range 32 1024
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 10/11] OMAP3: PM: Write voltage and clock setup times dynamically in idle loop

2009-10-23 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

It is suggested by TI (SWPA152 February 2009) to write clksetup,
voltsetup_time1, voltsetup_time2, voltsetup2 dynamically in idle loop.

This allows us to optimize the voltage + clock setup times according to the
used power save mode.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/pm.h |   10 -
 arch/arm/mach-omap2/pm34xx.c |   86 --
 2 files changed, 57 insertions(+), 39 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index f8d11a2..b384eb1 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -24,12 +24,18 @@ extern int omap3_can_sleep(void);
 extern int set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap3_idle_init(void);
 
-struct prm_setup_vc {
+struct prm_setup_times_vc {
u16 clksetup;
u16 voltsetup_time1;
u16 voltsetup_time2;
-   u16 voltoffset;
u16 voltsetup2;
+   u16 voltsetup1;
+};
+
+struct prm_setup_vc {
+   struct prm_setup_times_vc *setup_times;
+   struct prm_setup_times_vc *setup_times_off;
+   u16 voltoffset;
 /* PRM_VC_CMD_VAL_0 specific bits */
u16 vdd0_on;
u16 vdd0_onlp;
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 154cd31..5eb7321 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -82,12 +82,17 @@ static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
 static struct powerdomain *cam_pwrdm;
 
-static struct prm_setup_vc prm_setup = {
+static struct prm_setup_times_vc prm_setup_times_default = {
.clksetup = 0xff,
.voltsetup_time1 = 0xfff,
.voltsetup_time2 = 0xfff,
-   .voltoffset = 0xff,
.voltsetup2 = 0xff,
+};
+
+static struct prm_setup_vc prm_setup_default = {
+   .setup_times = prm_setup_times_default,
+   .setup_times_off = NULL,
+   .voltoffset = 0xff,
.vdd0_on = 0x30,/* 1.2v */
.vdd0_onlp = 0x20,  /* 1.0v */
.vdd0_ret = 0x1e,   /* 0.975v */
@@ -98,6 +103,8 @@ static struct prm_setup_vc prm_setup = {
.vdd1_off = 0x00,   /* 0.6v */
 };
 
+static struct prm_setup_vc *prm_setup = prm_setup_default;
+
 static inline void omap3_per_save_context(void)
 {
omap3_gpio_save_context();
@@ -338,6 +345,16 @@ static void restore_table_entry(void)
restore_control_register(control_reg_value);
 }
 
+static void prm_program_setup_times(struct prm_setup_times_vc *times)
+{
+   prm_write_mod_reg(times-voltsetup1, OMAP3430_GR_MOD,
+   OMAP3_PRM_VOLTSETUP1_OFFSET);
+   prm_write_mod_reg(times-voltsetup2, OMAP3430_GR_MOD,
+   OMAP3_PRM_VOLTSETUP2_OFFSET);
+   prm_write_mod_reg(times-clksetup, OMAP3430_GR_MOD,
+   OMAP3_PRM_CLKSETUP_OFFSET);
+}
+
 void omap_sram_idle(void)
 {
/* Variable to tell what needs to be saved and restored
@@ -422,6 +439,9 @@ void omap_sram_idle(void)
 OMAP3_PRM_VOLTCTRL_OFFSET);
omap3_core_save_context();
omap3_prcm_save_context();
+   if (prm_setup-setup_times_off != NULL)
+   prm_program_setup_times(prm_setup-
+   setup_times_off);
} else if (core_next_state == PWRDM_POWER_RET) {
prm_set_mod_reg_bits(OMAP3430_AUTO_RET,
OMAP3430_GR_MOD,
@@ -479,11 +499,13 @@ void omap_sram_idle(void)
}
omap_uart_resume_idle(0);
omap_uart_resume_idle(1);
-   if (core_next_state == PWRDM_POWER_OFF)
+   if (core_next_state == PWRDM_POWER_OFF) {
prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF,
   OMAP3430_GR_MOD,
   OMAP3_PRM_VOLTCTRL_OFFSET);
-   else if (core_next_state == PWRDM_POWER_RET)
+   if (prm_setup-setup_times_off != NULL)
+   prm_program_setup_times(prm_setup-setup_times);
+   } else if (core_next_state == PWRDM_POWER_RET)
prm_clear_mod_reg_bits(OMAP3430_AUTO_RET,
OMAP3430_GR_MOD,
OMAP3_PRM_VOLTCTRL_OFFSET);
@@ -1043,21 +1065,19 @@ int omap3_pm_set_suspend_state(struct powerdomain 
*pwrdm, int state)
return -EINVAL;
 }
 
+static void omap3_init_prm_setup_times(struct prm_setup_times_vc *conf)
+{
+   if (conf == NULL)
+   return;
+
+   conf-voltsetup1 =
+   (conf-voltsetup_time2  OMAP3430_SETUP_TIME2_SHIFT) |
+   (conf-voltsetup_time1  OMAP3430_SETUP_TIME1_SHIFT

[PATCH 01/11] OMAP3: PM: Fixed padconf save done check

2009-10-23 Thread Tero Kristo
From: Carlos Chinea carlos.chi...@nokia.com

Previously the operator precedence dictated that the delay loop was exited
immediately, potentially causing off-mode to be entered too soon.

Signed-off-by: Carlos Chinea carlos.chi...@nokia.com
Signed-off-by: Jouni Hogander jouni.hogan...@nokia.com
---
 arch/arm/mach-omap2/pm34xx.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 01260ec..8353764 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -146,8 +146,8 @@ static void omap3_core_save_context(void)
control_padconf_off |= START_PADCONF_SAVE;
omap_ctrl_writel(control_padconf_off, OMAP343X_CONTROL_PADCONF_OFF);
/* wait for the save to complete */
-   while (!omap_ctrl_readl(OMAP343X_CONTROL_GENERAL_PURPOSE_STATUS)
-PADCONF_SAVE_DONE)
+   while (!(omap_ctrl_readl(OMAP343X_CONTROL_GENERAL_PURPOSE_STATUS)
+PADCONF_SAVE_DONE))
;
/* Save the Interrupt controller context */
omap3_intc_save_context();
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] OMAP3: CPUidle: Fixed timer resolution

2009-10-26 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Previously used u32 as temporary data storage that wraps around at 4.294s.

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

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index a0d9f56..0ac3b63 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -137,7 +137,7 @@ return_sleep_time:
local_irq_enable();
local_fiq_enable();
 
-   return (u32)timespec_to_ns(ts_idle)/1000;
+   return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC;
 }
 
 /**
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] OMAP3: PM: Check BM for C2 state

2009-10-26 Thread Tero Kristo
From: De-Schrijver Peter peter.de-schrij...@nokia.com

C2 can't be entered while we have bus activity.

Signed-off-by: Peter 'p2' De Schrijver peter.de-schrij...@nokia.com
---
 arch/arm/mach-omap2/cpuidle34xx.c |7 ---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index c44a942..a0d9f56 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -38,7 +38,7 @@
 
 #define OMAP3_MAX_STATES 7
 #define OMAP3_STATE_C1 0 /* C1 - MPU WFI + Core active */
-#define OMAP3_STATE_C2 1 /* C2 - MPU WFI + Core inactive */
+#define OMAP3_STATE_C2 1 /* C2 - MPU inactive + Core inactive */
 #define OMAP3_STATE_C3 2 /* C3 - MPU CSWR + Core inactive */
 #define OMAP3_STATE_C4 3 /* C4 - MPU OFF + Core iactive */
 #define OMAP3_STATE_C5 4 /* C5 - MPU RET + Core RET */
@@ -169,7 +169,7 @@ DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
  *
  * Below is the desciption of each C state.
  * C1 . MPU WFI + Core active
- * C2 . MPU WFI + Core inactive
+ * C2 . MPU inactive + Core inactive
  * C3 . MPU CSWR + Core inactive
  * C4 . MPU OFF + Core inactive
  * C5 . MPU CSWR + Core CSWR
@@ -196,7 +196,8 @@ void omap_init_power_states(void)
omap3_power_states[OMAP3_STATE_C2].threshold = 30;
omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON;
omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
-   omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID;
+   omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID |
+   CPUIDLE_FLAG_CHECK_BM;
 
/* C3 . MPU CSWR + Core inactive */
omap3_power_states[OMAP3_STATE_C3].valid = 1;
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/2] OMAP3: Cpuidle fixes

2009-10-26 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Following patches apply on top of PM branch. They implement a couple of
small fixes for cpuidle. Timer resolution patch probably does not change
anything until kernel cpuidle is fixed to support longer timers (there are
some pending patches for this.)

-Tero


--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/4] RX51: Fix SDRAM RFR timings calculation

2009-10-26 Thread Tero Kristo
From: Kalle Jokiniemi kalle.jokini...@digia.com

sdrc_ps_to_ticks introduced some unnecessary
rounding error to SDRC_RFR value calculation.
Fixed by adding 10^3 more accuracy before
division and skipping the sdrc_ps_to_ticks call.

Problem-reported-by: Jukka S. Laitinen jukka.s.laiti...@nokia.com
Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com
---
 arch/arm/mach-omap2/board-rx51-sdram.c |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/board-rx51-sdram.c 
b/arch/arm/mach-omap2/board-rx51-sdram.c
index 237b898..f3b9917 100644
--- a/arch/arm/mach-omap2/board-rx51-sdram.c
+++ b/arch/arm/mach-omap2/board-rx51-sdram.c
@@ -166,7 +166,7 @@ static int set_sdrc_timing_regval_ps(u32 *regval, int 
st_bit, int end_bit,
 
 static int sdrc_timings(int id, long rate)
 {
-   u32 ticks_per_us;
+   u32 ticks_per_ms;
u32 rfr, l;
u32 actim_ctrla = 0, actim_ctrlb = 0;
u32 rfr_ctrl;
@@ -192,8 +192,8 @@ static int sdrc_timings(int id, long rate)
SDRC_SET_ONE(actim_ctrlb,  12,  14, tCKE, l3_rate);
SDRC_SET_ONE(actim_ctrlb,  16,  17, tWTR, l3_rate);
 
-   ticks_per_us = sdrc_ps_to_ticks(100, l3_rate);
-   rfr = rx51_timings[0].tREF * ticks_per_us / 1000;
+   ticks_per_ms = l3_rate;
+   rfr = rx51_timings[0].tREF * ticks_per_ms / 100;
if (rfr  65535 + 50)
rfr = 65535;
else
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/4] RX51: Add SDRAM configs for different OPPs

2009-10-26 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

This modification is needed by DVFS.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
Signed-off-by: Jouni Hogander jouni.hogan...@nokia.com
---
 arch/arm/mach-omap2/board-rx51-sdram.c |   84 ++--
 1 files changed, 47 insertions(+), 37 deletions(-)

diff --git a/arch/arm/mach-omap2/board-rx51-sdram.c 
b/arch/arm/mach-omap2/board-rx51-sdram.c
index 6f1f33c..78cd5ed 100644
--- a/arch/arm/mach-omap2/board-rx51-sdram.c
+++ b/arch/arm/mach-omap2/board-rx51-sdram.c
@@ -44,7 +44,7 @@ struct sdram_info {
 };
 
 
-struct omap_sdrc_params rx51_sdrc_params[2];
+struct omap_sdrc_params rx51_sdrc_params[4];
 
 static const struct sdram_timings rx51_timings[] = {
{
@@ -118,30 +118,28 @@ static unsigned long get_l3_rate(void)
return get_core_rate() / (l  0x03);
 }
 
-
-
-static unsigned long sdrc_get_fclk_period(void)
+static unsigned long sdrc_get_fclk_period(long rate)
 {
/* In picoseconds */
-   return 10 / get_l3_rate();
+   return 10 / rate;
 }
 
-static unsigned int sdrc_ps_to_ticks(unsigned int time_ps)
+static unsigned int sdrc_ps_to_ticks(unsigned int time_ps, long rate)
 {
unsigned long tick_ps;
 
/* Calculate in picosecs to yield more exact results */
-   tick_ps = sdrc_get_fclk_period();
+   tick_ps = sdrc_get_fclk_period(rate);
 
return (time_ps + tick_ps - 1) / tick_ps;
 }
 #undef DEBUG
 #ifdef DEBUG
 static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
-  int time, const char *name)
+  int time, long rate, const char *name)
 #else
 static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
-  int time)
+  int time, long rate)
 #endif
 {
int ticks, mask, nr_bits;
@@ -149,7 +147,7 @@ static int set_sdrc_timing_regval(u32 *regval, int st_bit, 
int end_bit,
if (time == 0)
ticks = 0;
else
-   ticks = sdrc_ps_to_ticks(time);
+   ticks = sdrc_ps_to_ticks(time, rate);
nr_bits = end_bit - st_bit + 1;
if (ticks = 1  nr_bits)
return -1;
@@ -158,42 +156,46 @@ static int set_sdrc_timing_regval(u32 *regval, int 
st_bit, int end_bit,
*regval |= ticks  st_bit;
 #ifdef DEBUG
printk(SDRC %s: %i ticks %i ns\n, name, ticks,
-   (unsigned int)sdrc_get_fclk_period() * ticks / 1000);
+   (unsigned int)sdrc_get_fclk_period(rate) * ticks /
+   1000);
 #endif
 
return 0;
 }
 
 #ifdef DEBUG
-#define SDRC_SET_ONE(reg, st, end, field) \
-   if (set_sdrc_timing_regval((reg), (st), (end), rx51_timings-field, 
#field)  0) \
-   err = -1
+#define SDRC_SET_ONE(reg, st, end, field, rate) \
+   if (set_sdrc_timing_regval((reg), (st), (end), \
+   rx51_timings-field, (rate), #field)  0) \
+   err = -1;
 #else
-#define SDRC_SET_ONE(reg, st, end, field) \
-   if (set_sdrc_timing_regval((reg), (st), (end), rx51_timings-field)  
0) \
-   err = -1
+#define SDRC_SET_ONE(reg, st, end, field, rate) \
+   if (set_sdrc_timing_regval((reg), (st), (end), \
+   rx51_timings-field, (rate))  0) \
+   err = -1;
 #endif
 
-struct omap_sdrc_params *rx51_get_sdram_timings(void)
+static int sdrc_timings(int id, long rate)
 {
u32 ticks_per_ms;
u32 rfr, l;
-   u32 actim_ctrla, actim_ctrlb;
+   u32 actim_ctrla = 0, actim_ctrlb = 0;
u32 rfr_ctrl;
int err = 0;
+   long l3_rate = rate / 1000;
 
-   SDRC_SET_ONE(actim_ctrla,  0,  4, tDAL);
-   SDRC_SET_ONE(actim_ctrla,  6,  8, tDPL);
-   SDRC_SET_ONE(actim_ctrla,  9, 11, tRRD);
-   SDRC_SET_ONE(actim_ctrla, 12, 14, tRCD);
-   SDRC_SET_ONE(actim_ctrla, 15, 17, tRP);
-   SDRC_SET_ONE(actim_ctrla, 18, 21, tRAS);
-   SDRC_SET_ONE(actim_ctrla, 22, 26, tRC);
-   SDRC_SET_ONE(actim_ctrla, 27, 31, tRFC);
+   SDRC_SET_ONE(actim_ctrla,  0,  4, tDAL, l3_rate);
+   SDRC_SET_ONE(actim_ctrla,  6,  8, tDPL, l3_rate);
+   SDRC_SET_ONE(actim_ctrla,  9, 11, tRRD, l3_rate);
+   SDRC_SET_ONE(actim_ctrla, 12, 14, tRCD, l3_rate);
+   SDRC_SET_ONE(actim_ctrla, 15, 17, tRP, l3_rate);
+   SDRC_SET_ONE(actim_ctrla, 18, 21, tRAS, l3_rate);
+   SDRC_SET_ONE(actim_ctrla, 22, 26, tRC, l3_rate);
+   SDRC_SET_ONE(actim_ctrla, 27, 31, tRFC, l3_rate);
 
-   SDRC_SET_ONE(actim_ctrlb,  0,  7, tXSR);
+   SDRC_SET_ONE(actim_ctrlb,  0,  7, tXSR, l3_rate);
 
-   ticks_per_ms = sdrc_ps_to_ticks(10);
+   ticks_per_ms = sdrc_ps_to_ticks(10, l3_rate);
rfr = rx51_timings[0].tREF * ticks_per_ms / (1  rx51_info.row_lines);
if (rfr  65535 + 50)
rfr = 65535;
@@ -203,16 +205,24 @@ struct omap_sdrc_params

[PATCH 0/4] RX51: SDRAM settings changes

2009-10-26 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Following patch set fixes a few issues with current RX51 board SDRAM settings.
Applies on top of PM branch.

-Tero


--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/4] RX51: SDRC: change timing values to follow generic memory requirements

2009-10-26 Thread Tero Kristo
From: Onkalo Samu.P samu.p.onk...@nokia.com

Current memory parameters are slightly off-spec. Also, a couple of unused
functions removed from code.

Signed-off-by: Samu Onkalo samu.p.onk...@nokia.com
---
 arch/arm/mach-omap2/board-rx51-sdram.c |  130 ++--
 1 files changed, 91 insertions(+), 39 deletions(-)

diff --git a/arch/arm/mach-omap2/board-rx51-sdram.c 
b/arch/arm/mach-omap2/board-rx51-sdram.c
index b5d1c55..237b898 100644
--- a/arch/arm/mach-omap2/board-rx51-sdram.c
+++ b/arch/arm/mach-omap2/board-rx51-sdram.c
@@ -1,5 +1,5 @@
 /*
- * SDRC register values for the Samsung K4X1G323PC
+ * SDRC register values for RX51
  *
  * Copyright (C) 2008 Nokia Corporation
  *
@@ -23,7 +23,7 @@
 #include mach/sdrc.h
 
 
-/* In picoseconds, except for tREF */
+/* In picoseconds, except for tREF (ns), tXP, tCKE, tWTR (clks) */
 struct sdram_timings {
u32 casl;
u32 tDAL;
@@ -36,7 +36,11 @@ struct sdram_timings {
u32 tRFC;
u32 tXSR;
 
-   u32 tREF; /* in ms */
+   u32 tREF; /* in ns */
+
+   u32 tXP;
+   u32 tCKE;
+   u32 tWTR;
 };
 
 struct sdram_info {
@@ -49,22 +53,22 @@ struct omap_sdrc_params rx51_sdrc_params[4];
 static const struct sdram_timings rx51_timings[] = {
{
.casl = 3,
-   .tDAL = 15000 + 18000,
+   .tDAL = 33000,
.tDPL = 15000,
.tRRD = 12000,
-   .tRCD = 18000,
+   .tRCD = 22500,
.tRP = 18000,
.tRAS = 42000,
.tRC = 66000,
-   .tRFC = 97500,
-   .tXSR = 12,
+   .tRFC = 138000,
+   .tXSR = 20,
 
-   .tREF = 64,
-   },
-};
+   .tREF = 7800,
 
-static const struct sdram_info rx51_info = {
-   .row_lines = 13,
+   .tXP = 2,
+   .tCKE = 2,
+   .tWTR = 2
+   },
 };
 
 static unsigned long sdrc_get_fclk_period(long rate)
@@ -85,18 +89,14 @@ static unsigned int sdrc_ps_to_ticks(unsigned int time_ps, 
long rate)
 #undef DEBUG
 #ifdef DEBUG
 static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
-  int time, long rate, const char *name)
+   int ticks, long rate, const char *name)
 #else
 static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
-  int time, long rate)
+  int ticks)
 #endif
 {
-   int ticks, mask, nr_bits;
+   int mask, nr_bits;
 
-   if (time == 0)
-   ticks = 0;
-   else
-   ticks = sdrc_ps_to_ticks(time, rate);
nr_bits = end_bit - st_bit + 1;
if (ticks = 1  nr_bits)
return -1;
@@ -104,7 +104,7 @@ static int set_sdrc_timing_regval(u32 *regval, int st_bit, 
int end_bit,
*regval = ~(mask  st_bit);
*regval |= ticks  st_bit;
 #ifdef DEBUG
-   printk(SDRC %s: %i ticks %i ns\n, name, ticks,
+   printk(KERN_INFO SDRC %s: %i ticks %i ns\n, name, ticks,
(unsigned int)sdrc_get_fclk_period(rate) * ticks /
1000);
 #endif
@@ -113,46 +113,98 @@ static int set_sdrc_timing_regval(u32 *regval, int 
st_bit, int end_bit,
 }
 
 #ifdef DEBUG
-#define SDRC_SET_ONE(reg, st, end, field, rate) \
-   if (set_sdrc_timing_regval((reg), (st), (end), \
+#define SDRC_SET_ONE(reg, st, end, field, rate)
  \
+   if (set_sdrc_timing_regval((reg), (st), (end),\
rx51_timings-field, (rate), #field)  0) \
err = -1;
 #else
-#define SDRC_SET_ONE(reg, st, end, field, rate) \
-   if (set_sdrc_timing_regval((reg), (st), (end), \
-   rx51_timings-field, (rate))  0) \
+#define SDRC_SET_ONE(reg, st, end, field, rate)
\
+   if (set_sdrc_timing_regval((reg), (st), (end),  \
+   rx51_timings-field, (rate))  0)   \
+   err = -1;
+#endif
+
+#ifdef DEBUG
+static int set_sdrc_timing_regval_ps(u32 *regval, int st_bit, int end_bit,
+   int time, long rate, const char *name)
+#else
+static int set_sdrc_timing_regval_ps(u32 *regval, int st_bit, int end_bit,
+   int time, long rate)
+#endif
+{
+   int ticks, ret;
+   ret = 0;
+
+   if (time == 0)
+   ticks = 0;
+   else
+   ticks = sdrc_ps_to_ticks(time, rate);
+
+#ifdef DEBUG
+   ret = set_sdrc_timing_regval(regval, st_bit, end_bit, ticks,
+rate, name);
+#else
+   ret = set_sdrc_timing_regval(regval, st_bit, end_bit, ticks);
+#endif
+
+   return ret;
+}
+
+#ifdef DEBUG
+#define SDRC_SET_ONE_PS(reg, st, end, field, rate) \
+   if (set_sdrc_timing_regval_ps((reg), (st), 

[PATCH 2/4] RX51: SDRAM: Cleanup the init code

2009-10-26 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Removed a few unused functions + macro definitions + variables from the code.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/board-rx51-sdram.c |   51 
 1 files changed, 0 insertions(+), 51 deletions(-)

diff --git a/arch/arm/mach-omap2/board-rx51-sdram.c 
b/arch/arm/mach-omap2/board-rx51-sdram.c
index 78cd5ed..b5d1c55 100644
--- a/arch/arm/mach-omap2/board-rx51-sdram.c
+++ b/arch/arm/mach-omap2/board-rx51-sdram.c
@@ -67,57 +67,6 @@ static const struct sdram_info rx51_info = {
.row_lines = 13,
 };
 
-#define CM_BASE0x48004000
-
-#define CM_CLKSEL_CORE  0x0a40
-#define CM_CLKSEL1_PLL  0x0d40
-
-#define PRM_CLKSEL  0x48306d40
-#define PRM_CLKSRC_CTRL 0x48307270
-
-static u32 cm_base = CM_BASE;
-
-static inline u32 cm_read_reg(int idx)
-{
-   return *(u32 *)OMAP2_L4_IO_ADDRESS(cm_base + idx);
-}
-
-static const unsigned long sys_clk_rate_table[] = {
-   12000, 13000, 19200, 26000, 38400, 16800
-};
-
-static unsigned long get_sys_clk_rate(void)
-{
-   unsigned long rate;
-
-   rate = sys_clk_rate_table[*(u32 *)OMAP2_L4_IO_ADDRESS(PRM_CLKSEL)  
0x07];
-   if (((*(u32 *)OMAP2_L4_IO_ADDRESS(PRM_CLKSRC_CTRL)  6)  0x03) == 
0x02)
-   rate /= 2;
-   return rate;
-}
-
-static unsigned long get_core_rate(void)
-{
-   unsigned long rate;
-   u32 l;
-
-   l = cm_read_reg(CM_CLKSEL1_PLL);
-   rate = get_sys_clk_rate();
-   rate *= ((l  16)  0x7ff);
-   rate /= ((l  8)  0x7f) + 1;
-   rate /= (l  27)  0x1f;
-
-   return rate;
-}
-
-static unsigned long get_l3_rate(void)
-{
-   u32 l;
-
-   l = cm_read_reg(CM_CLKSEL_CORE);
-   return get_core_rate() / (l  0x03);
-}
-
 static unsigned long sdrc_get_fclk_period(long rate)
 {
/* In picoseconds */
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] RX51: Add SDRAM init

2009-10-27 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

This patch adds board specific SDRAM init for RX51. This patch is a
collaboration of work from following people:

Juha Yrjola: Original code
Lauri Leukkunen: Port to RX51
Tero Kristo: Support for multiple OPP:s, merge of patches
Samu Onkalo: Fixed SDRAM parameters according to specs
Kalle Jokiniemi: A fix for rounding error

Signed-off-by: Tero Kristo tero.kri...@nokia.com
Cc: Samu Onkalo samu.p.onk...@nokia.com
Cc: Kalle Jokiniemi kalle.jokini...@digia.com
Cc: Lauri Leukkunen lauri.leukku...@nokia.com
Cc: Juha Yrjola juha.yrj...@solidboot.com
---
 arch/arm/mach-omap2/Makefile   |1 +
 arch/arm/mach-omap2/board-rx51-sdram.c |  221 
 arch/arm/mach-omap2/board-rx51.c   |7 +-
 3 files changed, 228 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-omap2/board-rx51-sdram.c

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 03cb4fc..9cd745a 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_MACH_OMAP_3430SDP)   += 
board-3430sdp.o \
   mmc-twl4030.o
 obj-$(CONFIG_MACH_NOKIA_N8X0)  += board-n8x0.o
 obj-$(CONFIG_MACH_NOKIA_RX51)  += board-rx51.o \
+  board-rx51-sdram.o \
   board-rx51-peripherals.o \
   mmc-twl4030.o
 obj-$(CONFIG_MACH_OMAP_ZOOM2)  += board-zoom2.o \
diff --git a/arch/arm/mach-omap2/board-rx51-sdram.c 
b/arch/arm/mach-omap2/board-rx51-sdram.c
new file mode 100644
index 000..f392844
--- /dev/null
+++ b/arch/arm/mach-omap2/board-rx51-sdram.c
@@ -0,0 +1,221 @@
+/*
+ * SDRC register values for RX51
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Lauri Leukkunen lauri.leukku...@nokia.com
+ *
+ * Original code by Juha Yrjola juha.yrj...@solidboot.com
+ *
+ * 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.
+ */
+
+#include linux/kernel.h
+#include linux/clk.h
+#include linux/err.h
+#include linux/io.h
+
+#include plat/io.h
+#include plat/common.h
+#include plat/clock.h
+#include plat/sdrc.h
+
+
+/* In picoseconds, except for tREF (ns), tXP, tCKE, tWTR (clks) */
+struct sdram_timings {
+   u32 casl;
+   u32 tDAL;
+   u32 tDPL;
+   u32 tRRD;
+   u32 tRCD;
+   u32 tRP;
+   u32 tRAS;
+   u32 tRC;
+   u32 tRFC;
+   u32 tXSR;
+
+   u32 tREF; /* in ns */
+
+   u32 tXP;
+   u32 tCKE;
+   u32 tWTR;
+};
+
+struct omap_sdrc_params rx51_sdrc_params[4];
+
+static const struct sdram_timings rx51_timings[] = {
+   {
+   .casl = 3,
+   .tDAL = 33000,
+   .tDPL = 15000,
+   .tRRD = 12000,
+   .tRCD = 22500,
+   .tRP = 18000,
+   .tRAS = 42000,
+   .tRC = 66000,
+   .tRFC = 138000,
+   .tXSR = 20,
+
+   .tREF = 7800,
+
+   .tXP = 2,
+   .tCKE = 2,
+   .tWTR = 2
+   },
+};
+
+static unsigned long sdrc_get_fclk_period(long rate)
+{
+   /* In picoseconds */
+   return 10 / rate;
+}
+
+static unsigned int sdrc_ps_to_ticks(unsigned int time_ps, long rate)
+{
+   unsigned long tick_ps;
+
+   /* Calculate in picosecs to yield more exact results */
+   tick_ps = sdrc_get_fclk_period(rate);
+
+   return (time_ps + tick_ps - 1) / tick_ps;
+}
+#undef DEBUG
+#ifdef DEBUG
+static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
+   int ticks, long rate, const char *name)
+#else
+static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
+  int ticks)
+#endif
+{
+   int mask, nr_bits;
+
+   nr_bits = end_bit - st_bit + 1;
+   if (ticks = 1  nr_bits)
+   return -1;
+   mask = (1  nr_bits) - 1;
+   *regval = ~(mask  st_bit);
+   *regval |= ticks  st_bit;
+#ifdef DEBUG
+   printk(KERN_INFO SDRC %s: %i ticks %i ns\n, name, ticks,
+   (unsigned int)sdrc_get_fclk_period(rate) * ticks /
+   1000);
+#endif
+
+   return 0;
+}
+
+#ifdef DEBUG
+#define SDRC_SET_ONE(reg, st, end, field, rate) \
+   if (set_sdrc_timing_regval((reg), (st), (end), \
+   rx51_timings-field, (rate), #field)  0) \
+   err = -1;
+#else
+#define SDRC_SET_ONE(reg, st, end, field, rate) \
+   if (set_sdrc_timing_regval((reg), (st), (end), \
+   rx51_timings-field)  0) \
+   err = -1;
+#endif
+
+#ifdef DEBUG
+static int set_sdrc_timing_regval_ps(u32 *regval, int st_bit, int end_bit,
+   int time, long rate, const char

[PATCH] OMAP3: Clock: Fixed dpll3_m2x2 rate calculation

2009-10-28 Thread Tero Kristo
From: Tero Kristo tero.kri...@nokia.com

Current calculation does not take into account any changes to M2 divisor, and
thus when we change VDD2 OPP, dpll3_m2x2 rate does not change. Fixed by
re-routing dpll3_m2x2 parent to dpll3_m2.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/clock34xx.h |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index a1b3de7..8fe1bcb 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -489,9 +489,9 @@ static struct clk core_ck = {
 static struct clk dpll3_m2x2_ck = {
.name   = dpll3_m2x2_ck,
.ops= clkops_null,
-   .parent = dpll3_x2_ck,
+   .parent = dpll3_m2_ck,
.clkdm_name = dpll3_clkdm,
-   .recalc = followparent_recalc,
+   .recalc = omap3_clkoutx2_recalc,
 };
 
 /* The PWRDN bit is apparently only available on 3430ES2 and above */
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/5] OMAP3: Fixed ARM aux ctrl register save/restore

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

Current value is stored on SDRAM and it is written back during wakeup.
Previously a static value of 0x72 was written there.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/sleep34xx.S |   13 +
 1 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index 4707ba8..8bd5fc5 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -278,7 +278,8 @@ restore:
mov r1, #0  @ set task id for ROM code in r1
mov r2, #4  @ set some flags in r2, r6
mov r6, #0xff
-   adr r3, write_aux_control_params@ r3 points to parameters
+   ldr r4, scratchpad_base
+   ldr r3, [r4, #0xBC] @ r3 points to parameters
mcr p15, 0, r0, c7, c10, 4  @ data write barrier
mcr p15, 0, r0, c7, c10, 5  @ data memory barrier
.word   0xE1600071  @ call SMI monitor (smi #1)
@@ -286,14 +287,14 @@ restore:
b   logic_l1_restore
 l2_inv_api_params:
.word   0x1, 0x00
-write_aux_control_params:
-   .word   0x1, 0x72
 l2_inv_gp:
/* Execute smi to invalidate L2 cache */
mov r12, #0x1 @ set up to invalide L2
 smi:.word 0xE1600070   @ Call SMI monitor (smieq)
/* Write to Aux control register to set some bits */
-   mov r0, #0x72
+   ldr r4, scratchpad_base
+   ldr r3, [r4,#0xBC]
+   ldr r0, [r3,#4]
mov r12, #0x3
.word 0xE1600070@ Call SMI monitor (smieq)
 logic_l1_restore:
@@ -304,6 +305,7 @@ logic_l1_restore:
 
ldr r4, scratchpad_base
ldr r3, [r4,#0xBC]
+   addsr3, r3, #8
ldmia   r3!, {r4-r6}
mov sp, r4
msr spsr_cxsf, r5
@@ -420,6 +422,9 @@ usettbr0:
 save_context_wfi:
/*b save_context_wfi*/  @ enable to debug save code
mov r8, r0 /* Store SDRAM address in r8 */
+   mrc p15, 0, r5, c1, c0, 1   @ Read Auxiliary Control Register
+   mov r4, #0x1@ Number of parameters for restore call
+   stmia   r8!, {r4-r5}
 /* Check what that target sleep state is:stored in r1*/
 /* 1 - Only L1 and logic lost */
 /* 2 - Only L2 lost */
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/5] OMAP3: PM: Write voltage and clock setup times dynamically in idle loop

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

It is suggested by TI (SWPA152 February 2009) to write clksetup,
voltsetup_time1, voltsetup_time2, voltsetup2 dynamically in idle loop.

This allows us to optimize the voltage + clock setup times according to the
used power save mode.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/pm.h |   10 -
 arch/arm/mach-omap2/pm34xx.c |   87 +++--
 2 files changed, 57 insertions(+), 40 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index b576424..d10e0c1 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -24,12 +24,18 @@ extern int omap3_can_sleep(void);
 extern int set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap3_idle_init(void);
 
-struct prm_setup_vc {
+struct prm_setup_times_vc {
u16 clksetup;
u16 voltsetup_time1;
u16 voltsetup_time2;
-   u16 voltoffset;
u16 voltsetup2;
+   u16 voltsetup1;
+};
+
+struct prm_setup_vc {
+   struct prm_setup_times_vc *setup_times;
+   struct prm_setup_times_vc *setup_times_off;
+   u16 voltoffset;
 /* PRM_VC_CMD_VAL_0 specific bits */
u16 vdd0_on;
u16 vdd0_onlp;
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 796d726..2f9f4a0 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -82,12 +82,17 @@ static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
 static struct powerdomain *cam_pwrdm;
 
-static struct prm_setup_vc prm_setup = {
+static struct prm_setup_times_vc prm_setup_times_default = {
.clksetup = 0xff,
.voltsetup_time1 = 0xfff,
.voltsetup_time2 = 0xfff,
-   .voltoffset = 0xff,
.voltsetup2 = 0xff,
+};
+
+static struct prm_setup_vc prm_setup_default = {
+   .setup_times = prm_setup_times_default,
+   .setup_times_off = NULL,
+   .voltoffset = 0xff,
.vdd0_on = 0x30,/* 1.2v */
.vdd0_onlp = 0x20,  /* 1.0v */
.vdd0_ret = 0x1e,   /* 0.975v */
@@ -98,6 +103,8 @@ static struct prm_setup_vc prm_setup = {
.vdd1_off = 0x00,   /* 0.6v */
 };
 
+static struct prm_setup_vc *prm_setup = prm_setup_default;
+
 static inline void omap3_per_save_context(void)
 {
omap_gpio_save_context();
@@ -338,6 +345,16 @@ static void restore_table_entry(void)
restore_control_register(control_reg_value);
 }
 
+static void prm_program_setup_times(struct prm_setup_times_vc *times)
+{
+   prm_write_mod_reg(times-voltsetup1, OMAP3430_GR_MOD,
+   OMAP3_PRM_VOLTSETUP1_OFFSET);
+   prm_write_mod_reg(times-voltsetup2, OMAP3430_GR_MOD,
+   OMAP3_PRM_VOLTSETUP2_OFFSET);
+   prm_write_mod_reg(times-clksetup, OMAP3430_GR_MOD,
+   OMAP3_PRM_CLKSETUP_OFFSET);
+}
+
 void omap_sram_idle(void)
 {
/* Variable to tell what needs to be saved and restored
@@ -422,6 +439,9 @@ void omap_sram_idle(void)
 OMAP3_PRM_VOLTCTRL_OFFSET);
omap3_core_save_context();
omap3_prcm_save_context();
+   if (prm_setup-setup_times_off != NULL)
+   prm_program_setup_times(prm_setup-
+   setup_times_off);
} else if (core_next_state == PWRDM_POWER_RET) {
prm_set_mod_reg_bits(OMAP3430_AUTO_RET,
OMAP3430_GR_MOD,
@@ -479,11 +499,13 @@ void omap_sram_idle(void)
}
omap_uart_resume_idle(0);
omap_uart_resume_idle(1);
-   if (core_next_state == PWRDM_POWER_OFF)
+   if (core_next_state == PWRDM_POWER_OFF) {
prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF,
   OMAP3430_GR_MOD,
   OMAP3_PRM_VOLTCTRL_OFFSET);
-   else if (core_next_state == PWRDM_POWER_RET)
+   if (prm_setup-setup_times_off != NULL)
+   prm_program_setup_times(prm_setup-setup_times);
+   } else if (core_next_state == PWRDM_POWER_RET)
prm_clear_mod_reg_bits(OMAP3430_AUTO_RET,
OMAP3430_GR_MOD,
OMAP3_PRM_VOLTCTRL_OFFSET);
@@ -1043,24 +1065,21 @@ int omap3_pm_set_suspend_state(struct powerdomain 
*pwrdm, int state)
return -EINVAL;
 }
 
+static void omap3_init_prm_setup_times(struct prm_setup_times_vc *conf)
+{
+   if (!conf)
+   return;
+
+   conf-voltsetup1 =
+   (conf-voltsetup_time2  OMAP3430_SETUP_TIME2_SHIFT) |
+   (conf-voltsetup_time1  OMAP3430_SETUP_TIME1_SHIFT);
+}
+
 void

[PATCH 5/5] OMAP3: PM: Disable OTG autoidle when waking up from off-mode

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

OMAP3 sleep can be prevented in some cases where OTG autoidle is enabled.
This patch force disables autoidle during wakeup from off-mode. See omap
errata 1.164.

This fix can't be done in driver level, as off-mode entry resets and enables
the autoidle bit, and driver does not access the register after each off-mode
entry even if it is loaded.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/pm34xx.c  |6 ++
 arch/arm/mach-omap2/usb-musb.c|   14 --
 arch/arm/plat-omap/include/plat/usb.h |3 +++
 3 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 2f9f4a0..ab7b30f 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -37,6 +37,7 @@
 #include plat/gpmc.h
 #include plat/dma.h
 #include plat/dmtimer.h
+#include plat/usb.h
 
 #include plat/resource.h
 
@@ -496,6 +497,11 @@ void omap_sram_idle(void)
omap3_prcm_restore_context();
omap3_sram_restore_context();
omap2_sms_restore_context();
+   /*
+* Errata 1.164 fix : OTG autoidle can prevent
+* sleep
+*/
+   usb_musb_disable_autoidle();
}
omap_uart_resume_idle(0);
omap_uart_resume_idle(1);
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index f5364b8..bb3cee4 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -44,10 +44,11 @@ static struct platform_device dummy_pdev = {
},
 };
 
+static void __iomem *otg_base;
+static struct clk *otg_clk;
+
 static void __init usb_musb_pm_init(void)
 {
-   void __iomem *otg_base;
-   struct clk *otg_clk;
struct device *dev = dummy_pdev.dev;
 
if (!cpu_is_omap34xx())
@@ -74,12 +75,13 @@ static void __init usb_musb_pm_init(void)
cpu_relax();
}
 
-   if (otg_clk) {
+   if (otg_clk)
clk_disable(otg_clk);
-   clk_put(otg_clk);
-   }
+}
 
-   iounmap(otg_base);
+void usb_musb_disable_autoidle(void)
+{
+   __raw_writel(0, otg_base + OTG_SYSCONFIG);
 }
 
 #ifdef CONFIG_USB_MUSB_SOC
diff --git a/arch/arm/plat-omap/include/plat/usb.h 
b/arch/arm/plat-omap/include/plat/usb.h
index 33a500e..31b13bc 100644
--- a/arch/arm/plat-omap/include/plat/usb.h
+++ b/arch/arm/plat-omap/include/plat/usb.h
@@ -46,6 +46,9 @@ extern void usb_musb_init(void);
 
 extern void usb_ehci_init(struct ehci_hcd_omap_platform_data *pdata);
 
+/* This is needed for OMAP3 errata 1.164: enabled autoidle can prevent sleep */
+extern void usb_musb_disable_autoidle(void);
+
 #endif
 
 void omap_usb_init(struct omap_usb_config *pdata);
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/5] OMAP3: PM: Added support for L2 aux ctrl register save and restore

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

This patch adds a save and restore mechanism for ARM L2 auxiliary control
register. The feature is enabled by default for GP devices, but for HS/EMU
devices the user must enable the service and define the PPA service ID to
be used for setting L2 aux ctrl, as this is not currently supported by the
bootloader. If nobody alters the contents of L2 aux ctrl from its reset
value, this feature is not needed.

Kconfig option to enable HS/EMU L2 aux save and restore:
- OMAP3_L2_AUX_SECURE_SAVE_RESTORE
Kconfig option to select HS/EMU PPA service for setting L2 aux ctrl:
- OMAP3_L2_AUX_SECURE_SERVICE_SET_ID

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/sleep34xx.S |   26 --
 arch/arm/plat-omap/Kconfig  |   17 +
 2 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index 8bd5fc5..69521be 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -284,6 +284,21 @@ restore:
mcr p15, 0, r0, c7, c10, 5  @ data memory barrier
.word   0xE1600071  @ call SMI monitor (smi #1)
 
+#ifdef CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE
+   /* Restore L2 aux control register */
+   @ set service ID for PPA
+   mov r0, #CONFIG_OMAP3_L2_AUX_SECURE_SERVICE_SET_ID
+   mov r12, r0 @ copy service ID in r12
+   mov r1, #0  @ set task ID for ROM code in r1
+   mov r2, #4  @ set some flags in r2, r6
+   mov r6, #0xff
+   ldr r4, scratchpad_base
+   ldr r3, [r4, #0xBC]
+   addsr3, r3, #8  @ r3 points to parameters
+   mcr p15, 0, r0, c7, c10, 4  @ data write barrier
+   mcr p15, 0, r0, c7, c10, 5  @ data memory barrier
+   .word   0xE1600071  @ call SMI monitor (smi #1)
+#endif
b   logic_l1_restore
 l2_inv_api_params:
.word   0x1, 0x00
@@ -297,6 +312,11 @@ smi:.word 0xE1600070   @ Call SMI monitor 
(smieq)
ldr r0, [r3,#4]
mov r12, #0x3
.word 0xE1600070@ Call SMI monitor (smieq)
+   ldr r4, scratchpad_base
+   ldr r3, [r4,#0xBC]
+   ldr r0, [r3,#12]
+   mov r12, #0x2
+   .word 0xE1600070@ Call SMI monitor (smieq)
 logic_l1_restore:
mov r1, #0
/* Invalidate all instruction caches to PoU
@@ -305,7 +325,7 @@ logic_l1_restore:
 
ldr r4, scratchpad_base
ldr r3, [r4,#0xBC]
-   addsr3, r3, #8
+   addsr3, r3, #16
ldmia   r3!, {r4-r6}
mov sp, r4
msr spsr_cxsf, r5
@@ -424,7 +444,9 @@ save_context_wfi:
mov r8, r0 /* Store SDRAM address in r8 */
mrc p15, 0, r5, c1, c0, 1   @ Read Auxiliary Control Register
mov r4, #0x1@ Number of parameters for restore call
-   stmia   r8!, {r4-r5}
+   stmia   r8!, {r4-r5}@ Push parameters for restore call
+   mrc p15, 1, r5, c9, c0, 2   @ Read L2 AUX ctrl register
+   stmia   r8!, {r4-r5}@ Push parameters for restore call
 /* Check what that target sleep state is:stored in r1*/
 /* 1 - Only L1 and logic lost */
 /* 2 - Only L2 lost */
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 2143db5..3ff1a5f 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -185,6 +185,23 @@ config OMAP3_DEBOBS
help
  Use ETK pads for debug observability
 
+config OMAP3_L2_AUX_SECURE_SAVE_RESTORE
+   bool OMAP3 HS/EMU save and restore for L2 AUX control register
+   depends on ARCH_OMAP3  PM
+   default n
+   help
+ Without this option, L2 Auxiliary control register contents are
+ lost during off-mode entry on HS/EMU devices. This feature
+ requires support from PPA / boot-loader in HS/EMU devices, which
+ currently does not exist by default.
+
+config OMAP3_L2_AUX_SECURE_SERVICE_SET_ID
+   int Service ID for the support routine to set L2 AUX control
+   depends on OMAP3_L2_AUX_SECURE_SAVE_RESTORE
+   default 43
+   help
+ PPA routine service ID for setting L2 auxiliary control register.
+
 config OMAP_32K_TIMER_HZ
int Kernel internal timer frequency for 32KHz timer
range 32 1024
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv3 0/5] Misc fixes [for PM branch]

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

This set contains following changes compared to previous one:

1) Removed accepted patches
2) ARM aux ctrl and L2 aux ctrl register save/restore uses now arm_context
   as save area
3) Added more detail to I2C4 repeated start disable fix description
4) Refreshed patches against PM branch


--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/5] OMAP3: PM: Disabled I2C4 repeated start operation mode

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

Repeated start forces I2C4 pads low during idle, which increases power
consumption through external pull-ups. On the other hand, this change
increases I2C4 command latencies somewhat due to additional master code
sent in the beginning of each I2C4 command (8 bits data + start + ack bits
in fast/standard mode = increases total command duration from 25us to 50us.)

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

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index b97f7d8..796d726 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -1221,7 +1221,7 @@ static void __init configure_vc(void)
prm_write_mod_reg(OMAP3430_CMD1 | OMAP3430_RAV1, OMAP3430_GR_MOD,
  OMAP3_PRM_VC_CH_CONF_OFFSET);
 
-   prm_write_mod_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN | OMAP3430_SREN,
+   prm_write_mod_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN,
  OMAP3430_GR_MOD,
  OMAP3_PRM_VC_I2C_CFG_OFFSET);
 
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/6] Idle status patches revisited

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

Following set implements checks for idle states of powerdomains, and
changes target cpuidle state according to those. This also includes as
a cleanup removal of some hacks from omap_sram_idle(), and also introduces
INACTIVE / ON state support for powerdomains which simplifies the code.

Applies on top of PM branch.


--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/6] OMAP3: PM: Removed PER + CORE state hacking from omap_sram_idle

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

This should be moved inside cpuidle to simplify design.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/pm34xx.c |   18 ++
 1 files changed, 2 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 7b52f30..c704756 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -81,7 +81,6 @@ static int (*_omap_save_secure_sram)(u32 *addr);
 
 static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
-static struct powerdomain *cam_pwrdm;
 
 static struct prm_setup_times_vc prm_setup_times_default = {
.clksetup = 0xff,
@@ -370,7 +369,6 @@ void omap_sram_idle(void)
int core_next_state = PWRDM_POWER_ON;
int core_prev_state, per_prev_state;
u32 sdrc_pwr = 0;
-   int per_state_modified = 0;
 
if (!_omap_sram_idle)
return;
@@ -409,19 +407,10 @@ void omap_sram_idle(void)
if (per_next_state  PWRDM_POWER_ON) {
omap_uart_prepare_idle(2);
omap2_gpio_prepare_for_idle(per_next_state);
-   if (per_next_state == PWRDM_POWER_OFF) {
-   if (core_next_state == PWRDM_POWER_ON) {
-   per_next_state = PWRDM_POWER_RET;
-   pwrdm_set_next_pwrst(per_pwrdm, per_next_state);
-   per_state_modified = 1;
-   } else
-   omap3_per_save_context();
-   }
+   if (per_next_state == PWRDM_POWER_OFF)
+   omap3_per_save_context();
}
 
-   if (pwrdm_read_pwrst(cam_pwrdm) == PWRDM_POWER_ON)
-   omap2_clkdm_deny_idle(mpu_pwrdm-pwrdm_clkdms[0]);
-
/*
 * Disable smartreflex before entering WFI.
 * Only needed if we are going to enter retention or off.
@@ -540,8 +529,6 @@ void omap_sram_idle(void)
omap3_gpio_restore_pad_context(1);
omap2_gpio_resume_after_idle();
omap_uart_resume_idle(2);
-   if (per_state_modified)
-   pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
}
 
/* Disable IO-PAD and IO-CHAIN wakeup */
@@ -1170,7 +1157,6 @@ static int __init omap3_pm_init(void)
neon_pwrdm = pwrdm_lookup(neon_pwrdm);
per_pwrdm = pwrdm_lookup(per_pwrdm);
core_pwrdm = pwrdm_lookup(core_pwrdm);
-   cam_pwrdm = pwrdm_lookup(cam_pwrdm);
 
omap_push_sram_idle();
 #ifdef CONFIG_SUSPEND
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/6] OMAP3: PM: Added support for INACTIVE and ON states for powerdomains

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

Previously omap_sram_idle() did not know about the difference between ON and
INACTIVE states, which complicated the state handling in these cases.

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

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 9d0a9b4..7b52f30 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -383,6 +383,7 @@ void omap_sram_idle(void)
mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
switch (mpu_next_state) {
case PWRDM_POWER_ON:
+   case PWRDM_POWER_INACTIVE:
case PWRDM_POWER_RET:
/* No need to save context */
save_state = 0;
@@ -448,9 +449,11 @@ void omap_sram_idle(void)
OMAP3430_GR_MOD,
OMAP3_PRM_VOLTCTRL_OFFSET);
}
-   /* Enable IO-PAD and IO-CHAIN wakeups */
-   prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
-   omap3_enable_io_chain();
+   if (core_next_state = PWRDM_POWER_RET) {
+   /* Enable IO-PAD and IO-CHAIN wakeups */
+   prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
+   omap3_enable_io_chain();
+   }
}
omap3_intc_prepare_idle();
 
@@ -542,15 +545,13 @@ void omap_sram_idle(void)
}
 
/* Disable IO-PAD and IO-CHAIN wakeup */
-   if (core_next_state  PWRDM_POWER_ON) {
+   if (core_next_state = PWRDM_POWER_ON) {
prm_clear_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
omap3_disable_io_chain();
}
 
 
pwrdm_post_transition();
-
-   omap2_clkdm_allow_idle(mpu_pwrdm-pwrdm_clkdms[0]);
 }
 
 int omap3_can_sleep(void)
@@ -598,7 +599,6 @@ int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
}
 
if (sleep_switch) {
-   omap2_clkdm_allow_idle(pwrdm-pwrdm_clkdms[0]);
pwrdm_wait_transition(pwrdm);
pwrdm_state_switch(pwrdm);
}
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[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

[PATCH 1/6] OMAP: Powerdomains: Add support for INACTIVE state on pwrdm level

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

Currently only ON, RET and OFF are supported, and ON is arguably broken as it
allows the powerdomain to enter INACTIVE state unless idle is prevented.
Now, pwrdm code prevents idle if ON is selected, and also adds support for
INACTIVE. This simplifies the control needed inside sleep code.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/powerdomain.c |   32 +
 arch/arm/mach-omap2/powerdomains34xx.h|   26 ++--
 arch/arm/plat-omap/include/plat/powerdomain.h |6 -
 3 files changed, 45 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index b6990e3..1237717 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -112,8 +112,8 @@ static struct powerdomain *_pwrdm_deps_lookup(struct 
powerdomain *pwrdm,
 static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 {
 
-   int prev;
-   int state;
+   u8 prev;
+   u8 state;
 
if (pwrdm == NULL)
return -EINVAL;
@@ -220,7 +220,7 @@ int pwrdm_register(struct powerdomain *pwrdm)
 
pr_debug(powerdomain: registered %s\n, pwrdm-name);
ret = 0;
-
+   pwrdm-next_state = -1;
 pr_unlock:
write_unlock_irqrestore(pwrdm_rwlock, flags);
 
@@ -701,19 +701,38 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
  */
 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 {
+   u8 prg_pwrst;
+
if (!pwrdm)
return -EINVAL;
 
+   if (pwrdm-next_state == pwrst)
+   return 0;
+
if (!(pwrdm-pwrsts  (1  pwrst)))
return -EINVAL;
 
pr_debug(powerdomain: setting next powerstate for %s to %0x\n,
 pwrdm-name, pwrst);
 
+   /* INACTIVE is reserved, so we program pwrdm as ON */
+   if (pwrst == PWRDM_POWER_INACTIVE)
+   prg_pwrst = PWRDM_POWER_ON;
+   else
+   prg_pwrst = pwrst;
+
prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
-(pwrst  OMAP_POWERSTATE_SHIFT),
+(prg_pwrst  OMAP_POWERSTATE_SHIFT),
 pwrdm-prcm_offs, PM_PWSTCTRL);
 
+   /* If next state is ON, prevent idle */
+   if (pwrst == PWRDM_POWER_ON)
+   omap2_clkdm_deny_idle(pwrdm-pwrdm_clkdms[0]);
+   else
+   omap2_clkdm_allow_idle(pwrdm-pwrdm_clkdms[0]);
+
+   pwrdm-next_state = pwrst;
+
return 0;
 }
 
@@ -730,8 +749,11 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
if (!pwrdm)
return -EINVAL;
 
+   if (pwrdm-next_state  -1)
+   return pwrdm-next_state;
+
return prm_read_mod_bits_shift(pwrdm-prcm_offs, PM_PWSTCTRL,
-   OMAP_POWERSTATE_MASK);
+  OMAP_POWERSTATE_MASK);
 }
 
 /**
diff --git a/arch/arm/mach-omap2/powerdomains34xx.h 
b/arch/arm/mach-omap2/powerdomains34xx.h
index fd09b08..9eb2dc5 100644
--- a/arch/arm/mach-omap2/powerdomains34xx.h
+++ b/arch/arm/mach-omap2/powerdomains34xx.h
@@ -165,7 +165,7 @@ static struct powerdomain iva2_pwrdm = {
.omap_chip= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.dep_bit  = OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
.wkdep_srcs   = iva2_wkdeps,
-   .pwrsts   = PWRSTS_OFF_RET_ON,
+   .pwrsts   = PWRSTS_OFF_RET_INA_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks= 4,
.pwrsts_mem_ret   = {
@@ -188,7 +188,7 @@ static struct powerdomain mpu_34xx_pwrdm = {
.omap_chip= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.dep_bit  = OMAP3430_EN_MPU_SHIFT,
.wkdep_srcs   = mpu_34xx_wkdeps,
-   .pwrsts   = PWRSTS_OFF_RET_ON,
+   .pwrsts   = PWRSTS_OFF_RET_INA_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks= 1,
.pwrsts_mem_ret   = {
@@ -206,7 +206,7 @@ static struct powerdomain core_34xx_pre_es3_1_pwrdm = {
.omap_chip= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
   CHIP_IS_OMAP3430ES2 |
   CHIP_IS_OMAP3430ES3_0),
-   .pwrsts   = PWRSTS_OFF_RET_ON,
+   .pwrsts   = PWRSTS_OFF_RET_INA_ON,
.dep_bit  = OMAP3430_EN_CORE_SHIFT,
.banks= 2,
.pwrsts_mem_ret   = {
@@ -214,8 +214,8 @@ static struct powerdomain core_34xx_pre_es3_1_pwrdm = {
[1] = PWRSTS_OFF_RET,/* MEM2RETSTATE */
},
.pwrsts_mem_on= {
-   [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
-   [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
+   [0] = PWRSTS_OFF_RET_INA_ON, /* MEM1ONSTATE */
+   [1] = PWRSTS_OFF_RET_INA_ON, /* MEM2ONSTATE

[PATCH 3/6] OMAP3: CPUidle: Fixed support for ON / INACTIVE states

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

New powerdomain code support for INACTIVE state removes the need to control
clockdomains directly from cpuidle. Also, cpuidle state definitions can now
directly support ON / INACTIVE simplifying the implementation.

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

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index fdfa1d5..e46345f 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -91,20 +91,6 @@ static int omap3_idle_bm_check(void)
return 0;
 }
 
-static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
-{
-   omap2_clkdm_allow_idle(clkdm);
-   return 0;
-}
-
-static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
-{
-   omap2_clkdm_deny_idle(clkdm);
-   return 0;
-}
-
 /**
  * omap3_enter_idle - Programs OMAP3 to enter the specified state
  * @dev: cpuidle device
@@ -141,19 +127,9 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
if (omap_irq_pending() || need_resched())
goto return_sleep_time;
 
-   if (cx-type == OMAP3_STATE_C1) {
-   pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
-   pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
-   }
-
/* Execute ARM wfi */
omap_sram_idle();
 
-   if (cx-type == OMAP3_STATE_C1) {
-   pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
-   pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
-   }
-
 return_sleep_time:
getnstimeofday(ts_postidle);
ts_idle = timespec_sub(ts_postidle, ts_preidle);
@@ -242,8 +218,8 @@ void omap_init_power_states(void)
cpuidle_params_table[OMAP3_STATE_C2].wake_latency;
omap3_power_states[OMAP3_STATE_C2].threshold =
cpuidle_params_table[OMAP3_STATE_C2].threshold;
-   omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON;
-   omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_INACTIVE;
+   omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID;
 
/* C3 . MPU CSWR + Core inactive */
@@ -256,7 +232,7 @@ void omap_init_power_states(void)
omap3_power_states[OMAP3_STATE_C3].threshold =
cpuidle_params_table[OMAP3_STATE_C3].threshold;
omap3_power_states[OMAP3_STATE_C3].mpu_state = PWRDM_POWER_RET;
-   omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
 
@@ -270,7 +246,7 @@ void omap_init_power_states(void)
omap3_power_states[OMAP3_STATE_C4].threshold =
cpuidle_params_table[OMAP3_STATE_C4].threshold;
omap3_power_states[OMAP3_STATE_C4].mpu_state = PWRDM_POWER_OFF;
-   omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
 
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/6] OMAP: Powerdomains: Add support for checking if pwrdm can idle

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

pwrdm_can_idle(pwrdm) will check if the specified powerdomain can enter
idle. This is done by checking the current fclk enable bits.

This call can be used e.g. inside cpuidle to decide which power states
core and mpu should enter during idle, as there are certain dependencies
between wakeup capabilities and reset logic.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/powerdomain.c |   22 ++
 arch/arm/mach-omap2/powerdomains34xx.h|   14 ++
 arch/arm/plat-omap/include/plat/powerdomain.h |9 +
 3 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 1237717..bf2b97a 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -1217,6 +1217,28 @@ int pwrdm_wait_transition(struct powerdomain *pwrdm)
return 0;
 }
 
+/**
+ * pwrdm_can_idle - check if the powerdomain can enter idle
+ * @pwrdm: struct powerdomain * the powerdomain to check status of
+ *
+ * Does a functional clock check for the powerdomain and returns 1 if the
+ * powerdomain can enter idle, 0 if not.
+ */
+int pwrdm_can_idle(struct powerdomain *pwrdm)
+{
+   int i;
+   const int fclk_regs[] = { CM_FCLKEN, OMAP3430ES2_CM_FCLKEN3 };
+
+   if (!pwrdm)
+   return -EINVAL;
+
+   for (i = 0; i  pwrdm-fclk_reg_amt; i++)
+   if (cm_read_mod_reg(pwrdm-prcm_offs, fclk_regs[i]) 
+   (0x ^ pwrdm-fclk_masks[i]))
+   return 0;
+   return 1;
+}
+
 int pwrdm_state_switch(struct powerdomain *pwrdm)
 {
return _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
diff --git a/arch/arm/mach-omap2/powerdomains34xx.h 
b/arch/arm/mach-omap2/powerdomains34xx.h
index 9eb2dc5..c8cd297 100644
--- a/arch/arm/mach-omap2/powerdomains34xx.h
+++ b/arch/arm/mach-omap2/powerdomains34xx.h
@@ -180,6 +180,7 @@ static struct powerdomain iva2_pwrdm = {
[2] = PWRSTS_OFF_ON,
[3] = PWRDM_POWER_ON,
},
+   .fclk_reg_amt = 1,
 };
 
 static struct powerdomain mpu_34xx_pwrdm = {
@@ -236,6 +237,11 @@ static struct powerdomain core_34xx_es3_1_pwrdm = {
[0] = PWRSTS_OFF_RET_INA_ON, /* MEM1ONSTATE */
[1] = PWRSTS_OFF_RET_INA_ON, /* MEM2ONSTATE */
},
+   .fclk_reg_amt = 2,
+   .fclk_masks   = {
+   [0] = OMAP3430_EN_UART2 | OMAP3430_EN_UART1,
+   [1] = 0,
+   },
 };
 
 /* Another case of bit name collisions between several registers: EN_DSS */
@@ -255,6 +261,7 @@ static struct powerdomain dss_pwrdm = {
.pwrsts_mem_on= {
[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
},
+   .fclk_reg_amt = 1,
 };
 
 /*
@@ -278,6 +285,7 @@ static struct powerdomain sgx_pwrdm = {
.pwrsts_mem_on= {
[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
},
+   .fclk_reg_amt = 1,
 };
 
 static struct powerdomain cam_pwrdm = {
@@ -295,6 +303,7 @@ static struct powerdomain cam_pwrdm = {
.pwrsts_mem_on= {
[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
},
+   .fclk_reg_amt = 1,
 };
 
 static struct powerdomain per_pwrdm = {
@@ -313,6 +322,10 @@ static struct powerdomain per_pwrdm = {
.pwrsts_mem_on= {
[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
},
+   .fclk_reg_amt = 1,
+   .fclk_masks   = {
+   [0] = OMAP3430_EN_UART3,
+   },
 };
 
 static struct powerdomain emu_pwrdm = {
@@ -352,6 +365,7 @@ static struct powerdomain usbhost_pwrdm = {
.pwrsts_mem_on= {
[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
},
+   .fclk_reg_amt = 1,
 };
 
 static struct powerdomain dpll1_pwrdm = {
diff --git a/arch/arm/plat-omap/include/plat/powerdomain.h 
b/arch/arm/plat-omap/include/plat/powerdomain.h
index 55350d0..b004d88 100644
--- a/arch/arm/plat-omap/include/plat/powerdomain.h
+++ b/arch/arm/plat-omap/include/plat/powerdomain.h
@@ -57,6 +57,12 @@
  */
 #define PWRDM_MAX_CLKDMS   4
 
+/*
+ * Maximum number of FCLK register masks that can be associated with a
+ * powerdomain. CORE powerdomain on OMAP3 is the worst case
+ */
+#define PWRDM_MAX_FCLK 2
+
 /* XXX A completely arbitrary number. What is reasonable here? */
 #define PWRDM_TRANSITION_BAILOUT 10
 
@@ -124,6 +130,8 @@ struct powerdomain {
s8 next_state;
unsigned state_counter[4];
 
+   u8 fclk_reg_amt;
+   u32 fclk_masks[PWRDM_MAX_FCLK];
 #ifdef CONFIG_PM_DEBUG
s64 timer;
s64 state_timer[4];
@@ -177,6 +185,7 @@ int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm);
 bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
 
 int pwrdm_wait_transition(struct powerdomain *pwrdm);
+int pwrdm_can_idle(struct powerdomain *pwrdm);
 
 int pwrdm_state_switch(struct

[PATCH 0/2] VFP context save/restore support for OMAP3

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

These two patches add support for VFP context save and restore. These patches
are a collaboration from several people (listed in CC), I have mainly
split the original patch in two parts (one generic ARM, one for OMAP3 PM),
and optimized the code a bit. No sign-offs added from anybody except myself
at the moment because I have modified the patches quite heavily.

I think patch #1 should actually go to linux-arm list, however I thought to
get some comments about the patches on omap list first.

These will apply on top of PM branch.

-Tero


--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] OMAP3: Implemented VFP restore/save context

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

VFP save context is called before MPU/NEON off. Restore is not needed as
the next VFP trap will restore context automatically. Uses the support
routine implemented in arch/arm/vfp/vfpmodule.c.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
Cc: Vishwanath Sripathy vishwanath...@ti.com
Cc: Rajendra Nayak rna...@ti.com
Cc: Richard Woodruff r-woodru...@ti.com
Cc: Peter 'p2' De Schrijver peter.de-schrij...@nokia.com
---
 arch/arm/mach-omap2/pm.h |1 +
 arch/arm/mach-omap2/pm34xx.c |   21 -
 2 files changed, 21 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 4f22107..dd5bbaf 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -18,6 +18,7 @@ extern u32 sleep_while_idle;
 extern u32 voltage_off_while_idle;
 
 extern void *omap3_secure_ram_storage;
+extern void vfp_pm_save_context(void);
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
 extern int omap3_can_sleep(void);
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index b26ae5b..4b01303 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -321,6 +321,18 @@ static void restore_control_register(u32 val)
__asm__ __volatile__ (mcr p15, 0, %0, c1, c0, 0 : : r (val));
 }
 
+static inline void omap3_save_neon_context(void)
+{
+#ifdef CONFIG_VFP
+   vfp_pm_save_context();
+#endif
+}
+
+static inline void omap3_restore_neon_context(void)
+{
+   return;
+}
+
 /* Function to restore the table entry that was modified for enabling MMU */
 static void restore_table_entry(void)
 {
@@ -365,6 +377,7 @@ void omap_sram_idle(void)
/* save_state = 3 = L1, L2 and logic lost */
int save_state = 0;
int mpu_next_state = PWRDM_POWER_ON;
+   int neon_next_state = PWRDM_POWER_ON;
int per_next_state = PWRDM_POWER_ON;
int core_next_state = PWRDM_POWER_ON;
int core_prev_state, per_prev_state;
@@ -398,8 +411,12 @@ void omap_sram_idle(void)
pwrdm_pre_transition();
 
/* NEON control */
-   if (pwrdm_read_pwrst(neon_pwrdm) == PWRDM_POWER_ON)
+   if (pwrdm_read_pwrst(neon_pwrdm) == PWRDM_POWER_ON) {
pwrdm_set_next_pwrst(neon_pwrdm, mpu_next_state);
+   neon_next_state = mpu_next_state;
+   if (neon_next_state == PWRDM_POWER_OFF)
+   omap3_save_neon_context();
+   }
 
/* PER */
per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
@@ -537,6 +554,8 @@ void omap_sram_idle(void)
omap3_disable_io_chain();
}
 
+   if (neon_next_state == PWRDM_POWER_OFF)
+   omap3_restore_neon_context();
 
pwrdm_post_transition();
 }
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] ARM: Implemented support for VFP PM context saving

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

In some ARM architectures, like OMAP3, the VFP context can be lost during
dynamic sleep cycle. For this purpose, there is now a function
vfp_pm_save_context() that should be called before the VFP is assumed to
lose context. Next VFP trap will then restore context automatically.

We need to have the last_VFP_context[cpu] cleared after the save in idle,
else the restore would fail to restore when it sees that the last_VFP_context
is same as the current threads vfp_state. This happens when the same
process/thread traps an exception post idle.

Main work for this patch was done by Peter and Rajendra. Some cleanup and
optimization by Tero.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
Cc: Vishwanath Sripathy vishwanath...@ti.com
Cc: Rajendra Nayak rna...@ti.com
Cc: Richard Woodruff r-woodru...@ti.com
Cc: Peter 'p2' De Schrijver peter.de-schrij...@nokia.com
---
 arch/arm/vfp/vfpmodule.c |   25 +
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 2d7423a..80a08bd 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -329,6 +329,31 @@ static void vfp_enable(void *unused)
 #ifdef CONFIG_PM
 #include linux/sysdev.h
 
+void vfp_pm_save_context(void)
+{
+   struct thread_info *thread = current_thread_info();
+   u32 fpexc = fmrx(FPEXC);
+   __u32 cpu = thread-cpu;
+
+   if (last_VFP_context[cpu]) {
+   if (!(fpexc  FPEXC_EN)) {
+   /* enable vfp now to save context */
+   vfp_enable(NULL);
+   fmxr(FPEXC, fmrx(FPEXC) | FPEXC_EN);
+   }
+   vfp_save_state(last_VFP_context[cpu], fpexc);
+
+   /* Disable vfp. The next inst traps an exception and restores*/
+   fmxr(FPEXC, fmrx(FPEXC)  ~FPEXC_EN);
+
+   /*
+* This is needed else the restore might fail if it sees
+* last_VFP_context if same as the current threads vfp_state.
+*/
+   last_VFP_context[cpu] = NULL;
+   }
+}
+
 static int vfp_pm_suspend(struct sys_device *dev, pm_message_t state)
 {
struct thread_info *ti = current_thread_info();
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] OMAP3: Implemented VFP restore/save context

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

VFP save context is called before MPU/NEON off. Restore is not needed as
the next VFP trap will restore context automatically. Uses the support
routine implemented in arch/arm/vfp/vfpmodule.c.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
Acked-by: Tony Lindgren t...@atomide.com
Cc: Vishwanath Sripathy vishwanath...@ti.com
Cc: Rajendra Nayak rna...@ti.com
Cc: Richard Woodruff r-woodru...@ti.com
Cc: Peter 'p2' De Schrijver peter.de-schrij...@nokia.com
---
 arch/arm/mach-omap2/pm.h |1 +
 arch/arm/mach-omap2/pm34xx.c |   21 -
 2 files changed, 21 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 4f22107..dd5bbaf 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -18,6 +18,7 @@ extern u32 sleep_while_idle;
 extern u32 voltage_off_while_idle;
 
 extern void *omap3_secure_ram_storage;
+extern void vfp_pm_save_context(void);
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
 extern int omap3_can_sleep(void);
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index b26ae5b..4b01303 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -321,6 +321,18 @@ static void restore_control_register(u32 val)
__asm__ __volatile__ (mcr p15, 0, %0, c1, c0, 0 : : r (val));
 }
 
+static inline void omap3_save_neon_context(void)
+{
+#ifdef CONFIG_VFP
+   vfp_pm_save_context();
+#endif
+}
+
+static inline void omap3_restore_neon_context(void)
+{
+   return;
+}
+
 /* Function to restore the table entry that was modified for enabling MMU */
 static void restore_table_entry(void)
 {
@@ -365,6 +377,7 @@ void omap_sram_idle(void)
/* save_state = 3 = L1, L2 and logic lost */
int save_state = 0;
int mpu_next_state = PWRDM_POWER_ON;
+   int neon_next_state = PWRDM_POWER_ON;
int per_next_state = PWRDM_POWER_ON;
int core_next_state = PWRDM_POWER_ON;
int core_prev_state, per_prev_state;
@@ -398,8 +411,12 @@ void omap_sram_idle(void)
pwrdm_pre_transition();
 
/* NEON control */
-   if (pwrdm_read_pwrst(neon_pwrdm) == PWRDM_POWER_ON)
+   if (pwrdm_read_pwrst(neon_pwrdm) == PWRDM_POWER_ON) {
pwrdm_set_next_pwrst(neon_pwrdm, mpu_next_state);
+   neon_next_state = mpu_next_state;
+   if (neon_next_state == PWRDM_POWER_OFF)
+   omap3_save_neon_context();
+   }
 
/* PER */
per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
@@ -537,6 +554,8 @@ void omap_sram_idle(void)
omap3_disable_io_chain();
}
 
+   if (neon_next_state == PWRDM_POWER_OFF)
+   omap3_restore_neon_context();
 
pwrdm_post_transition();
 }
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/2] VFP save/restore for OMAP3

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

Hi,

The following two patches are needed by OMAP3 to save/restore VFP context
during off-mode. Patch 1 adds generic support inside ARM VFP code, and the
second one adds the necessary hooks into OMAP3 power management code.

--Tero


--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] ARM: Implemented support for VFP PM context saving

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

In some ARM architectures, like OMAP3, the VFP context can be lost during
dynamic sleep cycle. For this purpose, there is now a function
vfp_pm_save_context() that should be called before the VFP is assumed to
lose context. Next VFP trap will then restore context automatically.

We need to have the last_VFP_context[cpu] cleared after the save in idle,
else the restore would fail to restore when it sees that the last_VFP_context
is same as the current threads vfp_state. This happens when the same
process/thread traps an exception post idle.

Main work for this patch was done by Peter and Rajendra. Some cleanup and
optimization by Tero.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
Acked-by: Tony Lindgren t...@atomide.com
Cc: Vishwanath Sripathy vishwanath...@ti.com
Cc: Rajendra Nayak rna...@ti.com
Cc: Richard Woodruff r-woodru...@ti.com
Cc: Peter 'p2' De Schrijver peter.de-schrij...@nokia.com
---
 arch/arm/vfp/vfpmodule.c |   25 +
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 2d7423a..80a08bd 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -329,6 +329,31 @@ static void vfp_enable(void *unused)
 #ifdef CONFIG_PM
 #include linux/sysdev.h
 
+void vfp_pm_save_context(void)
+{
+   struct thread_info *thread = current_thread_info();
+   u32 fpexc = fmrx(FPEXC);
+   __u32 cpu = thread-cpu;
+
+   if (last_VFP_context[cpu]) {
+   if (!(fpexc  FPEXC_EN)) {
+   /* enable vfp now to save context */
+   vfp_enable(NULL);
+   fmxr(FPEXC, fmrx(FPEXC) | FPEXC_EN);
+   }
+   vfp_save_state(last_VFP_context[cpu], fpexc);
+
+   /* Disable vfp. The next inst traps an exception and restores*/
+   fmxr(FPEXC, fmrx(FPEXC)  ~FPEXC_EN);
+
+   /*
+* This is needed else the restore might fail if it sees
+* last_VFP_context if same as the current threads vfp_state.
+*/
+   last_VFP_context[cpu] = NULL;
+   }
+}
+
 static int vfp_pm_suspend(struct sys_device *dev, pm_message_t state)
 {
struct thread_info *ti = current_thread_info();
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv2 2/2] OMAP3: Implemented VFP restore/save context

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

VFP save context is called before MPU/NEON off. Restore is not needed as
the next VFP trap will restore context automatically. Uses the support
routine implemented in arch/arm/vfp/vfpmodule.c.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
Cc: Vishwanath Sripathy vishwanath...@ti.com
Cc: Rajendra Nayak rna...@ti.com
Cc: Richard Woodruff r-woodru...@ti.com
Cc: Peter 'p2' De Schrijver peter.de-schrij...@nokia.com
---
 arch/arm/mach-omap2/pm.h |1 +
 arch/arm/mach-omap2/pm34xx.c |   14 +-
 2 files changed, 14 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index e0c94ea..bf9b7f9 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -23,6 +23,7 @@ extern void omap_sram_idle(void);
 extern int omap3_can_sleep(void);
 extern int set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap3_idle_init(void);
+extern void vfp_pm_save_context(void);
 
 struct prm_setup_times_vc {
u16 clksetup;
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 009bc55..624a7af 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -321,6 +321,13 @@ static void restore_control_register(u32 val)
__asm__ __volatile__ (mcr p15, 0, %0, c1, c0, 0 : : r (val));
 }
 
+static inline void omap3_save_neon_context(void)
+{
+#ifdef CONFIG_VFP
+   vfp_pm_save_context();
+#endif
+}
+
 /* Function to restore the table entry that was modified for enabling MMU */
 static void restore_table_entry(void)
 {
@@ -365,6 +372,7 @@ void omap_sram_idle(void)
/* save_state = 3 = L1, L2 and logic lost */
int save_state = 0;
int mpu_next_state = PWRDM_POWER_ON;
+   int neon_next_state = PWRDM_POWER_ON;
int per_next_state = PWRDM_POWER_ON;
int core_next_state = PWRDM_POWER_ON;
int core_prev_state, per_prev_state;
@@ -398,8 +406,12 @@ void omap_sram_idle(void)
pwrdm_pre_transition();
 
/* NEON control */
-   if (pwrdm_read_pwrst(neon_pwrdm) == PWRDM_POWER_ON)
+   if (pwrdm_read_pwrst(neon_pwrdm) == PWRDM_POWER_ON) {
pwrdm_set_next_pwrst(neon_pwrdm, mpu_next_state);
+   neon_next_state = mpu_next_state;
+   if (neon_next_state == PWRDM_POWER_OFF)
+   omap3_save_neon_context();
+   }
 
/* PER */
per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv2 1/2] ARM: VFP: Fixed suspend and added context save support

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

In some ARM architectures, like OMAP3, the VFP context can be lost during
dynamic sleep cycle. For this purpose, there is now a function
vfp_pm_save_context() that should be called before the VFP is assumed to
lose context. Next VFP trap will then restore context automatically.

We need to have the last_VFP_context[cpu] cleared after the save in idle,
else the restore would fail to restore when it sees that the last_VFP_context
is same as the current threads vfp_state. This happens when the same
process/thread traps an exception post idle.

This patch also fixes a potential problem with vfp_pm_suspend(), where
VFP context can be lost if the current process does not have VFP enabled.
Fixed by calling vfp_pm_save_context().

Signed-off-by: Tero Kristo tero.kri...@nokia.com
Cc: Vishwanath Sripathy vishwanath...@ti.com
Cc: Rajendra Nayak rna...@ti.com
Cc: Richard Woodruff r-woodru...@ti.com
Cc: Peter 'p2' De Schrijver peter.de-schrij...@nokia.com
---
 arch/arm/vfp/vfpmodule.c |   28 
 1 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 2d7423a..920a33b 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -329,22 +329,34 @@ static void vfp_enable(void *unused)
 #ifdef CONFIG_PM
 #include linux/sysdev.h
 
-static int vfp_pm_suspend(struct sys_device *dev, pm_message_t state)
+void vfp_pm_save_context(void)
 {
-   struct thread_info *ti = current_thread_info();
u32 fpexc = fmrx(FPEXC);
+   unsigned int cpu = get_cpu();
+
+   /* Save last_VFP_context if needed */
+   if (last_VFP_context[cpu]) {
+   /* Enable vfp to save context */
+   if (!(fpexc  FPEXC_EN)) {
+   vfp_enable(NULL);
+   fmxr(FPEXC, fpexc | FPEXC_EN);
+   }
 
-   /* if vfp is on, then save state for resumption */
-   if (fpexc  FPEXC_EN) {
printk(KERN_DEBUG %s: saving vfp state\n, __func__);
-   vfp_save_state(ti-vfpstate, fpexc);
+   vfp_save_state(last_VFP_context[cpu], fpexc);
 
/* disable, just in case */
-   fmxr(FPEXC, fmrx(FPEXC)  ~FPEXC_EN);
+   fmxr(FPEXC, fpexc  ~FPEXC_EN);
+
+   last_VFP_context[cpu] = NULL;
}
 
-   /* clear any information we had about last context state */
-   memset(last_VFP_context, 0, sizeof(last_VFP_context));
+   put_cpu();
+}
+
+static int vfp_pm_suspend(struct sys_device *dev, pm_message_t state)
+{
+   vfp_pm_save_context();
 
return 0;
 }
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv2 0/2] VFP context save/restore for OMAP3

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

Contains following fixes compared to previous version:

- vfp_pm_suspend uses the same routine as context save
- uses get_cpu / put_cpu to get current CPU id
- removed restore context call completely from OMAP3 idle (not needed)


--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv2 2/6] OMAP3: PM: Added support for INACTIVE and ON states for powerdomains

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

Previously omap_sram_idle() did not know about the difference between ON and
INACTIVE states, which complicated the state handling in these cases. Now,
the following changes are done in the idle logic:

- Check for IO-chain arming is changed to reflect desired state (RET)
- UART clocks will be disabled if we attempt to enter INACTIVE (this allows
  the state change to actually happen)

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

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 3b62c96..574492e 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -391,6 +391,7 @@ void omap_sram_idle(void)
mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
switch (mpu_next_state) {
case PWRDM_POWER_ON:
+   case PWRDM_POWER_INACTIVE:
case PWRDM_POWER_RET:
/* No need to save context */
save_state = 0;
@@ -460,9 +461,11 @@ void omap_sram_idle(void)
OMAP3430_GR_MOD,
OMAP3_PRM_VOLTCTRL_OFFSET);
}
-   /* Enable IO-PAD and IO-CHAIN wakeups */
-   prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
-   omap3_enable_io_chain();
+   if (core_next_state = PWRDM_POWER_RET) {
+   /* Enable IO-PAD and IO-CHAIN wakeups */
+   prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
+   omap3_enable_io_chain();
+   }
}
omap3_intc_prepare_idle();
 
@@ -561,15 +564,13 @@ void omap_sram_idle(void)
}
 
/* Disable IO-PAD and IO-CHAIN wakeup */
-   if (core_next_state  PWRDM_POWER_ON) {
+   if (core_next_state = PWRDM_POWER_RET) {
prm_clear_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN);
omap3_disable_io_chain();
}
 
 
pwrdm_post_transition();
-
-   omap2_clkdm_allow_idle(mpu_pwrdm-pwrdm_clkdms[0]);
 }
 
 int omap3_can_sleep(void)
@@ -617,7 +618,6 @@ int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
}
 
if (sleep_switch) {
-   omap2_clkdm_allow_idle(pwrdm-pwrdm_clkdms[0]);
pwrdm_wait_transition(pwrdm);
pwrdm_state_switch(pwrdm);
}
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv2 0/6] Idle status patches revisited

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

Improvements compared to previous set:

- Fixed wrong pwrdm state check on IO chain arming on patch 2
- Improved changelog on patch 2  4
- Moved FCLK checks inside clockdomain code from powerdomain code in patch 5
- Some style changes on patch 6

Still, I believe there is no simple way of implementing the idle status
check by using the usecounts inside clock framework. It would probably be
possible by adding a new usecount variable that would be updated according
to slightly different rules, but this also looks bit complicated compared
to the need.

-Tero


--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv2 1/6] OMAP: Powerdomains: Add support for INACTIVE state on pwrdm level

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

Currently only ON, RET and OFF are supported, and ON is arguably broken as it
allows the powerdomain to enter INACTIVE state unless idle is prevented.
Now, pwrdm code prevents idle if ON is selected, and also adds support for
INACTIVE. This simplifies the control needed inside sleep code.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/powerdomain.c |   32 +
 arch/arm/mach-omap2/powerdomains34xx.h|   26 ++--
 arch/arm/plat-omap/include/plat/powerdomain.h |6 -
 3 files changed, 45 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index b6990e3..1237717 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -112,8 +112,8 @@ static struct powerdomain *_pwrdm_deps_lookup(struct 
powerdomain *pwrdm,
 static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 {
 
-   int prev;
-   int state;
+   u8 prev;
+   u8 state;
 
if (pwrdm == NULL)
return -EINVAL;
@@ -220,7 +220,7 @@ int pwrdm_register(struct powerdomain *pwrdm)
 
pr_debug(powerdomain: registered %s\n, pwrdm-name);
ret = 0;
-
+   pwrdm-next_state = -1;
 pr_unlock:
write_unlock_irqrestore(pwrdm_rwlock, flags);
 
@@ -701,19 +701,38 @@ int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm)
  */
 int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 {
+   u8 prg_pwrst;
+
if (!pwrdm)
return -EINVAL;
 
+   if (pwrdm-next_state == pwrst)
+   return 0;
+
if (!(pwrdm-pwrsts  (1  pwrst)))
return -EINVAL;
 
pr_debug(powerdomain: setting next powerstate for %s to %0x\n,
 pwrdm-name, pwrst);
 
+   /* INACTIVE is reserved, so we program pwrdm as ON */
+   if (pwrst == PWRDM_POWER_INACTIVE)
+   prg_pwrst = PWRDM_POWER_ON;
+   else
+   prg_pwrst = pwrst;
+
prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
-(pwrst  OMAP_POWERSTATE_SHIFT),
+(prg_pwrst  OMAP_POWERSTATE_SHIFT),
 pwrdm-prcm_offs, PM_PWSTCTRL);
 
+   /* If next state is ON, prevent idle */
+   if (pwrst == PWRDM_POWER_ON)
+   omap2_clkdm_deny_idle(pwrdm-pwrdm_clkdms[0]);
+   else
+   omap2_clkdm_allow_idle(pwrdm-pwrdm_clkdms[0]);
+
+   pwrdm-next_state = pwrst;
+
return 0;
 }
 
@@ -730,8 +749,11 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
if (!pwrdm)
return -EINVAL;
 
+   if (pwrdm-next_state  -1)
+   return pwrdm-next_state;
+
return prm_read_mod_bits_shift(pwrdm-prcm_offs, PM_PWSTCTRL,
-   OMAP_POWERSTATE_MASK);
+  OMAP_POWERSTATE_MASK);
 }
 
 /**
diff --git a/arch/arm/mach-omap2/powerdomains34xx.h 
b/arch/arm/mach-omap2/powerdomains34xx.h
index fd09b08..9eb2dc5 100644
--- a/arch/arm/mach-omap2/powerdomains34xx.h
+++ b/arch/arm/mach-omap2/powerdomains34xx.h
@@ -165,7 +165,7 @@ static struct powerdomain iva2_pwrdm = {
.omap_chip= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.dep_bit  = OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
.wkdep_srcs   = iva2_wkdeps,
-   .pwrsts   = PWRSTS_OFF_RET_ON,
+   .pwrsts   = PWRSTS_OFF_RET_INA_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks= 4,
.pwrsts_mem_ret   = {
@@ -188,7 +188,7 @@ static struct powerdomain mpu_34xx_pwrdm = {
.omap_chip= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.dep_bit  = OMAP3430_EN_MPU_SHIFT,
.wkdep_srcs   = mpu_34xx_wkdeps,
-   .pwrsts   = PWRSTS_OFF_RET_ON,
+   .pwrsts   = PWRSTS_OFF_RET_INA_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks= 1,
.pwrsts_mem_ret   = {
@@ -206,7 +206,7 @@ static struct powerdomain core_34xx_pre_es3_1_pwrdm = {
.omap_chip= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
   CHIP_IS_OMAP3430ES2 |
   CHIP_IS_OMAP3430ES3_0),
-   .pwrsts   = PWRSTS_OFF_RET_ON,
+   .pwrsts   = PWRSTS_OFF_RET_INA_ON,
.dep_bit  = OMAP3430_EN_CORE_SHIFT,
.banks= 2,
.pwrsts_mem_ret   = {
@@ -214,8 +214,8 @@ static struct powerdomain core_34xx_pre_es3_1_pwrdm = {
[1] = PWRSTS_OFF_RET,/* MEM2RETSTATE */
},
.pwrsts_mem_on= {
-   [0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
-   [1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
+   [0] = PWRSTS_OFF_RET_INA_ON, /* MEM1ONSTATE */
+   [1] = PWRSTS_OFF_RET_INA_ON, /* MEM2ONSTATE

[PATCHv2 4/6] OMAP3: PM: Removed pwrdm state hacking from omap_sram_idle

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

Following hacks will be moved inside cpuidle in subsequent patch:

- CAM domain prevents idle completely
- PER should not go OFF if core remains active

This simplifies the design and allows cpuidle to keep better track of which
power states system will actually enter.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/pm34xx.c |   18 ++
 1 files changed, 2 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 574492e..d77fc88 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -81,7 +81,6 @@ static int (*_omap_save_secure_sram)(u32 *addr);
 
 static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
-static struct powerdomain *cam_pwrdm;
 
 static struct prm_setup_times_vc prm_setup_times_default = {
.clksetup = 0xff,
@@ -378,7 +377,6 @@ void omap_sram_idle(void)
int core_next_state = PWRDM_POWER_ON;
int core_prev_state, per_prev_state;
u32 sdrc_pwr = 0;
-   int per_state_modified = 0;
 
if (!_omap_sram_idle)
return;
@@ -421,19 +419,10 @@ void omap_sram_idle(void)
if (per_next_state  PWRDM_POWER_ON) {
omap_uart_prepare_idle(2);
omap2_gpio_prepare_for_idle(per_next_state);
-   if (per_next_state == PWRDM_POWER_OFF) {
-   if (core_next_state == PWRDM_POWER_ON) {
-   per_next_state = PWRDM_POWER_RET;
-   pwrdm_set_next_pwrst(per_pwrdm, per_next_state);
-   per_state_modified = 1;
-   } else
-   omap3_per_save_context();
-   }
+   if (per_next_state == PWRDM_POWER_OFF)
+   omap3_per_save_context();
}
 
-   if (pwrdm_read_pwrst(cam_pwrdm) == PWRDM_POWER_ON)
-   omap2_clkdm_deny_idle(mpu_pwrdm-pwrdm_clkdms[0]);
-
/*
 * Disable smartreflex before entering WFI.
 * Only needed if we are going to enter retention or off.
@@ -559,8 +548,6 @@ void omap_sram_idle(void)
}
omap2_gpio_resume_after_idle();
omap_uart_resume_idle(2);
-   if (per_state_modified)
-   pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
}
 
/* Disable IO-PAD and IO-CHAIN wakeup */
@@ -1174,7 +1161,6 @@ static int __init omap3_pm_init(void)
neon_pwrdm = pwrdm_lookup(neon_pwrdm);
per_pwrdm = pwrdm_lookup(per_pwrdm);
core_pwrdm = pwrdm_lookup(core_pwrdm);
-   cam_pwrdm = pwrdm_lookup(cam_pwrdm);
 
omap_push_sram_idle();
 #ifdef CONFIG_SUSPEND
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCHv2 5/6] OMAP: Powerdomains: Add support for checking if pwrdm/clkdm can idle

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

pwrdm_can_idle(pwrdm) will check if the specified powerdomain can enter
idle. This is done by checking all clockdomains under the powerdomain
if they can idle also.

omap2_clkdm_can_idle(clkdm) will check if the specified clockdomain can
enter idle. This checks the functional clock status in the clockdomain.

These calls can be used e.g. inside cpuidle to decide which power states
core and mpu should enter during idle, as there are certain dependencies
between wakeup capabilities and reset logic.

Signed-off-by: Tero Kristo tero.kri...@nokia.com
---
 arch/arm/mach-omap2/clockdomain.c |   24 
 arch/arm/mach-omap2/clockdomains.h|   14 ++
 arch/arm/mach-omap2/powerdomain.c |   25 +
 arch/arm/plat-omap/include/plat/clockdomain.h |   12 
 arch/arm/plat-omap/include/plat/powerdomain.h |1 +
 5 files changed, 76 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/clockdomain.c 
b/arch/arm/mach-omap2/clockdomain.c
index fcd8232..9ddeb96 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -474,6 +474,30 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm)
return 0;
 }
 
+
+/**
+ * omap2_clkdm_can_idle - check if clockdomain has any active clocks or not
+ * @clkdm: struct clockdomain *
+ *
+ * Checks if the clockdomain has any active clock or not, i.e. whether it
+ * can enter idle. Returns -EINVAL if clkdm is NULL; 0 if unable to idle;
+ * 1 if can idle.
+ */
+int omap2_clkdm_can_idle(struct clockdomain *clkdm)
+{
+   int i;
+   const int fclk_regs[] = { CM_FCLKEN, OMAP3430ES2_CM_FCLKEN3 };
+
+   if (!clkdm)
+   return -EINVAL;
+
+   for (i = 0; i  clkdm-fclk_reg_amt; i++)
+   if (cm_read_mod_reg(clkdm-pwrdm.ptr-prcm_offs,
+   fclk_regs[i])  ~clkdm-fclk_masks[i])
+   return 0;
+   return 1;
+}
+
 /**
  * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm
  * @clkdm: struct clockdomain *
diff --git a/arch/arm/mach-omap2/clockdomains.h 
b/arch/arm/mach-omap2/clockdomains.h
index c4ee076..2cde82a 100644
--- a/arch/arm/mach-omap2/clockdomains.h
+++ b/arch/arm/mach-omap2/clockdomains.h
@@ -167,6 +167,7 @@ static struct clockdomain iva2_clkdm = {
.flags  = CLKDM_CAN_HWSUP_SWSUP,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+   .fclk_reg_amt   = 1,
 };
 
 static struct clockdomain gfx_3430es1_clkdm = {
@@ -183,6 +184,7 @@ static struct clockdomain sgx_clkdm = {
.flags  = CLKDM_CAN_HWSUP_SWSUP,
.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
+   .fclk_reg_amt   = 1,
 };
 
 /*
@@ -206,6 +208,11 @@ static struct clockdomain core_l3_34xx_clkdm = {
.flags  = CLKDM_CAN_HWSUP,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+   .fclk_reg_amt   = 2,
+   .fclk_masks = {
+   [0] = OMAP3430_EN_UART2 | OMAP3430_EN_UART1,
+   [1] = 0,
+   },
 };
 
 static struct clockdomain core_l4_34xx_clkdm = {
@@ -222,6 +229,7 @@ static struct clockdomain dss_34xx_clkdm = {
.flags  = CLKDM_CAN_HWSUP_SWSUP,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+   .fclk_reg_amt   = 1,
 };
 
 static struct clockdomain cam_clkdm = {
@@ -230,6 +238,7 @@ static struct clockdomain cam_clkdm = {
.flags  = CLKDM_CAN_HWSUP_SWSUP,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+   .fclk_reg_amt   = 1,
 };
 
 static struct clockdomain usbhost_clkdm = {
@@ -238,6 +247,7 @@ static struct clockdomain usbhost_clkdm = {
.flags  = CLKDM_CAN_HWSUP_SWSUP,
.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
+   .fclk_reg_amt   = 1,
 };
 
 static struct clockdomain per_clkdm = {
@@ -246,6 +256,10 @@ static struct clockdomain per_clkdm = {
.flags  = CLKDM_CAN_HWSUP_SWSUP,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
.omap_chip  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+   .fclk_reg_amt   = 1,
+   .fclk_masks = {
+   [0] = OMAP3430_EN_UART3,
+   },
 };
 
 /*
diff --git a/arch/arm/mach-omap2/powerdomain.c 
b/arch/arm/mach-omap2/powerdomain.c
index 1237717..2bef099 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -1217,6 +1217,31 @@ int pwrdm_wait_transition(struct powerdomain *pwrdm)
return 0;
 }
 
+/**
+ * pwrdm_can_idle - check if the powerdomain can enter idle
+ * @pwrdm: struct

[PATCHv2 3/6] OMAP3: CPUidle: Fixed support for ON / INACTIVE states

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

New powerdomain code support for INACTIVE state removes the need to control
clockdomains directly from cpuidle. Also, cpuidle state definitions can now
directly support ON / INACTIVE simplifying the implementation.

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

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 1cfa5a6..4a81ef1 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -91,20 +91,6 @@ static int omap3_idle_bm_check(void)
return 0;
 }
 
-static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
-{
-   omap2_clkdm_allow_idle(clkdm);
-   return 0;
-}
-
-static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
-   struct clockdomain *clkdm)
-{
-   omap2_clkdm_deny_idle(clkdm);
-   return 0;
-}
-
 /**
  * omap3_enter_idle - Programs OMAP3 to enter the specified state
  * @dev: cpuidle device
@@ -141,19 +127,9 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
if (omap_irq_pending() || need_resched())
goto return_sleep_time;
 
-   if (cx-type == OMAP3_STATE_C1) {
-   pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
-   pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
-   }
-
/* Execute ARM wfi */
omap_sram_idle();
 
-   if (cx-type == OMAP3_STATE_C1) {
-   pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
-   pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
-   }
-
 return_sleep_time:
getnstimeofday(ts_postidle);
ts_idle = timespec_sub(ts_postidle, ts_preidle);
@@ -246,8 +222,8 @@ void omap_init_power_states(void)
cpuidle_params_table[OMAP3_STATE_C2].wake_latency;
omap3_power_states[OMAP3_STATE_C2].threshold =
cpuidle_params_table[OMAP3_STATE_C2].threshold;
-   omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON;
-   omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_INACTIVE;
+   omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID;
 
/* C3 . MPU CSWR + Core inactive */
@@ -261,7 +237,7 @@ void omap_init_power_states(void)
omap3_power_states[OMAP3_STATE_C3].threshold =
cpuidle_params_table[OMAP3_STATE_C3].threshold;
omap3_power_states[OMAP3_STATE_C3].mpu_state = PWRDM_POWER_RET;
-   omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
 
@@ -276,7 +252,7 @@ void omap_init_power_states(void)
omap3_power_states[OMAP3_STATE_C4].threshold =
cpuidle_params_table[OMAP3_STATE_C4].threshold;
omap3_power_states[OMAP3_STATE_C4].mpu_state = PWRDM_POWER_OFF;
-   omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_ON;
+   omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_INACTIVE;
omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID |
CPUIDLE_FLAG_CHECK_BM;
 
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

2009-12-04 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 |  118 ++--
 1 files changed, 111 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 4a81ef1..dad64a9 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
@@ -92,6 +93,22 @@ static int omap3_idle_bm_check(void)
 }
 
 /**
+ * pwrdm_get_idle_state - Get the power state a pwrdm will enter during idle
+ * @pwrdm: powerdomain to check state for
+ *
+ * Checks if the powerdomain can enter idle or not, if yes, will return
+ * the programmed target state for the domain. Otherwise will indicate
+ * that the domain will stay on.
+ * Returns the power state the pwrdm will enter.
+ */
+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
  * @state: The target state to be programmed
@@ -153,14 +170,94 @@ 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

[PATCH] Smartreflex: Avoid unnecessary spam

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

Current warning messages will be constantly printed out during normal operation
if smartreflex autocompensation is disabled.

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

diff --git a/arch/arm/mach-omap2/smartreflex.c 
b/arch/arm/mach-omap2/smartreflex.c
index be3a1da..db228b2 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -675,13 +675,8 @@ void sr_start_vddautocomap(int srid, u32 target_opp_no)
sr_configure(sr);
}
 
-   if (sr-is_autocomp_active == 1)
-   pr_warning(SR%d: VDD autocomp is already active\n,
-   srid);
-
sr-is_autocomp_active = 1;
if (!sr_enable(sr, target_opp_no)) {
-   pr_warning(SR%d: VDD autocomp not activated\n, srid);
sr-is_autocomp_active = 0;
if (sr-is_sr_reset == 1)
sr_clk_disable(sr);
@@ -707,11 +702,8 @@ int sr_stop_vddautocomap(int srid)
/* Reset the volatage for current OPP */
sr_reset_voltage(srid);
return true;
-   } else {
-   pr_warning(SR%d: VDD autocomp is not active\n,
-   srid);
+   } else
return false;
-   }
 
 }
 EXPORT_SYMBOL(sr_stop_vddautocomap);
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] PM: Fix a bug with noncore dpll rate calculation

2008-11-19 Thread Tero Kristo
Noncore dpll can enter autoidle state, in which case the rate calculation
fails. Fixed by checking dpll mode instead of idle status.

Signed-off-by: Tero Kristo [EMAIL PROTECTED]
---
 arch/arm/mach-omap2/clock.c   |   16 +++-
 arch/arm/mach-omap2/cm-regbits-34xx.h |2 ++
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 522ce6f..bbd3e82 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -212,9 +212,16 @@ u32 omap2_get_dpll_rate(struct clk *clk)
return 0;
 
/* Return bypass rate if DPLL is bypassed */
-   v = cm_read_mod_reg(clk-prcm_mod, dd-idlest_reg);
-   v = dd-idlest_mask;
-   v = __ffs(dd-idlest_mask);
+   if (cpu_is_omap34xx()) {
+   v = cm_read_mod_reg(clk-prcm_mod, dd-control_reg);
+   v = dd-enable_mask;
+   v = __ffs(dd-enable_mask);
+   } else {
+   v = cm_read_mod_reg(clk-prcm_mod, dd-idlest_reg);
+   v = dd-idlest_mask;
+   v = __ffs(dd-idlest_mask);
+   }
+
if (cpu_is_omap24xx()) {
 
if (v == ST_CORE_CLK_REF)
@@ -224,9 +231,8 @@ u32 omap2_get_dpll_rate(struct clk *clk)
 
} else if (cpu_is_omap34xx()) {
 
-   if (!v)
+   if (v == OMAP3430_EN_MPU_DPLL_BYPASS)
return dd-bypass_clk-rate;
-
}
 
v = cm_read_mod_reg(clk-prcm_mod, dd-mult_div1_reg);
diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h 
b/arch/arm/mach-omap2/cm-regbits-34xx.h
index 6f3f5a3..9995353 100644
--- a/arch/arm/mach-omap2/cm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-34xx.h
@@ -112,6 +112,8 @@
 #define OMAP3430_EN_MPU_DPLL_DRIFTGUARD_MASK   (1  3)
 #define OMAP3430_EN_MPU_DPLL_SHIFT 0
 #define OMAP3430_EN_MPU_DPLL_MASK  (0x7  0)
+#define OMAP3430_EN_MPU_DPLL_LOCK  (0x7  0)
+#define OMAP3430_EN_MPU_DPLL_BYPASS(0x5  0)
 
 /* CM_IDLEST_MPU */
 #define OMAP3430_ST_MPU(1  0)
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] PM: Added three PLL registers to the PRCM context save

2008-11-19 Thread Tero Kristo
These registers are now also saved:
CM_CLKSEL4
CM_CLKEN
CM_CLKEN2

Signed-off-by: Tero Kristo [EMAIL PROTECTED]
---
 arch/arm/mach-omap2/prcm.c |   14 ++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index d5a1e4b..c64b668 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -46,7 +46,10 @@ struct omap3_prcm_regs {
u32 emu_cm_clksel;
u32 emu_cm_clkstctrl;
u32 pll_cm_autoidle2;
+   u32 pll_cm_clksel4;
u32 pll_cm_clksel5;
+   u32 pll_cm_clken;
+   u32 pll_cm_clken2;
u32 cm_polctrl;
u32 iva2_cm_fclken;
u32 core_cm_fclken1;
@@ -233,8 +236,14 @@ void omap3_prcm_save_context(void)
 cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSTCTRL);
prcm_context.pll_cm_autoidle2 =
 cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
+   prcm_context.pll_cm_clksel4 =
+   cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL4);
prcm_context.pll_cm_clksel5 =
 cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL5);
+   prcm_context.pll_cm_clken =
+   cm_read_mod_reg(PLL_MOD, CM_CLKEN);
+   prcm_context.pll_cm_clken2 =
+   cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKEN2);
prcm_context.cm_polctrl = __raw_readl(OMAP3430_CM_POLCTRL);
prcm_context.iva2_cm_fclken =
 cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_FCLKEN);
@@ -380,8 +389,13 @@ void omap3_prcm_restore_context(void)
 CM_CLKSTCTRL);
cm_write_mod_reg(prcm_context.pll_cm_autoidle2, PLL_MOD,
 CM_AUTOIDLE2);
+   cm_write_mod_reg(prcm_context.pll_cm_clksel4, PLL_MOD,
+   OMAP3430ES2_CM_CLKSEL4);
cm_write_mod_reg(prcm_context.pll_cm_clksel5, PLL_MOD,
 OMAP3430ES2_CM_CLKSEL5);
+   cm_write_mod_reg(prcm_context.pll_cm_clken, PLL_MOD, CM_CLKEN);
+   cm_write_mod_reg(prcm_context.pll_cm_clken2, PLL_MOD,
+   OMAP3430ES2_CM_CLKEN2);
__raw_writel(prcm_context.cm_polctrl, OMAP3430_CM_POLCTRL);
cm_write_mod_reg(prcm_context.iva2_cm_fclken, OMAP3430_IVA2_MOD,
 CM_FCLKEN);
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] OMAP3: Fixes for suspend / resume GPIO wake-up handling

2008-11-26 Thread Tero Kristo
Signed-off-by: Tero Kristo [EMAIL PROTECTED]
---
 arch/arm/plat-omap/gpio.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index f4ec3af..62349fd 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -1585,7 +1585,7 @@ static int omap_gpio_suspend(struct sys_device *dev, 
pm_message_t mesg)
 #endif
 #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
case METHOD_GPIO_24XX:
-   wake_status = bank-base + OMAP24XX_GPIO_SETWKUENA;
+   wake_status = bank-base + OMAP24XX_GPIO_WAKE_EN;
wake_clear = bank-base + OMAP24XX_GPIO_CLEARWKUENA;
wake_set = bank-base + OMAP24XX_GPIO_SETWKUENA;
break;
@@ -1608,7 +1608,7 @@ static int omap_gpio_resume(struct sys_device *dev)
 {
int i;
 
-   if (!cpu_is_omap24xx()  !cpu_is_omap16xx())
+   if (!cpu_class_is_omap2()  !cpu_is_omap16xx())
return 0;
 
for (i = 0; i  gpio_bank_count; i++) {
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] PM: Added suspend target state control to debugfs for OMAP3

2008-11-26 Thread Tero Kristo
Target state can be read / programmed via files under:
  [debugfs]/pm_debug/[pwrdm]/suspend

Signed-off-by: Tero Kristo [EMAIL PROTECTED]
---
 arch/arm/mach-omap2/pm-debug.c |   30 --
 arch/arm/mach-omap2/pm.h   |4 
 arch/arm/mach-omap2/pm34xx.c   |   24 
 3 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 82219f4..ac61d15 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -26,6 +26,7 @@
 #include linux/clk.h
 #include linux/err.h
 #include linux/io.h
+#include linux/module.h
 
 #include mach/clock.h
 #include mach/board.h
@@ -511,11 +512,28 @@ int pm_dbg_regset_init(int reg_set)
return 0;
 }
 
-static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
+static int pwrdm_suspend_get(void *data, u64 *val)
+{
+   *val = omap3_pm_get_suspend_state((struct powerdomain *)data);
+
+   if (*val = 0)
+   return 0;
+   return *val;
+}
+
+static int pwrdm_suspend_set(void *data, u64 val)
+{
+   return omap3_pm_set_suspend_state((struct powerdomain *)data, (int)val);
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(pwrdm_suspend_fops, pwrdm_suspend_get, 
pwrdm_suspend_set, %llu\n);
+
+static int __init pwrdms_setup(struct powerdomain *pwrdm, void *dir)
 {
int i;
s64 t;
struct timespec now;
+   struct dentry *d;
 
getnstimeofday(now);
t = timespec_to_ns(now);
@@ -525,6 +543,14 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, 
void *unused)
 
pwrdm-timer = t;
 
+   if (strncmp(pwrdm-name, dpll, 4) == 0)
+   return 0;
+
+   d = debugfs_create_dir(pwrdm-name, (struct dentry *)dir);
+
+   (void) debugfs_create_file(suspend, S_IRUGO|S_IWUSR, d,
+   (void *)pwrdm, pwrdm_suspend_fops);
+
return 0;
 }
 
@@ -545,7 +571,7 @@ static int __init pm_dbg_init(void)
(void) debugfs_create_file(time, S_IRUGO,
d, (void *)DEBUG_FILE_TIMERS, debug_fops);
 
-   pwrdm_for_each(pwrdms_setup, NULL);
+   pwrdm_for_each(pwrdms_setup, (void *)d);
 
pm_dbg_dir = debugfs_create_dir(registers, d);
if (IS_ERR(pm_dbg_dir))
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 4b1ba7c..78fde57 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -34,8 +34,12 @@ extern void omap2_block_sleep(void);
 extern void omap2_allow_sleep(void);
 #ifdef CONFIG_ARCH_OMAP3
 extern void omap3_pm_off_mode_enable(int);
+extern int omap3_pm_get_suspend_state(struct powerdomain *pwrdm);
+extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state);
 #else
 #define omap3_pm_off_mode_enable(int) do {} while (0);
+#define omap3_pm_get_suspend_state(pwrdm) do {} while (0);
+#define omap3_pm_set_suspend_state(pwrdm,state) do {} while (0);
 #endif
 extern int set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 191299c..73ac22c 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -780,6 +780,30 @@ void omap3_pm_off_mode_enable(int enable)
}
 }
 
+int omap3_pm_get_suspend_state(struct powerdomain *pwrdm)
+{
+   struct power_state *pwrst;
+
+   list_for_each_entry(pwrst, pwrst_list, node) {
+   if (pwrst-pwrdm == pwrdm)
+   return pwrst-next_state;
+   }
+   return -EINVAL;
+}
+
+int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state)
+{
+   struct power_state *pwrst;
+
+   list_for_each_entry(pwrst, pwrst_list, node) {
+   if (pwrst-pwrdm == pwrdm) {
+   pwrst-next_state = state;
+   return 0;
+   }
+   }
+   return -EINVAL;
+}
+
 static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 {
struct power_state *pwrst;
-- 
1.5.4.3

--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


  1   2   3   4   5   6   7   8   9   10   >