aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/common/mcpm_entry.c15
-rw-r--r--arch/arm/common/mcpm_platsmp.c10
-rw-r--r--arch/arm/include/asm/mcpm.h31
3 files changed, 56 insertions, 0 deletions
diff --git a/arch/arm/common/mcpm_entry.c b/arch/arm/common/mcpm_entry.c
index 990250965f2c..6c03d0152e7f 100644
--- a/arch/arm/common/mcpm_entry.c
+++ b/arch/arm/common/mcpm_entry.c
@@ -90,6 +90,21 @@ void mcpm_cpu_power_down(void)
90 BUG(); 90 BUG();
91} 91}
92 92
93int mcpm_cpu_power_down_finish(unsigned int cpu, unsigned int cluster)
94{
95 int ret;
96
97 if (WARN_ON_ONCE(!platform_ops || !platform_ops->power_down_finish))
98 return -EUNATCH;
99
100 ret = platform_ops->power_down_finish(cpu, cluster);
101 if (ret)
102 pr_warn("%s: cpu %u, cluster %u failed to power down (%d)\n",
103 __func__, cpu, cluster, ret);
104
105 return ret;
106}
107
93void mcpm_cpu_suspend(u64 expected_residency) 108void mcpm_cpu_suspend(u64 expected_residency)
94{ 109{
95 phys_reset_t phys_reset; 110 phys_reset_t phys_reset;
diff --git a/arch/arm/common/mcpm_platsmp.c b/arch/arm/common/mcpm_platsmp.c
index c0c3cd799ccc..177251a4dd9a 100644
--- a/arch/arm/common/mcpm_platsmp.c
+++ b/arch/arm/common/mcpm_platsmp.c
@@ -56,6 +56,15 @@ static void mcpm_secondary_init(unsigned int cpu)
56 56
57#ifdef CONFIG_HOTPLUG_CPU 57#ifdef CONFIG_HOTPLUG_CPU
58 58
59static int mcpm_cpu_kill(unsigned int cpu)
60{
61 unsigned int pcpu, pcluster;
62
63 cpu_to_pcpu(cpu, &pcpu, &pcluster);
64
65 return !mcpm_cpu_power_down_finish(pcpu, pcluster);
66}
67
59static int mcpm_cpu_disable(unsigned int cpu) 68static int mcpm_cpu_disable(unsigned int cpu)
60{ 69{
61 /* 70 /*
@@ -82,6 +91,7 @@ static struct smp_operations __initdata mcpm_smp_ops = {
82 .smp_boot_secondary = mcpm_boot_secondary, 91 .smp_boot_secondary = mcpm_boot_secondary,
83 .smp_secondary_init = mcpm_secondary_init, 92 .smp_secondary_init = mcpm_secondary_init,
84#ifdef CONFIG_HOTPLUG_CPU 93#ifdef CONFIG_HOTPLUG_CPU
94 .cpu_kill = mcpm_cpu_kill,
85 .cpu_disable = mcpm_cpu_disable, 95 .cpu_disable = mcpm_cpu_disable,
86 .cpu_die = mcpm_cpu_die, 96 .cpu_die = mcpm_cpu_die,
87#endif 97#endif
diff --git a/arch/arm/include/asm/mcpm.h b/arch/arm/include/asm/mcpm.h
index fc82a88f5b69..1cf26010a6f3 100644
--- a/arch/arm/include/asm/mcpm.h
+++ b/arch/arm/include/asm/mcpm.h
@@ -81,10 +81,40 @@ int mcpm_cpu_power_up(unsigned int cpu, unsigned int cluster);
81 * 81 *
82 * This will return if mcpm_platform_register() has not been called 82 * This will return if mcpm_platform_register() has not been called
83 * previously in which case the caller should take appropriate action. 83 * previously in which case the caller should take appropriate action.
84 *
85 * On success, the CPU is not guaranteed to be truly halted until
86 * mcpm_cpu_power_down_finish() subsequently returns non-zero for the
87 * specified cpu. Until then, other CPUs should make sure they do not
88 * trash memory the target CPU might be executing/accessing.
84 */ 89 */
85void mcpm_cpu_power_down(void); 90void mcpm_cpu_power_down(void);
86 91
87/** 92/**
93 * mcpm_cpu_power_down_finish - wait for a specified CPU to halt, and
94 * make sure it is powered off
95 *
96 * @cpu: CPU number within given cluster
97 * @cluster: cluster number for the CPU
98 *
99 * Call this function to ensure that a pending powerdown has taken
100 * effect and the CPU is safely parked before performing non-mcpm
101 * operations that may affect the CPU (such as kexec trashing the
102 * kernel text).
103 *
104 * It is *not* necessary to call this function if you only need to
105 * serialise a pending powerdown with mcpm_cpu_power_up() or a wakeup
106 * event.
107 *
108 * Do not call this function unless the specified CPU has already
109 * called mcpm_cpu_power_down() or has committed to doing so.
110 *
111 * @return:
112 * - zero if the CPU is in a safely parked state
113 * - nonzero otherwise (e.g., timeout)
114 */
115int mcpm_cpu_power_down_finish(unsigned int cpu, unsigned int cluster);
116
117/**
88 * mcpm_cpu_suspend - bring the calling CPU in a suspended state 118 * mcpm_cpu_suspend - bring the calling CPU in a suspended state
89 * 119 *
90 * @expected_residency: duration in microseconds the CPU is expected 120 * @expected_residency: duration in microseconds the CPU is expected
@@ -126,6 +156,7 @@ int mcpm_cpu_powered_up(void);
126struct mcpm_platform_ops { 156struct mcpm_platform_ops {
127 int (*power_up)(unsigned int cpu, unsigned int cluster); 157 int (*power_up)(unsigned int cpu, unsigned int cluster);
128 void (*power_down)(void); 158 void (*power_down)(void);
159 int (*power_down_finish)(unsigned int cpu, unsigned int cluster);
129 void (*suspend)(u64); 160 void (*suspend)(u64);
130 void (*powered_up)(void); 161 void (*powered_up)(void);
131}; 162};