Tegra: memctrl_v2: implement MC txn override WAR

This patch sets the Memory Controller's TXN_OVERRIDE registers
for most write clients to CGID_ADR. This ensures ordering is maintained.
In some cases WAW ordering problems could occur. There are different
settings for Tegra version A01 v A02.

Original changes by Alex Waterman <alexw@nvidia.com>

Change-Id: I82ea02afa43a24250ed56985757b83e78e71178c
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
index 27c8789..bc2d7b5 100644
--- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
+++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
@@ -199,6 +199,40 @@
 	mc_make_sec_cfg(GPUSRD2, SECURE, NO_OVERRIDE, DISABLE),
 };
 
+const static mc_txn_override_cfg_t mc_override_cfgs[] = {
+	mc_make_txn_override_cfg(BPMPW, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(EQOSW, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(NVJPGSWR, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(SDMMCWAA, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(MPCOREW, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(SCEDMAW, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(SDMMCW, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(AXISW, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(TSECSWR, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(GPUSWR, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(XUSB_HOSTW, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(TSECSWRB, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(GPUSWR2, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(AONDMAW, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(AONW, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(SESWR, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(BPMPDMAW, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(SDMMCWA, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(HDAW, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(NVDECSWR, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(UFSHCW, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(SATAW, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(ETRW, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(VICSWR, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(NVENCSWR, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(SDMMCWAB, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(ISPWB, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(APEW, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(XUSB_DEVW, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(AFIW, CGID_TAG_ADR),
+	mc_make_txn_override_cfg(SCEW, CGID_TAG_ADR),
+};
+
 /*
  * Init SMMU.
  */
@@ -207,6 +241,8 @@
 	uint32_t val;
 	uint32_t num_overrides = sizeof(streamid_overrides) / sizeof(uint32_t);
 	uint32_t num_sec_cfgs = sizeof(sec_cfgs) / sizeof(mc_streamid_security_cfg_t);
+	uint32_t num_txn_overrides = sizeof(mc_override_cfgs) / sizeof(mc_txn_override_cfg_t);
+	uint32_t tegra_rev;
 	int i;
 
 	INFO("Tegra Memory Controller (v2)\n");
@@ -245,6 +281,42 @@
 	tegra_mc_write_32(MC_SMMU_BYPASS_CONFIG,
 		MC_SMMU_BYPASS_CONFIG_SETTINGS);
 
+	/*
+	 * Set the MC_TXN_OVERRIDE registers for write clients.
+	 */
+	tegra_rev = (mmio_read_32(TEGRA_MISC_BASE + HARDWARE_REVISION_OFFSET) &
+			HARDWARE_MINOR_REVISION_MASK) >> HARDWARE_MINOR_REVISION_SHIFT;
+
+	if (tegra_rev == HARDWARE_REVISION_A01) {
+
+		/* GPU and NVENC settings for rev. A01 */
+		val = tegra_mc_read_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR);
+		val &= ~MC_TXN_OVERRIDE_CGID_TAG_MASK;
+		tegra_mc_write_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR,
+			val | MC_TXN_OVERRIDE_CGID_TAG_ZERO);
+
+		val = tegra_mc_read_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR2);
+		val &= ~MC_TXN_OVERRIDE_CGID_TAG_MASK;
+		tegra_mc_write_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR2,
+			val | MC_TXN_OVERRIDE_CGID_TAG_ZERO);
+
+		val = tegra_mc_read_32(MC_TXN_OVERRIDE_CONFIG_NVENCSWR);
+		val &= ~MC_TXN_OVERRIDE_CGID_TAG_MASK;
+		tegra_mc_write_32(MC_TXN_OVERRIDE_CONFIG_NVENCSWR,
+			val | MC_TXN_OVERRIDE_CGID_TAG_CLIENT_AXI_ID);
+
+	} else {
+
+		/* settings for rev. A02 */
+		for (i = 0; i < num_txn_overrides; i++) {
+			val = tegra_mc_read_32(mc_override_cfgs[i].offset);
+			val &= ~MC_TXN_OVERRIDE_CGID_TAG_MASK;
+			tegra_mc_write_32(mc_override_cfgs[i].offset,
+				val | mc_override_cfgs[i].cgid_tag);
+		}
+
+	}
+
 	/* video memory carveout region */
 	if (video_mem_base) {
 		tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO,
diff --git a/plat/nvidia/tegra/include/drivers/memctrl_v2.h b/plat/nvidia/tegra/include/drivers/memctrl_v2.h
index 0736b59..c1061fe 100644
--- a/plat/nvidia/tegra/include/drivers/memctrl_v2.h
+++ b/plat/nvidia/tegra/include/drivers/memctrl_v2.h
@@ -208,6 +208,107 @@
 						 MC_SMMU_CTRL_TBU_BYPASS_SPL_STREAMID)
 
 /*******************************************************************************
+ * Memory Controller transaction override config registers
+ ******************************************************************************/
+#define MC_TXN_OVERRIDE_CONFIG_HDAR		0x10a8
+#define MC_TXN_OVERRIDE_CONFIG_BPMPW		0x14a0
+#define MC_TXN_OVERRIDE_CONFIG_PTCR		0x1000
+#define MC_TXN_OVERRIDE_CONFIG_NVDISPLAYR	0x1490
+#define MC_TXN_OVERRIDE_CONFIG_EQOSW		0x1478
+#define MC_TXN_OVERRIDE_CONFIG_NVJPGSWR		0x13f8
+#define MC_TXN_OVERRIDE_CONFIG_ISPRA		0x1220
+#define MC_TXN_OVERRIDE_CONFIG_SDMMCWAA		0x1328
+#define MC_TXN_OVERRIDE_CONFIG_VICSRD		0x1360
+#define MC_TXN_OVERRIDE_CONFIG_MPCOREW		0x11c8
+#define MC_TXN_OVERRIDE_CONFIG_GPUSRD		0x12c0
+#define MC_TXN_OVERRIDE_CONFIG_AXISR		0x1460
+#define MC_TXN_OVERRIDE_CONFIG_SCEDMAW		0x14f0
+#define MC_TXN_OVERRIDE_CONFIG_SDMMCW		0x1330
+#define MC_TXN_OVERRIDE_CONFIG_EQOSR		0x1470
+#define MC_TXN_OVERRIDE_CONFIG_APEDMAR		0x14f8
+#define MC_TXN_OVERRIDE_CONFIG_NVENCSRD		0x10e0
+#define MC_TXN_OVERRIDE_CONFIG_SDMMCRAB		0x1318
+#define MC_TXN_OVERRIDE_CONFIG_VICSRD1		0x1510
+#define MC_TXN_OVERRIDE_CONFIG_BPMPDMAR		0x14a8
+#define MC_TXN_OVERRIDE_CONFIG_VIW		0x1390
+#define MC_TXN_OVERRIDE_CONFIG_SDMMCRAA		0x1308
+#define MC_TXN_OVERRIDE_CONFIG_AXISW		0x1468
+#define MC_TXN_OVERRIDE_CONFIG_XUSB_DEVR	0x1260
+#define MC_TXN_OVERRIDE_CONFIG_UFSHCR		0x1480
+#define MC_TXN_OVERRIDE_CONFIG_TSECSWR		0x12a8
+#define MC_TXN_OVERRIDE_CONFIG_GPUSWR		0x12c8
+#define MC_TXN_OVERRIDE_CONFIG_SATAR		0x10f8
+#define MC_TXN_OVERRIDE_CONFIG_XUSB_HOSTW	0x1258
+#define MC_TXN_OVERRIDE_CONFIG_TSECSWRB		0x1438
+#define MC_TXN_OVERRIDE_CONFIG_GPUSRD2		0x1440
+#define MC_TXN_OVERRIDE_CONFIG_SCEDMAR		0x14e8
+#define MC_TXN_OVERRIDE_CONFIG_GPUSWR2		0x1448
+#define MC_TXN_OVERRIDE_CONFIG_AONDMAW		0x14d0
+#define MC_TXN_OVERRIDE_CONFIG_APEDMAW		0x1500
+#define MC_TXN_OVERRIDE_CONFIG_AONW		0x14c0
+#define MC_TXN_OVERRIDE_CONFIG_HOST1XDMAR	0x10b0
+#define MC_TXN_OVERRIDE_CONFIG_ETRR		0x1420
+#define MC_TXN_OVERRIDE_CONFIG_SESWR		0x1408
+#define MC_TXN_OVERRIDE_CONFIG_NVJPGSRD		0x13f0
+#define MC_TXN_OVERRIDE_CONFIG_NVDECSRD		0x13c0
+#define MC_TXN_OVERRIDE_CONFIG_TSECSRDB		0x1430
+#define MC_TXN_OVERRIDE_CONFIG_BPMPDMAW		0x14b0
+#define MC_TXN_OVERRIDE_CONFIG_APER		0x13d0
+#define MC_TXN_OVERRIDE_CONFIG_NVDECSRD1	0x1518
+#define MC_TXN_OVERRIDE_CONFIG_XUSB_HOSTR	0x1250
+#define MC_TXN_OVERRIDE_CONFIG_ISPWA		0x1230
+#define MC_TXN_OVERRIDE_CONFIG_SESRD		0x1400
+#define MC_TXN_OVERRIDE_CONFIG_SCER		0x14d8
+#define MC_TXN_OVERRIDE_CONFIG_AONR		0x14b8
+#define MC_TXN_OVERRIDE_CONFIG_MPCORER		0x1138
+#define MC_TXN_OVERRIDE_CONFIG_SDMMCWA		0x1320
+#define MC_TXN_OVERRIDE_CONFIG_HDAW		0x11a8
+#define MC_TXN_OVERRIDE_CONFIG_NVDECSWR		0x13c8
+#define MC_TXN_OVERRIDE_CONFIG_UFSHCW		0x1488
+#define MC_TXN_OVERRIDE_CONFIG_AONDMAR		0x14c8
+#define MC_TXN_OVERRIDE_CONFIG_SATAW		0x11e8
+#define MC_TXN_OVERRIDE_CONFIG_ETRW		0x1428
+#define MC_TXN_OVERRIDE_CONFIG_VICSWR		0x1368
+#define MC_TXN_OVERRIDE_CONFIG_NVENCSWR		0x1158
+#define MC_TXN_OVERRIDE_CONFIG_AFIR		0x1070
+#define MC_TXN_OVERRIDE_CONFIG_SDMMCWAB		0x1338
+#define MC_TXN_OVERRIDE_CONFIG_SDMMCRA		0x1300
+#define MC_TXN_OVERRIDE_CONFIG_NVDISPLAYR1	0x1508
+#define MC_TXN_OVERRIDE_CONFIG_ISPWB		0x1238
+#define MC_TXN_OVERRIDE_CONFIG_BPMPR		0x1498
+#define MC_TXN_OVERRIDE_CONFIG_APEW		0x13d8
+#define MC_TXN_OVERRIDE_CONFIG_SDMMCR		0x1310
+#define MC_TXN_OVERRIDE_CONFIG_XUSB_DEVW	0x1268
+#define MC_TXN_OVERRIDE_CONFIG_TSECSRD		0x12a0
+#define MC_TXN_OVERRIDE_CONFIG_AFIW		0x1188
+#define MC_TXN_OVERRIDE_CONFIG_SCEW		0x14e0
+
+/*******************************************************************************
+ * Non-SO_DEV transactions override values for CGID_TAG bitfield for the
+ * MC_TXN_OVERRIDE_CONFIG_{module} registers
+ ******************************************************************************/
+#define MC_TXN_OVERRIDE_CGID_TAG_DEFAULT	0
+#define MC_TXN_OVERRIDE_CGID_TAG_CLIENT_AXI_ID	1
+#define MC_TXN_OVERRIDE_CGID_TAG_ZERO		2
+#define MC_TXN_OVERRIDE_CGID_TAG_ADR		3
+#define MC_TXN_OVERRIDE_CGID_TAG_MASK		3
+
+/*******************************************************************************
+ * Structure to hold the transaction override settings to use to override
+ * client inputs
+ ******************************************************************************/
+typedef struct mc_txn_override_cfg {
+	uint32_t offset;
+	uint8_t cgid_tag;
+} mc_txn_override_cfg_t;
+
+#define mc_make_txn_override_cfg(off, val) \
+	{ \
+		.offset = MC_TXN_OVERRIDE_CONFIG_ ## off, \
+		.cgid_tag = MC_TXN_OVERRIDE_ ## val \
+	}
+
+/*******************************************************************************
  * Memory Controller SMMU Global Secure Aux. Configuration Register
  ******************************************************************************/
 #define ARM_SMMU_GSR0_SECURE_ACR		0x10
diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h
index 3983a6b..e74ed16 100644
--- a/plat/nvidia/tegra/include/t186/tegra_def.h
+++ b/plat/nvidia/tegra/include/t186/tegra_def.h
@@ -69,6 +69,10 @@
  * Tegra Miscellanous register constants
  ******************************************************************************/
 #define TEGRA_MISC_BASE			0x00100000
+#define  HARDWARE_REVISION_OFFSET	0x4
+#define  HARDWARE_MINOR_REVISION_MASK	0xf0000
+#define  HARDWARE_MINOR_REVISION_SHIFT	0x10
+#define  HARDWARE_REVISION_A01		1
 
 /*******************************************************************************
  * Tegra Memory Controller constants