1 /* 2 * Copyright (c) 2021, 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 13 #include <arch_helpers.h> 14 #include <common/debug.h> 15 #include <drivers/arm/gic600ae_fmu.h> 16 #include <drivers/arm/gicv3.h> 17 18 /* GIC-600 AE FMU specific register offsets */ 19 20 /* GIC-600 AE FMU specific macros */ 21 #define FMU_ERRIDR_NUM U(44) 22 #define FMU_ERRIDR_NUM_MASK U(0xFFFF) 23 24 /* Safety mechanisms for GICD block */ 25 static char *gicd_sm_info[] = { 26 "Reserved", 27 "GICD dual lockstep error", 28 "GICD AXI4 slave interface error", 29 "GICD-PPI AXI4-Stream interface error", 30 "GICD-ITS AXI4-Stream interface error", 31 "GICD-SPI-Collator AXI4-Stream interface error", 32 "GICD AXI4 master interface error", 33 "SPI RAM DED error", 34 "SGI RAM DED error", 35 "Reserved", 36 "LPI RAM DED error", 37 "GICD-remote-GICD AXI4-Stream interface error", 38 "GICD Q-Channel interface error", 39 "GICD P-Channel interface error", 40 "SPI RAM address decode error", 41 "SGI RAM address decode error", 42 "Reserved", 43 "LPI RAM address decode error", 44 "FMU dual lockstep error", 45 "FMU ping ACK error", 46 "FMU APB parity error", 47 "GICD-Wake AXI4-Stream interface error", 48 "GICD PageOffset or Chip ID error", 49 "MBIST REQ error", 50 "SPI RAM SEC error", 51 "SGI RAM SEC error", 52 "Reserved", 53 "LPI RAM SEC error", 54 "User custom SM0 error", 55 "User custom SM1 error", 56 "GICD-ITS Monolithic switch error", 57 "GICD-ITS Q-Channel interface error", 58 "GICD-ITS Monolithic interface error", 59 "GICD FMU ClkGate override" 60 }; 61 62 /* Safety mechanisms for PPI block */ 63 static char *ppi_sm_info[] = { 64 "Reserved", 65 "PPI dual lockstep error", 66 "PPI-GICD AXI4-Stream interface error", 67 "PPI-CPU-IF AXI4-Stream interface error", 68 "PPI Q-Channel interface error", 69 "PPI RAM DED error", 70 "PPI RAM address decode error", 71 "PPI RAM SEC error", 72 "PPI User0 SM", 73 "PPI User1 SM", 74 "MBIST REQ error", 75 "PPI interrupt parity protection error", 76 "PPI FMU ClkGate override" 77 }; 78 79 /* Safety mechanisms for ITS block */ 80 static char *its_sm_info[] = { 81 "Reserved", 82 "ITS dual lockstep error", 83 "ITS-GICD AXI4-Stream interface error", 84 "ITS AXI4 slave interface error", 85 "ITS AXI4 master interface error", 86 "ITS Q-Channel interface error", 87 "ITS RAM DED error", 88 "ITS RAM address decode error", 89 "Bypass ACE switch error", 90 "ITS RAM SEC error", 91 "ITS User0 SM", 92 "ITS User1 SM", 93 "ITS-GICD Monolithic interface error", 94 "MBIST REQ error", 95 "ITS FMU ClkGate override" 96 }; 97 98 /* Safety mechanisms for SPI Collator block */ 99 static char *spicol_sm_info[] = { 100 "Reserved", 101 "SPI Collator dual lockstep error", 102 "SPI-Collator-GICD AXI4-Stream interface error", 103 "SPI Collator Q-Channel interface error", 104 "SPI Collator Q-Channel clock error", 105 "SPI interrupt parity error" 106 }; 107 108 /* Safety mechanisms for Wake Request block */ 109 static char *wkrqst_sm_info[] = { 110 "Reserved", 111 "Wake dual lockstep error", 112 "Wake-GICD AXI4-Stream interface error" 113 }; 114 115 /* 116 * Initialization sequence for the FMU 117 * 118 * 1. enable error detection for error records that are passed in the blk_present_mask 119 * 2. enable MBIST REQ and FMU Clk Gate override safety mechanisms for error records 120 * that are present on the platform 121 * 122 * The platforms are expected to pass `errctlr_ce_en` and `errctlr_ue_en`. 123 */ 124 void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask, 125 bool errctlr_ce_en, bool errctlr_ue_en) 126 { 127 unsigned int num_blk = gic_fmu_read_erridr(base) & FMU_ERRIDR_NUM_MASK; 128 uint64_t errctlr; 129 uint32_t smen; 130 131 INFO("GIC600-AE FMU supports %d error records\n", num_blk); 132 133 assert(num_blk == FMU_ERRIDR_NUM); 134 135 /* sanitize block present mask */ 136 blk_present_mask &= FMU_BLK_PRESENT_MASK; 137 138 /* Enable error detection for all error records */ 139 for (unsigned int i = 0U; i < num_blk; i++) { 140 141 /* Skip next steps if the block is not present */ 142 if ((blk_present_mask & BIT(i)) == 0U) { 143 continue; 144 } 145 146 /* Read the error record control register */ 147 errctlr = gic_fmu_read_errctlr(base, i); 148 149 /* Enable error reporting and logging, if it is disabled */ 150 if ((errctlr & FMU_ERRCTLR_ED_BIT) == 0U) { 151 errctlr |= FMU_ERRCTLR_ED_BIT; 152 } 153 154 /* Enable client provided ERRCTLR settings */ 155 errctlr |= (errctlr_ce_en ? (FMU_ERRCTLR_CI_BIT | FMU_ERRCTLR_CE_EN_BIT) : 0); 156 errctlr |= (errctlr_ue_en ? FMU_ERRCTLR_UI_BIT : 0U); 157 158 gic_fmu_write_errctlr(base, i, errctlr); 159 } 160 161 /* 162 * Enable MBIST REQ error and FMU CLK gate override safety mechanisms for 163 * all blocks 164 * 165 * GICD, SMID 23 and SMID 33 166 * PPI, SMID 10 and SMID 12 167 * ITS, SMID 13 and SMID 14 168 */ 169 if ((blk_present_mask & BIT(FMU_BLK_GICD)) != 0U) { 170 smen = (GICD_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) | 171 (FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT); 172 gic_fmu_write_smen(base, smen); 173 174 smen = (GICD_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) | 175 (FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT); 176 gic_fmu_write_smen(base, smen); 177 } 178 179 for (unsigned int i = FMU_BLK_PPI0; i < FMU_BLK_PPI31; i++) { 180 if ((blk_present_mask & BIT(i)) != 0U) { 181 smen = (PPI_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) | 182 (i << FMU_SMEN_BLK_SHIFT); 183 gic_fmu_write_smen(base, smen); 184 185 smen = (PPI_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) | 186 (i << FMU_SMEN_BLK_SHIFT); 187 gic_fmu_write_smen(base, smen); 188 } 189 } 190 191 for (unsigned int i = FMU_BLK_ITS0; i < FMU_BLK_ITS7; i++) { 192 if ((blk_present_mask & BIT(i)) != 0U) { 193 smen = (ITS_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) | 194 (i << FMU_SMEN_BLK_SHIFT); 195 gic_fmu_write_smen(base, smen); 196 197 smen = (ITS_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) | 198 (i << FMU_SMEN_BLK_SHIFT); 199 gic_fmu_write_smen(base, smen); 200 } 201 } 202 } 203 204 /* 205 * This function enable the GICD background ping engine. The GICD sends ping 206 * messages to each remote GIC block, and expects a PING_ACK back within the 207 * specified timeout. Pings need to be enabled after programming the timeout 208 * value. 209 */ 210 void gic600_fmu_enable_ping(uint64_t base, uint64_t blk_present_mask, 211 unsigned int timeout_val, unsigned int interval_diff) 212 { 213 /* 214 * Populate the PING Mask to skip a specific block while generating 215 * background ping messages and enable the ping mechanism. 216 */ 217 gic_fmu_write_pingmask(base, ~blk_present_mask); 218 gic_fmu_write_pingctlr(base, (interval_diff << FMU_PINGCTLR_INTDIFF_SHIFT) | 219 (timeout_val << FMU_PINGCTLR_TIMEOUTVAL_SHIFT) | FMU_PINGCTLR_EN_BIT); 220 } 221 222 /* Print the safety mechanism description for a given block */ 223 void gic600_fmu_print_sm_info(uint64_t base, unsigned int blk, unsigned int smid) 224 { 225 if (blk == FMU_BLK_GICD && smid <= FMU_SMID_GICD_MAX) { 226 INFO("GICD, SMID %d: %s\n", smid, gicd_sm_info[smid]); 227 } 228 229 if (blk == FMU_BLK_SPICOL && smid <= FMU_SMID_SPICOL_MAX) { 230 INFO("SPI Collator, SMID %d: %s\n", smid, spicol_sm_info[smid]); 231 } 232 233 if (blk == FMU_BLK_WAKERQ && (smid <= FMU_SMID_WAKERQ_MAX)) { 234 INFO("Wake Request, SMID %d: %s\n", smid, wkrqst_sm_info[smid]); 235 } 236 237 if (((blk >= FMU_BLK_ITS0) && (blk <= FMU_BLK_ITS7)) && (smid <= FMU_SMID_ITS_MAX)) { 238 INFO("ITS, SMID %d: %s\n", smid, its_sm_info[smid]); 239 } 240 241 if (((blk >= FMU_BLK_PPI0) && (blk <= FMU_BLK_PPI31)) && (smid <= FMU_SMID_PPI_MAX)) { 242 INFO("PPI, SMID %d: %s\n", smid, ppi_sm_info[smid]); 243 } 244 } 245