Ventana: KBC: Removing the KBC usage on ventana
[linux-2.6.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/assembler.h>
25 #include <asm/cache.h>
26 #include <asm/page.h>
27
28 #include <mach/iomap.h>
29 #include <mach/io.h>
30
31 #include "asm_macros.h"
32 #include "reset.h"
33 #include "sleep.h"
34
35 #define DEBUG_CPU_RESET_HANDLER 0       /* Non-zero enables debug code */
36
37 #define PMC_SCRATCH41           0x140
38
39 #define RESET_DATA(x)           ((TEGRA_RESET_##x)*4)
40
41
42 #ifdef CONFIG_SMP
43 /*
44  *      tegra_secondary_startup
45  *
46  *       Initial secondary processor boot vector; jumps to kernel's
47  *       secondary_startup routine. Used for initial boot and hotplug
48  *       of secondary CPUs.
49  */
50 ENTRY(tegra_secondary_startup)
51         bl      tegra_invalidate_l1
52         bl      tegra_enable_coresite
53         b       secondary_startup
54 ENDPROC(tegra_secondary_startup)
55 #endif
56
57 #ifdef CONFIG_PM_SLEEP
58 /*
59  *      tegra_resume
60  *
61  *        CPU boot vector when restarting the a CPU following
62  *        an LP2 transition. Also branched to by LP0 and LP1 resume after
63  *        re-enabling sdram.
64  */
65 ENTRY(tegra_resume)
66         bl      tegra_enable_coresite
67         bl      tegra_invalidate_l1
68
69         cpu_id  r0
70         cmp     r0, #0                          @ CPU0?
71         bne     tegra_cpu_resume_phys           @ no
72
73 #ifndef CONFIG_ARCH_TEGRA_2x_SOC
74         @ Clear the flow controller flags for this CPU.
75         mov32   r2, TEGRA_FLOW_CTRL_BASE+8      @ CPU0 CSR
76         ldr     r1, [r2]
77         orr     r1, r1, #(1 << 15) | (1 << 14)  @ write to clear event & intr
78         movw    r0, #0x0FFD     @ enable, cluster_switch, immed, & bitmaps
79         bic     r1, r1, r0
80         str     r1, [r2]
81 #endif
82
83         /* enable SCU */
84         mov32   r0, TEGRA_ARM_PERIF_BASE
85         ldr     r1, [r0]
86         orr     r1, r1, #1
87         str     r1, [r0]
88
89         b       tegra_cpu_resume_phys
90 ENDPROC(tegra_resume)
91 #endif
92
93 /*
94  *      tegra_invalidate_l1
95  *
96  *        Invalidates the L1 data cache (no clean) during initial boot of a cpu
97  *
98  *        Corrupted registers: r0-r6
99  */
100 tegra_invalidate_l1:
101         mov     r0, #0
102         mcr     p15, 2, r0, c0, c0, 0
103         mrc     p15, 1, r0, c0, c0, 0
104
105         movw    r1, #0x7fff
106         and     r2, r1, r0, lsr #13
107
108         movw    r1, #0x3ff
109
110         and     r3, r1, r0, lsr #3      @ NumWays - 1
111         add     r2, r2, #1      @ NumSets
112
113         and     r0, r0, #0x7
114         add     r0, r0, #4      @ SetShift
115
116         clz     r1, r3          @ WayShift
117         add     r4, r3, #1      @ NumWays
118 1:      sub     r2, r2, #1      @ NumSets--
119         mov     r3, r4          @ Temp = NumWays
120 2:      subs    r3, r3, #1      @ Temp--
121         mov     r5, r3, lsl r1
122         mov     r6, r2, lsl r0
123         orr     r5, r5, r6      @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
124         mcr     p15, 0, r5, c7, c6, 2
125         bgt     2b
126         cmp     r2, #0
127         bgt     1b
128         dsb
129         isb
130         mov     pc, lr
131
132         /* Enable Coresight access on cpu */
133 tegra_enable_coresite:
134         mov32   r0, 0xC5ACCE55
135         mcr     p14, 0, r0, c7, c12, 6
136         mov     pc, lr
137
138 /*
139  * __tegra_cpu_reset_handler_halt_failed:
140  *
141  * Alternate entry point for reset handler for cases where the
142  * WFI halt failed to take effect.
143  *
144  */
145         .align L1_CACHE_SHIFT
146 ENTRY(__tegra_cpu_reset_handler_start)
147
148 /*
149  * __tegra_cpu_reset_handler:
150  *
151  * Common handler for all CPU reset events.
152  *
153  * Register usage within the reset handler:
154  *
155  *      R7  = CPU present (to the OS) mask
156  *      R8  = CPU in LP1 state mask
157  *      R9  = CPU in LP2 state mask
158  *      R10 = CPU number
159  *      R11 = CPU mask
160  *      R12 = pointer to reset handler data
161  *
162  * NOTE: This code is copied to IRAM. All code and data accesses
163  *       must be position-independent.
164  */
165
166         .align L1_CACHE_SHIFT
167 ENTRY(__tegra_cpu_reset_handler)
168
169 #if DEBUG_CPU_RESET_HANDLER
170         mov32   r0, 0xC5ACCE55
171         mcr     p14, 0, r0, c7, c12, 6          @ Enable CoreSight access
172         b       .
173 #endif
174         mrc     p15, 0, r10, c0, c0, 5          @ MPIDR
175         and     r10, r10, #0x3                  @ R10 = CPU number
176         mov     r11, #1
177         mov     r11, r11, lsl r10               @ R11 = CPU mask
178         adr     r12, __tegra_cpu_reset_handler_data
179
180 #ifdef CONFIG_SMP
181         /* Does the OS know about this CPU? */
182         ldr     r7, [r12, #RESET_DATA(MASK_PRESENT)]
183         tst     r7, r11                         @ if !present
184         bleq    __die                           @ CPU not present (to OS)
185 #endif
186
187 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
188         /* If CPU1, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
189         mov32   r6, TEGRA_PMC_BASE
190         mov     r0, #0
191         cmp     r10, #0
192         strne   r0, [r6, #PMC_SCRATCH41]
193 #endif
194
195 #ifdef CONFIG_PM_SLEEP
196         /* Waking up from LP1? */
197         ldr     r8, [r12, #RESET_DATA(MASK_LP1)]
198         tst     r8, r11                         @ if in_lp1
199         beq     __is_not_lp1
200         cmp     r10, #0
201         bne     __die                           @ only CPU0 can be here
202         ldr     lr, [r12, #RESET_DATA(STARTUP_LP1)]
203         cmp     lr, #0
204         bleq    __die                           @ no LP1 startup handler
205         bx      lr
206 __is_not_lp1:
207 #endif
208
209         /* Waking up from LP2? */
210         ldr     r9, [r12, #RESET_DATA(MASK_LP2)]
211         tst     r9, r11                         @ if in_lp2
212         beq     __is_not_lp2
213         ldr     lr, [r12, #RESET_DATA(STARTUP_LP2)]
214         cmp     lr, #0
215         bleq    __die                           @ no LP2 startup handler
216         bx      lr
217
218 __is_not_lp2:
219
220 #ifdef CONFIG_SMP
221         /* Can only be secondary boot (initial or hotplug) but CPU 0
222            cannot be here. */
223         cmp     r10, #0
224         bleq    __die                           @ CPU0 cannot be here
225         ldr     lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
226         cmp     lr, #0
227         bleq    __die                           @ no secondary startup handler
228         bx      lr
229 #endif
230
231 /*
232  * We don't know why the CPU reset. Just kill it.
233  * The LR register will contain the address we died at + 4.
234  */
235
236 __die:
237         sub     lr, lr, #4
238         mov32   r7, TEGRA_PMC_BASE
239         str     lr, [r7, #PMC_SCRATCH41]
240
241         mov32   r7, TEGRA_CLK_RESET_BASE
242
243 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
244         mov32   r0, 0x1111
245         mov     r1, r0, lsl r10
246         str     r1, [r7, #0x340]                @ CLK_RST_CPU_CMPLX_SET
247 #else
248         mov32   r6, TEGRA_FLOW_CTRL_BASE
249
250         cmp     r10, #0
251         moveq   r1, #FLOW_CTRL_HALT_CPU0_EVENTS
252         moveq   r2, #FLOW_CTRL_CPU0_CSR
253         movne   r1, r10, lsl #3
254         addne   r2, r1, #(FLOW_CTRL_CPU1_CSR-8)
255         addne   r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8)
256
257         /* Clear CPU "event" and "interrupt" flags and power gate
258            it when halting but not before it is in the "WFI" state. */
259         ldr     r0, [r6, +r2]
260         orr     r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
261         orr     r0, r0, #FLOW_CTRL_CSR_ENABLE
262         str     r0, [r6, +r2]
263
264         /* Unconditionally halt this CPU */
265         mov     r0, #FLOW_CTRL_WAITEVENT
266         str     r0, [r6, +r1]
267         ldr     r0, [r6, +r1]                   @ memory barrier
268
269         dsb
270         isb
271         wfi                                     @ CPU should be power gated here
272
273         /* If the CPU didn't power gate above just kill it's clock. */
274
275         mov     r0, r11, lsl #8
276         str     r0, [r7, #348]                  @ CLK_CPU_CMPLX_SET
277 #endif
278         /* If the CPU still isn't dead, just spin here. */
279         b       .
280
281 ENDPROC(__tegra_cpu_reset_handler)
282         .align L1_CACHE_SHIFT
283         .type   __tegra_cpu_reset_handler_data, %object
284         .globl  __tegra_cpu_reset_handler_data
285 __tegra_cpu_reset_handler_data:
286         .rept   TEGRA_RESET_DATA_SIZE
287         .long   0
288         .endr
289         .size   __tegra_cpu_reset_handler_data, .-tegra_cpu_reset_handler_data
290         .align L1_CACHE_SHIFT
291 ENTRY(__tegra_cpu_reset_handler_end)