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