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