aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
authorJoseph Lo <josephl@nvidia.com>2012-11-12 21:04:48 -0500
committerStephen Warren <swarren@nvidia.com>2012-11-15 17:09:22 -0500
commit29a0e7beab8e05be53d5b9c050253a4dc417041e (patch)
treeeddaa429e909f209cb0628b0733e0ade8e277fd0 /arch/arm/mach-tegra
parentd552920a02759cdc45d8507868de10ac2f5b9a18 (diff)
ARM: tegra: retain L2 content over CPU suspend/resume
The L2 RAM is in different power domain from the CPU cluster. So the L2 content can be retained over CPU suspend/resume. To do that, we need to disable L2 after the MMU is disabled, and enable L2 before the MMU is enabled. But the L2 controller is in the same power domain with the CPU cluster. We need to restore it's settings and re-enable it after the power be resumed. Signed-off-by: Joseph Lo <josephl@nvidia.com> Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com> Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r--arch/arm/mach-tegra/common.c6
-rw-r--r--arch/arm/mach-tegra/headsmp.S11
-rw-r--r--arch/arm/mach-tegra/pm.c2
-rw-r--r--arch/arm/mach-tegra/pm.h2
-rw-r--r--arch/arm/mach-tegra/sleep.S7
-rw-r--r--arch/arm/mach-tegra/sleep.h32
6 files changed, 57 insertions, 3 deletions
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 203a8b94863b..11a74db51e5d 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -36,6 +36,7 @@
36#include "pmc.h" 36#include "pmc.h"
37#include "apbio.h" 37#include "apbio.h"
38#include "sleep.h" 38#include "sleep.h"
39#include "pm.h"
39 40
40/* 41/*
41 * Storage for debug-macro.S's state. 42 * Storage for debug-macro.S's state.
@@ -117,6 +118,7 @@ static __initdata struct tegra_clk_init_table tegra30_clk_init_table[] = {
117static void __init tegra_init_cache(void) 118static void __init tegra_init_cache(void)
118{ 119{
119#ifdef CONFIG_CACHE_L2X0 120#ifdef CONFIG_CACHE_L2X0
121 int ret;
120 void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; 122 void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
121 u32 aux_ctrl, cache_type; 123 u32 aux_ctrl, cache_type;
122 124
@@ -124,7 +126,9 @@ static void __init tegra_init_cache(void)
124 aux_ctrl = (cache_type & 0x700) << (17-8); 126 aux_ctrl = (cache_type & 0x700) << (17-8);
125 aux_ctrl |= 0x7C400001; 127 aux_ctrl |= 0x7C400001;
126 128
127 l2x0_of_init(aux_ctrl, 0x8200c3fe); 129 ret = l2x0_of_init(aux_ctrl, 0x8200c3fe);
130 if (!ret)
131 l2x0_saved_regs_addr = virt_to_phys(&l2x0_saved_regs);
128#endif 132#endif
129 133
130} 134}
diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
index 82dc84b6b868..4a317fae6860 100644
--- a/arch/arm/mach-tegra/headsmp.S
+++ b/arch/arm/mach-tegra/headsmp.S
@@ -2,6 +2,8 @@
2#include <linux/init.h> 2#include <linux/init.h>
3 3
4#include <asm/cache.h> 4#include <asm/cache.h>
5#include <asm/asm-offsets.h>
6#include <asm/hardware/cache-l2x0.h>
5 7
6#include "flowctrl.h" 8#include "flowctrl.h"
7#include "iomap.h" 9#include "iomap.h"
@@ -113,10 +115,19 @@ ENTRY(tegra_resume)
113 str r1, [r0] 115 str r1, [r0]
114#endif 116#endif
115 117
118 /* L2 cache resume & re-enable */
119 l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr
120
116 b cpu_resume 121 b cpu_resume
117ENDPROC(tegra_resume) 122ENDPROC(tegra_resume)
118#endif 123#endif
119 124
125#ifdef CONFIG_CACHE_L2X0
126 .globl l2x0_saved_regs_addr
127l2x0_saved_regs_addr:
128 .long 0
129#endif
130
120 .align L1_CACHE_SHIFT 131 .align L1_CACHE_SHIFT
121ENTRY(__tegra_cpu_reset_handler_start) 132ENTRY(__tegra_cpu_reset_handler_start)
122 133
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 1460c3db8245..1b11707eaca0 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -207,11 +207,9 @@ void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time)
207 207
208 cpu_cluster_pm_enter(); 208 cpu_cluster_pm_enter();
209 suspend_cpu_complex(); 209 suspend_cpu_complex();
210 outer_disable();
211 210
212 cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu); 211 cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
213 212
214 outer_resume();
215 restore_cpu_complex(); 213 restore_cpu_complex();
216 cpu_cluster_pm_exit(); 214 cpu_cluster_pm_exit();
217} 215}
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
index 512345c9eec3..787335cc964c 100644
--- a/arch/arm/mach-tegra/pm.h
+++ b/arch/arm/mach-tegra/pm.h
@@ -21,6 +21,8 @@
21#ifndef _MACH_TEGRA_PM_H_ 21#ifndef _MACH_TEGRA_PM_H_
22#define _MACH_TEGRA_PM_H_ 22#define _MACH_TEGRA_PM_H_
23 23
24extern unsigned long l2x0_saved_regs_addr;
25
24void save_cpu_arch_register(void); 26void save_cpu_arch_register(void);
25void restore_cpu_arch_register(void); 27void restore_cpu_arch_register(void);
26 28
diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S
index 88f4de986a52..26afa7cbed11 100644
--- a/arch/arm/mach-tegra/sleep.S
+++ b/arch/arm/mach-tegra/sleep.S
@@ -27,6 +27,7 @@
27#include <asm/assembler.h> 27#include <asm/assembler.h>
28#include <asm/cache.h> 28#include <asm/cache.h>
29#include <asm/cp15.h> 29#include <asm/cp15.h>
30#include <asm/hardware/cache-l2x0.h>
30 31
31#include "iomap.h" 32#include "iomap.h"
32 33
@@ -98,6 +99,12 @@ ENTRY(tegra_shut_off_mmu)
98 dsb 99 dsb
99 mcr p15, 0, r3, c1, c0, 0 100 mcr p15, 0, r3, c1, c0, 0
100 isb 101 isb
102#ifdef CONFIG_CACHE_L2X0
103 /* Disable L2 cache */
104 mov32 r4, TEGRA_ARM_PERIF_BASE + 0x3000
105 mov r5, #0
106 str r5, [r4, #L2X0_CTRL]
107#endif
101 mov pc, r0 108 mov pc, r0
102ENDPROC(tegra_shut_off_mmu) 109ENDPROC(tegra_shut_off_mmu)
103 .popsection 110 .popsection
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index 6e1b9490c1cf..9821ee725420 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -71,6 +71,38 @@
71 str \tmp2, [\tmp1] @ invalidate SCU tags for CPU 71 str \tmp2, [\tmp1] @ invalidate SCU tags for CPU
72 dsb 72 dsb
73.endm 73.endm
74
75/* Macro to resume & re-enable L2 cache */
76#ifndef L2X0_CTRL_EN
77#define L2X0_CTRL_EN 1
78#endif
79
80#ifdef CONFIG_CACHE_L2X0
81.macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs
82 adr \tmp1, \phys_l2x0_saved_regs
83 ldr \tmp1, [\tmp1]
84 ldr \tmp2, [\tmp1, #L2X0_R_PHY_BASE]
85 ldr \tmp3, [\tmp2, #L2X0_CTRL]
86 tst \tmp3, #L2X0_CTRL_EN
87 bne exit_l2_resume
88 ldr \tmp3, [\tmp1, #L2X0_R_TAG_LATENCY]
89 str \tmp3, [\tmp2, #L2X0_TAG_LATENCY_CTRL]
90 ldr \tmp3, [\tmp1, #L2X0_R_DATA_LATENCY]
91 str \tmp3, [\tmp2, #L2X0_DATA_LATENCY_CTRL]
92 ldr \tmp3, [\tmp1, #L2X0_R_PREFETCH_CTRL]
93 str \tmp3, [\tmp2, #L2X0_PREFETCH_CTRL]
94 ldr \tmp3, [\tmp1, #L2X0_R_PWR_CTRL]
95 str \tmp3, [\tmp2, #L2X0_POWER_CTRL]
96 ldr \tmp3, [\tmp1, #L2X0_R_AUX_CTRL]
97 str \tmp3, [\tmp2, #L2X0_AUX_CTRL]
98 mov \tmp3, #L2X0_CTRL_EN
99 str \tmp3, [\tmp2, #L2X0_CTRL]
100exit_l2_resume:
101.endm
102#else /* CONFIG_CACHE_L2X0 */
103.macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs
104.endm
105#endif /* CONFIG_CACHE_L2X0 */
74#else 106#else
75void tegra_resume(void); 107void tegra_resume(void);
76int tegra_sleep_cpu_finish(unsigned long); 108int tegra_sleep_cpu_finish(unsigned long);