> Subject: [PATCH v2] ARM: Davinci: Fix DM644x timer overflow > handling and cleanup > > Fix ARM based DaVinci DM644x timer overflow handling and > cleanup timer code.
Acked-by: Pieter Voorthuijsen <[EMAIL PROTECTED]> Please apply, tested on DaVinci DVEVM and other board, working OK! > > 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 <[EMAIL PROTECTED]> > and Pieter Voorthuijsen <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]> > > --- > > This patch completely replaces first version of this patch > > http://article.gmane.org/gmane.comp.boot-loaders.u-boot/38312/ > > Changes: > > - Incorporate findings from testing on real HW: Don't change > CFG_HZ_CLOCK in config files, instead divide in udelay() and > get_timer() correctly. > > Thanks to Pieter! > > Index: uboot_davinci/cpu/arm926ejs/davinci/timer.c > =================================================================== > --- uboot_davinci.orig/cpu/arm926ejs/davinci/timer.c > +++ uboot_davinci/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; > } > ------------------------------------------------------------------------- Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace _______________________________________________ U-Boot-Users mailing list U-Boot-Users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/u-boot-users