1 /* 2 * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <delay_timer.h> 9 #include <platform_def.h> 10 #include <utils_def.h> 11 12 /*********************************************************** 13 * The delay timer implementation 14 ***********************************************************/ 15 static const timer_ops_t *timer_ops; 16 17 /*********************************************************** 18 * Delay for the given number of microseconds. The driver must 19 * be initialized before calling this function. 20 ***********************************************************/ 21 void udelay(uint32_t usec) 22 { 23 assert((timer_ops != NULL) && 24 (timer_ops->clk_mult != 0U) && 25 (timer_ops->clk_div != 0U) && 26 (timer_ops->get_timer_value != NULL)); 27 28 uint32_t start, delta, total_delta; 29 30 assert(usec < (UINT32_MAX / timer_ops->clk_div)); 31 32 start = timer_ops->get_timer_value(); 33 34 /* Add an extra tick to avoid delaying less than requested. */ 35 total_delta = 36 div_round_up(usec * timer_ops->clk_div, 37 timer_ops->clk_mult) + 1U; 38 39 do { 40 /* 41 * If the timer value wraps around, the subtraction will 42 * overflow and it will still give the correct result. 43 */ 44 delta = start - timer_ops->get_timer_value(); /* Decreasing counter */ 45 46 } while (delta < total_delta); 47 } 48 49 /*********************************************************** 50 * Delay for the given number of milliseconds. The driver must 51 * be initialized before calling this function. 52 ***********************************************************/ 53 void mdelay(uint32_t msec) 54 { 55 udelay(msec * 1000U); 56 } 57 58 /*********************************************************** 59 * Initialize the timer. The fields in the provided timer 60 * ops pointer must be valid. 61 ***********************************************************/ 62 void timer_init(const timer_ops_t *ops_ptr) 63 { 64 assert((ops_ptr != NULL) && 65 (ops_ptr->clk_mult != 0U) && 66 (ops_ptr->clk_div != 0U) && 67 (ops_ptr->get_timer_value != NULL)); 68 69 timer_ops = ops_ptr; 70 } 71