ARM: tegra: clean up the common assembly macros into sleep.h
[linux-3.10.git] / arch / arm / mach-tegra / headsmp.S
1 #include <linux/linkage.h>
2 #include <linux/init.h>
3
4 #include <asm/cache.h>
5
6 #include <mach/iomap.h>
7
8 #include "flowctrl.h"
9 #include "reset.h"
10 #include "sleep.h"
11
12 #define APB_MISC_GP_HIDREV      0x804
13 #define PMC_SCRATCH41   0x140
14
15 #define RESET_DATA(x)   ((TEGRA_RESET_##x)*4)
16
17         .section ".text.head", "ax"
18         __CPUINIT
19
20 /*
21  * Tegra specific entry point for secondary CPUs.
22  *   The secondary kernel init calls v7_flush_dcache_all before it enables
23  *   the L1; however, the L1 comes out of reset in an undefined state, so
24  *   the clean + invalidate performed by v7_flush_dcache_all causes a bunch
25  *   of cache lines with uninitialized data and uninitialized tags to get
26  *   written out to memory, which does really unpleasant things to the main
27  *   processor.  We fix this by performing an invalidate, rather than a
28  *   clean + invalidate, before jumping into the kernel.
29  */
30 ENTRY(v7_invalidate_l1)
31         mov     r0, #0
32         mcr     p15, 2, r0, c0, c0, 0
33         mrc     p15, 1, r0, c0, c0, 0
34
35         ldr     r1, =0x7fff
36         and     r2, r1, r0, lsr #13
37
38         ldr     r1, =0x3ff
39
40         and     r3, r1, r0, lsr #3  @ NumWays - 1
41         add     r2, r2, #1          @ NumSets
42
43         and     r0, r0, #0x7
44         add     r0, r0, #4          @ SetShift
45
46         clz     r1, r3              @ WayShift
47         add     r4, r3, #1          @ NumWays
48 1:      sub     r2, r2, #1          @ NumSets--
49         mov     r3, r4              @ Temp = NumWays
50 2:      subs    r3, r3, #1          @ Temp--
51         mov     r5, r3, lsl r1
52         mov     r6, r2, lsl r0
53         orr     r5, r5, r6          @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
54         mcr     p15, 0, r5, c7, c6, 2
55         bgt     2b
56         cmp     r2, #0
57         bgt     1b
58         dsb
59         isb
60         mov     pc, lr
61 ENDPROC(v7_invalidate_l1)
62
63
64 ENTRY(tegra_secondary_startup)
65         bl      v7_invalidate_l1
66         /* Enable coresight */
67         mov32   r0, 0xC5ACCE55
68         mcr     p14, 0, r0, c7, c12, 6
69         b       secondary_startup
70 ENDPROC(tegra_secondary_startup)
71
72         .align L1_CACHE_SHIFT
73 ENTRY(__tegra_cpu_reset_handler_start)
74
75 /*
76  * __tegra_cpu_reset_handler:
77  *
78  * Common handler for all CPU reset events.
79  *
80  * Register usage within the reset handler:
81  *
82  *      R7  = CPU present (to the OS) mask
83  *      R8  = CPU in LP1 state mask
84  *      R9  = CPU in LP2 state mask
85  *      R10 = CPU number
86  *      R11 = CPU mask
87  *      R12 = pointer to reset handler data
88  *
89  * NOTE: This code is copied to IRAM. All code and data accesses
90  *       must be position-independent.
91  */
92
93         .align L1_CACHE_SHIFT
94 ENTRY(__tegra_cpu_reset_handler)
95
96         cpsid   aif, 0x13                       @ SVC mode, interrupts disabled
97         mrc     p15, 0, r10, c0, c0, 5          @ MPIDR
98         and     r10, r10, #0x3                  @ R10 = CPU number
99         mov     r11, #1
100         mov     r11, r11, lsl r10               @ R11 = CPU mask
101         adr     r12, __tegra_cpu_reset_handler_data
102
103 #ifdef CONFIG_SMP
104         /* Does the OS know about this CPU? */
105         ldr     r7, [r12, #RESET_DATA(MASK_PRESENT)]
106         tst     r7, r11                         @ if !present
107         bleq    __die                           @ CPU not present (to OS)
108 #endif
109
110 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
111         /* Are we on Tegra20? */
112         mov32   r6, TEGRA_APB_MISC_BASE
113         ldr     r0, [r6, #APB_MISC_GP_HIDREV]
114         and     r0, r0, #0xff00
115         cmp     r0, #(0x20 << 8)
116         bne     1f
117         /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
118         mov32   r6, TEGRA_PMC_BASE
119         mov     r0, #0
120         cmp     r10, #0
121         strne   r0, [r6, #PMC_SCRATCH41]
122 1:
123 #endif
124
125 #ifdef CONFIG_SMP
126         /*
127          * Can only be secondary boot (initial or hotplug) but CPU 0
128          * cannot be here.
129          */
130         cmp     r10, #0
131         bleq    __die                           @ CPU0 cannot be here
132         ldr     lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
133         cmp     lr, #0
134         bleq    __die                           @ no secondary startup handler
135         bx      lr
136 #endif
137
138 /*
139  * We don't know why the CPU reset. Just kill it.
140  * The LR register will contain the address we died at + 4.
141  */
142
143 __die:
144         sub     lr, lr, #4
145         mov32   r7, TEGRA_PMC_BASE
146         str     lr, [r7, #PMC_SCRATCH41]
147
148         mov32   r7, TEGRA_CLK_RESET_BASE
149
150         /* Are we on Tegra20? */
151         mov32   r6, TEGRA_APB_MISC_BASE
152         ldr     r0, [r6, #APB_MISC_GP_HIDREV]
153         and     r0, r0, #0xff00
154         cmp     r0, #(0x20 << 8)
155         bne     1f
156
157 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
158         mov32   r0, 0x1111
159         mov     r1, r0, lsl r10
160         str     r1, [r7, #0x340]                @ CLK_RST_CPU_CMPLX_SET
161 #endif
162 1:
163 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
164         mov32   r6, TEGRA_FLOW_CTRL_BASE
165
166         cmp     r10, #0
167         moveq   r1, #FLOW_CTRL_HALT_CPU0_EVENTS
168         moveq   r2, #FLOW_CTRL_CPU0_CSR
169         movne   r1, r10, lsl #3
170         addne   r2, r1, #(FLOW_CTRL_CPU1_CSR-8)
171         addne   r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8)
172
173         /* Clear CPU "event" and "interrupt" flags and power gate
174            it when halting but not before it is in the "WFI" state. */
175         ldr     r0, [r6, +r2]
176         orr     r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
177         orr     r0, r0, #FLOW_CTRL_CSR_ENABLE
178         str     r0, [r6, +r2]
179
180         /* Unconditionally halt this CPU */
181         mov     r0, #FLOW_CTRL_WAITEVENT
182         str     r0, [r6, +r1]
183         ldr     r0, [r6, +r1]                   @ memory barrier
184
185         dsb
186         isb
187         wfi                                     @ CPU should be power gated here
188
189         /* If the CPU didn't power gate above just kill it's clock. */
190
191         mov     r0, r11, lsl #8
192         str     r0, [r7, #348]                  @ CLK_CPU_CMPLX_SET
193 #endif
194
195         /* If the CPU still isn't dead, just spin here. */
196         b       .
197 ENDPROC(__tegra_cpu_reset_handler)
198
199         .align L1_CACHE_SHIFT
200         .type   __tegra_cpu_reset_handler_data, %object
201         .globl  __tegra_cpu_reset_handler_data
202 __tegra_cpu_reset_handler_data:
203         .rept   TEGRA_RESET_DATA_SIZE
204         .long   0
205         .endr
206         .align L1_CACHE_SHIFT
207
208 ENTRY(__tegra_cpu_reset_handler_end)