aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDinh Nguyen <dinguyen@opensource.altera.com>2014-10-01 06:44:48 -0400
committerDinh Nguyen <dinguyen@opensource.altera.com>2014-10-21 15:04:14 -0400
commit3a4356c0c042a5f340c8d6ee1a4feaa1c8e51ea2 (patch)
tree74bb48d5106a2b80483ba7b50335e933fdc5bd15 /arch
parentf114040e3ea6e07372334ade75d1ee0775c355e1 (diff)
arm: socfpga: fix fetching cpu1start_addr for SMP
When CPU1 is brought out of reset, it's MMU is not turned on yet, so it will only be able to use physical addresses. For systems with that have the MMU page configured for 0xC0000000, 0x80000000, or 0x40000000 "BIC 0x40000000" will work just fine, as it was just converting the virtual address of &cpu1start_addr into a physical address, ie. 0xC0000000 became 0x80000000. So for systems where the SDRAM controller was able to do a wrap-around access, this was working fine, as it was just dropping the MSB, but for systems where out of bounds memory access is not allowed, this would not allow CPU1 to correctly fetch &cpu1start_addr. This patch fixes the secondary_trampoline code to correctly fetch the physical address of cpu1start_addr directly. The patch will subtract the correct PAGE_OFFSET from &cpu1start_addr. And since on this platform, the physical memory will always start at 0x0, subtracting PAGE_OFFSET from &cpu1start_addr will allow CPU1 to correctly fetch the value of cpu1start_addr. While at it, change the name of cpu1start_addr to socfpga_cpu1start_addr to avoid any future naming collisions for multiplatform image. Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com> --- v4: Updated commit log to correctly lay out the usage of PAGE_OFFSET and add comments to the same effect. v3: Used PAGE_OFFSET to get the physical address v2: Correctly get the physical address instead of just a BIC hack.
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-socfpga/core.h2
-rw-r--r--arch/arm/mach-socfpga/headsmp.S25
-rw-r--r--arch/arm/mach-socfpga/platsmp.c4
-rw-r--r--arch/arm/mach-socfpga/socfpga.c4
4 files changed, 20 insertions, 15 deletions
diff --git a/arch/arm/mach-socfpga/core.h b/arch/arm/mach-socfpga/core.h
index 572b8f719ffb..60c443dadb58 100644
--- a/arch/arm/mach-socfpga/core.h
+++ b/arch/arm/mach-socfpga/core.h
@@ -40,7 +40,7 @@ extern void __iomem *rst_manager_base_addr;
40extern struct smp_operations socfpga_smp_ops; 40extern struct smp_operations socfpga_smp_ops;
41extern char secondary_trampoline, secondary_trampoline_end; 41extern char secondary_trampoline, secondary_trampoline_end;
42 42
43extern unsigned long cpu1start_addr; 43extern unsigned long socfpga_cpu1start_addr;
44 44
45#define SOCFPGA_SCU_VIRT_BASE 0xfffec000 45#define SOCFPGA_SCU_VIRT_BASE 0xfffec000
46 46
diff --git a/arch/arm/mach-socfpga/headsmp.S b/arch/arm/mach-socfpga/headsmp.S
index 95c115d8b5ee..f65ea0af4af3 100644
--- a/arch/arm/mach-socfpga/headsmp.S
+++ b/arch/arm/mach-socfpga/headsmp.S
@@ -9,21 +9,26 @@
9 */ 9 */
10#include <linux/linkage.h> 10#include <linux/linkage.h>
11#include <linux/init.h> 11#include <linux/init.h>
12#include <asm/memory.h>
12 13
13 .arch armv7-a 14 .arch armv7-a
14 15
15ENTRY(secondary_trampoline) 16ENTRY(secondary_trampoline)
16 movw r2, #:lower16:cpu1start_addr 17 /* CPU1 will always fetch from 0x0 when it is brought out of reset.
17 movt r2, #:upper16:cpu1start_addr 18 * Thus, we can just subtract the PAGE_OFFSET to get the physical
18 19 * address of &cpu1start_addr. This would not work for platforms
19 /* The socfpga VT cannot handle a 0xC0000000 page offset when loading 20 * where the physical memory does not start at 0x0.
20 the cpu1start_addr, we bit clear it. Tested on HW and VT. */ 21 */
21 bic r2, r2, #0x40000000 22 adr r0, 1f
22 23 ldmia r0, {r1, r2}
23 ldr r0, [r2] 24 sub r2, r2, #PAGE_OFFSET
24 ldr r1, [r0] 25 ldr r3, [r2]
25 bx r1 26 ldr r4, [r3]
27 bx r4
26 28
29 .align
301: .long .
31 .long socfpga_cpu1start_addr
27ENTRY(secondary_trampoline_end) 32ENTRY(secondary_trampoline_end)
28 33
29ENTRY(socfpga_secondary_startup) 34ENTRY(socfpga_secondary_startup)
diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c
index 5356a72bc8ce..16ca97b039f9 100644
--- a/arch/arm/mach-socfpga/platsmp.c
+++ b/arch/arm/mach-socfpga/platsmp.c
@@ -33,11 +33,11 @@ static int socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
33{ 33{
34 int trampoline_size = &secondary_trampoline_end - &secondary_trampoline; 34 int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
35 35
36 if (cpu1start_addr) { 36 if (socfpga_cpu1start_addr) {
37 memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size); 37 memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
38 38
39 __raw_writel(virt_to_phys(socfpga_secondary_startup), 39 __raw_writel(virt_to_phys(socfpga_secondary_startup),
40 (sys_manager_base_addr + (cpu1start_addr & 0x000000ff))); 40 (sys_manager_base_addr + (socfpga_cpu1start_addr & 0x000000ff)));
41 41
42 flush_cache_all(); 42 flush_cache_all();
43 smp_wmb(); 43 smp_wmb();
diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c
index adbf38314ca8..383d61e138af 100644
--- a/arch/arm/mach-socfpga/socfpga.c
+++ b/arch/arm/mach-socfpga/socfpga.c
@@ -29,7 +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; 32unsigned long socfpga_cpu1start_addr;
33 33
34static struct map_desc scu_io_desc __initdata = { 34static struct map_desc scu_io_desc __initdata = {
35 .virtual = SOCFPGA_SCU_VIRT_BASE, 35 .virtual = SOCFPGA_SCU_VIRT_BASE,
@@ -70,7 +70,7 @@ void __init socfpga_sysmgr_init(void)
70 np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr"); 70 np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr");
71 71
72 if (of_property_read_u32(np, "cpu1-start-addr", 72 if (of_property_read_u32(np, "cpu1-start-addr",
73 (u32 *) &cpu1start_addr)) 73 (u32 *) &socfpga_cpu1start_addr))
74 pr_err("SMP: Need cpu1-start-addr in device tree.\n"); 74 pr_err("SMP: Need cpu1-start-addr in device tree.\n");
75 75
76 sys_manager_base_addr = of_iomap(np, 0); 76 sys_manager_base_addr = of_iomap(np, 0);