Skip to contentSkip to conversation

arm: a320: fix broken timer

PATCH New Po-Yu Chuang 3 participants 4 messages Aug 11, 2011 – Nov 8, 2011 Arm (32-bit)

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 arm: a320: fix broken timer

From: Po-Yu Chuang <[email protected]>

timer.c used static data and are called before relocation. Move all static variables into global_data structure. Also cleanup timer.c from unused stubs and make it truly use 64 bit tick values.

Remove reset_timer_masked() get_timer_masked()

reference: arch/arm/cpu/arm926ejs/at91/timer.c

Based on Reinhard Meyer <[email protected]>'s patches 5dca710a3d7703e41da0e9894f2d71f9e25bea6b cfff263f41e32c7ba2ee9162a8cc6423eb5a8390

---
 arch/arm/cpu/arm920t/a320/timer.c |  134 ++++++++++++++-----------------------
 1 files changed, 50 insertions(+), 84 deletions(-)
arch/arm/cpu/arm920t/a320/timer.c +50 -84
index 443d31d..4bfcef2 100644
@@ -18,20 +18,35 @@
  */
 
 #include <common.h>
+#include <div64.h>
 #include <asm/io.h>
 #include <faraday/ftpmu010.h>
 #include <faraday/fttmr010.h>
 
-static ulong timestamp;
-static ulong lastdec;
-
-static struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE;
+DECLARE_GLOBAL_DATA_PTR;
 
 #define TIMER_CLOCK	32768
 #define TIMER_LOAD_VAL	0xffffffff
 
+static inline unsigned long long tick_to_time(unsigned long long tick)
+{
+	tick *= CONFIG_SYS_HZ;
+	do_div(tick, gd->timer_rate_hz);
+
+	return tick;
+}
+
+static inline unsigned long long usec_to_tick(unsigned long long usec)
+{
+	usec *= gd->timer_rate_hz;
+	do_div(usec, 1000000);
+
+	return usec;
+}
+
 int timer_init(void)
 {
+	struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE;
 	unsigned int cr;
 
 	debug("%s()\n", __func__);
@@ -59,106 +74,57 @@ int timer_init(void)
 	cr |= FTTMR010_TM3_ENABLE;
 	writel(cr, &tmr->cr);
 
-	/* init the timestamp and lastdec value */
-	reset_timer_masked();
+	gd->timer_rate_hz = TIMER_CLOCK;
+	gd->tbu = gd->tbl = 0;
 
 	return 0;
 }
 
 /*
- * timer without interrupts
- */
-
-/*
- * reset time
- */
-void reset_timer_masked(void)
-{
-	/* capure current decrementer value time */
-	lastdec = readl(&tmr->timer3_counter) / (TIMER_CLOCK / CONFIG_SYS_HZ);
-	timestamp = 0;		/* start "advancing" time stamp from 0 */
-
-	debug("%s(): lastdec = %lx\n", __func__, lastdec);
-}
-
-/*
- * return timer ticks
- */
-ulong get_timer_masked(void)
-{
-	/* current tick value */
-	ulong now = readl(&tmr->timer3_counter) / (TIMER_CLOCK / CONFIG_SYS_HZ);
-
-	debug("%s(): now = %lx, lastdec = %lx\n", __func__, now, lastdec);
-
-	if (lastdec >= now) {
-		/*
-		 * normal mode (non roll)
-		 * move stamp fordward with absoulte diff ticks
-		 */
-		timestamp += lastdec - now;
-	} else {
-		/*
-		 * we have overflow of the count down timer
-		 *
-		 * nts = ts + ld + (TLV - now)
-		 * ts=old stamp, ld=time that passed before passing through -1
-		 * (TLV-now) amount of time after passing though -1
-		 * nts = new "advancing time stamp"...it could also roll and
-		 * cause problems.
-		 */
-		timestamp += lastdec + TIMER_LOAD_VAL - now;
-	}
-
-	lastdec = now;
-
-	debug("%s() returns %lx\n", __func__, timestamp);
-
-	return timestamp;
-}
-
-/*
- * return difference between timer ticks and base
+ * Get the current 64 bit timer tick count
  */
-ulong get_timer(ulong base)
+unsigned long long get_ticks(void)
 {
-	debug("%s(%lx)\n", __func__, base);
-	return get_timer_masked() - base;
+	struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE;
+	ulong now = TIMER_LOAD_VAL - readl(&tmr->timer3_counter);
+
+	/* increment tbu if tbl has rolled over */
+	if (now < gd->tbl)
+		gd->tbu++;
+	gd->tbl = now;
+	return (((unsigned long long)gd->tbu) << 32) | gd->tbl;
 }
 
-/* delay x useconds AND preserve advance timestamp value */
 void __udelay(unsigned long usec)
 {
-	long tmo = usec * (TIMER_CLOCK / 1000) / 1000;
-	unsigned long now, last = readl(&tmr->timer3_counter);
-
-	debug("%s(%lu)\n", __func__, usec);
-	while (tmo > 0) {
-		now = readl(&tmr->timer3_counter);
-		if (now > last) /* count down timer overflow */
-			tmo -= TIMER_LOAD_VAL + last - now;
-		else
-			tmo -= last - now;
-		last = now;
-	}
+	unsigned long long start;
+	ulong tmo;
+
+	start = get_ticks();		/* get current timestamp */
+	tmo = usec_to_tick(usec);	/* convert usecs to ticks */
+	while ((get_ticks() - start) < tmo)
+		;			/* loop till time has passed */
 }
 
 /*
- * This function is derived from PowerPC code (read timebase as long long).
- * On ARM it just returns the timer value.
+ * get_timer(base) can be used to check for timeouts or
+ * to measure elasped time relative to an event:
+ *
+ * ulong start_time = get_timer(0) sets start_time to the current
+ * time value.
+ * get_timer(start_time) returns the time elapsed since then.
+ *
+ * The time is used in CONFIG_SYS_HZ units!
  */
-unsigned long long get_ticks(void)
+ulong get_timer(ulong base)
 {
-	debug("%s()\n", __func__);
-	return get_timer(0);
+	return tick_to_time(get_ticks()) - base;
 }
 
 /*
- * This function is derived from PowerPC code (timebase clock frequency).
- * On ARM it returns the number of timer ticks per second.
+ * Return the number of timer ticks per second.
  */
 ulong get_tbclk(void)
 {
-	debug("%s()\n", __func__);
-	return CONFIG_SYS_HZ;
+	return gd->timer_rate_hz;
 }
Signature · 1 line
1.7.4.1
#1 lore raw

PATCH 1/1 arm: a320: fix broken timer

Hi Albert and Po-Yu,

2011/8/11 Po-Yu Chuang <[email protected]>

Quoted 6 lines

From: Po-Yu Chuang <[email protected]>

timer.c used static data and are called before relocation. Move all static variables into global_data structure. Also cleanup timer.c from unused stubs and make it truly use 64 bit tick values.

This patch has been tested by Macpaul on AG101 and AG101P boards.

--
Best regards,
Macpaul Lin

#2 lore raw

PATCH 1/1 arm: a320: fix broken timer

Dear Albert

Quoted 6 lines · ???

Hi Albert and Po-Yu,

2011/8/11 Po-Yu Chuang <[email protected]>

Quoted 3 lines

From: Po-Yu Chuang <[email protected]>

Quoted 7 lines
Quoted 3 lines

timer.c used static data and are called before relocation. Move all static variables into global_data structure. Also cleanup timer.c from unused stubs and make it truly use 64 bit tick values.

This patch has been tested by Macpaul on AG101 and AG101P boards.

This patch was posted 2 months ago and is still not in mainline. Is there any problem?

Best regards,
Po-Yu Chuang

#3 lore raw

PATCH 1/1 arm: a320: fix broken timer

Hi Po-Yu,

Le 18/10/2011 04:34, Po-Yu Chuang a ?crit :

Quoted 13 lines

Dear Albert

Quoted 10 lines · ???

Hi Albert and Po-Yu,

2011/8/11 Po-Yu Chuang<[email protected]>

Quoted 6 lines

From: Po-Yu Chuang<[email protected]>

timer.c used static data and are called before relocation. Move all static variables into global_data structure. Also cleanup timer.c from unused stubs and make it truly use 64 bit tick values.

Quoted 6 lines
Quoted 3 lines

This patch has been tested by Macpaul on AG101 and AG101P boards.

This patch was posted 2 months ago and is still not in mainline. Is there any problem?

None, except my own slowness.

Applied to u-boot-arm/master, and apologies.

Quoted 2 lines

Best regards,
Po-Yu Chuang

Amicalement,

Signature · 1 line
Albert.