1 /* 2 * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of ARM nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <arch.h> 32 #include <arch_helpers.h> 33 #include <assert.h> 34 #include <bl_common.h> 35 #include <context_mgmt.h> 36 #include <debug.h> 37 #include <denver.h> 38 #include <errno.h> 39 #include <mce.h> 40 #include <memctrl.h> 41 #include <runtime_svc.h> 42 #include <t18x_ari.h> 43 #include <tegra_private.h> 44 45 extern uint32_t tegra186_system_powerdn_state; 46 47 /******************************************************************************* 48 * Offset to read the ref_clk counter value 49 ******************************************************************************/ 50 #define REF_CLK_OFFSET 4 51 52 /******************************************************************************* 53 * Tegra186 SiP SMCs 54 ******************************************************************************/ 55 #define TEGRA_SIP_SYSTEM_SHUTDOWN_STATE 0xC2FFFE01 56 #define TEGRA_SIP_GET_ACTMON_CLK_COUNTERS 0xC2FFFE02 57 #define TEGRA_SIP_MCE_CMD_ENTER_CSTATE 0xC2FFFF00 58 #define TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO 0xC2FFFF01 59 #define TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME 0xC2FFFF02 60 #define TEGRA_SIP_MCE_CMD_READ_CSTATE_STATS 0xC2FFFF03 61 #define TEGRA_SIP_MCE_CMD_WRITE_CSTATE_STATS 0xC2FFFF04 62 #define TEGRA_SIP_MCE_CMD_IS_SC7_ALLOWED 0xC2FFFF05 63 #define TEGRA_SIP_MCE_CMD_ONLINE_CORE 0xC2FFFF06 64 #define TEGRA_SIP_MCE_CMD_CC3_CTRL 0xC2FFFF07 65 #define TEGRA_SIP_MCE_CMD_ECHO_DATA 0xC2FFFF08 66 #define TEGRA_SIP_MCE_CMD_READ_VERSIONS 0xC2FFFF09 67 #define TEGRA_SIP_MCE_CMD_ENUM_FEATURES 0xC2FFFF0A 68 #define TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE_TRBITS 0xC2FFFF0B 69 #define TEGRA_SIP_MCE_CMD_ENUM_READ_MCA 0xC2FFFF0C 70 #define TEGRA_SIP_MCE_CMD_ENUM_WRITE_MCA 0xC2FFFF0D 71 #define TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE 0xC2FFFF0E 72 #define TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE 0xC2FFFF0F 73 #define TEGRA_SIP_MCE_CMD_ENABLE_LATIC 0xC2FFFF10 74 #define TEGRA_SIP_MCE_CMD_UNCORE_PERFMON_REQ 0xC2FFFF11 75 #define TEGRA_SIP_MCE_CMD_MISC_CCPLEX 0xC2FFFF12 76 77 /******************************************************************************* 78 * This function is responsible for handling all T186 SiP calls 79 ******************************************************************************/ 80 int plat_sip_handler(uint32_t smc_fid, 81 uint64_t x1, 82 uint64_t x2, 83 uint64_t x3, 84 uint64_t x4, 85 void *cookie, 86 void *handle, 87 uint64_t flags) 88 { 89 int mce_ret; 90 int impl, cpu; 91 uint32_t base, core_clk_ctr, ref_clk_ctr; 92 93 if (((smc_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_32) { 94 /* 32-bit function, clear top parameter bits */ 95 96 x1 = (uint32_t)x1; 97 x2 = (uint32_t)x2; 98 x3 = (uint32_t)x3; 99 } 100 101 /* 102 * Convert SMC FID to SMC64, to support SMC32/SMC64 configurations 103 */ 104 smc_fid |= (SMC_64 << FUNCID_CC_SHIFT); 105 106 switch (smc_fid) { 107 /* 108 * Micro Coded Engine (MCE) commands reside in the 0x82FFFF00 - 109 * 0x82FFFFFF SiP SMC space 110 */ 111 case TEGRA_SIP_MCE_CMD_ENTER_CSTATE: 112 case TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO: 113 case TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME: 114 case TEGRA_SIP_MCE_CMD_READ_CSTATE_STATS: 115 case TEGRA_SIP_MCE_CMD_WRITE_CSTATE_STATS: 116 case TEGRA_SIP_MCE_CMD_IS_SC7_ALLOWED: 117 case TEGRA_SIP_MCE_CMD_CC3_CTRL: 118 case TEGRA_SIP_MCE_CMD_ECHO_DATA: 119 case TEGRA_SIP_MCE_CMD_READ_VERSIONS: 120 case TEGRA_SIP_MCE_CMD_ENUM_FEATURES: 121 case TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE_TRBITS: 122 case TEGRA_SIP_MCE_CMD_ENUM_READ_MCA: 123 case TEGRA_SIP_MCE_CMD_ENUM_WRITE_MCA: 124 case TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE: 125 case TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE: 126 case TEGRA_SIP_MCE_CMD_ENABLE_LATIC: 127 case TEGRA_SIP_MCE_CMD_UNCORE_PERFMON_REQ: 128 case TEGRA_SIP_MCE_CMD_MISC_CCPLEX: 129 130 /* clean up the high bits */ 131 smc_fid &= MCE_CMD_MASK; 132 133 /* execute the command and store the result */ 134 mce_ret = mce_command_handler(smc_fid, x1, x2, x3); 135 write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X0, 136 (uint64_t)mce_ret); 137 138 return 0; 139 140 case TEGRA_SIP_SYSTEM_SHUTDOWN_STATE: 141 142 /* clean up the high bits */ 143 x1 = (uint32_t)x1; 144 145 /* 146 * SC8 is a special Tegra186 system state where the CPUs and 147 * DRAM are powered down but the other subsystem is still 148 * alive. 149 */ 150 if ((x1 == TEGRA_ARI_SYSTEM_SC8) || 151 (x1 == TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF)) { 152 153 tegra186_system_powerdn_state = x1; 154 flush_dcache_range( 155 (uintptr_t)&tegra186_system_powerdn_state, 156 sizeof(tegra186_system_powerdn_state)); 157 158 } else { 159 160 ERROR("%s: unhandled powerdn state (%d)\n", __func__, 161 (uint32_t)x1); 162 return -ENOTSUP; 163 } 164 165 return 0; 166 167 /* 168 * This function ID reads the Activity monitor's core/ref clock 169 * counter values for a core/cluster. 170 * 171 * x1 = MPIDR of the target core 172 * x2 = MIDR of the target core 173 */ 174 case TEGRA_SIP_GET_ACTMON_CLK_COUNTERS: 175 176 cpu = (uint32_t)x1 & MPIDR_CPU_MASK; 177 impl = ((uint32_t)x2 >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; 178 179 /* sanity check target CPU number */ 180 if (cpu > PLATFORM_MAX_CPUS_PER_CLUSTER) 181 return -EINVAL; 182 183 /* get the base address for the current CPU */ 184 base = (impl == DENVER_IMPL) ? TEGRA_DENVER_ACTMON_CTR_BASE : 185 TEGRA_ARM_ACTMON_CTR_BASE; 186 187 /* read the clock counter values */ 188 core_clk_ctr = mmio_read_32(base + (8 * cpu)); 189 ref_clk_ctr = mmio_read_32(base + (8 * cpu) + REF_CLK_OFFSET); 190 191 /* return the counter values as two different parameters */ 192 write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X1, 193 (uint64_t)core_clk_ctr); 194 write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X2, 195 (uint64_t)ref_clk_ctr); 196 197 return 0; 198 199 default: 200 break; 201 } 202 203 return -ENOTSUP; 204 } 205