Commit | Line | Data |
---|---|---|
69c31b7a SG |
1 | /* |
2 | * Copyright 2011 Freescale Semiconductor, Inc. | |
3 | * Copyright 2011 Linaro Ltd. | |
4 | * | |
5 | * The code contained herein is licensed under the GNU General Public | |
6 | * License. You may obtain a copy of the GNU General Public License | |
7 | * Version 2 or later at the following locations: | |
8 | * | |
9 | * http://www.opensource.org/licenses/gpl-license.html | |
10 | * http://www.gnu.org/copyleft/gpl.html | |
11 | */ | |
12 | ||
13 | #include <linux/linkage.h> | |
14 | #include <linux/init.h> | |
a1f1c7ef | 15 | #include <asm/asm-offsets.h> |
69c31b7a SG |
16 | #include <asm/hardware/cache-l2x0.h> |
17 | ||
18 | .section ".text.head", "ax" | |
69c31b7a SG |
19 | |
20 | /* | |
21 | * The secondary kernel init calls v7_flush_dcache_all before it enables | |
22 | * the L1; however, the L1 comes out of reset in an undefined state, so | |
23 | * the clean + invalidate performed by v7_flush_dcache_all causes a bunch | |
24 | * of cache lines with uninitialized data and uninitialized tags to get | |
25 | * written out to memory, which does really unpleasant things to the main | |
26 | * processor. We fix this by performing an invalidate, rather than a | |
27 | * clean + invalidate, before jumping into the kernel. | |
28 | * | |
29 | * This funciton is cloned from arch/arm/mach-tegra/headsmp.S, and needs | |
30 | * to be called for both secondary cores startup and primary core resume | |
31 | * procedures. Ideally, it should be moved into arch/arm/mm/cache-v7.S. | |
32 | */ | |
33 | ENTRY(v7_invalidate_l1) | |
34 | mov r0, #0 | |
5b2acf38 | 35 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache |
69c31b7a SG |
36 | mcr p15, 2, r0, c0, c0, 0 |
37 | mrc p15, 1, r0, c0, c0, 0 | |
38 | ||
39 | ldr r1, =0x7fff | |
40 | and r2, r1, r0, lsr #13 | |
41 | ||
42 | ldr r1, =0x3ff | |
43 | ||
44 | and r3, r1, r0, lsr #3 @ NumWays - 1 | |
45 | add r2, r2, #1 @ NumSets | |
46 | ||
47 | and r0, r0, #0x7 | |
48 | add r0, r0, #4 @ SetShift | |
49 | ||
50 | clz r1, r3 @ WayShift | |
51 | add r4, r3, #1 @ NumWays | |
52 | 1: sub r2, r2, #1 @ NumSets-- | |
53 | mov r3, r4 @ Temp = NumWays | |
54 | 2: subs r3, r3, #1 @ Temp-- | |
55 | mov r5, r3, lsl r1 | |
56 | mov r6, r2, lsl r0 | |
57 | orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift) | |
58 | mcr p15, 0, r5, c7, c6, 2 | |
59 | bgt 2b | |
60 | cmp r2, #0 | |
61 | bgt 1b | |
62 | dsb | |
63 | isb | |
64 | mov pc, lr | |
65 | ENDPROC(v7_invalidate_l1) | |
66 | ||
67 | #ifdef CONFIG_SMP | |
68 | ENTRY(v7_secondary_startup) | |
69 | bl v7_invalidate_l1 | |
70 | b secondary_startup | |
71 | ENDPROC(v7_secondary_startup) | |
72 | #endif | |
a1f1c7ef | 73 | |
46ec1b26 | 74 | #ifdef CONFIG_PM |
a1f1c7ef SG |
75 | /* |
76 | * The following code is located into the .data section. This is to | |
77 | * allow phys_l2x0_saved_regs to be accessed with a relative load | |
78 | * as we are running on physical address here. | |
79 | */ | |
80 | .data | |
81 | .align | |
82 | ||
733d1724 | 83 | #ifdef CONFIG_CACHE_L2X0 |
a1f1c7ef SG |
84 | .macro pl310_resume |
85 | ldr r2, phys_l2x0_saved_regs | |
86 | ldr r0, [r2, #L2X0_R_PHY_BASE] @ get physical base of l2x0 | |
87 | ldr r1, [r2, #L2X0_R_AUX_CTRL] @ get aux_ctrl value | |
88 | str r1, [r0, #L2X0_AUX_CTRL] @ restore aux_ctrl | |
89 | mov r1, #0x1 | |
90 | str r1, [r0, #L2X0_CTRL] @ re-enable L2 | |
91 | .endm | |
92 | ||
733d1724 EM |
93 | .globl phys_l2x0_saved_regs |
94 | phys_l2x0_saved_regs: | |
95 | .long 0 | |
96 | #else | |
97 | .macro pl310_resume | |
98 | .endm | |
99 | #endif | |
100 | ||
a1f1c7ef SG |
101 | ENTRY(v7_cpu_resume) |
102 | bl v7_invalidate_l1 | |
103 | pl310_resume | |
104 | b cpu_resume | |
105 | ENDPROC(v7_cpu_resume) | |
46ec1b26 | 106 | #endif |