| From ae7f732e421913a955120f5f221fd6917cd87fde Mon Sep 17 00:00:00 2001 |
| From: Magnus Damm <damm@opensource.se> |
| Date: Wed, 31 Jul 2013 16:07:49 +0900 |
| Subject: ARM: shmobile: Add shared SCU CPU Hotplug code |
| |
| Add CPU Hotplug functions for SCU equipped mach-shmobile SoCs. |
| |
| The functions shmobile_smp_scu_cpu_die() together with |
| shmobile_smp_scu_cpu_kill() perform basic shutdown and |
| allows checking of shutdown status. These are written |
| to work together with SMP boot code in headsmp-scu.S. |
| |
| Signed-off-by: Magnus Damm <damm@opensource.se> |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| (cherry picked from commit e7b1c96384181d690950530f5a64167965226744) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| arch/arm/mach-shmobile/include/mach/common.h | 2 ++ |
| arch/arm/mach-shmobile/platsmp-scu.c | 45 ++++++++++++++++++++++++++++ |
| 2 files changed, 47 insertions(+) |
| |
| diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h |
| index 08d7cacc..2731dd71 100644 |
| --- a/arch/arm/mach-shmobile/include/mach/common.h |
| +++ b/arch/arm/mach-shmobile/include/mach/common.h |
| @@ -13,6 +13,8 @@ extern void shmobile_boot_scu(void); |
| extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus); |
| extern int shmobile_smp_scu_boot_secondary(unsigned int cpu, |
| struct task_struct *idle); |
| +extern void shmobile_smp_scu_cpu_die(unsigned int cpu); |
| +extern int shmobile_smp_scu_cpu_kill(unsigned int cpu); |
| struct clk; |
| extern int shmobile_clk_init(void); |
| extern void shmobile_handle_irq_intc(struct pt_regs *); |
| diff --git a/arch/arm/mach-shmobile/platsmp-scu.c b/arch/arm/mach-shmobile/platsmp-scu.c |
| index 8f478e4d..7a0c066d 100644 |
| --- a/arch/arm/mach-shmobile/platsmp-scu.c |
| +++ b/arch/arm/mach-shmobile/platsmp-scu.c |
| @@ -7,9 +7,11 @@ |
| * it under the terms of the GNU General Public License version 2 as |
| * published by the Free Software Foundation. |
| */ |
| +#include <linux/delay.h> |
| #include <linux/init.h> |
| #include <linux/io.h> |
| #include <linux/smp.h> |
| +#include <asm/cacheflush.h> |
| #include <asm/smp_plat.h> |
| #include <asm/smp_scu.h> |
| #include <mach/common.h> |
| @@ -29,3 +31,46 @@ int shmobile_smp_scu_boot_secondary(unsigned int cpu, struct task_struct *idle) |
| /* do nothing for now */ |
| return 0; |
| } |
| + |
| +#ifdef CONFIG_HOTPLUG_CPU |
| +void shmobile_smp_scu_cpu_die(unsigned int cpu) |
| +{ |
| + dsb(); |
| + flush_cache_all(); |
| + |
| + /* disable cache coherency */ |
| + scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF); |
| + |
| + /* Endless loop until reset */ |
| + while (1) |
| + cpu_do_idle(); |
| +} |
| + |
| +static int shmobile_smp_scu_psr_core_disabled(int cpu) |
| +{ |
| + unsigned long mask = SCU_PM_POWEROFF << (cpu * 8); |
| + |
| + if ((__raw_readl(shmobile_scu_base + 8) & mask) == mask) |
| + return 1; |
| + |
| + return 0; |
| +} |
| + |
| +int shmobile_smp_scu_cpu_kill(unsigned int cpu) |
| +{ |
| + int k; |
| + |
| + /* this function is running on another CPU than the offline target, |
| + * here we need wait for shutdown code in platform_cpu_die() to |
| + * finish before asking SoC-specific code to power off the CPU core. |
| + */ |
| + for (k = 0; k < 1000; k++) { |
| + if (shmobile_smp_scu_psr_core_disabled(cpu)) |
| + return 1; |
| + |
| + mdelay(1); |
| + } |
| + |
| + return 0; |
| +} |
| +#endif |
| -- |
| 1.8.4.3.gca3854a |
| |