Commit 543a0547 authored by Philippe Gerum's avatar Philippe Gerum

ARM: twd: ipipe: enable interrupt pipelining

parent 1ab4f83e
......@@ -20,10 +20,14 @@
#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ipipe.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/ipipe_tickdev.h>
#include <linux/irqchip/arm-gic.h>
#include <asm/smp_twd.h>
#include <asm/cputype.h>
/* set up by the platform code */
static void __iomem *twd_base;
......@@ -37,6 +41,36 @@ static unsigned int twd_features =
CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
static int twd_ppi;
#ifdef CONFIG_IPIPE
static DEFINE_PER_CPU(struct ipipe_timer, twd_itimer);
static void twd_ack(void)
{
writel_relaxed(1, twd_base + TWD_TIMER_INTSTAT);
}
static void twd_get_clock(struct device_node *np);
static void twd_calibrate_rate(void);
#ifdef CONFIG_IPIPE_DEBUG_INTERNAL
static DEFINE_PER_CPU(int, irqs);
void twd_hrtimer_debug(unsigned int irq) /* hw interrupt off */
{
int cpu = ipipe_processor_id();
if ((++per_cpu(irqs, cpu) % HZ) == 0) {
#if 0
raw_printk("%c", 'A' + cpu);
#else
do { } while (0);
#endif
}
}
#endif /* CONFIG_IPIPE_DEBUG_INTERNAL */
#endif /* CONFIG_IPIPE */
static int twd_shutdown(struct clock_event_device *clk)
{
writel_relaxed(0, twd_base + TWD_TIMER_CONTROL);
......@@ -191,6 +225,13 @@ core_initcall(twd_cpufreq_init);
#endif
#ifdef CONFIG_IPIPE
static unsigned int twd_refresh_freq(void)
{
return clk_get_rate(twd_clk);
}
#endif
static void twd_calibrate_rate(void)
{
unsigned long count;
......@@ -234,7 +275,11 @@ static irqreturn_t twd_handler(int irq, void *dev_id)
{
struct clock_event_device *evt = dev_id;
if (clockevent_ipipe_stolen(evt))
goto handle;
if (twd_timer_ack()) {
handle:
evt->event_handler(evt);
return IRQ_HANDLED;
}
......@@ -303,6 +348,18 @@ static void twd_timer_setup(void)
clk->tick_resume = twd_shutdown;
clk->set_next_event = twd_set_next_event;
clk->irq = twd_ppi;
#ifdef CONFIG_IPIPE
printk(KERN_INFO "I-pipe, %lu.%03lu MHz timer\n",
twd_timer_rate / 1000000,
(twd_timer_rate % 1000000) / 1000);
clk->ipipe_timer = raw_cpu_ptr(&twd_itimer);
clk->ipipe_timer->irq = clk->irq;
clk->ipipe_timer->ack = twd_ack;
clk->ipipe_timer->min_delay_ticks = 0xf;
clk->ipipe_timer->refresh_freq = twd_refresh_freq;
#endif
clk->cpumask = cpumask_of(cpu);
clockevents_config_and_register(clk, twd_timer_rate,
......@@ -356,6 +413,10 @@ static int __init twd_local_timer_common_register(struct device_node *np)
else
late_time_init = twd_timer_setup;
#ifdef CONFIG_IPIPE_DEBUG_INTERNAL
__ipipe_mach_hrtimer_debug = &twd_hrtimer_debug;
#endif /* CONFIG_IPIPE_DEBUG_INTERNAL */
return 0;
out_free:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment