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