ARM: Davinci: Fix DM644x timer overflow handling and cleanup

Fix ARM based DaVinci DM644x timer overflow handling and cleanup timer code.

Changes:

- Remove *_masked() functions as noted by Wolfgang

- Adapt register naming to recent TI spec (sprue26, March 2007)

- Fix reset_timer() handling

- As reported by Pieter [1] the overflow fix introduced a delay of factor 16 (e.g 2 seconds became 32). While the overflow fix is basically okay, it missed to divide udelay by 16, too. Fix this.

[1] http://article.gmane.org/gmane.comp.boot-loaders.u-boot/38179

- Remove software division of timer count value (DIV(x) macro) and do it in hardware (TIM_CLK_DIV).

Many thanks to Troy Kisky <troy.kisky@boundarydevices.com> and Pieter Voorthuijsen <pieter.voorthuijsen@Prodrive.nl> for the hints & testing!

Patch is compile tested with davinci_dvevm & sonata & schmoogie configuration and tested by Pieter on DaVinci EVM hardware.

Signed-off-by: Dirk Behme <dirk.behme@gmail.com>
Acked-by: Pieter Voorthuijsen <pieter.voorthuijsen@Prodrive.nl>
diff --git a/cpu/arm926ejs/davinci/timer.c b/cpu/arm926ejs/davinci/timer.c
index 8bb8b45..6c670f0 100644
--- a/cpu/arm926ejs/davinci/timer.c
+++ b/cpu/arm926ejs/davinci/timer.c
@@ -42,9 +42,9 @@
 
 typedef volatile struct {
 	u_int32_t	pid12;
-	u_int32_t	emumgt_clksped;
-	u_int32_t	gpint_en;
-	u_int32_t	gpdir_dat;
+	u_int32_t	emumgt;
+	u_int32_t	na1;
+	u_int32_t	na2;
 	u_int32_t	tim12;
 	u_int32_t	tim34;
 	u_int32_t	prd12;
@@ -52,21 +52,12 @@
 	u_int32_t	tcr;
 	u_int32_t	tgcr;
 	u_int32_t	wdtcr;
-	u_int32_t	tlgc;
-	u_int32_t	tlmr;
 } davinci_timer;
 
 davinci_timer		*timer = (davinci_timer *)CFG_TIMERBASE;
 
 #define TIMER_LOAD_VAL	(CFG_HZ_CLOCK / CFG_HZ)
-#define READ_TIMER	timer->tim34
-
-/*
- * Timer runs with CFG_HZ_CLOCK, currently 27MHz. To avoid wrap
- * around of timestamp already after min ~159s, divide it, e.g. by 16.
- * timestamp will then wrap around all min ~42min
- */
-#define DIV(x)		((x) >> 4)
+#define TIM_CLK_DIV	16
 
 static ulong timestamp;
 static ulong lastinc;
@@ -76,24 +67,43 @@
 	/* We are using timer34 in unchained 32-bit mode, full speed */
 	timer->tcr = 0x0;
 	timer->tgcr = 0x0;
-	timer->tgcr = 0x06;
+	timer->tgcr = 0x06 | ((TIM_CLK_DIV - 1) << 8);
 	timer->tim34 = 0x0;
 	timer->prd34 = TIMER_LOAD_VAL;
 	lastinc = 0;
-	timer->tcr = 0x80 << 16;
 	timestamp = 0;
+	timer->tcr = 2 << 22;
 
 	return(0);
 }
 
 void reset_timer(void)
 {
-	reset_timer_masked();
+	timer->tcr = 0x0;
+	timer->tim34 = 0;
+	lastinc = 0;
+	timestamp = 0;
+	timer->tcr = 2 << 22;
+}
+
+static ulong get_timer_raw(void)
+{
+	ulong now = timer->tim34;
+
+	if (now >= lastinc) {
+		/* normal mode */
+		timestamp += now - lastinc;
+	} else {
+		/* overflow ... */
+		timestamp += now + TIMER_LOAD_VAL - lastinc;
+	}
+	lastinc = now;
+	return timestamp;
 }
 
 ulong get_timer(ulong base)
 {
-	return(get_timer_masked() - base);
+	return((get_timer_raw() / (TIMER_LOAD_VAL / TIM_CLK_DIV)) - base);
 }
 
 void set_timer(ulong t)
@@ -103,44 +113,13 @@
 
 void udelay(unsigned long usec)
 {
-	udelay_masked(usec);
-}
-
-void reset_timer_masked(void)
-{
-	lastinc = DIV(READ_TIMER);
-	timestamp = 0;
-}
-
-ulong get_timer_raw(void)
-{
-	ulong now = DIV(READ_TIMER);
-
-	if (now >= lastinc) {
-		/* normal mode */
-		timestamp += now - lastinc;
-	} else {
-		/* overflow ... */
-		timestamp += now + DIV(TIMER_LOAD_VAL) - lastinc;
-	}
-	lastinc = now;
-	return timestamp;
-}
-
-ulong get_timer_masked(void)
-{
-	return(get_timer_raw() / DIV(TIMER_LOAD_VAL));
-}
-
-void udelay_masked(unsigned long usec)
-{
 	ulong tmo;
 	ulong endtime;
 	signed long diff;
 
 	tmo = CFG_HZ_CLOCK / 1000;
 	tmo *= usec;
-	tmo /= 1000;
+	tmo /= (1000 * TIM_CLK_DIV);
 
 	endtime = get_timer_raw() + tmo;
 
@@ -165,8 +144,5 @@
  */
 ulong get_tbclk(void)
 {
-	ulong tbclk;
-
-	tbclk = CFG_HZ;
-	return(tbclk);
+	return CFG_HZ;
 }