From 222de7bfdf135e33f8708c6b287c888c8ff100cc Mon Sep 17 00:00:00 2001 From: Marc Gonzalez Date: Wed, 29 Jun 2016 14:21:42 +0200 Subject: ARM: tango: add HOTPLUG_CPU support cpu_die() and cpu_kill() are implemented in firmware. Signed-off-by: Marc Gonzalez Signed-off-by: Olof Johansson --- arch/arm/mach-tango/platsmp.c | 36 ++++++++++++++++++++++++++++++++++++ arch/arm/mach-tango/smc.h | 4 +++- 2 files changed, 39 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-tango') diff --git a/arch/arm/mach-tango/platsmp.c b/arch/arm/mach-tango/platsmp.c index a21f55e000d2..8380699d4fa3 100644 --- a/arch/arm/mach-tango/platsmp.c +++ b/arch/arm/mach-tango/platsmp.c @@ -1,3 +1,4 @@ +#include #include #include #include "smc.h" @@ -9,8 +10,43 @@ static int tango_boot_secondary(unsigned int cpu, struct task_struct *idle) return 0; } +#ifdef CONFIG_HOTPLUG_CPU +/* + * cpu_kill() and cpu_die() run concurrently on different cores. + * Firmware will only "kill" a core once it has properly "died". + * Try a few times to kill a core before giving up, and sleep + * between tries to give that core enough time to die. + */ +static int tango_cpu_kill(unsigned int cpu) +{ + int i, err; + + for (i = 0; i < 10; ++i) { + msleep(10); + err = tango_aux_core_kill(cpu); + if (!err) + return true; + } + + return false; +} + +static void tango_cpu_die(unsigned int cpu) +{ + while (tango_aux_core_die(cpu) < 0) + cpu_relax(); + + panic("cpu %d failed to die\n", cpu); +} +#else +#define tango_cpu_kill NULL +#define tango_cpu_die NULL +#endif + static const struct smp_operations tango_smp_ops __initconst = { .smp_boot_secondary = tango_boot_secondary, + .cpu_kill = tango_cpu_kill, + .cpu_die = tango_cpu_die, }; CPU_METHOD_OF_DECLARE(tango4_smp, "sigma,tango4-smp", &tango_smp_ops); diff --git a/arch/arm/mach-tango/smc.h b/arch/arm/mach-tango/smc.h index 7a4af35cc390..3d31f984f44c 100644 --- a/arch/arm/mach-tango/smc.h +++ b/arch/arm/mach-tango/smc.h @@ -2,4 +2,6 @@ extern int tango_smc(unsigned int val, unsigned int service); #define tango_set_l2_control(val) tango_smc(val, 0x102) #define tango_start_aux_core(val) tango_smc(val, 0x104) -#define tango_set_aux_boot_addr(val) tango_smc((unsigned int)val, 0x105) +#define tango_set_aux_boot_addr(val) tango_smc(val, 0x105) +#define tango_aux_core_die(val) tango_smc(val, 0x121) +#define tango_aux_core_kill(val) tango_smc(val, 0x122) -- cgit v1.2.3 From 8264dde537b3de1a1d074d4034648bd9adfe9a6f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 6 Jul 2016 22:04:42 +0200 Subject: ARM: tango: fix CONFIG_HOTPLUG_CPU=n build Building with CONFIG_HOTPLUG_CPU disabled fails for mach-tango: include/linux/stddef.h:7:14: error: excess elements in struct initializer [-Werror] #define NULL ((void *)0) arch/arm/mach-tango/platsmp.c:48:15: note: in expansion of macro 'tango_cpu_kill' .cpu_kill = tango_cpu_kill, the problem as that the .cpu_kill and .cpu_die struct members are unavailable and we must not try to assign them in this configuration. Hiding the two (as all other platforms do too) lets us get rid of the #else clause as well. Signed-off-by: Arnd Bergmann Signed-off-by: Olof Johansson --- arch/arm/mach-tango/platsmp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch/arm/mach-tango') diff --git a/arch/arm/mach-tango/platsmp.c b/arch/arm/mach-tango/platsmp.c index 8380699d4fa3..98c62a4a8623 100644 --- a/arch/arm/mach-tango/platsmp.c +++ b/arch/arm/mach-tango/platsmp.c @@ -38,15 +38,14 @@ static void tango_cpu_die(unsigned int cpu) panic("cpu %d failed to die\n", cpu); } -#else -#define tango_cpu_kill NULL -#define tango_cpu_die NULL #endif static const struct smp_operations tango_smp_ops __initconst = { .smp_boot_secondary = tango_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU .cpu_kill = tango_cpu_kill, .cpu_die = tango_cpu_die, +#endif }; CPU_METHOD_OF_DECLARE(tango4_smp, "sigma,tango4-smp", &tango_smp_ops); -- cgit v1.2.3 From a30eceb7a59daa2d92cca7f2f30b9bd91a8d7111 Mon Sep 17 00:00:00 2001 From: Marc Gonzalez Date: Thu, 7 Jul 2016 15:08:14 +0200 Subject: ARM: tango: add Suspend-to-RAM support Ask firmware to put RAM in self-refresh mode and power system down. echo mem > /sys/power/state See Documentation/power/states.txt Signed-off-by: Marc Gonzalez Signed-off-by: Arnd Bergmann --- arch/arm/mach-tango/Makefile | 1 + arch/arm/mach-tango/pm.c | 32 ++++++++++++++++++++++++++++++++ arch/arm/mach-tango/smc.h | 1 + 3 files changed, 34 insertions(+) create mode 100644 arch/arm/mach-tango/pm.c (limited to 'arch/arm/mach-tango') diff --git a/arch/arm/mach-tango/Makefile b/arch/arm/mach-tango/Makefile index f33935e42e77..204fcd9fe180 100644 --- a/arch/arm/mach-tango/Makefile +++ b/arch/arm/mach-tango/Makefile @@ -3,3 +3,4 @@ AFLAGS_smc.o := -Wa,-march=armv7-a$(plus_sec) obj-y += setup.o smc.o obj-$(CONFIG_SMP) += platsmp.o +obj-$(CONFIG_SUSPEND) += pm.o diff --git a/arch/arm/mach-tango/pm.c b/arch/arm/mach-tango/pm.c new file mode 100644 index 000000000000..b05c6d6f99d0 --- /dev/null +++ b/arch/arm/mach-tango/pm.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include "smc.h" + +static int tango_pm_powerdown(unsigned long arg) +{ + tango_suspend(virt_to_phys(cpu_resume)); + + return -EIO; /* tango_suspend has failed */ +} + +static int tango_pm_enter(suspend_state_t state) +{ + if (state == PM_SUSPEND_MEM) + return cpu_suspend(0, tango_pm_powerdown); + + return -EINVAL; +} + +static const struct platform_suspend_ops tango_pm_ops = { + .enter = tango_pm_enter, + .valid = suspend_valid_only_mem, +}; + +static int __init tango_pm_init(void) +{ + suspend_set_ops(&tango_pm_ops); + return 0; +} + +late_initcall(tango_pm_init); diff --git a/arch/arm/mach-tango/smc.h b/arch/arm/mach-tango/smc.h index 3d31f984f44c..57919539da1b 100644 --- a/arch/arm/mach-tango/smc.h +++ b/arch/arm/mach-tango/smc.h @@ -3,5 +3,6 @@ extern int tango_smc(unsigned int val, unsigned int service); #define tango_set_l2_control(val) tango_smc(val, 0x102) #define tango_start_aux_core(val) tango_smc(val, 0x104) #define tango_set_aux_boot_addr(val) tango_smc(val, 0x105) +#define tango_suspend(val) tango_smc(val, 0x120) #define tango_aux_core_die(val) tango_smc(val, 0x121) #define tango_aux_core_kill(val) tango_smc(val, 0x122) -- cgit v1.2.3