1 /* 2 * Copyright (c) 2015-2016, 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 <context_mgmt.h> 12 #include <debug.h> 13 #include <denver.h> 14 #include <errno.h> 15 #include <mce.h> 16 #include <memctrl.h> 17 #include <runtime_svc.h> 18 #include <t18x_ari.h> 19 #include <tegra_private.h> 20 21 extern uint32_t tegra186_system_powerdn_state; 22 23 /******************************************************************************* 24 * Offset to read the ref_clk counter value 25 ******************************************************************************/ 26 #define REF_CLK_OFFSET 4 27 28 /******************************************************************************* 29 * Tegra186 SiP SMCs 30 ******************************************************************************/ 31 #define TEGRA_SIP_SYSTEM_SHUTDOWN_STATE 0xC2FFFE01 32 #define TEGRA_SIP_GET_ACTMON_CLK_COUNTERS 0xC2FFFE02 33 #define TEGRA_SIP_MCE_CMD_ENTER_CSTATE 0xC2FFFF00 34 #define TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO 0xC2FFFF01 35 #define TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME 0xC2FFFF02 36 #define TEGRA_SIP_MCE_CMD_READ_CSTATE_STATS 0xC2FFFF03 37 #define TEGRA_SIP_MCE_CMD_WRITE_CSTATE_STATS 0xC2FFFF04 38 #define TEGRA_SIP_MCE_CMD_IS_SC7_ALLOWED 0xC2FFFF05 39 #define TEGRA_SIP_MCE_CMD_ONLINE_CORE 0xC2FFFF06 40 #define TEGRA_SIP_MCE_CMD_CC3_CTRL 0xC2FFFF07 41 #define TEGRA_SIP_MCE_CMD_ECHO_DATA 0xC2FFFF08 42 #define TEGRA_SIP_MCE_CMD_READ_VERSIONS 0xC2FFFF09 43 #define TEGRA_SIP_MCE_CMD_ENUM_FEATURES 0xC2FFFF0A 44 #define TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE_TRBITS 0xC2FFFF0B 45 #define TEGRA_SIP_MCE_CMD_ENUM_READ_MCA 0xC2FFFF0C 46 #define TEGRA_SIP_MCE_CMD_ENUM_WRITE_MCA 0xC2FFFF0D 47 #define TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE 0xC2FFFF0E 48 #define TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE 0xC2FFFF0F 49 #define TEGRA_SIP_MCE_CMD_ENABLE_LATIC 0xC2FFFF10 50 #define TEGRA_SIP_MCE_CMD_UNCORE_PERFMON_REQ 0xC2FFFF11 51 #define TEGRA_SIP_MCE_CMD_MISC_CCPLEX 0xC2FFFF12 52 53 /******************************************************************************* 54 * This function is responsible for handling all T186 SiP calls 55 ******************************************************************************/ 56 int plat_sip_handler(uint32_t smc_fid, 57 uint64_t x1, 58 uint64_t x2, 59 uint64_t x3, 60 uint64_t x4, 61 void *cookie, 62 void *handle, 63 uint64_t flags) 64 { 65 int mce_ret; 66 int impl, cpu; 67 uint32_t base, core_clk_ctr, ref_clk_ctr; 68 69 if (((smc_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_32) { 70 /* 32-bit function, clear top parameter bits */ 71 72 x1 = (uint32_t)x1; 73 x2 = (uint32_t)x2; 74 x3 = (uint32_t)x3; 75 } 76 77 /* 78 * Convert SMC FID to SMC64, to support SMC32/SMC64 configurations 79 */ 80 smc_fid |= (SMC_64 << FUNCID_CC_SHIFT); 81 82 switch (smc_fid) { 83 /* 84 * Micro Coded Engine (MCE) commands reside in the 0x82FFFF00 - 85 * 0x82FFFFFF SiP SMC space 86 */ 87 case TEGRA_SIP_MCE_CMD_ENTER_CSTATE: 88 case TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO: 89 case TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME: 90 case TEGRA_SIP_MCE_CMD_READ_CSTATE_STATS: 91 case TEGRA_SIP_MCE_CMD_WRITE_CSTATE_STATS: 92 case TEGRA_SIP_MCE_CMD_IS_SC7_ALLOWED: 93 case TEGRA_SIP_MCE_CMD_CC3_CTRL: 94 case TEGRA_SIP_MCE_CMD_ECHO_DATA: 95 case TEGRA_SIP_MCE_CMD_READ_VERSIONS: 96 case TEGRA_SIP_MCE_CMD_ENUM_FEATURES: 97 case TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE_TRBITS: 98 case TEGRA_SIP_MCE_CMD_ENUM_READ_MCA: 99 case TEGRA_SIP_MCE_CMD_ENUM_WRITE_MCA: 100 case TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE: 101 case TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE: 102 case TEGRA_SIP_MCE_CMD_ENABLE_LATIC: 103 case TEGRA_SIP_MCE_CMD_UNCORE_PERFMON_REQ: 104 case TEGRA_SIP_MCE_CMD_MISC_CCPLEX: 105 106 /* clean up the high bits */ 107 smc_fid &= MCE_CMD_MASK; 108 109 /* execute the command and store the result */ 110 mce_ret = mce_command_handler(smc_fid, x1, x2, x3); 111 write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X0, 112 (uint64_t)mce_ret); 113 114 return 0; 115 116 case TEGRA_SIP_SYSTEM_SHUTDOWN_STATE: 117 118 /* clean up the high bits */ 119 x1 = (uint32_t)x1; 120 121 /* 122 * SC8 is a special Tegra186 system state where the CPUs and 123 * DRAM are powered down but the other subsystem is still 124 * alive. 125 */ 126 if ((x1 == TEGRA_ARI_SYSTEM_SC8) || 127 (x1 == TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF)) { 128 129 tegra186_system_powerdn_state = x1; 130 flush_dcache_range( 131 (uintptr_t)&tegra186_system_powerdn_state, 132 sizeof(tegra186_system_powerdn_state)); 133 134 } else { 135 136 ERROR("%s: unhandled powerdn state (%d)\n", __func__, 137 (uint32_t)x1); 138 return -ENOTSUP; 139 } 140 141 return 0; 142 143 /* 144 * This function ID reads the Activity monitor's core/ref clock 145 * counter values for a core/cluster. 146 * 147 * x1 = MPIDR of the target core 148 * x2 = MIDR of the target core 149 */ 150 case TEGRA_SIP_GET_ACTMON_CLK_COUNTERS: 151 152 cpu = (uint32_t)x1 & MPIDR_CPU_MASK; 153 impl = ((uint32_t)x2 >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; 154 155 /* sanity check target CPU number */ 156 if (cpu > PLATFORM_MAX_CPUS_PER_CLUSTER) 157 return -EINVAL; 158 159 /* get the base address for the current CPU */ 160 base = (impl == DENVER_IMPL) ? TEGRA_DENVER_ACTMON_CTR_BASE : 161 TEGRA_ARM_ACTMON_CTR_BASE; 162 163 /* read the clock counter values */ 164 core_clk_ctr = mmio_read_32(base + (8 * cpu)); 165 ref_clk_ctr = mmio_read_32(base + (8 * cpu) + REF_CLK_OFFSET); 166 167 /* return the counter values as two different parameters */ 168 write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X1, 169 (uint64_t)core_clk_ctr); 170 write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X2, 171 (uint64_t)ref_clk_ctr); 172 173 return 0; 174 175 default: 176 break; 177 } 178 179 return -ENOTSUP; 180 } 181