aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2013-02-11 22:37:51 -0500
committerOlof Johansson <olof@lixom.net>2013-02-11 22:37:51 -0500
commit1c75c4210009d5cceced76af316c51f9e56ce630 (patch)
treecfa3600b25fe8ca385ddc6a2cd230da876312dcb
parent877cd953167bc50765719ca047a3ac2c4fdd7aaf (diff)
parentd6dd735f4bda19bfe07d96d9025c94c4619d4596 (diff)
Merge branch 'socfpga/hw' into next/soc
From Dinh Nguyen, this is a series of patches introducing support for socfpga hardware (Altera Cyclone5). It also includes a cleanup that moves some of the ARMv7 cache maintenance functions to a common location, since three other platforms aready implemented it separately. * socfpga/hw: arm: socfpga: Add SMP support for actual socfpga harware arm: Add v7_invalidate_l1 to cache-v7.S arm: socfpga: Add entries to enable make dtbs socfpga arm: socfpga: Add new device tree source for actual socfpga HW Trivial conflict in arch/arm/mach-tegra/headsmp.S. Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r--Documentation/devicetree/bindings/arm/altera/socfpga-system.txt2
-rw-r--r--arch/arm/boot/dts/Makefile2
-rw-r--r--arch/arm/boot/dts/socfpga.dtsi22
-rw-r--r--arch/arm/boot/dts/socfpga_cyclone5.dts34
-rw-r--r--arch/arm/boot/dts/socfpga_vt.dts64
-rw-r--r--arch/arm/mach-imx/headsmp.S47
-rw-r--r--arch/arm/mach-shmobile/headsmp.S48
-rw-r--r--arch/arm/mach-socfpga/core.h4
-rw-r--r--arch/arm/mach-socfpga/headsmp.S16
-rw-r--r--arch/arm/mach-socfpga/platsmp.c17
-rw-r--r--arch/arm/mach-socfpga/socfpga.c7
-rw-r--r--arch/arm/mach-tegra/headsmp.S43
-rw-r--r--arch/arm/mm/cache-v7.S46
13 files changed, 187 insertions, 165 deletions
diff --git a/Documentation/devicetree/bindings/arm/altera/socfpga-system.txt b/Documentation/devicetree/bindings/arm/altera/socfpga-system.txt
index 07c65e3cdcbe..f4d04a067282 100644
--- a/Documentation/devicetree/bindings/arm/altera/socfpga-system.txt
+++ b/Documentation/devicetree/bindings/arm/altera/socfpga-system.txt
@@ -3,9 +3,11 @@ Altera SOCFPGA System Manager
3Required properties: 3Required properties:
4- compatible : "altr,sys-mgr" 4- compatible : "altr,sys-mgr"
5- reg : Should contain 1 register ranges(address and length) 5- reg : Should contain 1 register ranges(address and length)
6- cpu1-start-addr : CPU1 start address in hex.
6 7
7Example: 8Example:
8 sysmgr@ffd08000 { 9 sysmgr@ffd08000 {
9 compatible = "altr,sys-mgr"; 10 compatible = "altr,sys-mgr";
10 reg = <0xffd08000 0x1000>; 11 reg = <0xffd08000 0x1000>;
12 cpu1-start-addr = <0xffd080c4>;
11 }; 13 };
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 2e7a7e2de11a..042f2111485b 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -125,6 +125,8 @@ dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \
125 r8a7740-armadillo800eva.dtb \ 125 r8a7740-armadillo800eva.dtb \
126 sh73a0-kzm9g.dtb \ 126 sh73a0-kzm9g.dtb \
127 sh7372-mackerel.dtb 127 sh7372-mackerel.dtb
128dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_cyclone5.dtb \
129 socfpga_vt.dtb
128dtb-$(CONFIG_ARCH_SPEAR13XX) += spear1310-evb.dtb \ 130dtb-$(CONFIG_ARCH_SPEAR13XX) += spear1310-evb.dtb \
129 spear1340-evb.dtb 131 spear1340-evb.dtb
130dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \ 132dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \
diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
index 19aec421bb26..936d2306e7e1 100644
--- a/arch/arm/boot/dts/socfpga.dtsi
+++ b/arch/arm/boot/dts/socfpga.dtsi
@@ -25,6 +25,10 @@
25 ethernet0 = &gmac0; 25 ethernet0 = &gmac0;
26 serial0 = &uart0; 26 serial0 = &uart0;
27 serial1 = &uart1; 27 serial1 = &uart1;
28 timer0 = &timer0;
29 timer1 = &timer1;
30 timer2 = &timer2;
31 timer3 = &timer3;
28 }; 32 };
29 33
30 cpus { 34 cpus {
@@ -98,47 +102,41 @@
98 interrupts = <1 13 0xf04>; 102 interrupts = <1 13 0xf04>;
99 }; 103 };
100 104
101 timer0: timer@ffc08000 { 105 timer0: timer0@ffc08000 {
102 compatible = "snps,dw-apb-timer-sp"; 106 compatible = "snps,dw-apb-timer-sp";
103 interrupts = <0 167 4>; 107 interrupts = <0 167 4>;
104 clock-frequency = <200000000>;
105 reg = <0xffc08000 0x1000>; 108 reg = <0xffc08000 0x1000>;
106 }; 109 };
107 110
108 timer1: timer@ffc09000 { 111 timer1: timer1@ffc09000 {
109 compatible = "snps,dw-apb-timer-sp"; 112 compatible = "snps,dw-apb-timer-sp";
110 interrupts = <0 168 4>; 113 interrupts = <0 168 4>;
111 clock-frequency = <200000000>;
112 reg = <0xffc09000 0x1000>; 114 reg = <0xffc09000 0x1000>;
113 }; 115 };
114 116
115 timer2: timer@ffd00000 { 117 timer2: timer2@ffd00000 {
116 compatible = "snps,dw-apb-timer-osc"; 118 compatible = "snps,dw-apb-timer-osc";
117 interrupts = <0 169 4>; 119 interrupts = <0 169 4>;
118 clock-frequency = <200000000>;
119 reg = <0xffd00000 0x1000>; 120 reg = <0xffd00000 0x1000>;
120 }; 121 };
121 122
122 timer3: timer@ffd01000 { 123 timer3: timer3@ffd01000 {
123 compatible = "snps,dw-apb-timer-osc"; 124 compatible = "snps,dw-apb-timer-osc";
124 interrupts = <0 170 4>; 125 interrupts = <0 170 4>;
125 clock-frequency = <200000000>;
126 reg = <0xffd01000 0x1000>; 126 reg = <0xffd01000 0x1000>;
127 }; 127 };
128 128
129 uart0: uart@ffc02000 { 129 uart0: serial0@ffc02000 {
130 compatible = "snps,dw-apb-uart"; 130 compatible = "snps,dw-apb-uart";
131 reg = <0xffc02000 0x1000>; 131 reg = <0xffc02000 0x1000>;
132 clock-frequency = <7372800>;
133 interrupts = <0 162 4>; 132 interrupts = <0 162 4>;
134 reg-shift = <2>; 133 reg-shift = <2>;
135 reg-io-width = <4>; 134 reg-io-width = <4>;
136 }; 135 };
137 136
138 uart1: uart@ffc03000 { 137 uart1: serial1@ffc03000 {
139 compatible = "snps,dw-apb-uart"; 138 compatible = "snps,dw-apb-uart";
140 reg = <0xffc03000 0x1000>; 139 reg = <0xffc03000 0x1000>;
141 clock-frequency = <7372800>;
142 interrupts = <0 163 4>; 140 interrupts = <0 163 4>;
143 reg-shift = <2>; 141 reg-shift = <2>;
144 reg-io-width = <4>; 142 reg-io-width = <4>;
diff --git a/arch/arm/boot/dts/socfpga_cyclone5.dts b/arch/arm/boot/dts/socfpga_cyclone5.dts
index ab7e4a94299f..3ae8a83a0875 100644
--- a/arch/arm/boot/dts/socfpga_cyclone5.dts
+++ b/arch/arm/boot/dts/socfpga_cyclone5.dts
@@ -20,7 +20,7 @@
20 20
21/ { 21/ {
22 model = "Altera SOCFPGA Cyclone V"; 22 model = "Altera SOCFPGA Cyclone V";
23 compatible = "altr,socfpga-cyclone5"; 23 compatible = "altr,socfpga-cyclone5", "altr,socfpga";
24 24
25 chosen { 25 chosen {
26 bootargs = "console=ttyS0,57600"; 26 bootargs = "console=ttyS0,57600";
@@ -29,6 +29,36 @@
29 memory { 29 memory {
30 name = "memory"; 30 name = "memory";
31 device_type = "memory"; 31 device_type = "memory";
32 reg = <0x0 0x10000000>; /* 256MB */ 32 reg = <0x0 0x40000000>; /* 1GB */
33 };
34
35 soc {
36 timer0@ffc08000 {
37 clock-frequency = <100000000>;
38 };
39
40 timer1@ffc09000 {
41 clock-frequency = <100000000>;
42 };
43
44 timer2@ffd00000 {
45 clock-frequency = <25000000>;
46 };
47
48 timer3@ffd01000 {
49 clock-frequency = <25000000>;
50 };
51
52 serial0@ffc02000 {
53 clock-frequency = <100000000>;
54 };
55
56 serial1@ffc03000 {
57 clock-frequency = <100000000>;
58 };
59
60 sysmgr@ffd08000 {
61 cpu1-start-addr = <0xffd080c4>;
62 };
33 }; 63 };
34}; 64};
diff --git a/arch/arm/boot/dts/socfpga_vt.dts b/arch/arm/boot/dts/socfpga_vt.dts
new file mode 100644
index 000000000000..1036eba40bbf
--- /dev/null
+++ b/arch/arm/boot/dts/socfpga_vt.dts
@@ -0,0 +1,64 @@
1/*
2 * Copyright (C) 2013 Altera Corporation <www.altera.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/dts-v1/;
19/include/ "socfpga.dtsi"
20
21/ {
22 model = "Altera SOCFPGA VT";
23 compatible = "altr,socfpga-vt", "altr,socfpga";
24
25 chosen {
26 bootargs = "console=ttyS0,57600";
27 };
28
29 memory {
30 name = "memory";
31 device_type = "memory";
32 reg = <0x0 0x40000000>; /* 1 GB */
33 };
34
35 soc {
36 timer0@ffc08000 {
37 clock-frequency = <7000000>;
38 };
39
40 timer1@ffc09000 {
41 clock-frequency = <7000000>;
42 };
43
44 timer2@ffd00000 {
45 clock-frequency = <7000000>;
46 };
47
48 timer3@ffd01000 {
49 clock-frequency = <7000000>;
50 };
51
52 serial0@ffc02000 {
53 clock-frequency = <7372800>;
54 };
55
56 serial1@ffc03000 {
57 clock-frequency = <7372800>;
58 };
59
60 sysmgr@ffd08000 {
61 cpu1-start-addr = <0xffd08010>;
62 };
63 };
64};
diff --git a/arch/arm/mach-imx/headsmp.S b/arch/arm/mach-imx/headsmp.S
index 7e49deb128a4..921fc1555854 100644
--- a/arch/arm/mach-imx/headsmp.S
+++ b/arch/arm/mach-imx/headsmp.S
@@ -17,53 +17,6 @@
17 17
18 .section ".text.head", "ax" 18 .section ".text.head", "ax"
19 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 */
33ENTRY(v7_invalidate_l1)
34 mov r0, #0
35 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
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
521: sub r2, r2, #1 @ NumSets--
53 mov r3, r4 @ Temp = NumWays
542: 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
65ENDPROC(v7_invalidate_l1)
66
67#ifdef CONFIG_SMP 20#ifdef CONFIG_SMP
68ENTRY(v7_secondary_startup) 21ENTRY(v7_secondary_startup)
69 bl v7_invalidate_l1 22 bl v7_invalidate_l1
diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S
index b202c1272526..96001fd49b6c 100644
--- a/arch/arm/mach-shmobile/headsmp.S
+++ b/arch/arm/mach-shmobile/headsmp.S
@@ -16,54 +16,6 @@
16 16
17 __CPUINIT 17 __CPUINIT
18 18
19/* Cache invalidation nicked from arch/arm/mach-imx/head-v7.S, thanks!
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 */
33ENTRY(v7_invalidate_l1)
34 mov r0, #0
35 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
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
521: sub r2, r2, #1 @ NumSets--
53 mov r3, r4 @ Temp = NumWays
542: 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
65ENDPROC(v7_invalidate_l1)
66
67ENTRY(shmobile_invalidate_start) 19ENTRY(shmobile_invalidate_start)
68 bl v7_invalidate_l1 20 bl v7_invalidate_l1
69 b secondary_startup 21 b secondary_startup
diff --git a/arch/arm/mach-socfpga/core.h b/arch/arm/mach-socfpga/core.h
index 9941caa94931..315edff610f2 100644
--- a/arch/arm/mach-socfpga/core.h
+++ b/arch/arm/mach-socfpga/core.h
@@ -20,7 +20,7 @@
20#ifndef __MACH_CORE_H 20#ifndef __MACH_CORE_H
21#define __MACH_CORE_H 21#define __MACH_CORE_H
22 22
23extern void secondary_startup(void); 23extern void socfpga_secondary_startup(void);
24extern void __iomem *socfpga_scu_base_addr; 24extern void __iomem *socfpga_scu_base_addr;
25 25
26extern void socfpga_init_clocks(void); 26extern void socfpga_init_clocks(void);
@@ -29,6 +29,8 @@ extern void socfpga_sysmgr_init(void);
29extern struct smp_operations socfpga_smp_ops; 29extern struct smp_operations socfpga_smp_ops;
30extern char secondary_trampoline, secondary_trampoline_end; 30extern char secondary_trampoline, secondary_trampoline_end;
31 31
32extern unsigned long cpu1start_addr;
33
32#define SOCFPGA_SCU_VIRT_BASE 0xfffec000 34#define SOCFPGA_SCU_VIRT_BASE 0xfffec000
33 35
34#endif 36#endif
diff --git a/arch/arm/mach-socfpga/headsmp.S b/arch/arm/mach-socfpga/headsmp.S
index f09b1283ffca..9004bfb1756e 100644
--- a/arch/arm/mach-socfpga/headsmp.S
+++ b/arch/arm/mach-socfpga/headsmp.S
@@ -13,13 +13,21 @@
13 __CPUINIT 13 __CPUINIT
14 .arch armv7-a 14 .arch armv7-a
15 15
16#define CPU1_START_ADDR 0xffd08010
17
18ENTRY(secondary_trampoline) 16ENTRY(secondary_trampoline)
19 movw r0, #:lower16:CPU1_START_ADDR 17 movw r2, #:lower16:cpu1start_addr
20 movt r0, #:upper16:CPU1_START_ADDR 18 movt r2, #:upper16:cpu1start_addr
19
20 /* The socfpga VT cannot handle a 0xC0000000 page offset when loading
21 the cpu1start_addr, we bit clear it. Tested on HW and VT. */
22 bic r2, r2, #0x40000000
21 23
24 ldr r0, [r2]
22 ldr r1, [r0] 25 ldr r1, [r0]
23 bx r1 26 bx r1
24 27
25ENTRY(secondary_trampoline_end) 28ENTRY(secondary_trampoline_end)
29
30ENTRY(socfpga_secondary_startup)
31 bl v7_invalidate_l1
32 b secondary_startup
33ENDPROC(socfpga_secondary_startup)
diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c
index 4e9e69d9e7de..84c60fa8daa0 100644
--- a/arch/arm/mach-socfpga/platsmp.c
+++ b/arch/arm/mach-socfpga/platsmp.c
@@ -47,16 +47,19 @@ static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct task_struct
47{ 47{
48 int trampoline_size = &secondary_trampoline_end - &secondary_trampoline; 48 int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
49 49
50 memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size); 50 if (cpu1start_addr) {
51 memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
51 52
52 __raw_writel(virt_to_phys(secondary_startup), (sys_manager_base_addr+0x10)); 53 __raw_writel(virt_to_phys(socfpga_secondary_startup),
54 (sys_manager_base_addr + (cpu1start_addr & 0x000000ff)));
53 55
54 flush_cache_all(); 56 flush_cache_all();
55 smp_wmb(); 57 smp_wmb();
56 outer_clean_range(0, trampoline_size); 58 outer_clean_range(0, trampoline_size);
57 59
58 /* This will release CPU #1 out of reset.*/ 60 /* This will release CPU #1 out of reset.*/
59 __raw_writel(0, rst_manager_base_addr + 0x10); 61 __raw_writel(0, rst_manager_base_addr + 0x10);
62 }
60 63
61 return 0; 64 return 0;
62} 65}
diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c
index 27d68468a027..1042c023cf24 100644
--- a/arch/arm/mach-socfpga/socfpga.c
+++ b/arch/arm/mach-socfpga/socfpga.c
@@ -29,6 +29,7 @@
29void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE)); 29void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
30void __iomem *sys_manager_base_addr; 30void __iomem *sys_manager_base_addr;
31void __iomem *rst_manager_base_addr; 31void __iomem *rst_manager_base_addr;
32unsigned long cpu1start_addr;
32 33
33static struct map_desc scu_io_desc __initdata = { 34static struct map_desc scu_io_desc __initdata = {
34 .virtual = SOCFPGA_SCU_VIRT_BASE, 35 .virtual = SOCFPGA_SCU_VIRT_BASE,
@@ -67,6 +68,11 @@ void __init socfpga_sysmgr_init(void)
67 struct device_node *np; 68 struct device_node *np;
68 69
69 np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr"); 70 np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr");
71
72 if (of_property_read_u32(np, "cpu1-start-addr",
73 (u32 *) &cpu1start_addr))
74 pr_err("SMP: Need cpu1-start-addr in device tree.\n");
75
70 sys_manager_base_addr = of_iomap(np, 0); 76 sys_manager_base_addr = of_iomap(np, 0);
71 77
72 np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr"); 78 np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr");
@@ -93,7 +99,6 @@ static void __init socfpga_cyclone5_init(void)
93 99
94static const char *altera_dt_match[] = { 100static const char *altera_dt_match[] = {
95 "altr,socfpga", 101 "altr,socfpga",
96 "altr,socfpga-cyclone5",
97 NULL 102 NULL
98}; 103};
99 104
diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
index b2834810b02b..fd473f2b4c3d 100644
--- a/arch/arm/mach-tegra/headsmp.S
+++ b/arch/arm/mach-tegra/headsmp.S
@@ -5,49 +5,6 @@
5 5
6 .section ".text.head", "ax" 6 .section ".text.head", "ax"
7 7
8/*
9 * Tegra specific entry point for secondary CPUs.
10 * The secondary kernel init calls v7_flush_dcache_all before it enables
11 * the L1; however, the L1 comes out of reset in an undefined state, so
12 * the clean + invalidate performed by v7_flush_dcache_all causes a bunch
13 * of cache lines with uninitialized data and uninitialized tags to get
14 * written out to memory, which does really unpleasant things to the main
15 * processor. We fix this by performing an invalidate, rather than a
16 * clean + invalidate, before jumping into the kernel.
17 */
18ENTRY(v7_invalidate_l1)
19 mov r0, #0
20 mcr p15, 2, r0, c0, c0, 0
21 mrc p15, 1, r0, c0, c0, 0
22
23 ldr r1, =0x7fff
24 and r2, r1, r0, lsr #13
25
26 ldr r1, =0x3ff
27
28 and r3, r1, r0, lsr #3 @ NumWays - 1
29 add r2, r2, #1 @ NumSets
30
31 and r0, r0, #0x7
32 add r0, r0, #4 @ SetShift
33
34 clz r1, r3 @ WayShift
35 add r4, r3, #1 @ NumWays
361: sub r2, r2, #1 @ NumSets--
37 mov r3, r4 @ Temp = NumWays
382: subs r3, r3, #1 @ Temp--
39 mov r5, r3, lsl r1
40 mov r6, r2, lsl r0
41 orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
42 mcr p15, 0, r5, c7, c6, 2
43 bgt 2b
44 cmp r2, #0
45 bgt 1b
46 dsb
47 isb
48 mov pc, lr
49ENDPROC(v7_invalidate_l1)
50
51ENTRY(tegra_secondary_startup) 8ENTRY(tegra_secondary_startup)
52 bl v7_invalidate_l1 9 bl v7_invalidate_l1
53 /* Enable coresight */ 10 /* Enable coresight */
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index 7539ec275065..15451ee4acc8 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -19,6 +19,52 @@
19#include "proc-macros.S" 19#include "proc-macros.S"
20 20
21/* 21/*
22 * The secondary kernel init calls v7_flush_dcache_all before it enables
23 * the L1; however, the L1 comes out of reset in an undefined state, so
24 * the clean + invalidate performed by v7_flush_dcache_all causes a bunch
25 * of cache lines with uninitialized data and uninitialized tags to get
26 * written out to memory, which does really unpleasant things to the main
27 * processor. We fix this by performing an invalidate, rather than a
28 * clean + invalidate, before jumping into the kernel.
29 *
30 * This function is cloned from arch/arm/mach-tegra/headsmp.S, and needs
31 * to be called for both secondary cores startup and primary core resume
32 * procedures.
33 */
34ENTRY(v7_invalidate_l1)
35 mov r0, #0
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
521: sub r2, r2, #1 @ NumSets--
53 mov r3, r4 @ Temp = NumWays
542: 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
65ENDPROC(v7_invalidate_l1)
66
67/*
22 * v7_flush_icache_all() 68 * v7_flush_icache_all()
23 * 69 *
24 * Flush the whole I-cache. 70 * Flush the whole I-cache.