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