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 | |
| 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')
| -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 | }; | ||
