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