From d8bc0a2889700ba063598de6d4e7d135360b537e Mon Sep 17 00:00:00 2001 From: Scott McNutt Date: Thu, 1 Apr 2010 00:00:56 -0400 Subject: [PATCH] nios2: Reload timer count in reset_timer() When the timestamp is incremented via interrupt and the interrupt period is greater than 1 msec, successive calls to get_timer() can produce inaccurate timing since the interrupts are asynchronous to the timing loop. For example, with an interrupt period of 10 msec two successive calls to get_timer() could indicate an elapsed time of 10 msec after only several hundred usecs -- depending on when the next interrupt actually occurs. This behavior can cause reliability issues with components such as CFI and NAND. This can be remedied by calling reset_timer() prior to establishing the base timestamp with get_timer(0), provided reset_timer() resets the hardware timer (rather than simply resetting only the timestamp). This has the effect of synchronizing the interrupts (and the advance of the timestamp) with the timing loop. Signed-off-by: Scott McNutt --- cpu/nios2/interrupts.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/cpu/nios2/interrupts.c b/cpu/nios2/interrupts.c index 5c3b5e6..b552db4 100644 --- a/cpu/nios2/interrupts.c +++ b/cpu/nios2/interrupts.c @@ -56,7 +56,40 @@ volatile ulong timestamp = 0; void reset_timer (void) { + nios_timer_t *tmr =(nios_timer_t *)CONFIG_SYS_NIOS_TMRBASE; + + /* From Embedded Peripherals Handbook: + * + * "When the hardware is configured with Writeable period + * disabled, writing to one of the period_n registers causes + * the counter to reset to the fixed Timeout Period specified + * at system generation time." + * + * Here we force a reload to prevent early timeouts from + * get_timer() when the interrupt period is greater than + * than 1 msec. + * + * Simply write to periodl with its own value to force an + * internal counter reload, THEN reset the timestamp. + */ + writel (readl (&tmr->periodl), &tmr->periodl); timestamp = 0; + + /* From Embedded Peripherals Handbook: + * + * "Writing to one of the period_n registers stops the internal + * counter, except when the hardware is configured with Start/Stop + * control bits off. If Start/Stop control bits is off, writing + * either register does not stop the counter." + * + * In order to accomodate either configuration, the control + * register is re-written. If the counter is stopped, it will + * be restarted. If it is running, the write is essentially + * a nop. + */ + writel (NIOS_TIMER_ITO | NIOS_TIMER_CONT | NIOS_TIMER_START, + &tmr->control); + } ulong get_timer (ulong base)