]> git.karo-electronics.de Git - karo-tx-linux.git/blob - arch/arm/mach-tegra/reset-handler.S
Merge tag 'trace-3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux...
[karo-tx-linux.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 "fuse.h"
26 #include "iomap.h"
27 #include "reset.h"
28 #include "sleep.h"
29
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  *      r6: SoC ID
43  */
44 ENTRY(tegra_resume)
45         bl      v7_invalidate_l1
46
47         cpu_id  r0
48         tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
49         cmp     r6, #TEGRA114
50         beq     no_cpu0_chk
51
52         cmp     r0, #0                          @ CPU0?
53  THUMB( it      ne )
54         bne     cpu_resume                      @ no
55 no_cpu0_chk:
56
57         /* Are we on Tegra20? */
58         cmp     r6, #TEGRA20
59         beq     1f                              @ Yes
60         /* Clear the flow controller flags for this CPU. */
61         cpu_to_csr_reg r1, r0
62         mov32   r2, TEGRA_FLOW_CTRL_BASE
63         ldr     r1, [r2, r1]
64         /* Clear event & intr flag */
65         orr     r1, r1, \
66                 #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
67         movw    r0, #0x3FFD     @ enable, cluster_switch, immed, bitmaps
68                                 @ & ext flags for CPU power mgnt
69         bic     r1, r1, r0
70         str     r1, [r2]
71 1:
72
73         check_cpu_part_num 0xc09, r8, r9
74         bne     not_ca9
75 #ifdef CONFIG_HAVE_ARM_SCU
76         /* enable SCU */
77         mov32   r0, TEGRA_ARM_PERIF_BASE
78         ldr     r1, [r0]
79         orr     r1, r1, #1
80         str     r1, [r0]
81 #endif
82
83         /* L2 cache resume & re-enable */
84         l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr
85 not_ca9:
86
87         b       cpu_resume
88 ENDPROC(tegra_resume)
89 #endif
90
91 #ifdef CONFIG_CACHE_L2X0
92         .globl  l2x0_saved_regs_addr
93 l2x0_saved_regs_addr:
94         .long   0
95 #endif
96
97         .align L1_CACHE_SHIFT
98 ENTRY(__tegra_cpu_reset_handler_start)
99
100 /*
101  * __tegra_cpu_reset_handler:
102  *
103  * Common handler for all CPU reset events.
104  *
105  * Register usage within the reset handler:
106  *
107  *      Others: scratch
108  *      R6  = SoC ID
109  *      R7  = CPU present (to the OS) mask
110  *      R8  = CPU in LP1 state mask
111  *      R9  = CPU in LP2 state mask
112  *      R10 = CPU number
113  *      R11 = CPU mask
114  *      R12 = pointer to reset handler data
115  *
116  * NOTE: This code is copied to IRAM. All code and data accesses
117  *       must be position-independent.
118  */
119
120         .align L1_CACHE_SHIFT
121 ENTRY(__tegra_cpu_reset_handler)
122
123         cpsid   aif, 0x13                       @ SVC mode, interrupts disabled
124
125         tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
126 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
127 t20_check:
128         cmp     r6, #TEGRA20
129         bne     after_t20_check
130 t20_errata:
131         # Tegra20 is a Cortex-A9 r1p1
132         mrc     p15, 0, r0, c1, c0, 0   @ read system control register
133         orr     r0, r0, #1 << 14        @ erratum 716044
134         mcr     p15, 0, r0, c1, c0, 0   @ write system control register
135         mrc     p15, 0, r0, c15, c0, 1  @ read diagnostic register
136         orr     r0, r0, #1 << 4         @ erratum 742230
137         orr     r0, r0, #1 << 11        @ erratum 751472
138         mcr     p15, 0, r0, c15, c0, 1  @ write diagnostic register
139         b       after_errata
140 after_t20_check:
141 #endif
142 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
143 t30_check:
144         cmp     r6, #TEGRA30
145         bne     after_t30_check
146 t30_errata:
147         # Tegra30 is a Cortex-A9 r2p9
148         mrc     p15, 0, r0, c15, c0, 1  @ read diagnostic register
149         orr     r0, r0, #1 << 6         @ erratum 743622
150         orr     r0, r0, #1 << 11        @ erratum 751472
151         mcr     p15, 0, r0, c15, c0, 1  @ write diagnostic register
152         b       after_errata
153 after_t30_check:
154 #endif
155 after_errata:
156         mrc     p15, 0, r10, c0, c0, 5          @ MPIDR
157         and     r10, r10, #0x3                  @ R10 = CPU number
158         mov     r11, #1
159         mov     r11, r11, lsl r10               @ R11 = CPU mask
160         adr     r12, __tegra_cpu_reset_handler_data
161
162 #ifdef CONFIG_SMP
163         /* Does the OS know about this CPU? */
164         ldr     r7, [r12, #RESET_DATA(MASK_PRESENT)]
165         tst     r7, r11                         @ if !present
166         bleq    __die                           @ CPU not present (to OS)
167 #endif
168
169 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
170         /* Are we on Tegra20? */
171         cmp     r6, #TEGRA20
172         bne     1f
173         /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
174         mov32   r5, TEGRA_PMC_BASE
175         mov     r0, #0
176         cmp     r10, #0
177         strne   r0, [r5, #PMC_SCRATCH41]
178 1:
179 #endif
180
181         /* Waking up from LP2? */
182         ldr     r9, [r12, #RESET_DATA(MASK_LP2)]
183         tst     r9, r11                         @ if in_lp2
184         beq     __is_not_lp2
185         ldr     lr, [r12, #RESET_DATA(STARTUP_LP2)]
186         cmp     lr, #0
187         bleq    __die                           @ no LP2 startup handler
188         bx      lr
189
190 __is_not_lp2:
191
192 #ifdef CONFIG_SMP
193         /*
194          * Can only be secondary boot (initial or hotplug)
195          * CPU0 can't be here for Tegra20/30
196          */
197         cmp     r6, #TEGRA114
198         beq     __no_cpu0_chk
199         cmp     r10, #0
200         bleq    __die                           @ CPU0 cannot be here
201 __no_cpu0_chk:
202         ldr     lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
203         cmp     lr, #0
204         bleq    __die                           @ no secondary startup handler
205         bx      lr
206 #endif
207
208 /*
209  * We don't know why the CPU reset. Just kill it.
210  * The LR register will contain the address we died at + 4.
211  */
212
213 __die:
214         sub     lr, lr, #4
215         mov32   r7, TEGRA_PMC_BASE
216         str     lr, [r7, #PMC_SCRATCH41]
217
218         mov32   r7, TEGRA_CLK_RESET_BASE
219
220         /* Are we on Tegra20? */
221         cmp     r6, #TEGRA20
222         bne     1f
223
224 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
225         mov32   r0, 0x1111
226         mov     r1, r0, lsl r10
227         str     r1, [r7, #0x340]                @ CLK_RST_CPU_CMPLX_SET
228 #endif
229 1:
230 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
231         mov32   r6, TEGRA_FLOW_CTRL_BASE
232
233         cmp     r10, #0
234         moveq   r1, #FLOW_CTRL_HALT_CPU0_EVENTS
235         moveq   r2, #FLOW_CTRL_CPU0_CSR
236         movne   r1, r10, lsl #3
237         addne   r2, r1, #(FLOW_CTRL_CPU1_CSR-8)
238         addne   r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8)
239
240         /* Clear CPU "event" and "interrupt" flags and power gate
241            it when halting but not before it is in the "WFI" state. */
242         ldr     r0, [r6, +r2]
243         orr     r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
244         orr     r0, r0, #FLOW_CTRL_CSR_ENABLE
245         str     r0, [r6, +r2]
246
247         /* Unconditionally halt this CPU */
248         mov     r0, #FLOW_CTRL_WAITEVENT
249         str     r0, [r6, +r1]
250         ldr     r0, [r6, +r1]                   @ memory barrier
251
252         dsb
253         isb
254         wfi                                     @ CPU should be power gated here
255
256         /* If the CPU didn't power gate above just kill it's clock. */
257
258         mov     r0, r11, lsl #8
259         str     r0, [r7, #348]                  @ CLK_CPU_CMPLX_SET
260 #endif
261
262         /* If the CPU still isn't dead, just spin here. */
263         b       .
264 ENDPROC(__tegra_cpu_reset_handler)
265
266         .align L1_CACHE_SHIFT
267         .type   __tegra_cpu_reset_handler_data, %object
268         .globl  __tegra_cpu_reset_handler_data
269 __tegra_cpu_reset_handler_data:
270         .rept   TEGRA_RESET_DATA_SIZE
271         .long   0
272         .endr
273         .align L1_CACHE_SHIFT
274
275 ENTRY(__tegra_cpu_reset_handler_end)