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