From 0bcedb2212bd2436834117cd956d7b6e16b11673 Mon Sep 17 00:00:00 2001 From: Antonio Nino Diaz Date: Wed, 18 May 2016 10:37:25 +0100 Subject: Implement generic delay timer Add delay timer implementation based on the system generic counter. This either uses the platform's implementation of `plat_get_syscnt_freq()` or explicit clock multiplier/divider values provided by the platform. The current implementation of udelay has been modified to avoid unnecessary calculations while waiting on the loop and to make it easier to check for overflows. Change-Id: I9062e1d506dc2f68367fd9289250b93444721732 --- drivers/delay_timer/delay_timer.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers/delay_timer/delay_timer.c') diff --git a/drivers/delay_timer/delay_timer.c b/drivers/delay_timer/delay_timer.c index 0bee876f..ed7ed52e 100644 --- a/drivers/delay_timer/delay_timer.c +++ b/drivers/delay_timer/delay_timer.c @@ -48,19 +48,22 @@ void udelay(uint32_t usec) (ops->clk_div != 0) && (ops->get_timer_value != 0)); - uint32_t start, cnt, delta, delta_us; + uint32_t start, delta, total_delta; + + assert(usec < UINT32_MAX / ops->clk_div); - /* counter is decreasing */ start = ops->get_timer_value(); + + total_delta = (usec * ops->clk_div) / ops->clk_mult; + do { - cnt = ops->get_timer_value(); - if (cnt > start) { - delta = UINT32_MAX - cnt; - delta += start; - } else - delta = start - cnt; - delta_us = (delta * ops->clk_mult) / ops->clk_div; - } while (delta_us < usec); + /* + * If the timer value wraps around, the subtraction will + * overflow and it will still give the correct result. + */ + delta = start - ops->get_timer_value(); /* Decreasing counter */ + + } while (delta < total_delta); } /*********************************************************** -- cgit