1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. 4*91f16700Schasinglulu * 5*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu #include <assert.h> 9*91f16700Schasinglulu #include <errno.h> 10*91f16700Schasinglulu #include <inttypes.h> 11*91f16700Schasinglulu #include <stdint.h> 12*91f16700Schasinglulu #include <string.h> 13*91f16700Schasinglulu 14*91f16700Schasinglulu #include <arch.h> 15*91f16700Schasinglulu #include <arch_helpers.h> 16*91f16700Schasinglulu #include <common/bl_common.h> 17*91f16700Schasinglulu #include <common/debug.h> 18*91f16700Schasinglulu #include <context.h> 19*91f16700Schasinglulu #include <denver.h> 20*91f16700Schasinglulu #include <lib/el3_runtime/context_mgmt.h> 21*91f16700Schasinglulu #include <lib/mmio.h> 22*91f16700Schasinglulu 23*91f16700Schasinglulu #include <mce.h> 24*91f16700Schasinglulu #include <mce_private.h> 25*91f16700Schasinglulu #include <t18x_ari.h> 26*91f16700Schasinglulu #include <tegra_def.h> 27*91f16700Schasinglulu #include <tegra_platform.h> 28*91f16700Schasinglulu 29*91f16700Schasinglulu /* NVG functions handlers */ 30*91f16700Schasinglulu static arch_mce_ops_t nvg_mce_ops = { 31*91f16700Schasinglulu .enter_cstate = nvg_enter_cstate, 32*91f16700Schasinglulu .update_cstate_info = nvg_update_cstate_info, 33*91f16700Schasinglulu .update_crossover_time = nvg_update_crossover_time, 34*91f16700Schasinglulu .read_cstate_stats = nvg_read_cstate_stats, 35*91f16700Schasinglulu .write_cstate_stats = nvg_write_cstate_stats, 36*91f16700Schasinglulu .call_enum_misc = ari_enumeration_misc, 37*91f16700Schasinglulu .is_ccx_allowed = nvg_is_ccx_allowed, 38*91f16700Schasinglulu .is_sc7_allowed = nvg_is_sc7_allowed, 39*91f16700Schasinglulu .online_core = nvg_online_core, 40*91f16700Schasinglulu .cc3_ctrl = nvg_cc3_ctrl, 41*91f16700Schasinglulu .update_reset_vector = ari_reset_vector_update, 42*91f16700Schasinglulu .roc_flush_cache = ari_roc_flush_cache, 43*91f16700Schasinglulu .roc_flush_cache_trbits = ari_roc_flush_cache_trbits, 44*91f16700Schasinglulu .roc_clean_cache = ari_roc_clean_cache, 45*91f16700Schasinglulu .read_write_mca = ari_read_write_mca, 46*91f16700Schasinglulu .update_ccplex_gsc = ari_update_ccplex_gsc, 47*91f16700Schasinglulu .enter_ccplex_state = ari_enter_ccplex_state, 48*91f16700Schasinglulu .read_write_uncore_perfmon = ari_read_write_uncore_perfmon, 49*91f16700Schasinglulu .misc_ccplex = ari_misc_ccplex 50*91f16700Schasinglulu }; 51*91f16700Schasinglulu 52*91f16700Schasinglulu /* ARI functions handlers */ 53*91f16700Schasinglulu static arch_mce_ops_t ari_mce_ops = { 54*91f16700Schasinglulu .enter_cstate = ari_enter_cstate, 55*91f16700Schasinglulu .update_cstate_info = ari_update_cstate_info, 56*91f16700Schasinglulu .update_crossover_time = ari_update_crossover_time, 57*91f16700Schasinglulu .read_cstate_stats = ari_read_cstate_stats, 58*91f16700Schasinglulu .write_cstate_stats = ari_write_cstate_stats, 59*91f16700Schasinglulu .call_enum_misc = ari_enumeration_misc, 60*91f16700Schasinglulu .is_ccx_allowed = ari_is_ccx_allowed, 61*91f16700Schasinglulu .is_sc7_allowed = ari_is_sc7_allowed, 62*91f16700Schasinglulu .online_core = ari_online_core, 63*91f16700Schasinglulu .cc3_ctrl = ari_cc3_ctrl, 64*91f16700Schasinglulu .update_reset_vector = ari_reset_vector_update, 65*91f16700Schasinglulu .roc_flush_cache = ari_roc_flush_cache, 66*91f16700Schasinglulu .roc_flush_cache_trbits = ari_roc_flush_cache_trbits, 67*91f16700Schasinglulu .roc_clean_cache = ari_roc_clean_cache, 68*91f16700Schasinglulu .read_write_mca = ari_read_write_mca, 69*91f16700Schasinglulu .update_ccplex_gsc = ari_update_ccplex_gsc, 70*91f16700Schasinglulu .enter_ccplex_state = ari_enter_ccplex_state, 71*91f16700Schasinglulu .read_write_uncore_perfmon = ari_read_write_uncore_perfmon, 72*91f16700Schasinglulu .misc_ccplex = ari_misc_ccplex 73*91f16700Schasinglulu }; 74*91f16700Schasinglulu 75*91f16700Schasinglulu typedef struct { 76*91f16700Schasinglulu uint32_t ari_base; 77*91f16700Schasinglulu arch_mce_ops_t *ops; 78*91f16700Schasinglulu } mce_config_t; 79*91f16700Schasinglulu 80*91f16700Schasinglulu /* Table to hold the per-CPU ARI base address and function handlers */ 81*91f16700Schasinglulu static mce_config_t mce_cfg_table[MCE_ARI_APERTURES_MAX] = { 82*91f16700Schasinglulu { 83*91f16700Schasinglulu /* A57 Core 0 */ 84*91f16700Schasinglulu .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_0_OFFSET, 85*91f16700Schasinglulu .ops = &ari_mce_ops, 86*91f16700Schasinglulu }, 87*91f16700Schasinglulu { 88*91f16700Schasinglulu /* A57 Core 1 */ 89*91f16700Schasinglulu .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_1_OFFSET, 90*91f16700Schasinglulu .ops = &ari_mce_ops, 91*91f16700Schasinglulu }, 92*91f16700Schasinglulu { 93*91f16700Schasinglulu /* A57 Core 2 */ 94*91f16700Schasinglulu .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_2_OFFSET, 95*91f16700Schasinglulu .ops = &ari_mce_ops, 96*91f16700Schasinglulu }, 97*91f16700Schasinglulu { 98*91f16700Schasinglulu /* A57 Core 3 */ 99*91f16700Schasinglulu .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_3_OFFSET, 100*91f16700Schasinglulu .ops = &ari_mce_ops, 101*91f16700Schasinglulu }, 102*91f16700Schasinglulu { 103*91f16700Schasinglulu /* D15 Core 0 */ 104*91f16700Schasinglulu .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_4_OFFSET, 105*91f16700Schasinglulu .ops = &nvg_mce_ops, 106*91f16700Schasinglulu }, 107*91f16700Schasinglulu { 108*91f16700Schasinglulu /* D15 Core 1 */ 109*91f16700Schasinglulu .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_5_OFFSET, 110*91f16700Schasinglulu .ops = &nvg_mce_ops, 111*91f16700Schasinglulu } 112*91f16700Schasinglulu }; 113*91f16700Schasinglulu 114*91f16700Schasinglulu static uint32_t mce_get_curr_cpu_ari_base(void) 115*91f16700Schasinglulu { 116*91f16700Schasinglulu uint64_t mpidr = read_mpidr(); 117*91f16700Schasinglulu uint64_t cpuid = mpidr & MPIDR_CPU_MASK; 118*91f16700Schasinglulu uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; 119*91f16700Schasinglulu 120*91f16700Schasinglulu /* 121*91f16700Schasinglulu * T186 has 2 CPU clusters, one with Denver CPUs and the other with 122*91f16700Schasinglulu * ARM CortexA-57 CPUs. Each cluster consists of 4 CPUs and the CPU 123*91f16700Schasinglulu * numbers start from 0. In order to get the proper arch_mce_ops_t 124*91f16700Schasinglulu * struct, we have to convert the Denver CPU ids to the corresponding 125*91f16700Schasinglulu * indices in the mce_ops_table array. 126*91f16700Schasinglulu */ 127*91f16700Schasinglulu if (impl == DENVER_IMPL) { 128*91f16700Schasinglulu cpuid |= 0x4U; 129*91f16700Schasinglulu } 130*91f16700Schasinglulu 131*91f16700Schasinglulu return mce_cfg_table[cpuid].ari_base; 132*91f16700Schasinglulu } 133*91f16700Schasinglulu 134*91f16700Schasinglulu static arch_mce_ops_t *mce_get_curr_cpu_ops(void) 135*91f16700Schasinglulu { 136*91f16700Schasinglulu uint64_t mpidr = read_mpidr(); 137*91f16700Schasinglulu uint64_t cpuid = mpidr & MPIDR_CPU_MASK; 138*91f16700Schasinglulu uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & 139*91f16700Schasinglulu MIDR_IMPL_MASK; 140*91f16700Schasinglulu 141*91f16700Schasinglulu /* 142*91f16700Schasinglulu * T186 has 2 CPU clusters, one with Denver CPUs and the other with 143*91f16700Schasinglulu * ARM CortexA-57 CPUs. Each cluster consists of 4 CPUs and the CPU 144*91f16700Schasinglulu * numbers start from 0. In order to get the proper arch_mce_ops_t 145*91f16700Schasinglulu * struct, we have to convert the Denver CPU ids to the corresponding 146*91f16700Schasinglulu * indices in the mce_ops_table array. 147*91f16700Schasinglulu */ 148*91f16700Schasinglulu if (impl == DENVER_IMPL) { 149*91f16700Schasinglulu cpuid |= 0x4U; 150*91f16700Schasinglulu } 151*91f16700Schasinglulu 152*91f16700Schasinglulu return mce_cfg_table[cpuid].ops; 153*91f16700Schasinglulu } 154*91f16700Schasinglulu 155*91f16700Schasinglulu /******************************************************************************* 156*91f16700Schasinglulu * Common handler for all MCE commands 157*91f16700Schasinglulu ******************************************************************************/ 158*91f16700Schasinglulu int32_t mce_command_handler(uint64_t cmd, uint64_t arg0, uint64_t arg1, 159*91f16700Schasinglulu uint64_t arg2) 160*91f16700Schasinglulu { 161*91f16700Schasinglulu const arch_mce_ops_t *ops; 162*91f16700Schasinglulu gp_regs_t *gp_regs = get_gpregs_ctx(cm_get_context(NON_SECURE)); 163*91f16700Schasinglulu uint32_t cpu_ari_base; 164*91f16700Schasinglulu uint64_t ret64 = 0, arg3, arg4, arg5; 165*91f16700Schasinglulu int32_t ret = 0; 166*91f16700Schasinglulu 167*91f16700Schasinglulu assert(gp_regs != NULL); 168*91f16700Schasinglulu 169*91f16700Schasinglulu /* get a pointer to the CPU's arch_mce_ops_t struct */ 170*91f16700Schasinglulu ops = mce_get_curr_cpu_ops(); 171*91f16700Schasinglulu 172*91f16700Schasinglulu /* get the CPU's ARI base address */ 173*91f16700Schasinglulu cpu_ari_base = mce_get_curr_cpu_ari_base(); 174*91f16700Schasinglulu 175*91f16700Schasinglulu switch (cmd) { 176*91f16700Schasinglulu case (uint64_t)MCE_CMD_ENTER_CSTATE: 177*91f16700Schasinglulu ret = ops->enter_cstate(cpu_ari_base, arg0, arg1); 178*91f16700Schasinglulu 179*91f16700Schasinglulu break; 180*91f16700Schasinglulu 181*91f16700Schasinglulu case (uint64_t)MCE_CMD_UPDATE_CSTATE_INFO: 182*91f16700Schasinglulu /* 183*91f16700Schasinglulu * get the parameters required for the update cstate info 184*91f16700Schasinglulu * command 185*91f16700Schasinglulu */ 186*91f16700Schasinglulu arg3 = read_ctx_reg(gp_regs, CTX_GPREG_X4); 187*91f16700Schasinglulu arg4 = read_ctx_reg(gp_regs, CTX_GPREG_X5); 188*91f16700Schasinglulu arg5 = read_ctx_reg(gp_regs, CTX_GPREG_X6); 189*91f16700Schasinglulu 190*91f16700Schasinglulu ret = ops->update_cstate_info(cpu_ari_base, (uint32_t)arg0, 191*91f16700Schasinglulu (uint32_t)arg1, (uint32_t)arg2, (uint8_t)arg3, 192*91f16700Schasinglulu (uint32_t)arg4, (uint8_t)arg5); 193*91f16700Schasinglulu 194*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X4, (0ULL)); 195*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X5, (0ULL)); 196*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X6, (0ULL)); 197*91f16700Schasinglulu 198*91f16700Schasinglulu break; 199*91f16700Schasinglulu 200*91f16700Schasinglulu case (uint64_t)MCE_CMD_UPDATE_CROSSOVER_TIME: 201*91f16700Schasinglulu ret = ops->update_crossover_time(cpu_ari_base, arg0, arg1); 202*91f16700Schasinglulu 203*91f16700Schasinglulu break; 204*91f16700Schasinglulu 205*91f16700Schasinglulu case (uint64_t)MCE_CMD_READ_CSTATE_STATS: 206*91f16700Schasinglulu ret64 = ops->read_cstate_stats(cpu_ari_base, arg0); 207*91f16700Schasinglulu 208*91f16700Schasinglulu /* update context to return cstate stats value */ 209*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64)); 210*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X2, (ret64)); 211*91f16700Schasinglulu 212*91f16700Schasinglulu break; 213*91f16700Schasinglulu 214*91f16700Schasinglulu case (uint64_t)MCE_CMD_WRITE_CSTATE_STATS: 215*91f16700Schasinglulu ret = ops->write_cstate_stats(cpu_ari_base, arg0, arg1); 216*91f16700Schasinglulu 217*91f16700Schasinglulu break; 218*91f16700Schasinglulu 219*91f16700Schasinglulu case (uint64_t)MCE_CMD_IS_CCX_ALLOWED: 220*91f16700Schasinglulu ret = ops->is_ccx_allowed(cpu_ari_base, arg0, arg1); 221*91f16700Schasinglulu 222*91f16700Schasinglulu /* update context to return CCx status value */ 223*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X1, (uint64_t)(ret)); 224*91f16700Schasinglulu 225*91f16700Schasinglulu break; 226*91f16700Schasinglulu 227*91f16700Schasinglulu case (uint64_t)MCE_CMD_IS_SC7_ALLOWED: 228*91f16700Schasinglulu ret = ops->is_sc7_allowed(cpu_ari_base, arg0, arg1); 229*91f16700Schasinglulu 230*91f16700Schasinglulu /* update context to return SC7 status value */ 231*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X1, (uint64_t)(ret)); 232*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X3, (uint64_t)(ret)); 233*91f16700Schasinglulu 234*91f16700Schasinglulu break; 235*91f16700Schasinglulu 236*91f16700Schasinglulu case (uint64_t)MCE_CMD_ONLINE_CORE: 237*91f16700Schasinglulu ret = ops->online_core(cpu_ari_base, arg0); 238*91f16700Schasinglulu 239*91f16700Schasinglulu break; 240*91f16700Schasinglulu 241*91f16700Schasinglulu case (uint64_t)MCE_CMD_CC3_CTRL: 242*91f16700Schasinglulu ret = ops->cc3_ctrl(cpu_ari_base, arg0, arg1, arg2); 243*91f16700Schasinglulu 244*91f16700Schasinglulu break; 245*91f16700Schasinglulu 246*91f16700Schasinglulu case (uint64_t)MCE_CMD_ECHO_DATA: 247*91f16700Schasinglulu ret64 = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_ECHO, 248*91f16700Schasinglulu arg0); 249*91f16700Schasinglulu 250*91f16700Schasinglulu /* update context to return if echo'd data matched source */ 251*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X1, ((ret64 == arg0) ? 252*91f16700Schasinglulu 1ULL : 0ULL)); 253*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X2, ((ret64 == arg0) ? 254*91f16700Schasinglulu 1ULL : 0ULL)); 255*91f16700Schasinglulu 256*91f16700Schasinglulu break; 257*91f16700Schasinglulu 258*91f16700Schasinglulu case (uint64_t)MCE_CMD_READ_VERSIONS: 259*91f16700Schasinglulu ret64 = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_VERSION, 260*91f16700Schasinglulu arg0); 261*91f16700Schasinglulu 262*91f16700Schasinglulu /* 263*91f16700Schasinglulu * version = minor(63:32) | major(31:0). Update context 264*91f16700Schasinglulu * to return major and minor version number. 265*91f16700Schasinglulu */ 266*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64)); 267*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X2, (ret64 >> 32ULL)); 268*91f16700Schasinglulu 269*91f16700Schasinglulu break; 270*91f16700Schasinglulu 271*91f16700Schasinglulu case (uint64_t)MCE_CMD_ENUM_FEATURES: 272*91f16700Schasinglulu ret64 = ops->call_enum_misc(cpu_ari_base, 273*91f16700Schasinglulu TEGRA_ARI_MISC_FEATURE_LEAF_0, arg0); 274*91f16700Schasinglulu 275*91f16700Schasinglulu /* update context to return features value */ 276*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64)); 277*91f16700Schasinglulu 278*91f16700Schasinglulu break; 279*91f16700Schasinglulu 280*91f16700Schasinglulu case (uint64_t)MCE_CMD_ROC_FLUSH_CACHE_TRBITS: 281*91f16700Schasinglulu ret = ops->roc_flush_cache_trbits(cpu_ari_base); 282*91f16700Schasinglulu 283*91f16700Schasinglulu break; 284*91f16700Schasinglulu 285*91f16700Schasinglulu case (uint64_t)MCE_CMD_ROC_FLUSH_CACHE: 286*91f16700Schasinglulu ret = ops->roc_flush_cache(cpu_ari_base); 287*91f16700Schasinglulu 288*91f16700Schasinglulu break; 289*91f16700Schasinglulu 290*91f16700Schasinglulu case (uint64_t)MCE_CMD_ROC_CLEAN_CACHE: 291*91f16700Schasinglulu ret = ops->roc_clean_cache(cpu_ari_base); 292*91f16700Schasinglulu 293*91f16700Schasinglulu break; 294*91f16700Schasinglulu 295*91f16700Schasinglulu case (uint64_t)MCE_CMD_ENUM_READ_MCA: 296*91f16700Schasinglulu ret64 = ops->read_write_mca(cpu_ari_base, arg0, &arg1); 297*91f16700Schasinglulu 298*91f16700Schasinglulu /* update context to return MCA data/error */ 299*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64)); 300*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X2, (arg1)); 301*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X3, (ret64)); 302*91f16700Schasinglulu 303*91f16700Schasinglulu break; 304*91f16700Schasinglulu 305*91f16700Schasinglulu case (uint64_t)MCE_CMD_ENUM_WRITE_MCA: 306*91f16700Schasinglulu ret64 = ops->read_write_mca(cpu_ari_base, arg0, &arg1); 307*91f16700Schasinglulu 308*91f16700Schasinglulu /* update context to return MCA error */ 309*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64)); 310*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X3, (ret64)); 311*91f16700Schasinglulu 312*91f16700Schasinglulu break; 313*91f16700Schasinglulu 314*91f16700Schasinglulu #if ENABLE_CHIP_VERIFICATION_HARNESS 315*91f16700Schasinglulu case (uint64_t)MCE_CMD_ENABLE_LATIC: 316*91f16700Schasinglulu /* 317*91f16700Schasinglulu * This call is not for production use. The constant value, 318*91f16700Schasinglulu * 0xFFFF0000, is specific to allowing for enabling LATIC on 319*91f16700Schasinglulu * pre-production parts for the chip verification harness. 320*91f16700Schasinglulu * 321*91f16700Schasinglulu * Enabling LATIC allows S/W to read the MINI ISPs in the 322*91f16700Schasinglulu * CCPLEX. The ISMs are used for various measurements relevant 323*91f16700Schasinglulu * to particular locations in the Silicon. They are small 324*91f16700Schasinglulu * counters which can be polled to determine how fast a 325*91f16700Schasinglulu * particular location in the Silicon is. 326*91f16700Schasinglulu */ 327*91f16700Schasinglulu ops->enter_ccplex_state(mce_get_curr_cpu_ari_base(), 328*91f16700Schasinglulu 0xFFFF0000); 329*91f16700Schasinglulu 330*91f16700Schasinglulu break; 331*91f16700Schasinglulu #endif 332*91f16700Schasinglulu 333*91f16700Schasinglulu case (uint64_t)MCE_CMD_UNCORE_PERFMON_REQ: 334*91f16700Schasinglulu ret = ops->read_write_uncore_perfmon(cpu_ari_base, arg0, &arg1); 335*91f16700Schasinglulu 336*91f16700Schasinglulu /* update context to return data */ 337*91f16700Schasinglulu write_ctx_reg(gp_regs, CTX_GPREG_X1, (arg1)); 338*91f16700Schasinglulu break; 339*91f16700Schasinglulu 340*91f16700Schasinglulu case (uint64_t)MCE_CMD_MISC_CCPLEX: 341*91f16700Schasinglulu ops->misc_ccplex(cpu_ari_base, arg0, arg1); 342*91f16700Schasinglulu 343*91f16700Schasinglulu break; 344*91f16700Schasinglulu 345*91f16700Schasinglulu default: 346*91f16700Schasinglulu ERROR("unknown MCE command (%" PRIu64 ")\n", cmd); 347*91f16700Schasinglulu ret = EINVAL; 348*91f16700Schasinglulu break; 349*91f16700Schasinglulu } 350*91f16700Schasinglulu 351*91f16700Schasinglulu return ret; 352*91f16700Schasinglulu } 353*91f16700Schasinglulu 354*91f16700Schasinglulu /******************************************************************************* 355*91f16700Schasinglulu * Handler to update the reset vector for CPUs 356*91f16700Schasinglulu ******************************************************************************/ 357*91f16700Schasinglulu int32_t mce_update_reset_vector(void) 358*91f16700Schasinglulu { 359*91f16700Schasinglulu const arch_mce_ops_t *ops = mce_get_curr_cpu_ops(); 360*91f16700Schasinglulu 361*91f16700Schasinglulu ops->update_reset_vector(mce_get_curr_cpu_ari_base()); 362*91f16700Schasinglulu 363*91f16700Schasinglulu return 0; 364*91f16700Schasinglulu } 365*91f16700Schasinglulu 366*91f16700Schasinglulu static int32_t mce_update_ccplex_gsc(tegra_ari_gsc_index_t gsc_idx) 367*91f16700Schasinglulu { 368*91f16700Schasinglulu const arch_mce_ops_t *ops = mce_get_curr_cpu_ops(); 369*91f16700Schasinglulu 370*91f16700Schasinglulu ops->update_ccplex_gsc(mce_get_curr_cpu_ari_base(), gsc_idx); 371*91f16700Schasinglulu 372*91f16700Schasinglulu return 0; 373*91f16700Schasinglulu } 374*91f16700Schasinglulu 375*91f16700Schasinglulu /******************************************************************************* 376*91f16700Schasinglulu * Handler to update carveout values for Video Memory Carveout region 377*91f16700Schasinglulu ******************************************************************************/ 378*91f16700Schasinglulu int32_t mce_update_gsc_videomem(void) 379*91f16700Schasinglulu { 380*91f16700Schasinglulu return mce_update_ccplex_gsc(TEGRA_ARI_GSC_VPR_IDX); 381*91f16700Schasinglulu } 382*91f16700Schasinglulu 383*91f16700Schasinglulu /******************************************************************************* 384*91f16700Schasinglulu * Handler to update carveout values for TZDRAM aperture 385*91f16700Schasinglulu ******************************************************************************/ 386*91f16700Schasinglulu int32_t mce_update_gsc_tzdram(void) 387*91f16700Schasinglulu { 388*91f16700Schasinglulu return mce_update_ccplex_gsc(TEGRA_ARI_GSC_TZ_DRAM_IDX); 389*91f16700Schasinglulu } 390*91f16700Schasinglulu 391*91f16700Schasinglulu /******************************************************************************* 392*91f16700Schasinglulu * Handler to shutdown/reset the entire system 393*91f16700Schasinglulu ******************************************************************************/ 394*91f16700Schasinglulu __dead2 void mce_enter_ccplex_state(uint32_t state_idx) 395*91f16700Schasinglulu { 396*91f16700Schasinglulu const arch_mce_ops_t *ops = mce_get_curr_cpu_ops(); 397*91f16700Schasinglulu 398*91f16700Schasinglulu /* sanity check state value */ 399*91f16700Schasinglulu if ((state_idx != TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF) && 400*91f16700Schasinglulu (state_idx != TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT)) { 401*91f16700Schasinglulu panic(); 402*91f16700Schasinglulu } 403*91f16700Schasinglulu 404*91f16700Schasinglulu ops->enter_ccplex_state(mce_get_curr_cpu_ari_base(), state_idx); 405*91f16700Schasinglulu 406*91f16700Schasinglulu /* wait till the CCPLEX powers down */ 407*91f16700Schasinglulu for (;;) { 408*91f16700Schasinglulu ; 409*91f16700Schasinglulu } 410*91f16700Schasinglulu 411*91f16700Schasinglulu } 412*91f16700Schasinglulu 413*91f16700Schasinglulu /******************************************************************************* 414*91f16700Schasinglulu * Handler to issue the UPDATE_CSTATE_INFO request 415*91f16700Schasinglulu ******************************************************************************/ 416*91f16700Schasinglulu void mce_update_cstate_info(const mce_cstate_info_t *cstate) 417*91f16700Schasinglulu { 418*91f16700Schasinglulu const arch_mce_ops_t *ops = mce_get_curr_cpu_ops(); 419*91f16700Schasinglulu 420*91f16700Schasinglulu /* issue the UPDATE_CSTATE_INFO request */ 421*91f16700Schasinglulu ops->update_cstate_info(mce_get_curr_cpu_ari_base(), cstate->cluster, 422*91f16700Schasinglulu cstate->ccplex, cstate->system, cstate->system_state_force, 423*91f16700Schasinglulu cstate->wake_mask, cstate->update_wake_mask); 424*91f16700Schasinglulu } 425*91f16700Schasinglulu 426*91f16700Schasinglulu /******************************************************************************* 427*91f16700Schasinglulu * Handler to read the MCE firmware version and check if it is compatible 428*91f16700Schasinglulu * with interface header the BL3-1 was compiled against 429*91f16700Schasinglulu ******************************************************************************/ 430*91f16700Schasinglulu void mce_verify_firmware_version(void) 431*91f16700Schasinglulu { 432*91f16700Schasinglulu const arch_mce_ops_t *ops; 433*91f16700Schasinglulu uint32_t cpu_ari_base; 434*91f16700Schasinglulu uint64_t version; 435*91f16700Schasinglulu uint32_t major, minor; 436*91f16700Schasinglulu 437*91f16700Schasinglulu /* 438*91f16700Schasinglulu * MCE firmware is not supported on simulation platforms. 439*91f16700Schasinglulu */ 440*91f16700Schasinglulu if (tegra_platform_is_emulation()) { 441*91f16700Schasinglulu 442*91f16700Schasinglulu INFO("MCE firmware is not supported\n"); 443*91f16700Schasinglulu 444*91f16700Schasinglulu } else { 445*91f16700Schasinglulu /* get a pointer to the CPU's arch_mce_ops_t struct */ 446*91f16700Schasinglulu ops = mce_get_curr_cpu_ops(); 447*91f16700Schasinglulu 448*91f16700Schasinglulu /* get the CPU's ARI base address */ 449*91f16700Schasinglulu cpu_ari_base = mce_get_curr_cpu_ari_base(); 450*91f16700Schasinglulu 451*91f16700Schasinglulu /* 452*91f16700Schasinglulu * Read the MCE firmware version and extract the major and minor 453*91f16700Schasinglulu * version fields 454*91f16700Schasinglulu */ 455*91f16700Schasinglulu version = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_VERSION, 0); 456*91f16700Schasinglulu major = (uint32_t)version; 457*91f16700Schasinglulu minor = (uint32_t)(version >> 32); 458*91f16700Schasinglulu 459*91f16700Schasinglulu INFO("MCE Version - HW=%d:%d, SW=%d:%d\n", major, minor, 460*91f16700Schasinglulu TEGRA_ARI_VERSION_MAJOR, TEGRA_ARI_VERSION_MINOR); 461*91f16700Schasinglulu 462*91f16700Schasinglulu /* 463*91f16700Schasinglulu * Verify that the MCE firmware version and the interface header 464*91f16700Schasinglulu * match 465*91f16700Schasinglulu */ 466*91f16700Schasinglulu if (major != TEGRA_ARI_VERSION_MAJOR) { 467*91f16700Schasinglulu ERROR("ARI major version mismatch\n"); 468*91f16700Schasinglulu panic(); 469*91f16700Schasinglulu } 470*91f16700Schasinglulu 471*91f16700Schasinglulu if (minor < TEGRA_ARI_VERSION_MINOR) { 472*91f16700Schasinglulu ERROR("ARI minor version mismatch\n"); 473*91f16700Schasinglulu panic(); 474*91f16700Schasinglulu } 475*91f16700Schasinglulu } 476*91f16700Schasinglulu } 477