arm: Add v7_invalidate_l1 to cache-v7.S
[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 #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"
12
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"
19         __CPUINIT
20
21
22 ENTRY(tegra_secondary_startup)
23         bl      v7_invalidate_l1
24         /* Enable coresight */
25         mov32   r0, 0xC5ACCE55
26         mcr     p14, 0, r0, c7, c12, 6
27         b       secondary_startup
28 ENDPROC(tegra_secondary_startup)
29
30 #ifdef CONFIG_PM_SLEEP
31 /*
32  *      tegra_resume
33  *
34  *        CPU boot vector when restarting the a CPU following
35  *        an LP2 transition. Also branched to by LP0 and LP1 resume after
36  *        re-enabling sdram.
37  */
38 ENTRY(tegra_resume)
39         bl      v7_invalidate_l1
40         /* Enable coresight */
41         mov32   r0, 0xC5ACCE55
42         mcr     p14, 0, r0, c7, c12, 6
43
44         cpu_id  r0
45         cmp     r0, #0                          @ CPU0?
46         bne     cpu_resume                      @ no
47
48 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
49         /* Are we on Tegra20? */
50         mov32   r6, TEGRA_APB_MISC_BASE
51         ldr     r0, [r6, #APB_MISC_GP_HIDREV]
52         and     r0, r0, #0xff00
53         cmp     r0, #(0x20 << 8)
54         beq     1f                              @ Yes
55         /* Clear the flow controller flags for this CPU. */
56         mov32   r2, TEGRA_FLOW_CTRL_BASE + FLOW_CTRL_CPU0_CSR   @ CPU0 CSR
57         ldr     r1, [r2]
58         /* Clear event & intr flag */
59         orr     r1, r1, \
60                 #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
61         movw    r0, #0x0FFD     @ enable, cluster_switch, immed, & bitmaps
62         bic     r1, r1, r0
63         str     r1, [r2]
64 1:
65 #endif
66
67 #ifdef CONFIG_HAVE_ARM_SCU
68         /* enable SCU */
69         mov32   r0, TEGRA_ARM_PERIF_BASE
70         ldr     r1, [r0]
71         orr     r1, r1, #1
72         str     r1, [r0]
73 #endif
74
75         /* L2 cache resume & re-enable */
76         l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr
77
78         b       cpu_resume
79 ENDPROC(tegra_resume)
80 #endif
81
82 #ifdef CONFIG_CACHE_L2X0
83         .globl  l2x0_saved_regs_addr
84 l2x0_saved_regs_addr:
85         .long   0
86 #endif
87
88         .align L1_CACHE_SHIFT
89 ENTRY(__tegra_cpu_reset_handler_start)
90
91 /*
92  * __tegra_cpu_reset_handler:
93  *
94  * Common handler for all CPU reset events.
95  *
96  * Register usage within the reset handler:
97  *
98  *      R7  = CPU present (to the OS) mask
99  *      R8  = CPU in LP1 state mask
100  *      R9  = CPU in LP2 state mask
101  *      R10 = CPU number
102  *      R11 = CPU mask
103  *      R12 = pointer to reset handler data
104  *
105  * NOTE: This code is copied to IRAM. All code and data accesses
106  *       must be position-independent.
107  */
108
109         .align L1_CACHE_SHIFT
110 ENTRY(__tegra_cpu_reset_handler)
111
112         cpsid   aif, 0x13                       @ SVC mode, interrupts disabled
113         mrc     p15, 0, r10, c0, c0, 5          @ MPIDR
114         and     r10, r10, #0x3                  @ R10 = CPU number
115         mov     r11, #1
116         mov     r11, r11, lsl r10               @ R11 = CPU mask
117         adr     r12, __tegra_cpu_reset_handler_data
118
119 #ifdef CONFIG_SMP
120         /* Does the OS know about this CPU? */
121         ldr     r7, [r12, #RESET_DATA(MASK_PRESENT)]
122         tst     r7, r11                         @ if !present
123         bleq    __die                           @ CPU not present (to OS)
124 #endif
125
126 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
127         /* Are we on Tegra20? */
128         mov32   r6, TEGRA_APB_MISC_BASE
129         ldr     r0, [r6, #APB_MISC_GP_HIDREV]
130         and     r0, r0, #0xff00
131         cmp     r0, #(0x20 << 8)
132         bne     1f
133         /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
134         mov32   r6, TEGRA_PMC_BASE
135         mov     r0, #0
136         cmp     r10, #0
137         strne   r0, [r6, #PMC_SCRATCH41]
138 1:
139 #endif
140
141         /* Waking up from LP2? */
142         ldr     r9, [r12, #RESET_DATA(MASK_LP2)]
143         tst     r9, r11                         @ if in_lp2
144         beq     __is_not_lp2
145         ldr     lr, [r12, #RESET_DATA(STARTUP_LP2)]
146         cmp     lr, #0
147         bleq    __die                           @ no LP2 startup handler
148         bx      lr
149
150 __is_not_lp2:
151
152 #ifdef CONFIG_SMP
153         /*
154          * Can only be secondary boot (initial or hotplug) but CPU 0
155          * cannot be here.
156          */
157         cmp     r10, #0
158         bleq    __die                           @ CPU0 cannot be here
159         ldr     lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
160         cmp     lr, #0
161         bleq    __die                           @ no secondary startup handler
162         bx      lr
163 #endif
164
165 /*
166  * We don't know why the CPU reset. Just kill it.
167  * The LR register will contain the address we died at + 4.
168  */
169
170 __die:
171         sub     lr, lr, #4
172         mov32   r7, TEGRA_PMC_BASE
173         str     lr, [r7, #PMC_SCRATCH41]
174
175         mov32   r7, TEGRA_CLK_RESET_BASE
176
177         /* Are we on Tegra20? */
178         mov32   r6, TEGRA_APB_MISC_BASE
179         ldr     r0, [r6, #APB_MISC_GP_HIDREV]
180         and     r0, r0, #0xff00
181         cmp     r0, #(0x20 << 8)
182         bne     1f
183
184 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
185         mov32   r0, 0x1111
186         mov     r1, r0, lsl r10
187         str     r1, [r7, #0x340]                @ CLK_RST_CPU_CMPLX_SET
188 #endif
189 1:
190 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
191         mov32   r6, TEGRA_FLOW_CTRL_BASE
192
193         cmp     r10, #0
194         moveq   r1, #FLOW_CTRL_HALT_CPU0_EVENTS
195         moveq   r2, #FLOW_CTRL_CPU0_CSR
196         movne   r1, r10, lsl #3
197         addne   r2, r1, #(FLOW_CTRL_CPU1_CSR-8)
198         addne   r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8)
199
200         /* Clear CPU "event" and "interrupt" flags and power gate
201            it when halting but not before it is in the "WFI" state. */
202         ldr     r0, [r6, +r2]
203         orr     r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
204         orr     r0, r0, #FLOW_CTRL_CSR_ENABLE
205         str     r0, [r6, +r2]
206
207         /* Unconditionally halt this CPU */
208         mov     r0, #FLOW_CTRL_WAITEVENT
209         str     r0, [r6, +r1]
210         ldr     r0, [r6, +r1]                   @ memory barrier
211
212         dsb
213         isb
214         wfi                                     @ CPU should be power gated here
215
216         /* If the CPU didn't power gate above just kill it's clock. */
217
218         mov     r0, r11, lsl #8
219         str     r0, [r7, #348]                  @ CLK_CPU_CMPLX_SET
220 #endif
221
222         /* If the CPU still isn't dead, just spin here. */
223         b       .
224 ENDPROC(__tegra_cpu_reset_handler)
225
226         .align L1_CACHE_SHIFT
227         .type   __tegra_cpu_reset_handler_data, %object
228         .globl  __tegra_cpu_reset_handler_data
229 __tegra_cpu_reset_handler_data:
230         .rept   TEGRA_RESET_DATA_SIZE
231         .long   0
232         .endr
233         .align L1_CACHE_SHIFT
234
235 ENTRY(__tegra_cpu_reset_handler_end)