aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoseph Lo <josephl@nvidia.com>2012-10-31 05:41:16 -0400
committerStephen Warren <swarren@nvidia.com>2012-11-15 17:09:21 -0500
commitd3f293656c07a1147c11e8c8774d7955a903cee0 (patch)
treef17307f8dfa112840ba00d05eef16d0d37f9921c
parent0b25e25bef0e03c0465c3eb1119b32cb906db689 (diff)
ARM: tegra: cpuidle: add CPU resume function
The CPU suspending on Tegra means CPU power gating. We add a resume function for taking care the CPUs that resume from power gating status. This function was been hooked to the reset handler. We take care everything here before go into kernel. Be aware of that, you may see the legacy power status "LP2" in the code which is exactly the same meaning of "CPU power down". Based on the work by: Scott Williams <scwilliams@nvidia.com> Colin Cross <ccross@android.com> Gary King <gking@nvidia.com> Signed-off-by: Joseph Lo <josephl@nvidia.com> Signed-off-by: Stephen Warren <swarren@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/headsmp.S60
-rw-r--r--arch/arm/mach-tegra/reset.c6
-rw-r--r--arch/arm/mach-tegra/sleep.h1
3 files changed, 67 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
index 93f0370cc95b..82dc84b6b868 100644
--- a/arch/arm/mach-tegra/headsmp.S
+++ b/arch/arm/mach-tegra/headsmp.S
@@ -68,6 +68,55 @@ ENTRY(tegra_secondary_startup)
68 b secondary_startup 68 b secondary_startup
69ENDPROC(tegra_secondary_startup) 69ENDPROC(tegra_secondary_startup)
70 70
71#ifdef CONFIG_PM_SLEEP
72/*
73 * tegra_resume
74 *
75 * CPU boot vector when restarting the a CPU following
76 * an LP2 transition. Also branched to by LP0 and LP1 resume after
77 * re-enabling sdram.
78 */
79ENTRY(tegra_resume)
80 bl v7_invalidate_l1
81 /* Enable coresight */
82 mov32 r0, 0xC5ACCE55
83 mcr p14, 0, r0, c7, c12, 6
84
85 cpu_id r0
86 cmp r0, #0 @ CPU0?
87 bne cpu_resume @ no
88
89#ifdef CONFIG_ARCH_TEGRA_3x_SOC
90 /* Are we on Tegra20? */
91 mov32 r6, TEGRA_APB_MISC_BASE
92 ldr r0, [r6, #APB_MISC_GP_HIDREV]
93 and r0, r0, #0xff00
94 cmp r0, #(0x20 << 8)
95 beq 1f @ Yes
96 /* Clear the flow controller flags for this CPU. */
97 mov32 r2, TEGRA_FLOW_CTRL_BASE + FLOW_CTRL_CPU0_CSR @ CPU0 CSR
98 ldr r1, [r2]
99 /* Clear event & intr flag */
100 orr r1, r1, \
101 #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
102 movw r0, #0x0FFD @ enable, cluster_switch, immed, & bitmaps
103 bic r1, r1, r0
104 str r1, [r2]
1051:
106#endif
107
108#ifdef CONFIG_HAVE_ARM_SCU
109 /* enable SCU */
110 mov32 r0, TEGRA_ARM_PERIF_BASE
111 ldr r1, [r0]
112 orr r1, r1, #1
113 str r1, [r0]
114#endif
115
116 b cpu_resume
117ENDPROC(tegra_resume)
118#endif
119
71 .align L1_CACHE_SHIFT 120 .align L1_CACHE_SHIFT
72ENTRY(__tegra_cpu_reset_handler_start) 121ENTRY(__tegra_cpu_reset_handler_start)
73 122
@@ -121,6 +170,17 @@ ENTRY(__tegra_cpu_reset_handler)
1211: 1701:
122#endif 171#endif
123 172
173 /* Waking up from LP2? */
174 ldr r9, [r12, #RESET_DATA(MASK_LP2)]
175 tst r9, r11 @ if in_lp2
176 beq __is_not_lp2
177 ldr lr, [r12, #RESET_DATA(STARTUP_LP2)]
178 cmp lr, #0
179 bleq __die @ no LP2 startup handler
180 bx lr
181
182__is_not_lp2:
183
124#ifdef CONFIG_SMP 184#ifdef CONFIG_SMP
125 /* 185 /*
126 * Can only be secondary boot (initial or hotplug) but CPU 0 186 * Can only be secondary boot (initial or hotplug) but CPU 0
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c
index e05da7d10c3b..3fd89ecd158e 100644
--- a/arch/arm/mach-tegra/reset.c
+++ b/arch/arm/mach-tegra/reset.c
@@ -25,6 +25,7 @@
25#include "iomap.h" 25#include "iomap.h"
26#include "irammap.h" 26#include "irammap.h"
27#include "reset.h" 27#include "reset.h"
28#include "sleep.h"
28#include "fuse.h" 29#include "fuse.h"
29 30
30#define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \ 31#define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \
@@ -79,5 +80,10 @@ void __init tegra_cpu_reset_handler_init(void)
79 virt_to_phys((void *)tegra_secondary_startup); 80 virt_to_phys((void *)tegra_secondary_startup);
80#endif 81#endif
81 82
83#ifdef CONFIG_PM_SLEEP
84 __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP2] =
85 virt_to_phys((void *)tegra_resume);
86#endif
87
82 tegra_cpu_reset_handler_enable(); 88 tegra_cpu_reset_handler_enable();
83} 89}
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index 4889b281c5f9..addb83f5bc73 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -72,6 +72,7 @@
72 dsb 72 dsb
73.endm 73.endm
74#else 74#else
75void tegra_resume(void);
75 76
76#ifdef CONFIG_HOTPLUG_CPU 77#ifdef CONFIG_HOTPLUG_CPU
77void tegra20_hotplug_init(void); 78void tegra20_hotplug_init(void);