2 * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
4 * SPDX-License-Identifier: BSD-3-Clause
12 #include <arch_helpers.h>
13 #include <common/bl_common.h>
14 #include <common/debug.h>
17 #include <lib/el3_runtime/context_mgmt.h>
21 #include <mce_private.h>
23 #include <tegra_def.h>
24 #include <tegra_platform.h>
26 /* NVG functions handlers */
27 static arch_mce_ops_t nvg_mce_ops
= {
28 .enter_cstate
= nvg_enter_cstate
,
29 .update_cstate_info
= nvg_update_cstate_info
,
30 .update_crossover_time
= nvg_update_crossover_time
,
31 .read_cstate_stats
= nvg_read_cstate_stats
,
32 .write_cstate_stats
= nvg_write_cstate_stats
,
33 .call_enum_misc
= ari_enumeration_misc
,
34 .is_ccx_allowed
= nvg_is_ccx_allowed
,
35 .is_sc7_allowed
= nvg_is_sc7_allowed
,
36 .online_core
= nvg_online_core
,
37 .cc3_ctrl
= nvg_cc3_ctrl
,
38 .update_reset_vector
= ari_reset_vector_update
,
39 .roc_flush_cache
= ari_roc_flush_cache
,
40 .roc_flush_cache_trbits
= ari_roc_flush_cache_trbits
,
41 .roc_clean_cache
= ari_roc_clean_cache
,
42 .read_write_mca
= ari_read_write_mca
,
43 .update_ccplex_gsc
= ari_update_ccplex_gsc
,
44 .enter_ccplex_state
= ari_enter_ccplex_state
,
45 .read_write_uncore_perfmon
= ari_read_write_uncore_perfmon
,
46 .misc_ccplex
= ari_misc_ccplex
49 /* ARI functions handlers */
50 static arch_mce_ops_t ari_mce_ops
= {
51 .enter_cstate
= ari_enter_cstate
,
52 .update_cstate_info
= ari_update_cstate_info
,
53 .update_crossover_time
= ari_update_crossover_time
,
54 .read_cstate_stats
= ari_read_cstate_stats
,
55 .write_cstate_stats
= ari_write_cstate_stats
,
56 .call_enum_misc
= ari_enumeration_misc
,
57 .is_ccx_allowed
= ari_is_ccx_allowed
,
58 .is_sc7_allowed
= ari_is_sc7_allowed
,
59 .online_core
= ari_online_core
,
60 .cc3_ctrl
= ari_cc3_ctrl
,
61 .update_reset_vector
= ari_reset_vector_update
,
62 .roc_flush_cache
= ari_roc_flush_cache
,
63 .roc_flush_cache_trbits
= ari_roc_flush_cache_trbits
,
64 .roc_clean_cache
= ari_roc_clean_cache
,
65 .read_write_mca
= ari_read_write_mca
,
66 .update_ccplex_gsc
= ari_update_ccplex_gsc
,
67 .enter_ccplex_state
= ari_enter_ccplex_state
,
68 .read_write_uncore_perfmon
= ari_read_write_uncore_perfmon
,
69 .misc_ccplex
= ari_misc_ccplex
77 /* Table to hold the per-CPU ARI base address and function handlers */
78 static mce_config_t mce_cfg_table
[MCE_ARI_APERTURES_MAX
] = {
81 .ari_base
= TEGRA_MMCRAB_BASE
+ MCE_ARI_APERTURE_0_OFFSET
,
86 .ari_base
= TEGRA_MMCRAB_BASE
+ MCE_ARI_APERTURE_1_OFFSET
,
91 .ari_base
= TEGRA_MMCRAB_BASE
+ MCE_ARI_APERTURE_2_OFFSET
,
96 .ari_base
= TEGRA_MMCRAB_BASE
+ MCE_ARI_APERTURE_3_OFFSET
,
101 .ari_base
= TEGRA_MMCRAB_BASE
+ MCE_ARI_APERTURE_4_OFFSET
,
106 .ari_base
= TEGRA_MMCRAB_BASE
+ MCE_ARI_APERTURE_5_OFFSET
,
111 static uint32_t mce_get_curr_cpu_ari_base(void)
113 uint64_t mpidr
= read_mpidr();
114 uint64_t cpuid
= mpidr
& (uint64_t)MPIDR_CPU_MASK
;
115 uint64_t impl
= (read_midr() >> (uint64_t)MIDR_IMPL_SHIFT
) & (uint64_t)MIDR_IMPL_MASK
;
118 * T186 has 2 CPU clusters, one with Denver CPUs and the other with
119 * ARM CortexA-57 CPUs. Each cluster consists of 4 CPUs and the CPU
120 * numbers start from 0. In order to get the proper arch_mce_ops_t
121 * struct, we have to convert the Denver CPU ids to the corresponding
122 * indices in the mce_ops_table array.
124 if (impl
== DENVER_IMPL
) {
128 return mce_cfg_table
[cpuid
].ari_base
;
131 static arch_mce_ops_t
*mce_get_curr_cpu_ops(void)
133 uint64_t mpidr
= read_mpidr();
134 uint64_t cpuid
= mpidr
& (uint64_t)MPIDR_CPU_MASK
;
135 uint64_t impl
= (read_midr() >> (uint64_t)MIDR_IMPL_SHIFT
) &
136 (uint64_t)MIDR_IMPL_MASK
;
139 * T186 has 2 CPU clusters, one with Denver CPUs and the other with
140 * ARM CortexA-57 CPUs. Each cluster consists of 4 CPUs and the CPU
141 * numbers start from 0. In order to get the proper arch_mce_ops_t
142 * struct, we have to convert the Denver CPU ids to the corresponding
143 * indices in the mce_ops_table array.
145 if (impl
== DENVER_IMPL
) {
149 return mce_cfg_table
[cpuid
].ops
;
152 /*******************************************************************************
153 * Common handler for all MCE commands
154 ******************************************************************************/
155 int32_t mce_command_handler(uint64_t cmd
, uint64_t arg0
, uint64_t arg1
,
158 const arch_mce_ops_t
*ops
;
159 gp_regs_t
*gp_regs
= get_gpregs_ctx(cm_get_context(NON_SECURE
));
160 uint32_t cpu_ari_base
;
161 uint64_t ret64
= 0, arg3
, arg4
, arg5
;
164 assert(gp_regs
!= NULL
);
166 /* get a pointer to the CPU's arch_mce_ops_t struct */
167 ops
= mce_get_curr_cpu_ops();
169 /* get the CPU's ARI base address */
170 cpu_ari_base
= mce_get_curr_cpu_ari_base();
173 case MCE_CMD_ENTER_CSTATE
:
174 ret
= ops
->enter_cstate(cpu_ari_base
, arg0
, arg1
);
176 ERROR("%s: enter_cstate failed(%d)\n", __func__
, ret
);
181 case MCE_CMD_UPDATE_CSTATE_INFO
:
183 * get the parameters required for the update cstate info
186 arg3
= read_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X4
));
187 arg4
= read_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X5
));
188 arg5
= read_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X6
));
190 ret
= ops
->update_cstate_info(cpu_ari_base
, (uint32_t)arg0
,
191 (uint32_t)arg1
, (uint32_t)arg2
, (uint8_t)arg3
,
192 (uint32_t)arg4
, (uint8_t)arg5
);
194 ERROR("%s: update_cstate_info failed(%d)\n",
198 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X4
), (0));
199 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X5
), (0));
200 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X6
), (0));
204 case MCE_CMD_UPDATE_CROSSOVER_TIME
:
205 ret
= ops
->update_crossover_time(cpu_ari_base
, arg0
, arg1
);
207 ERROR("%s: update_crossover_time failed(%d)\n",
213 case MCE_CMD_READ_CSTATE_STATS
:
214 ret64
= ops
->read_cstate_stats(cpu_ari_base
, arg0
);
216 /* update context to return cstate stats value */
217 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X1
), (ret64
));
218 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X2
), (ret64
));
222 case MCE_CMD_WRITE_CSTATE_STATS
:
223 ret
= ops
->write_cstate_stats(cpu_ari_base
, arg0
, arg1
);
225 ERROR("%s: write_cstate_stats failed(%d)\n",
231 case MCE_CMD_IS_CCX_ALLOWED
:
232 ret
= ops
->is_ccx_allowed(cpu_ari_base
, arg0
, arg1
);
234 ERROR("%s: is_ccx_allowed failed(%d)\n", __func__
, ret
);
238 /* update context to return CCx status value */
239 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X1
),
244 case MCE_CMD_IS_SC7_ALLOWED
:
245 ret
= ops
->is_sc7_allowed(cpu_ari_base
, arg0
, arg1
);
247 ERROR("%s: is_sc7_allowed failed(%d)\n", __func__
, ret
);
251 /* update context to return SC7 status value */
252 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X1
),
254 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X3
),
259 case MCE_CMD_ONLINE_CORE
:
260 ret
= ops
->online_core(cpu_ari_base
, arg0
);
262 ERROR("%s: online_core failed(%d)\n", __func__
, ret
);
267 case MCE_CMD_CC3_CTRL
:
268 ret
= ops
->cc3_ctrl(cpu_ari_base
, arg0
, arg1
, arg2
);
270 ERROR("%s: cc3_ctrl failed(%d)\n", __func__
, ret
);
275 case MCE_CMD_ECHO_DATA
:
276 ret64
= ops
->call_enum_misc(cpu_ari_base
, TEGRA_ARI_MISC_ECHO
,
279 /* update context to return if echo'd data matched source */
280 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X1
),
281 ((ret64
== arg0
) ? 1ULL : 0ULL));
282 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X2
),
283 ((ret64
== arg0
) ? 1ULL : 0ULL));
287 case MCE_CMD_READ_VERSIONS
:
288 ret64
= ops
->call_enum_misc(cpu_ari_base
, TEGRA_ARI_MISC_VERSION
,
292 * version = minor(63:32) | major(31:0). Update context
293 * to return major and minor version number.
295 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X1
),
297 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X2
),
302 case MCE_CMD_ENUM_FEATURES
:
303 ret64
= ops
->call_enum_misc(cpu_ari_base
,
304 TEGRA_ARI_MISC_FEATURE_LEAF_0
, arg0
);
306 /* update context to return features value */
307 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X1
), (ret64
));
311 case MCE_CMD_ROC_FLUSH_CACHE_TRBITS
:
312 ret
= ops
->roc_flush_cache_trbits(cpu_ari_base
);
314 ERROR("%s: flush cache_trbits failed(%d)\n", __func__
,
320 case MCE_CMD_ROC_FLUSH_CACHE
:
321 ret
= ops
->roc_flush_cache(cpu_ari_base
);
323 ERROR("%s: flush cache failed(%d)\n", __func__
, ret
);
328 case MCE_CMD_ROC_CLEAN_CACHE
:
329 ret
= ops
->roc_clean_cache(cpu_ari_base
);
331 ERROR("%s: clean cache failed(%d)\n", __func__
, ret
);
336 case MCE_CMD_ENUM_READ_MCA
:
337 ret64
= ops
->read_write_mca(cpu_ari_base
, arg0
, &arg1
);
339 /* update context to return MCA data/error */
340 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X1
), (ret64
));
341 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X2
), (arg1
));
342 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X3
), (ret64
));
346 case MCE_CMD_ENUM_WRITE_MCA
:
347 ret64
= ops
->read_write_mca(cpu_ari_base
, arg0
, &arg1
);
349 /* update context to return MCA error */
350 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X1
), (ret64
));
351 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X3
), (ret64
));
355 #if ENABLE_CHIP_VERIFICATION_HARNESS
356 case MCE_CMD_ENABLE_LATIC
:
358 * This call is not for production use. The constant value,
359 * 0xFFFF0000, is specific to allowing for enabling LATIC on
360 * pre-production parts for the chip verification harness.
362 * Enabling LATIC allows S/W to read the MINI ISPs in the
363 * CCPLEX. The ISMs are used for various measurements relevant
364 * to particular locations in the Silicon. They are small
365 * counters which can be polled to determine how fast a
366 * particular location in the Silicon is.
368 ops
->enter_ccplex_state(mce_get_curr_cpu_ari_base(),
374 case MCE_CMD_UNCORE_PERFMON_REQ
:
375 ret
= ops
->read_write_uncore_perfmon(cpu_ari_base
, arg0
, &arg1
);
377 /* update context to return data */
378 write_ctx_reg((gp_regs
), (uint32_t)(CTX_GPREG_X1
), (arg1
));
381 case MCE_CMD_MISC_CCPLEX
:
382 ops
->misc_ccplex(cpu_ari_base
, arg0
, arg1
);
387 ERROR("unknown MCE command (%llu)\n", cmd
);
395 /*******************************************************************************
396 * Handler to update the reset vector for CPUs
397 ******************************************************************************/
398 int32_t mce_update_reset_vector(void)
400 const arch_mce_ops_t
*ops
= mce_get_curr_cpu_ops();
402 ops
->update_reset_vector(mce_get_curr_cpu_ari_base());
407 static int32_t mce_update_ccplex_gsc(tegra_ari_gsc_index_t gsc_idx
)
409 const arch_mce_ops_t
*ops
= mce_get_curr_cpu_ops();
411 ops
->update_ccplex_gsc(mce_get_curr_cpu_ari_base(), gsc_idx
);
416 /*******************************************************************************
417 * Handler to update carveout values for Video Memory Carveout region
418 ******************************************************************************/
419 int32_t mce_update_gsc_videomem(void)
421 return mce_update_ccplex_gsc(TEGRA_ARI_GSC_VPR_IDX
);
424 /*******************************************************************************
425 * Handler to update carveout values for TZDRAM aperture
426 ******************************************************************************/
427 int32_t mce_update_gsc_tzdram(void)
429 return mce_update_ccplex_gsc(TEGRA_ARI_GSC_TZ_DRAM_IDX
);
432 /*******************************************************************************
433 * Handler to update carveout values for TZ SysRAM aperture
434 ******************************************************************************/
435 int32_t mce_update_gsc_tzram(void)
437 return mce_update_ccplex_gsc(TEGRA_ARI_GSC_TZRAM
);
440 /*******************************************************************************
441 * Handler to shutdown/reset the entire system
442 ******************************************************************************/
443 __dead2
void mce_enter_ccplex_state(uint32_t state_idx
)
445 const arch_mce_ops_t
*ops
= mce_get_curr_cpu_ops();
447 /* sanity check state value */
448 if ((state_idx
!= TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF
) &&
449 (state_idx
!= TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT
)) {
453 ops
->enter_ccplex_state(mce_get_curr_cpu_ari_base(), state_idx
);
455 /* wait till the CCPLEX powers down */
462 /*******************************************************************************
463 * Handler to issue the UPDATE_CSTATE_INFO request
464 ******************************************************************************/
465 void mce_update_cstate_info(const mce_cstate_info_t
*cstate
)
467 const arch_mce_ops_t
*ops
= mce_get_curr_cpu_ops();
469 /* issue the UPDATE_CSTATE_INFO request */
470 ops
->update_cstate_info(mce_get_curr_cpu_ari_base(), cstate
->cluster
,
471 cstate
->ccplex
, cstate
->system
, cstate
->system_state_force
,
472 cstate
->wake_mask
, cstate
->update_wake_mask
);
475 /*******************************************************************************
476 * Handler to read the MCE firmware version and check if it is compatible
477 * with interface header the BL3-1 was compiled against
478 ******************************************************************************/
479 void mce_verify_firmware_version(void)
481 const arch_mce_ops_t
*ops
;
482 uint32_t cpu_ari_base
;
484 uint32_t major
, minor
;
487 * MCE firmware is not supported on simulation platforms.
489 if (tegra_platform_is_emulation()) {
491 INFO("MCE firmware is not supported\n");
494 /* get a pointer to the CPU's arch_mce_ops_t struct */
495 ops
= mce_get_curr_cpu_ops();
497 /* get the CPU's ARI base address */
498 cpu_ari_base
= mce_get_curr_cpu_ari_base();
501 * Read the MCE firmware version and extract the major and minor
504 version
= ops
->call_enum_misc(cpu_ari_base
, TEGRA_ARI_MISC_VERSION
, 0);
505 major
= (uint32_t)version
;
506 minor
= (uint32_t)(version
>> 32);
508 INFO("MCE Version - HW=%d:%d, SW=%d:%d\n", major
, minor
,
509 TEGRA_ARI_VERSION_MAJOR
, TEGRA_ARI_VERSION_MINOR
);
512 * Verify that the MCE firmware version and the interface header
515 if (major
!= TEGRA_ARI_VERSION_MAJOR
) {
516 ERROR("ARI major version mismatch\n");
520 if (minor
< TEGRA_ARI_VERSION_MINOR
) {
521 ERROR("ARI minor version mismatch\n");