diff options
author | Rajendra Nayak <rnayak@ti.com> | 2008-10-08 17:31:22 +0530 |
---|---|---|
committer | Kevin Hilman <khilman@deeprootsystems.com> | 2009-11-11 14:42:48 -0800 |
commit | 20b01669885483ba2102d5a71c662bb6ae1bed0b (patch) | |
tree | 95e71bcf90bcb81e97b5be95383bccf310cb8ad0 /arch/arm | |
parent | 99e6a4d22f7c7bda0cd8978333c2e85fba02f181 (diff) |
OMAP3: PM: CPUidle: support retention and off-mode C-states
This patch adds support and enables state C4(MPU RET + CORE RET)
and MPU OFF states (C3 and C5.)
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-omap2/cpuidle34xx.c | 28 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm34xx.c | 6 |
3 files changed, 20 insertions, 16 deletions
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 858b216b63b..0bf1bc359ea 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -26,6 +26,8 @@ #include <plat/prcm.h> #include <plat/powerdomain.h> +#include <plat/irqs.h> +#include <plat/control.h> #ifdef CONFIG_CPU_IDLE @@ -50,10 +52,12 @@ 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; +struct powerdomain *mpu_pd, *core_pd; static int omap3_idle_bm_check(void) { + if (!omap3_can_sleep()) + return 1; return 0; } @@ -79,24 +83,23 @@ static int omap3_enter_idle(struct cpuidle_device *dev, local_irq_disable(); local_fiq_disable(); - /* Program MPU to target state */ - if (cx->mpu_state < PWRDM_POWER_ON) - pwrdm_set_next_pwrst(mpu_pd, cx->mpu_state); + set_pwrdm_state(mpu_pd, cx->mpu_state); + set_pwrdm_state(core_pd, cx->core_state); + + if (omap_irq_pending()) + goto return_sleep_time; /* Execute ARM wfi */ omap_sram_idle(); - /* Program MPU to ON */ - if (cx->mpu_state < PWRDM_POWER_ON) - pwrdm_set_next_pwrst(mpu_pd, PWRDM_POWER_ON); - +return_sleep_time: getnstimeofday(&ts_postidle); ts_idle = timespec_sub(ts_postidle, ts_preidle); local_irq_enable(); local_fiq_enable(); - return timespec_to_ns(&ts_idle); + return (u32)timespec_to_ns(&ts_idle)/1000; } /** @@ -153,7 +156,7 @@ void omap_init_power_states(void) omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID; /* C3 . MPU OFF + Core active */ - omap3_power_states[OMAP3_STATE_C3].valid = 0; + omap3_power_states[OMAP3_STATE_C3].valid = 1; omap3_power_states[OMAP3_STATE_C3].type = OMAP3_STATE_C3; omap3_power_states[OMAP3_STATE_C3].sleep_latency = 1500; omap3_power_states[OMAP3_STATE_C3].wakeup_latency = 1800; @@ -163,7 +166,7 @@ void omap_init_power_states(void) omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID; /* C4 . MPU CSWR + Core CSWR*/ - omap3_power_states[OMAP3_STATE_C4].valid = 0; + omap3_power_states[OMAP3_STATE_C4].valid = 1; omap3_power_states[OMAP3_STATE_C4].type = OMAP3_STATE_C4; omap3_power_states[OMAP3_STATE_C4].sleep_latency = 2500; omap3_power_states[OMAP3_STATE_C4].wakeup_latency = 7500; @@ -174,7 +177,7 @@ void omap_init_power_states(void) CPUIDLE_FLAG_CHECK_BM; /* C5 . MPU OFF + Core CSWR */ - omap3_power_states[OMAP3_STATE_C5].valid = 0; + omap3_power_states[OMAP3_STATE_C5].valid = 1; omap3_power_states[OMAP3_STATE_C5].type = OMAP3_STATE_C5; omap3_power_states[OMAP3_STATE_C5].sleep_latency = 3000; omap3_power_states[OMAP3_STATE_C5].wakeup_latency = 8500; @@ -215,6 +218,7 @@ int omap3_idle_init(void) struct cpuidle_device *dev; mpu_pd = pwrdm_lookup("mpu_pwrdm"); + core_pd = pwrdm_lookup("core_pwrdm"); omap_init_power_states(); cpuidle_register_driver(&omap3_idle_driver); diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 2edf1ba12dc..379e35034cc 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -19,6 +19,8 @@ extern u32 sleep_while_idle; extern void *omap3_secure_ram_storage; extern void omap3_pm_off_mode_enable(int); 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_pm_get_suspend_state(struct powerdomain *pwrdm); extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state); diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 0c49db8afa9..69c47edcc0f 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -76,8 +76,6 @@ static struct powerdomain *mpu_pwrdm, *neon_pwrdm; static struct powerdomain *core_pwrdm, *per_pwrdm; static struct powerdomain *cam_pwrdm; -static int set_pwrdm_state(struct powerdomain *pwrdm, u32 state); - static inline void omap3_per_save_context(void) { omap_gpio_save_context(); @@ -503,7 +501,7 @@ static int omap3_fclks_active(void) return 0; } -static int omap3_can_sleep(void) +int omap3_can_sleep(void) { if (!sleep_while_idle) return 0; @@ -517,7 +515,7 @@ static int omap3_can_sleep(void) /* 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. */ -static int set_pwrdm_state(struct powerdomain *pwrdm, u32 state) +int set_pwrdm_state(struct powerdomain *pwrdm, u32 state) { u32 cur_state; int sleep_switch = 0; |