diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-07-26 13:19:43 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-07-27 10:48:42 +0100 |
commit | 5388a6b266e9c3357353332ba0cd5549082887f1 (patch) | |
tree | 9d035a01bb75fa466e70cd9590eb963a30f3d53d | |
parent | 9ca03a21e320a6bf44559323527aba704bcc8772 (diff) |
ARM: SMP: Always enable clock event broadcast support
The TWD local timers are unable to wake up the CPU when it is placed
into a low power mode, eg. C3. Therefore, we need to adapt things
such that the TWD code can cope with this.
We do this by always providing a broadcast tick function, and marking
the fact that the TWD local timer will stop in low power modes. This
means that when the CPU is placed into a low power mode, the core
timer code marks this fact, and allows an IPI to be given to the core.
Tested-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | arch/arm/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/kernel/smp.c | 6 | ||||
-rw-r--r-- | arch/arm/kernel/smp_twd.c | 3 |
3 files changed, 8 insertions, 3 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 88b4f389ab35..157b08aa0366 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -56,7 +56,7 @@ config GENERIC_CLOCKEVENTS config GENERIC_CLOCKEVENTS_BROADCAST bool depends on GENERIC_CLOCKEVENTS - default y if SMP && !LOCAL_TIMERS + default y if SMP config HAVE_TCM bool diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index b8c3d0f689d9..0170e248a1dd 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -429,7 +429,11 @@ static void smp_timer_broadcast(const struct cpumask *mask) { send_ipi_message(mask, IPI_TIMER); } +#else +#define smp_timer_broadcast NULL +#endif +#ifndef CONFIG_LOCAL_TIMERS static void broadcast_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { @@ -444,7 +448,6 @@ static void local_timer_setup(struct clock_event_device *evt) evt->rating = 400; evt->mult = 1; evt->set_mode = broadcast_timer_set_mode; - evt->broadcast = smp_timer_broadcast; clockevents_register_device(evt); } @@ -456,6 +459,7 @@ void __cpuinit percpu_timer_setup(void) struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); evt->cpumask = cpumask_of(cpu); + evt->broadcast = smp_timer_broadcast; local_timer_setup(evt); } diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 7c5f0c024db7..35882fbf37f9 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -132,7 +132,8 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) twd_calibrate_rate(); clk->name = "local_timer"; - clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; + clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_C3STOP; clk->rating = 350; clk->set_mode = twd_set_mode; clk->set_next_event = twd_set_next_event; |