Commit 963151f2 authored by Andrew Victor's avatar Andrew Victor Committed by Russell King

[ARM] 3579/1: AT91RM9200 Timer simplification

Patch from Andrew Victor

Use a global variable 'last_crtr' to store the time of the last timer
tick instead of the ST_RTAR register.
It's faster, frees up the ST_RTAR register for other uses, and hopefully
makes the code more understandable.  [Patch from Peter Menzebach]

Also add the SA_TIMER flag to Timer IRQ.  (It seems to be required for
the realtime preempt patch).
Signed-off-by: default avatarAndrew Victor <andrew@sanpeople.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 91f8ed83
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/mach/time.h> #include <asm/mach/time.h>
static unsigned long last_crtr;
/* /*
* The ST_CRTR is updated asynchronously to the master clock. It is therefore * The ST_CRTR is updated asynchronously to the master clock. It is therefore
* necessary to read it twice (with the same value) to ensure accuracy. * necessary to read it twice (with the same value) to ensure accuracy.
...@@ -56,7 +58,7 @@ static unsigned long at91rm9200_gettimeoffset(void) ...@@ -56,7 +58,7 @@ static unsigned long at91rm9200_gettimeoffset(void)
{ {
unsigned long elapsed; unsigned long elapsed;
elapsed = (read_CRTR() - at91_sys_read(AT91_ST_RTAR)) & AT91_ST_ALMV; elapsed = (read_CRTR() - last_crtr) & AT91_ST_ALMV;
return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH; return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
} }
...@@ -66,15 +68,12 @@ static unsigned long at91rm9200_gettimeoffset(void) ...@@ -66,15 +68,12 @@ static unsigned long at91rm9200_gettimeoffset(void)
*/ */
static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
unsigned long rtar;
if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) { /* This is a shared interrupt */ if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) { /* This is a shared interrupt */
write_seqlock(&xtime_lock); write_seqlock(&xtime_lock);
while (((read_CRTR() - at91_sys_read(AT91_ST_RTAR)) & AT91_ST_ALMV) >= LATCH) { while (((read_CRTR() - last_crtr) & AT91_ST_ALMV) >= LATCH) {
timer_tick(regs); timer_tick(regs);
rtar = (at91_sys_read(AT91_ST_RTAR) + LATCH) & AT91_ST_ALMV; last_crtr = (last_crtr + LATCH) & AT91_ST_ALMV;
at91_sys_write(AT91_ST_RTAR, rtar);
} }
write_sequnlock(&xtime_lock); write_sequnlock(&xtime_lock);
...@@ -87,7 +86,7 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_r ...@@ -87,7 +86,7 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_r
static struct irqaction at91rm9200_timer_irq = { static struct irqaction at91rm9200_timer_irq = {
.name = "at91_tick", .name = "at91_tick",
.flags = SA_SHIRQ | SA_INTERRUPT, .flags = SA_SHIRQ | SA_INTERRUPT | SA_TIMER,
.handler = at91rm9200_timer_interrupt .handler = at91rm9200_timer_interrupt
}; };
......
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