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