dadc57930c9f69e062c6580b179d6f5e6ec88776
[linux-3.10.git] / arch / arm / mach-tegra / headsmp.S
1 /*
2  * arch/arm/mach-tegra/headsmp.S
3  *
4  * CPU initialization routines for Tegra SoCs
5  *
6  * Copyright (c) 2009-2011, NVIDIA Corporation.
7  * Copyright (c) 2011 Google, Inc.
8  * Author: Colin Cross <ccross@android.com>
9  *         Gary King <gking@nvidia.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License.
14  *
15  * This program is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18  * more details.
19  */
20
21 #include <linux/linkage.h>
22 #include <linux/init.h>
23
24 #include <asm/cache.h>
25 #include <asm/page.h>
26
27 #include "flowctrl.h"
28 #include "iomap.h"
29 #include "reset.h"
30 #include "sleep.h"
31
32 #define DEBUG_CPU_RESET_HANDLER 0       /* Non-zero enables debug code */
33
34 #define APB_MISC_GP_HIDREV      0x804
35 #define PMC_SCRATCH41   0x140
36
37 #define RESET_DATA(x)   ((TEGRA_RESET_##x)*4)
38
39         .section ".text.head", "ax"
40         __CPUINIT
41
42 /*
43  *      __invalidate_cpu_state
44  *
45  *        Invalidates volatile CPU state (SCU tags, caches, branch address
46  *        arrays, exclusive monitor, etc.) so that they can be safely enabled
47  *        instruction caching and branch predicition enabled
48  */
49 __invalidate_cpu_state:
50         clrex
51         mov     r0, #0
52         mcr     p15, 0, r0, c1, c0, 1   @ disable SMP, prefetch, broadcast
53         isb
54         mcr     p15, 0, r0, c7, c5, 0   @ invalidate BTAC, i-cache
55         mcr     p15, 0, r0, c7, c5, 6   @ invalidate branch pred array
56         mcr     p15, 0, r0, c8, c7, 0   @ invalidate unified TLB
57         dsb
58         isb
59
60         cpu_id  r0
61         cmp     r0, #0
62         mov32   r1, (TEGRA_ARM_PERIF_BASE + 0xC)
63         movne   r0, r0, lsl #2
64         movne   r2, #0xf
65         movne   r2, r2, lsl r0
66         strne   r2, [r1]                @ invalidate SCU tags for CPU
67
68         dsb
69         mov     r0, #0x1800
70         mcr     p15, 0, r0, c1, c0, 0   @ enable branch prediction, i-cache
71         isb
72         /* fall through */
73
74 /*
75  *   The secondary kernel init calls v7_flush_dcache_all before it enables
76  *   the L1; however, the L1 comes out of reset in an undefined state, so
77  *   the clean + invalidate performed by v7_flush_dcache_all causes a bunch
78  *   of cache lines with uninitialized data and uninitialized tags to get
79  *   written out to memory, which does really unpleasant things to the main
80  *   processor.  We fix this by performing an invalidate, rather than a
81  *   clean + invalidate, before jumping into the kernel.
82  */
83 ENTRY(v7_invalidate_l1)
84         mov     r0, #0
85         mcr     p15, 2, r0, c0, c0, 0
86         mrc     p15, 1, r0, c0, c0, 0
87
88         ldr     r1, =0x7fff
89         and     r2, r1, r0, lsr #13
90
91         ldr     r1, =0x3ff
92
93         and     r3, r1, r0, lsr #3  @ NumWays - 1
94         add     r2, r2, #1          @ NumSets
95
96         and     r0, r0, #0x7
97         add     r0, r0, #4          @ SetShift
98
99         clz     r1, r3              @ WayShift
100         add     r4, r3, #1          @ NumWays
101 1:      sub     r2, r2, #1          @ NumSets--
102         mov     r3, r4              @ Temp = NumWays
103 2:      subs    r3, r3, #1          @ Temp--
104         mov     r5, r3, lsl r1
105         mov     r6, r2, lsl r0
106         orr     r5, r5, r6          @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
107         mcr     p15, 0, r5, c7, c6, 2
108         bgt     2b
109         cmp     r2, #0
110         bgt     1b
111         dsb
112         isb
113         mov     pc, lr
114 ENDPROC(v7_invalidate_l1)
115
116
117 #ifdef CONFIG_SMP
118 /* 
119  *      tegra_secondary_startup
120  *
121  *       Initial secondary processor boot vector; jumps to kernel's
122  *       secondary_startup routine. Used for initial boot and hotplug
123  *       of secondary CPUs.
124  */
125         __CPUINIT
126 ENTRY(tegra_secondary_startup)
127         bl      __invalidate_cpu_state
128         b       secondary_startup
129 ENDPROC(tegra_secondary_startup)
130         .previous
131 #endif
132
133 #ifdef CONFIG_PM_SLEEP
134 /*
135  *      tegra_resume
136  *
137  *        CPU boot vector when restarting the a CPU following
138  *        an LP2 transition. Also branched to by LP0 and LP1 resume after
139  *        re-enabling sdram.
140  */
141 ENTRY(tegra_resume)
142         bl      __invalidate_cpu_state
143
144         cpu_id  r0
145         cmp     r0, #0                          @ CPU0?
146         bne     cpu_resume                      @ no
147
148 #ifndef CONFIG_ARCH_TEGRA_2x_SOC
149         @ Clear the flow controller flags for this CPU.
150         mov32   r2, TEGRA_FLOW_CTRL_BASE+8      @ CPU0 CSR
151         ldr     r1, [r2]
152         orr     r1, r1, #(1 << 15) | (1 << 14)  @ write to clear event & intr
153         movw    r0, #0x0FFD     @ enable, cluster_switch, immed, & bitmaps
154         bic     r1, r1, r0
155         str     r1, [r2]
156 #endif
157
158         /* enable SCU */
159         mov32   r0, TEGRA_ARM_PERIF_BASE
160         ldr     r1, [r0]
161         orr     r1, r1, #1
162 #if defined(CONFIG_HAVE_ARM_SCU)
163         orr     r1, r1, #(1 << 3)       @ Enable SCU speculative line fill.
164         orr     r1, r1, #(1 << 5)       @ Enable IC standby.
165         orr     r1, r1, #(1 << 6)       @ Enable SCU standby.
166 #endif
167         str     r1, [r0]
168
169 #ifdef CONFIG_TRUSTED_FOUNDATIONS
170         /* wake up (should have specified args?) */
171         bl      tegra_generic_smc
172 #endif
173
174         b       cpu_resume
175 ENDPROC(tegra_resume)
176 #endif
177
178         .align L1_CACHE_SHIFT
179 ENTRY(__tegra_cpu_reset_handler_start)
180
181 /*
182  * __tegra_cpu_reset_handler:
183  *
184  * Common handler for all CPU reset events.
185  *
186  * Register usage within the reset handler:
187  *
188  *      R7  = CPU present (to the OS) mask
189  *      R8  = CPU in LP1 state mask
190  *      R9  = CPU in LP2 state mask
191  *      R10 = CPU number
192  *      R11 = CPU mask
193  *      R12 = pointer to reset handler data
194  *
195  * NOTE: This code is copied to IRAM. All code and data accesses
196  *       must be position-independent.
197  */
198
199         .align L1_CACHE_SHIFT
200 ENTRY(__tegra_cpu_reset_handler)
201
202 #if DEBUG_CPU_RESET_HANDLER
203         b       .
204 #endif
205 #ifndef CONFIG_TRUSTED_FOUNDATIONS
206         cpsid   aif, 0x13                       @ SVC mode, interrupts disabled
207         mrc     p15, 0, r0, c0, c0, 0           @ read main ID register
208         and     r5, r0, #0x00f00000             @ variant
209         and     r6, r0, #0x0000000f             @ revision
210         orr     r6, r6, r5, lsr #20-4           @ combine variant and revision
211 #ifdef CONFIG_ARM_ERRATA_743622
212         teq     r6, #0x20                       @ present in r2p0
213         teqne   r6, #0x21                       @ present in r2p1
214         teqne   r6, #0x22                       @ present in r2p2
215         teqne   r6, #0x27                       @ present in r2p7
216         teqne   r6, #0x29                       @ present in r2p9
217         mrceq   p15, 0, r10, c15, c0, 1         @ read diagnostic register
218         orreq   r10, r10, #1 << 6               @ set bit #6
219         mcreq   p15, 0, r10, c15, c0, 1         @ write diagnostic register
220 #endif
221 #endif
222         mrc     p15, 0, r10, c0, c0, 5          @ MPIDR
223         and     r10, r10, #0x3                  @ R10 = CPU number
224         mov     r11, #1
225         mov     r11, r11, lsl r10               @ R11 = CPU mask
226         adr     r12, __tegra_cpu_reset_handler_data
227
228 #ifdef CONFIG_SMP
229         /* Does the OS know about this CPU? */
230         ldr     r7, [r12, #RESET_DATA(MASK_PRESENT)]
231         tst     r7, r11                         @ if !present
232         bleq    __die                           @ CPU not present (to OS)
233 #endif
234
235 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
236         /* Are we on Tegra20? */
237         mov32   r6, TEGRA_APB_MISC_BASE
238         ldr     r0, [r6, #APB_MISC_GP_HIDREV]
239         and     r0, r0, #0xff00
240         cmp     r0, #(0x20 << 8)
241         bne     1f
242         /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
243         mov32   r6, TEGRA_PMC_BASE
244         mov     r0, #0
245         cmp     r10, #0
246         strne   r0, [r6, #PMC_SCRATCH41]
247 1:
248 #endif
249
250 #ifdef CONFIG_PM_SLEEP
251         /* Waking up from LP1? */
252         ldr     r8, [r12, #RESET_DATA(MASK_LP1)]
253         tst     r8, r11                         @ if in_lp1
254         beq     __is_not_lp1
255         cmp     r10, #0
256         bne     __die                           @ only CPU0 can be here
257         ldr     lr, [r12, #RESET_DATA(STARTUP_LP1)]
258         cmp     lr, #0
259         bleq    __die                           @ no LP1 startup handler
260         bx      lr
261 __is_not_lp1:
262 #endif
263
264         /* Waking up from LP2? */
265         ldr     r9, [r12, #RESET_DATA(MASK_LP2)]
266         tst     r9, r11                         @ if in_lp2
267         beq     __is_not_lp2
268         ldr     lr, [r12, #RESET_DATA(STARTUP_LP2)]
269         cmp     lr, #0
270         bleq    __die                           @ no LP2 startup handler
271         bx      lr
272
273 __is_not_lp2:
274 #ifdef CONFIG_SMP
275         /*
276          * Can only be secondary boot (initial or hotplug) but CPU 0
277          * cannot be here.
278          */
279         cmp     r10, #0
280         bleq    __die                           @ CPU0 cannot be here
281         ldr     lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
282         cmp     lr, #0
283         bleq    __die                           @ no secondary startup handler
284         bx      lr
285 #endif
286
287 /*
288  * We don't know why the CPU reset. Just kill it.
289  * The LR register will contain the address we died at + 4.
290  */
291
292 __die:
293         sub     lr, lr, #4
294         mov32   r7, TEGRA_PMC_BASE
295         str     lr, [r7, #PMC_SCRATCH41]
296
297         mov32   r7, TEGRA_CLK_RESET_BASE
298
299         /* Are we on Tegra20? */
300         mov32   r6, TEGRA_APB_MISC_BASE
301         ldr     r0, [r6, #APB_MISC_GP_HIDREV]
302         and     r0, r0, #0xff00
303         cmp     r0, #(0x20 << 8)
304         bne     1f
305
306 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
307         mov32   r0, 0x1111
308         mov     r1, r0, lsl r10
309         str     r1, [r7, #0x340]                @ CLK_RST_CPU_CMPLX_SET
310 #endif
311 1:
312 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
313         mov32   r6, TEGRA_FLOW_CTRL_BASE
314
315         cmp     r10, #0
316         moveq   r1, #FLOW_CTRL_HALT_CPU0_EVENTS
317         moveq   r2, #FLOW_CTRL_CPU0_CSR
318         movne   r1, r10, lsl #3
319         addne   r2, r1, #(FLOW_CTRL_CPU1_CSR-8)
320         addne   r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8)
321
322         /* Clear CPU "event" and "interrupt" flags and power gate
323            it when halting but not before it is in the "WFI" state. */
324         ldr     r0, [r6, +r2]
325         orr     r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
326         orr     r0, r0, #FLOW_CTRL_CSR_ENABLE
327         str     r0, [r6, +r2]
328
329         /* Unconditionally halt this CPU */
330         mov     r0, #FLOW_CTRL_WAITEVENT
331         str     r0, [r6, +r1]
332         ldr     r0, [r6, +r1]                   @ memory barrier
333
334         dsb
335         isb
336         wfi                                     @ CPU should be power gated here
337
338         /* If the CPU didn't power gate above just kill it's clock. */
339
340         mov     r0, r11, lsl #8
341         str     r0, [r7, #348]                  @ CLK_CPU_CMPLX_SET
342 #endif
343
344         /* If the CPU still isn't dead, just spin here. */
345         b       .
346 ENDPROC(__tegra_cpu_reset_handler)
347
348         .align L1_CACHE_SHIFT
349         .type   __tegra_cpu_reset_handler_data, %object
350         .globl  __tegra_cpu_reset_handler_data
351 __tegra_cpu_reset_handler_data:
352         .rept   TEGRA_RESET_DATA_SIZE
353         .long   0
354         .endr
355         .align L1_CACHE_SHIFT
356
357 ENTRY(__tegra_cpu_reset_handler_end)