diff options
author | Yudong Tan <ytan@nvidia.com> | 2011-08-18 15:26:52 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:48:39 -0800 |
commit | 6d76e260493dc5f8c071f6330f3f6490952125f9 (patch) | |
tree | 04e8fb9d7742ccdc9e2010119d4e95c4e5b4803a /arch/arm/mach-tegra/pm.c | |
parent | f93887c0760e4530d3023b7682f2322ea312f3c5 (diff) |
ARM: tegra: power: implement LP1 suspend/resume for Tegra3
Bug 862502
Change-Id: If70e54fb32ce14d5f13dde1d7fb4c1f1499a6722
Reviewed-on: http://git-master/r/47398
Reviewed-by: Daniel Willemsen <dwillemsen@nvidia.com>
Tested-by: Daniel Willemsen <dwillemsen@nvidia.com>
Rebase-Id: Ra77a54e6930692bca628a97bf1de10a30408cdef
Diffstat (limited to 'arch/arm/mach-tegra/pm.c')
-rw-r--r-- | arch/arm/mach-tegra/pm.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c index 688775531fe0..9211671984b0 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c @@ -66,6 +66,7 @@ #include "reset.h" #include "sleep.h" #include "timer.h" +#include "reset.h" struct suspend_context { /* @@ -99,6 +100,7 @@ static pgd_t *tegra_pgd; static DEFINE_SPINLOCK(tegra_lp2_lock); static cpumask_t tegra_in_lp2; static cpumask_t *iram_cpu_lp2_mask; +static unsigned long *iram_cpu_lp1_mask; static u8 *iram_save; static unsigned long iram_save_size; static void __iomem *iram_code = IO_ADDRESS(TEGRA_IRAM_CODE_AREA); @@ -664,8 +666,6 @@ static void tegra_pm_set(enum tegra_suspend_mode mode) * scratch 41 to tegra_resume */ writel(0x0, pmc + PMC_SCRATCH39); - __raw_writel(virt_to_phys(tegra_resume), pmc + PMC_SCRATCH41); - wmb(); /* Enable DPD sample to trigger sampling pads data and direction * in which pad will be driven during lp0 mode*/ @@ -678,8 +678,10 @@ static void tegra_pm_set(enum tegra_suspend_mode mode) pmc_32kwritel(tegra_lp0_vec_start, PMC_SCRATCH1); reg |= TEGRA_POWER_EFFECT_LP0; - break; + /* No break here. LP0 code falls through to write SCRATCH41 */ case TEGRA_SUSPEND_LP1: + __raw_writel(virt_to_phys(tegra_resume), pmc + PMC_SCRATCH41); + wmb(); break; case TEGRA_SUSPEND_LP2: rate = clk_get_rate(tegra_pclk); @@ -709,7 +711,7 @@ static int tegra_suspend_enter(suspend_state_t state) if (pdata && pdata->board_suspend) pdata->board_suspend(current_suspend_mode, TEGRA_SUSPEND_BEFORE_PERIPHERAL); - ret = tegra_suspend_dram(current_suspend_mode); + ret = tegra_suspend_dram(current_suspend_mode, 0); if (pdata && pdata->board_resume) pdata->board_resume(current_suspend_mode, TEGRA_RESUME_AFTER_PERIPHERAL); @@ -743,7 +745,7 @@ static void tegra_suspend_check_pwr_stats(void) return; } -int tegra_suspend_dram(enum tegra_suspend_mode mode) +int tegra_suspend_dram(enum tegra_suspend_mode mode, unsigned int flags) { BUG_ON(mode < 0 || mode >= TEGRA_MAX_SUSPEND_MODE); @@ -774,7 +776,11 @@ int tegra_suspend_dram(enum tegra_suspend_mode mode) tegra_lp0_suspend_mc(); } - suspend_cpu_complex(0); + suspend_cpu_complex(flags); + + if (mode == TEGRA_SUSPEND_LP1) + *iram_cpu_lp1_mask = 1; + flush_cache_all(); outer_flush_all(); outer_disable(); @@ -789,9 +795,10 @@ int tegra_suspend_dram(enum tegra_suspend_mode mode) if (mode == TEGRA_SUSPEND_LP0) { tegra_lp0_resume_mc(); tegra_lp0_cpu_mode(false); - } + } else if (mode == TEGRA_SUSPEND_LP1) + *iram_cpu_lp1_mask = 0; - restore_cpu_complex(0); + restore_cpu_complex(flags); cpu_complex_pm_exit(); cpu_pm_exit(); @@ -803,6 +810,8 @@ int tegra_suspend_dram(enum tegra_suspend_mode mode) tegra_common_resume(); + pr_info("Exited suspend state %s\n", lp_state[mode]); + return 0; } @@ -1021,6 +1030,7 @@ out: } iram_cpu_lp2_mask = tegra_cpu_lp2_mask; + iram_cpu_lp1_mask = tegra_cpu_lp1_mask; fail: #endif if (plat->suspend_mode == TEGRA_SUSPEND_NONE) |