17808b06bSVarun Wadekar /*
293c78ed2SAntonio Nino Diaz * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
371376951SVarun Wadekar * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
47808b06bSVarun Wadekar *
582cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause
67808b06bSVarun Wadekar */
77808b06bSVarun Wadekar
809d40e0eSAntonio Nino Diaz #include <assert.h>
909d40e0eSAntonio Nino Diaz #include <errno.h>
10*4ce3e99aSScott Branden #include <inttypes.h>
11*4ce3e99aSScott Branden #include <stdint.h>
1209d40e0eSAntonio Nino Diaz #include <string.h>
1309d40e0eSAntonio Nino Diaz
147808b06bSVarun Wadekar #include <arch.h>
157808b06bSVarun Wadekar #include <arch_helpers.h>
1609d40e0eSAntonio Nino Diaz #include <common/bl_common.h>
1709d40e0eSAntonio Nino Diaz #include <common/debug.h>
187808b06bSVarun Wadekar #include <context.h>
197808b06bSVarun Wadekar #include <denver.h>
2009d40e0eSAntonio Nino Diaz #include <lib/el3_runtime/context_mgmt.h>
2109d40e0eSAntonio Nino Diaz #include <lib/mmio.h>
2209d40e0eSAntonio Nino Diaz
237808b06bSVarun Wadekar #include <mce.h>
2406060028SVarun Wadekar #include <mce_private.h>
257808b06bSVarun Wadekar #include <t18x_ari.h>
267808b06bSVarun Wadekar #include <tegra_def.h>
27524bd090SVarun Wadekar #include <tegra_platform.h>
287808b06bSVarun Wadekar
297808b06bSVarun Wadekar /* NVG functions handlers */
307808b06bSVarun Wadekar static arch_mce_ops_t nvg_mce_ops = {
317808b06bSVarun Wadekar .enter_cstate = nvg_enter_cstate,
327808b06bSVarun Wadekar .update_cstate_info = nvg_update_cstate_info,
337808b06bSVarun Wadekar .update_crossover_time = nvg_update_crossover_time,
347808b06bSVarun Wadekar .read_cstate_stats = nvg_read_cstate_stats,
357808b06bSVarun Wadekar .write_cstate_stats = nvg_write_cstate_stats,
367808b06bSVarun Wadekar .call_enum_misc = ari_enumeration_misc,
377808b06bSVarun Wadekar .is_ccx_allowed = nvg_is_ccx_allowed,
387808b06bSVarun Wadekar .is_sc7_allowed = nvg_is_sc7_allowed,
397808b06bSVarun Wadekar .online_core = nvg_online_core,
407808b06bSVarun Wadekar .cc3_ctrl = nvg_cc3_ctrl,
417808b06bSVarun Wadekar .update_reset_vector = ari_reset_vector_update,
427808b06bSVarun Wadekar .roc_flush_cache = ari_roc_flush_cache,
437808b06bSVarun Wadekar .roc_flush_cache_trbits = ari_roc_flush_cache_trbits,
447808b06bSVarun Wadekar .roc_clean_cache = ari_roc_clean_cache,
457808b06bSVarun Wadekar .read_write_mca = ari_read_write_mca,
467808b06bSVarun Wadekar .update_ccplex_gsc = ari_update_ccplex_gsc,
47c11e0ddfSVarun Wadekar .enter_ccplex_state = ari_enter_ccplex_state,
4853451898SKrishna Sitaraman .read_write_uncore_perfmon = ari_read_write_uncore_perfmon,
4953451898SKrishna Sitaraman .misc_ccplex = ari_misc_ccplex
507808b06bSVarun Wadekar };
517808b06bSVarun Wadekar
527808b06bSVarun Wadekar /* ARI functions handlers */
537808b06bSVarun Wadekar static arch_mce_ops_t ari_mce_ops = {
547808b06bSVarun Wadekar .enter_cstate = ari_enter_cstate,
557808b06bSVarun Wadekar .update_cstate_info = ari_update_cstate_info,
567808b06bSVarun Wadekar .update_crossover_time = ari_update_crossover_time,
577808b06bSVarun Wadekar .read_cstate_stats = ari_read_cstate_stats,
587808b06bSVarun Wadekar .write_cstate_stats = ari_write_cstate_stats,
597808b06bSVarun Wadekar .call_enum_misc = ari_enumeration_misc,
607808b06bSVarun Wadekar .is_ccx_allowed = ari_is_ccx_allowed,
617808b06bSVarun Wadekar .is_sc7_allowed = ari_is_sc7_allowed,
627808b06bSVarun Wadekar .online_core = ari_online_core,
637808b06bSVarun Wadekar .cc3_ctrl = ari_cc3_ctrl,
647808b06bSVarun Wadekar .update_reset_vector = ari_reset_vector_update,
657808b06bSVarun Wadekar .roc_flush_cache = ari_roc_flush_cache,
667808b06bSVarun Wadekar .roc_flush_cache_trbits = ari_roc_flush_cache_trbits,
677808b06bSVarun Wadekar .roc_clean_cache = ari_roc_clean_cache,
687808b06bSVarun Wadekar .read_write_mca = ari_read_write_mca,
697808b06bSVarun Wadekar .update_ccplex_gsc = ari_update_ccplex_gsc,
70c11e0ddfSVarun Wadekar .enter_ccplex_state = ari_enter_ccplex_state,
7153451898SKrishna Sitaraman .read_write_uncore_perfmon = ari_read_write_uncore_perfmon,
7253451898SKrishna Sitaraman .misc_ccplex = ari_misc_ccplex
737808b06bSVarun Wadekar };
747808b06bSVarun Wadekar
75ab712fd8SAnthony Zhou typedef struct {
767808b06bSVarun Wadekar uint32_t ari_base;
777808b06bSVarun Wadekar arch_mce_ops_t *ops;
787808b06bSVarun Wadekar } mce_config_t;
797808b06bSVarun Wadekar
807808b06bSVarun Wadekar /* Table to hold the per-CPU ARI base address and function handlers */
817808b06bSVarun Wadekar static mce_config_t mce_cfg_table[MCE_ARI_APERTURES_MAX] = {
827808b06bSVarun Wadekar {
837808b06bSVarun Wadekar /* A57 Core 0 */
847808b06bSVarun Wadekar .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_0_OFFSET,
857808b06bSVarun Wadekar .ops = &ari_mce_ops,
867808b06bSVarun Wadekar },
877808b06bSVarun Wadekar {
887808b06bSVarun Wadekar /* A57 Core 1 */
897808b06bSVarun Wadekar .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_1_OFFSET,
907808b06bSVarun Wadekar .ops = &ari_mce_ops,
917808b06bSVarun Wadekar },
927808b06bSVarun Wadekar {
937808b06bSVarun Wadekar /* A57 Core 2 */
947808b06bSVarun Wadekar .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_2_OFFSET,
957808b06bSVarun Wadekar .ops = &ari_mce_ops,
967808b06bSVarun Wadekar },
977808b06bSVarun Wadekar {
987808b06bSVarun Wadekar /* A57 Core 3 */
997808b06bSVarun Wadekar .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_3_OFFSET,
1007808b06bSVarun Wadekar .ops = &ari_mce_ops,
1017808b06bSVarun Wadekar },
1027808b06bSVarun Wadekar {
1037808b06bSVarun Wadekar /* D15 Core 0 */
1047808b06bSVarun Wadekar .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_4_OFFSET,
1057808b06bSVarun Wadekar .ops = &nvg_mce_ops,
1067808b06bSVarun Wadekar },
1077808b06bSVarun Wadekar {
1087808b06bSVarun Wadekar /* D15 Core 1 */
1097808b06bSVarun Wadekar .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_5_OFFSET,
1107808b06bSVarun Wadekar .ops = &nvg_mce_ops,
1117808b06bSVarun Wadekar }
1127808b06bSVarun Wadekar };
1137808b06bSVarun Wadekar
mce_get_curr_cpu_ari_base(void)1147808b06bSVarun Wadekar static uint32_t mce_get_curr_cpu_ari_base(void)
1157808b06bSVarun Wadekar {
116ab712fd8SAnthony Zhou uint64_t mpidr = read_mpidr();
1170f426f8fSAnthony Zhou uint64_t cpuid = mpidr & MPIDR_CPU_MASK;
1180f426f8fSAnthony Zhou uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
1197808b06bSVarun Wadekar
1207808b06bSVarun Wadekar /*
1217808b06bSVarun Wadekar * T186 has 2 CPU clusters, one with Denver CPUs and the other with
1227808b06bSVarun Wadekar * ARM CortexA-57 CPUs. Each cluster consists of 4 CPUs and the CPU
1237808b06bSVarun Wadekar * numbers start from 0. In order to get the proper arch_mce_ops_t
1247808b06bSVarun Wadekar * struct, we have to convert the Denver CPU ids to the corresponding
1257808b06bSVarun Wadekar * indices in the mce_ops_table array.
1267808b06bSVarun Wadekar */
127ab712fd8SAnthony Zhou if (impl == DENVER_IMPL) {
128ab712fd8SAnthony Zhou cpuid |= 0x4U;
129ab712fd8SAnthony Zhou }
1307808b06bSVarun Wadekar
1317808b06bSVarun Wadekar return mce_cfg_table[cpuid].ari_base;
1327808b06bSVarun Wadekar }
1337808b06bSVarun Wadekar
mce_get_curr_cpu_ops(void)1347808b06bSVarun Wadekar static arch_mce_ops_t *mce_get_curr_cpu_ops(void)
1357808b06bSVarun Wadekar {
136ab712fd8SAnthony Zhou uint64_t mpidr = read_mpidr();
1370f426f8fSAnthony Zhou uint64_t cpuid = mpidr & MPIDR_CPU_MASK;
1380f426f8fSAnthony Zhou uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) &
1390f426f8fSAnthony Zhou MIDR_IMPL_MASK;
1407808b06bSVarun Wadekar
1417808b06bSVarun Wadekar /*
1427808b06bSVarun Wadekar * T186 has 2 CPU clusters, one with Denver CPUs and the other with
1437808b06bSVarun Wadekar * ARM CortexA-57 CPUs. Each cluster consists of 4 CPUs and the CPU
1447808b06bSVarun Wadekar * numbers start from 0. In order to get the proper arch_mce_ops_t
1457808b06bSVarun Wadekar * struct, we have to convert the Denver CPU ids to the corresponding
1467808b06bSVarun Wadekar * indices in the mce_ops_table array.
1477808b06bSVarun Wadekar */
148ab712fd8SAnthony Zhou if (impl == DENVER_IMPL) {
149ab712fd8SAnthony Zhou cpuid |= 0x4U;
150ab712fd8SAnthony Zhou }
1517808b06bSVarun Wadekar
1527808b06bSVarun Wadekar return mce_cfg_table[cpuid].ops;
1537808b06bSVarun Wadekar }
1547808b06bSVarun Wadekar
1557808b06bSVarun Wadekar /*******************************************************************************
1567808b06bSVarun Wadekar * Common handler for all MCE commands
1577808b06bSVarun Wadekar ******************************************************************************/
mce_command_handler(uint64_t cmd,uint64_t arg0,uint64_t arg1,uint64_t arg2)158ab712fd8SAnthony Zhou int32_t mce_command_handler(uint64_t cmd, uint64_t arg0, uint64_t arg1,
1597808b06bSVarun Wadekar uint64_t arg2)
1607808b06bSVarun Wadekar {
161ab712fd8SAnthony Zhou const arch_mce_ops_t *ops;
162ab712fd8SAnthony Zhou gp_regs_t *gp_regs = get_gpregs_ctx(cm_get_context(NON_SECURE));
1637808b06bSVarun Wadekar uint32_t cpu_ari_base;
1647808b06bSVarun Wadekar uint64_t ret64 = 0, arg3, arg4, arg5;
165ab712fd8SAnthony Zhou int32_t ret = 0;
1667808b06bSVarun Wadekar
167ab712fd8SAnthony Zhou assert(gp_regs != NULL);
1687808b06bSVarun Wadekar
1697808b06bSVarun Wadekar /* get a pointer to the CPU's arch_mce_ops_t struct */
1707808b06bSVarun Wadekar ops = mce_get_curr_cpu_ops();
1717808b06bSVarun Wadekar
1727808b06bSVarun Wadekar /* get the CPU's ARI base address */
1737808b06bSVarun Wadekar cpu_ari_base = mce_get_curr_cpu_ari_base();
1747808b06bSVarun Wadekar
1757808b06bSVarun Wadekar switch (cmd) {
176aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_ENTER_CSTATE:
1777808b06bSVarun Wadekar ret = ops->enter_cstate(cpu_ari_base, arg0, arg1);
1787808b06bSVarun Wadekar
1797808b06bSVarun Wadekar break;
1807808b06bSVarun Wadekar
181aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_UPDATE_CSTATE_INFO:
1827808b06bSVarun Wadekar /*
1837808b06bSVarun Wadekar * get the parameters required for the update cstate info
1847808b06bSVarun Wadekar * command
1857808b06bSVarun Wadekar */
1860f426f8fSAnthony Zhou arg3 = read_ctx_reg(gp_regs, CTX_GPREG_X4);
1870f426f8fSAnthony Zhou arg4 = read_ctx_reg(gp_regs, CTX_GPREG_X5);
1880f426f8fSAnthony Zhou arg5 = read_ctx_reg(gp_regs, CTX_GPREG_X6);
1897808b06bSVarun Wadekar
1907808b06bSVarun Wadekar ret = ops->update_cstate_info(cpu_ari_base, (uint32_t)arg0,
1917808b06bSVarun Wadekar (uint32_t)arg1, (uint32_t)arg2, (uint8_t)arg3,
1927808b06bSVarun Wadekar (uint32_t)arg4, (uint8_t)arg5);
1937808b06bSVarun Wadekar
1940f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X4, (0ULL));
1950f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X5, (0ULL));
1960f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X6, (0ULL));
1977808b06bSVarun Wadekar
1987808b06bSVarun Wadekar break;
1997808b06bSVarun Wadekar
200aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_UPDATE_CROSSOVER_TIME:
2017808b06bSVarun Wadekar ret = ops->update_crossover_time(cpu_ari_base, arg0, arg1);
2027808b06bSVarun Wadekar
2037808b06bSVarun Wadekar break;
2047808b06bSVarun Wadekar
205aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_READ_CSTATE_STATS:
2067808b06bSVarun Wadekar ret64 = ops->read_cstate_stats(cpu_ari_base, arg0);
2077808b06bSVarun Wadekar
2087808b06bSVarun Wadekar /* update context to return cstate stats value */
2090f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64));
2100f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X2, (ret64));
2117808b06bSVarun Wadekar
2127808b06bSVarun Wadekar break;
2137808b06bSVarun Wadekar
214aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_WRITE_CSTATE_STATS:
2157808b06bSVarun Wadekar ret = ops->write_cstate_stats(cpu_ari_base, arg0, arg1);
2167808b06bSVarun Wadekar
2177808b06bSVarun Wadekar break;
2187808b06bSVarun Wadekar
219aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_IS_CCX_ALLOWED:
2207808b06bSVarun Wadekar ret = ops->is_ccx_allowed(cpu_ari_base, arg0, arg1);
2217808b06bSVarun Wadekar
2227808b06bSVarun Wadekar /* update context to return CCx status value */
2230f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X1, (uint64_t)(ret));
2247808b06bSVarun Wadekar
2257808b06bSVarun Wadekar break;
2267808b06bSVarun Wadekar
227aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_IS_SC7_ALLOWED:
2287808b06bSVarun Wadekar ret = ops->is_sc7_allowed(cpu_ari_base, arg0, arg1);
2297808b06bSVarun Wadekar
2307808b06bSVarun Wadekar /* update context to return SC7 status value */
2310f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X1, (uint64_t)(ret));
2320f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X3, (uint64_t)(ret));
2337808b06bSVarun Wadekar
2347808b06bSVarun Wadekar break;
2357808b06bSVarun Wadekar
236aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_ONLINE_CORE:
2377808b06bSVarun Wadekar ret = ops->online_core(cpu_ari_base, arg0);
2387808b06bSVarun Wadekar
2397808b06bSVarun Wadekar break;
2407808b06bSVarun Wadekar
241aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_CC3_CTRL:
2427808b06bSVarun Wadekar ret = ops->cc3_ctrl(cpu_ari_base, arg0, arg1, arg2);
2437808b06bSVarun Wadekar
2447808b06bSVarun Wadekar break;
2457808b06bSVarun Wadekar
246aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_ECHO_DATA:
2477808b06bSVarun Wadekar ret64 = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_ECHO,
2487808b06bSVarun Wadekar arg0);
2497808b06bSVarun Wadekar
2507808b06bSVarun Wadekar /* update context to return if echo'd data matched source */
2510f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X1, ((ret64 == arg0) ?
2520f426f8fSAnthony Zhou 1ULL : 0ULL));
2530f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X2, ((ret64 == arg0) ?
2540f426f8fSAnthony Zhou 1ULL : 0ULL));
2557808b06bSVarun Wadekar
2567808b06bSVarun Wadekar break;
2577808b06bSVarun Wadekar
258aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_READ_VERSIONS:
2597808b06bSVarun Wadekar ret64 = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_VERSION,
2607808b06bSVarun Wadekar arg0);
2617808b06bSVarun Wadekar
2627808b06bSVarun Wadekar /*
2637808b06bSVarun Wadekar * version = minor(63:32) | major(31:0). Update context
2647808b06bSVarun Wadekar * to return major and minor version number.
2657808b06bSVarun Wadekar */
2660f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64));
2670f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X2, (ret64 >> 32ULL));
2687808b06bSVarun Wadekar
2697808b06bSVarun Wadekar break;
2707808b06bSVarun Wadekar
271aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_ENUM_FEATURES:
2726ef90b96SKrishna Sitaraman ret64 = ops->call_enum_misc(cpu_ari_base,
2737808b06bSVarun Wadekar TEGRA_ARI_MISC_FEATURE_LEAF_0, arg0);
2747808b06bSVarun Wadekar
2757808b06bSVarun Wadekar /* update context to return features value */
2760f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64));
2777808b06bSVarun Wadekar
2787808b06bSVarun Wadekar break;
2797808b06bSVarun Wadekar
280aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_ROC_FLUSH_CACHE_TRBITS:
2817808b06bSVarun Wadekar ret = ops->roc_flush_cache_trbits(cpu_ari_base);
2827808b06bSVarun Wadekar
2837808b06bSVarun Wadekar break;
2847808b06bSVarun Wadekar
285aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_ROC_FLUSH_CACHE:
2867808b06bSVarun Wadekar ret = ops->roc_flush_cache(cpu_ari_base);
2877808b06bSVarun Wadekar
2887808b06bSVarun Wadekar break;
2897808b06bSVarun Wadekar
290aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_ROC_CLEAN_CACHE:
2917808b06bSVarun Wadekar ret = ops->roc_clean_cache(cpu_ari_base);
2927808b06bSVarun Wadekar
2937808b06bSVarun Wadekar break;
2947808b06bSVarun Wadekar
295aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_ENUM_READ_MCA:
296ab712fd8SAnthony Zhou ret64 = ops->read_write_mca(cpu_ari_base, arg0, &arg1);
2977808b06bSVarun Wadekar
2987808b06bSVarun Wadekar /* update context to return MCA data/error */
2990f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64));
3000f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X2, (arg1));
3010f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X3, (ret64));
3027808b06bSVarun Wadekar
3037808b06bSVarun Wadekar break;
3047808b06bSVarun Wadekar
305aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_ENUM_WRITE_MCA:
306ab712fd8SAnthony Zhou ret64 = ops->read_write_mca(cpu_ari_base, arg0, &arg1);
3077808b06bSVarun Wadekar
3087808b06bSVarun Wadekar /* update context to return MCA error */
3090f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64));
3100f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X3, (ret64));
3117808b06bSVarun Wadekar
3127808b06bSVarun Wadekar break;
3137808b06bSVarun Wadekar
31466ec1125SVarun Wadekar #if ENABLE_CHIP_VERIFICATION_HARNESS
315aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_ENABLE_LATIC:
31666ec1125SVarun Wadekar /*
31766ec1125SVarun Wadekar * This call is not for production use. The constant value,
31866ec1125SVarun Wadekar * 0xFFFF0000, is specific to allowing for enabling LATIC on
31966ec1125SVarun Wadekar * pre-production parts for the chip verification harness.
32066ec1125SVarun Wadekar *
32166ec1125SVarun Wadekar * Enabling LATIC allows S/W to read the MINI ISPs in the
32266ec1125SVarun Wadekar * CCPLEX. The ISMs are used for various measurements relevant
32366ec1125SVarun Wadekar * to particular locations in the Silicon. They are small
32466ec1125SVarun Wadekar * counters which can be polled to determine how fast a
32566ec1125SVarun Wadekar * particular location in the Silicon is.
32666ec1125SVarun Wadekar */
32766ec1125SVarun Wadekar ops->enter_ccplex_state(mce_get_curr_cpu_ari_base(),
32866ec1125SVarun Wadekar 0xFFFF0000);
32966ec1125SVarun Wadekar
33066ec1125SVarun Wadekar break;
33166ec1125SVarun Wadekar #endif
332c11e0ddfSVarun Wadekar
333aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_UNCORE_PERFMON_REQ:
334ab712fd8SAnthony Zhou ret = ops->read_write_uncore_perfmon(cpu_ari_base, arg0, &arg1);
335c11e0ddfSVarun Wadekar
336c11e0ddfSVarun Wadekar /* update context to return data */
3370f426f8fSAnthony Zhou write_ctx_reg(gp_regs, CTX_GPREG_X1, (arg1));
338c11e0ddfSVarun Wadekar break;
339c11e0ddfSVarun Wadekar
340aa64c5fbSAnthony Zhou case (uint64_t)MCE_CMD_MISC_CCPLEX:
34153451898SKrishna Sitaraman ops->misc_ccplex(cpu_ari_base, arg0, arg1);
34253451898SKrishna Sitaraman
34353451898SKrishna Sitaraman break;
34453451898SKrishna Sitaraman
3457808b06bSVarun Wadekar default:
346*4ce3e99aSScott Branden ERROR("unknown MCE command (%" PRIu64 ")\n", cmd);
347ab712fd8SAnthony Zhou ret = EINVAL;
348ab712fd8SAnthony Zhou break;
3497808b06bSVarun Wadekar }
3507808b06bSVarun Wadekar
3517808b06bSVarun Wadekar return ret;
3527808b06bSVarun Wadekar }
3537808b06bSVarun Wadekar
3547808b06bSVarun Wadekar /*******************************************************************************
3557808b06bSVarun Wadekar * Handler to update the reset vector for CPUs
3567808b06bSVarun Wadekar ******************************************************************************/
mce_update_reset_vector(void)357ab712fd8SAnthony Zhou int32_t mce_update_reset_vector(void)
3587808b06bSVarun Wadekar {
359ab712fd8SAnthony Zhou const arch_mce_ops_t *ops = mce_get_curr_cpu_ops();
3607808b06bSVarun Wadekar
361a259293eSKrishna Sitaraman ops->update_reset_vector(mce_get_curr_cpu_ari_base());
3627808b06bSVarun Wadekar
3637808b06bSVarun Wadekar return 0;
3647808b06bSVarun Wadekar }
3657808b06bSVarun Wadekar
mce_update_ccplex_gsc(tegra_ari_gsc_index_t gsc_idx)366ab712fd8SAnthony Zhou static int32_t mce_update_ccplex_gsc(tegra_ari_gsc_index_t gsc_idx)
3677808b06bSVarun Wadekar {
368ab712fd8SAnthony Zhou const arch_mce_ops_t *ops = mce_get_curr_cpu_ops();
3697808b06bSVarun Wadekar
3707808b06bSVarun Wadekar ops->update_ccplex_gsc(mce_get_curr_cpu_ari_base(), gsc_idx);
3717808b06bSVarun Wadekar
3727808b06bSVarun Wadekar return 0;
3737808b06bSVarun Wadekar }
3747808b06bSVarun Wadekar
3757808b06bSVarun Wadekar /*******************************************************************************
3767808b06bSVarun Wadekar * Handler to update carveout values for Video Memory Carveout region
3777808b06bSVarun Wadekar ******************************************************************************/
mce_update_gsc_videomem(void)378ab712fd8SAnthony Zhou int32_t mce_update_gsc_videomem(void)
3797808b06bSVarun Wadekar {
3807808b06bSVarun Wadekar return mce_update_ccplex_gsc(TEGRA_ARI_GSC_VPR_IDX);
3817808b06bSVarun Wadekar }
3827808b06bSVarun Wadekar
3837808b06bSVarun Wadekar /*******************************************************************************
3847808b06bSVarun Wadekar * Handler to update carveout values for TZDRAM aperture
3857808b06bSVarun Wadekar ******************************************************************************/
mce_update_gsc_tzdram(void)386ab712fd8SAnthony Zhou int32_t mce_update_gsc_tzdram(void)
3877808b06bSVarun Wadekar {
3887808b06bSVarun Wadekar return mce_update_ccplex_gsc(TEGRA_ARI_GSC_TZ_DRAM_IDX);
3897808b06bSVarun Wadekar }
3907808b06bSVarun Wadekar
3917808b06bSVarun Wadekar /*******************************************************************************
3927808b06bSVarun Wadekar * Handler to shutdown/reset the entire system
3937808b06bSVarun Wadekar ******************************************************************************/
mce_enter_ccplex_state(uint32_t state_idx)3947808b06bSVarun Wadekar __dead2 void mce_enter_ccplex_state(uint32_t state_idx)
3957808b06bSVarun Wadekar {
396ab712fd8SAnthony Zhou const arch_mce_ops_t *ops = mce_get_curr_cpu_ops();
3977808b06bSVarun Wadekar
3987808b06bSVarun Wadekar /* sanity check state value */
399ab712fd8SAnthony Zhou if ((state_idx != TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF) &&
400ab712fd8SAnthony Zhou (state_idx != TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT)) {
4017808b06bSVarun Wadekar panic();
402ab712fd8SAnthony Zhou }
4037808b06bSVarun Wadekar
4047808b06bSVarun Wadekar ops->enter_ccplex_state(mce_get_curr_cpu_ari_base(), state_idx);
4057808b06bSVarun Wadekar
4067808b06bSVarun Wadekar /* wait till the CCPLEX powers down */
407ab712fd8SAnthony Zhou for (;;) {
4087808b06bSVarun Wadekar ;
409ab712fd8SAnthony Zhou }
4107808b06bSVarun Wadekar
4117808b06bSVarun Wadekar }
4125cb89c56SVarun Wadekar
4135cb89c56SVarun Wadekar /*******************************************************************************
41487a1df73SVarun Wadekar * Handler to issue the UPDATE_CSTATE_INFO request
41587a1df73SVarun Wadekar ******************************************************************************/
mce_update_cstate_info(const mce_cstate_info_t * cstate)416ab712fd8SAnthony Zhou void mce_update_cstate_info(const mce_cstate_info_t *cstate)
41787a1df73SVarun Wadekar {
418ab712fd8SAnthony Zhou const arch_mce_ops_t *ops = mce_get_curr_cpu_ops();
41987a1df73SVarun Wadekar
42087a1df73SVarun Wadekar /* issue the UPDATE_CSTATE_INFO request */
42187a1df73SVarun Wadekar ops->update_cstate_info(mce_get_curr_cpu_ari_base(), cstate->cluster,
42287a1df73SVarun Wadekar cstate->ccplex, cstate->system, cstate->system_state_force,
42387a1df73SVarun Wadekar cstate->wake_mask, cstate->update_wake_mask);
42487a1df73SVarun Wadekar }
42587a1df73SVarun Wadekar
42687a1df73SVarun Wadekar /*******************************************************************************
4275cb89c56SVarun Wadekar * Handler to read the MCE firmware version and check if it is compatible
4285cb89c56SVarun Wadekar * with interface header the BL3-1 was compiled against
4295cb89c56SVarun Wadekar ******************************************************************************/
mce_verify_firmware_version(void)4305cb89c56SVarun Wadekar void mce_verify_firmware_version(void)
4315cb89c56SVarun Wadekar {
432ab712fd8SAnthony Zhou const arch_mce_ops_t *ops;
4335cb89c56SVarun Wadekar uint32_t cpu_ari_base;
4345cb89c56SVarun Wadekar uint64_t version;
435524bd090SVarun Wadekar uint32_t major, minor;
436524bd090SVarun Wadekar
437524bd090SVarun Wadekar /*
43806060028SVarun Wadekar * MCE firmware is not supported on simulation platforms.
439524bd090SVarun Wadekar */
440ab712fd8SAnthony Zhou if (tegra_platform_is_emulation()) {
4415cb89c56SVarun Wadekar
442ab712fd8SAnthony Zhou INFO("MCE firmware is not supported\n");
443ab712fd8SAnthony Zhou
444ab712fd8SAnthony Zhou } else {
4455cb89c56SVarun Wadekar /* get a pointer to the CPU's arch_mce_ops_t struct */
4465cb89c56SVarun Wadekar ops = mce_get_curr_cpu_ops();
4475cb89c56SVarun Wadekar
4485cb89c56SVarun Wadekar /* get the CPU's ARI base address */
4495cb89c56SVarun Wadekar cpu_ari_base = mce_get_curr_cpu_ari_base();
4505cb89c56SVarun Wadekar
4515cb89c56SVarun Wadekar /*
4525cb89c56SVarun Wadekar * Read the MCE firmware version and extract the major and minor
4535cb89c56SVarun Wadekar * version fields
4545cb89c56SVarun Wadekar */
4555cb89c56SVarun Wadekar version = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_VERSION, 0);
4565cb89c56SVarun Wadekar major = (uint32_t)version;
4575cb89c56SVarun Wadekar minor = (uint32_t)(version >> 32);
4585cb89c56SVarun Wadekar
4595cb89c56SVarun Wadekar INFO("MCE Version - HW=%d:%d, SW=%d:%d\n", major, minor,
4605cb89c56SVarun Wadekar TEGRA_ARI_VERSION_MAJOR, TEGRA_ARI_VERSION_MINOR);
4615cb89c56SVarun Wadekar
4625cb89c56SVarun Wadekar /*
4635cb89c56SVarun Wadekar * Verify that the MCE firmware version and the interface header
4645cb89c56SVarun Wadekar * match
4655cb89c56SVarun Wadekar */
4665cb89c56SVarun Wadekar if (major != TEGRA_ARI_VERSION_MAJOR) {
4675cb89c56SVarun Wadekar ERROR("ARI major version mismatch\n");
4685cb89c56SVarun Wadekar panic();
4695cb89c56SVarun Wadekar }
4705cb89c56SVarun Wadekar
4715cb89c56SVarun Wadekar if (minor < TEGRA_ARI_VERSION_MINOR) {
4725cb89c56SVarun Wadekar ERROR("ARI minor version mismatch\n");
4735cb89c56SVarun Wadekar panic();
4745cb89c56SVarun Wadekar }
4755cb89c56SVarun Wadekar }
476ab712fd8SAnthony Zhou }
477