summaryrefslogtreecommitdiff
path: root/cpu/arm1136
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/arm1136
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/arm1136')
-rw-r--r--cpu/arm1136/mx31/generic.c1
-rw-r--r--cpu/arm1136/mx35/generic.c15
-rw-r--r--cpu/arm1136/mx35/timer.c63
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*/;
}