Tegra: smmu: support for multiple devices

This patch adds flexibility to the code to initialise multiple SMMU
devices. The base address macro name has been changed to make it
explicit that we support multiple SMMUs.

Change-Id: Id4854fb010ebeb699512d79c769de24050c2ad69
Signed-off-by: Pritesh Raithatha <praithatha@nvidia.com>
Signed-off-by: Krishna Reddy <vdumpa@nvidia.com>
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
diff --git a/plat/nvidia/tegra/common/drivers/smmu/smmu.c b/plat/nvidia/tegra/common/drivers/smmu/smmu.c
index abb3408..a57db8b 100644
--- a/plat/nvidia/tegra/common/drivers/smmu/smmu.c
+++ b/plat/nvidia/tegra/common/drivers/smmu/smmu.c
@@ -36,6 +36,52 @@
 #include <string.h>
 #include <tegra_private.h>
 
+/* SMMU IDs currently supported by the driver */
+enum {
+	TEGRA_SMMU0,
+	TEGRA_SMMU1,
+	TEGRA_SMMU2
+};
+
+static uint32_t tegra_smmu_read_32(uint32_t smmu_id, uint32_t off)
+{
+#if defined(TEGRA_SMMU0_BASE)
+	if (smmu_id == TEGRA_SMMU0)
+		return mmio_read_32(TEGRA_SMMU0_BASE + off);
+#endif
+
+#if defined(TEGRA_SMMU1_BASE)
+	if (smmu_id == TEGRA_SMMU1)
+		return mmio_read_32(TEGRA_SMMU1_BASE + off);
+#endif
+
+#if defined(TEGRA_SMMU2_BASE)
+	if (smmu_id == TEGRA_SMMU2)
+		return mmio_read_32(TEGRA_SMMU2_BASE + off);
+#endif
+
+	return 0;
+}
+
+static void tegra_smmu_write_32(uint32_t smmu_id,
+			uint32_t off, uint32_t val)
+{
+#if defined(TEGRA_SMMU0_BASE)
+	if (smmu_id == TEGRA_SMMU0)
+		mmio_write_32(TEGRA_SMMU0_BASE + off, val);
+#endif
+
+#if defined(TEGRA_SMMU1_BASE)
+	if (smmu_id == TEGRA_SMMU1)
+		mmio_write_32(TEGRA_SMMU1_BASE + off, val);
+#endif
+
+#if defined(TEGRA_SMMU2_BASE)
+	if (smmu_id == TEGRA_SMMU2)
+		mmio_write_32(TEGRA_SMMU2_BASE + off, val);
+#endif
+}
+
 /*
  * Save SMMU settings before "System Suspend" to TZDRAM
  */
@@ -50,7 +96,7 @@
 	uint32_t reg_id1, pgshift, cb_size;
 
 	/* sanity check SMMU settings c*/
-	reg_id1 = mmio_read_32((TEGRA_SMMU_BASE + SMMU_GNSR0_IDR1));
+	reg_id1 = mmio_read_32((TEGRA_SMMU0_BASE + SMMU_GNSR0_IDR1));
 	pgshift = (reg_id1 & ID1_PAGESIZE) ? 16 : 12;
 	cb_size = (2 << pgshift) * \
 	(1 << (((reg_id1 >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1));
@@ -87,34 +133,39 @@
  */
 void tegra_smmu_init(void)
 {
-	uint32_t val, i, ctx_base;
+	uint32_t val, cb_idx, smmu_id, ctx_base;
 
-	/* Program the SMMU pagesize and reset CACHE_LOCK bit */
-	val = tegra_smmu_read_32(SMMU_GSR0_SECURE_ACR);
-	val |= SMMU_GSR0_PGSIZE_64K;
-	val &= ~SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
-	tegra_smmu_write_32(SMMU_GSR0_SECURE_ACR, val);
+	for (smmu_id = 0; smmu_id < NUM_SMMU_DEVICES; smmu_id++) {
+		/* Program the SMMU pagesize and reset CACHE_LOCK bit */
+		val = tegra_smmu_read_32(smmu_id, SMMU_GSR0_SECURE_ACR);
+		val |= SMMU_GSR0_PGSIZE_64K;
+		val &= ~SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
+		tegra_smmu_write_32(smmu_id, SMMU_GSR0_SECURE_ACR, val);
 
-	/* reset CACHE LOCK bit for NS Aux. Config. Register */
-	val = tegra_smmu_read_32(SMMU_GNSR_ACR);
-	val &= ~SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
-	tegra_smmu_write_32(SMMU_GNSR_ACR, val);
+		/* reset CACHE LOCK bit for NS Aux. Config. Register */
+		val = tegra_smmu_read_32(smmu_id, SMMU_GNSR_ACR);
+		val &= ~SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
+		tegra_smmu_write_32(smmu_id, SMMU_GNSR_ACR, val);
 
-	/* disable TCU prefetch for all contexts */
-	ctx_base = (SMMU_GSR0_PGSIZE_64K * SMMU_NUM_CONTEXTS) + SMMU_CBn_ACTLR;
-	for (i = 0; i < SMMU_CONTEXT_BANK_MAX_IDX; i++) {
-		val = tegra_smmu_read_32(ctx_base + (SMMU_GSR0_PGSIZE_64K * i));
-		val &= ~SMMU_CBn_ACTLR_CPRE_BIT;
-		tegra_smmu_write_32(ctx_base + (SMMU_GSR0_PGSIZE_64K * i), val);
-	}
+		/* disable TCU prefetch for all contexts */
+		ctx_base = (SMMU_GSR0_PGSIZE_64K * SMMU_NUM_CONTEXTS)
+				+ SMMU_CBn_ACTLR;
+		for (cb_idx = 0; cb_idx < SMMU_CONTEXT_BANK_MAX_IDX; cb_idx++) {
+			val = tegra_smmu_read_32(smmu_id,
+				ctx_base + (SMMU_GSR0_PGSIZE_64K * cb_idx));
+			val &= ~SMMU_CBn_ACTLR_CPRE_BIT;
+			tegra_smmu_write_32(smmu_id, ctx_base +
+				(SMMU_GSR0_PGSIZE_64K * cb_idx), val);
+		}
 
-	/* set CACHE LOCK bit for NS Aux. Config. Register */
-	val = tegra_smmu_read_32(SMMU_GNSR_ACR);
-	val |= SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
-	tegra_smmu_write_32(SMMU_GNSR_ACR, val);
+		/* set CACHE LOCK bit for NS Aux. Config. Register */
+		val = tegra_smmu_read_32(smmu_id, SMMU_GNSR_ACR);
+		val |= SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
+		tegra_smmu_write_32(smmu_id, SMMU_GNSR_ACR, val);
 
-	/* set CACHE LOCK bit for S Aux. Config. Register */
-	val = tegra_smmu_read_32(SMMU_GSR0_SECURE_ACR);
-	val |= SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
-	tegra_smmu_write_32(SMMU_GSR0_SECURE_ACR, val);
+		/* set CACHE LOCK bit for S Aux. Config. Register */
+		val = tegra_smmu_read_32(smmu_id, SMMU_GSR0_SECURE_ACR);
+		val |= SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
+		tegra_smmu_write_32(smmu_id, SMMU_GSR0_SECURE_ACR, val);
+	}
 }
diff --git a/plat/nvidia/tegra/include/drivers/smmu.h b/plat/nvidia/tegra/include/drivers/smmu.h
index a59b06b..61ad5f0 100644
--- a/plat/nvidia/tegra/include/drivers/smmu.h
+++ b/plat/nvidia/tegra/include/drivers/smmu.h
@@ -643,7 +643,7 @@
 
 #define smmu_make_gnsr0_sec_cfg(name) \
 	{ \
-		.reg = TEGRA_SMMU_BASE + SMMU_GNSR0_ ## name, \
+		.reg = TEGRA_SMMU0_BASE + SMMU_GNSR0_ ## name, \
 		.val = 0x00000000, \
 	}
 
@@ -653,37 +653,37 @@
  */
 #define smmu_make_gnsr0_nsec_cfg(name) \
 	{ \
-		.reg = TEGRA_SMMU_BASE + 0x400 + SMMU_GNSR0_ ## name, \
+		.reg = TEGRA_SMMU0_BASE + 0x400 + SMMU_GNSR0_ ## name, \
 		.val = 0x00000000, \
 	}
 
 #define smmu_make_gnsr0_smr_cfg(n) \
 	{ \
-		.reg = TEGRA_SMMU_BASE + SMMU_GNSR0_SMR ## n, \
+		.reg = TEGRA_SMMU0_BASE + SMMU_GNSR0_SMR ## n, \
 		.val = 0x00000000, \
 	}
 
 #define smmu_make_gnsr0_s2cr_cfg(n) \
 	{ \
-		.reg = TEGRA_SMMU_BASE + SMMU_GNSR0_S2CR ## n, \
+		.reg = TEGRA_SMMU0_BASE + SMMU_GNSR0_S2CR ## n, \
 		.val = 0x00000000, \
 	}
 
 #define smmu_make_gnsr1_cbar_cfg(n) \
 	{ \
-		.reg = TEGRA_SMMU_BASE + (1 << PGSHIFT) + SMMU_GNSR1_CBAR ## n, \
+		.reg = TEGRA_SMMU0_BASE + (1 << PGSHIFT) + SMMU_GNSR1_CBAR ## n, \
 		.val = 0x00000000, \
 	}
 
 #define smmu_make_gnsr1_cba2r_cfg(n) \
 	{ \
-		.reg = TEGRA_SMMU_BASE + (1 << PGSHIFT) + SMMU_GNSR1_CBA2R ## n, \
+		.reg = TEGRA_SMMU0_BASE + (1 << PGSHIFT) + SMMU_GNSR1_CBA2R ## n, \
 		.val = 0x00000000, \
 	}
 
 #define make_smmu_cb_cfg(name, n) \
 	{ \
-		.reg = TEGRA_SMMU_BASE + (CB_SIZE >> 1) + (n * (1 << PGSHIFT)) \
+		.reg = TEGRA_SMMU0_BASE + (CB_SIZE >> 1) + (n * (1 << PGSHIFT)) \
 			+ SMMU_CBn_ ## name, \
 		.val = 0x00000000, \
 	}
diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h
index 8a1dd3f..ae11d28 100644
--- a/plat/nvidia/tegra/include/t186/tegra_def.h
+++ b/plat/nvidia/tegra/include/t186/tegra_def.h
@@ -272,7 +272,7 @@
 /*******************************************************************************
  * Tegra SMMU Controller constants
  ******************************************************************************/
-#define TEGRA_SMMU_BASE			0x12000000
+#define TEGRA_SMMU0_BASE		0x12000000
 
 /*******************************************************************************
  * Tegra TZRAM constants
diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c
index 13f867e..e165df1 100644
--- a/plat/nvidia/tegra/soc/t186/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t186/plat_setup.c
@@ -111,10 +111,8 @@
 			MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(TEGRA_ARM_ACTMON_CTR_BASE, 0x20000, /* 128KB - ARM/Denver */
 			MT_DEVICE | MT_RW | MT_SECURE),
-#if ENABLE_SMMU_DEVICE
-	MAP_REGION_FLAT(TEGRA_SMMU_BASE, 0x1000000, /* 64KB */
+	MAP_REGION_FLAT(TEGRA_SMMU0_BASE, 0x1000000, /* 64KB */
 			MT_DEVICE | MT_RW | MT_SECURE),
-#endif
 	{0}
 };
 
diff --git a/plat/nvidia/tegra/soc/t186/platform_t186.mk b/plat/nvidia/tegra/soc/t186/platform_t186.mk
index 85c924b..979dcb1 100644
--- a/plat/nvidia/tegra/soc/t186/platform_t186.mk
+++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk
@@ -44,6 +44,9 @@
 ENABLE_SMMU_DEVICE			:= 1
 $(eval $(call add_define,ENABLE_SMMU_DEVICE))
 
+NUM_SMMU_DEVICES			:= 1
+$(eval $(call add_define,NUM_SMMU_DEVICES))
+
 RESET_TO_BL31				:= 1
 
 PROGRAMMABLE_RESET_ADDRESS		:= 1