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 */
ras_ierr_to_str(unsigned int blkid,unsigned int 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 */
gic600_fmu_probe(uint64_t base,int * probe_data)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 */
gic600_fmu_ras_handler(uint64_t base,int probe_data)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 */
gic600_fmu_init(uint64_t base,uint64_t blk_present_mask,bool errctlr_ce_en,bool errctlr_ue_en)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 */
gic600_fmu_enable_ping(uint64_t base,uint64_t blk_present_mask,unsigned int timeout_val,unsigned int interval_diff)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 */
gic600_fmu_print_sm_info(uint64_t base,unsigned int blk,unsigned int smid)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