aboutsummaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
authorLily Zhang <r58066@freescale.com>2010-10-19 16:08:16 +0800
committerLily Zhang <r58066@freescale.com>2010-10-19 16:35:25 +0800
commitba5bcec0bb99c7c4dd14cf3fbe38ba6e7bf05e0c (patch)
tree224bc1102dda51bcea8a49552a62e8d5152ffbb8 /cpu
parent73662d021d4af3e29e7c8c6e85c31a74c1a584ef (diff)
ENGR00132759 MX53: use 32K CLK as GPT source
MT29F16G08MAA NAND flash was failed on MX53 ARD/RevB board, but it's fine in RevA board. After check, it's found that udelay is not accurate on MX53 ARD/RevB board because GPT uses IPG peripheral clock and assume it is 50MHZ. However IPG peripheral clock is not 50MHZ in MX53 ARD/RevB board. So it causes udelay is not accurate. This patch changes GPT clk source as 32K to make udelay accurate. Signed-off-by: Lily Zhang <r58066@freescale.com>
Diffstat (limited to 'cpu')
-rw-r--r--cpu/arm_cortexa8/mx53/timer.c71
1 files changed, 33 insertions, 38 deletions
diff --git a/cpu/arm_cortexa8/mx53/timer.c b/cpu/arm_cortexa8/mx53/timer.c
index e6b78466f..1f959b85b 100644
--- a/cpu/arm_cortexa8/mx53/timer.c
+++ b/cpu/arm_cortexa8/mx53/timer.c
@@ -25,6 +25,7 @@
#include <common.h>
#include <asm/arch/mx53.h>
+#include <div64.h>
/* General purpose timers registers */
#define GPTCR __REG(GPT1_BASE_ADDR) /* Control register */
@@ -35,10 +36,11 @@
/* General purpose timers bitfields */
#define GPTCR_SWR (1<<15) /* Software reset */
#define GPTCR_FRR (1<<9) /* Freerun / restart */
-#define GPTCR_CLKSOURCE_32 (0x100<<6) /* Clock source */
-#define GPTCR_CLKSOURCE_IPG (0x001<<6) /* Clock source */
+#define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */
#define GPTCR_TEN (1) /* Timer enable */
-#define GPTPR_VAL (50)
+
+static ulong timestamp;
+static ulong lastinc;
static inline void setup_gpt(void)
{
@@ -54,9 +56,10 @@ static inline void setup_gpt(void)
GPTCR = GPTCR_SWR;
for (i = 0; i < 100; i++)
GPTCR = 0; /* We have no udelay by now */
- GPTPR = GPTPR_VAL; /* 50Mhz / 50 */
- /* Freerun Mode, PERCLK1 input */
- GPTCR |= GPTCR_CLKSOURCE_IPG | GPTCR_TEN;
+ GPTPR = 0; /* 32KHz */
+ /* Freerun Mode, CLK32 input */
+ GPTCR = GPTCR | GPTCR_CLKSOURCE_32 | GPTCR_TEN;
+ reset_timer_masked();
}
int timer_init(void)
@@ -68,60 +71,52 @@ int timer_init(void)
void reset_timer_masked(void)
{
- GPTCR = 0;
- /* Freerun Mode, PERCLK1 input */
- GPTCR = GPTCR_CLKSOURCE_IPG | GPTCR_TEN;
+ /* capture current incrementer value time */
+ lastinc = GPTCNT / (CONFIG_MX53_CLK32 / CONFIG_SYS_HZ);
+ timestamp = 0; /* start "advancing" time stamp from 0 */
}
-inline ulong get_timer_masked(void)
+void reset_timer(void)
{
- ulong val = GPTCNT;
-
- return val;
+ reset_timer_masked();
}
-void reset_timer(void)
+inline ulong get_timer_masked(void)
{
- reset_timer_masked();
+ ulong val = GPTCNT;
+ val /= (CONFIG_MX53_CLK32 / CONFIG_SYS_HZ);
+ if (val >= lastinc)
+ timestamp += (val - lastinc);
+ else
+ timestamp += ((0xFFFFFFFF / (CONFIG_MX53_CLK32 / CONFIG_SYS_HZ))
+ - lastinc) + val;
+ lastinc = val;
+ return timestamp;
}
ulong get_timer(ulong base)
{
- ulong tmp;
-
- tmp = get_timer_masked();
-
- if (tmp <= (base * 1000)) {
- /* Overflow */
- tmp += (0xffffffff - base);
- }
-
- return (tmp / 1000) - base;
+ return get_timer_masked() - base;
}
void set_timer(ulong t)
{
+ timestamp = 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 tmp;
-
+ unsigned long now, start, tmo;
setup_gpt();
- tmp = get_timer_masked(); /* get current timestamp */
+ tmo = usec * (CONFIG_MX53_CLK32 / 1000) / 1000;
+ if (!tmo)
+ tmo = 1;
- /* 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;
- }
+ now = start = GPTCNT;
- while (get_timer_masked() < tmp) /* loop till event */
- /*NOP*/;
+ while ((now - start) < tmo)
+ now = GPTCNT;
}