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