xref: /aosp_15_r20/external/arm-trusted-firmware/bl32/tsp/tsp_timer.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park  * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park  *
4*54fd6939SJiyong Park  * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park  */
6*54fd6939SJiyong Park 
7*54fd6939SJiyong Park #include <assert.h>
8*54fd6939SJiyong Park 
9*54fd6939SJiyong Park #include <arch_helpers.h>
10*54fd6939SJiyong Park #include <plat/common/platform.h>
11*54fd6939SJiyong Park 
12*54fd6939SJiyong Park #include "tsp_private.h"
13*54fd6939SJiyong Park 
14*54fd6939SJiyong Park /*******************************************************************************
15*54fd6939SJiyong Park  * Data structure to keep track of per-cpu secure generic timer context across
16*54fd6939SJiyong Park  * power management operations.
17*54fd6939SJiyong Park  ******************************************************************************/
18*54fd6939SJiyong Park typedef struct timer_context {
19*54fd6939SJiyong Park 	uint64_t cval;
20*54fd6939SJiyong Park 	uint32_t ctl;
21*54fd6939SJiyong Park } timer_context_t;
22*54fd6939SJiyong Park 
23*54fd6939SJiyong Park static timer_context_t pcpu_timer_context[PLATFORM_CORE_COUNT];
24*54fd6939SJiyong Park 
25*54fd6939SJiyong Park /*******************************************************************************
26*54fd6939SJiyong Park  * This function initializes the generic timer to fire every 0.5 second
27*54fd6939SJiyong Park  ******************************************************************************/
tsp_generic_timer_start(void)28*54fd6939SJiyong Park void tsp_generic_timer_start(void)
29*54fd6939SJiyong Park {
30*54fd6939SJiyong Park 	uint64_t cval;
31*54fd6939SJiyong Park 	uint32_t ctl = 0;
32*54fd6939SJiyong Park 
33*54fd6939SJiyong Park 	/* The timer will fire every 0.5 second */
34*54fd6939SJiyong Park 	cval = read_cntpct_el0() + (read_cntfrq_el0() >> 1);
35*54fd6939SJiyong Park 	write_cntps_cval_el1(cval);
36*54fd6939SJiyong Park 
37*54fd6939SJiyong Park 	/* Enable the secure physical timer */
38*54fd6939SJiyong Park 	set_cntp_ctl_enable(ctl);
39*54fd6939SJiyong Park 	write_cntps_ctl_el1(ctl);
40*54fd6939SJiyong Park }
41*54fd6939SJiyong Park 
42*54fd6939SJiyong Park /*******************************************************************************
43*54fd6939SJiyong Park  * This function deasserts the timer interrupt and sets it up again
44*54fd6939SJiyong Park  ******************************************************************************/
tsp_generic_timer_handler(void)45*54fd6939SJiyong Park void tsp_generic_timer_handler(void)
46*54fd6939SJiyong Park {
47*54fd6939SJiyong Park 	/* Ensure that the timer did assert the interrupt */
48*54fd6939SJiyong Park 	assert(get_cntp_ctl_istatus(read_cntps_ctl_el1()));
49*54fd6939SJiyong Park 
50*54fd6939SJiyong Park 	/*
51*54fd6939SJiyong Park 	 * Disable the timer and reprogram it. The barriers ensure that there is
52*54fd6939SJiyong Park 	 * no reordering of instructions around the reprogramming code.
53*54fd6939SJiyong Park 	 */
54*54fd6939SJiyong Park 	isb();
55*54fd6939SJiyong Park 	write_cntps_ctl_el1(0);
56*54fd6939SJiyong Park 	tsp_generic_timer_start();
57*54fd6939SJiyong Park 	isb();
58*54fd6939SJiyong Park }
59*54fd6939SJiyong Park 
60*54fd6939SJiyong Park /*******************************************************************************
61*54fd6939SJiyong Park  * This function deasserts the timer interrupt prior to cpu power down
62*54fd6939SJiyong Park  ******************************************************************************/
tsp_generic_timer_stop(void)63*54fd6939SJiyong Park void tsp_generic_timer_stop(void)
64*54fd6939SJiyong Park {
65*54fd6939SJiyong Park 	/* Disable the timer */
66*54fd6939SJiyong Park 	write_cntps_ctl_el1(0);
67*54fd6939SJiyong Park }
68*54fd6939SJiyong Park 
69*54fd6939SJiyong Park /*******************************************************************************
70*54fd6939SJiyong Park  * This function saves the timer context prior to cpu suspension
71*54fd6939SJiyong Park  ******************************************************************************/
tsp_generic_timer_save(void)72*54fd6939SJiyong Park void tsp_generic_timer_save(void)
73*54fd6939SJiyong Park {
74*54fd6939SJiyong Park 	uint32_t linear_id = plat_my_core_pos();
75*54fd6939SJiyong Park 
76*54fd6939SJiyong Park 	pcpu_timer_context[linear_id].cval = read_cntps_cval_el1();
77*54fd6939SJiyong Park 	pcpu_timer_context[linear_id].ctl = read_cntps_ctl_el1();
78*54fd6939SJiyong Park 	flush_dcache_range((uint64_t) &pcpu_timer_context[linear_id],
79*54fd6939SJiyong Park 			   sizeof(pcpu_timer_context[linear_id]));
80*54fd6939SJiyong Park }
81*54fd6939SJiyong Park 
82*54fd6939SJiyong Park /*******************************************************************************
83*54fd6939SJiyong Park  * This function restores the timer context post cpu resumption
84*54fd6939SJiyong Park  ******************************************************************************/
tsp_generic_timer_restore(void)85*54fd6939SJiyong Park void tsp_generic_timer_restore(void)
86*54fd6939SJiyong Park {
87*54fd6939SJiyong Park 	uint32_t linear_id = plat_my_core_pos();
88*54fd6939SJiyong Park 
89*54fd6939SJiyong Park 	write_cntps_cval_el1(pcpu_timer_context[linear_id].cval);
90*54fd6939SJiyong Park 	write_cntps_ctl_el1(pcpu_timer_context[linear_id].ctl);
91*54fd6939SJiyong Park }
92