From d54cc007878697a92e7f696b71a3eb203c0386e2 Mon Sep 17 00:00:00 2001 From: David Andrey Date: Fri, 7 Dec 2012 16:51:32 +0100 Subject: arm: zynq: U-Boot udelay < 1000 FIX Rework the __udelay function of U-Boot Zynq Arch to handle delay < 1000 usec Signed-off-by: David Andrey Signed-off-by: Michal Simek Reviewed-by: Tom Rini --- arch/arm/cpu/armv7/zynq/timer.c | 46 +++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 9 deletions(-) (limited to 'arch/arm/cpu/armv7/zynq') diff --git a/arch/arm/cpu/armv7/zynq/timer.c b/arch/arm/cpu/armv7/zynq/timer.c index 45b405a..5d8bb24 100644 --- a/arch/arm/cpu/armv7/zynq/timer.c +++ b/arch/arm/cpu/armv7/zynq/timer.c @@ -114,15 +114,43 @@ ulong get_timer_masked(void) void __udelay(unsigned long usec) { - unsigned long long tmp; - ulong tmo; - - tmo = usec / (1000000 / CONFIG_SYS_HZ); - tmp = get_ticks() + tmo; /* Get current timestamp */ - - while (get_ticks() < tmp) { /* Loop till event */ - /* NOP */; - } + u32 countticks; + u32 timeend; + u32 timediff; + u32 timenow; + + if (usec == 0) + return; + + countticks = (u32) (((unsigned long long) TIMER_TICK_HZ * usec) / + 1000000); + + /* decrementing timer */ + timeend = readl(&timer_base->counter) - countticks; + +#if TIMER_LOAD_VAL != 0xFFFFFFFF + /* do not manage multiple overflow */ + if (countticks >= TIMER_LOAD_VAL) + countticks = TIMER_LOAD_VAL - 1; +#endif + + do { + timenow = readl(&timer_base->counter); + + if (timenow >= timeend) { + /* normal case */ + timediff = timenow - timeend; + } else { + if ((TIMER_LOAD_VAL - timeend + timenow) <= + countticks) { + /* overflow */ + timediff = TIMER_LOAD_VAL - timeend + timenow; + } else { + /* missed the exact match */ + break; + } + } + } while (timediff > 0); } /* Timer without interrupts */ -- cgit v1.1