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)25void 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)42void 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)60void 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)69void 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)82void 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