diff options
author | Dinh Nguyen <dinguyen@altera.com> | 2013-02-11 18:30:33 -0500 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2013-02-11 22:37:26 -0500 |
commit | d6dd735f4bda19bfe07d96d9025c94c4619d4596 (patch) | |
tree | c8c688aacf4c7315ed7af8ade6508f511ac28aab | |
parent | c08e20d246ded319fc77616c64dcbf69456cb4be (diff) |
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>
-rw-r--r-- | Documentation/devicetree/bindings/arm/altera/socfpga-system.txt | 2 | ||||
-rw-r--r-- | arch/arm/boot/dts/socfpga_cyclone5.dts | 4 | ||||
-rw-r--r-- | arch/arm/boot/dts/socfpga_vt.dts | 4 | ||||
-rw-r--r-- | arch/arm/mach-socfpga/core.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-socfpga/headsmp.S | 16 | ||||
-rw-r--r-- | arch/arm/mach-socfpga/platsmp.c | 17 | ||||
-rw-r--r-- | arch/arm/mach-socfpga/socfpga.c | 6 |
7 files changed, 41 insertions, 12 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 | |||
3 | Required properties: | 3 | Required 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 | ||
7 | Example: | 8 | Example: |
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/socfpga_cyclone5.dts b/arch/arm/boot/dts/socfpga_cyclone5.dts index 7ad3cc69df5a..3ae8a83a0875 100644 --- a/arch/arm/boot/dts/socfpga_cyclone5.dts +++ b/arch/arm/boot/dts/socfpga_cyclone5.dts | |||
@@ -56,5 +56,9 @@ | |||
56 | serial1@ffc03000 { | 56 | serial1@ffc03000 { |
57 | clock-frequency = <100000000>; | 57 | clock-frequency = <100000000>; |
58 | }; | 58 | }; |
59 | |||
60 | sysmgr@ffd08000 { | ||
61 | cpu1-start-addr = <0xffd080c4>; | ||
62 | }; | ||
59 | }; | 63 | }; |
60 | }; | 64 | }; |
diff --git a/arch/arm/boot/dts/socfpga_vt.dts b/arch/arm/boot/dts/socfpga_vt.dts index a0c6c651850f..1036eba40bbf 100644 --- a/arch/arm/boot/dts/socfpga_vt.dts +++ b/arch/arm/boot/dts/socfpga_vt.dts | |||
@@ -56,5 +56,9 @@ | |||
56 | serial1@ffc03000 { | 56 | serial1@ffc03000 { |
57 | clock-frequency = <7372800>; | 57 | clock-frequency = <7372800>; |
58 | }; | 58 | }; |
59 | |||
60 | sysmgr@ffd08000 { | ||
61 | cpu1-start-addr = <0xffd08010>; | ||
62 | }; | ||
59 | }; | 63 | }; |
60 | }; | 64 | }; |
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 | ||
23 | extern void secondary_startup(void); | 23 | extern void socfpga_secondary_startup(void); |
24 | extern void __iomem *socfpga_scu_base_addr; | 24 | extern void __iomem *socfpga_scu_base_addr; |
25 | 25 | ||
26 | extern void socfpga_init_clocks(void); | 26 | extern void socfpga_init_clocks(void); |
@@ -29,6 +29,8 @@ extern void socfpga_sysmgr_init(void); | |||
29 | extern struct smp_operations socfpga_smp_ops; | 29 | extern struct smp_operations socfpga_smp_ops; |
30 | extern char secondary_trampoline, secondary_trampoline_end; | 30 | extern char secondary_trampoline, secondary_trampoline_end; |
31 | 31 | ||
32 | extern 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 | |||
18 | ENTRY(secondary_trampoline) | 16 | ENTRY(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 | ||
25 | ENTRY(secondary_trampoline_end) | 28 | ENTRY(secondary_trampoline_end) |
29 | |||
30 | ENTRY(socfpga_secondary_startup) | ||
31 | bl v7_invalidate_l1 | ||
32 | b secondary_startup | ||
33 | 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 | |||
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 94aa6add6443..cec126679ec3 100644 --- a/arch/arm/mach-socfpga/socfpga.c +++ b/arch/arm/mach-socfpga/socfpga.c | |||
@@ -29,6 +29,7 @@ | |||
29 | void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE)); | 29 | void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE)); |
30 | void __iomem *sys_manager_base_addr; | 30 | void __iomem *sys_manager_base_addr; |
31 | void __iomem *rst_manager_base_addr; | 31 | void __iomem *rst_manager_base_addr; |
32 | unsigned long cpu1start_addr; | ||
32 | 33 | ||
33 | static struct map_desc scu_io_desc __initdata = { | 34 | static struct map_desc scu_io_desc __initdata = { |
34 | .virtual = SOCFPGA_SCU_VIRT_BASE, | 35 | .virtual = SOCFPGA_SCU_VIRT_BASE, |
@@ -72,6 +73,11 @@ void __init socfpga_sysmgr_init(void) | |||
72 | struct device_node *np; | 73 | struct device_node *np; |
73 | 74 | ||
74 | np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr"); | 75 | np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr"); |
76 | |||
77 | if (of_property_read_u32(np, "cpu1-start-addr", | ||
78 | (u32 *) &cpu1start_addr)) | ||
79 | pr_err("SMP: Need cpu1-start-addr in device tree.\n"); | ||
80 | |||
75 | sys_manager_base_addr = of_iomap(np, 0); | 81 | sys_manager_base_addr = of_iomap(np, 0); |
76 | 82 | ||
77 | np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr"); | 83 | np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr"); |