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