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/arm926ejs | |
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/arm926ejs')
-rw-r--r-- | cpu/arm926ejs/mx25/generic.c | 4 | ||||
-rw-r--r-- | cpu/arm926ejs/mx25/timer.c | 77 |
2 files changed, 47 insertions, 34 deletions
diff --git a/cpu/arm926ejs/mx25/generic.c b/cpu/arm926ejs/mx25/generic.c index 5ee10d4..bda3fbe 100644 --- a/cpu/arm926ejs/mx25/generic.c +++ b/cpu/arm926ejs/mx25/generic.c @@ -97,6 +97,9 @@ unsigned int mxc_get_clock(enum mxc_clock clk) return mx25_get_cspi_clk(); case MXC_UART_CLK: break; + case MXC_ESDHC_CLK: + return mx25_get_ipg_clk(); + break; } return -1; } @@ -106,6 +109,7 @@ int print_cpuinfo(void) { printf("CPU: Freescale i.MX25 at %d MHz\n", mx25_get_mcu_main_clk() / 1000000); + mx25_dump_clocks(); return 0; } /* diff --git a/cpu/arm926ejs/mx25/timer.c b/cpu/arm926ejs/mx25/timer.c index 1900240..34c28e1 100644 --- a/cpu/arm926ejs/mx25/timer.c +++ b/cpu/arm926ejs/mx25/timer.c @@ -26,22 +26,19 @@ #include <common.h> #include <asm/arch/mx25-regs.h> -#define TIMER_BASE 0x53f90000 /* General purpose timer 1 */ - /* General purpose timers registers */ -#define GPTCR __REG(TIMER_BASE) /* Control register */ -#define GPTPR __REG(TIMER_BASE + 0x4) /* Prescaler register */ -#define GPTSR __REG(TIMER_BASE + 0x8) /* Status register */ -#define GPTCNT __REG(TIMER_BASE + 0x24) /* Counter register */ +#define GPTCR __REG(GPT1_BASE) /* Control register */ +#define GPTPR __REG(GPT1_BASE + 0x4) /* Prescaler register */ +#define GPTSR __REG(GPT1_BASE + 0x8) /* Status register */ +#define GPTCNT __REG(GPT1_BASE + 0x24) /* Counter register */ /* 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 */ - -static ulong timestamp; -static ulong lastinc; +#define GPTPR_VAL (66) static inline void setup_gpt() { @@ -56,13 +53,12 @@ static inline void setup_gpt() /* setup GP Timer 1 */ GPTCR = GPTCR_SWR; for (i = 0; i < 100; i++) - GPTCR = 0; /* We have no udelay by now */ - GPTPR = 0; /* 32Khz */ + GPTCR = 0; /* We have no udelay by now */ + GPTPR = GPTPR_VAL; /* 66Mhz / 66 */ /* Freerun Mode, PERCLK1 input */ - GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_TEN; + GPTCR |= GPTCR_CLKSOURCE_IPG | GPTCR_TEN; } -/* nothing really to do with interrupts, just starts up a counter. */ int timer_init(void) { setup_gpt(); @@ -72,27 +68,35 @@ int timer_init(void) void reset_timer_masked(void) { - /* reset time */ - lastinc = GPTCNT; /* capture current incrementer value time */ - timestamp = 0; /* start "advancing" time stamp from 0 */ + GPTCR = 0; + /* Freerun Mode, PERCLK1 input */ + GPTCR = GPTCR_CLKSOURCE_IPG | GPTCR_TEN; } -void reset_timer(void) +inline ulong get_timer_masked(void) { - reset_timer_masked(); + ulong val = GPTCNT; + + return val; } -ulong get_timer_masked(void) +void reset_timer(void) { - ulong now = GPTCNT; - now = now * 1000 / CONFIG_SYS_HZ; /* current tick value */ - - return now; + 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) @@ -100,21 +104,26 @@ 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(); - tmo = usec / 1000; /* Current precision is Millisecond */ + tmp = get_timer_masked(); /* get current timestamp */ + + /* if setting this forward will roll time stamp */ + if ((usec + tmp + 1) < tmp) { + /* reset "advancing" timestamp to 0, set lastinc value */ + reset_timer_masked(); + } else { + /* else, set advancing stamp wake up time */ + tmp += usec; + } - tmp = get_timer(0); /* get current timestamp */ - if ((tmo + tmp + 1) < tmp) /* if overflow time stamp */ - reset_timer_masked(); /* reset "advancing" timestamp to 0 */ - else - tmo += tmp; /* else, set stamp wake up time */ - while (get_timer_masked() < tmo)/* loop till event */ - /*NOP*/; + while (get_timer_masked() < tmp) /* loop till event */ + /*NOP*/; } void reset_cpu(ulong addr) |