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