diff options
author | Nicolas Pitre <nicolas.pitre@linaro.org> | 2012-11-19 16:02:17 -0500 |
---|---|---|
committer | Nicolas Pitre <nicolas.pitre@linaro.org> | 2013-04-24 10:37:02 -0400 |
commit | 9ff221bad8869f73141c6a3c187afe2e933c991f (patch) | |
tree | 2639d192fdbf042d05ead4e37b2084caf451965a /arch/arm/common | |
parent | 1ae98561b16f305e43151405f226727c00ee52bc (diff) |
ARM: mcpm: generic SMP secondary bringup and hotplug support
Now that the cluster power API is in place, we can use it for SMP secondary
bringup and CPU hotplug in a generic fashion.
Signed-off-by: Nicolas Pitre <nico@linaro.org>
Reviewed-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm/common')
-rw-r--r-- | arch/arm/common/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/common/mcpm_platsmp.c | 87 |
2 files changed, 88 insertions, 1 deletions
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index 9ec273188ccb..48c0ee578174 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile | |||
@@ -11,4 +11,4 @@ obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o | |||
11 | obj-$(CONFIG_SHARP_SCOOP) += scoop.o | 11 | obj-$(CONFIG_SHARP_SCOOP) += scoop.o |
12 | obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o | 12 | obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o |
13 | obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o | 13 | obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o |
14 | obj-$(CONFIG_MCPM) += mcpm_head.o mcpm_entry.o vlock.o | 14 | obj-$(CONFIG_MCPM) += mcpm_head.o mcpm_entry.o mcpm_platsmp.o vlock.o |
diff --git a/arch/arm/common/mcpm_platsmp.c b/arch/arm/common/mcpm_platsmp.c new file mode 100644 index 000000000000..e7e3235b8b64 --- /dev/null +++ b/arch/arm/common/mcpm_platsmp.c | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-vexpress/mcpm_platsmp.c | ||
3 | * | ||
4 | * Created by: Nicolas Pitre, November 2012 | ||
5 | * Copyright: (C) 2012-2013 Linaro Limited | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * Code to handle secondary CPU bringup and hotplug for the cluster power API. | ||
12 | */ | ||
13 | |||
14 | #include <linux/init.h> | ||
15 | #include <linux/smp.h> | ||
16 | #include <linux/spinlock.h> | ||
17 | |||
18 | #include <linux/irqchip/arm-gic.h> | ||
19 | |||
20 | #include <asm/mcpm.h> | ||
21 | #include <asm/smp.h> | ||
22 | #include <asm/smp_plat.h> | ||
23 | |||
24 | static void __init simple_smp_init_cpus(void) | ||
25 | { | ||
26 | } | ||
27 | |||
28 | static int __cpuinit mcpm_boot_secondary(unsigned int cpu, struct task_struct *idle) | ||
29 | { | ||
30 | unsigned int mpidr, pcpu, pcluster, ret; | ||
31 | extern void secondary_startup(void); | ||
32 | |||
33 | mpidr = cpu_logical_map(cpu); | ||
34 | pcpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); | ||
35 | pcluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); | ||
36 | pr_debug("%s: logical CPU %d is physical CPU %d cluster %d\n", | ||
37 | __func__, cpu, pcpu, pcluster); | ||
38 | |||
39 | mcpm_set_entry_vector(pcpu, pcluster, NULL); | ||
40 | ret = mcpm_cpu_power_up(pcpu, pcluster); | ||
41 | if (ret) | ||
42 | return ret; | ||
43 | mcpm_set_entry_vector(pcpu, pcluster, secondary_startup); | ||
44 | arch_send_wakeup_ipi_mask(cpumask_of(cpu)); | ||
45 | dsb_sev(); | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static void __cpuinit mcpm_secondary_init(unsigned int cpu) | ||
50 | { | ||
51 | mcpm_cpu_powered_up(); | ||
52 | gic_secondary_init(0); | ||
53 | } | ||
54 | |||
55 | #ifdef CONFIG_HOTPLUG_CPU | ||
56 | |||
57 | static int mcpm_cpu_disable(unsigned int cpu) | ||
58 | { | ||
59 | /* | ||
60 | * We assume all CPUs may be shut down. | ||
61 | * This would be the hook to use for eventual Secure | ||
62 | * OS migration requests as described in the PSCI spec. | ||
63 | */ | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static void mcpm_cpu_die(unsigned int cpu) | ||
68 | { | ||
69 | unsigned int mpidr, pcpu, pcluster; | ||
70 | mpidr = read_cpuid_mpidr(); | ||
71 | pcpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); | ||
72 | pcluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); | ||
73 | mcpm_set_entry_vector(pcpu, pcluster, NULL); | ||
74 | mcpm_cpu_power_down(); | ||
75 | } | ||
76 | |||
77 | #endif | ||
78 | |||
79 | struct smp_operations __initdata mcpm_smp_ops = { | ||
80 | .smp_init_cpus = simple_smp_init_cpus, | ||
81 | .smp_boot_secondary = mcpm_boot_secondary, | ||
82 | .smp_secondary_init = mcpm_secondary_init, | ||
83 | #ifdef CONFIG_HOTPLUG_CPU | ||
84 | .cpu_disable = mcpm_cpu_disable, | ||
85 | .cpu_die = mcpm_cpu_die, | ||
86 | #endif | ||
87 | }; | ||