1c8961326SVarun Wadekar /* 23436089dSAnthony Zhou * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. 3dd4f0885SVarun Wadekar * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. 4c8961326SVarun Wadekar * 582cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 6c8961326SVarun Wadekar */ 7c8961326SVarun Wadekar 8dd4f0885SVarun Wadekar #include <arch.h> 9dd4f0885SVarun Wadekar 1009d40e0eSAntonio Nino Diaz #include <drivers/delay_timer.h> 1109d40e0eSAntonio Nino Diaz #include <lib/mmio.h> 12dd4f0885SVarun Wadekar #include <lib/utils_def.h> 13dd4f0885SVarun Wadekar #include <plat/common/platform.h> 1409d40e0eSAntonio Nino Diaz 15c8961326SVarun Wadekar #include <tegra_def.h> 163436089dSAnthony Zhou #include <tegra_private.h> 17c8961326SVarun Wadekar 18dd4f0885SVarun Wadekar static uint32_t tegra_timer_get_value(void) 19c8961326SVarun Wadekar { 20dd4f0885SVarun Wadekar /* enable cntps_tval_el1 timer, mask interrupt */ 21dd4f0885SVarun Wadekar write_cntps_ctl_el1(CNTP_CTL_IMASK_BIT | CNTP_CTL_ENABLE_BIT); 22dd4f0885SVarun Wadekar 23dd4f0885SVarun Wadekar /* 24dd4f0885SVarun Wadekar * Generic delay timer implementation expects the timer to be a down 25*923c221bSanzhou * counter. The value is clipped from 64 to 32 bits. 26dd4f0885SVarun Wadekar */ 27*923c221bSanzhou return (uint32_t)(read_cntps_tval_el1()); 28c8961326SVarun Wadekar } 29c8961326SVarun Wadekar 30c8961326SVarun Wadekar /* 31dd4f0885SVarun Wadekar * Initialise the architecture provided counter as the delay timer. 32c8961326SVarun Wadekar */ 33c8961326SVarun Wadekar void tegra_delay_timer_init(void) 34c8961326SVarun Wadekar { 35dd4f0885SVarun Wadekar static timer_ops_t tegra_timer_ops; 363436089dSAnthony Zhou 37dd4f0885SVarun Wadekar /* Value in ticks */ 38dd4f0885SVarun Wadekar uint32_t multiplier = MHZ_TICKS_PER_SEC; 39dd4f0885SVarun Wadekar 40dd4f0885SVarun Wadekar /* Value in ticks per second (Hz) */ 41dd4f0885SVarun Wadekar uint32_t divider = plat_get_syscnt_freq2(); 42dd4f0885SVarun Wadekar 43dd4f0885SVarun Wadekar /* Reduce multiplier and divider by dividing them repeatedly by 10 */ 44dd4f0885SVarun Wadekar while (((multiplier % 10U) == 0U) && ((divider % 10U) == 0U)) { 45dd4f0885SVarun Wadekar multiplier /= 10U; 46dd4f0885SVarun Wadekar divider /= 10U; 47dd4f0885SVarun Wadekar } 48dd4f0885SVarun Wadekar 49dd4f0885SVarun Wadekar /* enable cntps_tval_el1 timer, mask interrupt */ 50dd4f0885SVarun Wadekar write_cntps_ctl_el1(CNTP_CTL_IMASK_BIT | CNTP_CTL_ENABLE_BIT); 51dd4f0885SVarun Wadekar 52dd4f0885SVarun Wadekar /* register the timer */ 53dd4f0885SVarun Wadekar tegra_timer_ops.get_timer_value = tegra_timer_get_value; 54dd4f0885SVarun Wadekar tegra_timer_ops.clk_mult = multiplier; 55dd4f0885SVarun Wadekar tegra_timer_ops.clk_div = divider; 56c8961326SVarun Wadekar timer_init(&tegra_timer_ops); 57c8961326SVarun Wadekar } 58