summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Andrey <david.andrey@netmodule.com>2012-12-07 16:51:32 +0100
committerMichal Simek <michal.simek@xilinx.com>2013-04-30 11:39:10 +0200
commitd54cc007878697a92e7f696b71a3eb203c0386e2 (patch)
treeb4dba36a37a114391b7b7df19e7add5a9993a3f9
parentd10f68ae47b67acab8b110b5c605dde4197a1820 (diff)
downloadu-boot-imx-d54cc007878697a92e7f696b71a3eb203c0386e2.zip
u-boot-imx-d54cc007878697a92e7f696b71a3eb203c0386e2.tar.gz
u-boot-imx-d54cc007878697a92e7f696b71a3eb203c0386e2.tar.bz2
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 <david.andrey@netmodule.com> Signed-off-by: Michal Simek <michal.simek@xilinx.com> Reviewed-by: Tom Rini <trini@ti.com>
-rw-r--r--arch/arm/cpu/armv7/zynq/timer.c46
1 files changed, 37 insertions, 9 deletions
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 */