diff options
author | Paul Mundt <lethal@linux-sh.org> | 2008-08-06 18:37:07 +0900 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2008-09-08 10:35:03 +0900 |
commit | 8c24594deab89a484879bee270e948f0a556ed75 (patch) | |
tree | 2b0c95a4d53614e1118ea20aa7e705d983ddb23f /arch/sh/kernel | |
parent | 6f52707e6882eb3bc6920c3f59beb05d23d68354 (diff) |
sh: generic clockevent broadcast support.
This hooks up GENERIC_CLOCKEVENTS_BROADCAST and a dummy local timer,
which we call in to from the timer IPI when no other local timer is
provided.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r-- | arch/sh/kernel/smp.c | 7 | ||||
-rw-r--r-- | arch/sh/kernel/time_32.c | 9 | ||||
-rw-r--r-- | arch/sh/kernel/timers/Makefile | 1 | ||||
-rw-r--r-- | arch/sh/kernel/timers/timer-broadcast.c | 57 |
4 files changed, 70 insertions, 4 deletions
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 9cb3734dbd4..c55d314166c 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -84,9 +84,12 @@ asmlinkage void __cpuinit start_secondary(void) local_irq_enable(); + cpu = smp_processor_id(); + + /* Enable local timers */ + local_timer_setup(cpu); calibrate_delay(); - cpu = smp_processor_id(); smp_store_cpu_info(cpu); cpu_set(cpu, cpu_online_map); @@ -195,7 +198,7 @@ void smp_timer_broadcast(cpumask_t mask) static void ipi_timer(void) { irq_enter(); - /* XXX ... */ + local_timer_interrupt(); irq_exit(); } diff --git a/arch/sh/kernel/time_32.c b/arch/sh/kernel/time_32.c index 0758b5ee818..decee0a453a 100644 --- a/arch/sh/kernel/time_32.c +++ b/arch/sh/kernel/time_32.c @@ -1,9 +1,9 @@ /* - * arch/sh/kernel/time.c + * arch/sh/kernel/time_32.c * * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> - * Copyright (C) 2002 - 2007 Paul Mundt + * Copyright (C) 2002 - 2008 Paul Mundt * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> * * Some code taken from i386 version. @@ -16,6 +16,7 @@ #include <linux/timex.h> #include <linux/sched.h> #include <linux/clockchips.h> +#include <linux/smp.h> #include <asm/clock.h> #include <asm/rtc.h> #include <asm/timer.h> @@ -260,6 +261,10 @@ void __init time_init(void) sys_timer = get_sys_timer(); printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); +#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST + local_timer_setup(smp_processor_id()); +#endif + if (sys_timer->ops->read) clocksource_sh.read = sys_timer->ops->read; diff --git a/arch/sh/kernel/timers/Makefile b/arch/sh/kernel/timers/Makefile index bcf244ff6a1..0b7f8577193 100644 --- a/arch/sh/kernel/timers/Makefile +++ b/arch/sh/kernel/timers/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_SH_TMU) += timer-tmu.o obj-$(CONFIG_SH_MTU2) += timer-mtu2.o obj-$(CONFIG_SH_CMT) += timer-cmt.o +obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += timer-broadcast.o diff --git a/arch/sh/kernel/timers/timer-broadcast.c b/arch/sh/kernel/timers/timer-broadcast.c new file mode 100644 index 00000000000..c2317635230 --- /dev/null +++ b/arch/sh/kernel/timers/timer-broadcast.c @@ -0,0 +1,57 @@ +/* + * Dummy local timer + * + * Copyright (C) 2008 Paul Mundt + * + * cloned from: + * + * linux/arch/arm/mach-realview/localtimer.c + * + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * 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/delay.h> +#include <linux/device.h> +#include <linux/smp.h> +#include <linux/jiffies.h> +#include <linux/percpu.h> +#include <linux/clockchips.h> +#include <linux/irq.h> + +static DEFINE_PER_CPU(struct clock_event_device, local_clockevent); + +/* + * Used on SMP for either the local timer or SMP_MSG_TIMER + */ +void local_timer_interrupt(void) +{ + struct clock_event_device *clk = &__get_cpu_var(local_clockevent); + + clk->event_handler(clk); +} + +static void dummy_timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *clk) +{ +} + +void __cpuinit local_timer_setup(unsigned int cpu) +{ + struct clock_event_device *clk = &per_cpu(local_clockevent, cpu); + + clk->name = "dummy_timer"; + clk->features = CLOCK_EVT_FEAT_DUMMY; + clk->rating = 200; + clk->mult = 1; + clk->set_mode = dummy_timer_set_mode; + clk->broadcast = smp_timer_broadcast; + clk->cpumask = cpumask_of_cpu(cpu); + + clockevents_register_device(clk); +} |