| /* |
| * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| */ |
| |
| #include <arch.h> |
| #include <arch_helpers.h> |
| #include <assert.h> |
| #include <common/bl_common.h> |
| #include <context.h> |
| #include <lib/el3_runtime/context_mgmt.h> |
| #include <common/debug.h> |
| #include <denver.h> |
| #include <mce.h> |
| #include <mce_private.h> |
| #include <mmio.h> |
| #include <platform_def.h> |
| #include <string.h> |
| #include <errno.h> |
| #include <t194_nvg.h> |
| #include <tegra_def.h> |
| #include <tegra_platform.h> |
| |
| /******************************************************************************* |
| * Common handler for all MCE commands |
| ******************************************************************************/ |
| int32_t mce_command_handler(uint64_t cmd, uint64_t arg0, uint64_t arg1, |
| uint64_t arg2) |
| { |
| uint64_t ret64 = 0, arg3, arg4, arg5; |
| int32_t ret = 0; |
| cpu_context_t *ctx = cm_get_context(NON_SECURE); |
| gp_regs_t *gp_regs = get_gpregs_ctx(ctx); |
| |
| assert(ctx); |
| assert(gp_regs); |
| |
| switch (cmd) { |
| case MCE_CMD_ENTER_CSTATE: |
| ret = nvg_enter_cstate((uint32_t)arg0, (uint32_t)arg1); |
| if (ret < 0) { |
| ERROR("%s: enter_cstate failed(%d)\n", __func__, ret); |
| } |
| |
| break; |
| |
| case MCE_CMD_UPDATE_CSTATE_INFO: |
| /* |
| * get the parameters required for the update cstate info |
| * command |
| */ |
| arg3 = read_ctx_reg(gp_regs, ((uint64_t)CTX_GPREG_X4)); |
| arg4 = read_ctx_reg(gp_regs, ((uint64_t)CTX_GPREG_X5)); |
| arg5 = read_ctx_reg(gp_regs, ((uint64_t)CTX_GPREG_X6)); |
| |
| /* arg0 cluster |
| * arg1 ccplex |
| * arg2 system |
| * arg3 sys_state_force => T19x not support |
| * arg4 wake_mask |
| * arg5 update_wake_mask |
| */ |
| nvg_update_cstate_info((uint32_t)arg0, (uint32_t)arg1, |
| (uint32_t)arg2, (uint32_t)arg4, (uint8_t)arg5); |
| |
| write_ctx_reg(gp_regs, ((uint64_t)CTX_GPREG_X4), (arg3)); |
| write_ctx_reg(gp_regs, ((uint64_t)CTX_GPREG_X5), (arg4)); |
| write_ctx_reg(gp_regs, ((uint64_t)CTX_GPREG_X6), (arg5)); |
| |
| break; |
| |
| case MCE_CMD_UPDATE_CROSSOVER_TIME: |
| ret = nvg_update_crossover_time((uint32_t)arg0, (uint32_t)arg1); |
| if (ret < 0) { |
| ERROR("%s: update_crossover_time failed(%d)\n", |
| __func__, ret); |
| } |
| |
| break; |
| |
| case MCE_CMD_READ_CSTATE_STATS: |
| ret64 = nvg_get_cstate_stat_query_value(); |
| |
| /* update context to return cstate stats value */ |
| write_ctx_reg(gp_regs, ((uint64_t)CTX_GPREG_X1), (ret64)); |
| write_ctx_reg(gp_regs, ((uint64_t)CTX_GPREG_X2), (ret64)); |
| |
| break; |
| |
| case MCE_CMD_WRITE_CSTATE_STATS: |
| ret = nvg_set_cstate_stat_query_value(arg0); |
| |
| break; |
| |
| case MCE_CMD_IS_SC7_ALLOWED: |
| ret = nvg_is_sc7_allowed(); |
| if (ret < 0) { |
| ERROR("%s: is_sc7_allowed failed(%d)\n", __func__, ret); |
| break; |
| } |
| |
| /* update context to return SC7 status value */ |
| write_ctx_reg(gp_regs, ((uint64_t)CTX_GPREG_X1), ((uint64_t)ret)); |
| write_ctx_reg(gp_regs, ((uint64_t)CTX_GPREG_X3), ((uint64_t)ret)); |
| |
| break; |
| |
| case MCE_CMD_ONLINE_CORE: |
| ret = nvg_online_core((uint32_t)arg0); |
| if (ret < 0) { |
| ERROR("%s: online_core failed(%d)\n", __func__, ret); |
| } |
| |
| break; |
| |
| case MCE_CMD_CC3_CTRL: |
| ret = nvg_cc3_ctrl((uint32_t)arg0, (uint8_t)arg2); |
| if (ret < 0) { |
| ERROR("%s: cc3_ctrl failed(%d)\n", __func__, ret); |
| } |
| |
| break; |
| |
| case MCE_CMD_READ_VERSIONS: |
| /* get the MCE firmware version */ |
| ret64 = nvg_get_version(); |
| |
| /* |
| * version = minor(63:32) | major(31:0). Update context |
| * to return major and minor version number. |
| */ |
| write_ctx_reg(gp_regs, ((uint64_t)CTX_GPREG_X1), (ret64 & (uint64_t)0xFFFF)); |
| write_ctx_reg(gp_regs, ((uint64_t)CTX_GPREG_X2), (ret64 >> 32)); |
| |
| break; |
| |
| case MCE_CMD_ROC_FLUSH_CACHE_TRBITS: |
| ret = nvg_roc_clean_cache_trbits(); |
| if (ret < 0) { |
| ERROR("%s: flush cache_trbits failed(%d)\n", __func__, |
| ret); |
| } |
| |
| break; |
| |
| case MCE_CMD_ROC_FLUSH_CACHE: |
| ret = nvg_roc_flush_cache(); |
| if (ret < 0) { |
| ERROR("%s: flush cache failed(%d)\n", __func__, ret); |
| } |
| |
| break; |
| |
| case MCE_CMD_ROC_CLEAN_CACHE: |
| ret = nvg_roc_clean_cache(); |
| if (ret < 0) { |
| ERROR("%s: clean cache failed(%d)\n", __func__, ret); |
| } |
| |
| break; |
| |
| default: |
| ERROR("unknown MCE command (%llu)\n", cmd); |
| ret = EINVAL; |
| break; |
| } |
| |
| return ret; |
| } |
| |
| /******************************************************************************* |
| * Handler to update carveout values for Video Memory Carveout region |
| ******************************************************************************/ |
| int32_t mce_update_gsc_videomem(void) |
| { |
| return nvg_update_ccplex_gsc((uint32_t)TEGRA_NVG_GSC_VPR_IDX); |
| } |
| |
| /******************************************************************************* |
| * Handler to update carveout values for TZDRAM aperture |
| ******************************************************************************/ |
| int32_t mce_update_gsc_tzdram(void) |
| { |
| return nvg_update_ccplex_gsc((uint32_t)TEGRA_NVG_GSC_TZ_DRAM_IDX); |
| } |
| |
| /******************************************************************************* |
| * Handler to update carveout values for TZ SysRAM aperture |
| ******************************************************************************/ |
| int32_t mce_update_gsc_tzram(void) |
| { |
| return nvg_update_ccplex_gsc((uint32_t)TEGRA_NVG_GSC_TZRAM); |
| } |
| |
| /******************************************************************************* |
| * Handler to issue the UPDATE_CSTATE_INFO request |
| ******************************************************************************/ |
| void mce_update_cstate_info(const mce_cstate_info_t *cstate) |
| { |
| /* issue the UPDATE_CSTATE_INFO request */ |
| nvg_update_cstate_info(cstate->cluster, cstate->ccplex, cstate->system, |
| cstate->wake_mask, cstate->update_wake_mask); |
| } |
| |
| /******************************************************************************* |
| * Handler to read the MCE firmware version and check if it is compatible |
| * with interface header the BL3-1 was compiled against |
| ******************************************************************************/ |
| void mce_verify_firmware_version(void) |
| { |
| uint64_t version; |
| uint32_t major, minor; |
| |
| /* |
| * MCE firmware is not running on simulation platforms. |
| */ |
| if ((tegra_platform_is_linsim() == 1U) || |
| (tegra_platform_is_virt_dev_kit() == 1U) || |
| (tegra_platform_is_qt() == 1U)) { |
| return; |
| } |
| |
| /* |
| * Read the MCE firmware version and extract the major and minor |
| * version fields |
| */ |
| version = nvg_get_version(); |
| minor = (uint32_t)version; |
| major = (uint32_t)(version >> 32); |
| |
| INFO("MCE Version - HW=%d:%d, SW=%d:%d\n", major, minor, |
| 0, 0); |
| |
| /* |
| * Verify that the MCE firmware version and the interface header |
| * match |
| */ |
| if (major != (uint32_t)TEGRA_NVG_VERSION_MAJOR) { |
| ERROR("MCE major version mismatch\n"); |
| panic(); |
| } |
| |
| if (minor < (uint32_t)TEGRA_NVG_VERSION_MINOR) { |
| ERROR("MCE minor version mismatch\n"); |
| panic(); |
| } |
| } |