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