aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGregory CLEMENT <gregory.clement@free-electrons.com>2012-11-14 16:51:08 -0500
committerGregory CLEMENT <gregory.clement@free-electrons.com>2012-11-21 10:49:38 -0500
commit45f5984a8a528f7507f3ec860d297934d4449ad1 (patch)
tree2491bbc83f450f2630ab2b3792698f29c374b79b
parentde4901933f6dfc0180f761790d3f47fc64e6270f (diff)
arm: mvebu: Add SMP support for Armada XP
This enables SMP support on the Armada XP processor. It adds the mandatory functions to support SMP such as: the SMP initialization functions in platsmp.c, the secondary CPU entry point in headsmp.S and the CPU hotplug initial support in hotplug.c. Signed-off-by: Yehuda Yitschak <yehuday@marvell.com> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Reviewed-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--arch/arm/configs/mvebu_defconfig3
-rw-r--r--arch/arm/mach-mvebu/Kconfig1
-rw-r--r--arch/arm/mach-mvebu/Makefile2
-rw-r--r--arch/arm/mach-mvebu/armada-370-xp.c3
-rw-r--r--arch/arm/mach-mvebu/common.h3
-rw-r--r--arch/arm/mach-mvebu/headsmp.S49
-rw-r--r--arch/arm/mach-mvebu/hotplug.c30
-rw-r--r--arch/arm/mach-mvebu/platsmp.c122
8 files changed, 213 insertions, 0 deletions
diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig
index 3458752c4bb2..da598d37a65f 100644
--- a/arch/arm/configs/mvebu_defconfig
+++ b/arch/arm/configs/mvebu_defconfig
@@ -12,6 +12,9 @@ CONFIG_ARCH_MVEBU=y
12CONFIG_MACH_ARMADA_370=y 12CONFIG_MACH_ARMADA_370=y
13CONFIG_MACH_ARMADA_XP=y 13CONFIG_MACH_ARMADA_XP=y
14# CONFIG_CACHE_L2X0 is not set 14# CONFIG_CACHE_L2X0 is not set
15# CONFIG_SWP_EMULATE is not set
16CONFIG_SMP=y
17# CONFIG_LOCAL_TIMERS is not set
15CONFIG_AEABI=y 18CONFIG_AEABI=y
16CONFIG_HIGHMEM=y 19CONFIG_HIGHMEM=y
17# CONFIG_COMPACTION is not set 20# CONFIG_COMPACTION is not set
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index f4c3bf88f178..c934e1d4933d 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -21,6 +21,7 @@ menu "Marvell SOC with device tree"
21config MACH_ARMADA_370_XP 21config MACH_ARMADA_370_XP
22 bool 22 bool
23 select ARMADA_370_XP_TIMER 23 select ARMADA_370_XP_TIMER
24 select HAVE_SMP
24 select CPU_PJ4B 25 select CPU_PJ4B
25 26
26config MACH_ARMADA_370 27config MACH_ARMADA_370
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index 2e3ec11c51e6..5dcb369b58aa 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -3,3 +3,5 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
3 3
4obj-y += system-controller.o 4obj-y += system-controller.o
5obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o coherency.o coherency_ll.o pmsu.o 5obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o coherency.o coherency_ll.o pmsu.o
6obj-$(CONFIG_SMP) += platsmp.o headsmp.o
7obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c
index 3292d6da5dc7..472e70ffce8d 100644
--- a/arch/arm/mach-mvebu/armada-370-xp.c
+++ b/arch/arm/mach-mvebu/armada-370-xp.c
@@ -23,6 +23,7 @@
23#include <asm/mach/time.h> 23#include <asm/mach/time.h>
24#include "armada-370-xp.h" 24#include "armada-370-xp.h"
25#include "common.h" 25#include "common.h"
26#include "coherency.h"
26 27
27static struct map_desc armada_370_xp_io_desc[] __initdata = { 28static struct map_desc armada_370_xp_io_desc[] __initdata = {
28 { 29 {
@@ -51,6 +52,7 @@ struct sys_timer armada_370_xp_timer = {
51static void __init armada_370_xp_dt_init(void) 52static void __init armada_370_xp_dt_init(void)
52{ 53{
53 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); 54 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
55 coherency_init();
54} 56}
55 57
56static const char * const armada_370_xp_dt_board_dt_compat[] = { 58static const char * const armada_370_xp_dt_board_dt_compat[] = {
@@ -60,6 +62,7 @@ static const char * const armada_370_xp_dt_board_dt_compat[] = {
60}; 62};
61 63
62DT_MACHINE_START(ARMADA_XP_DT, "Marvell Aramada 370/XP (Device Tree)") 64DT_MACHINE_START(ARMADA_XP_DT, "Marvell Aramada 370/XP (Device Tree)")
65 .smp = smp_ops(armada_xp_smp_ops),
63 .init_machine = armada_370_xp_dt_init, 66 .init_machine = armada_370_xp_dt_init,
64 .map_io = armada_370_xp_map_io, 67 .map_io = armada_370_xp_map_io,
65 .init_irq = armada_370_xp_init_irq, 68 .init_irq = armada_370_xp_init_irq,
diff --git a/arch/arm/mach-mvebu/common.h b/arch/arm/mach-mvebu/common.h
index 9285d0496651..aa27bc2ffb60 100644
--- a/arch/arm/mach-mvebu/common.h
+++ b/arch/arm/mach-mvebu/common.h
@@ -20,6 +20,9 @@ void mvebu_restart(char mode, const char *cmd);
20void armada_370_xp_init_irq(void); 20void armada_370_xp_init_irq(void);
21void armada_370_xp_handle_irq(struct pt_regs *regs); 21void armada_370_xp_handle_irq(struct pt_regs *regs);
22 22
23void armada_xp_cpu_die(unsigned int cpu);
23int armada_370_xp_coherency_init(void); 24int armada_370_xp_coherency_init(void);
24int armada_370_xp_pmsu_init(void); 25int armada_370_xp_pmsu_init(void);
26void armada_xp_secondary_startup(void);
27extern struct smp_operations armada_xp_smp_ops;
25#endif 28#endif
diff --git a/arch/arm/mach-mvebu/headsmp.S b/arch/arm/mach-mvebu/headsmp.S
new file mode 100644
index 000000000000..a06e0ede8c08
--- /dev/null
+++ b/arch/arm/mach-mvebu/headsmp.S
@@ -0,0 +1,49 @@
1/*
2 * SMP support: Entry point for secondary CPUs
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Yehuda Yitschak <yehuday@marvell.com>
7 * Gregory CLEMENT <gregory.clement@free-electrons.com>
8 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
9 *
10 * This file is licensed under the terms of the GNU General Public
11 * License version 2. This program is licensed "as is" without any
12 * warranty of any kind, whether express or implied.
13 *
14 * This file implements the assembly entry point for secondary CPUs in
15 * an SMP kernel. The only thing we need to do is to add the CPU to
16 * the coherency fabric by writing to 2 registers. Currently the base
17 * register addresses are hard coded due to the early initialisation
18 * problems.
19 */
20
21#include <linux/linkage.h>
22#include <linux/init.h>
23
24/*
25 * At this stage the secondary CPUs don't have acces yet to the MMU, so
26 * we have to provide physical addresses
27 */
28#define ARMADA_XP_CFB_BASE 0xD0020200
29
30 __CPUINIT
31
32/*
33 * Armada XP specific entry point for secondary CPUs.
34 * We add the CPU to the coherency fabric and then jump to secondary
35 * startup
36 */
37ENTRY(armada_xp_secondary_startup)
38
39 /* Read CPU id */
40 mrc p15, 0, r1, c0, c0, 5
41 and r1, r1, #0xF
42
43 /* Add CPU to coherency fabric */
44 ldr r0, =ARMADA_XP_CFB_BASE
45
46 bl ll_set_cpu_coherent
47 b secondary_startup
48
49ENDPROC(armada_xp_secondary_startup)
diff --git a/arch/arm/mach-mvebu/hotplug.c b/arch/arm/mach-mvebu/hotplug.c
new file mode 100644
index 000000000000..b228b6a80c85
--- /dev/null
+++ b/arch/arm/mach-mvebu/hotplug.c
@@ -0,0 +1,30 @@
1/*
2 * Symmetric Multi Processing (SMP) support for Armada XP
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Lior Amsalem <alior@marvell.com>
7 * Gregory CLEMENT <gregory.clement@free-electrons.com>
8 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
9 *
10 * This file is licensed under the terms of the GNU General Public
11 * License version 2. This program is licensed "as is" without any
12 * warranty of any kind, whether express or implied.
13 */
14#include <linux/kernel.h>
15#include <linux/errno.h>
16#include <linux/smp.h>
17#include <asm/proc-fns.h>
18
19/*
20 * platform-specific code to shutdown a CPU
21 *
22 * Called with IRQs disabled
23 */
24void __ref armada_xp_cpu_die(unsigned int cpu)
25{
26 cpu_do_idle();
27
28 /* We should never return from idle */
29 panic("mvebu: cpu %d unexpectedly exit from shutdown\n", cpu);
30}
diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c
new file mode 100644
index 000000000000..fe16aaf7c19c
--- /dev/null
+++ b/arch/arm/mach-mvebu/platsmp.c
@@ -0,0 +1,122 @@
1/*
2 * Symmetric Multi Processing (SMP) support for Armada XP
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Lior Amsalem <alior@marvell.com>
7 * Yehuda Yitschak <yehuday@marvell.com>
8 * Gregory CLEMENT <gregory.clement@free-electrons.com>
9 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
10 *
11 * This file is licensed under the terms of the GNU General Public
12 * License version 2. This program is licensed "as is" without any
13 * warranty of any kind, whether express or implied.
14 *
15 * The Armada XP SoC has 4 ARMv7 PJ4B CPUs running in full HW coherency
16 * This file implements the routines for preparing the SMP infrastructure
17 * and waking up the secondary CPUs
18 */
19
20#include <linux/init.h>
21#include <linux/smp.h>
22#include <linux/clk.h>
23#include <linux/of.h>
24#include <asm/cacheflush.h>
25#include <asm/smp_plat.h>
26#include "common.h"
27#include "armada-370-xp.h"
28#include "pmsu.h"
29#include "coherency.h"
30
31void __init set_secondary_cpus_clock(void)
32{
33 int thiscpu;
34 unsigned long rate;
35 struct clk *cpu_clk = NULL;
36 struct device_node *np = NULL;
37
38 thiscpu = smp_processor_id();
39 for_each_node_by_type(np, "cpu") {
40 int err;
41 int cpu;
42
43 err = of_property_read_u32(np, "reg", &cpu);
44 if (WARN_ON(err))
45 return;
46
47 if (cpu == thiscpu) {
48 cpu_clk = of_clk_get(np, 0);
49 break;
50 }
51 }
52 if (WARN_ON(IS_ERR(cpu_clk)))
53 return;
54 clk_prepare_enable(cpu_clk);
55 rate = clk_get_rate(cpu_clk);
56
57 /* set all the other CPU clk to the same rate than the boot CPU */
58 for_each_node_by_type(np, "cpu") {
59 int err;
60 int cpu;
61
62 err = of_property_read_u32(np, "reg", &cpu);
63 if (WARN_ON(err))
64 return;
65
66 if (cpu != thiscpu) {
67 cpu_clk = of_clk_get(np, 0);
68 clk_set_rate(cpu_clk, rate);
69 }
70 }
71}
72
73static void __cpuinit armada_xp_secondary_init(unsigned int cpu)
74{
75 armada_xp_mpic_smp_cpu_init();
76}
77
78static int __cpuinit armada_xp_boot_secondary(unsigned int cpu,
79 struct task_struct *idle)
80{
81 pr_info("Booting CPU %d\n", cpu);
82
83 armada_xp_boot_cpu(cpu, armada_xp_secondary_startup);
84
85 return 0;
86}
87
88static void __init armada_xp_smp_init_cpus(void)
89{
90 unsigned int i, ncores;
91 ncores = coherency_get_cpu_count();
92
93 /* Limit possible CPUs to defconfig */
94 if (ncores > nr_cpu_ids) {
95 pr_warn("SMP: %d CPUs physically present. Only %d configured.",
96 ncores, nr_cpu_ids);
97 pr_warn("Clipping CPU count to %d\n", nr_cpu_ids);
98 ncores = nr_cpu_ids;
99 }
100
101 for (i = 0; i < ncores; i++)
102 set_cpu_possible(i, true);
103
104 set_smp_cross_call(armada_mpic_send_doorbell);
105}
106
107void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus)
108{
109 set_secondary_cpus_clock();
110 flush_cache_all();
111 set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0);
112}
113
114struct smp_operations armada_xp_smp_ops __initdata = {
115 .smp_init_cpus = armada_xp_smp_init_cpus,
116 .smp_prepare_cpus = armada_xp_smp_prepare_cpus,
117 .smp_secondary_init = armada_xp_secondary_init,
118 .smp_boot_secondary = armada_xp_boot_secondary,
119#ifdef CONFIG_HOTPLUG_CPU
120 .cpu_die = armada_xp_cpu_die,
121#endif
122};