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