Tegra: memctrl: clean MC INT status before exit to bootloader

This patch cleans the Memory controller's interrupt status
register, before exiting to the non-secure world during
cold boot. This is required as we observed that the MC's
arbitration bit is set before exiting the secure world.

Change-Id: Iacd01994d03b3b9cbd7b8a57fe7ab5b04e607a9f
Signed-off-by: Harvey Hsieh <hhsieh@nvidia.com>
diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v1.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v1.c
index 27ad563..92fa273 100644
--- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v1.c
+++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v1.c
@@ -209,3 +209,16 @@
 	/* lock the aperture registers */
 	tegra_mc_write_32(MC_IRAM_REG_CTRL, MC_DISABLE_IRAM_CFG_WRITES);
 }
+
+void tegra_memctrl_clear_pending_interrupts(void)
+{
+	uint32_t mcerr;
+
+	/* check if there are any pending interrupts */
+	mcerr = mmio_read_32(TEGRA_MC_BASE + MC_INTSTATUS);
+
+	if (mcerr != (uint32_t)0U) { /* should not see error here */
+		WARN("MC_INTSTATUS = 0x%x (should be zero)\n", mcerr);
+		mmio_write_32((TEGRA_MC_BASE + MC_INTSTATUS),  mcerr);
+	}
+}
diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
index cfa9581..1b221c2 100644
--- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
+++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
@@ -712,3 +712,8 @@
 {
 	; /* do nothing */
 }
+
+void tegra_memctrl_clear_pending_interrupts(void)
+{
+	; /* do nothing */
+}
diff --git a/plat/nvidia/tegra/common/tegra_bl31_setup.c b/plat/nvidia/tegra/common/tegra_bl31_setup.c
index 30ff0a3..afb10fe 100644
--- a/plat/nvidia/tegra/common/tegra_bl31_setup.c
+++ b/plat/nvidia/tegra/common/tegra_bl31_setup.c
@@ -342,6 +342,15 @@
 void bl31_plat_runtime_setup(void)
 {
 	/*
+	 * During cold boot, it is observed that the arbitration
+	 * bit is set in the Memory controller leading to false
+	 * error interrupts in the non-secure world. To avoid
+	 * this, clean the interrupt status register before
+	 * booting into the non-secure world
+	 */
+	tegra_memctrl_clear_pending_interrupts();
+
+	/*
 	 * During boot, USB3 and flash media (SDMMC/SATA) devices need
 	 * access to IRAM. Because these clients connect to the MC and
 	 * do not have a direct path to the IRAM, the MC implements AHB
diff --git a/plat/nvidia/tegra/include/drivers/memctrl.h b/plat/nvidia/tegra/include/drivers/memctrl.h
index 17427cb..d5ef60d 100644
--- a/plat/nvidia/tegra/include/drivers/memctrl.h
+++ b/plat/nvidia/tegra/include/drivers/memctrl.h
@@ -13,5 +13,6 @@
 void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_in_bytes);
 void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes);
 void tegra_memctrl_disable_ahb_redirection(void);
+void tegra_memctrl_clear_pending_interrupts(void);
 
 #endif /* MEMCTRL_H */
diff --git a/plat/nvidia/tegra/include/t132/tegra_def.h b/plat/nvidia/tegra/include/t132/tegra_def.h
index 1f58caa..fd75fbc 100644
--- a/plat/nvidia/tegra/include/t132/tegra_def.h
+++ b/plat/nvidia/tegra/include/t132/tegra_def.h
@@ -83,6 +83,9 @@
  ******************************************************************************/
 #define TEGRA_MC_BASE			U(0x70019000)
 
+/* Memory Controller Interrupt Status */
+#define MC_INTSTATUS			0x00U
+
 /* TZDRAM carveout configuration registers */
 #define MC_SECURITY_CFG0_0		U(0x70)
 #define MC_SECURITY_CFG1_0		U(0x74)
diff --git a/plat/nvidia/tegra/include/t210/tegra_def.h b/plat/nvidia/tegra/include/t210/tegra_def.h
index b16a129..75919e1 100644
--- a/plat/nvidia/tegra/include/t210/tegra_def.h
+++ b/plat/nvidia/tegra/include/t210/tegra_def.h
@@ -163,6 +163,9 @@
  ******************************************************************************/
 #define TEGRA_MC_BASE			U(0x70019000)
 
+/* Memory Controller Interrupt Status */
+#define MC_INTSTATUS			0x00U
+
 /* TZDRAM carveout configuration registers */
 #define MC_SECURITY_CFG0_0		U(0x70)
 #define MC_SECURITY_CFG1_0		U(0x74)