summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-socfpga
diff options
context:
space:
mode:
authorDinh Nguyen <dinguyen@altera.com>2013-02-12 00:30:33 +0100
committerOlof Johansson <olof@lixom.net>2013-02-12 04:37:26 +0100
commitd6dd735f4bda19bfe07d96d9025c94c4619d4596 (patch)
treec8c688aacf4c7315ed7af8ade6508f511ac28aab /arch/arm/mach-socfpga
parentarm: Add v7_invalidate_l1 to cache-v7.S (diff)
downloadlinux-d6dd735f4bda19bfe07d96d9025c94c4619d4596.tar.xz
linux-d6dd735f4bda19bfe07d96d9025c94c4619d4596.zip
arm: socfpga: Add SMP support for actual socfpga harware
Because the CPU1 start address is different for socfpga-vt and socfpga-cyclone5, we add code to use the correct CPU1 start addr. Signed-off-by: Dinh Nguyen <dinguyen@altera.com> Signed-off-by: Pavel Machek <pavel@denx.de> Cc: Russell King <linux@arm.linux.org.uk> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Olof Johansson <olof@lixom.net> Cc: Rob Herring <rob.herring@calxeda.com> Cc: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/arm/mach-socfpga')
-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.c6
4 files changed, 31 insertions, 12 deletions
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 @@
#ifndef __MACH_CORE_H
#define __MACH_CORE_H
-extern void secondary_startup(void);
+extern void socfpga_secondary_startup(void);
extern void __iomem *socfpga_scu_base_addr;
extern void socfpga_init_clocks(void);
@@ -29,6 +29,8 @@ extern void socfpga_sysmgr_init(void);
extern struct smp_operations socfpga_smp_ops;
extern char secondary_trampoline, secondary_trampoline_end;
+extern unsigned long cpu1start_addr;
+
#define SOCFPGA_SCU_VIRT_BASE 0xfffec000
#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 @@
__CPUINIT
.arch armv7-a
-#define CPU1_START_ADDR 0xffd08010
-
ENTRY(secondary_trampoline)
- movw r0, #:lower16:CPU1_START_ADDR
- movt r0, #:upper16:CPU1_START_ADDR
+ movw r2, #:lower16:cpu1start_addr
+ movt r2, #:upper16:cpu1start_addr
+
+ /* The socfpga VT cannot handle a 0xC0000000 page offset when loading
+ the cpu1start_addr, we bit clear it. Tested on HW and VT. */
+ bic r2, r2, #0x40000000
+ ldr r0, [r2]
ldr r1, [r0]
bx r1
ENTRY(secondary_trampoline_end)
+
+ENTRY(socfpga_secondary_startup)
+ bl v7_invalidate_l1
+ b secondary_startup
+ENDPROC(socfpga_secondary_startup)
diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c
index 68dd1b69512a..248196809202 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
{
int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
- memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
+ if (cpu1start_addr) {
+ memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
- __raw_writel(virt_to_phys(secondary_startup), (sys_manager_base_addr+0x10));
+ __raw_writel(virt_to_phys(socfpga_secondary_startup),
+ (sys_manager_base_addr + (cpu1start_addr & 0x000000ff)));
- flush_cache_all();
- smp_wmb();
- outer_clean_range(0, trampoline_size);
+ flush_cache_all();
+ smp_wmb();
+ outer_clean_range(0, trampoline_size);
- /* This will release CPU #1 out of reset.*/
- __raw_writel(0, rst_manager_base_addr + 0x10);
+ /* This will release CPU #1 out of reset.*/
+ __raw_writel(0, rst_manager_base_addr + 0x10);
+ }
return 0;
}
diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c
index 94aa6add6443..cec126679ec3 100644
--- a/arch/arm/mach-socfpga/socfpga.c
+++ b/arch/arm/mach-socfpga/socfpga.c
@@ -29,6 +29,7 @@
void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
void __iomem *sys_manager_base_addr;
void __iomem *rst_manager_base_addr;
+unsigned long cpu1start_addr;
static struct map_desc scu_io_desc __initdata = {
.virtual = SOCFPGA_SCU_VIRT_BASE,
@@ -72,6 +73,11 @@ void __init socfpga_sysmgr_init(void)
struct device_node *np;
np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr");
+
+ if (of_property_read_u32(np, "cpu1-start-addr",
+ (u32 *) &cpu1start_addr))
+ pr_err("SMP: Need cpu1-start-addr in device tree.\n");
+
sys_manager_base_addr = of_iomap(np, 0);
np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr");