aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2013-03-04 19:05:56 -0500
committerStephen Warren <swarren@nvidia.com>2013-03-11 16:29:22 -0400
commitc34f30e588d310a70f994659c06f0a31dfdcfc15 (patch)
treeb04ec4f4afc54301907d7df60839b5f155138720
parent908ab9368866e6edf0edebdd546adefd5f3128f9 (diff)
ARM: tegra: add CPU errata WARs to Tegra reset handler
The CPU cores in Tegra contain some errata. Workarounds must be applied for these every time a CPU boots. Implement those workarounds directly in the Tegra-specific CPU reset vector. Many of these workarounds duplicate code in the core ARM kernel. However, the core ARM kernel cannot enable those workarounds when building a multi-platform kernel, since they require writing to secure- only registers, and a multi-platform kernel often does not run in secure mode, and also cannot generically/architecturally detect whether it is running in secure mode, and hence cannot either unconditionally or conditionally apply these workarounds. Instead, the workarounds must be applied in architecture-specific reset code, which is able to have more direct knowledge of the secure/normal state. On Tegra, we will be able to detect this using a non-architected register in the future, although we currently assume the kernel runs only in secure mode. Other SoCs may never run the kernel in secure mode, and hence always rely on a secure monitor to enable the workarounds, and hence never implement them in the kernel. Signed-off-by: Stephen Warren <swarren@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/reset-handler.S45
1 files changed, 39 insertions, 6 deletions
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index 54382ceade4a..ff7b45c6c2a0 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -99,6 +99,8 @@ ENTRY(__tegra_cpu_reset_handler_start)
99 * 99 *
100 * Register usage within the reset handler: 100 * Register usage within the reset handler:
101 * 101 *
102 * Others: scratch
103 * R6 = SoC ID << 8
102 * R7 = CPU present (to the OS) mask 104 * R7 = CPU present (to the OS) mask
103 * R8 = CPU in LP1 state mask 105 * R8 = CPU in LP1 state mask
104 * R9 = CPU in LP2 state mask 106 * R9 = CPU in LP2 state mask
@@ -114,6 +116,40 @@ ENTRY(__tegra_cpu_reset_handler_start)
114ENTRY(__tegra_cpu_reset_handler) 116ENTRY(__tegra_cpu_reset_handler)
115 117
116 cpsid aif, 0x13 @ SVC mode, interrupts disabled 118 cpsid aif, 0x13 @ SVC mode, interrupts disabled
119
120 mov32 r6, TEGRA_APB_MISC_BASE
121 ldr r6, [r6, #APB_MISC_GP_HIDREV]
122 and r6, r6, #0xff00
123#ifdef CONFIG_ARCH_TEGRA_2x_SOC
124t20_check:
125 cmp r6, #(0x20 << 8)
126 bne after_t20_check
127t20_errata:
128 # Tegra20 is a Cortex-A9 r1p1
129 mrc p15, 0, r0, c1, c0, 0 @ read system control register
130 orr r0, r0, #1 << 14 @ erratum 716044
131 mcr p15, 0, r0, c1, c0, 0 @ write system control register
132 mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register
133 orr r0, r0, #1 << 4 @ erratum 742230
134 orr r0, r0, #1 << 11 @ erratum 751472
135 mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register
136 b after_errata
137after_t20_check:
138#endif
139#ifdef CONFIG_ARCH_TEGRA_3x_SOC
140t30_check:
141 cmp r6, #(0x30 << 8)
142 bne after_t30_check
143t30_errata:
144 # Tegra30 is a Cortex-A9 r2p9
145 mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register
146 orr r0, r0, #1 << 6 @ erratum 743622
147 orr r0, r0, #1 << 11 @ erratum 751472
148 mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register
149 b after_errata
150after_t30_check:
151#endif
152after_errata:
117 mrc p15, 0, r10, c0, c0, 5 @ MPIDR 153 mrc p15, 0, r10, c0, c0, 5 @ MPIDR
118 and r10, r10, #0x3 @ R10 = CPU number 154 and r10, r10, #0x3 @ R10 = CPU number
119 mov r11, #1 155 mov r11, #1
@@ -129,16 +165,13 @@ ENTRY(__tegra_cpu_reset_handler)
129 165
130#ifdef CONFIG_ARCH_TEGRA_2x_SOC 166#ifdef CONFIG_ARCH_TEGRA_2x_SOC
131 /* Are we on Tegra20? */ 167 /* Are we on Tegra20? */
132 mov32 r6, TEGRA_APB_MISC_BASE 168 cmp r6, #(0x20 << 8)
133 ldr r0, [r6, #APB_MISC_GP_HIDREV]
134 and r0, r0, #0xff00
135 cmp r0, #(0x20 << 8)
136 bne 1f 169 bne 1f
137 /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */ 170 /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
138 mov32 r6, TEGRA_PMC_BASE 171 mov32 r5, TEGRA_PMC_BASE
139 mov r0, #0 172 mov r0, #0
140 cmp r10, #0 173 cmp r10, #0
141 strne r0, [r6, #PMC_SCRATCH41] 174 strne r0, [r5, #PMC_SCRATCH41]
1421: 1751:
143#endif 176#endif
144 177