aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-socfpga
diff options
context:
space:
mode:
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.c21
-rw-r--r--arch/arm/mach-socfpga/socfpga.c23
4 files changed, 37 insertions, 27 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 @@
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 68dd1b69512a..84c60fa8daa0 100644
--- a/arch/arm/mach-socfpga/platsmp.c
+++ b/arch/arm/mach-socfpga/platsmp.c
@@ -22,9 +22,9 @@
22#include <linux/io.h> 22#include <linux/io.h>
23#include <linux/of.h> 23#include <linux/of.h>
24#include <linux/of_address.h> 24#include <linux/of_address.h>
25#include <linux/irqchip/arm-gic.h>
25 26
26#include <asm/cacheflush.h> 27#include <asm/cacheflush.h>
27#include <asm/hardware/gic.h>
28#include <asm/smp_scu.h> 28#include <asm/smp_scu.h>
29#include <asm/smp_plat.h> 29#include <asm/smp_plat.h>
30 30
@@ -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}
@@ -83,8 +86,6 @@ static void __init socfpga_smp_init_cpus(void)
83 86
84 for (i = 0; i < ncores; i++) 87 for (i = 0; i < ncores; i++)
85 set_cpu_possible(i, true); 88 set_cpu_possible(i, true);
86
87 set_smp_cross_call(gic_raise_softirq);
88} 89}
89 90
90static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus) 91static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c
index 6732924a5fee..1042c023cf24 100644
--- a/arch/arm/mach-socfpga/socfpga.c
+++ b/arch/arm/mach-socfpga/socfpga.c
@@ -15,12 +15,12 @@
15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17#include <linux/dw_apb_timer.h> 17#include <linux/dw_apb_timer.h>
18#include <linux/irqchip.h>
18#include <linux/of_address.h> 19#include <linux/of_address.h>
19#include <linux/of_irq.h> 20#include <linux/of_irq.h>
20#include <linux/of_platform.h> 21#include <linux/of_platform.h>
21 22
22#include <asm/hardware/cache-l2x0.h> 23#include <asm/hardware/cache-l2x0.h>
23#include <asm/hardware/gic.h>
24#include <asm/mach/arch.h> 24#include <asm/mach/arch.h>
25#include <asm/mach/map.h> 25#include <asm/mach/map.h>
26 26
@@ -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,
@@ -62,25 +63,25 @@ static void __init socfpga_map_io(void)
62 early_printk("Early printk initialized\n"); 63 early_printk("Early printk initialized\n");
63} 64}
64 65
65const static struct of_device_id irq_match[] = {
66 { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
67 {}
68};
69
70void __init socfpga_sysmgr_init(void) 66void __init socfpga_sysmgr_init(void)
71{ 67{
72 struct device_node *np; 68 struct device_node *np;
73 69
74 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
75 sys_manager_base_addr = of_iomap(np, 0); 76 sys_manager_base_addr = of_iomap(np, 0);
76 77
77 np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr"); 78 np = of_find_compatible_node(NULL, NULL, "altr,rst-mgr");
78 rst_manager_base_addr = of_iomap(np, 0); 79 rst_manager_base_addr = of_iomap(np, 0);
79} 80}
80 81
81static void __init gic_init_irq(void) 82static void __init socfpga_init_irq(void)
82{ 83{
83 of_irq_init(irq_match); 84 irqchip_init();
84 socfpga_sysmgr_init(); 85 socfpga_sysmgr_init();
85} 86}
86 87
@@ -98,16 +99,14 @@ static void __init socfpga_cyclone5_init(void)
98 99
99static const char *altera_dt_match[] = { 100static const char *altera_dt_match[] = {
100 "altr,socfpga", 101 "altr,socfpga",
101 "altr,socfpga-cyclone5",
102 NULL 102 NULL
103}; 103};
104 104
105DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA") 105DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA")
106 .smp = smp_ops(socfpga_smp_ops), 106 .smp = smp_ops(socfpga_smp_ops),
107 .map_io = socfpga_map_io, 107 .map_io = socfpga_map_io,
108 .init_irq = gic_init_irq, 108 .init_irq = socfpga_init_irq,
109 .handle_irq = gic_handle_irq, 109 .init_time = dw_apb_timer_init,
110 .timer = &dw_apb_timer,
111 .init_machine = socfpga_cyclone5_init, 110 .init_machine = socfpga_cyclone5_init,
112 .restart = socfpga_cyclone5_restart, 111 .restart = socfpga_cyclone5_restart,
113 .dt_compat = altera_dt_match, 112 .dt_compat = altera_dt_match,