Merge changes I573e6478,I52dc3bee,I7e543664 into integration

* changes:
  feat(gic600ae_fmu): enable all GICD, PPI, ITS SMs
  feat(gic600ae_fmu): disable SMID for unavailable blocks
  feat(gic600ae_fmu): introduce support for RAS error handling
diff --git a/drivers/arm/gic/v3/gic600ae_fmu.c b/drivers/arm/gic/v3/gic600ae_fmu.c
index 13979fa..0262f48 100644
--- a/drivers/arm/gic/v3/gic600ae_fmu.c
+++ b/drivers/arm/gic/v3/gic600ae_fmu.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2021-2022, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,7 @@
  */
 
 #include <assert.h>
+#include <inttypes.h>
 
 #include <arch_helpers.h>
 #include <common/debug.h>
@@ -112,6 +113,135 @@
 	"Wake-GICD AXI4-Stream interface error"
 };
 
+/* Helper function to find detailed information for a specific IERR */
+static char __unused *ras_ierr_to_str(unsigned int blkid, unsigned int ierr)
+{
+	char *str = NULL;
+
+	/* Find the correct record */
+	switch (blkid) {
+	case FMU_BLK_GICD:
+		assert(ierr < ARRAY_SIZE(gicd_sm_info));
+		str = gicd_sm_info[ierr];
+		break;
+
+	case FMU_BLK_SPICOL:
+		assert(ierr < ARRAY_SIZE(spicol_sm_info));
+		str = spicol_sm_info[ierr];
+		break;
+
+	case FMU_BLK_WAKERQ:
+		assert(ierr < ARRAY_SIZE(wkrqst_sm_info));
+		str = wkrqst_sm_info[ierr];
+		break;
+
+	case FMU_BLK_ITS0...FMU_BLK_ITS7:
+		assert(ierr < ARRAY_SIZE(its_sm_info));
+		str = its_sm_info[ierr];
+		break;
+
+	case FMU_BLK_PPI0...FMU_BLK_PPI31:
+		assert(ierr < ARRAY_SIZE(ppi_sm_info));
+		str = ppi_sm_info[ierr];
+		break;
+
+	default:
+		assert(false);
+		break;
+	}
+
+	return str;
+}
+
+/*
+ * Probe for error in memory-mapped registers containing error records.
+ * Upon detecting an error, set probe data to the index of the record
+ * in error, and return 1; otherwise, return 0.
+ */
+int gic600_fmu_probe(uint64_t base, int *probe_data)
+{
+	uint64_t gsr;
+
+	assert(base != 0UL);
+
+	/*
+	 * Read ERR_GSR to find the error record 'M'
+	 */
+	gsr = gic_fmu_read_errgsr(base);
+	if (gsr == U(0)) {
+		return 0;
+	}
+
+	/* Return the index of the record in error */
+	if (probe_data != NULL) {
+		*probe_data = (int)__builtin_ctzll(gsr);
+	}
+
+	return 1;
+}
+
+/*
+ * The handler function to read RAS records and find the safety
+ * mechanism with the error.
+ */
+int gic600_fmu_ras_handler(uint64_t base, int probe_data)
+{
+	uint64_t errstatus;
+	unsigned int blkid = (unsigned int)probe_data, ierr, serr;
+
+	assert(base != 0UL);
+
+	/*
+	 * FMU_ERRGSR indicates the ID of the GIC
+	 * block that faulted.
+	 */
+	assert(blkid <= FMU_BLK_PPI31);
+
+	/*
+	 * Find more information by reading FMU_ERR<M>STATUS
+	 * register
+	 */
+	errstatus = gic_fmu_read_errstatus(base, blkid);
+
+	/*
+	 * If FMU_ERR<M>STATUS.V is set to 0, no RAS records
+	 * need to be scanned.
+	 */
+	if ((errstatus & FMU_ERRSTATUS_V_BIT) == U(0)) {
+		return 0;
+	}
+
+	/*
+	 * FMU_ERR<M>STATUS.IERR indicates which Safety Mechanism
+	 * reported the error.
+	 */
+	ierr = (errstatus >> FMU_ERRSTATUS_IERR_SHIFT) &
+			FMU_ERRSTATUS_IERR_MASK;
+
+	/*
+	 * FMU_ERR<M>STATUS.SERR indicates architecturally
+	 * defined primary error code.
+	 */
+	serr = errstatus & FMU_ERRSTATUS_SERR_MASK;
+
+	ERROR("**************************************\n");
+	ERROR("RAS %s Error detected by GIC600 AE FMU\n",
+		((errstatus & FMU_ERRSTATUS_UE_BIT) != 0U) ?
+			"Uncorrectable" : "Corrected");
+	ERROR("\tStatus = 0x%lx \n", errstatus);
+	ERROR("\tBlock ID = 0x%x\n", blkid);
+	ERROR("\tSafety Mechanism ID = 0x%x (%s)\n", ierr,
+		ras_ierr_to_str(blkid, ierr));
+	ERROR("\tArchitecturally defined primary error code = 0x%x\n",
+		serr);
+	ERROR("**************************************\n");
+
+	/* Clear FMU_ERR<M>STATUS */
+	gic_fmu_write_errstatus(base, probe_data, errstatus);
+
+	return 0;
+}
+
 /*
  * Initialization sequence for the FMU
  *
@@ -138,8 +268,12 @@
 	/* Enable error detection for all error records */
 	for (unsigned int i = 0U; i < num_blk; i++) {
 
-		/* Skip next steps if the block is not present */
+		/*
+		 * Disable all safety mechanisms for blocks that are not
+		 * present and skip the next steps.
+		 */
 		if ((blk_present_mask & BIT(i)) == 0U) {
+			gic_fmu_disable_all_sm_blkid(base, i);
 			continue;
 		}
 
@@ -168,22 +302,26 @@
 	 */
 	if ((blk_present_mask & BIT(FMU_BLK_GICD)) != 0U) {
 		smen = (GICD_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
-			(FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT);
+			(FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT) |
+			FMU_SMEN_EN_BIT;
 		gic_fmu_write_smen(base, smen);
 
 		smen = (GICD_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
-			(FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT);
+			(FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT) |
+			FMU_SMEN_EN_BIT;
 		gic_fmu_write_smen(base, smen);
 	}
 
 	for (unsigned int i = FMU_BLK_PPI0; i < FMU_BLK_PPI31; i++) {
 		if ((blk_present_mask & BIT(i)) != 0U) {
 			smen = (PPI_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
-				(i << FMU_SMEN_BLK_SHIFT);
+				(i << FMU_SMEN_BLK_SHIFT) |
+				FMU_SMEN_EN_BIT;
 			gic_fmu_write_smen(base, smen);
 
 			smen = (PPI_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
-				(i << FMU_SMEN_BLK_SHIFT);
+				(i << FMU_SMEN_BLK_SHIFT) |
+				FMU_SMEN_EN_BIT;
 			gic_fmu_write_smen(base, smen);
 		}
 	}
@@ -191,11 +329,13 @@
 	for (unsigned int i = FMU_BLK_ITS0; i < FMU_BLK_ITS7; i++) {
 		if ((blk_present_mask & BIT(i)) != 0U) {
 			smen = (ITS_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
-				(i << FMU_SMEN_BLK_SHIFT);
+				(i << FMU_SMEN_BLK_SHIFT) |
+				FMU_SMEN_EN_BIT;
 			gic_fmu_write_smen(base, smen);
 
 			smen = (ITS_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
-				(i << FMU_SMEN_BLK_SHIFT);
+				(i << FMU_SMEN_BLK_SHIFT) |
+				FMU_SMEN_EN_BIT;
 			gic_fmu_write_smen(base, smen);
 		}
 	}
diff --git a/drivers/arm/gic/v3/gic600ae_fmu_helpers.c b/drivers/arm/gic/v3/gic600ae_fmu_helpers.c
index 4aa0efb..09806dc 100644
--- a/drivers/arm/gic/v3/gic600ae_fmu_helpers.c
+++ b/drivers/arm/gic/v3/gic600ae_fmu_helpers.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2021-2022, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -258,3 +258,47 @@
 {
 	GIC_FMU_WRITE_64(base, GICFMU_PINGMASK, 0, val);
 }
+
+/*
+ * Helper function to disable all safety mechanisms for a given block
+ */
+void gic_fmu_disable_all_sm_blkid(uintptr_t base, unsigned int blkid)
+{
+	uint32_t smen, max_smid = U(0);
+
+	/* Sanity check block ID */
+	assert((blkid >= FMU_BLK_GICD) && (blkid <= FMU_BLK_PPI31));
+
+	/* Find the max safety mechanism ID for the block */
+	switch (blkid) {
+	case FMU_BLK_GICD:
+		max_smid = FMU_SMID_GICD_MAX;
+		break;
+
+	case FMU_BLK_SPICOL:
+		max_smid = FMU_SMID_SPICOL_MAX;
+		break;
+
+	case FMU_BLK_WAKERQ:
+		max_smid = FMU_SMID_WAKERQ_MAX;
+		break;
+
+	case FMU_BLK_ITS0...FMU_BLK_ITS7:
+		max_smid = FMU_SMID_ITS_MAX;
+		break;
+
+	case FMU_BLK_PPI0...FMU_BLK_PPI31:
+		max_smid = FMU_SMID_PPI_MAX;
+		break;
+
+	default:
+		assert(false);
+		break;
+	}
+
+	/* Disable all Safety Mechanisms for a given block id */
+	for (unsigned int i = 0U; i < max_smid; i++) {
+		smen = (blkid << FMU_SMEN_BLK_SHIFT) | (i << FMU_SMEN_SMID_SHIFT);
+		gic_fmu_write_smen(base, smen);
+	}
+}
diff --git a/include/drivers/arm/gic600ae_fmu.h b/include/drivers/arm/gic600ae_fmu.h
index 691ffc7..88b87b9 100644
--- a/include/drivers/arm/gic600ae_fmu.h
+++ b/include/drivers/arm/gic600ae_fmu.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2021-2022, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -37,6 +37,7 @@
 /* SMEN constants */
 #define FMU_SMEN_BLK_SHIFT	U(8)
 #define FMU_SMEN_SMID_SHIFT	U(24)
+#define FMU_SMEN_EN_BIT		BIT(0)
 
 /* Error record IDs */
 #define FMU_BLK_GICD		U(0)
@@ -86,10 +87,10 @@
 
 /* Safety Mechamism limit */
 #define FMU_SMID_GICD_MAX	U(33)
+#define FMU_SMID_PPI_MAX	U(12)
+#define FMU_SMID_ITS_MAX	U(14)
 #define FMU_SMID_SPICOL_MAX	U(5)
 #define FMU_SMID_WAKERQ_MAX	U(2)
-#define FMU_SMID_ITS_MAX	U(14)
-#define FMU_SMID_PPI_MAX	U(12)
 
 /* MBIST Safety Mechanism ID */
 #define GICD_MBIST_REQ_ERROR	U(23)
@@ -100,12 +101,17 @@
 #define ITS_FMU_CLKGATE_ERROR	U(14)
 
 /* ERRSTATUS bits */
-#define FMU_ERRSTATUS_V_BIT	BIT(30)
-#define FMU_ERRSTATUS_UE_BIT	BIT(29)
-#define FMU_ERRSTATUS_OV_BIT	BIT(27)
-#define FMU_ERRSTATUS_CE_BITS	(BIT(25) | BIT(24))
-#define FMU_ERRSTATUS_CLEAR	(FMU_ERRSTATUS_V_BIT | FMU_ERRSTATUS_UE_BIT | \
-				 FMU_ERRSTATUS_OV_BIT | FMU_ERRSTATUS_CE_BITS)
+#define FMU_ERRSTATUS_BLKID_SHIFT	U(32)
+#define FMU_ERRSTATUS_BLKID_MASK	U(0xFF)
+#define FMU_ERRSTATUS_V_BIT		BIT(30)
+#define FMU_ERRSTATUS_UE_BIT		BIT(29)
+#define FMU_ERRSTATUS_OV_BIT		BIT(27)
+#define FMU_ERRSTATUS_CE_BITS		(BIT(25) | BIT(24))
+#define FMU_ERRSTATUS_CLEAR		(FMU_ERRSTATUS_V_BIT | FMU_ERRSTATUS_UE_BIT | \
+					 FMU_ERRSTATUS_OV_BIT | FMU_ERRSTATUS_CE_BITS)
+#define FMU_ERRSTATUS_IERR_MASK		U(0xFF)
+#define FMU_ERRSTATUS_IERR_SHIFT	U(8)
+#define FMU_ERRSTATUS_SERR_MASK		U(0xFF)
 
 /* PINGCTLR constants */
 #define FMU_PINGCTLR_INTDIFF_SHIFT	U(16)
@@ -137,11 +143,14 @@
 void gic_fmu_write_smen(uintptr_t base, uint32_t val);
 void gic_fmu_write_sminjerr(uintptr_t base, uint32_t val);
 void gic_fmu_write_pingmask(uintptr_t base, uint64_t val);
+void gic_fmu_disable_all_sm_blkid(uintptr_t base, unsigned int blkid);
 
 void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask, bool errctlr_ce_en, bool errctlr_ue_en);
 void gic600_fmu_enable_ping(uint64_t base, uint64_t blk_present_mask,
 		unsigned int timeout_val, unsigned int interval_diff);
 void gic600_fmu_print_sm_info(uint64_t base, unsigned int blk, unsigned int smid);
+int gic600_fmu_probe(uint64_t base, int *probe_data);
+int gic600_fmu_ras_handler(uint64_t base, int probe_data);
 
 #endif /* __ASSEMBLER__ */