[PATCH 2/4] ARM: realview: fix CPU hotplug support for SMP platforms
Will Deacon
will.deacon at arm.com
Fri Sep 17 09:12:02 EDT 2010
The current CPU hotplug functions for RealView boards suffer from a number
of problems:
- The location of the SMP/AMP bit in the Auxiliary Control Register is
correct only for 11MPCore.
- The I-cache is not flushed when a core leaves lowpower mode
- The assembly routines for entering/leaving the lowpower state can
be made more readable by using macros for operations such as dsb().
This patch fixes these problems for the RealView boards and has been
tested successfully on the PB11MPCore board.
Cc: Russell King - ARM Linux <linux at arm.linux.org.uk>
Signed-off-by: Will Deacon <will.deacon at arm.com>
---
arch/arm/mach-realview/hotplug.c | 41 ++++++++++++++++++++++++-------------
1 files changed, 26 insertions(+), 15 deletions(-)
diff --git a/arch/arm/mach-realview/hotplug.c b/arch/arm/mach-realview/hotplug.c
index f95521a..b90c15a 100644
--- a/arch/arm/mach-realview/hotplug.c
+++ b/arch/arm/mach-realview/hotplug.c
@@ -8,11 +8,15 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/smp.h>
#include <linux/completion.h>
+#include <mach/board-eb.h>
+#include <mach/board-pbx.h>
+
#include <asm/cacheflush.h>
extern volatile int pen_release;
@@ -21,42 +25,52 @@ static DECLARE_COMPLETION(cpu_killed);
static inline void cpu_enter_lowpower(void)
{
- unsigned int v;
+ unsigned int v, smp_ctrl;
+
+ smp_ctrl = (core_tile_pbxa9mp() || core_tile_a9mp()) ? 0x40 : 0x20;
flush_cache_all();
+ dsb();
asm volatile(
- " mcr p15, 0, %1, c7, c5, 0\n"
- " mcr p15, 0, %1, c7, c10, 4\n"
/*
* Turn off coherency
*/
" mrc p15, 0, %0, c1, c0, 1\n"
- " bic %0, %0, #0x20\n"
+ " bic %0, %0, %1\n"
" mcr p15, 0, %0, c1, c0, 1\n"
+ /* DSB */
+ " mcr p15, 0, %2, c7, c10, 4\n"
+ /* Disable D-cache */
" mrc p15, 0, %0, c1, c0, 0\n"
" bic %0, %0, #0x04\n"
" mcr p15, 0, %0, c1, c0, 0\n"
: "=&r" (v)
- : "r" (0)
- : "cc");
+ : "r" (smp_ctrl), "r" (0)
+ : "memory");
+ isb();
}
static inline void cpu_leave_lowpower(void)
{
- unsigned int v;
+ unsigned int v, smp_ctrl;
+ smp_ctrl = (core_tile_pbxa9mp() || core_tile_a9mp()) ? 0x40 : 0x20;
+
+ flush_cache_all();
+ dsb();
asm volatile( "mrc p15, 0, %0, c1, c0, 0\n"
" orr %0, %0, #0x04\n"
" mcr p15, 0, %0, c1, c0, 0\n"
" mrc p15, 0, %0, c1, c0, 1\n"
- " orr %0, %0, #0x20\n"
+ " orr %0, %0, %1\n"
" mcr p15, 0, %0, c1, c0, 1\n"
: "=&r" (v)
- :
- : "cc");
+ : "r" (smp_ctrl)
+ : "memory");
+ isb();
}
-static inline void platform_do_lowpower(unsigned int cpu)
+static void __ref platform_do_lowpower(unsigned int cpu)
{
/*
* there is no power-control hardware on this platform, so all
@@ -67,10 +81,7 @@ static inline void platform_do_lowpower(unsigned int cpu)
/*
* here's the WFI
*/
- asm(".word 0xe320f003\n"
- :
- :
- : "memory", "cc");
+ asm volatile("wfi" : : : "memory");
if (pen_release == cpu) {
/*
--
1.7.0.4
More information about the linux-arm-kernel
mailing list