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