[U-Boot] [PATCH] Fix LS102xa timer setup to use 64-bit.

Christopher Kilgour
2015-07-12T04:05:34Z

Fix LS102xa timer configuration to ensure timer compare value is set to
all-ones as a 64-bit number rather than a 32-bit number.

When the 32-bit all-ones was used, this could result in a timer compare value
of 2^32-1, which at 12.5 MHz will fire in ~344 seconds. If the operating
system's timer support does not expect or handle the timer compare, it can
lock up when the timer compare fires and never clears (in Linux this shows up
as a stuck GIC 29).

It's also possible to interactively work with u-boot for longer than 344
seconds, and have the timer compare silently fire in the background without
impact on u-boot operation. However, as soon as the operating system enables
interrupts, it can lock up. On embedded Linux without early console support,
this can be a silent lockup without warning or diagnostic output.

It's likely Freescale wanted to set the timer compare to the largest possible
value of all-ones at 64-bits. Rather than 344 seconds, this would fire after
~47k years. Even though Linux systems are known for long uptimes, one assumes
this is Freescale's intended, safe value.

Signed-off-by: Christopher Kilgour <techie@whiterocker.com>
Cc: York Sun <yorksun@freescale.com>
---
arch/arm/cpu/armv7/ls102xa/timer.c | 7 ++++---
arch/arm/include/asm/arch-ls102xa/immap_ls102xa.h | 2 +-
2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/arm/cpu/armv7/ls102xa/timer.c b/arch/arm/cpu/armv7/ls102xa/timer.c
index 11b17b2..746bfc0 100644
--- a/arch/arm/cpu/armv7/ls102xa/timer.c
+++ b/arch/arm/cpu/armv7/ls102xa/timer.c
@@ -56,7 +56,8 @@ static inline unsigned long long us_to_tick(unsigned long long usec)
int timer_init(void)
{
struct sctr_regs *sctr = (struct sctr_regs *)SCTR_BASE_ADDR;
- unsigned long ctrl, val, freq;
+ unsigned long ctrl, freq;
+ unsigned long long val64;

/* Enable System Counter */
writel(SYS_COUNTER_CTRL_ENABLE, &sctr->cntcr);
@@ -69,8 +70,8 @@ int timer_init(void)
asm("mcr p15, 0, %0, c14, c2, 1" : : "r" (ctrl));

/* Set PL1 Physical Comp Value */
- val = TIMER_COMP_VAL;
- asm("mcrr p15, 2, %Q0, %R0, c14" : : "r" (val));
+ val64 = TIMER_COMP_VAL;
+ asm("mcrr p15, 2, %Q0, %R0, c14" : : "r" (val64));

gd->arch.tbl = 0;
gd->arch.tbu = 0;
diff --git a/arch/arm/include/asm/arch-ls102xa/immap_ls102xa.h b/arch/arm/include/asm/arch-ls102xa/immap_ls102xa.h
index ee547fb..1f55655 100644
--- a/arch/arm/include/asm/arch-ls102xa/immap_ls102xa.h
+++ b/arch/arm/include/asm/arch-ls102xa/immap_ls102xa.h
@@ -31,7 +31,7 @@
#define RCWSR4_SRDS1_PRTCL_SHIFT 24
#define RCWSR4_SRDS1_PRTCL_MASK 0xff000000

-#define TIMER_COMP_VAL 0xffffffff
+#define TIMER_COMP_VAL ((unsigned long long)(-1))
#define ARCH_TIMER_CTRL_ENABLE (1 << 0)
#define SYS_COUNTER_CTRL_ENABLE (1 << 24)

--
2.1.0