aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/headsmp.S
diff options
context:
space:
mode:
authorJoseph Lo <josephl@nvidia.com>2013-01-04 04:32:22 -0500
committerStephen Warren <swarren@nvidia.com>2013-01-28 13:14:06 -0500
commit9e32366fe51fea464adb21c244f372d55207e13c (patch)
tree2afe44644ee7d424bab09d1d30d640d42eb84e02 /arch/arm/mach-tegra/headsmp.S
parent8c627fa6583a4894189a47a0bf868f7848b51748 (diff)
ARM: tegra: make device can run on UP
The reset handler code is used for either UP or SMP. To make Tegra device can compile for UP. It needs to be moved to another file that is not SMP only. This is because the reset handler also be needed by CPU idle "powered-down" mode. So we also need to put the reset handler init function in non-SMP only and init them always. And currently the implementation of the reset handler to know which CPU is OK to bring up was identital with "cpu_present_mask". But the "cpu_present_mask" did not initialize yet when the reset handler init function was moved to init early function. We use the "cpu_possible_mask" to replace "cpu_present_mask". Then it can work on both UP and SMP case. Signed-off-by: Joseph Lo <josephl@nvidia.com> [swarren: dropped the move of v7_invalidate_l1() from one file to another, to avoid conflicts with Pavel's cleanup of this function, adjust Makefile so each line only contains 1 file.] Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/headsmp.S')
-rw-r--r--arch/arm/mach-tegra/headsmp.S221
1 files changed, 1 insertions, 220 deletions
diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
index 23f487da7a57..b2834810b02b 100644
--- a/arch/arm/mach-tegra/headsmp.S
+++ b/arch/arm/mach-tegra/headsmp.S
@@ -1,21 +1,10 @@
1#include <linux/linkage.h> 1#include <linux/linkage.h>
2#include <linux/init.h> 2#include <linux/init.h>
3 3
4#include <asm/cache.h>
5#include <asm/asm-offsets.h>
6#include <asm/hardware/cache-l2x0.h>
7
8#include "flowctrl.h"
9#include "iomap.h"
10#include "reset.h"
11#include "sleep.h" 4#include "sleep.h"
12 5
13#define APB_MISC_GP_HIDREV 0x804
14#define PMC_SCRATCH41 0x140
15
16#define RESET_DATA(x) ((TEGRA_RESET_##x)*4)
17
18 .section ".text.head", "ax" 6 .section ".text.head", "ax"
7
19/* 8/*
20 * Tegra specific entry point for secondary CPUs. 9 * Tegra specific entry point for secondary CPUs.
21 * The secondary kernel init calls v7_flush_dcache_all before it enables 10 * The secondary kernel init calls v7_flush_dcache_all before it enables
@@ -59,7 +48,6 @@ ENTRY(v7_invalidate_l1)
59 mov pc, lr 48 mov pc, lr
60ENDPROC(v7_invalidate_l1) 49ENDPROC(v7_invalidate_l1)
61 50
62
63ENTRY(tegra_secondary_startup) 51ENTRY(tegra_secondary_startup)
64 bl v7_invalidate_l1 52 bl v7_invalidate_l1
65 /* Enable coresight */ 53 /* Enable coresight */
@@ -67,210 +55,3 @@ ENTRY(tegra_secondary_startup)
67 mcr p14, 0, r0, c7, c12, 6 55 mcr p14, 0, r0, c7, c12, 6
68 b secondary_startup 56 b secondary_startup
69ENDPROC(tegra_secondary_startup) 57ENDPROC(tegra_secondary_startup)
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 /* L2 cache resume & re-enable */
117 l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr
118
119 b cpu_resume
120ENDPROC(tegra_resume)
121#endif
122
123#ifdef CONFIG_CACHE_L2X0
124 .globl l2x0_saved_regs_addr
125l2x0_saved_regs_addr:
126 .long 0
127#endif
128
129 .align L1_CACHE_SHIFT
130ENTRY(__tegra_cpu_reset_handler_start)
131
132/*
133 * __tegra_cpu_reset_handler:
134 *
135 * Common handler for all CPU reset events.
136 *
137 * Register usage within the reset handler:
138 *
139 * R7 = CPU present (to the OS) mask
140 * R8 = CPU in LP1 state mask
141 * R9 = CPU in LP2 state mask
142 * R10 = CPU number
143 * R11 = CPU mask
144 * R12 = pointer to reset handler data
145 *
146 * NOTE: This code is copied to IRAM. All code and data accesses
147 * must be position-independent.
148 */
149
150 .align L1_CACHE_SHIFT
151ENTRY(__tegra_cpu_reset_handler)
152
153 cpsid aif, 0x13 @ SVC mode, interrupts disabled
154 mrc p15, 0, r10, c0, c0, 5 @ MPIDR
155 and r10, r10, #0x3 @ R10 = CPU number
156 mov r11, #1
157 mov r11, r11, lsl r10 @ R11 = CPU mask
158 adr r12, __tegra_cpu_reset_handler_data
159
160#ifdef CONFIG_SMP
161 /* Does the OS know about this CPU? */
162 ldr r7, [r12, #RESET_DATA(MASK_PRESENT)]
163 tst r7, r11 @ if !present
164 bleq __die @ CPU not present (to OS)
165#endif
166
167#ifdef CONFIG_ARCH_TEGRA_2x_SOC
168 /* Are we on Tegra20? */
169 mov32 r6, TEGRA_APB_MISC_BASE
170 ldr r0, [r6, #APB_MISC_GP_HIDREV]
171 and r0, r0, #0xff00
172 cmp r0, #(0x20 << 8)
173 bne 1f
174 /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
175 mov32 r6, TEGRA_PMC_BASE
176 mov r0, #0
177 cmp r10, #0
178 strne r0, [r6, #PMC_SCRATCH41]
1791:
180#endif
181
182 /* Waking up from LP2? */
183 ldr r9, [r12, #RESET_DATA(MASK_LP2)]
184 tst r9, r11 @ if in_lp2
185 beq __is_not_lp2
186 ldr lr, [r12, #RESET_DATA(STARTUP_LP2)]
187 cmp lr, #0
188 bleq __die @ no LP2 startup handler
189 bx lr
190
191__is_not_lp2:
192
193#ifdef CONFIG_SMP
194 /*
195 * Can only be secondary boot (initial or hotplug) but CPU 0
196 * cannot be here.
197 */
198 cmp r10, #0
199 bleq __die @ CPU0 cannot be here
200 ldr lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
201 cmp lr, #0
202 bleq __die @ no secondary startup handler
203 bx lr
204#endif
205
206/*
207 * We don't know why the CPU reset. Just kill it.
208 * The LR register will contain the address we died at + 4.
209 */
210
211__die:
212 sub lr, lr, #4
213 mov32 r7, TEGRA_PMC_BASE
214 str lr, [r7, #PMC_SCRATCH41]
215
216 mov32 r7, TEGRA_CLK_RESET_BASE
217
218 /* Are we on Tegra20? */
219 mov32 r6, TEGRA_APB_MISC_BASE
220 ldr r0, [r6, #APB_MISC_GP_HIDREV]
221 and r0, r0, #0xff00
222 cmp r0, #(0x20 << 8)
223 bne 1f
224
225#ifdef CONFIG_ARCH_TEGRA_2x_SOC
226 mov32 r0, 0x1111
227 mov r1, r0, lsl r10
228 str r1, [r7, #0x340] @ CLK_RST_CPU_CMPLX_SET
229#endif
2301:
231#ifdef CONFIG_ARCH_TEGRA_3x_SOC
232 mov32 r6, TEGRA_FLOW_CTRL_BASE
233
234 cmp r10, #0
235 moveq r1, #FLOW_CTRL_HALT_CPU0_EVENTS
236 moveq r2, #FLOW_CTRL_CPU0_CSR
237 movne r1, r10, lsl #3
238 addne r2, r1, #(FLOW_CTRL_CPU1_CSR-8)
239 addne r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8)
240
241 /* Clear CPU "event" and "interrupt" flags and power gate
242 it when halting but not before it is in the "WFI" state. */
243 ldr r0, [r6, +r2]
244 orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
245 orr r0, r0, #FLOW_CTRL_CSR_ENABLE
246 str r0, [r6, +r2]
247
248 /* Unconditionally halt this CPU */
249 mov r0, #FLOW_CTRL_WAITEVENT
250 str r0, [r6, +r1]
251 ldr r0, [r6, +r1] @ memory barrier
252
253 dsb
254 isb
255 wfi @ CPU should be power gated here
256
257 /* If the CPU didn't power gate above just kill it's clock. */
258
259 mov r0, r11, lsl #8
260 str r0, [r7, #348] @ CLK_CPU_CMPLX_SET
261#endif
262
263 /* If the CPU still isn't dead, just spin here. */
264 b .
265ENDPROC(__tegra_cpu_reset_handler)
266
267 .align L1_CACHE_SHIFT
268 .type __tegra_cpu_reset_handler_data, %object
269 .globl __tegra_cpu_reset_handler_data
270__tegra_cpu_reset_handler_data:
271 .rept TEGRA_RESET_DATA_SIZE
272 .long 0
273 .endr
274 .align L1_CACHE_SHIFT
275
276ENTRY(__tegra_cpu_reset_handler_end)