1 /* 2 * Copyright (c) 2021-2022, NVIDIA Corporation. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 /* 8 * Driver for GIC-600AE Fault Management Unit 9 */ 10 11 #include <assert.h> 12 #include <inttypes.h> 13 14 #include <arch_helpers.h> 15 #include <common/debug.h> 16 #include <drivers/arm/gic600ae_fmu.h> 17 #include <drivers/arm/gicv3.h> 18 19 /* GIC-600 AE FMU specific register offsets */ 20 21 /* GIC-600 AE FMU specific macros */ 22 #define FMU_ERRIDR_NUM U(44) 23 #define FMU_ERRIDR_NUM_MASK U(0xFFFF) 24 25 /* Safety mechanisms for GICD block */ 26 static char *gicd_sm_info[] = { 27 "Reserved", 28 "GICD dual lockstep error", 29 "GICD AXI4 slave interface error", 30 "GICD-PPI AXI4-Stream interface error", 31 "GICD-ITS AXI4-Stream interface error", 32 "GICD-SPI-Collator AXI4-Stream interface error", 33 "GICD AXI4 master interface error", 34 "SPI RAM DED error", 35 "SGI RAM DED error", 36 "Reserved", 37 "LPI RAM DED error", 38 "GICD-remote-GICD AXI4-Stream interface error", 39 "GICD Q-Channel interface error", 40 "GICD P-Channel interface error", 41 "SPI RAM address decode error", 42 "SGI RAM address decode error", 43 "Reserved", 44 "LPI RAM address decode error", 45 "FMU dual lockstep error", 46 "FMU ping ACK error", 47 "FMU APB parity error", 48 "GICD-Wake AXI4-Stream interface error", 49 "GICD PageOffset or Chip ID error", 50 "MBIST REQ error", 51 "SPI RAM SEC error", 52 "SGI RAM SEC error", 53 "Reserved", 54 "LPI RAM SEC error", 55 "User custom SM0 error", 56 "User custom SM1 error", 57 "GICD-ITS Monolithic switch error", 58 "GICD-ITS Q-Channel interface error", 59 "GICD-ITS Monolithic interface error", 60 "GICD FMU ClkGate override" 61 }; 62 63 /* Safety mechanisms for PPI block */ 64 static char *ppi_sm_info[] = { 65 "Reserved", 66 "PPI dual lockstep error", 67 "PPI-GICD AXI4-Stream interface error", 68 "PPI-CPU-IF AXI4-Stream interface error", 69 "PPI Q-Channel interface error", 70 "PPI RAM DED error", 71 "PPI RAM address decode error", 72 "PPI RAM SEC error", 73 "PPI User0 SM", 74 "PPI User1 SM", 75 "MBIST REQ error", 76 "PPI interrupt parity protection error", 77 "PPI FMU ClkGate override" 78 }; 79 80 /* Safety mechanisms for ITS block */ 81 static char *its_sm_info[] = { 82 "Reserved", 83 "ITS dual lockstep error", 84 "ITS-GICD AXI4-Stream interface error", 85 "ITS AXI4 slave interface error", 86 "ITS AXI4 master interface error", 87 "ITS Q-Channel interface error", 88 "ITS RAM DED error", 89 "ITS RAM address decode error", 90 "Bypass ACE switch error", 91 "ITS RAM SEC error", 92 "ITS User0 SM", 93 "ITS User1 SM", 94 "ITS-GICD Monolithic interface error", 95 "MBIST REQ error", 96 "ITS FMU ClkGate override" 97 }; 98 99 /* Safety mechanisms for SPI Collator block */ 100 static char *spicol_sm_info[] = { 101 "Reserved", 102 "SPI Collator dual lockstep error", 103 "SPI-Collator-GICD AXI4-Stream interface error", 104 "SPI Collator Q-Channel interface error", 105 "SPI Collator Q-Channel clock error", 106 "SPI interrupt parity error" 107 }; 108 109 /* Safety mechanisms for Wake Request block */ 110 static char *wkrqst_sm_info[] = { 111 "Reserved", 112 "Wake dual lockstep error", 113 "Wake-GICD AXI4-Stream interface error" 114 }; 115 116 /* Helper function to find detailed information for a specific IERR */ 117 static char __unused *ras_ierr_to_str(unsigned int blkid, unsigned int ierr) 118 { 119 char *str = NULL; 120 121 /* Find the correct record */ 122 switch (blkid) { 123 case FMU_BLK_GICD: 124 assert(ierr < ARRAY_SIZE(gicd_sm_info)); 125 str = gicd_sm_info[ierr]; 126 break; 127 128 case FMU_BLK_SPICOL: 129 assert(ierr < ARRAY_SIZE(spicol_sm_info)); 130 str = spicol_sm_info[ierr]; 131 break; 132 133 case FMU_BLK_WAKERQ: 134 assert(ierr < ARRAY_SIZE(wkrqst_sm_info)); 135 str = wkrqst_sm_info[ierr]; 136 break; 137 138 case FMU_BLK_ITS0...FMU_BLK_ITS7: 139 assert(ierr < ARRAY_SIZE(its_sm_info)); 140 str = its_sm_info[ierr]; 141 break; 142 143 case FMU_BLK_PPI0...FMU_BLK_PPI31: 144 assert(ierr < ARRAY_SIZE(ppi_sm_info)); 145 str = ppi_sm_info[ierr]; 146 break; 147 148 default: 149 assert(false); 150 break; 151 } 152 153 return str; 154 } 155 156 /* 157 * Probe for error in memory-mapped registers containing error records. 158 * Upon detecting an error, set probe data to the index of the record 159 * in error, and return 1; otherwise, return 0. 160 */ 161 int gic600_fmu_probe(uint64_t base, int *probe_data) 162 { 163 uint64_t gsr; 164 165 assert(base != 0UL); 166 167 /* 168 * Read ERR_GSR to find the error record 'M' 169 */ 170 gsr = gic_fmu_read_errgsr(base); 171 if (gsr == U(0)) { 172 return 0; 173 } 174 175 /* Return the index of the record in error */ 176 if (probe_data != NULL) { 177 *probe_data = (int)__builtin_ctzll(gsr); 178 } 179 180 return 1; 181 } 182 183 /* 184 * The handler function to read RAS records and find the safety 185 * mechanism with the error. 186 */ 187 int gic600_fmu_ras_handler(uint64_t base, int probe_data) 188 { 189 uint64_t errstatus; 190 unsigned int blkid = (unsigned int)probe_data, ierr, serr; 191 192 assert(base != 0UL); 193 194 /* 195 * FMU_ERRGSR indicates the ID of the GIC 196 * block that faulted. 197 */ 198 assert(blkid <= FMU_BLK_PPI31); 199 200 /* 201 * Find more information by reading FMU_ERR<M>STATUS 202 * register 203 */ 204 errstatus = gic_fmu_read_errstatus(base, blkid); 205 206 /* 207 * If FMU_ERR<M>STATUS.V is set to 0, no RAS records 208 * need to be scanned. 209 */ 210 if ((errstatus & FMU_ERRSTATUS_V_BIT) == U(0)) { 211 return 0; 212 } 213 214 /* 215 * FMU_ERR<M>STATUS.IERR indicates which Safety Mechanism 216 * reported the error. 217 */ 218 ierr = (errstatus >> FMU_ERRSTATUS_IERR_SHIFT) & 219 FMU_ERRSTATUS_IERR_MASK; 220 221 /* 222 * FMU_ERR<M>STATUS.SERR indicates architecturally 223 * defined primary error code. 224 */ 225 serr = errstatus & FMU_ERRSTATUS_SERR_MASK; 226 227 ERROR("**************************************\n"); 228 ERROR("RAS %s Error detected by GIC600 AE FMU\n", 229 ((errstatus & FMU_ERRSTATUS_UE_BIT) != 0U) ? 230 "Uncorrectable" : "Corrected"); 231 ERROR("\tStatus = 0x%lx \n", errstatus); 232 ERROR("\tBlock ID = 0x%x\n", blkid); 233 ERROR("\tSafety Mechanism ID = 0x%x (%s)\n", ierr, 234 ras_ierr_to_str(blkid, ierr)); 235 ERROR("\tArchitecturally defined primary error code = 0x%x\n", 236 serr); 237 ERROR("**************************************\n"); 238 239 /* Clear FMU_ERR<M>STATUS */ 240 gic_fmu_write_errstatus(base, probe_data, errstatus); 241 242 return 0; 243 } 244 245 /* 246 * Initialization sequence for the FMU 247 * 248 * 1. enable error detection for error records that are passed in the blk_present_mask 249 * 2. enable MBIST REQ and FMU Clk Gate override safety mechanisms for error records 250 * that are present on the platform 251 * 252 * The platforms are expected to pass `errctlr_ce_en` and `errctlr_ue_en`. 253 */ 254 void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask, 255 bool errctlr_ce_en, bool errctlr_ue_en) 256 { 257 unsigned int num_blk = gic_fmu_read_erridr(base) & FMU_ERRIDR_NUM_MASK; 258 uint64_t errctlr; 259 uint32_t smen; 260 261 INFO("GIC600-AE FMU supports %d error records\n", num_blk); 262 263 assert(num_blk == FMU_ERRIDR_NUM); 264 265 /* sanitize block present mask */ 266 blk_present_mask &= FMU_BLK_PRESENT_MASK; 267 268 /* Enable error detection for all error records */ 269 for (unsigned int i = 0U; i < num_blk; i++) { 270 271 /* 272 * Disable all safety mechanisms for blocks that are not 273 * present and skip the next steps. 274 */ 275 if ((blk_present_mask & BIT(i)) == 0U) { 276 gic_fmu_disable_all_sm_blkid(base, i); 277 continue; 278 } 279 280 /* Read the error record control register */ 281 errctlr = gic_fmu_read_errctlr(base, i); 282 283 /* Enable error reporting and logging, if it is disabled */ 284 if ((errctlr & FMU_ERRCTLR_ED_BIT) == 0U) { 285 errctlr |= FMU_ERRCTLR_ED_BIT; 286 } 287 288 /* Enable client provided ERRCTLR settings */ 289 errctlr |= (errctlr_ce_en ? (FMU_ERRCTLR_CI_BIT | FMU_ERRCTLR_CE_EN_BIT) : 0); 290 errctlr |= (errctlr_ue_en ? FMU_ERRCTLR_UI_BIT : 0U); 291 292 gic_fmu_write_errctlr(base, i, errctlr); 293 } 294 295 /* 296 * Enable MBIST REQ error and FMU CLK gate override safety mechanisms for 297 * all blocks 298 * 299 * GICD, SMID 23 and SMID 33 300 * PPI, SMID 10 and SMID 12 301 * ITS, SMID 13 and SMID 14 302 */ 303 if ((blk_present_mask & BIT(FMU_BLK_GICD)) != 0U) { 304 smen = (GICD_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) | 305 (FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT) | 306 FMU_SMEN_EN_BIT; 307 gic_fmu_write_smen(base, smen); 308 309 smen = (GICD_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) | 310 (FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT) | 311 FMU_SMEN_EN_BIT; 312 gic_fmu_write_smen(base, smen); 313 } 314 315 for (unsigned int i = FMU_BLK_PPI0; i < FMU_BLK_PPI31; i++) { 316 if ((blk_present_mask & BIT(i)) != 0U) { 317 smen = (PPI_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) | 318 (i << FMU_SMEN_BLK_SHIFT) | 319 FMU_SMEN_EN_BIT; 320 gic_fmu_write_smen(base, smen); 321 322 smen = (PPI_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) | 323 (i << FMU_SMEN_BLK_SHIFT) | 324 FMU_SMEN_EN_BIT; 325 gic_fmu_write_smen(base, smen); 326 } 327 } 328 329 for (unsigned int i = FMU_BLK_ITS0; i < FMU_BLK_ITS7; i++) { 330 if ((blk_present_mask & BIT(i)) != 0U) { 331 smen = (ITS_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) | 332 (i << FMU_SMEN_BLK_SHIFT) | 333 FMU_SMEN_EN_BIT; 334 gic_fmu_write_smen(base, smen); 335 336 smen = (ITS_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) | 337 (i << FMU_SMEN_BLK_SHIFT) | 338 FMU_SMEN_EN_BIT; 339 gic_fmu_write_smen(base, smen); 340 } 341 } 342 } 343 344 /* 345 * This function enable the GICD background ping engine. The GICD sends ping 346 * messages to each remote GIC block, and expects a PING_ACK back within the 347 * specified timeout. Pings need to be enabled after programming the timeout 348 * value. 349 */ 350 void gic600_fmu_enable_ping(uint64_t base, uint64_t blk_present_mask, 351 unsigned int timeout_val, unsigned int interval_diff) 352 { 353 /* 354 * Populate the PING Mask to skip a specific block while generating 355 * background ping messages and enable the ping mechanism. 356 */ 357 gic_fmu_write_pingmask(base, ~blk_present_mask); 358 gic_fmu_write_pingctlr(base, (interval_diff << FMU_PINGCTLR_INTDIFF_SHIFT) | 359 (timeout_val << FMU_PINGCTLR_TIMEOUTVAL_SHIFT) | FMU_PINGCTLR_EN_BIT); 360 } 361 362 /* Print the safety mechanism description for a given block */ 363 void gic600_fmu_print_sm_info(uint64_t base, unsigned int blk, unsigned int smid) 364 { 365 if (blk == FMU_BLK_GICD && smid <= FMU_SMID_GICD_MAX) { 366 INFO("GICD, SMID %d: %s\n", smid, gicd_sm_info[smid]); 367 } 368 369 if (blk == FMU_BLK_SPICOL && smid <= FMU_SMID_SPICOL_MAX) { 370 INFO("SPI Collator, SMID %d: %s\n", smid, spicol_sm_info[smid]); 371 } 372 373 if (blk == FMU_BLK_WAKERQ && (smid <= FMU_SMID_WAKERQ_MAX)) { 374 INFO("Wake Request, SMID %d: %s\n", smid, wkrqst_sm_info[smid]); 375 } 376 377 if (((blk >= FMU_BLK_ITS0) && (blk <= FMU_BLK_ITS7)) && (smid <= FMU_SMID_ITS_MAX)) { 378 INFO("ITS, SMID %d: %s\n", smid, its_sm_info[smid]); 379 } 380 381 if (((blk >= FMU_BLK_PPI0) && (blk <= FMU_BLK_PPI31)) && (smid <= FMU_SMID_PPI_MAX)) { 382 INFO("PPI, SMID %d: %s\n", smid, ppi_sm_info[smid]); 383 } 384 } 385