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 <arch.h> 8 #include <arch_helpers.h> 9 #include <assert.h> 10 #include <bl_common.h> 11 #include <debug.h> 12 #include <errno.h> 13 #include <memctrl.h> 14 #include <mmio.h> 15 #include <runtime_svc.h> 16 #include <tegra_platform.h> 17 #include <tegra_private.h> 18 19 /******************************************************************************* 20 * Common Tegra SiP SMCs 21 ******************************************************************************/ 22 #define TEGRA_SIP_NEW_VIDEOMEM_REGION 0x82000003 23 #define TEGRA_SIP_FIQ_NS_ENTRYPOINT 0x82000005 24 #define TEGRA_SIP_FIQ_NS_GET_CONTEXT 0x82000006 25 #define TEGRA_SIP_ENABLE_FAKE_SYSTEM_SUSPEND 0xC2000007 26 27 /******************************************************************************* 28 * Fake system suspend mode control var 29 ******************************************************************************/ 30 extern uint8_t tegra_fake_system_suspend; 31 32 33 /******************************************************************************* 34 * SoC specific SiP handler 35 ******************************************************************************/ 36 #pragma weak plat_sip_handler 37 int plat_sip_handler(uint32_t smc_fid, 38 uint64_t x1, 39 uint64_t x2, 40 uint64_t x3, 41 uint64_t x4, 42 void *cookie, 43 void *handle, 44 uint64_t flags) 45 { 46 return -ENOTSUP; 47 } 48 49 /******************************************************************************* 50 * This function is responsible for handling all SiP calls 51 ******************************************************************************/ 52 uint64_t tegra_sip_handler(uint32_t smc_fid, 53 uint64_t x1, 54 uint64_t x2, 55 uint64_t x3, 56 uint64_t x4, 57 void *cookie, 58 void *handle, 59 uint64_t flags) 60 { 61 uint32_t regval; 62 int err; 63 64 /* Check if this is a SoC specific SiP */ 65 err = plat_sip_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags); 66 if (err == 0) 67 SMC_RET1(handle, (uint64_t)err); 68 69 switch (smc_fid) { 70 71 case TEGRA_SIP_NEW_VIDEOMEM_REGION: 72 73 /* clean up the high bits */ 74 x2 = (uint32_t)x2; 75 76 /* 77 * Check if Video Memory overlaps TZDRAM (contains bl31/bl32) 78 * or falls outside of the valid DRAM range 79 */ 80 err = bl31_check_ns_address(x1, x2); 81 if (err) 82 SMC_RET1(handle, err); 83 84 /* 85 * Check if Video Memory is aligned to 1MB. 86 */ 87 if ((x1 & 0xFFFFF) || (x2 & 0xFFFFF)) { 88 ERROR("Unaligned Video Memory base address!\n"); 89 SMC_RET1(handle, -ENOTSUP); 90 } 91 92 /* 93 * The GPU is the user of the Video Memory region. In order to 94 * transition to the new memory region smoothly, we program the 95 * new base/size ONLY if the GPU is in reset mode. 96 */ 97 regval = mmio_read_32(TEGRA_CAR_RESET_BASE + 98 TEGRA_GPU_RESET_REG_OFFSET); 99 if ((regval & GPU_RESET_BIT) == 0U) { 100 ERROR("GPU not in reset! Video Memory setup failed\n"); 101 SMC_RET1(handle, -ENOTSUP); 102 } 103 104 /* new video memory carveout settings */ 105 tegra_memctrl_videomem_setup(x1, x2); 106 107 SMC_RET1(handle, 0); 108 break; 109 110 /* 111 * The NS world registers the address of its handler to be 112 * used for processing the FIQ. This is normally used by the 113 * NS FIQ debugger driver to detect system hangs by programming 114 * a watchdog timer to fire a FIQ interrupt. 115 */ 116 case TEGRA_SIP_FIQ_NS_ENTRYPOINT: 117 118 if (!x1) 119 SMC_RET1(handle, SMC_UNK); 120 121 /* 122 * TODO: Check if x1 contains a valid DRAM address 123 */ 124 125 /* store the NS world's entrypoint */ 126 tegra_fiq_set_ns_entrypoint(x1); 127 128 SMC_RET1(handle, 0); 129 break; 130 131 /* 132 * The NS world's FIQ handler issues this SMC to get the NS EL1/EL0 133 * CPU context when the FIQ interrupt was triggered. This allows the 134 * NS world to understand the CPU state when the watchdog interrupt 135 * triggered. 136 */ 137 case TEGRA_SIP_FIQ_NS_GET_CONTEXT: 138 139 /* retrieve context registers when FIQ triggered */ 140 tegra_fiq_get_intr_context(); 141 142 SMC_RET0(handle); 143 break; 144 145 case TEGRA_SIP_ENABLE_FAKE_SYSTEM_SUSPEND: 146 /* 147 * System suspend fake mode is set if we are on VDK and we make 148 * a debug SIP call. This mode ensures that we excercise debug 149 * path instead of the regular code path to suit the pre-silicon 150 * platform needs. These include replacing the call to WFI by 151 * a warm reset request. 152 */ 153 if (tegra_platform_is_emulation() != 0U) { 154 155 tegra_fake_system_suspend = 1; 156 SMC_RET1(handle, 0); 157 } 158 159 /* 160 * We return to the external world as if this SIP is not 161 * implemented in case, we are not running on VDK. 162 */ 163 break; 164 165 default: 166 ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); 167 break; 168 } 169 170 SMC_RET1(handle, SMC_UNK); 171 } 172 173 /* Define a runtime service descriptor for fast SMC calls */ 174 DECLARE_RT_SVC( 175 tegra_sip_fast, 176 177 OEN_SIP_START, 178 OEN_SIP_END, 179 SMC_TYPE_FAST, 180 NULL, 181 tegra_sip_handler 182 ); 183