Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
0004  */
0005 
0006 #include <linux/init.h>
0007 #include <linux/linkage.h>
0008 
0009 #include <soc/tegra/flowctrl.h>
0010 #include <soc/tegra/fuse.h>
0011 
0012 #include <asm/assembler.h>
0013 #include <asm/asm-offsets.h>
0014 #include <asm/cache.h>
0015 
0016 #include "iomap.h"
0017 #include "reset.h"
0018 #include "sleep.h"
0019 
0020 #define PMC_SCRATCH41   0x140
0021 
0022 #ifdef CONFIG_PM_SLEEP
0023 /*
0024  *  tegra_resume
0025  *
0026  *    CPU boot vector when restarting the a CPU following
0027  *    an LP2 transition. Also branched to by LP0 and LP1 resume after
0028  *    re-enabling sdram.
0029  *
0030  *  r6: SoC ID
0031  *  r8: CPU part number
0032  */
0033 ENTRY(tegra_resume)
0034     check_cpu_part_num 0xc09, r8, r9
0035     bleq    v7_invalidate_l1
0036 
0037     cpu_id  r0
0038     cmp r0, #0              @ CPU0?
0039  THUMB( it  ne )
0040     bne cpu_resume          @ no
0041 
0042     tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
0043     /* Are we on Tegra20? */
0044     cmp r6, #TEGRA20
0045     beq 1f              @ Yes
0046     /* Clear the flow controller flags for this CPU. */
0047     cpu_to_csr_reg r3, r0
0048     mov32   r2, TEGRA_FLOW_CTRL_BASE
0049     ldr r1, [r2, r3]
0050     /* Clear event & intr flag */
0051     orr r1, r1, \
0052         #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
0053     movw    r0, #0x3FFD @ enable, cluster_switch, immed, bitmaps
0054                 @ & ext flags for CPU power mgnt
0055     bic r1, r1, r0
0056     str r1, [r2, r3]
0057 1:
0058 
0059     mov32   r9, 0xc09
0060     cmp r8, r9
0061     bne end_ca9_scu_l2_resume
0062 #ifdef CONFIG_HAVE_ARM_SCU
0063     /* enable SCU */
0064     mov32   r0, TEGRA_ARM_PERIF_BASE
0065     ldr r1, [r0]
0066     orr r1, r1, #1
0067     str r1, [r0]
0068 #endif
0069     bl  tegra_resume_trusted_foundations
0070 
0071 #ifdef CONFIG_CACHE_L2X0
0072     /* L2 cache resume & re-enable */
0073     bl  l2c310_early_resume
0074 #endif
0075 end_ca9_scu_l2_resume:
0076     mov32   r9, 0xc0f
0077     cmp r8, r9
0078     bleq    tegra_init_l2_for_a15
0079 
0080     b   cpu_resume
0081 ENDPROC(tegra_resume)
0082 
0083 /*
0084  *  tegra_resume_trusted_foundations
0085  *
0086  *    Trusted Foundations firmware initialization.
0087  *
0088  *  Doesn't return if firmware presents.
0089  *  Corrupted registers: r1, r2
0090  */
0091 ENTRY(tegra_resume_trusted_foundations)
0092     /* Check whether Trusted Foundations firmware presents. */
0093     mov32   r2, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET
0094     ldr r1, =__tegra_cpu_reset_handler_data_offset + \
0095                             RESET_DATA(TF_PRESENT)
0096     ldr r1, [r2, r1]
0097     cmp r1, #0
0098     reteq   lr
0099 
0100  .arch_extension sec
0101     /*
0102      * First call after suspend wakes firmware. No arguments required
0103      * for some firmware versions. Downstream kernel of ASUS TF300T uses
0104      * r0=3 for the wake-up notification.
0105      */
0106     mov r0, #3
0107     smc #0
0108 
0109     b   cpu_resume
0110 ENDPROC(tegra_resume_trusted_foundations)
0111 #endif
0112 
0113     .align L1_CACHE_SHIFT
0114 ENTRY(__tegra_cpu_reset_handler_start)
0115 
0116 /*
0117  * __tegra_cpu_reset_handler:
0118  *
0119  * Common handler for all CPU reset events.
0120  *
0121  * Register usage within the reset handler:
0122  *
0123  *      Others: scratch
0124  *      R6  = SoC ID
0125  *      R7  = CPU present (to the OS) mask
0126  *      R8  = CPU in LP1 state mask
0127  *      R9  = CPU in LP2 state mask
0128  *      R10 = CPU number
0129  *      R11 = CPU mask
0130  *      R12 = pointer to reset handler data
0131  *
0132  * NOTE: This code is copied to IRAM. All code and data accesses
0133  *       must be position-independent.
0134  */
0135 
0136     .arm
0137     .align L1_CACHE_SHIFT
0138 ENTRY(__tegra_cpu_reset_handler)
0139 
0140     cpsid   aif, 0x13           @ SVC mode, interrupts disabled
0141 
0142     tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
0143 
0144     adr r12, __tegra_cpu_reset_handler_data
0145     ldr r5, [r12, #RESET_DATA(TF_PRESENT)]
0146     cmp r5, #0
0147     bne after_errata
0148 
0149 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
0150 t20_check:
0151     cmp r6, #TEGRA20
0152     bne after_t20_check
0153 t20_errata:
0154     # Tegra20 is a Cortex-A9 r1p1
0155     mrc p15, 0, r0, c1, c0, 0   @ read system control register
0156     orr r0, r0, #1 << 14        @ erratum 716044
0157     mcr p15, 0, r0, c1, c0, 0   @ write system control register
0158     mrc p15, 0, r0, c15, c0, 1  @ read diagnostic register
0159     orr r0, r0, #1 << 4         @ erratum 742230
0160     orr r0, r0, #1 << 11        @ erratum 751472
0161     mcr p15, 0, r0, c15, c0, 1  @ write diagnostic register
0162     b   after_errata
0163 after_t20_check:
0164 #endif
0165 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
0166 t30_check:
0167     cmp r6, #TEGRA30
0168     bne after_t30_check
0169 t30_errata:
0170     # Tegra30 is a Cortex-A9 r2p9
0171     mrc p15, 0, r0, c15, c0, 1  @ read diagnostic register
0172     orr r0, r0, #1 << 6         @ erratum 743622
0173     orr r0, r0, #1 << 11        @ erratum 751472
0174     mcr p15, 0, r0, c15, c0, 1  @ write diagnostic register
0175     b   after_errata
0176 after_t30_check:
0177 #endif
0178 after_errata:
0179     mrc p15, 0, r10, c0, c0, 5      @ MPIDR
0180     and r10, r10, #0x3          @ R10 = CPU number
0181     mov r11, #1
0182     mov r11, r11, lsl r10       @ R11 = CPU mask
0183 
0184 #ifdef CONFIG_SMP
0185     /* Does the OS know about this CPU? */
0186     ldr r7, [r12, #RESET_DATA(MASK_PRESENT)]
0187     tst r7, r11             @ if !present
0188     bleq    __die               @ CPU not present (to OS)
0189 #endif
0190 
0191     /* Waking up from LP1? */
0192     ldr r8, [r12, #RESET_DATA(MASK_LP1)]
0193     tst r8, r11             @ if in_lp1
0194     beq __is_not_lp1
0195     cmp r10, #0
0196     bne __die               @ only CPU0 can be here
0197     ldr lr, [r12, #RESET_DATA(STARTUP_LP1)]
0198     cmp lr, #0
0199     bleq    __die               @ no LP1 startup handler
0200  THUMB( add lr, lr, #1 )            @ switch to Thumb mode
0201     bx  lr
0202 __is_not_lp1:
0203 
0204     /* Waking up from LP2? */
0205     ldr r9, [r12, #RESET_DATA(MASK_LP2)]
0206     tst r9, r11             @ if in_lp2
0207     beq __is_not_lp2
0208     ldr lr, [r12, #RESET_DATA(STARTUP_LP2)]
0209     cmp lr, #0
0210     bleq    __die               @ no LP2 startup handler
0211     bx  lr
0212 
0213 __is_not_lp2:
0214 
0215 #ifdef CONFIG_SMP
0216     /*
0217      * Can only be secondary boot (initial or hotplug)
0218      * CPU0 can't be here for Tegra20/30
0219      */
0220     cmp r6, #TEGRA114
0221     beq __no_cpu0_chk
0222     cmp r10, #0
0223     bleq    __die               @ CPU0 cannot be here
0224 __no_cpu0_chk:
0225     ldr lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
0226     cmp lr, #0
0227     bleq    __die               @ no secondary startup handler
0228     bx  lr
0229 #endif
0230 
0231 /*
0232  * We don't know why the CPU reset. Just kill it.
0233  * The LR register will contain the address we died at + 4.
0234  */
0235 
0236 __die:
0237     sub lr, lr, #4
0238     mov32   r7, TEGRA_PMC_BASE
0239     str lr, [r7, #PMC_SCRATCH41]
0240 
0241     mov32   r7, TEGRA_CLK_RESET_BASE
0242 
0243     /* Are we on Tegra20? */
0244     cmp r6, #TEGRA20
0245     bne 1f
0246 
0247 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
0248     mov32   r0, 0x1111
0249     mov r1, r0, lsl r10
0250     str r1, [r7, #0x340]        @ CLK_RST_CPU_CMPLX_SET
0251 #endif
0252 1:
0253 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
0254     mov32   r6, TEGRA_FLOW_CTRL_BASE
0255 
0256     cmp r10, #0
0257     moveq   r1, #FLOW_CTRL_HALT_CPU0_EVENTS
0258     moveq   r2, #FLOW_CTRL_CPU0_CSR
0259     movne   r1, r10, lsl #3
0260     addne   r2, r1, #(FLOW_CTRL_CPU1_CSR-8)
0261     addne   r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8)
0262 
0263     /* Clear CPU "event" and "interrupt" flags and power gate
0264        it when halting but not before it is in the "WFI" state. */
0265     ldr r0, [r6, +r2]
0266     orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
0267     orr r0, r0, #FLOW_CTRL_CSR_ENABLE
0268     str r0, [r6, +r2]
0269 
0270     /* Unconditionally halt this CPU */
0271     mov r0, #FLOW_CTRL_WAITEVENT
0272     str r0, [r6, +r1]
0273     ldr r0, [r6, +r1]           @ memory barrier
0274 
0275     dsb
0276     isb
0277     wfi                 @ CPU should be power gated here
0278 
0279     /* If the CPU didn't power gate above just kill it's clock. */
0280 
0281     mov r0, r11, lsl #8
0282     str r0, [r7, #348]          @ CLK_CPU_CMPLX_SET
0283 #endif
0284 
0285     /* If the CPU still isn't dead, just spin here. */
0286     b   .
0287 ENDPROC(__tegra_cpu_reset_handler)
0288 
0289     .align L1_CACHE_SHIFT
0290     .type   __tegra_cpu_reset_handler_data, %object
0291     .globl  __tegra_cpu_reset_handler_data
0292     .globl  __tegra_cpu_reset_handler_data_offset
0293     .equ    __tegra_cpu_reset_handler_data_offset, \
0294                     . - __tegra_cpu_reset_handler_start
0295 __tegra_cpu_reset_handler_data:
0296     .rept   TEGRA_RESET_DATA_SIZE
0297     .long   0
0298     .endr
0299     .align L1_CACHE_SHIFT
0300 
0301 ENTRY(__tegra_cpu_reset_handler_end)