diff options
author | Mayuresh Kulkarni <mkulkarni@nvidia.com> | 2010-02-20 13:31:13 +0530 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-02-22 11:41:14 -0800 |
commit | 8fba90b4d4f400af56cf9f2e998d0562f087fcd9 (patch) | |
tree | be9b78b4ede81cf2d87a9f72300365b442a46254 | |
parent | 3f3eefc8ac980eb3fc71aea68f0572de696c5192 (diff) |
tegra pm: implement suspend_ops
We implement suspend_ops->valid, suspend_ops->begin,
suspend_ops->enter and suspend_ops->end.
For suspend_ops->begin :
Check if CPU1 is in reset or not.
If not, reset it and maintain this state.
For suspend_ops->end :
Check if CPU1 was reseted by suspend_ops->begin.
If yes, take it out of reset.
For harmony board, add a timed wake lock as a WAR.
For suspend_ops->enter :
Do a odm query for lowest power state.
Call the appropriate low power state (LP1/LP0)
routine based on SOC type.
Change-Id: I6f4be75978573bba94e95723c023abc091e06d1e
-rwxr-xr-x[-rw-r--r--] | arch/arm/mach-tegra/suspend_ops.c | 70 |
1 files changed, 46 insertions, 24 deletions
diff --git a/arch/arm/mach-tegra/suspend_ops.c b/arch/arm/mach-tegra/suspend_ops.c index 0aef7afe151e..9f2a756dc3ad 100644..100755 --- a/arch/arm/mach-tegra/suspend_ops.c +++ b/arch/arm/mach-tegra/suspend_ops.c @@ -22,10 +22,23 @@ #include <linux/suspend.h> #include "nvcommon.h" +#include "nvodm_query.h" +#include <linux/wakelock.h> +#include <linux/cpu.h> + +extern void cpu_ap20_do_lp0(void); +extern void cpu_ap20_do_lp1(void); +extern unsigned int check_for_cpu1_reset(void); + +#if defined(CONFIG_TEGRA_ODM_HARMONY) +static struct wake_lock suspend_ops_wake_lock; +static bool wake_lock_initialized = false; +#endif + +static bool Cpu1PoweredOff = false; int tegra_state_valid(suspend_state_t state) { - printk("%s CALLED\n", __func__); if (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX) return 1; return 0; @@ -33,49 +46,58 @@ int tegra_state_valid(suspend_state_t state) int tegra_state_begin(suspend_state_t state) { - printk("%s CALLED with state = %d\n", __func__, state); - return 0; -} - -int tegra_state_prepare(void) -{ - printk("%s CALLED \n", __func__); + if(check_for_cpu1_reset() == 0) { + cpu_down(1); + Cpu1PoweredOff = true; + } return 0; } int tegra_state_enter(suspend_state_t state) { - printk("%s CALLED with state = %d\n", __func__, state); - return 0; -} + const NvOdmSocPowerStateInfo *LPStateInfo; -void tegra_state_finish(void) -{ - printk("%s CALLED \n", __func__); + LPStateInfo = NvOdmQueryLowestSocPowerState(); + if (LPStateInfo->LowestPowerState == NvOdmSocPowerState_DeepSleep) { +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) + /* do AP20 LP0 */ + cpu_ap20_do_lp0(); +#endif + } + else if (LPStateInfo->LowestPowerState == NvOdmSocPowerState_Suspend) { +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) + /* do AP20 LP1 */ + cpu_ap20_do_lp1(); +#endif + } + return 0; } void tegra_state_end(void) { - printk("%s CALLED \n", __func__); -} + if(Cpu1PoweredOff) { + cpu_up(1); + Cpu1PoweredOff = false; + } -void tegra_state_recover(void) -{ - printk("%s CALLED \n", __func__); +#if defined(CONFIG_TEGRA_ODM_HARMONY) + if(!wake_lock_initialized) { + wake_lock_init(&suspend_ops_wake_lock, WAKE_LOCK_SUSPEND, "tegra_suspend_ops"); + wake_lock_initialized = true; + } + wake_lock_timeout(&suspend_ops_wake_lock, 1000); +#endif } static struct platform_suspend_ops tegra_suspend_ops = { .valid = tegra_state_valid, .begin = tegra_state_begin, - .prepare = tegra_state_prepare, .enter = tegra_state_enter, - .finish = tegra_state_finish, - .end = tegra_state_end, - .recover = tegra_state_recover + .end = tegra_state_end }; -void tegra_set_suspend_ops() +void tegra_set_suspend_ops(void) { suspend_set_ops(&tegra_suspend_ops); } |