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