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 | |
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')
-rw-r--r-- | cpu/arm1136/mx31/generic.c | 1 | ||||
-rw-r--r-- | cpu/arm1136/mx35/generic.c | 15 | ||||
-rw-r--r-- | cpu/arm1136/mx35/timer.c | 63 |
3 files changed, 41 insertions, 38 deletions
diff --git a/cpu/arm1136/mx31/generic.c b/cpu/arm1136/mx31/generic.c index 1415d6c..67c0cc6 100644 --- a/cpu/arm1136/mx31/generic.c +++ b/cpu/arm1136/mx31/generic.c @@ -95,6 +95,7 @@ int print_cpuinfo (void) { printf("CPU: Freescale i.MX31 at %d MHz\n", mx31_get_mcu_main_clk() / 1000000); + mx31_dump_clocks(); return 0; } #endif diff --git a/cpu/arm1136/mx35/generic.c b/cpu/arm1136/mx35/generic.c index fbe9084..e9abe0c 100644 --- a/cpu/arm1136/mx35/generic.c +++ b/cpu/arm1136/mx35/generic.c @@ -89,15 +89,10 @@ static u32 __get_arm_div(u32 pdr0, u32 *fi, u32 *fd) static int __get_ahb_div(u32 pdr0) { int *pclk_mux; - if (pdr0 & MXC_CCM_PDR0_AUTO_CON) { - pclk_mux = g_clk_mux_consumer + - ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> - MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); - } else { - pclk_mux = g_clk_mux_auto + - ((pdr0 & MXC_CCM_PDR0_AUTO_MUX_DIV_MASK) >> - MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET); - } + + pclk_mux = g_clk_mux_consumer + + ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> + MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); if ((*pclk_mux) == -1) return -1; @@ -348,6 +343,7 @@ void mxc_dump_clocks(void) u32 cpufreq = __get_mcu_main_clk(); printf("mx35 cpu clock: %dMHz\n", cpufreq / 1000000); printf("ipg clock : %dHz\n", __get_ipg_clk()); + printf("ipg per clock : %dHz\n", __get_ipg_per_clk()); printf("uart clock : %dHz\n", mxc_get_clock(MXC_UART_CLK)); } @@ -356,6 +352,7 @@ int print_cpuinfo(void) { printf("CPU: Freescale i.MX35 at %d MHz\n", __get_mcu_main_clk() / 1000000); + /* mxc_dump_clocks(); */ return 0; } #endif 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*/; } |