ARM: Tegra: Add CONFIG_TEGRA_USE_SECURE_KERNEL
[linux-3.10.git] / arch / arm / mach-tegra / headsmp.S
index e63ff0a..06091dd 100644 (file)
@@ -3,7 +3,7 @@
  *
  * CPU initialization routines for Tegra SoCs
  *
- * Copyright (c) 2009-2012, NVIDIA Corporation.
+ * Copyright (c) 2009-2013, NVIDIA CORPORATION.  All rights reserved.
  * Copyright (c) 2011 Google, Inc.
  * Author: Colin Cross <ccross@android.com>
  *         Gary King <gking@nvidia.com>
@@ -24,6 +24,7 @@
 #include <asm/assembler.h>
 #include <asm/cache.h>
 #include <asm/page.h>
+#include <asm/hardware/cache-l2x0.h>
 
 #include "flowctrl.h"
 #include "iomap.h"
@@ -35,7 +36,8 @@
 
 #define DEBUG_CPU_RESET_HANDLER        0       /* Non-zero enables debug code */
 
-#define RESET_DATA(x)  ((TEGRA_RESET_##x)*4)
+#define RESET_DATA_PHYS (TEGRA_RESET_HANDLER_BASE \
+       + __tegra_cpu_reset_handler_data - __tegra_cpu_reset_handler_start)
 
 #ifdef CONFIG_SMP
 /*
        __CPUINIT
 ENTRY(tegra_secondary_startup)
        bl      __invalidate_cpu_state
+
+       /* enable user space perf counter access */
+       /* only accessible in secure state       */
+       mrc     p15, 0, r0, c9, c12, 0
+       lsr     r0, #11
+       and     r0, r0, #0x1f
+       mov     r1, #1
+       lsl     r1, r1, r0
+       sub     r1, r1, #1
+       movt    r1, #0x8000
+       mcr     p15, 0, r1, c9, c14, 2
+       mov     r0, #1
+       mcr     p15, 0, r0, c9, c14, 0
+
        b       secondary_startup
 ENDPROC(tegra_secondary_startup)
 #endif
@@ -62,6 +78,13 @@ ENDPROC(tegra_secondary_startup)
  *       re-enabling sdram.
  */
 ENTRY(tegra_resume)
+#ifdef CONFIG_TEGRA_USE_SECURE_KERNEL
+       mov32   r1, TEGRA_TMRUS_BASE
+       ldr     r0, [r1]
+       adr     r1, tegra_resume_entry_time
+       str     r0, [r1]
+#endif
+
        bl      __invalidate_cpu_state
 
        cpu_id  r0
@@ -79,37 +102,175 @@ ENTRY(tegra_resume)
        movw    r0, #0x3FFD     @ enable, enable_ext, cluster_switch, immed, & bitmaps
        bic     r1, r1, r0
        str     r1, [r2]
-#endif
+#endif /* !CONFIG_ARCH_TEGRA_2x_SOC */
 
 #if defined(CONFIG_HAVE_ARM_SCU)
        /* enable SCU */
        mov32   r0, TEGRA_ARM_PERIF_BASE
        ldr     r1, [r0]
        orr     r1, r1, #1
-       str     r1, [r0]
+#ifdef CONFIG_ARCH_TEGRA_14x_SOC
+       orr     r1, r1, #8
 #endif
+       str     r1, [r0]
+#endif /* CONFIG_HAVE_ARM_SCU */
 
-#ifdef CONFIG_TRUSTED_FOUNDATIONS
-       /* wake up (should have specified args?) */
+#ifdef CONFIG_TEGRA_USE_SECURE_KERNEL
+#ifndef CONFIG_ARCH_TEGRA_11x_SOC
+       mov32   r1, TEGRA_TMRUS_BASE
+       ldr     r0, [r1]
+       adr     r1, tegra_resume_smc_entry_time
+       str     r0, [r1]
+
+       /* wake up */
+       mov     r0, #0x00000003
        bl      tegra_generic_smc
-#endif
 
+       mov32   r1, TEGRA_TMRUS_BASE
+       ldr     r0, [r1]
+       adr     r1, tegra_resume_smc_exit_time
+       str     r0, [r1]
+#endif /* !CONFIG_ARCH_TEGRA_11x_SOC */
+#endif /* CONFIG_TEGRA_USE_SECURE_KERNEL */
+
+#ifdef CONFIG_CACHE_L2X0
+#if !defined(CONFIG_TEGRA_USE_SECURE_KERNEL) && \
+               !defined(CONFIG_ARCH_TEGRA_14x_SOC)
+       adr     r0, tegra_resume_l2_init
+       ldr     r1, [r0]
+       tst     r1, #1
+       beq     no_l2_init
+       /* Enable L2 */
+       bic     r1, #1
+       str     r1, [r0]
+       mov32   r3, TEGRA_ARM_PL310_BASE
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+       mov32   r0, 0x331                       /* tag latency */
+       mov32   r1, 0x441                       /* data latency */
+#elif defined(CONFIG_ARCH_TEGRA_3x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
+#ifdef CONFIG_TEGRA_SILICON_PLATFORM
+       mov32   r0, TEGRA_FLOW_CTRL_BASE + 0x2c /* FLOW_CTRL_CLUSTER_CONTROL */
+       mov32   r2, RESET_DATA_PHYS
+       ldr     r1, [r0]
+       tst     r1, #1                          /* 0 == G, 1 == LP */
+       ldrne   r0, [r2, #RESET_DATA(C1_L2_TAG_LATENCY)]
+       ldrne   r1, [r2, #RESET_DATA(C1_L2_DATA_LATENCY)]
+       ldreq   r0, [r2, #RESET_DATA(C0_L2_TAG_LATENCY)]
+       ldreq   r1, [r2, #RESET_DATA(C0_L2_DATA_LATENCY)]
+#else /* !CONFIG_TEGRA_SILICON_PLATFORM */
+       mov32   r0, #0x770                      /* tag latency */
+       mov32   r1, #0x770                      /* data latency */
+#endif /* ?CONFIG_TEGRA_SILICON_PLATFORM */
+#endif /* CONFIG_ARCH_TEGRA_3x_SOC || CONFIG_ARCH_TEGRA_14x_SOC */
+       str     r0, [r3, #L2X0_TAG_LATENCY_CTRL]
+       str     r1, [r3, #L2X0_DATA_LATENCY_CTRL]
+#ifndef CONFIG_TEGRA_FPGA_PLATFORM
+#ifdef CONFIG_ARCH_TEGRA_14x_SOC
+       mov32   r0, 0x40000007  /* Enable double line fill */
+#else
+       mov     r0, #7
+#endif
+       str     r0, [r3, #L2X0_PREFETCH_CTRL]
+#endif /* !CONFIG_TEGRA_FPGA_PLATFORM */
+       mov     r0, #3
+       str     r0, [r3, #L2X0_POWER_CTRL]
+       /* figure out aux ctrl */
+       ldr     r2, [r3, #L2X0_CACHE_TYPE]
+       and     r2, r2, #0x700
+       lsl     r2, r2, #(17-8)
+       mov32   r4, 0x7C400001
+       orr     r2, r2, r4
+       ldr     r4, [r3, #L2X0_AUX_CTRL]
+       mov32   r5, 0x8200c3fe
+       and     r4, r4, r5
+       orr     r2, r2, r4
+       str     r2, [r3, #L2X0_AUX_CTRL]
+       mov     r2, #1
+       str     r2, [r3, #L2X0_CTRL]
+#endif /* ?CONFIG_TEGRA_USE_SECURE_KERNEL */
+#endif /* CONFIG_CACHE_L2X0 */
+no_l2_init:
        b       cpu_resume
 ENDPROC(tegra_resume)
-#endif
+
+#ifdef CONFIG_TEGRA_USE_SECURE_KERNEL
+       .globl tegra_resume_timestamps_start
+#ifndef CONFIG_ARCH_TEGRA_11x_SOC
+       .globl tegra_resume_smc_entry_time
+       .globl tegra_resume_smc_exit_time
+#endif /* !CONFIG_ARCH_TEGRA_11x_SOC */
+       .globl tegra_resume_entry_time
+       .globl tegra_resume_timestamps_end
+tegra_resume_timestamps_start:
+#ifndef CONFIG_ARCH_TEGRA_11x_SOC
+tegra_resume_smc_entry_time:
+       .long   0
+tegra_resume_smc_exit_time:
+       .long   0
+#endif /* !CONFIG_ARCH_TEGRA_11x_SOC */
+tegra_resume_entry_time:
+       .long   0
+tegra_resume_timestamps_end:
+#endif /* CONFIG_TEGRA_USE_SECURE_KERNEL */
+#ifdef CONFIG_CACHE_L2X0
+       .globl tegra_resume_l2_init
+tegra_resume_l2_init:
+       .long 0
+#endif /* CONFIG_CACHE_L2X0 */
+#endif /* CONFIG_PM_SLEEP */
 
 /*
  *     __invalidate_cpu_state
  *
  *       Invalidates volatile CPU state (SCU tags, caches, branch address
- *       arrays, exclusive monitor, etc.) so that they can be safely enabled
- *       instruction caching and branch predicition enabled
+ *       arrays, exclusive monitor, etc.) so that they can be safely
+ *       enabled. Instruction caching and branch prediction are enabled.
+ *
+ *       Cortex-A15 has an integrated SCU in L2 memory system, we only
+ *       need to set the correct L2 cache data RAM latency and enable
+ *       i-cache/branch prediction.
  */
 __invalidate_cpu_state:
        clrex
        mov     r0, #0
        mcr     p15, 0, r0, c1, c0, 1   @ disable SMP, prefetch, broadcast
        isb
+       mrc     p15, 0, r0, c0, c0, 0   @ main ID register
+       ubfx    r1, r0, #4, #28
+       ldr     r0, =0x00f0000
+       bic     r1, r1, r0
+       ldr     r0, =0x410fc09
+       teq     r1, r0
+       beq     cortex_a9
+
+       mrc     p15, 0x1, r0, c15, c0, 3        @ L2 prefetch control reg
+       tst     r0, #0x1000
+       orreq   r0, r0, #0x1000                 @ disable throttling
+       mcreq   p15, 0x1, r0, c15, c0, 3
+
+       /*      This is only needed for cluster 0 with integrated L2 cache */
+       mrc     p15, 0, r0, c0, c0, 5
+       ubfx    r0, r0, #8, #4
+       tst     r0, #1
+       bne     __enable_i_cache_branch_pred
+       mrc     p15, 0x1, r0, c9, c0, 2
+       and     r1, r0, #7
+       cmp     r1, #2
+       beq     __enable_i_cache_branch_pred
+       bic     r0, r0, #7
+       orr     r0, r0, #2
+       mcr     p15, 0x1, r0, c9, c0, 2
+       mrc     p15, 0x1, r0, c15, c0, 0        @ L2 ACTLR
+       orr     r0, r0, #0x80                   @ hazard detection timeout
+       mcr     p15, 0x1, r0, c15, c0, 0
+__enable_i_cache_branch_pred:
+       mov     r0, #0x1800
+       mcr     p15, 0, r0, c1, c0, 0   @ enable branch prediction, i-cache
+       mov     pc, lr
+       /* no fall through, just return to the caller */
+
+cortex_a9:
+       /* Following is for Cortex-A9 */
        mcr     p15, 0, r0, c7, c5, 0   @ invalidate BTAC, i-cache
        mcr     p15, 0, r0, c7, c5, 6   @ invalidate branch pred array
        mcr     p15, 0, r0, c8, c5, 0   @ invalidate instruction TLB
@@ -126,52 +287,16 @@ __invalidate_cpu_state:
        movne   r2, #0xf
        movne   r2, r2, lsl r0
        strne   r2, [r1]                @ invalidate SCU tags for CPU
-#else
-       /*      This is only needed for cluster 0 with integrated L2 cache */
-       mov32   r0, TEGRA_FLOW_CTRL_BASE+0x2c   @ CLUSTER_CONTROL
-       ldr     r0, [r0]
-       tst     r0, #1
-       bne     enable_icache_bp
-       mrc     p15, 0x1, r0, c9, c0, 2
-       and     r1, r0, #7
-       cmp     r1, #2
-       beq     enable_icache_bp
-       bic r0, r0, #7
-       orr r0, r0, #2
-       mcr p15, 0x1, r0, c9, c0, 2
-
 #endif
 
-enable_icache_bp:
        dsb
        mov     r0, #0x1800
        mcr     p15, 0, r0, c1, c0, 0   @ enable branch prediction, i-cache
        isb
-       /* fall through */
 
-/*
- *     tegra_invalidate_cache
- *
- *       Invalidates the L1 or L2 data cache (no clean) during initial boot of
- *       a cpu. For architecture with external L2, invalidate L1 only. For
- *       architecture with integrated L2 and SCU, invalidate L2 if current CPU
- *       boots up with a power gated NC partition initially or power rail was
- *       initially off, invalidates L1 in other cases
- *
- *       Corrupted registers: r0-r6
- */
-tegra_invalidate_cache:
-#if defined(CONFIG_HAVE_ARM_SCU)
+       /* Invalidates L1 d-cache during initial cpu boot (corrupt r0-r6) */
+
        mov     r0, #0
-#else
-       cpu_id  r0
-       cpu_to_csr_reg  r1, r0
-       mov32   r0, TEGRA_FLOW_CTRL_BASE
-       ldr     r0, [r0, r1]
-       tst     r0, #FLOW_CTRL_CSR_ENABLE_EXT_MASK
-       movne   r0, #2
-       moveq   r0, #0
-#endif
        mcr     p15, 2, r0, c0, c0, 0
        mrc     p15, 1, r0, c0, c0, 0
 
@@ -198,10 +323,6 @@ tegra_invalidate_cache:
        bgt     2b
        cmp     r2, #0
        bgt     1b
-#if !defined(CONFIG_HAVE_ARM_SCU)
-       mov     r0, #0
-       mcr     p15, 2, r0, c0, c0, 0
-#endif
        dsb
        isb
        mov     pc, lr
@@ -251,7 +372,7 @@ ENTRY(__tegra_cpu_reset_handler)
 #if DEBUG_CPU_RESET_HANDLER
        b       .
 #endif
-#ifndef CONFIG_TRUSTED_FOUNDATIONS
+#ifndef CONFIG_TEGRA_USE_SECURE_KERNEL
        cpsid   aif, 0x13                       @ SVC mode, interrupts disabled
        mrc     p15, 0, r0, c0, c0, 0           @ read main ID register
        and     r5, r0, #0x00f00000             @ variant
@@ -395,6 +516,11 @@ __tegra_cpu_reset_handler_data:
        .rept   TEGRA_RESET_DATA_SIZE
        .long   0
        .endr
-       .size   __tegra_cpu_reset_handler_data, . - __tegra_cpu_reset_handler_data
+       .size   __tegra_cpu_reset_handler_data, \
+       . - __tegra_cpu_reset_handler_data
        .align L1_CACHE_SHIFT
 ENTRY(__tegra_cpu_reset_handler_end)
+
+       .globl  __tegra_cpu_reset_handler_data_offset
+       .equ    __tegra_cpu_reset_handler_data_offset, \
+       __tegra_cpu_reset_handler_data - __tegra_cpu_reset_handler_start