mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-17 01:54:22 +00:00

The delay_timer driver for Tegra uses the CNTPS_TVAL_EL1 secure, physical, decrementing timer as the source. The current logic incorrectly marks this as an incrementing timer, by negating the timer value. This patch fixes the anomaly and updates the driver to remove this logic. Signed-off-by: anzhou <anzhou@nvidia.com> Change-Id: I60490bdcaf0b66bf4553a6de3f4e4e32109017f4
57 lines
1.5 KiB
C
57 lines
1.5 KiB
C
/*
|
|
* 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 <arch.h>
|
|
|
|
#include <drivers/delay_timer.h>
|
|
#include <lib/mmio.h>
|
|
#include <lib/utils_def.h>
|
|
#include <plat/common/platform.h>
|
|
|
|
#include <tegra_def.h>
|
|
#include <tegra_private.h>
|
|
|
|
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);
|
|
}
|