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