1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <inttypes.h> 8*91f16700Schasinglulu #include <stdbool.h> 9*91f16700Schasinglulu #include <stdint.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <common/debug.h> 12*91f16700Schasinglulu #include <lib/bakery_lock.h> 13*91f16700Schasinglulu #include <lib/cassert.h> 14*91f16700Schasinglulu #include <lib/extensions/ras.h> 15*91f16700Schasinglulu #include <lib/utils_def.h> 16*91f16700Schasinglulu #include <services/sdei.h> 17*91f16700Schasinglulu 18*91f16700Schasinglulu #include <plat/common/platform.h> 19*91f16700Schasinglulu #include <platform_def.h> 20*91f16700Schasinglulu #include <tegra194_ras_private.h> 21*91f16700Schasinglulu #include <tegra_def.h> 22*91f16700Schasinglulu #include <tegra_platform.h> 23*91f16700Schasinglulu #include <tegra_private.h> 24*91f16700Schasinglulu 25*91f16700Schasinglulu /* 26*91f16700Schasinglulu * ERR<n>FR bits[63:32], it indicates supported RAS errors which can be enabled 27*91f16700Schasinglulu * by setting corresponding bits in ERR<n>CTLR 28*91f16700Schasinglulu */ 29*91f16700Schasinglulu #define ERR_FR_EN_BITS_MASK 0xFFFFFFFF00000000ULL 30*91f16700Schasinglulu 31*91f16700Schasinglulu /* 32*91f16700Schasinglulu * Number of RAS errors will be cleared per 'tegra194_ras_corrected_err_clear' 33*91f16700Schasinglulu * function call. 34*91f16700Schasinglulu */ 35*91f16700Schasinglulu #define RAS_ERRORS_PER_CALL 8 36*91f16700Schasinglulu 37*91f16700Schasinglulu /* 38*91f16700Schasinglulu * the max possible RAS node index value. 39*91f16700Schasinglulu */ 40*91f16700Schasinglulu #define RAS_NODE_INDEX_MAX 0x1FFFFFFFU 41*91f16700Schasinglulu 42*91f16700Schasinglulu /* bakery lock for platform RAS handler. */ 43*91f16700Schasinglulu static DEFINE_BAKERY_LOCK(ras_handler_lock); 44*91f16700Schasinglulu #define ras_lock() bakery_lock_get(&ras_handler_lock) 45*91f16700Schasinglulu #define ras_unlock() bakery_lock_release(&ras_handler_lock) 46*91f16700Schasinglulu 47*91f16700Schasinglulu /* 48*91f16700Schasinglulu * Function to handle an External Abort received at EL3. 49*91f16700Schasinglulu * This function is invoked by RAS framework. 50*91f16700Schasinglulu */ 51*91f16700Schasinglulu static void tegra194_ea_handler(unsigned int ea_reason, uint64_t syndrome, 52*91f16700Schasinglulu void *cookie, void *handle, uint64_t flags) 53*91f16700Schasinglulu { 54*91f16700Schasinglulu int32_t ret; 55*91f16700Schasinglulu 56*91f16700Schasinglulu ras_lock(); 57*91f16700Schasinglulu 58*91f16700Schasinglulu ERROR("MPIDR 0x%lx: exception reason=%u syndrome=0x%" PRIx64 "\n", 59*91f16700Schasinglulu read_mpidr(), ea_reason, syndrome); 60*91f16700Schasinglulu 61*91f16700Schasinglulu /* Call RAS EA handler */ 62*91f16700Schasinglulu ret = ras_ea_handler(ea_reason, syndrome, cookie, handle, flags); 63*91f16700Schasinglulu if (ret != 0) { 64*91f16700Schasinglulu ERROR("RAS error handled!\n"); 65*91f16700Schasinglulu ret = sdei_dispatch_event(TEGRA_SDEI_EP_EVENT_0 + 66*91f16700Schasinglulu plat_my_core_pos()); 67*91f16700Schasinglulu if (ret != 0) 68*91f16700Schasinglulu ERROR("sdei_dispatch_event returned %d\n", ret); 69*91f16700Schasinglulu } else { 70*91f16700Schasinglulu ERROR("Not a RAS error!\n"); 71*91f16700Schasinglulu } 72*91f16700Schasinglulu 73*91f16700Schasinglulu ras_unlock(); 74*91f16700Schasinglulu } 75*91f16700Schasinglulu 76*91f16700Schasinglulu /* 77*91f16700Schasinglulu * Function to enable all supported RAS error report. 78*91f16700Schasinglulu * 79*91f16700Schasinglulu * Uncorrected errors are set to report as External abort (SError) 80*91f16700Schasinglulu * Corrected errors are set to report as interrupt. 81*91f16700Schasinglulu */ 82*91f16700Schasinglulu void tegra194_ras_enable(void) 83*91f16700Schasinglulu { 84*91f16700Schasinglulu VERBOSE("%s\n", __func__); 85*91f16700Schasinglulu 86*91f16700Schasinglulu /* skip RAS enablement if not a silicon platform. */ 87*91f16700Schasinglulu if (!tegra_platform_is_silicon()) { 88*91f16700Schasinglulu return; 89*91f16700Schasinglulu } 90*91f16700Schasinglulu 91*91f16700Schasinglulu /* 92*91f16700Schasinglulu * Iterate for each group(num_idx ERRSELRs starting from idx_start) 93*91f16700Schasinglulu * use normal for loop instead of for_each_err_record_info to get rid 94*91f16700Schasinglulu * of MISRA noise.. 95*91f16700Schasinglulu */ 96*91f16700Schasinglulu for (uint32_t i = 0U; i < err_record_mappings.num_err_records; i++) { 97*91f16700Schasinglulu 98*91f16700Schasinglulu const struct err_record_info *info = &err_record_mappings.err_records[i]; 99*91f16700Schasinglulu 100*91f16700Schasinglulu uint32_t idx_start = info->sysreg.idx_start; 101*91f16700Schasinglulu uint32_t num_idx = info->sysreg.num_idx; 102*91f16700Schasinglulu const struct ras_aux_data *aux_data = (const struct ras_aux_data *)info->aux_data; 103*91f16700Schasinglulu 104*91f16700Schasinglulu assert(aux_data != NULL); 105*91f16700Schasinglulu 106*91f16700Schasinglulu for (uint32_t j = 0; j < num_idx; j++) { 107*91f16700Schasinglulu 108*91f16700Schasinglulu /* ERR<n>CTLR register value. */ 109*91f16700Schasinglulu uint64_t err_ctrl = 0ULL; 110*91f16700Schasinglulu /* all supported errors for this node. */ 111*91f16700Schasinglulu uint64_t err_fr; 112*91f16700Schasinglulu /* uncorrectable errors */ 113*91f16700Schasinglulu uint64_t uncorr_errs; 114*91f16700Schasinglulu /* correctable errors */ 115*91f16700Schasinglulu uint64_t corr_errs; 116*91f16700Schasinglulu 117*91f16700Schasinglulu /* 118*91f16700Schasinglulu * Catch error if something wrong with the RAS aux data 119*91f16700Schasinglulu * record table. 120*91f16700Schasinglulu */ 121*91f16700Schasinglulu assert(aux_data[j].err_ctrl != NULL); 122*91f16700Schasinglulu 123*91f16700Schasinglulu /* 124*91f16700Schasinglulu * Write to ERRSELR_EL1 to select the RAS error node. 125*91f16700Schasinglulu * Always program this at first to select corresponding 126*91f16700Schasinglulu * RAS node before any other RAS register r/w. 127*91f16700Schasinglulu */ 128*91f16700Schasinglulu ser_sys_select_record(idx_start + j); 129*91f16700Schasinglulu 130*91f16700Schasinglulu err_fr = read_erxfr_el1() & ERR_FR_EN_BITS_MASK; 131*91f16700Schasinglulu uncorr_errs = aux_data[j].err_ctrl(); 132*91f16700Schasinglulu corr_errs = ~uncorr_errs & err_fr; 133*91f16700Schasinglulu 134*91f16700Schasinglulu /* enable error reporting */ 135*91f16700Schasinglulu ERR_CTLR_ENABLE_FIELD(err_ctrl, ED); 136*91f16700Schasinglulu 137*91f16700Schasinglulu /* enable SError reporting for uncorrectable errors */ 138*91f16700Schasinglulu if ((uncorr_errs & err_fr) != 0ULL) { 139*91f16700Schasinglulu ERR_CTLR_ENABLE_FIELD(err_ctrl, UE); 140*91f16700Schasinglulu } 141*91f16700Schasinglulu 142*91f16700Schasinglulu /* generate interrupt for corrected errors. */ 143*91f16700Schasinglulu if (corr_errs != 0ULL) { 144*91f16700Schasinglulu ERR_CTLR_ENABLE_FIELD(err_ctrl, CFI); 145*91f16700Schasinglulu } 146*91f16700Schasinglulu 147*91f16700Schasinglulu /* enable the supported errors */ 148*91f16700Schasinglulu err_ctrl |= err_fr; 149*91f16700Schasinglulu 150*91f16700Schasinglulu VERBOSE("errselr_el1:0x%x, erxfr:0x%" PRIx64 ", err_ctrl:0x%" PRIx64 "\n", 151*91f16700Schasinglulu idx_start + j, err_fr, err_ctrl); 152*91f16700Schasinglulu 153*91f16700Schasinglulu /* enable specified errors, or set to 0 if no supported error */ 154*91f16700Schasinglulu write_erxctlr_el1(err_ctrl); 155*91f16700Schasinglulu } 156*91f16700Schasinglulu } 157*91f16700Schasinglulu } 158*91f16700Schasinglulu 159*91f16700Schasinglulu /* 160*91f16700Schasinglulu * Function to clear RAS ERR<n>STATUS for corrected RAS error. 161*91f16700Schasinglulu * 162*91f16700Schasinglulu * This function clears number of 'RAS_ERRORS_PER_CALL' RAS errors at most. 163*91f16700Schasinglulu * 'cookie' - in/out cookie parameter to specify/store last visited RAS 164*91f16700Schasinglulu * error record index. it is set to '0' to indicate no more RAS 165*91f16700Schasinglulu * error record to clear. 166*91f16700Schasinglulu */ 167*91f16700Schasinglulu void tegra194_ras_corrected_err_clear(uint64_t *cookie) 168*91f16700Schasinglulu { 169*91f16700Schasinglulu /* 170*91f16700Schasinglulu * 'last_node' and 'last_idx' represent last visited RAS node index from 171*91f16700Schasinglulu * previous function call. they are set to 0 when first smc call is made 172*91f16700Schasinglulu * or all RAS error are visited by followed multipile smc calls. 173*91f16700Schasinglulu */ 174*91f16700Schasinglulu union prev_record { 175*91f16700Schasinglulu struct record { 176*91f16700Schasinglulu uint32_t last_node; 177*91f16700Schasinglulu uint32_t last_idx; 178*91f16700Schasinglulu } rec; 179*91f16700Schasinglulu uint64_t value; 180*91f16700Schasinglulu } prev; 181*91f16700Schasinglulu 182*91f16700Schasinglulu uint64_t clear_ce_status = 0ULL; 183*91f16700Schasinglulu int32_t nerrs_per_call = RAS_ERRORS_PER_CALL; 184*91f16700Schasinglulu uint32_t i; 185*91f16700Schasinglulu 186*91f16700Schasinglulu if (cookie == NULL) { 187*91f16700Schasinglulu return; 188*91f16700Schasinglulu } 189*91f16700Schasinglulu 190*91f16700Schasinglulu prev.value = *cookie; 191*91f16700Schasinglulu 192*91f16700Schasinglulu if ((prev.rec.last_node >= RAS_NODE_INDEX_MAX) || 193*91f16700Schasinglulu (prev.rec.last_idx >= RAS_NODE_INDEX_MAX)) { 194*91f16700Schasinglulu return; 195*91f16700Schasinglulu } 196*91f16700Schasinglulu 197*91f16700Schasinglulu ERR_STATUS_SET_FIELD(clear_ce_status, AV, 0x1UL); 198*91f16700Schasinglulu ERR_STATUS_SET_FIELD(clear_ce_status, V, 0x1UL); 199*91f16700Schasinglulu ERR_STATUS_SET_FIELD(clear_ce_status, OF, 0x1UL); 200*91f16700Schasinglulu ERR_STATUS_SET_FIELD(clear_ce_status, MV, 0x1UL); 201*91f16700Schasinglulu ERR_STATUS_SET_FIELD(clear_ce_status, CE, 0x3UL); 202*91f16700Schasinglulu 203*91f16700Schasinglulu 204*91f16700Schasinglulu for (i = prev.rec.last_node; i < err_record_mappings.num_err_records; i++) { 205*91f16700Schasinglulu 206*91f16700Schasinglulu const struct err_record_info *info = &err_record_mappings.err_records[i]; 207*91f16700Schasinglulu uint32_t idx_start = info->sysreg.idx_start; 208*91f16700Schasinglulu uint32_t num_idx = info->sysreg.num_idx; 209*91f16700Schasinglulu 210*91f16700Schasinglulu uint32_t j; 211*91f16700Schasinglulu 212*91f16700Schasinglulu j = (i == prev.rec.last_node && prev.value != 0UL) ? 213*91f16700Schasinglulu (prev.rec.last_idx + 1U) : 0U; 214*91f16700Schasinglulu 215*91f16700Schasinglulu for (; j < num_idx; j++) { 216*91f16700Schasinglulu 217*91f16700Schasinglulu uint64_t status; 218*91f16700Schasinglulu uint32_t err_idx = idx_start + j; 219*91f16700Schasinglulu 220*91f16700Schasinglulu if (err_idx >= RAS_NODE_INDEX_MAX) { 221*91f16700Schasinglulu return; 222*91f16700Schasinglulu } 223*91f16700Schasinglulu 224*91f16700Schasinglulu write_errselr_el1(err_idx); 225*91f16700Schasinglulu status = read_erxstatus_el1(); 226*91f16700Schasinglulu 227*91f16700Schasinglulu if (ERR_STATUS_GET_FIELD(status, CE) != 0U) { 228*91f16700Schasinglulu write_erxstatus_el1(clear_ce_status); 229*91f16700Schasinglulu } 230*91f16700Schasinglulu 231*91f16700Schasinglulu --nerrs_per_call; 232*91f16700Schasinglulu 233*91f16700Schasinglulu /* only clear 'nerrs_per_call' errors each time. */ 234*91f16700Schasinglulu if (nerrs_per_call <= 0) { 235*91f16700Schasinglulu prev.rec.last_idx = j; 236*91f16700Schasinglulu prev.rec.last_node = i; 237*91f16700Schasinglulu /* save last visited error record index 238*91f16700Schasinglulu * into cookie. 239*91f16700Schasinglulu */ 240*91f16700Schasinglulu *cookie = prev.value; 241*91f16700Schasinglulu 242*91f16700Schasinglulu return; 243*91f16700Schasinglulu } 244*91f16700Schasinglulu } 245*91f16700Schasinglulu } 246*91f16700Schasinglulu 247*91f16700Schasinglulu /* 248*91f16700Schasinglulu * finish if all ras error records are checked or provided index is out 249*91f16700Schasinglulu * of range. 250*91f16700Schasinglulu */ 251*91f16700Schasinglulu *cookie = 0ULL; 252*91f16700Schasinglulu } 253*91f16700Schasinglulu 254*91f16700Schasinglulu /* Function to probe an error from error record group. */ 255*91f16700Schasinglulu static int32_t tegra194_ras_record_probe(const struct err_record_info *info, 256*91f16700Schasinglulu int *probe_data) 257*91f16700Schasinglulu { 258*91f16700Schasinglulu /* Skip probing if not a silicon platform */ 259*91f16700Schasinglulu if (!tegra_platform_is_silicon()) { 260*91f16700Schasinglulu return 0; 261*91f16700Schasinglulu } 262*91f16700Schasinglulu 263*91f16700Schasinglulu return ser_probe_sysreg(info->sysreg.idx_start, info->sysreg.num_idx, probe_data); 264*91f16700Schasinglulu } 265*91f16700Schasinglulu 266*91f16700Schasinglulu /* Function to handle error from one given node */ 267*91f16700Schasinglulu static int32_t tegra194_ras_node_handler(uint32_t errselr, const char *name, 268*91f16700Schasinglulu const struct ras_error *errors, uint64_t status) 269*91f16700Schasinglulu { 270*91f16700Schasinglulu bool found = false; 271*91f16700Schasinglulu uint32_t ierr = (uint32_t)ERR_STATUS_GET_FIELD(status, IERR); 272*91f16700Schasinglulu uint32_t serr = (uint32_t)ERR_STATUS_GET_FIELD(status, SERR); 273*91f16700Schasinglulu uint64_t val = 0; 274*91f16700Schasinglulu 275*91f16700Schasinglulu /* not a valid error. */ 276*91f16700Schasinglulu if (ERR_STATUS_GET_FIELD(status, V) == 0U) { 277*91f16700Schasinglulu return 0; 278*91f16700Schasinglulu } 279*91f16700Schasinglulu 280*91f16700Schasinglulu ERR_STATUS_SET_FIELD(val, V, 1); 281*91f16700Schasinglulu 282*91f16700Schasinglulu /* keep the log print same as linux arm64_ras driver. */ 283*91f16700Schasinglulu ERROR("**************************************\n"); 284*91f16700Schasinglulu ERROR("RAS Error in %s, ERRSELR_EL1=0x%x:\n", name, errselr); 285*91f16700Schasinglulu ERROR("\tStatus = 0x%" PRIx64 "\n", status); 286*91f16700Schasinglulu 287*91f16700Schasinglulu /* Print uncorrectable error information. */ 288*91f16700Schasinglulu if (ERR_STATUS_GET_FIELD(status, UE) != 0U) { 289*91f16700Schasinglulu 290*91f16700Schasinglulu ERR_STATUS_SET_FIELD(val, UE, 1); 291*91f16700Schasinglulu ERR_STATUS_SET_FIELD(val, UET, 1); 292*91f16700Schasinglulu 293*91f16700Schasinglulu /* IERR to error message */ 294*91f16700Schasinglulu for (uint32_t i = 0; errors[i].error_msg != NULL; i++) { 295*91f16700Schasinglulu if (ierr == errors[i].error_code) { 296*91f16700Schasinglulu ERROR("\tIERR = %s: 0x%x\n", 297*91f16700Schasinglulu errors[i].error_msg, ierr); 298*91f16700Schasinglulu 299*91f16700Schasinglulu found = true; 300*91f16700Schasinglulu break; 301*91f16700Schasinglulu } 302*91f16700Schasinglulu } 303*91f16700Schasinglulu 304*91f16700Schasinglulu if (!found) { 305*91f16700Schasinglulu ERROR("\tUnknown IERR: 0x%x\n", ierr); 306*91f16700Schasinglulu } 307*91f16700Schasinglulu 308*91f16700Schasinglulu ERROR("SERR = %s: 0x%x\n", ras_serr_to_str(serr), serr); 309*91f16700Schasinglulu 310*91f16700Schasinglulu /* Overflow, multiple errors have been detected. */ 311*91f16700Schasinglulu if (ERR_STATUS_GET_FIELD(status, OF) != 0U) { 312*91f16700Schasinglulu ERROR("\tOverflow (there may be more errors) - " 313*91f16700Schasinglulu "Uncorrectable\n"); 314*91f16700Schasinglulu ERR_STATUS_SET_FIELD(val, OF, 1); 315*91f16700Schasinglulu } 316*91f16700Schasinglulu 317*91f16700Schasinglulu ERROR("\tUncorrectable (this is fatal)\n"); 318*91f16700Schasinglulu 319*91f16700Schasinglulu /* Miscellaneous Register Valid. */ 320*91f16700Schasinglulu if (ERR_STATUS_GET_FIELD(status, MV) != 0U) { 321*91f16700Schasinglulu ERROR("\tMISC0 = 0x%lx\n", read_erxmisc0_el1()); 322*91f16700Schasinglulu ERROR("\tMISC1 = 0x%lx\n", read_erxmisc1_el1()); 323*91f16700Schasinglulu ERR_STATUS_SET_FIELD(val, MV, 1); 324*91f16700Schasinglulu } 325*91f16700Schasinglulu 326*91f16700Schasinglulu /* Address Valid. */ 327*91f16700Schasinglulu if (ERR_STATUS_GET_FIELD(status, AV) != 0U) { 328*91f16700Schasinglulu ERROR("\tADDR = 0x%lx\n", read_erxaddr_el1()); 329*91f16700Schasinglulu ERR_STATUS_SET_FIELD(val, AV, 1); 330*91f16700Schasinglulu } 331*91f16700Schasinglulu 332*91f16700Schasinglulu /* Deferred error */ 333*91f16700Schasinglulu if (ERR_STATUS_GET_FIELD(status, DE) != 0U) { 334*91f16700Schasinglulu ERROR("\tDeferred error\n"); 335*91f16700Schasinglulu ERR_STATUS_SET_FIELD(val, DE, 1); 336*91f16700Schasinglulu } 337*91f16700Schasinglulu 338*91f16700Schasinglulu } else { 339*91f16700Schasinglulu /* For corrected error, simply clear it. */ 340*91f16700Schasinglulu VERBOSE("corrected RAS error is cleared: ERRSELR_EL1:0x%x, " 341*91f16700Schasinglulu "IERR:0x%x, SERR:0x%x\n", errselr, ierr, serr); 342*91f16700Schasinglulu ERR_STATUS_SET_FIELD(val, CE, 1); 343*91f16700Schasinglulu } 344*91f16700Schasinglulu 345*91f16700Schasinglulu ERROR("**************************************\n"); 346*91f16700Schasinglulu 347*91f16700Schasinglulu /* Write to clear reported errors. */ 348*91f16700Schasinglulu write_erxstatus_el1(val); 349*91f16700Schasinglulu 350*91f16700Schasinglulu /* error handled */ 351*91f16700Schasinglulu return 0; 352*91f16700Schasinglulu } 353*91f16700Schasinglulu 354*91f16700Schasinglulu /* Function to handle one error node from an error record group. */ 355*91f16700Schasinglulu static int32_t tegra194_ras_record_handler(const struct err_record_info *info, 356*91f16700Schasinglulu int probe_data, const struct err_handler_data *const data __unused) 357*91f16700Schasinglulu { 358*91f16700Schasinglulu uint32_t num_idx = info->sysreg.num_idx; 359*91f16700Schasinglulu uint32_t idx_start = info->sysreg.idx_start; 360*91f16700Schasinglulu const struct ras_aux_data *aux_data = info->aux_data; 361*91f16700Schasinglulu const struct ras_error *errors; 362*91f16700Schasinglulu uint32_t offset; 363*91f16700Schasinglulu const char *node_name; 364*91f16700Schasinglulu 365*91f16700Schasinglulu uint64_t status = 0ULL; 366*91f16700Schasinglulu 367*91f16700Schasinglulu VERBOSE("%s\n", __func__); 368*91f16700Schasinglulu 369*91f16700Schasinglulu assert(probe_data >= 0); 370*91f16700Schasinglulu assert((uint32_t)probe_data < num_idx); 371*91f16700Schasinglulu 372*91f16700Schasinglulu offset = (uint32_t)probe_data; 373*91f16700Schasinglulu errors = aux_data[offset].error_records; 374*91f16700Schasinglulu node_name = aux_data[offset].name; 375*91f16700Schasinglulu 376*91f16700Schasinglulu assert(errors != NULL); 377*91f16700Schasinglulu 378*91f16700Schasinglulu /* Write to ERRSELR_EL1 to select the error record */ 379*91f16700Schasinglulu ser_sys_select_record(idx_start + offset); 380*91f16700Schasinglulu 381*91f16700Schasinglulu /* Retrieve status register from the error record */ 382*91f16700Schasinglulu status = read_erxstatus_el1(); 383*91f16700Schasinglulu 384*91f16700Schasinglulu return tegra194_ras_node_handler(idx_start + offset, node_name, 385*91f16700Schasinglulu errors, status); 386*91f16700Schasinglulu } 387*91f16700Schasinglulu 388*91f16700Schasinglulu 389*91f16700Schasinglulu /* Instantiate RAS nodes */ 390*91f16700Schasinglulu PER_CORE_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE) 391*91f16700Schasinglulu PER_CLUSTER_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE) 392*91f16700Schasinglulu SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE) 393*91f16700Schasinglulu CCPLEX_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE) 394*91f16700Schasinglulu 395*91f16700Schasinglulu /* Instantiate RAS node groups */ 396*91f16700Schasinglulu static struct ras_aux_data per_core_ras_group[] = { 397*91f16700Schasinglulu PER_CORE_RAS_GROUP_NODES 398*91f16700Schasinglulu }; 399*91f16700Schasinglulu CASSERT(ARRAY_SIZE(per_core_ras_group) < RAS_NODE_INDEX_MAX, 400*91f16700Schasinglulu assert_max_per_core_ras_group_size); 401*91f16700Schasinglulu 402*91f16700Schasinglulu static struct ras_aux_data per_cluster_ras_group[] = { 403*91f16700Schasinglulu PER_CLUSTER_RAS_GROUP_NODES 404*91f16700Schasinglulu }; 405*91f16700Schasinglulu CASSERT(ARRAY_SIZE(per_cluster_ras_group) < RAS_NODE_INDEX_MAX, 406*91f16700Schasinglulu assert_max_per_cluster_ras_group_size); 407*91f16700Schasinglulu 408*91f16700Schasinglulu static struct ras_aux_data scf_l3_ras_group[] = { 409*91f16700Schasinglulu SCF_L3_BANK_RAS_GROUP_NODES 410*91f16700Schasinglulu }; 411*91f16700Schasinglulu CASSERT(ARRAY_SIZE(scf_l3_ras_group) < RAS_NODE_INDEX_MAX, 412*91f16700Schasinglulu assert_max_scf_l3_ras_group_size); 413*91f16700Schasinglulu 414*91f16700Schasinglulu static struct ras_aux_data ccplex_ras_group[] = { 415*91f16700Schasinglulu CCPLEX_RAS_GROUP_NODES 416*91f16700Schasinglulu }; 417*91f16700Schasinglulu CASSERT(ARRAY_SIZE(ccplex_ras_group) < RAS_NODE_INDEX_MAX, 418*91f16700Schasinglulu assert_max_ccplex_ras_group_size); 419*91f16700Schasinglulu 420*91f16700Schasinglulu /* 421*91f16700Schasinglulu * We have same probe and handler for each error record group, use a macro to 422*91f16700Schasinglulu * simply the record definition. 423*91f16700Schasinglulu */ 424*91f16700Schasinglulu #define ADD_ONE_ERR_GROUP(errselr_start, group) \ 425*91f16700Schasinglulu ERR_RECORD_SYSREG_V1((errselr_start), (uint32_t)ARRAY_SIZE((group)), \ 426*91f16700Schasinglulu &tegra194_ras_record_probe, \ 427*91f16700Schasinglulu &tegra194_ras_record_handler, (group)) 428*91f16700Schasinglulu 429*91f16700Schasinglulu /* RAS error record group information */ 430*91f16700Schasinglulu static struct err_record_info carmel_ras_records[] = { 431*91f16700Schasinglulu /* 432*91f16700Schasinglulu * Per core ras error records 433*91f16700Schasinglulu * ERRSELR starts from 0*256 + Logical_CPU_ID*16 + 0 to 434*91f16700Schasinglulu * 0*256 + Logical_CPU_ID*16 + 5 for each group. 435*91f16700Schasinglulu * 8 cores/groups, 6 * 8 nodes in total. 436*91f16700Schasinglulu */ 437*91f16700Schasinglulu ADD_ONE_ERR_GROUP(0x000, per_core_ras_group), 438*91f16700Schasinglulu ADD_ONE_ERR_GROUP(0x010, per_core_ras_group), 439*91f16700Schasinglulu ADD_ONE_ERR_GROUP(0x020, per_core_ras_group), 440*91f16700Schasinglulu ADD_ONE_ERR_GROUP(0x030, per_core_ras_group), 441*91f16700Schasinglulu ADD_ONE_ERR_GROUP(0x040, per_core_ras_group), 442*91f16700Schasinglulu ADD_ONE_ERR_GROUP(0x050, per_core_ras_group), 443*91f16700Schasinglulu ADD_ONE_ERR_GROUP(0x060, per_core_ras_group), 444*91f16700Schasinglulu ADD_ONE_ERR_GROUP(0x070, per_core_ras_group), 445*91f16700Schasinglulu 446*91f16700Schasinglulu /* 447*91f16700Schasinglulu * Per cluster ras error records 448*91f16700Schasinglulu * ERRSELR starts from 2*256 + Logical_Cluster_ID*16 + 0 to 449*91f16700Schasinglulu * 2*256 + Logical_Cluster_ID*16 + 3. 450*91f16700Schasinglulu * 4 clusters/groups, 3 * 4 nodes in total. 451*91f16700Schasinglulu */ 452*91f16700Schasinglulu ADD_ONE_ERR_GROUP(0x200, per_cluster_ras_group), 453*91f16700Schasinglulu ADD_ONE_ERR_GROUP(0x210, per_cluster_ras_group), 454*91f16700Schasinglulu ADD_ONE_ERR_GROUP(0x220, per_cluster_ras_group), 455*91f16700Schasinglulu ADD_ONE_ERR_GROUP(0x230, per_cluster_ras_group), 456*91f16700Schasinglulu 457*91f16700Schasinglulu /* 458*91f16700Schasinglulu * SCF L3_Bank ras error records 459*91f16700Schasinglulu * ERRSELR: 3*256 + L3_Bank_ID, L3_Bank_ID: 0-3 460*91f16700Schasinglulu * 1 groups, 4 nodes in total. 461*91f16700Schasinglulu */ 462*91f16700Schasinglulu ADD_ONE_ERR_GROUP(0x300, scf_l3_ras_group), 463*91f16700Schasinglulu 464*91f16700Schasinglulu /* 465*91f16700Schasinglulu * CCPLEX ras error records 466*91f16700Schasinglulu * ERRSELR: 4*256 + Unit_ID, Unit_ID: 0 - 4 467*91f16700Schasinglulu * 1 groups, 5 nodes in total. 468*91f16700Schasinglulu */ 469*91f16700Schasinglulu ADD_ONE_ERR_GROUP(0x400, ccplex_ras_group), 470*91f16700Schasinglulu }; 471*91f16700Schasinglulu 472*91f16700Schasinglulu CASSERT(ARRAY_SIZE(carmel_ras_records) < RAS_NODE_INDEX_MAX, 473*91f16700Schasinglulu assert_max_carmel_ras_records_size); 474*91f16700Schasinglulu 475*91f16700Schasinglulu REGISTER_ERR_RECORD_INFO(carmel_ras_records); 476*91f16700Schasinglulu 477*91f16700Schasinglulu /* dummy RAS interrupt */ 478*91f16700Schasinglulu static struct ras_interrupt carmel_ras_interrupts[] = {}; 479*91f16700Schasinglulu REGISTER_RAS_INTERRUPTS(carmel_ras_interrupts); 480*91f16700Schasinglulu 481*91f16700Schasinglulu /******************************************************************************* 482*91f16700Schasinglulu * RAS handler for the platform 483*91f16700Schasinglulu ******************************************************************************/ 484*91f16700Schasinglulu void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, 485*91f16700Schasinglulu void *handle, uint64_t flags) 486*91f16700Schasinglulu { 487*91f16700Schasinglulu #if ENABLE_FEAT_RAS 488*91f16700Schasinglulu tegra194_ea_handler(ea_reason, syndrome, cookie, handle, flags); 489*91f16700Schasinglulu #else 490*91f16700Schasinglulu plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags); 491*91f16700Schasinglulu #endif 492*91f16700Schasinglulu } 493