xref: /rk3399_ARM-atf/drivers/nxp/timer/nxp_timer.c (revision 447a42e7355d39f43756af8e3f9a792cd2ccf8bd)
1*447a42e7SPankaj Gupta /*
2*447a42e7SPankaj Gupta  * Copyright 2021 NXP
3*447a42e7SPankaj Gupta  *
4*447a42e7SPankaj Gupta  * SPDX-License-Identifier: BSD-3-Clause
5*447a42e7SPankaj Gupta  *
6*447a42e7SPankaj Gupta  */
7*447a42e7SPankaj Gupta 
8*447a42e7SPankaj Gupta #include <arch_helpers.h>
9*447a42e7SPankaj Gupta #include <common/debug.h>
10*447a42e7SPankaj Gupta #include <drivers/delay_timer.h>
11*447a42e7SPankaj Gupta #include <lib/mmio.h>
12*447a42e7SPankaj Gupta #include <lib/utils_def.h>
13*447a42e7SPankaj Gupta #include <nxp_timer.h>
14*447a42e7SPankaj Gupta #include <plat/common/platform.h>
15*447a42e7SPankaj Gupta 
16*447a42e7SPankaj Gupta static uintptr_t g_nxp_timer_addr;
17*447a42e7SPankaj Gupta static timer_ops_t ops;
18*447a42e7SPankaj Gupta 
19*447a42e7SPankaj Gupta uint64_t get_timer_val(uint64_t start)
20*447a42e7SPankaj Gupta {
21*447a42e7SPankaj Gupta 	uint64_t cntpct;
22*447a42e7SPankaj Gupta 
23*447a42e7SPankaj Gupta 	isb();
24*447a42e7SPankaj Gupta 	cntpct = read_cntpct_el0();
25*447a42e7SPankaj Gupta 	return (cntpct * 1000ULL / read_cntfrq_el0() - start);
26*447a42e7SPankaj Gupta }
27*447a42e7SPankaj Gupta 
28*447a42e7SPankaj Gupta static uint32_t timer_get_value(void)
29*447a42e7SPankaj Gupta {
30*447a42e7SPankaj Gupta 	uint64_t cntpct;
31*447a42e7SPankaj Gupta 
32*447a42e7SPankaj Gupta 	isb();
33*447a42e7SPankaj Gupta 	cntpct = read_cntpct_el0();
34*447a42e7SPankaj Gupta #ifdef ERRATA_SOC_A008585
35*447a42e7SPankaj Gupta 	uint8_t	max_fetch_count = 10U;
36*447a42e7SPankaj Gupta 	/* This erratum number needs to be confirmed to match ARM document */
37*447a42e7SPankaj Gupta 	uint64_t temp;
38*447a42e7SPankaj Gupta 
39*447a42e7SPankaj Gupta 	isb();
40*447a42e7SPankaj Gupta 	temp = read_cntpct_el0();
41*447a42e7SPankaj Gupta 
42*447a42e7SPankaj Gupta 	while (temp != cntpct && max_fetch_count) {
43*447a42e7SPankaj Gupta 		isb();
44*447a42e7SPankaj Gupta 		cntpct = read_cntpct_el0();
45*447a42e7SPankaj Gupta 		isb();
46*447a42e7SPankaj Gupta 		temp = read_cntpct_el0();
47*447a42e7SPankaj Gupta 		max_fetch_count--;
48*447a42e7SPankaj Gupta 	}
49*447a42e7SPankaj Gupta #endif
50*447a42e7SPankaj Gupta 
51*447a42e7SPankaj Gupta 	/*
52*447a42e7SPankaj Gupta 	 * Generic delay timer implementation expects the timer to be a down
53*447a42e7SPankaj Gupta 	 * counter. We apply bitwise NOT operator to the tick values returned
54*447a42e7SPankaj Gupta 	 * by read_cntpct_el0() to simulate the down counter. The value is
55*447a42e7SPankaj Gupta 	 * clipped from 64 to 32 bits.
56*447a42e7SPankaj Gupta 	 */
57*447a42e7SPankaj Gupta 	return (uint32_t)(~cntpct);
58*447a42e7SPankaj Gupta }
59*447a42e7SPankaj Gupta 
60*447a42e7SPankaj Gupta static void delay_timer_init_args(uint32_t mult, uint32_t div)
61*447a42e7SPankaj Gupta {
62*447a42e7SPankaj Gupta 	ops.get_timer_value	= timer_get_value,
63*447a42e7SPankaj Gupta 	ops.clk_mult		= mult;
64*447a42e7SPankaj Gupta 	ops.clk_div		= div;
65*447a42e7SPankaj Gupta 
66*447a42e7SPankaj Gupta 	timer_init(&ops);
67*447a42e7SPankaj Gupta 
68*447a42e7SPankaj Gupta 	VERBOSE("Generic delay timer configured with mult=%u and div=%u\n",
69*447a42e7SPankaj Gupta 		mult, div);
70*447a42e7SPankaj Gupta }
71*447a42e7SPankaj Gupta 
72*447a42e7SPankaj Gupta /*
73*447a42e7SPankaj Gupta  * Initialise the nxp on-chip free rolling usec counter as the delay
74*447a42e7SPankaj Gupta  * timer.
75*447a42e7SPankaj Gupta  */
76*447a42e7SPankaj Gupta void delay_timer_init(uintptr_t nxp_timer_addr)
77*447a42e7SPankaj Gupta {
78*447a42e7SPankaj Gupta 	/* Value in ticks */
79*447a42e7SPankaj Gupta 	unsigned int mult = MHZ_TICKS_PER_SEC;
80*447a42e7SPankaj Gupta 
81*447a42e7SPankaj Gupta 	unsigned int div;
82*447a42e7SPankaj Gupta 
83*447a42e7SPankaj Gupta 	unsigned int counter_base_frequency = plat_get_syscnt_freq2();
84*447a42e7SPankaj Gupta 
85*447a42e7SPankaj Gupta 	g_nxp_timer_addr = nxp_timer_addr;
86*447a42e7SPankaj Gupta 	/* Rounding off the Counter Frequency to MHZ_TICKS_PER_SEC */
87*447a42e7SPankaj Gupta 	if (counter_base_frequency > MHZ_TICKS_PER_SEC) {
88*447a42e7SPankaj Gupta 		counter_base_frequency = (counter_base_frequency
89*447a42e7SPankaj Gupta 					/ MHZ_TICKS_PER_SEC)
90*447a42e7SPankaj Gupta 					* MHZ_TICKS_PER_SEC;
91*447a42e7SPankaj Gupta 	} else {
92*447a42e7SPankaj Gupta 		counter_base_frequency = (counter_base_frequency
93*447a42e7SPankaj Gupta 					/ KHZ_TICKS_PER_SEC)
94*447a42e7SPankaj Gupta 					* KHZ_TICKS_PER_SEC;
95*447a42e7SPankaj Gupta 	}
96*447a42e7SPankaj Gupta 
97*447a42e7SPankaj Gupta 	/* Value in ticks per second (Hz) */
98*447a42e7SPankaj Gupta 	div = counter_base_frequency;
99*447a42e7SPankaj Gupta 
100*447a42e7SPankaj Gupta 	/* Reduce multiplier and divider by dividing them repeatedly by 10 */
101*447a42e7SPankaj Gupta 	while ((mult % 10U == 0U) && (div % 10U == 0U)) {
102*447a42e7SPankaj Gupta 		mult /= 10U;
103*447a42e7SPankaj Gupta 		div /= 10U;
104*447a42e7SPankaj Gupta 	}
105*447a42e7SPankaj Gupta 
106*447a42e7SPankaj Gupta 	/* Enable and initialize the System level generic timer */
107*447a42e7SPankaj Gupta 	mmio_write_32(g_nxp_timer_addr + CNTCR_OFF,
108*447a42e7SPankaj Gupta 			CNTCR_FCREQ(0) | CNTCR_EN);
109*447a42e7SPankaj Gupta 
110*447a42e7SPankaj Gupta 	delay_timer_init_args(mult, div);
111*447a42e7SPankaj Gupta }
112*447a42e7SPankaj Gupta 
113*447a42e7SPankaj Gupta 
114*447a42e7SPankaj Gupta #ifdef IMAGE_BL31
115*447a42e7SPankaj Gupta /*******************************************************************************
116*447a42e7SPankaj Gupta  * TBD: Configures access to the system counter timer module.
117*447a42e7SPankaj Gupta  ******************************************************************************/
118*447a42e7SPankaj Gupta void ls_configure_sys_timer(uintptr_t ls_sys_timctl_base,
119*447a42e7SPankaj Gupta 			    uint8_t ls_config_cntacr,
120*447a42e7SPankaj Gupta 			    uint8_t plat_ls_ns_timer_frame_id)
121*447a42e7SPankaj Gupta {
122*447a42e7SPankaj Gupta 	unsigned int reg_val;
123*447a42e7SPankaj Gupta 
124*447a42e7SPankaj Gupta 	if (ls_config_cntacr == 1U) {
125*447a42e7SPankaj Gupta 		reg_val = (1U << CNTACR_RPCT_SHIFT) | (1U << CNTACR_RVCT_SHIFT);
126*447a42e7SPankaj Gupta 		reg_val |= (1U << CNTACR_RFRQ_SHIFT) | (1U << CNTACR_RVOFF_SHIFT);
127*447a42e7SPankaj Gupta 		reg_val |= (1U << CNTACR_RWVT_SHIFT) | (1U << CNTACR_RWPT_SHIFT);
128*447a42e7SPankaj Gupta 		mmio_write_32(ls_sys_timctl_base +
129*447a42e7SPankaj Gupta 		      CNTACR_BASE(plat_ls_ns_timer_frame_id), reg_val);
130*447a42e7SPankaj Gupta 		mmio_write_32(ls_sys_timctl_base, plat_get_syscnt_freq2());
131*447a42e7SPankaj Gupta 	}
132*447a42e7SPankaj Gupta 
133*447a42e7SPankaj Gupta 	reg_val = (1U << CNTNSAR_NS_SHIFT(plat_ls_ns_timer_frame_id));
134*447a42e7SPankaj Gupta 	mmio_write_32(ls_sys_timctl_base + CNTNSAR, reg_val);
135*447a42e7SPankaj Gupta }
136*447a42e7SPankaj Gupta 
137*447a42e7SPankaj Gupta void enable_init_timer(void)
138*447a42e7SPankaj Gupta {
139*447a42e7SPankaj Gupta 	/* Enable and initialize the System level generic timer */
140*447a42e7SPankaj Gupta 	mmio_write_32(g_nxp_timer_addr + CNTCR_OFF,
141*447a42e7SPankaj Gupta 			CNTCR_FCREQ(0) | CNTCR_EN);
142*447a42e7SPankaj Gupta }
143*447a42e7SPankaj Gupta #endif
144