diff --git a/arch/arm/cpu/arm926ejs/davinci/timer.c b/arch/arm/cpu/arm926ejs/davinci/timer.c
index 9da7443f30b5fea4df134a932ac49739f6c9e1ee..1c6fa4ae8715ef20f428853e739a1a7234ed3744 100644
--- a/arch/arm/cpu/arm926ejs/davinci/timer.c
+++ b/arch/arm/cpu/arm926ejs/davinci/timer.c
@@ -40,6 +40,8 @@
 #include <common.h>
 #include <asm/io.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 struct davinci_timer {
 	u_int32_t	pid12;
 	u_int32_t	emumgt;
@@ -57,11 +59,9 @@ struct davinci_timer {
 static struct davinci_timer * const timer =
 	(struct davinci_timer *)CONFIG_SYS_TIMERBASE;
 
-#define TIMER_LOAD_VAL	(CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ)
-#define TIM_CLK_DIV	16
+#define TIMER_LOAD_VAL	0xffffffff
 
-static ulong timestamp;
-static ulong lastinc;
+#define TIM_CLK_DIV	16
 
 int timer_init(void)
 {
@@ -71,72 +71,51 @@ int timer_init(void)
 	writel(0x06 | ((TIM_CLK_DIV - 1) << 8), &timer->tgcr);
 	writel(0x0, &timer->tim34);
 	writel(TIMER_LOAD_VAL, &timer->prd34);
-	lastinc = 0;
-	timestamp = 0;
 	writel(2 << 22, &timer->tcr);
+	gd->timer_rate_hz = CONFIG_SYS_HZ_CLOCK / TIM_CLK_DIV;
+	gd->timer_reset_value = 0;
 
 	return(0);
 }
 
 void reset_timer(void)
 {
-	writel(0x0, &timer->tcr);
-	writel(0x0, &timer->tim34);
-	lastinc = 0;
-	timestamp = 0;
-	writel(2 << 22, &timer->tcr);
+	gd->timer_reset_value = get_ticks();
 }
 
-static ulong get_timer_raw(void)
+/*
+ * Get the current 64 bit timer tick count
+ */
+unsigned long long get_ticks(void)
 {
-	ulong now = readl(&timer->tim34);
-
-	if (now >= lastinc) {
-		/* normal mode */
-		timestamp += now - lastinc;
-	} else {
-		/* overflow ... */
-		timestamp += now + TIMER_LOAD_VAL - lastinc;
-	}
-	lastinc = now;
-	return timestamp;
+	unsigned long now = readl(&timer->tim34);
+
+	/* 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;
 }
 
 ulong get_timer(ulong base)
 {
-	return((get_timer_raw() / (TIMER_LOAD_VAL / TIM_CLK_DIV)) - base);
-}
+	unsigned long long timer_diff;
 
-void set_timer(ulong t)
-{
-	timestamp = t;
+	timer_diff = get_ticks() - gd->timer_reset_value;
+
+	return (timer_diff / (gd->timer_rate_hz / CONFIG_SYS_HZ)) - base;
 }
 
 void __udelay(unsigned long usec)
 {
-	ulong tmo;
-	ulong endtime;
-	signed long diff;
-
-	tmo = CONFIG_SYS_HZ_CLOCK / 1000;
-	tmo *= usec;
-	tmo /= (1000 * TIM_CLK_DIV);
-
-	endtime = get_timer_raw() + tmo;
+	unsigned long long endtime;
 
-	do {
-		ulong now = get_timer_raw();
-		diff = endtime - now;
-	} while (diff >= 0);
-}
+	endtime = ((unsigned long long)usec * gd->timer_rate_hz) / 1000000UL;
+	endtime += get_ticks();
 
-/*
- * This function is derived from PowerPC code (read timebase as long long).
- * On ARM it just returns the timer value.
- */
-unsigned long long get_ticks(void)
-{
-	return(get_timer(0));
+	while (get_ticks() < endtime)
+		;
 }
 
 /*