diff options
author | Dirk Behme <dirk.behme@googlemail.com> | 2008-03-26 08:53:29 (GMT) |
---|---|---|
committer | Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> | 2008-04-22 21:12:01 (GMT) |
commit | 80c40b765b3642ddb9f3392b7898715aab44a29c (patch) | |
tree | f5238b881170be5e46f2c6846593f72027edf898 | |
parent | 58c5376ba67767ee684069d43e7f747a5d9ae8ed (diff) | |
download | u-boot-80c40b765b3642ddb9f3392b7898715aab44a29c.tar.xz |
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>
-rw-r--r-- | cpu/arm926ejs/davinci/timer.c | 70 |
1 files changed, 23 insertions, 47 deletions
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 @@ typedef volatile struct { 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,63 +67,51 @@ int timer_init(void) /* 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(); -} - -ulong get_timer(ulong base) -{ - return(get_timer_masked() - base); -} - -void set_timer(ulong t) -{ - timestamp = t; -} - -void udelay(unsigned long usec) -{ - udelay_masked(usec); -} - -void reset_timer_masked(void) -{ - lastinc = DIV(READ_TIMER); + timer->tcr = 0x0; + timer->tim34 = 0; + lastinc = 0; timestamp = 0; + timer->tcr = 2 << 22; } -ulong get_timer_raw(void) +static ulong get_timer_raw(void) { - ulong now = DIV(READ_TIMER); + ulong now = timer->tim34; if (now >= lastinc) { /* normal mode */ timestamp += now - lastinc; } else { /* overflow ... */ - timestamp += now + DIV(TIMER_LOAD_VAL) - lastinc; + timestamp += now + TIMER_LOAD_VAL - lastinc; } lastinc = now; return timestamp; } -ulong get_timer_masked(void) +ulong get_timer(ulong base) +{ + return((get_timer_raw() / (TIMER_LOAD_VAL / TIM_CLK_DIV)) - base); +} + +void set_timer(ulong t) { - return(get_timer_raw() / DIV(TIMER_LOAD_VAL)); + timestamp = t; } -void udelay_masked(unsigned long usec) +void udelay(unsigned long usec) { ulong tmo; ulong endtime; @@ -140,7 +119,7 @@ void udelay_masked(unsigned long usec) tmo = CFG_HZ_CLOCK / 1000; tmo *= usec; - tmo /= 1000; + tmo /= (1000 * TIM_CLK_DIV); endtime = get_timer_raw() + tmo; @@ -165,8 +144,5 @@ unsigned long long get_ticks(void) */ ulong get_tbclk(void) { - ulong tbclk; - - tbclk = CFG_HZ; - return(tbclk); + return CFG_HZ; } |