Skip to content

Commit

Permalink
m68k: mvme147: Handle timer counter overflow
Browse files Browse the repository at this point in the history
Reading the timer counter races with timer overflow (and the
corresponding interrupt). This is resolved by reading the overflow
register and taking this value into account. The interrupt handler
must clear the overflow register when it eventually executes.

Suggested-by: Thomas Gleixner <[email protected]>
Signed-off-by: Finn Thain <[email protected]>
Signed-off-by: Geert Uytterhoeven <[email protected]>
  • Loading branch information
Finn Thain authored and geertu committed Mar 25, 2019
1 parent fc4c47b commit 7529b90
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 10 deletions.
1 change: 1 addition & 0 deletions arch/m68k/include/asm/mvme147hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ struct pcc_regs {
#define PCC_INT_ENAB 0x08

#define PCC_TIMER_INT_CLR 0x80
#define PCC_TIMER_CLR_OVF 0x04

#define PCC_LEVEL_ABORT 0x07
#define PCC_LEVEL_SERIAL 0x04
Expand Down
21 changes: 11 additions & 10 deletions arch/m68k/mvme147/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id)

local_irq_save(flags);
m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR;
m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;
m147_pcc->t1_cntrl = PCC_TIMER_CLR_OVF;
clk_total += PCC_TIMER_CYCLES;
timer_routine(0, NULL);
local_irq_restore(flags);
Expand All @@ -144,21 +144,22 @@ void mvme147_sched_init (irq_handler_t timer_routine)
clocksource_register_hz(&mvme147_clk, PCC_TIMER_CLOCK_FREQ);
}

/* XXX There are race hazards in this code XXX */
static u64 mvme147_read_clk(struct clocksource *cs)
{
unsigned long flags;
volatile unsigned short *cp = (volatile unsigned short *)0xfffe1012;
unsigned short n;
u8 overflow, tmp;
u16 count;
u32 ticks;

local_irq_save(flags);
n = *cp;
while (n != *cp)
n = *cp;

n -= PCC_TIMER_PRELOAD;
ticks = clk_total + n;
tmp = m147_pcc->t1_cntrl >> 4;
count = m147_pcc->t1_count;
overflow = m147_pcc->t1_cntrl >> 4;
if (overflow != tmp)
count = m147_pcc->t1_count;
count -= PCC_TIMER_PRELOAD;
ticks = count + overflow * PCC_TIMER_CYCLES;
ticks += clk_total;
local_irq_restore(flags);

return ticks;
Expand Down

0 comments on commit 7529b90

Please sign in to comment.