~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-tegra/reset-handler.S

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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)

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php