sh: generic clockevent broadcast support.
authorPaul Mundt <lethal@linux-sh.org>
Wed, 6 Aug 2008 09:37:07 +0000 (18:37 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Mon, 8 Sep 2008 01:35:03 +0000 (10:35 +0900)
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>
arch/sh/Kconfig
arch/sh/include/asm/smp.h
arch/sh/kernel/smp.c
arch/sh/kernel/time_32.c
arch/sh/kernel/timers/Makefile
arch/sh/kernel/timers/timer-broadcast.c [new file with mode: 0644]

index 5131d50f851ac44f0a81709708023e2c6f00a5af..399664c1f386c4ca64ab767d9d3916d6a132bbab 100644 (file)
@@ -66,6 +66,9 @@ config GENERIC_TIME
 config GENERIC_CLOCKEVENTS
        def_bool n
 
+config GENERIC_CLOCKEVENTS_BROADCAST
+       bool
+
 config GENERIC_LOCKBREAK
        def_bool y
        depends on SMP && PREEMPT
@@ -323,6 +326,7 @@ config CPU_SUBTYPE_SHX3
        select ARCH_SPARSEMEM_ENABLE
        select SYS_SUPPORTS_NUMA
        select SYS_SUPPORTS_SMP
+       select GENERIC_CLOCKEVENTS_BROADCAST
 
 # SH4AL-DSP Processor Support
 
index 9d22cda67c29ef7e8ea4a44f534d484b81fb8925..85b660c17eb070e230b7ce3e0dcac1c7f7ab27c8 100644 (file)
@@ -33,6 +33,9 @@ enum {
 void smp_message_recv(unsigned int msg);
 void smp_timer_broadcast(cpumask_t mask);
 
+void local_timer_interrupt(void);
+void local_timer_setup(unsigned int cpu);
+
 void plat_smp_setup(void);
 void plat_prepare_cpus(unsigned int max_cpus);
 int plat_smp_processor_id(void);
index 9cb3734dbd49d3f24aeba3e09b5f7c87afb68f5f..c55d314166c79bd8802464d1023fdd931e6967cf 100644 (file)
@@ -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();
 }
 
index 0758b5ee818079b3fd2f3948da6dfe7af5825d0b..decee0a453ab0b949bf996eb31ed60a95c0bb178 100644 (file)
@@ -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;
 
index bcf244ff6a128a90698257804490f9d6c3d4be97..0b7f8577193ffb2a10d268309b12f607f3a0ad7f 100644 (file)
@@ -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 (file)
index 0000000..c231763
--- /dev/null
@@ -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);
+}