blob: 0489f79430cd913cc400f376a5b3837ca2d4c257 [file] [log] [blame]
Varun Wadekara0352ab2017-03-14 14:24:35 -07001/*
2 * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <arch.h>
32#include <arch_helpers.h>
33#include <assert.h>
34#include <bl_common.h>
35#include <context.h>
36#include <context_mgmt.h>
37#include <debug.h>
38#include <denver.h>
39#include <mce.h>
Varun Wadekarb5568282016-12-13 18:04:35 -080040#include <mce_private.h>
Varun Wadekara0352ab2017-03-14 14:24:35 -070041#include <mmio.h>
42#include <string.h>
43#include <sys/errno.h>
44#include <t18x_ari.h>
45#include <tegra_def.h>
Varun Wadekarefa66d42016-07-18 17:42:02 -070046#include <tegra_platform.h>
Varun Wadekara0352ab2017-03-14 14:24:35 -070047
48/* NVG functions handlers */
49static arch_mce_ops_t nvg_mce_ops = {
50 .enter_cstate = nvg_enter_cstate,
51 .update_cstate_info = nvg_update_cstate_info,
52 .update_crossover_time = nvg_update_crossover_time,
53 .read_cstate_stats = nvg_read_cstate_stats,
54 .write_cstate_stats = nvg_write_cstate_stats,
55 .call_enum_misc = ari_enumeration_misc,
56 .is_ccx_allowed = nvg_is_ccx_allowed,
57 .is_sc7_allowed = nvg_is_sc7_allowed,
58 .online_core = nvg_online_core,
59 .cc3_ctrl = nvg_cc3_ctrl,
60 .update_reset_vector = ari_reset_vector_update,
61 .roc_flush_cache = ari_roc_flush_cache,
62 .roc_flush_cache_trbits = ari_roc_flush_cache_trbits,
63 .roc_clean_cache = ari_roc_clean_cache,
64 .read_write_mca = ari_read_write_mca,
65 .update_ccplex_gsc = ari_update_ccplex_gsc,
Varun Wadekar4ff3e8d2016-04-29 10:40:02 -070066 .enter_ccplex_state = ari_enter_ccplex_state,
Krishna Sitaramanb429d562016-07-19 16:36:13 -070067 .read_write_uncore_perfmon = ari_read_write_uncore_perfmon,
68 .misc_ccplex = ari_misc_ccplex
Varun Wadekara0352ab2017-03-14 14:24:35 -070069};
70
71/* ARI functions handlers */
72static arch_mce_ops_t ari_mce_ops = {
73 .enter_cstate = ari_enter_cstate,
74 .update_cstate_info = ari_update_cstate_info,
75 .update_crossover_time = ari_update_crossover_time,
76 .read_cstate_stats = ari_read_cstate_stats,
77 .write_cstate_stats = ari_write_cstate_stats,
78 .call_enum_misc = ari_enumeration_misc,
79 .is_ccx_allowed = ari_is_ccx_allowed,
80 .is_sc7_allowed = ari_is_sc7_allowed,
81 .online_core = ari_online_core,
82 .cc3_ctrl = ari_cc3_ctrl,
83 .update_reset_vector = ari_reset_vector_update,
84 .roc_flush_cache = ari_roc_flush_cache,
85 .roc_flush_cache_trbits = ari_roc_flush_cache_trbits,
86 .roc_clean_cache = ari_roc_clean_cache,
87 .read_write_mca = ari_read_write_mca,
88 .update_ccplex_gsc = ari_update_ccplex_gsc,
Varun Wadekar4ff3e8d2016-04-29 10:40:02 -070089 .enter_ccplex_state = ari_enter_ccplex_state,
Krishna Sitaramanb429d562016-07-19 16:36:13 -070090 .read_write_uncore_perfmon = ari_read_write_uncore_perfmon,
91 .misc_ccplex = ari_misc_ccplex
Varun Wadekara0352ab2017-03-14 14:24:35 -070092};
93
94typedef struct mce_config {
95 uint32_t ari_base;
96 arch_mce_ops_t *ops;
97} mce_config_t;
98
99/* Table to hold the per-CPU ARI base address and function handlers */
100static mce_config_t mce_cfg_table[MCE_ARI_APERTURES_MAX] = {
101 {
102 /* A57 Core 0 */
103 .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_0_OFFSET,
104 .ops = &ari_mce_ops,
105 },
106 {
107 /* A57 Core 1 */
108 .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_1_OFFSET,
109 .ops = &ari_mce_ops,
110 },
111 {
112 /* A57 Core 2 */
113 .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_2_OFFSET,
114 .ops = &ari_mce_ops,
115 },
116 {
117 /* A57 Core 3 */
118 .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_3_OFFSET,
119 .ops = &ari_mce_ops,
120 },
121 {
122 /* D15 Core 0 */
123 .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_4_OFFSET,
124 .ops = &nvg_mce_ops,
125 },
126 {
127 /* D15 Core 1 */
128 .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_5_OFFSET,
129 .ops = &nvg_mce_ops,
130 }
131};
132
133static uint32_t mce_get_curr_cpu_ari_base(void)
134{
135 uint32_t mpidr = read_mpidr();
136 int cpuid = mpidr & MPIDR_CPU_MASK;
137 int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
138
139 /*
140 * T186 has 2 CPU clusters, one with Denver CPUs and the other with
141 * ARM CortexA-57 CPUs. Each cluster consists of 4 CPUs and the CPU
142 * numbers start from 0. In order to get the proper arch_mce_ops_t
143 * struct, we have to convert the Denver CPU ids to the corresponding
144 * indices in the mce_ops_table array.
145 */
146 if (impl == DENVER_IMPL)
147 cpuid |= 0x4;
148
149 return mce_cfg_table[cpuid].ari_base;
150}
151
152static arch_mce_ops_t *mce_get_curr_cpu_ops(void)
153{
154 uint32_t mpidr = read_mpidr();
155 int cpuid = mpidr & MPIDR_CPU_MASK;
156 int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
157
158 /*
159 * T186 has 2 CPU clusters, one with Denver CPUs and the other with
160 * ARM CortexA-57 CPUs. Each cluster consists of 4 CPUs and the CPU
161 * numbers start from 0. In order to get the proper arch_mce_ops_t
162 * struct, we have to convert the Denver CPU ids to the corresponding
163 * indices in the mce_ops_table array.
164 */
165 if (impl == DENVER_IMPL)
166 cpuid |= 0x4;
167
168 return mce_cfg_table[cpuid].ops;
169}
170
171/*******************************************************************************
172 * Common handler for all MCE commands
173 ******************************************************************************/
174int mce_command_handler(mce_cmd_t cmd, uint64_t arg0, uint64_t arg1,
175 uint64_t arg2)
176{
177 arch_mce_ops_t *ops;
178 uint32_t cpu_ari_base;
179 uint64_t ret64 = 0, arg3, arg4, arg5;
180 int ret = 0;
181 mca_cmd_t mca_cmd;
Varun Wadekar4ff3e8d2016-04-29 10:40:02 -0700182 uncore_perfmon_req_t req;
Varun Wadekara0352ab2017-03-14 14:24:35 -0700183 cpu_context_t *ctx = cm_get_context(NON_SECURE);
184 gp_regs_t *gp_regs = get_gpregs_ctx(ctx);
185
186 assert(ctx);
187 assert(gp_regs);
188
189 /* get a pointer to the CPU's arch_mce_ops_t struct */
190 ops = mce_get_curr_cpu_ops();
191
192 /* get the CPU's ARI base address */
193 cpu_ari_base = mce_get_curr_cpu_ari_base();
194
195 switch (cmd) {
196 case MCE_CMD_ENTER_CSTATE:
197 ret = ops->enter_cstate(cpu_ari_base, arg0, arg1);
198 if (ret < 0)
199 ERROR("%s: enter_cstate failed(%d)\n", __func__, ret);
200
201 break;
202
203 case MCE_CMD_UPDATE_CSTATE_INFO:
204 /*
205 * get the parameters required for the update cstate info
206 * command
207 */
208 arg3 = read_ctx_reg(gp_regs, CTX_GPREG_X4);
209 arg4 = read_ctx_reg(gp_regs, CTX_GPREG_X5);
210 arg5 = read_ctx_reg(gp_regs, CTX_GPREG_X6);
211
212 ret = ops->update_cstate_info(cpu_ari_base, (uint32_t)arg0,
213 (uint32_t)arg1, (uint32_t)arg2, (uint8_t)arg3,
214 (uint32_t)arg4, (uint8_t)arg5);
215 if (ret < 0)
216 ERROR("%s: update_cstate_info failed(%d)\n",
217 __func__, ret);
218
219 write_ctx_reg(gp_regs, CTX_GPREG_X4, 0);
220 write_ctx_reg(gp_regs, CTX_GPREG_X5, 0);
221 write_ctx_reg(gp_regs, CTX_GPREG_X6, 0);
222
223 break;
224
225 case MCE_CMD_UPDATE_CROSSOVER_TIME:
226 ret = ops->update_crossover_time(cpu_ari_base, arg0, arg1);
227 if (ret < 0)
228 ERROR("%s: update_crossover_time failed(%d)\n",
229 __func__, ret);
230
231 break;
232
233 case MCE_CMD_READ_CSTATE_STATS:
234 ret64 = ops->read_cstate_stats(cpu_ari_base, arg0);
235
236 /* update context to return cstate stats value */
237 write_ctx_reg(gp_regs, CTX_GPREG_X1, ret64);
238 write_ctx_reg(gp_regs, CTX_GPREG_X2, ret64);
239
240 break;
241
242 case MCE_CMD_WRITE_CSTATE_STATS:
243 ret = ops->write_cstate_stats(cpu_ari_base, arg0, arg1);
244 if (ret < 0)
245 ERROR("%s: write_cstate_stats failed(%d)\n",
246 __func__, ret);
247
248 break;
249
250 case MCE_CMD_IS_CCX_ALLOWED:
251 ret = ops->is_ccx_allowed(cpu_ari_base, arg0, arg1);
252 if (ret < 0) {
253 ERROR("%s: is_ccx_allowed failed(%d)\n", __func__, ret);
254 break;
255 }
256
257 /* update context to return CCx status value */
258 write_ctx_reg(gp_regs, CTX_GPREG_X1, ret);
259
260 break;
261
262 case MCE_CMD_IS_SC7_ALLOWED:
263 ret = ops->is_sc7_allowed(cpu_ari_base, arg0, arg1);
264 if (ret < 0) {
265 ERROR("%s: is_sc7_allowed failed(%d)\n", __func__, ret);
266 break;
267 }
268
269 /* update context to return SC7 status value */
270 write_ctx_reg(gp_regs, CTX_GPREG_X1, ret);
271 write_ctx_reg(gp_regs, CTX_GPREG_X3, ret);
Varun Wadekara0352ab2017-03-14 14:24:35 -0700272
273 break;
274
275 case MCE_CMD_ONLINE_CORE:
276 ret = ops->online_core(cpu_ari_base, arg0);
277 if (ret < 0)
278 ERROR("%s: online_core failed(%d)\n", __func__, ret);
279
280 break;
281
282 case MCE_CMD_CC3_CTRL:
283 ret = ops->cc3_ctrl(cpu_ari_base, arg0, arg1, arg2);
284 if (ret < 0)
285 ERROR("%s: cc3_ctrl failed(%d)\n", __func__, ret);
286
287 break;
288
289 case MCE_CMD_ECHO_DATA:
290 ret64 = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_ECHO,
291 arg0);
292
293 /* update context to return if echo'd data matched source */
294 write_ctx_reg(gp_regs, CTX_GPREG_X1, ret64 == arg0);
295 write_ctx_reg(gp_regs, CTX_GPREG_X2, ret64 == arg0);
296
297 break;
298
299 case MCE_CMD_READ_VERSIONS:
300 ret64 = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_VERSION,
301 arg0);
302
303 /*
304 * version = minor(63:32) | major(31:0). Update context
305 * to return major and minor version number.
306 */
307 write_ctx_reg(gp_regs, CTX_GPREG_X1, (uint32_t)ret64);
308 write_ctx_reg(gp_regs, CTX_GPREG_X2, (uint32_t)(ret64 >> 32));
309
310 break;
311
312 case MCE_CMD_ENUM_FEATURES:
Krishna Sitaramanfc2ec162016-07-27 16:26:45 -0700313 ret64 = ops->call_enum_misc(cpu_ari_base,
Varun Wadekara0352ab2017-03-14 14:24:35 -0700314 TEGRA_ARI_MISC_FEATURE_LEAF_0, arg0);
315
316 /* update context to return features value */
317 write_ctx_reg(gp_regs, CTX_GPREG_X1, ret64);
318
Varun Wadekara0352ab2017-03-14 14:24:35 -0700319 break;
320
321 case MCE_CMD_ROC_FLUSH_CACHE_TRBITS:
322 ret = ops->roc_flush_cache_trbits(cpu_ari_base);
323 if (ret < 0)
324 ERROR("%s: flush cache_trbits failed(%d)\n", __func__,
325 ret);
326
327 break;
328
329 case MCE_CMD_ROC_FLUSH_CACHE:
330 ret = ops->roc_flush_cache(cpu_ari_base);
331 if (ret < 0)
332 ERROR("%s: flush cache failed(%d)\n", __func__, ret);
333
334 break;
335
336 case MCE_CMD_ROC_CLEAN_CACHE:
337 ret = ops->roc_clean_cache(cpu_ari_base);
338 if (ret < 0)
339 ERROR("%s: clean cache failed(%d)\n", __func__, ret);
340
341 break;
342
343 case MCE_CMD_ENUM_READ_MCA:
344 memcpy(&mca_cmd, &arg0, sizeof(arg0));
345 ret64 = ops->read_write_mca(cpu_ari_base, mca_cmd, &arg1);
346
347 /* update context to return MCA data/error */
348 write_ctx_reg(gp_regs, CTX_GPREG_X1, ret64);
349 write_ctx_reg(gp_regs, CTX_GPREG_X2, arg1);
350 write_ctx_reg(gp_regs, CTX_GPREG_X3, ret64);
351
352 break;
353
354 case MCE_CMD_ENUM_WRITE_MCA:
355 memcpy(&mca_cmd, &arg0, sizeof(arg0));
356 ret64 = ops->read_write_mca(cpu_ari_base, mca_cmd, &arg1);
357
358 /* update context to return MCA error */
359 write_ctx_reg(gp_regs, CTX_GPREG_X1, ret64);
360 write_ctx_reg(gp_regs, CTX_GPREG_X3, ret64);
361
362 break;
363
Varun Wadekarad2824f2016-03-28 13:44:35 -0700364#if ENABLE_CHIP_VERIFICATION_HARNESS
365 case MCE_CMD_ENABLE_LATIC:
366 /*
367 * This call is not for production use. The constant value,
368 * 0xFFFF0000, is specific to allowing for enabling LATIC on
369 * pre-production parts for the chip verification harness.
370 *
371 * Enabling LATIC allows S/W to read the MINI ISPs in the
372 * CCPLEX. The ISMs are used for various measurements relevant
373 * to particular locations in the Silicon. They are small
374 * counters which can be polled to determine how fast a
375 * particular location in the Silicon is.
376 */
377 ops->enter_ccplex_state(mce_get_curr_cpu_ari_base(),
378 0xFFFF0000);
379
380 break;
381#endif
Varun Wadekar4ff3e8d2016-04-29 10:40:02 -0700382
383 case MCE_CMD_UNCORE_PERFMON_REQ:
384 memcpy(&req, &arg0, sizeof(arg0));
385 ret = ops->read_write_uncore_perfmon(cpu_ari_base, req, &arg1);
386
387 /* update context to return data */
388 write_ctx_reg(gp_regs, CTX_GPREG_X1, arg1);
389 break;
390
Krishna Sitaramanb429d562016-07-19 16:36:13 -0700391 case MCE_CMD_MISC_CCPLEX:
392 ops->misc_ccplex(cpu_ari_base, arg0, arg1);
393
394 break;
395
Varun Wadekara0352ab2017-03-14 14:24:35 -0700396 default:
397 ERROR("unknown MCE command (%d)\n", cmd);
398 return EINVAL;
399 }
400
401 return ret;
402}
403
404/*******************************************************************************
405 * Handler to update the reset vector for CPUs
406 ******************************************************************************/
Krishna Sitaramand007f762016-09-02 16:53:04 -0700407int mce_update_reset_vector(void)
Varun Wadekara0352ab2017-03-14 14:24:35 -0700408{
409 arch_mce_ops_t *ops = mce_get_curr_cpu_ops();
410
Krishna Sitaramand007f762016-09-02 16:53:04 -0700411 ops->update_reset_vector(mce_get_curr_cpu_ari_base());
Varun Wadekara0352ab2017-03-14 14:24:35 -0700412
413 return 0;
414}
415
416static int mce_update_ccplex_gsc(tegra_ari_gsc_index_t gsc_idx)
417{
418 arch_mce_ops_t *ops = mce_get_curr_cpu_ops();
419
420 ops->update_ccplex_gsc(mce_get_curr_cpu_ari_base(), gsc_idx);
421
422 return 0;
423}
424
425/*******************************************************************************
426 * Handler to update carveout values for Video Memory Carveout region
427 ******************************************************************************/
428int mce_update_gsc_videomem(void)
429{
430 return mce_update_ccplex_gsc(TEGRA_ARI_GSC_VPR_IDX);
431}
432
433/*******************************************************************************
434 * Handler to update carveout values for TZDRAM aperture
435 ******************************************************************************/
436int mce_update_gsc_tzdram(void)
437{
438 return mce_update_ccplex_gsc(TEGRA_ARI_GSC_TZ_DRAM_IDX);
439}
440
441/*******************************************************************************
442 * Handler to update carveout values for TZ SysRAM aperture
443 ******************************************************************************/
444int mce_update_gsc_tzram(void)
445{
446 return mce_update_ccplex_gsc(TEGRA_ARI_GSC_TZRAM);
447}
448
449/*******************************************************************************
450 * Handler to shutdown/reset the entire system
451 ******************************************************************************/
452__dead2 void mce_enter_ccplex_state(uint32_t state_idx)
453{
454 arch_mce_ops_t *ops = mce_get_curr_cpu_ops();
455
456 /* sanity check state value */
457 if (state_idx != TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF &&
458 state_idx != TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT)
459 panic();
460
461 ops->enter_ccplex_state(mce_get_curr_cpu_ari_base(), state_idx);
462
463 /* wait till the CCPLEX powers down */
464 for (;;)
465 ;
466
467 panic();
468}
Varun Wadekar47ddd002016-03-28 16:00:02 -0700469
470/*******************************************************************************
Varun Wadekarc47504f2017-03-23 17:32:20 -0700471 * Handler to issue the UPDATE_CSTATE_INFO request
472 ******************************************************************************/
473void mce_update_cstate_info(mce_cstate_info_t *cstate)
474{
475 arch_mce_ops_t *ops = mce_get_curr_cpu_ops();
476
477 /* issue the UPDATE_CSTATE_INFO request */
478 ops->update_cstate_info(mce_get_curr_cpu_ari_base(), cstate->cluster,
479 cstate->ccplex, cstate->system, cstate->system_state_force,
480 cstate->wake_mask, cstate->update_wake_mask);
481}
482
483/*******************************************************************************
Varun Wadekar47ddd002016-03-28 16:00:02 -0700484 * Handler to read the MCE firmware version and check if it is compatible
485 * with interface header the BL3-1 was compiled against
486 ******************************************************************************/
487void mce_verify_firmware_version(void)
488{
489 arch_mce_ops_t *ops;
490 uint32_t cpu_ari_base;
491 uint64_t version;
Varun Wadekarefa66d42016-07-18 17:42:02 -0700492 uint32_t major, minor;
493
494 /*
Varun Wadekarb5568282016-12-13 18:04:35 -0800495 * MCE firmware is not supported on simulation platforms.
Varun Wadekarefa66d42016-07-18 17:42:02 -0700496 */
497 if (tegra_platform_is_emulation())
498 return;
Varun Wadekar47ddd002016-03-28 16:00:02 -0700499
500 /* get a pointer to the CPU's arch_mce_ops_t struct */
501 ops = mce_get_curr_cpu_ops();
502
503 /* get the CPU's ARI base address */
504 cpu_ari_base = mce_get_curr_cpu_ari_base();
505
506 /*
507 * Read the MCE firmware version and extract the major and minor
508 * version fields
509 */
510 version = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_VERSION, 0);
511 major = (uint32_t)version;
512 minor = (uint32_t)(version >> 32);
513
514 INFO("MCE Version - HW=%d:%d, SW=%d:%d\n", major, minor,
515 TEGRA_ARI_VERSION_MAJOR, TEGRA_ARI_VERSION_MINOR);
516
517 /*
518 * Verify that the MCE firmware version and the interface header
519 * match
520 */
521 if (major != TEGRA_ARI_VERSION_MAJOR) {
522 ERROR("ARI major version mismatch\n");
523 panic();
524 }
525
526 if (minor < TEGRA_ARI_VERSION_MINOR) {
527 ERROR("ARI minor version mismatch\n");
528 panic();
529 }
530}