1 /* 2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <arch_helpers.h> 8 #include <assert.h> 9 #include <bl_common.h> 10 #include <debug.h> 11 #include <delay_timer.h> 12 #include <platform.h> 13 14 /* Ticks elapsed in one second by a signal of 1 MHz */ 15 #define MHZ_TICKS_PER_SEC 1000000 16 17 static timer_ops_t ops; 18 19 static uint32_t get_timer_value(void) 20 { 21 /* 22 * Generic delay timer implementation expects the timer to be a down 23 * counter. We apply bitwise NOT operator to the tick values returned 24 * by read_cntpct_el0() to simulate the down counter. The value is 25 * clipped from 64 to 32 bits. 26 */ 27 return (uint32_t)(~read_cntpct_el0()); 28 } 29 30 void generic_delay_timer_init_args(uint32_t mult, uint32_t div) 31 { 32 ops.get_timer_value = get_timer_value; 33 ops.clk_mult = mult; 34 ops.clk_div = div; 35 36 timer_init(&ops); 37 38 VERBOSE("Generic delay timer configured with mult=%u and div=%u\n", 39 mult, div); 40 } 41 42 void generic_delay_timer_init(void) 43 { 44 /* Value in ticks */ 45 unsigned int mult = MHZ_TICKS_PER_SEC; 46 47 /* Value in ticks per second (Hz) */ 48 unsigned int div = plat_get_syscnt_freq2(); 49 50 /* Reduce multiplier and divider by dividing them repeatedly by 10 */ 51 while ((mult % 10 == 0) && (div % 10 == 0)) { 52 mult /= 10; 53 div /= 10; 54 } 55 56 generic_delay_timer_init_args(mult, div); 57 } 58 59