summaryrefslogtreecommitdiff
path: root/drivers/delay_timer/delay_timer.c
diff options
context:
space:
mode:
authordanh-arm <dan.handley@arm.com>2016-05-24 16:12:08 +0100
committerdanh-arm <dan.handley@arm.com>2016-05-24 16:12:08 +0100
commite141aa0357fd4977ba874f4f86874e2cadc73498 (patch)
treecc01a644b84f7e07215a4920c3053ce4ddfb3f50 /drivers/delay_timer/delay_timer.c
parentd1d716531db8d52101d9168a79d4b6acaef976fe (diff)
parent6704f425ddb2772bd9a2b9dacacbefcbb00dcf28 (diff)
Merge pull request #625 from antonio-nino-diaz-arm/an/delay-timer-v2
Implement generic delay timer and use it on platforms
Diffstat (limited to 'drivers/delay_timer/delay_timer.c')
-rw-r--r--drivers/delay_timer/delay_timer.c23
1 files changed, 13 insertions, 10 deletions
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);
}
/***********************************************************