summaryrefslogtreecommitdiff
path: root/cpu/arm926ejs
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/arm926ejs
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/arm926ejs')
-rw-r--r--cpu/arm926ejs/mx25/generic.c4
-rw-r--r--cpu/arm926ejs/mx25/timer.c77
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)