feat(mt8188): add secure iommu support

The secure IOMMU has two secure banks: VDO and VPP. Add SiP call to
report the secure bank status in debug build.
About more background, please see:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/include/dt-bindings/memory/mediatek,mt8188-memory-port.h?id=d5cda142d649c690fb0fcf1e29f3df63fbafc442

Change-Id: I7b3319e84391fc6d7f456659f8b8c5d9d1c6ab9d
Signed-off-by: Anan Sun <anan.sun@mediatek.corp-partner.google.com>
Signed-off-by: Kiwi Liu <kiwi.liu@mediatek.corp-partner.google.com>
diff --git a/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.c b/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.c
index 1d6863f..64a10f1 100644
--- a/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.c
+++ b/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.c
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <mtk_iommu_plat.h>
+#include <mtk_iommu_priv.h>
 #include <mtk_mmap_pool.h>
 #include <platform_def.h>
 
@@ -42,7 +42,7 @@
 #define MMU_DEV_PCIE_0		(0)
 #define IFR_CFG_GROUP_NUM	(1)
 
-static struct mtk_smi_larb_config mt8188_larb_cfg[SMI_LARB_NUM] = {
+static struct mtk_smi_larb_config mt8188_larb_cfg[] = {
 	[SMI_L0_ID] = LARB_CFG_ENTRY(SMI_LARB_0_BASE, 7, 0),
 	[SMI_L1_ID] = LARB_CFG_ENTRY(SMI_LARB_1_BASE, 7, 0),
 	[SMI_L2_ID] = LARB_CFG_ENTRY(SMI_LARB_2_BASE, 5, 0),
@@ -80,12 +80,24 @@
 static uint32_t mt8188_ifr_mst_cfg_offs[IFR_CFG_GROUP_NUM] = {
 	PERICFG_AO_IOMMU_1,
 };
-static struct mtk_ifr_mst_config mt8188_ifr_mst_cfg[MMU_DEV_NUM] = {
+static struct mtk_ifr_mst_config mt8188_ifr_mst_cfg[] = {
 	[MMU_DEV_PCIE_0] = IFR_MST_CFG_ENTRY(0, 18),
 };
 
 struct mtk_smi_larb_config *g_larb_cfg = &mt8188_larb_cfg[0];
+const unsigned int g_larb_num = ARRAY_SIZE(mt8188_larb_cfg);
+
+static struct mtk_secure_iommu_config mt8188_secure_iommu_config[] = {
+	SEC_IOMMU_CFG_ENTRY(VDO_SECURE_IOMMU_BASE),
+	SEC_IOMMU_CFG_ENTRY(VPP_SECURE_IOMMU_BASE),
+};
+
+struct mtk_secure_iommu_config *g_sec_iommu_cfg = &mt8188_secure_iommu_config[0];
+const unsigned int g_sec_iommu_num = ARRAY_SIZE(mt8188_secure_iommu_config);
+
 struct mtk_ifr_mst_config *g_ifr_mst_cfg = &mt8188_ifr_mst_cfg[0];
+const unsigned int g_ifr_mst_num = ARRAY_SIZE(mt8188_ifr_mst_cfg);
+
 uint32_t *g_ifr_mst_cfg_base = &mt8188_ifr_mst_cfg_base[0];
 uint32_t *g_ifr_mst_cfg_offs = &mt8188_ifr_mst_cfg_offs[0];
 
diff --git a/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.h b/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.h
index a59e0c7..a3f38a5 100644
--- a/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.h
+++ b/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.h
@@ -7,18 +7,13 @@
 #ifndef IOMMU_PLAT_H
 #define IOMMU_PLAT_H
 
-#include <mtk_iommu_priv.h>
-
 /* mm iommu */
-#define SMI_LARB_NUM	(26)
-extern struct mtk_smi_larb_config *g_larb_cfg;
+#define ATF_MTK_SMI_LARB_CFG_SUPPORT
 
-/* infra iommu */
-#define MMU_DEV_NUM	(1)
-extern struct mtk_ifr_mst_config *g_ifr_mst_cfg;
-extern uint32_t *g_ifr_mst_cfg_base;
-extern uint32_t *g_ifr_mst_cfg_offs;
+/* mm iommu, sec bank dump */
+#define ATF_MTK_IOMMU_CFG_SUPPORT
 
-extern void mtk_infra_iommu_enable_protect(void);
+/* infra iommu */
+#define ATF_MTK_INFRA_MASTER_CFG_SUPPORT
 
 #endif /* IOMMU_PLAT_H */
diff --git a/plat/mediatek/drivers/iommu/mtk_iommu_priv.h b/plat/mediatek/drivers/iommu/mtk_iommu_priv.h
index 3404d31..bae3694 100644
--- a/plat/mediatek/drivers/iommu/mtk_iommu_priv.h
+++ b/plat/mediatek/drivers/iommu/mtk_iommu_priv.h
@@ -9,6 +9,7 @@
 
 #include <common/debug.h>
 #include <lib/mmio.h>
+#include <mtk_iommu_plat.h>
 #include <mtk_sip_svc.h>
 
 #define LARB_CFG_ENTRY(bs, p_nr, dom)			\
@@ -22,9 +23,13 @@
 #define IFR_MST_CFG_ENTRY(idx, bit)	\
 	{ .cfg_addr_idx = (idx), .r_mmu_en_bit = (bit), }
 
+#define SEC_IOMMU_CFG_ENTRY(s_bs)	\
+	{ .base = (s_bs), }
+
 enum IOMMU_ATF_CMD {
 	IOMMU_ATF_CMD_CONFIG_SMI_LARB,		/* For mm master to enable iommu */
 	IOMMU_ATF_CMD_CONFIG_INFRA_IOMMU,	/* For infra master to enable iommu */
+	IOMMU_ATF_CMD_GET_SECURE_IOMMU_STATUS,	/* For secure iommu translation fault report */
 	IOMMU_ATF_CMD_COUNT,
 };
 
@@ -41,4 +46,30 @@
 	uint8_t r_mmu_en_bit;
 };
 
+struct mtk_secure_iommu_config {
+	uint32_t base;
+};
+
+
+#ifdef ATF_MTK_SMI_LARB_CFG_SUPPORT
+/* mm smi larb security feature is used */
+extern struct mtk_smi_larb_config *g_larb_cfg;
+extern const unsigned int g_larb_num;
+#endif
+
+#ifdef ATF_MTK_INFRA_MASTER_CFG_SUPPORT
+/* infra iommu is used */
+extern struct mtk_ifr_mst_config *g_ifr_mst_cfg;
+extern const unsigned int g_ifr_mst_num;
+extern uint32_t *g_ifr_mst_cfg_base;
+extern uint32_t *g_ifr_mst_cfg_offs;
+extern void mtk_infra_iommu_enable_protect(void);
+#endif
+
+#ifdef ATF_MTK_IOMMU_CFG_SUPPORT
+/* secure iommu is used */
+extern struct mtk_secure_iommu_config *g_sec_iommu_cfg;
+extern const unsigned int g_sec_iommu_num;
+#endif
+
 #endif	/* IOMMU_PRIV_H */
diff --git a/plat/mediatek/drivers/iommu/mtk_iommu_smc.c b/plat/mediatek/drivers/iommu/mtk_iommu_smc.c
index e998725..7d70114 100644
--- a/plat/mediatek/drivers/iommu/mtk_iommu_smc.c
+++ b/plat/mediatek/drivers/iommu/mtk_iommu_smc.c
@@ -5,7 +5,7 @@
  */
 
 #include <stddef.h>
-#include <mtk_iommu_plat.h>
+#include <mtk_iommu_priv.h>
 
 /* defination */
 /* smi larb */
@@ -23,12 +23,23 @@
 /* infra master */
 #define IFR_CFG_MMU_EN_MSK(r_bit)	(0x3 << (r_bit))
 
+/* secure iommu */
+#define MMU_INT_CONTROL0		(0x120)
+#define INT_CLR				BIT(12)
+#define MMU_FAULT_ST1			(0x134)
+#define MMU_AXI_0_ERR_MASK		GENMASK(6, 0)
+#define MMU_AXI_FAULT_STATUS(bus)	(0x13c + (bus) * 8)
+#define MMU_AXI_INVLD_PA(bus)		(0x140 + (bus) * 8)
+#define MMU_AXI_INT_ID(bus)		(0x150 + (bus) * 4)
+
 /* smi larb configure */
 /*
  * If multimedia security config is enabled, the SMI config register must be
  * configurated in security world.
  * And the SRAM path is also configurated here to enhance security.
  */
+#ifdef ATF_MTK_SMI_LARB_CFG_SUPPORT
+
 static void mtk_smi_larb_port_config_to_sram(
 				const struct mtk_smi_larb_config *larb,
 				uint32_t port_id)
@@ -55,7 +66,7 @@
 	uint32_t to_sram;
 	uint8_t mmu_en;
 
-	if (larb_id >= SMI_LARB_NUM) {
+	if (larb_id >= g_larb_num) {
 		return MTK_SIP_E_INVALID_PARAM;
 	}
 
@@ -75,6 +86,11 @@
 	return MTK_SIP_E_SUCCESS;
 }
 
+#endif /* ATF_MTK_SMI_LARB_CFG_SUPPORT */
+
+/* infra iommu configure */
+#ifdef ATF_MTK_INFRA_MASTER_CFG_SUPPORT
+
 static int mtk_infra_master_config_sec(uint32_t dev_id_msk, uint32_t enable)
 {
 	const struct mtk_ifr_mst_config *ifr_cfg;
@@ -82,11 +98,11 @@
 
 	mtk_infra_iommu_enable_protect();
 
-	if (dev_id_msk >= BIT(MMU_DEV_NUM)) {
+	if (dev_id_msk >= BIT(g_ifr_mst_num)) {
 		return MTK_SIP_E_INVALID_PARAM;
 	}
 
-	for (dev_id = 0U; dev_id < MMU_DEV_NUM; dev_id++) {
+	for (dev_id = 0U; dev_id < g_ifr_mst_num; dev_id++) {
 		if ((dev_id_msk & BIT(dev_id)) == 0U) {
 			continue;
 		}
@@ -105,10 +121,50 @@
 
 	return MTK_SIP_E_SUCCESS;
 }
+#endif /* ATF_MTK_INFRA_MASTER_CFG_SUPPORT */
+
+/* secure iommu */
+#ifdef ATF_MTK_IOMMU_CFG_SUPPORT
+/* Report secure IOMMU fault status to normal world for the debug version */
+static int mtk_secure_iommu_fault_report(uint32_t sec_mmu_base,
+					 uint32_t *f_sta, uint32_t *f_pa,
+					 uint32_t *f_id)
+{
+	const struct mtk_secure_iommu_config *mmu_cfg = NULL;
+	uint32_t __maybe_unused bus_id, fault_type;
+	uint32_t i;
+	int ret = MTK_SIP_E_NOT_SUPPORTED;
+
+	for (i = 0; i < g_sec_iommu_num; i++) {
+		if (g_sec_iommu_cfg[i].base == sec_mmu_base) {
+			mmu_cfg = &g_sec_iommu_cfg[i];
+			break;
+		}
+	}
+
+	if (!mmu_cfg)
+		return MTK_SIP_E_INVALID_PARAM;
+#if DEBUG
+	fault_type = mmio_read_32(mmu_cfg->base + MMU_FAULT_ST1);
+	bus_id = (fault_type & MMU_AXI_0_ERR_MASK) ? 0 : 1;
+
+	if (f_sta)
+		*f_sta = mmio_read_32(mmu_cfg->base + MMU_AXI_FAULT_STATUS(bus_id));
+	if (f_pa)
+		*f_pa = mmio_read_32(mmu_cfg->base + MMU_AXI_INVLD_PA(bus_id));
+	if (f_id)
+		*f_id = mmio_read_32(mmu_cfg->base + MMU_AXI_INT_ID(bus_id));
+	ret = MTK_SIP_E_SUCCESS;
+#endif
+	mmio_setbits_32(mmu_cfg->base + MMU_INT_CONTROL0, INT_CLR);
+
+	return ret;
+}
+#endif /* ATF_MTK_IOMMU_CFG_SUPPORT */
 
-static u_register_t mtk_iommu_handler(u_register_t x1, u_register_t x2,
-				      u_register_t x3, u_register_t x4,
-				      void *handle, struct smccc_res *smccc_ret)
+u_register_t mtk_iommu_handler(u_register_t x1, u_register_t x2,
+			u_register_t x3, u_register_t x4,
+			void *handle, struct smccc_res *smccc_ret)
 {
 	uint32_t cmd_id = x1, mdl_id = x2, val = x3;
 	int ret = MTK_SIP_E_NOT_SUPPORTED;
@@ -117,12 +173,25 @@
 	(void)handle;
 
 	switch (cmd_id) {
+#ifdef ATF_MTK_SMI_LARB_CFG_SUPPORT
 	case IOMMU_ATF_CMD_CONFIG_SMI_LARB:
 		ret = mtk_smi_larb_port_config_sec(mdl_id, val);
 		break;
+#endif
+#ifdef ATF_MTK_INFRA_MASTER_CFG_SUPPORT
 	case IOMMU_ATF_CMD_CONFIG_INFRA_IOMMU:
 		ret = mtk_infra_master_config_sec(mdl_id, val);
 		break;
+#endif
+#ifdef ATF_MTK_IOMMU_CFG_SUPPORT
+	case IOMMU_ATF_CMD_GET_SECURE_IOMMU_STATUS:
+		(void)val;
+		ret = mtk_secure_iommu_fault_report(mdl_id,
+					(uint32_t *)&smccc_ret->a1,
+					(uint32_t *)&smccc_ret->a2,
+					(uint32_t *)&smccc_ret->a3);
+		break;
+#endif
 	default:
 		break;
 	}
diff --git a/plat/mediatek/drivers/iommu/mtk_iommu_smc.h b/plat/mediatek/drivers/iommu/mtk_iommu_smc.h
new file mode 100644
index 0000000..9537dbe
--- /dev/null
+++ b/plat/mediatek/drivers/iommu/mtk_iommu_smc.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2023, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IOMMU_SMC_H
+#define IOMMU_SMC_H
+
+#include <mtk_sip_svc.h>
+
+u_register_t mtk_iommu_handler(u_register_t x1, u_register_t x2,
+			u_register_t x3, u_register_t x4,
+			void *handle, struct smccc_res *smccc_ret);
+#endif
diff --git a/plat/mediatek/mt8188/include/platform_def.h b/plat/mediatek/mt8188/include/platform_def.h
index 0a7ae6d..71a4e97 100644
--- a/plat/mediatek/mt8188/include/platform_def.h
+++ b/plat/mediatek/mt8188/include/platform_def.h
@@ -107,7 +107,13 @@
 #define CIRQ_SPI_START		(96)
 
 /*******************************************************************************
- * MM IOMMU & SMI related constants
+ * MM IOMMU related constants
+ ******************************************************************************/
+#define VDO_SECURE_IOMMU_BASE	(IO_PHYS + 0x0c028000 + 0x4000)
+#define VPP_SECURE_IOMMU_BASE	(IO_PHYS + 0x04018000 + 0x4000)
+
+/*******************************************************************************
+ * SMI larb constants
  ******************************************************************************/
 #define SMI_LARB_0_BASE		(IO_PHYS + 0x0c022000)
 #define SMI_LARB_1_BASE		(IO_PHYS + 0x0c023000)