xref: /rk3399_ARM-atf/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c (revision 28623c102d6fec0ba0271be64951679bf20681ba)
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