Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc28248e authored by Russell King's avatar Russell King Committed by Russell King
Browse files

[ARM] smp: move core localtimer support out of platform specific files

parent ee348d5a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -859,6 +859,7 @@ source "kernel/time/Kconfig"
config SMP
	bool "Symmetric Multi-Processing (EXPERIMENTAL)"
	depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP)
	depends on GENERIC_CLOCKEVENTS
	select USE_GENERIC_SMP_HELPERS
	help
	  This enables support for systems with more than one CPU. If you have
+51 −0
Original line number Diff line number Diff line
/*
 *  arch/arm/include/asm/localtimer.h
 *
 *  Copyright (C) 2004-2005 ARM Ltd.
 *
 * 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.
 */
#ifndef __ASM_ARM_LOCALTIMER_H
#define __ASM_ARM_LOCALTIMER_H

struct clock_event_device;

/*
 * Setup a per-cpu timer, whether it be a local timer or dummy broadcast
 */
void percpu_timer_setup(void);

/*
 * Called from assembly, this is the local timer IRQ handler
 */
asmlinkage void do_local_timer(struct pt_regs *);


#ifdef CONFIG_LOCAL_TIMERS
/*
 * Platform provides this to acknowledge a local timer IRQ.
 * Returns true if the local timer IRQ is to be processed.
 */
int local_timer_ack(void);

/*
 * Stop a local timer interrupt.
 */
void local_timer_stop(void);

/*
 * Setup a local timer interrupt for a CPU.
 */
void local_timer_setup(struct clock_event_device *);

#else

static inline void local_timer_stop(void)
{
}

#endif

#endif
+0 −40
Original line number Diff line number Diff line
@@ -55,11 +55,6 @@ extern void smp_store_cpu_info(unsigned int cpuid);
 */
extern void smp_cross_call(const struct cpumask *mask);

/*
 * Broadcast a clock event to other CPUs.
 */
extern void smp_timer_broadcast(const struct cpumask *mask);

/*
 * Boot a secondary CPU, and assign it the specified idle task.
 * This also gives us the initial stack to use for this CPU.
@@ -100,44 +95,9 @@ extern void arch_send_call_function_single_ipi(int cpu);
extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
#define arch_send_call_function_ipi_mask arch_send_call_function_ipi_mask

/*
 * Local timer interrupt handling function (can be IPI'ed).
 */
extern void local_timer_interrupt(void);

#ifdef CONFIG_LOCAL_TIMERS

/*
 * Stop a local timer interrupt.
 */
extern void local_timer_stop(void);

/*
 * Platform provides this to acknowledge a local timer IRQ
 */
extern int local_timer_ack(void);

#else

static inline void local_timer_stop(void)
{
}

#endif

/*
 * Setup a local timer interrupt for a CPU.
 */
extern void local_timer_setup(void);

/*
 * show local interrupt info
 */
extern void show_local_irqs(struct seq_file *);

/*
 * Called from assembly, this is the local timer IRQ handler
 */
asmlinkage void do_local_timer(struct pt_regs *);

#endif /* ifndef __ASM_ARM_SMP_H */
+48 −8
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@
#include <linux/smp.h>
#include <linux/seq_file.h>
#include <linux/irq.h>
#include <linux/percpu.h>
#include <linux/clockchips.h>

#include <asm/atomic.h>
#include <asm/cacheflush.h>
@@ -32,6 +34,7 @@
#include <asm/processor.h>
#include <asm/tlbflush.h>
#include <asm/ptrace.h>
#include <asm/localtimer.h>

/*
 * as from 2.5, kernels no longer have an init_tasks structure
@@ -274,9 +277,9 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
	local_fiq_enable();

	/*
	 * Setup local timer for this CPU.
	 * Setup the percpu timer for this CPU.
	 */
	local_timer_setup();
	percpu_timer_setup();

	calibrate_delay();

@@ -383,10 +386,16 @@ void show_local_irqs(struct seq_file *p)
	seq_putc(p, '\n');
}

/*
 * Timer (local or broadcast) support
 */
static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent);

static void ipi_timer(void)
{
	struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
	irq_enter();
	local_timer_interrupt();
	evt->event_handler(evt);
	irq_exit();
}

@@ -405,6 +414,42 @@ asmlinkage void __exception do_local_timer(struct pt_regs *regs)
}
#endif

#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
static void smp_timer_broadcast(const struct cpumask *mask)
{
	send_ipi_message(mask, IPI_TIMER);
}

static void broadcast_timer_set_mode(enum clock_event_mode mode,
	struct clock_event_device *evt)
{
}

static void local_timer_setup(struct clock_event_device *evt)
{
	evt->name	= "dummy_timer";
	evt->features	= CLOCK_EVT_FEAT_ONESHOT |
			  CLOCK_EVT_FEAT_PERIODIC |
			  CLOCK_EVT_FEAT_DUMMY;
	evt->rating	= 400;
	evt->mult	= 1;
	evt->set_mode	= broadcast_timer_set_mode;
	evt->broadcast	= smp_timer_broadcast;

	clockevents_register_device(evt);
}
#endif

void __cpuinit percpu_timer_setup(void)
{
	unsigned int cpu = smp_processor_id();
	struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);

	evt->cpumask = cpumask_of(cpu);

	local_timer_setup(evt);
}

static DEFINE_SPINLOCK(stop_lock);

/*
@@ -501,11 +546,6 @@ void smp_send_reschedule(int cpu)
	send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE);
}

void smp_timer_broadcast(const struct cpumask *mask)
{
	send_ipi_message(mask, IPI_TIMER);
}

void smp_send_stop(void)
{
	cpumask_t mask = cpu_online_map;
+14 −56
Original line number Diff line number Diff line
@@ -11,10 +11,8 @@
#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>
#include <linux/io.h>
@@ -24,18 +22,6 @@
#include <mach/hardware.h>
#include <asm/irq.h>

static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);

/*
 * Used on SMP for either the local timer or IPI_TIMER
 */
void local_timer_interrupt(void)
{
	struct clock_event_device *clk = &__get_cpu_var(local_clockevent);

	clk->event_handler(clk);
}

#ifdef CONFIG_LOCAL_TIMERS

/* set up by the platform code */
@@ -44,7 +30,7 @@ void __iomem *twd_base;
static unsigned long mpcore_timer_rate;

static void local_timer_set_mode(enum clock_event_mode mode,
				 struct clock_event_device *clk)
				 struct clock_event_device *evt)
{
	unsigned long ctrl;

@@ -140,32 +126,29 @@ static void __cpuinit twd_calibrate_rate(void)
/*
 * Setup the local clock events for a CPU.
 */
void __cpuinit local_timer_setup(void)
void __cpuinit local_timer_setup(struct clock_event_device *evt)
{
	unsigned int cpu = smp_processor_id();
	struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
	unsigned long flags;

	twd_calibrate_rate();

	clk->name		= "local_timer";
	clk->features		= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
	clk->rating		= 350;
	clk->set_mode		= local_timer_set_mode;
	clk->set_next_event	= local_timer_set_next_event;
	clk->irq		= IRQ_LOCALTIMER;
	clk->cpumask		= cpumask_of(cpu);
	clk->shift		= 20;
	clk->mult		= div_sc(mpcore_timer_rate, NSEC_PER_SEC, clk->shift);
	clk->max_delta_ns	= clockevent_delta2ns(0xffffffff, clk);
	clk->min_delta_ns	= clockevent_delta2ns(0xf, clk);
	evt->name		= "local_timer";
	evt->features		= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
	evt->rating		= 350;
	evt->set_mode		= local_timer_set_mode;
	evt->set_next_event	= local_timer_set_next_event;
	evt->irq		= IRQ_LOCALTIMER;
	evt->shift		= 20;
	evt->mult		= div_sc(mpcore_timer_rate, NSEC_PER_SEC, evt->shift);
	evt->max_delta_ns	= clockevent_delta2ns(0xffffffff, evt);
	evt->min_delta_ns	= clockevent_delta2ns(0xf, evt);

	/* Make sure our local interrupt controller has this enabled */
	local_irq_save(flags);
	get_irq_chip(IRQ_LOCALTIMER)->unmask(IRQ_LOCALTIMER);
	local_irq_restore(flags);

	clockevents_register_device(clk);
	clockevents_register_device(evt);
}

/*
@@ -176,29 +159,4 @@ void __cpuexit local_timer_stop(void)
	__raw_writel(0, twd_base + TWD_TIMER_CONTROL);
}

#else	/* CONFIG_LOCAL_TIMERS */

static void dummy_timer_set_mode(enum clock_event_mode mode,
				 struct clock_event_device *clk)
{
}

void __cpuinit local_timer_setup(void)
{
	unsigned int cpu = smp_processor_id();
	struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);

	clk->name		= "dummy_timer";
	clk->features		= CLOCK_EVT_FEAT_ONESHOT |
				  CLOCK_EVT_FEAT_PERIODIC |
				  CLOCK_EVT_FEAT_DUMMY;
	clk->rating		= 400;
	clk->mult               = 1;
	clk->set_mode		= dummy_timer_set_mode;
	clk->broadcast		= smp_timer_broadcast;
	clk->cpumask		= cpumask_of(cpu);

	clockevents_register_device(clk);
}

#endif	/* !CONFIG_LOCAL_TIMERS */
#endif	/* CONFIG_LOCAL_TIMERS */
Loading