aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-shmobile/smp-sh73a0.c
diff options
context:
space:
mode:
authorBastian Hecht <hechtb@gmail.com>2013-01-09 14:41:52 -0500
committerSimon Horman <horms+renesas@verge.net.au>2013-01-24 22:43:48 -0500
commit20aa11358d52e1a3fc037d601ffe704e6f55c5fb (patch)
tree225f63a404bf6b1a5fe5b85468157e578ea37120 /arch/arm/mach-shmobile/smp-sh73a0.c
parent33419a69a56436dda8e9187cf09ff0bde74d8a01 (diff)
ARM: SH-Mobile: sh73a0: Add CPU Hotplug
Add the capability to add and remove CPUs on the fly. The Cortex-A9 offers the possibility to take single cores out of the MP Core. We add this capabilty taking care that caches are kept coherent. For verifying the shutdown we rely on the internal SH73A0 Power Status Register PSTR. Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com> Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Diffstat (limited to 'arch/arm/mach-shmobile/smp-sh73a0.c')
-rw-r--r--arch/arm/mach-shmobile/smp-sh73a0.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index 430b44ea85f2..9812ea3255c9 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -25,6 +25,7 @@
25#include <linux/delay.h> 25#include <linux/delay.h>
26#include <linux/irqchip/arm-gic.h> 26#include <linux/irqchip/arm-gic.h>
27#include <mach/common.h> 27#include <mach/common.h>
28#include <asm/cacheflush.h>
28#include <asm/smp_plat.h> 29#include <asm/smp_plat.h>
29#include <mach/sh73a0.h> 30#include <mach/sh73a0.h>
30#include <asm/smp_scu.h> 31#include <asm/smp_scu.h>
@@ -36,6 +37,8 @@
36#define SBAR IOMEM(0xe6180020) 37#define SBAR IOMEM(0xe6180020)
37#define APARMBAREA IOMEM(0xe6f10020) 38#define APARMBAREA IOMEM(0xe6f10020)
38 39
40#define PSTR_SHUTDOWN_MODE 3
41
39static void __iomem *scu_base_addr(void) 42static void __iomem *scu_base_addr(void)
40{ 43{
41 return (void __iomem *)0xf0000000; 44 return (void __iomem *)0xf0000000;
@@ -92,16 +95,20 @@ static void __init sh73a0_smp_init_cpus(void)
92 shmobile_smp_init_cpus(ncores); 95 shmobile_smp_init_cpus(ncores);
93} 96}
94 97
95static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu) 98#ifdef CONFIG_HOTPLUG_CPU
99static int sh73a0_cpu_kill(unsigned int cpu)
96{ 100{
101
97 int k; 102 int k;
103 u32 pstr;
98 104
99 /* this function is running on another CPU than the offline target, 105 /*
100 * here we need wait for shutdown code in platform_cpu_die() to 106 * wait until the power status register confirms the shutdown of the
101 * finish before asking SoC-specific code to power off the CPU core. 107 * offline target
102 */ 108 */
103 for (k = 0; k < 1000; k++) { 109 for (k = 0; k < 1000; k++) {
104 if (shmobile_cpu_is_dead(cpu)) 110 pstr = (__raw_readl(PSTR) >> (4 * cpu)) & 3;
111 if (pstr == PSTR_SHUTDOWN_MODE)
105 return 1; 112 return 1;
106 113
107 mdelay(1); 114 mdelay(1);
@@ -110,6 +117,23 @@ static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu)
110 return 0; 117 return 0;
111} 118}
112 119
120static void sh73a0_cpu_die(unsigned int cpu)
121{
122 /*
123 * The ARM MPcore does not issue a cache coherency request for the L1
124 * cache when powering off single CPUs. We must take care of this and
125 * further caches.
126 */
127 dsb();
128 flush_cache_all();
129
130 /* Set power off mode. This takes the CPU out of the MP cluster */
131 scu_power_mode(scu_base_addr(), SCU_PM_POWEROFF);
132
133 /* Enter shutdown mode */
134 cpu_do_idle();
135}
136#endif /* CONFIG_HOTPLUG_CPU */
113 137
114struct smp_operations sh73a0_smp_ops __initdata = { 138struct smp_operations sh73a0_smp_ops __initdata = {
115 .smp_init_cpus = sh73a0_smp_init_cpus, 139 .smp_init_cpus = sh73a0_smp_init_cpus,
@@ -118,7 +142,7 @@ struct smp_operations sh73a0_smp_ops __initdata = {
118 .smp_boot_secondary = sh73a0_boot_secondary, 142 .smp_boot_secondary = sh73a0_boot_secondary,
119#ifdef CONFIG_HOTPLUG_CPU 143#ifdef CONFIG_HOTPLUG_CPU
120 .cpu_kill = sh73a0_cpu_kill, 144 .cpu_kill = sh73a0_cpu_kill,
121 .cpu_die = shmobile_cpu_die, 145 .cpu_die = sh73a0_cpu_die,
122 .cpu_disable = shmobile_cpu_disable, 146 .cpu_disable = shmobile_cpu_disable,
123#endif 147#endif
124}; 148};