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