1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. 4*91f16700Schasinglulu * 5*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu #include <assert.h> 9*91f16700Schasinglulu #include <errno.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <arch.h> 12*91f16700Schasinglulu #include <arch_helpers.h> 13*91f16700Schasinglulu #include <common/bl_common.h> 14*91f16700Schasinglulu #include <common/debug.h> 15*91f16700Schasinglulu #include <common/runtime_svc.h> 16*91f16700Schasinglulu #include <lib/mmio.h> 17*91f16700Schasinglulu 18*91f16700Schasinglulu #include <memctrl.h> 19*91f16700Schasinglulu #include <tegra_platform.h> 20*91f16700Schasinglulu #include <tegra_private.h> 21*91f16700Schasinglulu 22*91f16700Schasinglulu /******************************************************************************* 23*91f16700Schasinglulu * Common Tegra SiP SMCs 24*91f16700Schasinglulu ******************************************************************************/ 25*91f16700Schasinglulu #define TEGRA_SIP_NEW_VIDEOMEM_REGION 0x82000003 26*91f16700Schasinglulu #define TEGRA_SIP_FIQ_NS_ENTRYPOINT 0x82000005 27*91f16700Schasinglulu #define TEGRA_SIP_FIQ_NS_GET_CONTEXT 0x82000006 28*91f16700Schasinglulu 29*91f16700Schasinglulu /******************************************************************************* 30*91f16700Schasinglulu * This function is responsible for handling all SiP calls 31*91f16700Schasinglulu ******************************************************************************/ 32*91f16700Schasinglulu uintptr_t tegra_sip_handler(uint32_t smc_fid, 33*91f16700Schasinglulu u_register_t x1, 34*91f16700Schasinglulu u_register_t x2, 35*91f16700Schasinglulu u_register_t x3, 36*91f16700Schasinglulu u_register_t x4, 37*91f16700Schasinglulu void *cookie, 38*91f16700Schasinglulu void *handle, 39*91f16700Schasinglulu u_register_t flags) 40*91f16700Schasinglulu { 41*91f16700Schasinglulu uint32_t regval, local_x2_32 = (uint32_t)x2; 42*91f16700Schasinglulu int32_t err; 43*91f16700Schasinglulu 44*91f16700Schasinglulu /* Check if this is a SoC specific SiP */ 45*91f16700Schasinglulu err = plat_sip_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags); 46*91f16700Schasinglulu if (err == 0) { 47*91f16700Schasinglulu 48*91f16700Schasinglulu SMC_RET1(handle, (uint64_t)err); 49*91f16700Schasinglulu 50*91f16700Schasinglulu } else { 51*91f16700Schasinglulu 52*91f16700Schasinglulu switch (smc_fid) { 53*91f16700Schasinglulu 54*91f16700Schasinglulu case TEGRA_SIP_NEW_VIDEOMEM_REGION: 55*91f16700Schasinglulu /* Check whether Video memory resize is enabled */ 56*91f16700Schasinglulu if (mmio_read_32(TEGRA_MC_BASE + MC_VIDEO_PROTECT_REG_CTRL) 57*91f16700Schasinglulu != MC_VIDEO_PROTECT_WRITE_ACCESS_ENABLED) { 58*91f16700Schasinglulu ERROR("Video Memory Resize isn't enabled! \n"); 59*91f16700Schasinglulu SMC_RET1(handle, (uint64_t)-ENOTSUP); 60*91f16700Schasinglulu } 61*91f16700Schasinglulu 62*91f16700Schasinglulu /* 63*91f16700Schasinglulu * Check if Video Memory overlaps TZDRAM (contains bl31/bl32) 64*91f16700Schasinglulu * or falls outside of the valid DRAM range 65*91f16700Schasinglulu */ 66*91f16700Schasinglulu err = bl31_check_ns_address(x1, local_x2_32); 67*91f16700Schasinglulu if (err != 0) { 68*91f16700Schasinglulu SMC_RET1(handle, (uint64_t)err); 69*91f16700Schasinglulu } 70*91f16700Schasinglulu 71*91f16700Schasinglulu /* 72*91f16700Schasinglulu * Check if Video Memory is aligned to 1MB. 73*91f16700Schasinglulu */ 74*91f16700Schasinglulu if (((x1 & 0xFFFFFU) != 0U) || ((local_x2_32 & 0xFFFFFU) != 0U)) { 75*91f16700Schasinglulu ERROR("Unaligned Video Memory base address!\n"); 76*91f16700Schasinglulu SMC_RET1(handle, (uint64_t)-ENOTSUP); 77*91f16700Schasinglulu } 78*91f16700Schasinglulu 79*91f16700Schasinglulu /* 80*91f16700Schasinglulu * The GPU is the user of the Video Memory region. In order to 81*91f16700Schasinglulu * transition to the new memory region smoothly, we program the 82*91f16700Schasinglulu * new base/size ONLY if the GPU is in reset mode. 83*91f16700Schasinglulu */ 84*91f16700Schasinglulu regval = mmio_read_32(TEGRA_CAR_RESET_BASE + 85*91f16700Schasinglulu TEGRA_GPU_RESET_REG_OFFSET); 86*91f16700Schasinglulu if ((regval & GPU_RESET_BIT) == 0U) { 87*91f16700Schasinglulu ERROR("GPU not in reset! Video Memory setup failed\n"); 88*91f16700Schasinglulu SMC_RET1(handle, (uint64_t)-ENOTSUP); 89*91f16700Schasinglulu } 90*91f16700Schasinglulu 91*91f16700Schasinglulu /* new video memory carveout settings */ 92*91f16700Schasinglulu tegra_memctrl_videomem_setup(x1, local_x2_32); 93*91f16700Schasinglulu 94*91f16700Schasinglulu /* 95*91f16700Schasinglulu * Ensure again that GPU is still in reset after VPR resize 96*91f16700Schasinglulu */ 97*91f16700Schasinglulu regval = mmio_read_32(TEGRA_CAR_RESET_BASE + 98*91f16700Schasinglulu TEGRA_GPU_RESET_REG_OFFSET); 99*91f16700Schasinglulu if ((regval & GPU_RESET_BIT) == 0U) { 100*91f16700Schasinglulu mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_GPU_SET_OFFSET, 101*91f16700Schasinglulu GPU_SET_BIT); 102*91f16700Schasinglulu } 103*91f16700Schasinglulu 104*91f16700Schasinglulu SMC_RET1(handle, 0); 105*91f16700Schasinglulu 106*91f16700Schasinglulu /* 107*91f16700Schasinglulu * The NS world registers the address of its handler to be 108*91f16700Schasinglulu * used for processing the FIQ. This is normally used by the 109*91f16700Schasinglulu * NS FIQ debugger driver to detect system hangs by programming 110*91f16700Schasinglulu * a watchdog timer to fire a FIQ interrupt. 111*91f16700Schasinglulu */ 112*91f16700Schasinglulu case TEGRA_SIP_FIQ_NS_ENTRYPOINT: 113*91f16700Schasinglulu 114*91f16700Schasinglulu if (x1 == 0U) { 115*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 116*91f16700Schasinglulu } 117*91f16700Schasinglulu 118*91f16700Schasinglulu /* 119*91f16700Schasinglulu * TODO: Check if x1 contains a valid DRAM address 120*91f16700Schasinglulu */ 121*91f16700Schasinglulu 122*91f16700Schasinglulu /* store the NS world's entrypoint */ 123*91f16700Schasinglulu tegra_fiq_set_ns_entrypoint(x1); 124*91f16700Schasinglulu 125*91f16700Schasinglulu SMC_RET1(handle, 0); 126*91f16700Schasinglulu 127*91f16700Schasinglulu /* 128*91f16700Schasinglulu * The NS world's FIQ handler issues this SMC to get the NS EL1/EL0 129*91f16700Schasinglulu * CPU context when the FIQ interrupt was triggered. This allows the 130*91f16700Schasinglulu * NS world to understand the CPU state when the watchdog interrupt 131*91f16700Schasinglulu * triggered. 132*91f16700Schasinglulu */ 133*91f16700Schasinglulu case TEGRA_SIP_FIQ_NS_GET_CONTEXT: 134*91f16700Schasinglulu 135*91f16700Schasinglulu /* retrieve context registers when FIQ triggered */ 136*91f16700Schasinglulu (void)tegra_fiq_get_intr_context(); 137*91f16700Schasinglulu 138*91f16700Schasinglulu SMC_RET0(handle); 139*91f16700Schasinglulu 140*91f16700Schasinglulu default: 141*91f16700Schasinglulu ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); 142*91f16700Schasinglulu break; 143*91f16700Schasinglulu } 144*91f16700Schasinglulu } 145*91f16700Schasinglulu 146*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 147*91f16700Schasinglulu } 148*91f16700Schasinglulu 149*91f16700Schasinglulu /* Define a runtime service descriptor for fast SMC calls */ 150*91f16700Schasinglulu DECLARE_RT_SVC( 151*91f16700Schasinglulu tegra_sip_fast, 152*91f16700Schasinglulu 153*91f16700Schasinglulu (OEN_SIP_START), 154*91f16700Schasinglulu (OEN_SIP_END), 155*91f16700Schasinglulu (SMC_TYPE_FAST), 156*91f16700Schasinglulu (NULL), 157*91f16700Schasinglulu (tegra_sip_handler) 158*91f16700Schasinglulu ); 159