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