diff options
author | Fred Fan <r01011@freescale.com> | 2009-11-19 16:43:08 +0800 |
---|---|---|
committer | Terry Lv <r65388@freescale.com> | 2009-12-04 17:14:08 +0800 |
commit | d8667412a8b7e1ad96979bc2191b4e3fa90c8254 (patch) | |
tree | 52f9a08604fdbb9a3dfee9e77473f7a0127126ca /cpu/arm1136/mx35/timer.c | |
parent | 3f86cf9693f8b98c44999e81d4067943c634b421 (diff) | |
download | u-boot-imx-d8667412a8b7e1ad96979bc2191b4e3fa90c8254.zip u-boot-imx-d8667412a8b7e1ad96979bc2191b4e3fa90c8254.tar.gz u-boot-imx-d8667412a8b7e1ad96979bc2191b4e3fa90c8254.tar.bz2 |
ENGR00118978: Timer adjustment for all platforms
In current u-boot design,
get_timer_masked is not correct and udelay is not accurate
when the time is less than 1000us.
Thus we need to use ipg clock source for accurate timer.
Signed-off-by: Terry Lv <r65388@freescale.com>
Diffstat (limited to 'cpu/arm1136/mx35/timer.c')
-rw-r--r-- | cpu/arm1136/mx35/timer.c | 63 |
1 files changed, 34 insertions, 29 deletions
diff --git a/cpu/arm1136/mx35/timer.c b/cpu/arm1136/mx35/timer.c index d6f65cf..f18be9c 100644 --- a/cpu/arm1136/mx35/timer.c +++ b/cpu/arm1136/mx35/timer.c @@ -35,8 +35,10 @@ /* General purpose timers bitfields */ #define GPTCR_SWR (1<<15) /* Software reset */ #define GPTCR_FRR (1<<9) /* Freerun / restart */ -#define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */ +#define GPTCR_CLKSOURCE_32 (0x100<<6) /* Clock source */ +#define GPTCR_CLKSOURCE_IPG (0x001<<6) /* Clock source */ #define GPTCR_TEN (1) /* Timer enable */ +#define GPTPR_VAL (66) static inline void setup_gpt() { @@ -52,9 +54,9 @@ static inline void setup_gpt() GPTCR = GPTCR_SWR; for (i = 0; i < 100; i++) GPTCR = 0; /* We have no udelay by now */ - GPTPR = 0; /* 32Khz */ + GPTPR = GPTPR_VAL; /* 66Mhz / 66 */ /* Freerun Mode, PERCLK1 input */ - GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_TEN; + GPTCR |= GPTCR_CLKSOURCE_IPG | GPTCR_TEN; } int timer_init(void) @@ -64,27 +66,37 @@ int timer_init(void) return 0; } -void reset_timer(void) -{ - reset_timer_masked(); -} - void reset_timer_masked(void) { GPTCR = 0; /* Freerun Mode, PERCLK1 input */ - GPTCR = GPTCR_CLKSOURCE_32 | GPTCR_TEN; + GPTCR = GPTCR_CLKSOURCE_IPG | GPTCR_TEN; } -ulong get_timer_masked(void) +inline ulong get_timer_masked(void) { ulong val = GPTCNT; + return val; } +void reset_timer(void) +{ + reset_timer_masked(); +} + ulong get_timer(ulong base) { - return get_timer_masked() - base; + ulong tmp; + + tmp = get_timer_masked(); + + if (tmp <= (base * 1000)) { + /* Overflow */ + tmp += (0xffffffff - base); + } + + return (tmp / 1000) - base; } void set_timer(ulong t) @@ -92,32 +104,25 @@ void set_timer(ulong t) } /* delay x useconds AND perserve advance timstamp value */ +/* GPTCNT is now supposed to tick 1 by 1 us. */ void udelay(unsigned long usec) { - ulong tmo, tmp; + ulong tmp; setup_gpt(); - /* if "big" number, spread normalization to seconds */ - if (usec >= 1000) { - /* start to normalize for usec to ticks per sec */ - tmo = usec / 1000; - /* find number of "ticks" to wait to achieve target */ - tmo *= CONFIG_SYS_HZ; - tmo /= 1000; /* finish normalize. */ - } else {/* else small number, don't kill it prior to HZ multiply */ - tmo = usec * CONFIG_SYS_HZ; - tmo /= (1000 * 1000); - } + tmp = get_timer_masked(); /* get current timestamp */ - tmp = get_timer(0); /* get current timestamp */ /* if setting this forward will roll time stamp */ - if ((tmo + tmp + 1) < tmp) - /* reset "advancing" timestamp to 0, set lastinc value */ + if ((usec + tmp + 1) < tmp) { + /* reset "advancing" timestamp to 0, set lastinc value */ reset_timer_masked(); - else /* else, set advancing stamp wake up time */ - tmo += tmp; - while (get_timer_masked() < tmo) /* loop till event */ + } else { + /* else, set advancing stamp wake up time */ + tmp += usec; + } + + while (get_timer_masked() < tmp) /* loop till event */ /*NOP*/; } |