fix(intel): fix ECC Double Bit Error handling

SError and Abort are handled in Linux (EL1) instead of
EL3. This patch adds some functionality that complements the
use cases by Linux as follows:

- Provide SMC for ECC DBE notification to EL3
- Determine type of reset needed and service the request in
  place of Linux

Signed-off-by: Abdul Halim, Muhammad Hadi Asyrafi <muhammad.hadi.asyrafi.abdul.halim@intel.com>
Signed-off-by: Sieu Mun Tang <sieu.mun.tang@intel.com>
Change-Id: I43d02c77f28004a31770be53599a5a42de412211
diff --git a/plat/intel/soc/agilex/platform.mk b/plat/intel/soc/agilex/platform.mk
index 92b7754..10a3eec 100644
--- a/plat/intel/soc/agilex/platform.mk
+++ b/plat/intel/soc/agilex/platform.mk
@@ -65,6 +65,7 @@
 		plat/intel/soc/common/socfpga_psci.c			\
 		plat/intel/soc/common/socfpga_sip_svc.c			\
 		plat/intel/soc/common/socfpga_topology.c		\
+		plat/intel/soc/common/sip/socfpga_sip_ecc.c		\
 		plat/intel/soc/common/sip/socfpga_sip_fcs.c		\
 		plat/intel/soc/common/soc/socfpga_mailbox.c		\
 		plat/intel/soc/common/soc/socfpga_reset_manager.c
diff --git a/plat/intel/soc/common/include/socfpga_reset_manager.h b/plat/intel/soc/common/include/socfpga_reset_manager.h
index 637f8df..a976df7 100644
--- a/plat/intel/soc/common/include/socfpga_reset_manager.h
+++ b/plat/intel/soc/common/include/socfpga_reset_manager.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/plat/intel/soc/common/include/socfpga_sip_svc.h b/plat/intel/soc/common/include/socfpga_sip_svc.h
index 6eca197..5770f11 100644
--- a/plat/intel/soc/common/include/socfpga_sip_svc.h
+++ b/plat/intel/soc/common/include/socfpga_sip_svc.h
@@ -40,12 +40,22 @@
 #define INTEL_SIP_SMC_RSU_DCMF_VERSION			0xC2000010
 #define INTEL_SIP_SMC_RSU_COPY_DCMF_VERSION		0xC2000011
 
+
+/* ECC */
+#define INTEL_SIP_SMC_ECC_DBE				0xC200000D
+
 /* Send Mailbox Command */
 #define INTEL_SIP_SMC_MBOX_SEND_CMD			0xC200001E
 
 
 /* SiP Definitions */
 
+/* ECC DBE */
+#define WARM_RESET_WFI_FLAG				BIT(31)
+#define SYSMGR_ECC_DBE_COLD_RST_MASK		(SYSMGR_ECC_OCRAM_MASK |\
+							SYSMGR_ECC_DDR0_MASK |\
+							SYSMGR_ECC_DDR1_MASK)
+
 /* FPGA config helpers */
 #define INTEL_SIP_SMC_FPGA_CONFIG_ADDR			0x400000
 #define INTEL_SIP_SMC_FPGA_CONFIG_SIZE			0x2000000
@@ -74,4 +84,8 @@
 
 bool is_address_in_ddr_range(uint64_t addr, uint64_t size);
 
+/* ECC DBE */
+bool cold_reset_for_ecc_dbe(void);
+uint32_t intel_ecc_dbe_notification(uint64_t dbe_value);
+
 #endif /* SOCFPGA_SIP_SVC_H */
diff --git a/plat/intel/soc/common/include/socfpga_system_manager.h b/plat/intel/soc/common/include/socfpga_system_manager.h
index 8b42d47..2b13f1f 100644
--- a/plat/intel/soc/common/include/socfpga_system_manager.h
+++ b/plat/intel/soc/common/include/socfpga_system_manager.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, Intel Corporation. All rights reserved.
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -30,6 +30,8 @@
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_0		0x200
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_1		0x204
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_2		0x208
+#define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_8		0x220
+#define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_9		0x224
 
 /* Field Masking */
 
@@ -47,6 +49,10 @@
 					| SCR_MPU_MASK)
 #define DISABLE_BRIDGE_FIREWALL				0x0ffe0101
 
+#define SYSMGR_ECC_OCRAM_MASK				BIT(1)
+#define SYSMGR_ECC_DDR0_MASK				BIT(16)
+#define SYSMGR_ECC_DDR1_MASK				BIT(17)
+
 /* Macros */
 
 #define SOCFPGA_SYSMGR(_reg)		(SOCFPGA_SYSMGR_REG_BASE \
diff --git a/plat/intel/soc/common/sip/socfpga_sip_ecc.c b/plat/intel/soc/common/sip/socfpga_sip_ecc.c
new file mode 100644
index 0000000..c4e06a6
--- /dev/null
+++ b/plat/intel/soc/common/sip/socfpga_sip_ecc.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
+ */
+
+#include <assert.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+#include <tools_share/uuid.h>
+
+#include "socfpga_fcs.h"
+#include "socfpga_mailbox.h"
+#include "socfpga_reset_manager.h"
+#include "socfpga_sip_svc.h"
+#include "socfpga_system_manager.h"
+
+uint32_t intel_ecc_dbe_notification(uint64_t dbe_value)
+{
+	dbe_value &= WARM_RESET_WFI_FLAG;
+
+	/* Trap CPUs in WFI if warm reset flag is set */
+	if (dbe_value > 0) {
+		while (1) {
+			wfi();
+		}
+	}
+
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
+bool cold_reset_for_ecc_dbe(void)
+{
+	uint32_t dbe_int_status;
+
+	dbe_int_status = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_8));
+
+	/* Trigger cold reset only for error in critical memory (DDR/OCRAM) */
+	dbe_int_status &= SYSMGR_ECC_DBE_COLD_RST_MASK;
+
+	if (dbe_int_status > 0) {
+		return true;
+	}
+
+	return false;
+}
diff --git a/plat/intel/soc/common/socfpga_psci.c b/plat/intel/soc/common/socfpga_psci.c
index 4b57b8f..5fd6559 100644
--- a/plat/intel/soc/common/socfpga_psci.c
+++ b/plat/intel/soc/common/socfpga_psci.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,9 +14,9 @@
 #include "socfpga_mailbox.h"
 #include "socfpga_plat_def.h"
 #include "socfpga_reset_manager.h"
+#include "socfpga_sip_svc.h"
 
 
-
 /*******************************************************************************
  * plat handler called when a CPU is about to enter standby.
  ******************************************************************************/
@@ -151,6 +151,9 @@
 static int socfpga_system_reset2(int is_vendor, int reset_type,
 					u_register_t cookie)
 {
+	if (cold_reset_for_ecc_dbe()) {
+		mailbox_reset_cold();
+	}
 	/* disable cpuif */
 	gicv2_cpuif_disable();
 
diff --git a/plat/intel/soc/common/socfpga_sip_svc.c b/plat/intel/soc/common/socfpga_sip_svc.c
index 16f8145..14cd9e0 100644
--- a/plat/intel/soc/common/socfpga_sip_svc.c
+++ b/plat/intel/soc/common/socfpga_sip_svc.c
@@ -530,6 +530,10 @@
 			SMC_RET2(handle, status, retval);
 		}
 
+	case INTEL_SIP_SMC_ECC_DBE:
+		status = intel_ecc_dbe_notification(x1);
+		SMC_RET1(handle, status);
+
 	case INTEL_SIP_SMC_MBOX_SEND_CMD:
 		x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
 		x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
diff --git a/plat/intel/soc/n5x/platform.mk b/plat/intel/soc/n5x/platform.mk
index 722694d..8366d6d 100644
--- a/plat/intel/soc/n5x/platform.mk
+++ b/plat/intel/soc/n5x/platform.mk
@@ -38,6 +38,7 @@
 		plat/intel/soc/common/socfpga_psci.c			\
 		plat/intel/soc/common/socfpga_sip_svc.c			\
 		plat/intel/soc/common/socfpga_topology.c		\
+		plat/intel/soc/common/sip/socfpga_sip_ecc.c             \
 		plat/intel/soc/common/sip/socfpga_sip_fcs.c		\
 		plat/intel/soc/common/soc/socfpga_mailbox.c		\
 		plat/intel/soc/common/soc/socfpga_reset_manager.c
diff --git a/plat/intel/soc/stratix10/platform.mk b/plat/intel/soc/stratix10/platform.mk
index b47ac9d..d9d88d4 100644
--- a/plat/intel/soc/stratix10/platform.mk
+++ b/plat/intel/soc/stratix10/platform.mk
@@ -63,6 +63,7 @@
 		plat/intel/soc/common/socfpga_psci.c			\
 		plat/intel/soc/common/socfpga_sip_svc.c			\
 		plat/intel/soc/common/socfpga_topology.c		\
+		plat/intel/soc/common/sip/socfpga_sip_ecc.c		\
 		plat/intel/soc/common/sip/socfpga_sip_fcs.c		\
 		plat/intel/soc/common/soc/socfpga_mailbox.c		\
 		plat/intel/soc/common/soc/socfpga_reset_manager.c