Commit 0661d1e8 authored by Gilles Chanteperdrix's avatar Gilles Chanteperdrix Committed by Dmitriy Cherkasov

ARM: arch_timer: ipipe: enable interrupt pipelining

parent 9d1ea32d
......@@ -106,6 +106,10 @@ static inline u32 arch_timer_get_cntkctl(void)
static inline void arch_timer_set_cntkctl(u32 cntkctl)
{
#ifdef CONFIG_IPIPE
/* Enable access to user-space (may not be needed) */
cntkctl |= ARCH_TIMER_USR_PCT_ACCESS_EN;
#endif
asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
}
......
......@@ -20,6 +20,8 @@
#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <linux/interrupt.h>
#include <linux/ipipe.h>
#include <linux/ipipe_tickdev.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/io.h>
......@@ -549,8 +551,7 @@ static bool arch_timer_this_cpu_has_cntvct_wa(void)
#define arch_timer_this_cpu_has_cntvct_wa() ({false;})
#endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */
static __always_inline irqreturn_t timer_handler(const int access,
struct clock_event_device *evt)
static int arch_timer_ack(const int access, struct clock_event_device *evt)
{
unsigned long ctrl;
......@@ -558,6 +559,52 @@ static __always_inline irqreturn_t timer_handler(const int access,
if (ctrl & ARCH_TIMER_CTRL_IT_STAT) {
ctrl |= ARCH_TIMER_CTRL_IT_MASK;
arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, evt);
return 1;
}
return 0;
}
#ifdef CONFIG_IPIPE
static DEFINE_PER_CPU(struct ipipe_timer, arch_itimer);
static struct __ipipe_tscinfo tsc_info = {
.type = IPIPE_TSC_TYPE_FREERUNNING_ARCH,
.u = {
{
.mask = 0xffffffffffffffff,
},
},
};
static void arch_itimer_ack_phys(void)
{
struct clock_event_device *evt = this_cpu_ptr(arch_timer_evt);
arch_timer_ack(ARCH_TIMER_PHYS_ACCESS, evt);
}
static void arch_itimer_ack_virt(void)
{
struct clock_event_device *evt = this_cpu_ptr(arch_timer_evt);
arch_timer_ack(ARCH_TIMER_VIRT_ACCESS, evt);
}
#endif /* CONFIG_IPIPE */
static inline irqreturn_t timer_handler(int irq, const int access,
struct clock_event_device *evt)
{
if (clockevent_ipipe_stolen(evt))
goto stolen;
if (arch_timer_ack(access, evt)) {
#ifdef CONFIG_IPIPE
struct ipipe_timer *itimer = raw_cpu_ptr(&arch_itimer);
if (itimer->irq != irq)
itimer->irq = irq;
#endif /* CONFIG_IPIPE */
stolen:
/*
* This is a 64bit clock source, no need for TSC
* update.
*/
evt->event_handler(evt);
return IRQ_HANDLED;
}
......@@ -569,28 +616,28 @@ static irqreturn_t arch_timer_handler_virt(int irq, void *dev_id)
{
struct clock_event_device *evt = dev_id;
return timer_handler(ARCH_TIMER_VIRT_ACCESS, evt);
return timer_handler(irq, ARCH_TIMER_VIRT_ACCESS, evt);
}
static irqreturn_t arch_timer_handler_phys(int irq, void *dev_id)
{
struct clock_event_device *evt = dev_id;
return timer_handler(ARCH_TIMER_PHYS_ACCESS, evt);
return timer_handler(irq, ARCH_TIMER_PHYS_ACCESS, evt);
}
static irqreturn_t arch_timer_handler_phys_mem(int irq, void *dev_id)
{
struct clock_event_device *evt = dev_id;
return timer_handler(ARCH_TIMER_MEM_PHYS_ACCESS, evt);
return timer_handler(irq, ARCH_TIMER_MEM_PHYS_ACCESS, evt);
}
static irqreturn_t arch_timer_handler_virt_mem(int irq, void *dev_id)
{
struct clock_event_device *evt = dev_id;
return timer_handler(ARCH_TIMER_MEM_VIRT_ACCESS, evt);
return timer_handler(irq, ARCH_TIMER_MEM_VIRT_ACCESS, evt);
}
static __always_inline int timer_shutdown(const int access,
......@@ -704,6 +751,17 @@ static void __arch_timer_setup(unsigned type,
}
arch_timer_check_ool_workaround(ate_match_local_cap_id, NULL);
#ifdef CONFIG_IPIPE
clk->ipipe_timer = raw_cpu_ptr(&arch_itimer);
if (arch_timer_mem_use_virtual) {
clk->ipipe_timer->irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
clk->ipipe_timer->ack = arch_itimer_ack_virt;
} else {
clk->ipipe_timer->irq = arch_timer_ppi[ARCH_TIMER_PHYS_SECURE_PPI];
clk->ipipe_timer->ack = arch_itimer_ack_phys;
}
clk->ipipe_timer->freq = arch_timer_rate;
#endif
} else {
clk->features |= CLOCK_EVT_FEAT_DYNIRQ;
clk->name = "arch_mem_timer";
......@@ -777,6 +835,9 @@ static void arch_counter_set_user_access(void)
else
cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN;
#ifdef CONFIG_IPIPE
cntkctl |= ARCH_TIMER_USR_PCT_ACCESS_EN;
#endif
arch_timer_set_cntkctl(cntkctl);
}
......@@ -901,6 +962,10 @@ static void __init arch_counter_register(unsigned type)
arch_timer_read_counter = arch_counter_get_cntvct_mem;
}
#ifdef CONFIG_IPIPE
tsc_info.freq = arch_timer_rate;
__ipipe_tsc_register(&tsc_info);
#endif /* CONFIG_IPIPE */
if (!arch_counter_suspend_stop)
clocksource_counter.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
start_count = arch_timer_read_counter();
......
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