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/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);