blob: 43f5af7b39d9040aa6a8a0de32418f7488d347c9 [file] [log] [blame]
Ryan Harkin32539fc2015-03-17 14:50:05 +00001/*
2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
3 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Ryan Harkin32539fc2015-03-17 14:50:05 +00005 */
6
7#include <assert.h>
8#include <delay_timer.h>
9#include <platform_def.h>
10
11/***********************************************************
12 * The delay timer implementation
13 ***********************************************************/
14static const timer_ops_t *ops;
15
16/***********************************************************
17 * Delay for the given number of microseconds. The driver must
18 * be initialized before calling this function.
19 ***********************************************************/
20void udelay(uint32_t usec)
21{
Etienne Carrieref4eecb22017-06-07 16:42:26 +020022 assert(ops != NULL &&
Ryan Harkin32539fc2015-03-17 14:50:05 +000023 (ops->clk_mult != 0) &&
24 (ops->clk_div != 0) &&
Etienne Carrieref4eecb22017-06-07 16:42:26 +020025 (ops->get_timer_value != NULL));
Ryan Harkin32539fc2015-03-17 14:50:05 +000026
Antonio Nino Diazbcd79b22016-05-18 10:37:25 +010027 uint32_t start, delta, total_delta;
Ryan Harkin32539fc2015-03-17 14:50:05 +000028
Antonio Nino Diazbcd79b22016-05-18 10:37:25 +010029 assert(usec < UINT32_MAX / ops->clk_div);
30
Ryan Harkin32539fc2015-03-17 14:50:05 +000031 start = ops->get_timer_value();
Antonio Nino Diazbcd79b22016-05-18 10:37:25 +010032
33 total_delta = (usec * ops->clk_div) / ops->clk_mult;
34
Ryan Harkin32539fc2015-03-17 14:50:05 +000035 do {
Antonio Nino Diazbcd79b22016-05-18 10:37:25 +010036 /*
37 * If the timer value wraps around, the subtraction will
38 * overflow and it will still give the correct result.
39 */
40 delta = start - ops->get_timer_value(); /* Decreasing counter */
41
42 } while (delta < total_delta);
Ryan Harkin32539fc2015-03-17 14:50:05 +000043}
44
45/***********************************************************
46 * Delay for the given number of milliseconds. The driver must
47 * be initialized before calling this function.
48 ***********************************************************/
49void mdelay(uint32_t msec)
50{
51 udelay(msec*1000);
52}
53
54/***********************************************************
55 * Initialize the timer. The fields in the provided timer
56 * ops pointer must be valid.
57 ***********************************************************/
58void timer_init(const timer_ops_t *ops_ptr)
59{
Etienne Carrieref4eecb22017-06-07 16:42:26 +020060 assert(ops_ptr != NULL &&
Ryan Harkin32539fc2015-03-17 14:50:05 +000061 (ops_ptr->clk_mult != 0) &&
62 (ops_ptr->clk_div != 0) &&
Etienne Carrieref4eecb22017-06-07 16:42:26 +020063 (ops_ptr->get_timer_value != NULL));
Ryan Harkin32539fc2015-03-17 14:50:05 +000064
65 ops = ops_ptr;
66}