root/arch/arm/mach-tegra/reset-handler.S

/* [<][>][^][v][top][bottom][index][help] */
   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)

/* [<][>][^][v][top][bottom][index][help] */