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 | |
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')
-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 | ||||
-rw-r--r-- | cpu/arm926ejs/mx25/generic.c | 4 | ||||
-rw-r--r-- | cpu/arm926ejs/mx25/timer.c | 77 | ||||
-rw-r--r-- | cpu/arm_cortexa8/mx51/interrupts.c | 12 | ||||
-rw-r--r-- | cpu/arm_cortexa8/mx51/timer.c | 68 |
7 files changed, 124 insertions, 116 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*/; } 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) diff --git a/cpu/arm_cortexa8/mx51/interrupts.c b/cpu/arm_cortexa8/mx51/interrupts.c index 1b5a4d1..9758bef 100644 --- a/cpu/arm_cortexa8/mx51/interrupts.c +++ b/cpu/arm_cortexa8/mx51/interrupts.c @@ -26,18 +26,6 @@ #include <common.h> #include <asm/arch/mx51.h> -/* General purpose timers registers */ -#define GPTCR __REG(GPT1_BASE_ADDR) /* Control register */ -#define GPTPR __REG(GPT1_BASE_ADDR + 0x4) /* Prescaler register */ -#define GPTSR __REG(GPT1_BASE_ADDR + 0x8) /* Status register */ -#define GPTCNT __REG(GPT1_BASE_ADDR + 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_TEN (1) /* Timer enable */ - /* nothing really to do with interrupts, just starts up a counter. */ int interrupt_init(void) { diff --git a/cpu/arm_cortexa8/mx51/timer.c b/cpu/arm_cortexa8/mx51/timer.c index ff982be..2fa04d6 100644 --- a/cpu/arm_cortexa8/mx51/timer.c +++ b/cpu/arm_cortexa8/mx51/timer.c @@ -2,7 +2,7 @@ * (C) Copyright 2007 * Sascha Hauer, Pengutronix * - * (C) Copyright 2009 Freescale Semiconductor, Inc. + * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. * * See file CREDITS for list of people who contributed to this * project. @@ -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() { @@ -51,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(); @@ -65,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) @@ -93,31 +104,24 @@ 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*/; } |