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>
This commit is contained in:
Paul Mundt 2008-08-06 18:37:07 +09:00
parent 6f52707e68
commit 8c24594dea
6 changed files with 77 additions and 4 deletions

View File

@ -66,6 +66,9 @@ config GENERIC_TIME
config GENERIC_CLOCKEVENTS config GENERIC_CLOCKEVENTS
def_bool n def_bool n
config GENERIC_CLOCKEVENTS_BROADCAST
bool
config GENERIC_LOCKBREAK config GENERIC_LOCKBREAK
def_bool y def_bool y
depends on SMP && PREEMPT depends on SMP && PREEMPT
@ -323,6 +326,7 @@ config CPU_SUBTYPE_SHX3
select ARCH_SPARSEMEM_ENABLE select ARCH_SPARSEMEM_ENABLE
select SYS_SUPPORTS_NUMA select SYS_SUPPORTS_NUMA
select SYS_SUPPORTS_SMP select SYS_SUPPORTS_SMP
select GENERIC_CLOCKEVENTS_BROADCAST
# SH4AL-DSP Processor Support # SH4AL-DSP Processor Support

View File

@ -33,6 +33,9 @@ enum {
void smp_message_recv(unsigned int msg); void smp_message_recv(unsigned int msg);
void smp_timer_broadcast(cpumask_t mask); 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_smp_setup(void);
void plat_prepare_cpus(unsigned int max_cpus); void plat_prepare_cpus(unsigned int max_cpus);
int plat_smp_processor_id(void); int plat_smp_processor_id(void);

View File

@ -84,9 +84,12 @@ asmlinkage void __cpuinit start_secondary(void)
local_irq_enable(); local_irq_enable();
cpu = smp_processor_id();
/* Enable local timers */
local_timer_setup(cpu);
calibrate_delay(); calibrate_delay();
cpu = smp_processor_id();
smp_store_cpu_info(cpu); smp_store_cpu_info(cpu);
cpu_set(cpu, cpu_online_map); cpu_set(cpu, cpu_online_map);
@ -195,7 +198,7 @@ void smp_timer_broadcast(cpumask_t mask)
static void ipi_timer(void) static void ipi_timer(void)
{ {
irq_enter(); irq_enter();
/* XXX ... */ local_timer_interrupt();
irq_exit(); irq_exit();
} }

View 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) 1999 Tetsuya Okada & Niibe Yutaka
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> * 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> * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
* *
* Some code taken from i386 version. * Some code taken from i386 version.
@ -16,6 +16,7 @@
#include <linux/timex.h> #include <linux/timex.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/clockchips.h> #include <linux/clockchips.h>
#include <linux/smp.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/rtc.h> #include <asm/rtc.h>
#include <asm/timer.h> #include <asm/timer.h>
@ -260,6 +261,10 @@ void __init time_init(void)
sys_timer = get_sys_timer(); sys_timer = get_sys_timer();
printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); 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) if (sys_timer->ops->read)
clocksource_sh.read = sys_timer->ops->read; clocksource_sh.read = sys_timer->ops->read;

View File

@ -8,3 +8,4 @@ obj-$(CONFIG_SH_TMU) += timer-tmu.o
obj-$(CONFIG_SH_MTU2) += timer-mtu2.o obj-$(CONFIG_SH_MTU2) += timer-mtu2.o
obj-$(CONFIG_SH_CMT) += timer-cmt.o obj-$(CONFIG_SH_CMT) += timer-cmt.o
obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) += timer-broadcast.o

View File

@ -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);
}