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