arm: socfpga: Add SMP support for actual socfpga harware
authorDinh Nguyen <dinguyen@altera.com>
Mon, 11 Feb 2013 23:30:33 +0000 (17:30 -0600)
committerOlof Johansson <olof@lixom.net>
Tue, 12 Feb 2013 03:37:26 +0000 (19:37 -0800)
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>
Documentation/devicetree/bindings/arm/altera/socfpga-system.txt
arch/arm/boot/dts/socfpga_cyclone5.dts
arch/arm/boot/dts/socfpga_vt.dts
arch/arm/mach-socfpga/core.h
arch/arm/mach-socfpga/headsmp.S
arch/arm/mach-socfpga/platsmp.c
arch/arm/mach-socfpga/socfpga.c

index 07c65e3cdcbe1245575d89ef9b3005b9242ad707..f4d04a0672824087de6987b6be4dfd5c4fd2bf84 100644 (file)
@@ -3,9 +3,11 @@ Altera SOCFPGA System Manager
 Required properties:
 - compatible : "altr,sys-mgr"
 - reg : Should contain 1 register ranges(address and length)
+- cpu1-start-addr : CPU1 start address in hex.
 
 Example:
         sysmgr@ffd08000 {
                compatible = "altr,sys-mgr";
                reg = <0xffd08000 0x1000>;
+               cpu1-start-addr = <0xffd080c4>;
        };
index 7ad3cc69df5a06a5b8ee318f36c57e28f23f0951..3ae8a83a08759021f2946f7872ceb3e53ce79c0a 100644 (file)
@@ -56,5 +56,9 @@
                serial1@ffc03000 {
                        clock-frequency = <100000000>;
                };
+
+               sysmgr@ffd08000 {
+                       cpu1-start-addr = <0xffd080c4>;
+               };
        };
 };
index a0c6c651850fbaff836d8ac68703a9850202951d..1036eba40bbfca306e26d754e4f96b085c61ae8d 100644 (file)
@@ -56,5 +56,9 @@
                serial1@ffc03000 {
                        clock-frequency = <7372800>;
                };
+
+               sysmgr@ffd08000 {
+                       cpu1-start-addr = <0xffd08010>;
+               };
        };
 };
index 9941caa949310849968859b8b20e3da971dff7ff..315edff610f241747439e92c3c5ff858ed4570cc 100644 (file)
@@ -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
index f09b1283ffca79fa275418bae0abb4519eba2477..9004bfb1756ee345192d78c3f2a125c2b985a8e5 100644 (file)
        __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)
index 68dd1b69512acc5f02770ae1a0a0493ba11862bd..248196809202337407044a7d649caef5d4a79e03 100644 (file)
@@ -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;
 }
index 94aa6add64436ad7a34cd9fb768ebda14a7df4b1..cec126679ec32410e6e4e717ab5032502d9ea721 100644 (file)
@@ -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");