xref: /rk3399_ARM-atf/plat/nvidia/tegra/common/tegra_delay_timer.c (revision 923c221b6d94c16678abca04ab76b633b052b585)
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