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 != 0) && 25 (timer_ops->clk_div != 0) && 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, timer_ops->clk_mult) + 1; 37 38 do { 39 /* 40 * If the timer value wraps around, the subtraction will 41 * overflow and it will still give the correct result. 42 */ 43 delta = start - timer_ops->get_timer_value(); /* Decreasing counter */ 44 45 } while (delta < total_delta); 46 } 47 48 /*********************************************************** 49 * Delay for the given number of milliseconds. The driver must 50 * be initialized before calling this function. 51 ***********************************************************/ 52 void mdelay(uint32_t msec) 53 { 54 udelay(msec*1000); 55 } 56 57 /*********************************************************** 58 * Initialize the timer. The fields in the provided timer 59 * ops pointer must be valid. 60 ***********************************************************/ 61 void timer_init(const timer_ops_t *ops_ptr) 62 { 63 assert(ops_ptr != NULL && 64 (ops_ptr->clk_mult != 0) && 65 (ops_ptr->clk_div != 0) && 66 (ops_ptr->get_timer_value != NULL)); 67 68 timer_ops = ops_ptr; 69 } 70