/* * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include static uint32_t tegra_timer_get_value(void) { /* enable cntps_tval_el1 timer, mask interrupt */ write_cntps_ctl_el1(CNTP_CTL_IMASK_BIT | CNTP_CTL_ENABLE_BIT); /* * Generic delay timer implementation expects the timer to be a down * counter. The value is clipped from 64 to 32 bits. */ return (uint32_t)(read_cntps_tval_el1()); } /* * Initialise the architecture provided counter as the delay timer. */ void tegra_delay_timer_init(void) { static timer_ops_t tegra_timer_ops; /* Value in ticks */ uint32_t multiplier = MHZ_TICKS_PER_SEC; /* Value in ticks per second (Hz) */ uint32_t divider = plat_get_syscnt_freq2(); /* Reduce multiplier and divider by dividing them repeatedly by 10 */ while (((multiplier % 10U) == 0U) && ((divider % 10U) == 0U)) { multiplier /= 10U; divider /= 10U; } /* enable cntps_tval_el1 timer, mask interrupt */ write_cntps_ctl_el1(CNTP_CTL_IMASK_BIT | CNTP_CTL_ENABLE_BIT); /* register the timer */ tegra_timer_ops.get_timer_value = tegra_timer_get_value; tegra_timer_ops.clk_mult = multiplier; tegra_timer_ops.clk_div = divider; timer_init(&tegra_timer_ops); }