1251877Speter/* 2251877Speter * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3251877Speter * 4251877Speter * SPDX-License-Identifier: GPL-2.0-only 5251877Speter */ 6251877Speter 7251877Speter#include <autoconf.h> 8251877Speter#include <elfloader.h> 9251877Speter#include <printf.h> 10251877Speter 11251877Speter/* The code for enabling SError is from L4T (Linux for Tegra). 12251877Speter * Read the Parker TRM 17.12 and 17.13 for NVIDIA-specific 13251877Speter * SError extensions and the ARI (abstract request interface). 14251877Speter */ 15251877Speter 16251877Speter 17251877Speter#define SMC_SIP_INVOKE_MCE 0xc2ffff00 18251877Speter#define MCE_SMC_ENUM_MAX 0xff 19251877Speter#define ARI_MCA_GLOBAL_CONFIG 0x12 20251877Speter#define ARI_MCA_WRITE_SERR 0x2 21251877Speter#define NR_SMC_REGS 6 22251877Speter 23251877Spetertypedef union { 24251877Speter struct { 25251877Speter uint8_t cmd; 26262339Speter uint8_t subidx; 27262339Speter uint8_t idx; 28262339Speter uint8_t inst; 29251877Speter }; 30251877Speter struct { 31253895Speter uint32_t low; 32253895Speter uint32_t high; 33253895Speter }; 34253895Speter uint64_t data; 35253895Speter} mca_cmd_t; 36253895Speter 37253895Speterstruct mce_regs { 38251877Speter uint64_t args[NR_SMC_REGS]; 39251877Speter}; 40251877Speter 41251877Speterstatic __attribute__((noinline)) int send_smc(uint8_t func, struct mce_regs *regs) 42251877Speter{ 43251877Speter uint32_t ret = SMC_SIP_INVOKE_MCE | (func & MCE_SMC_ENUM_MAX); 44251877Speter asm volatile( 45251877Speter "mov x0, %x0\n" 46251877Speter "ldp x1, x2, [%1, #16 * 0] \n" 47251877Speter "ldp x3, x4, [%1, #16 * 1] \n" 48251877Speter "ldp x5, x6, [%1, #16 * 2] \n" 49251877Speter "isb\n" 50251877Speter "smc #0\n" 51253895Speter "mov %x0, x0\n" 52253895Speter "stp x0, x1, [%1, #16 * 0]\n" 53251877Speter "stp x2, x3, [%1, #16 * 1]\n" 54253895Speter : "+r"(ret) 55253895Speter : "r"(regs) 56253895Speter : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", 57253895Speter "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17"); 58253895Speter return ret; 59253895Speter} 60253895Speter 61253895Speter 62253895Speterstatic void tegra_mce_write_uncore_mca(mca_cmd_t cmd, uint64_t data, uint32_t *err) 63253895Speter{ 64251877Speter struct mce_regs regs; 65251877Speter regs.args[0] = cmd.data; 66251877Speter regs.args[1] = data; 67251877Speter send_smc(13, ®s); 68251877Speter *err = (uint32_t)regs.args[3]; 69251877Speter} 70251877Speter 71251877Speterstatic void enable_serr(void) 72251877Speter{ 73251877Speter uint32_t err; 74251877Speter mca_cmd_t cmd; 75251877Speter cmd.data = 0; 76251877Speter cmd.cmd = ARI_MCA_WRITE_SERR; 77251877Speter cmd.idx = ARI_MCA_GLOBAL_CONFIG; 78251877Speter tegra_mce_write_uncore_mca(cmd, 1, &err); 79251877Speter printf("Enabling TX2 SError result %d\n", err); 80251877Speter} 81251877Speter 82251877Speter/* Enable SError report for TX2 */ 83251877Spetervoid platform_init(void) 84251877Speter{ 85251877Speter enable_serr(); 86251877Speter} 87251877Speter 88251877Speter