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