summaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
authorFred Fan <r01011@freescale.com>2009-11-19 16:43:08 +0800
committerTerry Lv <r65388@freescale.com>2009-12-04 17:14:08 +0800
commitd8667412a8b7e1ad96979bc2191b4e3fa90c8254 (patch)
tree52f9a08604fdbb9a3dfee9e77473f7a0127126ca /cpu
parent3f86cf9693f8b98c44999e81d4067943c634b421 (diff)
downloadu-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.c1
-rw-r--r--cpu/arm1136/mx35/generic.c15
-rw-r--r--cpu/arm1136/mx35/timer.c63
-rw-r--r--cpu/arm926ejs/mx25/generic.c4
-rw-r--r--cpu/arm926ejs/mx25/timer.c77
-rw-r--r--cpu/arm_cortexa8/mx51/interrupts.c12
-rw-r--r--cpu/arm_cortexa8/mx51/timer.c68
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*/;
}