1bc149bfcSSoby Mathew /* 21af540efSRoberto Vargas * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. 3bc149bfcSSoby Mathew * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 5bc149bfcSSoby Mathew */ 6bc149bfcSSoby Mathew #include <arch.h> 7bc149bfcSSoby Mathew #include <arch_helpers.h> 8bc149bfcSSoby Mathew #include <assert.h> 9bc149bfcSSoby Mathew #include <debug.h> 10bc149bfcSSoby Mathew #include <mmio.h> 11bc149bfcSSoby Mathew #include <plat_arm.h> 121af540efSRoberto Vargas #include <platform.h> 131eb735d7SRoberto Vargas #include <platform_def.h> 141eb735d7SRoberto Vargas #include <romlib.h> 15e29efeb1SAntonio Nino Diaz #include <secure_partition.h> 1603987d01SAntonio Nino Diaz #include <xlat_tables_compat.h> 17bc149bfcSSoby Mathew 18bc149bfcSSoby Mathew /* Weak definitions may be overridden in specific ARM standard platform */ 19bc149bfcSSoby Mathew #pragma weak plat_get_ns_image_entrypoint 20bc149bfcSSoby Mathew #pragma weak plat_arm_get_mmap 21bc149bfcSSoby Mathew 22bc149bfcSSoby Mathew /* Conditionally provide a weak definition of plat_get_syscnt_freq2 to avoid 23bc149bfcSSoby Mathew * conflicts with the definition in plat/common. */ 24bc149bfcSSoby Mathew #pragma weak plat_get_syscnt_freq2 25bc149bfcSSoby Mathew 261eb735d7SRoberto Vargas 271eb735d7SRoberto Vargas void arm_setup_romlib(void) 281eb735d7SRoberto Vargas { 291eb735d7SRoberto Vargas #if USE_ROMLIB 301eb735d7SRoberto Vargas if (!rom_lib_init(ROMLIB_VERSION)) 311eb735d7SRoberto Vargas panic(); 321eb735d7SRoberto Vargas #endif 331eb735d7SRoberto Vargas } 341eb735d7SRoberto Vargas 35bc149bfcSSoby Mathew uintptr_t plat_get_ns_image_entrypoint(void) 36bc149bfcSSoby Mathew { 3748ac1df9SSoby Mathew #ifdef PRELOADED_BL33_BASE 3848ac1df9SSoby Mathew return PRELOADED_BL33_BASE; 3948ac1df9SSoby Mathew #else 40bc149bfcSSoby Mathew return PLAT_ARM_NS_IMAGE_OFFSET; 4148ac1df9SSoby Mathew #endif 42bc149bfcSSoby Mathew } 43bc149bfcSSoby Mathew 44bc149bfcSSoby Mathew /******************************************************************************* 45bc149bfcSSoby Mathew * Gets SPSR for BL32 entry 46bc149bfcSSoby Mathew ******************************************************************************/ 47bc149bfcSSoby Mathew uint32_t arm_get_spsr_for_bl32_entry(void) 48bc149bfcSSoby Mathew { 49bc149bfcSSoby Mathew /* 50bc149bfcSSoby Mathew * The Secure Payload Dispatcher service is responsible for 51bc149bfcSSoby Mathew * setting the SPSR prior to entry into the BL32 image. 52bc149bfcSSoby Mathew */ 53bc149bfcSSoby Mathew return 0; 54bc149bfcSSoby Mathew } 55bc149bfcSSoby Mathew 56bc149bfcSSoby Mathew /******************************************************************************* 57bc149bfcSSoby Mathew * Gets SPSR for BL33 entry 58bc149bfcSSoby Mathew ******************************************************************************/ 59877cf3ffSSoby Mathew #ifndef AARCH32 60bc149bfcSSoby Mathew uint32_t arm_get_spsr_for_bl33_entry(void) 61bc149bfcSSoby Mathew { 62bc149bfcSSoby Mathew unsigned int mode; 63bc149bfcSSoby Mathew uint32_t spsr; 64bc149bfcSSoby Mathew 65bc149bfcSSoby Mathew /* Figure out what mode we enter the non-secure world in */ 66*a0fee747SAntonio Nino Diaz mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1; 67bc149bfcSSoby Mathew 68bc149bfcSSoby Mathew /* 69bc149bfcSSoby Mathew * TODO: Consider the possibility of specifying the SPSR in 70bc149bfcSSoby Mathew * the FIP ToC and allowing the platform to have a say as 71bc149bfcSSoby Mathew * well. 72bc149bfcSSoby Mathew */ 73bc149bfcSSoby Mathew spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); 74bc149bfcSSoby Mathew return spsr; 75bc149bfcSSoby Mathew } 76877cf3ffSSoby Mathew #else 77877cf3ffSSoby Mathew /******************************************************************************* 78877cf3ffSSoby Mathew * Gets SPSR for BL33 entry 79877cf3ffSSoby Mathew ******************************************************************************/ 80877cf3ffSSoby Mathew uint32_t arm_get_spsr_for_bl33_entry(void) 81877cf3ffSSoby Mathew { 82877cf3ffSSoby Mathew unsigned int hyp_status, mode, spsr; 83877cf3ffSSoby Mathew 84877cf3ffSSoby Mathew hyp_status = GET_VIRT_EXT(read_id_pfr1()); 85877cf3ffSSoby Mathew 86877cf3ffSSoby Mathew mode = (hyp_status) ? MODE32_hyp : MODE32_svc; 87877cf3ffSSoby Mathew 88877cf3ffSSoby Mathew /* 89877cf3ffSSoby Mathew * TODO: Consider the possibility of specifying the SPSR in 90877cf3ffSSoby Mathew * the FIP ToC and allowing the platform to have a say as 91877cf3ffSSoby Mathew * well. 92877cf3ffSSoby Mathew */ 93877cf3ffSSoby Mathew spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1, 94877cf3ffSSoby Mathew SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); 95877cf3ffSSoby Mathew return spsr; 96877cf3ffSSoby Mathew } 97877cf3ffSSoby Mathew #endif /* AARCH32 */ 98bc149bfcSSoby Mathew 99bc149bfcSSoby Mathew /******************************************************************************* 100bc149bfcSSoby Mathew * Configures access to the system counter timer module. 101bc149bfcSSoby Mathew ******************************************************************************/ 102bc149bfcSSoby Mathew #ifdef ARM_SYS_TIMCTL_BASE 103bc149bfcSSoby Mathew void arm_configure_sys_timer(void) 104bc149bfcSSoby Mathew { 105bc149bfcSSoby Mathew unsigned int reg_val; 106bc149bfcSSoby Mathew 107342d6220SSoby Mathew /* Read the frequency of the system counter */ 108342d6220SSoby Mathew unsigned int freq_val = plat_get_syscnt_freq2(); 109342d6220SSoby Mathew 110bc149bfcSSoby Mathew #if ARM_CONFIG_CNTACR 111bc149bfcSSoby Mathew reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT); 112bc149bfcSSoby Mathew reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT); 113bc149bfcSSoby Mathew reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT); 114bc149bfcSSoby Mathew mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTACR_BASE(PLAT_ARM_NSTIMER_FRAME_ID), reg_val); 115bc149bfcSSoby Mathew #endif /* ARM_CONFIG_CNTACR */ 116bc149bfcSSoby Mathew 117bc149bfcSSoby Mathew reg_val = (1 << CNTNSAR_NS_SHIFT(PLAT_ARM_NSTIMER_FRAME_ID)); 118bc149bfcSSoby Mathew mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTNSAR, reg_val); 119342d6220SSoby Mathew 120342d6220SSoby Mathew /* 121342d6220SSoby Mathew * Initialize CNTFRQ register in CNTCTLBase frame. The CNTFRQ 122342d6220SSoby Mathew * system register initialized during psci_arch_setup() is different 123342d6220SSoby Mathew * from this and has to be updated independently. 124342d6220SSoby Mathew */ 125342d6220SSoby Mathew mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTCTLBASE_CNTFRQ, freq_val); 126342d6220SSoby Mathew 127342d6220SSoby Mathew #ifdef PLAT_juno 128342d6220SSoby Mathew /* 129342d6220SSoby Mathew * Initialize CNTFRQ register in Non-secure CNTBase frame. 130342d6220SSoby Mathew * This is only required for Juno, because it doesn't follow ARM ARM 131342d6220SSoby Mathew * in that the value updated in CNTFRQ is not reflected in CNTBASE_CNTFRQ. 132342d6220SSoby Mathew * Hence update the value manually. 133342d6220SSoby Mathew */ 134342d6220SSoby Mathew mmio_write_32(ARM_SYS_CNT_BASE_NS + CNTBASE_CNTFRQ, freq_val); 135342d6220SSoby Mathew #endif 136bc149bfcSSoby Mathew } 137bc149bfcSSoby Mathew #endif /* ARM_SYS_TIMCTL_BASE */ 138bc149bfcSSoby Mathew 139bc149bfcSSoby Mathew /******************************************************************************* 140bc149bfcSSoby Mathew * Returns ARM platform specific memory map regions. 141bc149bfcSSoby Mathew ******************************************************************************/ 142bc149bfcSSoby Mathew const mmap_region_t *plat_arm_get_mmap(void) 143bc149bfcSSoby Mathew { 144bc149bfcSSoby Mathew return plat_arm_mmap; 145bc149bfcSSoby Mathew } 146bc149bfcSSoby Mathew 147bc149bfcSSoby Mathew #ifdef ARM_SYS_CNTCTL_BASE 148bc149bfcSSoby Mathew 149bc149bfcSSoby Mathew unsigned int plat_get_syscnt_freq2(void) 150bc149bfcSSoby Mathew { 151bc149bfcSSoby Mathew unsigned int counter_base_frequency; 152bc149bfcSSoby Mathew 153bc149bfcSSoby Mathew /* Read the frequency from Frequency modes table */ 154bc149bfcSSoby Mathew counter_base_frequency = mmio_read_32(ARM_SYS_CNTCTL_BASE + CNTFID_OFF); 155bc149bfcSSoby Mathew 156bc149bfcSSoby Mathew /* The first entry of the frequency modes table must not be 0 */ 157bc149bfcSSoby Mathew if (counter_base_frequency == 0) 158bc149bfcSSoby Mathew panic(); 159bc149bfcSSoby Mathew 160bc149bfcSSoby Mathew return counter_base_frequency; 161bc149bfcSSoby Mathew } 162bc149bfcSSoby Mathew 163bc149bfcSSoby Mathew #endif /* ARM_SYS_CNTCTL_BASE */ 164781f4aacSJeenu Viswambharan 165781f4aacSJeenu Viswambharan #if SDEI_SUPPORT 166781f4aacSJeenu Viswambharan /* 167781f4aacSJeenu Viswambharan * Translate SDEI entry point to PA, and perform standard ARM entry point 168781f4aacSJeenu Viswambharan * validation on it. 169781f4aacSJeenu Viswambharan */ 170781f4aacSJeenu Viswambharan int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode) 171781f4aacSJeenu Viswambharan { 172781f4aacSJeenu Viswambharan uint64_t par, pa; 173781f4aacSJeenu Viswambharan uint32_t scr_el3; 174781f4aacSJeenu Viswambharan 175781f4aacSJeenu Viswambharan /* Doing Non-secure address translation requires SCR_EL3.NS set */ 176781f4aacSJeenu Viswambharan scr_el3 = read_scr_el3(); 177781f4aacSJeenu Viswambharan write_scr_el3(scr_el3 | SCR_NS_BIT); 178781f4aacSJeenu Viswambharan isb(); 179781f4aacSJeenu Viswambharan 180781f4aacSJeenu Viswambharan assert((client_mode == MODE_EL2) || (client_mode == MODE_EL1)); 181781f4aacSJeenu Viswambharan if (client_mode == MODE_EL2) { 182781f4aacSJeenu Viswambharan /* 183781f4aacSJeenu Viswambharan * Translate entry point to Physical Address using the EL2 184781f4aacSJeenu Viswambharan * translation regime. 185781f4aacSJeenu Viswambharan */ 186781f4aacSJeenu Viswambharan ats1e2r(ep); 187781f4aacSJeenu Viswambharan } else { 188781f4aacSJeenu Viswambharan /* 189781f4aacSJeenu Viswambharan * Translate entry point to Physical Address using the EL1&0 190781f4aacSJeenu Viswambharan * translation regime, including stage 2. 191781f4aacSJeenu Viswambharan */ 192781f4aacSJeenu Viswambharan ats12e1r(ep); 193781f4aacSJeenu Viswambharan } 194781f4aacSJeenu Viswambharan isb(); 195781f4aacSJeenu Viswambharan par = read_par_el1(); 196781f4aacSJeenu Viswambharan 197781f4aacSJeenu Viswambharan /* Restore original SCRL_EL3 */ 198781f4aacSJeenu Viswambharan write_scr_el3(scr_el3); 199781f4aacSJeenu Viswambharan isb(); 200781f4aacSJeenu Viswambharan 201781f4aacSJeenu Viswambharan /* If the translation resulted in fault, return failure */ 202781f4aacSJeenu Viswambharan if ((par & PAR_F_MASK) != 0) 203781f4aacSJeenu Viswambharan return -1; 204781f4aacSJeenu Viswambharan 205781f4aacSJeenu Viswambharan /* Extract Physical Address from PAR */ 206781f4aacSJeenu Viswambharan pa = (par & (PAR_ADDR_MASK << PAR_ADDR_SHIFT)); 207781f4aacSJeenu Viswambharan 208781f4aacSJeenu Viswambharan /* Perform NS entry point validation on the physical address */ 209781f4aacSJeenu Viswambharan return arm_validate_ns_entrypoint(pa); 210781f4aacSJeenu Viswambharan } 211781f4aacSJeenu Viswambharan #endif 212