feat(intel): support IO96B ECC Error Injection via SMC call

Add SMC call for IO96B ECC error injection, write dummy data
to DDR and read back. This is required to do from ATF,because
the error injection from Linux kernel is causing inconsitent
behaviour and sometimes causing memory crash.

Change-Id: I62f9dca319ea6a7ddbdbb7cc2965a0a4e2d41ab6
Signed-off-by: Rabara, Niravkumar L <niravkumar.l.rabara@intel.com>
Signed-off-by: Girisha Dengi <girisha.dengi@intel.com>
Signed-off-by: Jit Loon Lim <jit.loon.lim@altera.com>
diff --git a/plat/intel/soc/agilex5/include/agilex5_system_manager.h b/plat/intel/soc/agilex5/include/agilex5_system_manager.h
index 8c86ab1..f4b53e8 100644
--- a/plat/intel/soc/agilex5/include/agilex5_system_manager.h
+++ b/plat/intel/soc/agilex5/include/agilex5_system_manager.h
@@ -160,6 +160,11 @@
 #define SOCFPGA_ECC_QSPI_ECC_STARTACC					0x7C
 #define SOCFPGA_ECC_QSPI_ECC_WDCTRL					0x80
 
+/* IOSSM mailbox address */
+#define IOSSM_CMD_PARAM							0x18400438
+#define IOSSM_CMD_TRIG_OP						0x1840043C
+#define IOSSM_CMD_RESP_STATUS						0x1840045C
+
 #define DMA0_STREAM_CTRL_REG						0x10D1217C
 #define DMA1_STREAM_CTRL_REG						0x10D12180
 #define SDM_STREAM_CTRL_REG						0x10D12184
diff --git a/plat/intel/soc/common/include/socfpga_sip_svc.h b/plat/intel/soc/common/include/socfpga_sip_svc.h
index 7f96adb..fdd1bf8 100644
--- a/plat/intel/soc/common/include/socfpga_sip_svc.h
+++ b/plat/intel/soc/common/include/socfpga_sip_svc.h
@@ -153,6 +153,9 @@
 /* ATF build version */
 #define INTEL_SIP_SMC_ATF_BUILD_VER					0xC200009B
 
+/* IO96B ECC Error Injection */
+#define INTEL_SIP_SMC_INJECT_IO96B_ECC_ERR				0xC200009C
+
 #define INTEL_SIP_SMC_FCS_SHA_MODE_MASK					0xF
 #define INTEL_SIP_SMC_FCS_DIGEST_SIZE_MASK				0xF
 #define INTEL_SIP_SMC_FCS_DIGEST_SIZE_OFFSET				4U
@@ -163,6 +166,8 @@
 #define SYSMGR_ECC_DBE_COLD_RST_MASK					(SYSMGR_ECC_OCRAM_MASK |\
 									SYSMGR_ECC_DDR0_MASK |\
 									SYSMGR_ECC_DDR1_MASK)
+#define IOSSM_ECC_ERR_INJ_DELAY_USECS					(40U)
+#define IOSSM_CMD_STATUS_RESP_READY					BIT(0)
 
 /* Non-mailbox SMC Call */
 #define INTEL_SIP_SMC_SVC_VERSION					0xC2000200
diff --git a/plat/intel/soc/common/socfpga_sip_svc.c b/plat/intel/soc/common/socfpga_sip_svc.c
index f4a3ea0..89e0dd4 100644
--- a/plat/intel/soc/common/socfpga_sip_svc.c
+++ b/plat/intel/soc/common/socfpga_sip_svc.c
@@ -9,6 +9,7 @@
 #include <assert.h>
 #include <common/debug.h>
 #include <common/runtime_svc.h>
+#include <drivers/delay_timer.h>
 #include <lib/mmio.h>
 #include <tools_share/uuid.h>
 
@@ -799,6 +800,22 @@
 	}
 	return INTEL_SIP_SMC_STATUS_OK;
 }
+
+static void intel_inject_io96b_ecc_err(const uint32_t *syndrome, const uint32_t command)
+{
+	volatile uint64_t atf_ddr_buffer;
+	volatile uint64_t val;
+
+	mmio_write_32(IOSSM_CMD_PARAM, *syndrome);
+	mmio_write_32(IOSSM_CMD_TRIG_OP, command);
+	udelay(IOSSM_ECC_ERR_INJ_DELAY_USECS);
+	atf_ddr_buffer = 0xCAFEBABEFEEDFACE;	/* Write data */
+	memcpy_s((void *)&val, sizeof(val),
+		 (void *)&atf_ddr_buffer, sizeof(atf_ddr_buffer));
+
+	/* Clear response_ready BIT0 of status_register before sending next command. */
+	mmio_clrbits_32(IOSSM_CMD_RESP_STATUS, IOSSM_CMD_STATUS_RESP_READY);
+}
 #endif
 
 #if SIP_SVC_V3
@@ -2194,6 +2211,12 @@
 		SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK, VERSION_MAJOR,
 			 VERSION_MINOR, VERSION_PATCH);
 
+#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
+	case INTEL_SIP_SMC_INJECT_IO96B_ECC_ERR:
+		intel_inject_io96b_ecc_err((uint32_t *)&x1, (uint32_t)x2);
+		SMC_RET1(handle, INTEL_SIP_SMC_STATUS_OK);
+#endif
+
 	default:
 		return socfpga_sip_handler(smc_fid, x1, x2, x3, x4,
 			cookie, handle, flags);