aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/headsmp.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/headsmp.S')
-rw-r--r--arch/arm/mach-tegra/headsmp.S61
1 files changed, 61 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
new file mode 100644
index 000000000000..b5349b2f13d2
--- /dev/null
+++ b/arch/arm/mach-tegra/headsmp.S
@@ -0,0 +1,61 @@
1#include <linux/linkage.h>
2#include <linux/init.h>
3
4 .section ".text.head", "ax"
5 __CPUINIT
6
7/*
8 * Tegra specific entry point for secondary CPUs.
9 * The secondary kernel init calls v7_flush_dcache_all before it enables
10 * the L1; however, the L1 comes out of reset in an undefined state, so
11 * the clean + invalidate performed by v7_flush_dcache_all causes a bunch
12 * of cache lines with uninitialized data and uninitialized tags to get
13 * written out to memory, which does really unpleasant things to the main
14 * processor. We fix this by performing an invalidate, rather than a
15 * clean + invalidate, before jumping into the kernel.
16 */
17ENTRY(v7_invalidate_l1)
18 mov r0, #0
19 mcr p15, 2, r0, c0, c0, 0
20 mrc p15, 1, r0, c0, c0, 0
21
22 ldr r1, =0x7fff
23 and r2, r1, r0, lsr #13
24
25 ldr r1, =0x3ff
26
27 and r3, r1, r0, lsr #3 @ NumWays - 1
28 add r2, r2, #1 @ NumSets
29
30 and r0, r0, #0x7
31 add r0, r0, #4 @ SetShift
32
33 clz r1, r3 @ WayShift
34 add r4, r3, #1 @ NumWays
351: sub r2, r2, #1 @ NumSets--
36 mov r3, r4 @ Temp = NumWays
372: subs r3, r3, #1 @ Temp--
38 mov r5, r3, lsl r1
39 mov r6, r2, lsl r0
40 orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
41 mcr p15, 0, r5, c7, c6, 2
42 bgt 2b
43 cmp r2, #0
44 bgt 1b
45 dsb
46 isb
47 mov pc, lr
48ENDPROC(v7_invalidate_l1)
49
50ENTRY(tegra_secondary_startup)
51 msr cpsr_fsxc, #0xd3
52 bl v7_invalidate_l1
53 mrc p15, 0, r0, c0, c0, 5
54 and r0, r0, #15
55 ldr r1, =0x6000f100
56 str r0, [r1]
571: ldr r2, [r1]
58 cmp r0, r2
59 beq 1b
60 b secondary_startup
61ENDPROC(tegra_secondary_startup)