blob: 0262f4835846c2e36e6710457e6547d2b6788eb2 [file] [log] [blame]
Varun Wadekareea6dc12021-05-04 16:14:09 -07001/*
Varun Wadekarde198442022-01-24 05:45:15 -08002 * Copyright (c) 2021-2022, NVIDIA Corporation. All rights reserved.
Varun Wadekareea6dc12021-05-04 16:14:09 -07003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7/*
8 * Driver for GIC-600AE Fault Management Unit
9 */
10
11#include <assert.h>
Varun Wadekarde198442022-01-24 05:45:15 -080012#include <inttypes.h>
Varun Wadekareea6dc12021-05-04 16:14:09 -070013
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 */
26static 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 */
64static 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 */
81static 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 */
100static 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 */
110static char *wkrqst_sm_info[] = {
111 "Reserved",
112 "Wake dual lockstep error",
113 "Wake-GICD AXI4-Stream interface error"
114};
115
Varun Wadekarde198442022-01-24 05:45:15 -0800116/* Helper function to find detailed information for a specific IERR */
117static 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 */
161int 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 */
187int 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
Varun Wadekareea6dc12021-05-04 16:14:09 -0700245/*
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 */
254void 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
Varun Wadekarf6e7c952022-01-25 03:39:28 -0800271 /*
272 * Disable all safety mechanisms for blocks that are not
273 * present and skip the next steps.
274 */
Varun Wadekareea6dc12021-05-04 16:14:09 -0700275 if ((blk_present_mask & BIT(i)) == 0U) {
Varun Wadekarf6e7c952022-01-25 03:39:28 -0800276 gic_fmu_disable_all_sm_blkid(base, i);
Varun Wadekareea6dc12021-05-04 16:14:09 -0700277 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) |
Varun Wadekarf333bee2022-01-26 00:33:02 -0800305 (FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT) |
306 FMU_SMEN_EN_BIT;
Varun Wadekareea6dc12021-05-04 16:14:09 -0700307 gic_fmu_write_smen(base, smen);
308
309 smen = (GICD_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
Varun Wadekarf333bee2022-01-26 00:33:02 -0800310 (FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT) |
311 FMU_SMEN_EN_BIT;
Varun Wadekareea6dc12021-05-04 16:14:09 -0700312 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) |
Varun Wadekarf333bee2022-01-26 00:33:02 -0800318 (i << FMU_SMEN_BLK_SHIFT) |
319 FMU_SMEN_EN_BIT;
Varun Wadekareea6dc12021-05-04 16:14:09 -0700320 gic_fmu_write_smen(base, smen);
321
322 smen = (PPI_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
Varun Wadekarf333bee2022-01-26 00:33:02 -0800323 (i << FMU_SMEN_BLK_SHIFT) |
324 FMU_SMEN_EN_BIT;
Varun Wadekareea6dc12021-05-04 16:14:09 -0700325 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) |
Varun Wadekarf333bee2022-01-26 00:33:02 -0800332 (i << FMU_SMEN_BLK_SHIFT) |
333 FMU_SMEN_EN_BIT;
Varun Wadekareea6dc12021-05-04 16:14:09 -0700334 gic_fmu_write_smen(base, smen);
335
336 smen = (ITS_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
Varun Wadekarf333bee2022-01-26 00:33:02 -0800337 (i << FMU_SMEN_BLK_SHIFT) |
338 FMU_SMEN_EN_BIT;
Varun Wadekareea6dc12021-05-04 16:14:09 -0700339 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 */
350void 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 */
363void 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}