[U-Boot] [PATCH] nios2: Reload timer count in reset_timer()

Scott McNutt smcnutt at psyent.com
Thu Apr 1 06:33:20 CEST 2010


   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 <smcnutt at psyent.com>
---
 cpu/nios2/interrupts.c |   33 +++++++++++++++++++++++++++++++++
 1 files changed, 33 insertions(+), 0 deletions(-)

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)
-- 
1.6.0.6



More information about the U-Boot mailing list