diff options
Diffstat (limited to 'plat/nvidia/tegra/common/tegra_delay_timer.c')
-rw-r--r-- | plat/nvidia/tegra/common/tegra_delay_timer.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/plat/nvidia/tegra/common/tegra_delay_timer.c b/plat/nvidia/tegra/common/tegra_delay_timer.c new file mode 100644 index 0000000..d9547c4 --- /dev/null +++ b/plat/nvidia/tegra/common/tegra_delay_timer.c @@ -0,0 +1,57 @@ +/* + * 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); +} |