Skip to content

Commit

Permalink
sh: generic clockevent broadcast support.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Paul Mundt committed Sep 8, 2008
1 parent 6f52707 commit 8c24594
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 4 deletions.
4 changes: 4 additions & 0 deletions arch/sh/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
3 changes: 3 additions & 0 deletions arch/sh/include/asm/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 5 additions & 2 deletions arch/sh/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -195,7 +198,7 @@ void smp_timer_broadcast(cpumask_t mask)
static void ipi_timer(void)
{
irq_enter();
/* XXX ... */
local_timer_interrupt();
irq_exit();
}

Expand Down
9 changes: 7 additions & 2 deletions arch/sh/kernel/time_32.c
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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>
Expand Down Expand Up @@ -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;

Expand Down
1 change: 1 addition & 0 deletions arch/sh/kernel/timers/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
57 changes: 57 additions & 0 deletions arch/sh/kernel/timers/timer-broadcast.c
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit 8c24594

Please sign in to comment.