iommu.lists.linux-foundation.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/9] arm64: tegra: Prevent early SMMU faults
@ 2021-03-25 13:03 Thierry Reding
  2021-03-25 13:03 ` [PATCH 1/9] memory: tegra: Move internal data structures into separate header Thierry Reding
                   ` (9 more replies)
  0 siblings, 10 replies; 23+ messages in thread
From: Thierry Reding @ 2021-03-25 13:03 UTC (permalink / raw)
  To: Thierry Reding, Will Deacon, Robin Murphy, Joerg Roedel,
	Krzysztof Kozlowski
  Cc: iommu, Jon Hunter, Nicolin Chen, linux-tegra, linux-arm-kernel

From: Thierry Reding <treding@nvidia.com>

Hi,

this is a set of patches that is the result of earlier discussions
regarding early identity mappings that are needed to avoid SMMU faults
during early boot.

The goal here is to avoid early identity mappings altogether and instead
postpone the need for the identity mappings to when devices are attached
to the SMMU. This works by making the SMMU driver coordinate with the
memory controller driver on when to start enforcing SMMU translations.
This makes Tegra behave in a more standard way and pushes the code to
deal with the Tegra-specific programming into the NVIDIA SMMU
implementation.

Patches 1 and 2 are preparatory work that is used in patch 3 to provide
a mechanism to program SID overrides at runtime. Patches 4 and 5 create
the fundamentals in the SMMU driver to support this and also make this
functionality available on Tegra186. Patch 6 hooks the ARM SMMU up to
the memory controller so that the memory overrides can be programmed at
the right time.

Patch 7 extends this mechanism to Tegra186 and patches 8-9 enable all of
this through device tree updates.

The end result is that various peripherals will have SMMU enabled, while
the display controllers will keep using passthrough, as initially set up
by firmware. Once the device tree bindings have been accepted and the
SMMU driver has been updated to create identity mappings for the display
controllers, they can be hooked up to the SMMU and the code in this
series will automatically program the SID overrides to enable SMMU
translations at the right time.

Thierry

Thierry Reding (9):
  memory: tegra: Move internal data structures into separate header
  memory: tegra: Add memory client IDs to tables
  memory: tegra: Implement SID override programming
  iommu/arm-smmu: Implement ->probe_finalize()
  iommu/arm-smmu: tegra: Detect number of instances at runtime
  iommu/arm-smmu: tegra: Implement SID override programming
  iommu/arm-smmu: Use Tegra implementation on Tegra186
  arm64: tegra: Hook up memory controller to SMMU on Tegra186
  arm64: tegra: Enable SMMU support on Tegra194

 arch/arm64/boot/dts/nvidia/tegra186.dtsi     |   2 +
 arch/arm64/boot/dts/nvidia/tegra194.dtsi     |  86 ++++++
 drivers/iommu/arm/arm-smmu/arm-smmu-impl.c   |   3 +-
 drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c |  81 ++++--
 drivers/iommu/arm/arm-smmu/arm-smmu.c        |  17 ++
 drivers/iommu/arm/arm-smmu/arm-smmu.h        |   1 +
 drivers/iommu/tegra-gart.c                   |   2 +-
 drivers/iommu/tegra-smmu.c                   |   2 +-
 drivers/memory/tegra/mc.h                    |   2 +-
 drivers/memory/tegra/tegra186.c              | 288 ++++++++++++++++++-
 include/soc/tegra/mc-internal.h              |  62 ++++
 include/soc/tegra/mc.h                       |  60 +---
 12 files changed, 529 insertions(+), 77 deletions(-)
 create mode 100644 include/soc/tegra/mc-internal.h

-- 
2.30.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 1/9] memory: tegra: Move internal data structures into separate header
  2021-03-25 13:03 [PATCH 0/9] arm64: tegra: Prevent early SMMU faults Thierry Reding
@ 2021-03-25 13:03 ` Thierry Reding
  2021-03-25 15:12   ` Dmitry Osipenko
  2021-03-25 13:03 ` [PATCH 2/9] memory: tegra: Add memory client IDs to tables Thierry Reding
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: Thierry Reding @ 2021-03-25 13:03 UTC (permalink / raw)
  To: Thierry Reding, Will Deacon, Robin Murphy, Joerg Roedel,
	Krzysztof Kozlowski
  Cc: iommu, Jon Hunter, Nicolin Chen, linux-tegra, linux-arm-kernel

From: Thierry Reding <treding@nvidia.com>

From Tegra20 through Tegra210, either the GART or SMMU drivers need
access to the internals of the memory controller driver because they are
tightly coupled (in fact, the GART and SMMU are part of the memory
controller). On later chips, a separate hardware block implements the
SMMU functionality, so this is no longer needed. However, we still want
to reuse some of the existing infrastructure on later chips, so split
the memory controller internals into a separate header file to avoid
conflicts with the implementation on newer chips.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/iommu/tegra-gart.c      |  2 +-
 drivers/iommu/tegra-smmu.c      |  2 +-
 drivers/memory/tegra/mc.h       |  2 +-
 drivers/memory/tegra/tegra186.c | 12 ++++---
 include/soc/tegra/mc-internal.h | 62 +++++++++++++++++++++++++++++++++
 include/soc/tegra/mc.h          | 50 --------------------------
 6 files changed, 72 insertions(+), 58 deletions(-)
 create mode 100644 include/soc/tegra/mc-internal.h

diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c
index 6f130e51f072..716185234b2a 100644
--- a/drivers/iommu/tegra-gart.c
+++ b/drivers/iommu/tegra-gart.c
@@ -17,7 +17,7 @@
 #include <linux/spinlock.h>
 #include <linux/vmalloc.h>
 
-#include <soc/tegra/mc.h>
+#include <soc/tegra/mc-internal.h>
 
 #define GART_REG_BASE		0x24
 #define GART_CONFIG		(0x24 - GART_REG_BASE)
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 602aab98c079..fdb798c62596 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -17,7 +17,7 @@
 #include <linux/dma-mapping.h>
 
 #include <soc/tegra/ahb.h>
-#include <soc/tegra/mc.h>
+#include <soc/tegra/mc-internal.h>
 
 struct tegra_smmu_group {
 	struct list_head list;
diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h
index 1ee34f0da4f7..116bf68325b7 100644
--- a/drivers/memory/tegra/mc.h
+++ b/drivers/memory/tegra/mc.h
@@ -10,7 +10,7 @@
 #include <linux/io.h>
 #include <linux/types.h>
 
-#include <soc/tegra/mc.h>
+#include <soc/tegra/mc-internal.h>
 
 #define MC_INTSTATUS					0x00
 #define MC_INTMASK					0x04
diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c
index e25c954dde2e..aa676c45650b 100644
--- a/drivers/memory/tegra/tegra186.c
+++ b/drivers/memory/tegra/tegra186.c
@@ -9,6 +9,8 @@
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 
+#include <soc/tegra/mc.h>
+
 #if defined(CONFIG_ARCH_TEGRA_186_SOC)
 #include <dt-bindings/memory/tegra186-mc.h>
 #endif
@@ -31,14 +33,14 @@ struct tegra186_mc_soc {
 	unsigned int num_clients;
 };
 
-struct tegra186_mc {
+struct tegra_mc {
 	struct device *dev;
 	void __iomem *regs;
 
 	const struct tegra186_mc_soc *soc;
 };
 
-static void tegra186_mc_program_sid(struct tegra186_mc *mc)
+static void tegra186_mc_program_sid(struct tegra_mc *mc)
 {
 	unsigned int i;
 
@@ -1523,8 +1525,8 @@ static const struct tegra186_mc_soc tegra194_mc_soc = {
 
 static int tegra186_mc_probe(struct platform_device *pdev)
 {
-	struct tegra186_mc *mc;
 	struct resource *res;
+	struct tegra_mc *mc;
 	int err;
 
 	mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
@@ -1552,7 +1554,7 @@ static int tegra186_mc_probe(struct platform_device *pdev)
 
 static int tegra186_mc_remove(struct platform_device *pdev)
 {
-	struct tegra186_mc *mc = platform_get_drvdata(pdev);
+	struct tegra_mc *mc = platform_get_drvdata(pdev);
 
 	of_platform_depopulate(mc->dev);
 
@@ -1577,7 +1579,7 @@ static int __maybe_unused tegra186_mc_suspend(struct device *dev)
 
 static int __maybe_unused tegra186_mc_resume(struct device *dev)
 {
-	struct tegra186_mc *mc = dev_get_drvdata(dev);
+	struct tegra_mc *mc = dev_get_drvdata(dev);
 
 	tegra186_mc_program_sid(mc);
 
diff --git a/include/soc/tegra/mc-internal.h b/include/soc/tegra/mc-internal.h
new file mode 100644
index 000000000000..4f327695d58c
--- /dev/null
+++ b/include/soc/tegra/mc-internal.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2014 NVIDIA Corporation
+ * Copyright (C) 2021 NVIDIA Corporation
+ */
+
+#ifndef __SOC_TEGRA_MC_INTERNAL_H__
+#define __SOC_TEGRA_MC_INTERNAL_H__
+
+#include <soc/tegra/mc.h>
+
+struct tegra_mc_soc {
+	const struct tegra_mc_client *clients;
+	unsigned int num_clients;
+
+	const unsigned long *emem_regs;
+	unsigned int num_emem_regs;
+
+	unsigned int num_address_bits;
+	unsigned int atom_size;
+
+	u8 client_id_mask;
+
+	const struct tegra_smmu_soc *smmu;
+
+	u32 intmask;
+
+	const struct tegra_mc_reset_ops *reset_ops;
+	const struct tegra_mc_reset *resets;
+	unsigned int num_resets;
+
+	const struct tegra_mc_icc_ops *icc_ops;
+
+	int (*init)(struct tegra_mc *mc);
+};
+
+struct tegra_mc {
+	struct device *dev;
+	struct tegra_smmu *smmu;
+	struct gart_device *gart;
+	void __iomem *regs;
+	struct clk *clk;
+	int irq;
+
+	const struct tegra_mc_soc *soc;
+	unsigned long tick;
+
+	struct tegra_mc_timing *timings;
+	unsigned int num_timings;
+
+	struct reset_controller_dev reset;
+
+	struct icc_provider provider;
+
+	spinlock_t lock;
+
+	struct {
+		struct dentry *root;
+	} debugfs;
+};
+
+#endif /* __SOC_TEGRA_MC_INTERNAL_H__ */
diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h
index d2fbe6a8b25b..7be8441c6e9e 100644
--- a/include/soc/tegra/mc.h
+++ b/include/soc/tegra/mc.h
@@ -155,56 +155,6 @@ struct tegra_mc_icc_ops {
 						void *data);
 };
 
-struct tegra_mc_soc {
-	const struct tegra_mc_client *clients;
-	unsigned int num_clients;
-
-	const unsigned long *emem_regs;
-	unsigned int num_emem_regs;
-
-	unsigned int num_address_bits;
-	unsigned int atom_size;
-
-	u8 client_id_mask;
-
-	const struct tegra_smmu_soc *smmu;
-
-	u32 intmask;
-
-	const struct tegra_mc_reset_ops *reset_ops;
-	const struct tegra_mc_reset *resets;
-	unsigned int num_resets;
-
-	const struct tegra_mc_icc_ops *icc_ops;
-
-	int (*init)(struct tegra_mc *mc);
-};
-
-struct tegra_mc {
-	struct device *dev;
-	struct tegra_smmu *smmu;
-	struct gart_device *gart;
-	void __iomem *regs;
-	struct clk *clk;
-	int irq;
-
-	const struct tegra_mc_soc *soc;
-	unsigned long tick;
-
-	struct tegra_mc_timing *timings;
-	unsigned int num_timings;
-
-	struct reset_controller_dev reset;
-
-	struct icc_provider provider;
-
-	spinlock_t lock;
-
-	struct {
-		struct dentry *root;
-	} debugfs;
-};
-
 int tegra_mc_write_emem_configuration(struct tegra_mc *mc, unsigned long rate);
 unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc);
 
-- 
2.30.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 2/9] memory: tegra: Add memory client IDs to tables
  2021-03-25 13:03 [PATCH 0/9] arm64: tegra: Prevent early SMMU faults Thierry Reding
  2021-03-25 13:03 ` [PATCH 1/9] memory: tegra: Move internal data structures into separate header Thierry Reding
@ 2021-03-25 13:03 ` Thierry Reding
  2021-03-25 13:03 ` [PATCH 3/9] memory: tegra: Implement SID override programming Thierry Reding
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Thierry Reding @ 2021-03-25 13:03 UTC (permalink / raw)
  To: Thierry Reding, Will Deacon, Robin Murphy, Joerg Roedel,
	Krzysztof Kozlowski
  Cc: iommu, Jon Hunter, Nicolin Chen, linux-tegra, linux-arm-kernel

From: Thierry Reding <treding@nvidia.com>

The memory client IDs will subsequently be used to program override SIDs
for the given clients depending on the device tree configuration.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/memory/tegra/tegra186.c | 206 ++++++++++++++++++++++++++++++++
 1 file changed, 206 insertions(+)

diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c
index aa676c45650b..efa922d51d83 100644
--- a/drivers/memory/tegra/tegra186.c
+++ b/drivers/memory/tegra/tegra186.c
@@ -21,6 +21,7 @@
 
 struct tegra186_mc_client {
 	const char *name;
+	unsigned int id;
 	unsigned int sid;
 	struct {
 		unsigned int override;
@@ -70,6 +71,7 @@ static void tegra186_mc_program_sid(struct tegra_mc *mc)
 static const struct tegra186_mc_client tegra186_mc_clients[] = {
 	{
 		.name = "ptcr",
+		.id = TEGRA186_MEMORY_CLIENT_PTCR,
 		.sid = TEGRA186_SID_PASSTHROUGH,
 		.regs = {
 			.override = 0x000,
@@ -77,6 +79,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "afir",
+		.id = TEGRA186_MEMORY_CLIENT_AFIR,
 		.sid = TEGRA186_SID_AFI,
 		.regs = {
 			.override = 0x070,
@@ -84,6 +87,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "hdar",
+		.id = TEGRA186_MEMORY_CLIENT_HDAR,
 		.sid = TEGRA186_SID_HDA,
 		.regs = {
 			.override = 0x0a8,
@@ -91,6 +95,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "host1xdmar",
+		.id = TEGRA186_MEMORY_CLIENT_HOST1XDMAR,
 		.sid = TEGRA186_SID_HOST1X,
 		.regs = {
 			.override = 0x0b0,
@@ -99,12 +104,14 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 	}, {
 		.name = "nvencsrd",
 		.sid = TEGRA186_SID_NVENC,
+		.id = TEGRA186_MEMORY_CLIENT_NVENCSRD,
 		.regs = {
 			.override = 0x0e0,
 			.security = 0x0e4,
 		},
 	}, {
 		.name = "satar",
+		.id = TEGRA186_MEMORY_CLIENT_SATAR,
 		.sid = TEGRA186_SID_SATA,
 		.regs = {
 			.override = 0x0f8,
@@ -112,6 +119,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "mpcorer",
+		.id = TEGRA186_MEMORY_CLIENT_MPCORER,
 		.sid = TEGRA186_SID_PASSTHROUGH,
 		.regs = {
 			.override = 0x138,
@@ -119,6 +127,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "nvencswr",
+		.id = TEGRA186_MEMORY_CLIENT_NVENCSWR,
 		.sid = TEGRA186_SID_NVENC,
 		.regs = {
 			.override = 0x158,
@@ -126,6 +135,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "afiw",
+		.id = TEGRA186_MEMORY_CLIENT_AFIW,
 		.sid = TEGRA186_SID_AFI,
 		.regs = {
 			.override = 0x188,
@@ -133,6 +143,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "hdaw",
+		.id = TEGRA186_MEMORY_CLIENT_HDAW,
 		.sid = TEGRA186_SID_HDA,
 		.regs = {
 			.override = 0x1a8,
@@ -140,6 +151,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "mpcorew",
+		.id = TEGRA186_MEMORY_CLIENT_MPCOREW,
 		.sid = TEGRA186_SID_PASSTHROUGH,
 		.regs = {
 			.override = 0x1c8,
@@ -147,6 +159,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "sataw",
+		.id = TEGRA186_MEMORY_CLIENT_SATAW,
 		.sid = TEGRA186_SID_SATA,
 		.regs = {
 			.override = 0x1e8,
@@ -154,6 +167,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "ispra",
+		.id = TEGRA186_MEMORY_CLIENT_ISPRA,
 		.sid = TEGRA186_SID_ISP,
 		.regs = {
 			.override = 0x220,
@@ -161,6 +175,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "ispwa",
+		.id = TEGRA186_MEMORY_CLIENT_ISPWA,
 		.sid = TEGRA186_SID_ISP,
 		.regs = {
 			.override = 0x230,
@@ -168,6 +183,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "ispwb",
+		.id = TEGRA186_MEMORY_CLIENT_ISPWB,
 		.sid = TEGRA186_SID_ISP,
 		.regs = {
 			.override = 0x238,
@@ -175,6 +191,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "xusb_hostr",
+		.id = TEGRA186_MEMORY_CLIENT_XUSB_HOSTR,
 		.sid = TEGRA186_SID_XUSB_HOST,
 		.regs = {
 			.override = 0x250,
@@ -182,6 +199,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "xusb_hostw",
+		.id = TEGRA186_MEMORY_CLIENT_XUSB_HOSTW,
 		.sid = TEGRA186_SID_XUSB_HOST,
 		.regs = {
 			.override = 0x258,
@@ -189,6 +207,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "xusb_devr",
+		.id = TEGRA186_MEMORY_CLIENT_XUSB_DEVR,
 		.sid = TEGRA186_SID_XUSB_DEV,
 		.regs = {
 			.override = 0x260,
@@ -196,6 +215,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "xusb_devw",
+		.id = TEGRA186_MEMORY_CLIENT_XUSB_DEVW,
 		.sid = TEGRA186_SID_XUSB_DEV,
 		.regs = {
 			.override = 0x268,
@@ -203,6 +223,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "tsecsrd",
+		.id = TEGRA186_MEMORY_CLIENT_TSECSRD,
 		.sid = TEGRA186_SID_TSEC,
 		.regs = {
 			.override = 0x2a0,
@@ -210,6 +231,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "tsecswr",
+		.id = TEGRA186_MEMORY_CLIENT_TSECSWR,
 		.sid = TEGRA186_SID_TSEC,
 		.regs = {
 			.override = 0x2a8,
@@ -217,6 +239,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "gpusrd",
+		.id = TEGRA186_MEMORY_CLIENT_GPUSRD,
 		.sid = TEGRA186_SID_GPU,
 		.regs = {
 			.override = 0x2c0,
@@ -224,6 +247,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "gpuswr",
+		.id = TEGRA186_MEMORY_CLIENT_GPUSWR,
 		.sid = TEGRA186_SID_GPU,
 		.regs = {
 			.override = 0x2c8,
@@ -231,6 +255,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "sdmmcra",
+		.id = TEGRA186_MEMORY_CLIENT_SDMMCRA,
 		.sid = TEGRA186_SID_SDMMC1,
 		.regs = {
 			.override = 0x300,
@@ -238,6 +263,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "sdmmcraa",
+		.id = TEGRA186_MEMORY_CLIENT_SDMMCRAA,
 		.sid = TEGRA186_SID_SDMMC2,
 		.regs = {
 			.override = 0x308,
@@ -245,6 +271,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "sdmmcr",
+		.id = TEGRA186_MEMORY_CLIENT_SDMMCR,
 		.sid = TEGRA186_SID_SDMMC3,
 		.regs = {
 			.override = 0x310,
@@ -252,6 +279,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "sdmmcrab",
+		.id = TEGRA186_MEMORY_CLIENT_SDMMCRAB,
 		.sid = TEGRA186_SID_SDMMC4,
 		.regs = {
 			.override = 0x318,
@@ -259,6 +287,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "sdmmcwa",
+		.id = TEGRA186_MEMORY_CLIENT_SDMMCWA,
 		.sid = TEGRA186_SID_SDMMC1,
 		.regs = {
 			.override = 0x320,
@@ -266,6 +295,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "sdmmcwaa",
+		.id = TEGRA186_MEMORY_CLIENT_SDMMCWAA,
 		.sid = TEGRA186_SID_SDMMC2,
 		.regs = {
 			.override = 0x328,
@@ -273,6 +303,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "sdmmcw",
+		.id = TEGRA186_MEMORY_CLIENT_SDMMCW,
 		.sid = TEGRA186_SID_SDMMC3,
 		.regs = {
 			.override = 0x330,
@@ -280,6 +311,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "sdmmcwab",
+		.id = TEGRA186_MEMORY_CLIENT_SDMMCWAB,
 		.sid = TEGRA186_SID_SDMMC4,
 		.regs = {
 			.override = 0x338,
@@ -287,6 +319,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "vicsrd",
+		.id = TEGRA186_MEMORY_CLIENT_VICSRD,
 		.sid = TEGRA186_SID_VIC,
 		.regs = {
 			.override = 0x360,
@@ -294,6 +327,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "vicswr",
+		.id = TEGRA186_MEMORY_CLIENT_VICSWR,
 		.sid = TEGRA186_SID_VIC,
 		.regs = {
 			.override = 0x368,
@@ -301,6 +335,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "viw",
+		.id = TEGRA186_MEMORY_CLIENT_VIW,
 		.sid = TEGRA186_SID_VI,
 		.regs = {
 			.override = 0x390,
@@ -308,6 +343,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "nvdecsrd",
+		.id = TEGRA186_MEMORY_CLIENT_NVDECSRD,
 		.sid = TEGRA186_SID_NVDEC,
 		.regs = {
 			.override = 0x3c0,
@@ -315,6 +351,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "nvdecswr",
+		.id = TEGRA186_MEMORY_CLIENT_NVDECSWR,
 		.sid = TEGRA186_SID_NVDEC,
 		.regs = {
 			.override = 0x3c8,
@@ -322,6 +359,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "aper",
+		.id = TEGRA186_MEMORY_CLIENT_APER,
 		.sid = TEGRA186_SID_APE,
 		.regs = {
 			.override = 0x3d0,
@@ -329,6 +367,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "apew",
+		.id = TEGRA186_MEMORY_CLIENT_APEW,
 		.sid = TEGRA186_SID_APE,
 		.regs = {
 			.override = 0x3d8,
@@ -336,6 +375,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "nvjpgsrd",
+		.id = TEGRA186_MEMORY_CLIENT_NVJPGSRD,
 		.sid = TEGRA186_SID_NVJPG,
 		.regs = {
 			.override = 0x3f0,
@@ -343,6 +383,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "nvjpgswr",
+		.id = TEGRA186_MEMORY_CLIENT_NVJPGSWR,
 		.sid = TEGRA186_SID_NVJPG,
 		.regs = {
 			.override = 0x3f8,
@@ -350,6 +391,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "sesrd",
+		.id = TEGRA186_MEMORY_CLIENT_SESRD,
 		.sid = TEGRA186_SID_SE,
 		.regs = {
 			.override = 0x400,
@@ -357,6 +399,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "seswr",
+		.id = TEGRA186_MEMORY_CLIENT_SESWR,
 		.sid = TEGRA186_SID_SE,
 		.regs = {
 			.override = 0x408,
@@ -364,6 +407,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "etrr",
+		.id = TEGRA186_MEMORY_CLIENT_ETRR,
 		.sid = TEGRA186_SID_ETR,
 		.regs = {
 			.override = 0x420,
@@ -371,6 +415,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "etrw",
+		.id = TEGRA186_MEMORY_CLIENT_ETRW,
 		.sid = TEGRA186_SID_ETR,
 		.regs = {
 			.override = 0x428,
@@ -378,6 +423,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "tsecsrdb",
+		.id = TEGRA186_MEMORY_CLIENT_TSECSRDB,
 		.sid = TEGRA186_SID_TSECB,
 		.regs = {
 			.override = 0x430,
@@ -385,6 +431,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "tsecswrb",
+		.id = TEGRA186_MEMORY_CLIENT_TSECSWRB,
 		.sid = TEGRA186_SID_TSECB,
 		.regs = {
 			.override = 0x438,
@@ -392,6 +439,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "gpusrd2",
+		.id = TEGRA186_MEMORY_CLIENT_GPUSRD2,
 		.sid = TEGRA186_SID_GPU,
 		.regs = {
 			.override = 0x440,
@@ -399,6 +447,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "gpuswr2",
+		.id = TEGRA186_MEMORY_CLIENT_GPUSWR2,
 		.sid = TEGRA186_SID_GPU,
 		.regs = {
 			.override = 0x448,
@@ -406,6 +455,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "axisr",
+		.id = TEGRA186_MEMORY_CLIENT_AXISR,
 		.sid = TEGRA186_SID_GPCDMA_0,
 		.regs = {
 			.override = 0x460,
@@ -413,6 +463,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "axisw",
+		.id = TEGRA186_MEMORY_CLIENT_AXISW,
 		.sid = TEGRA186_SID_GPCDMA_0,
 		.regs = {
 			.override = 0x468,
@@ -420,6 +471,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "eqosr",
+		.id = TEGRA186_MEMORY_CLIENT_EQOSR,
 		.sid = TEGRA186_SID_EQOS,
 		.regs = {
 			.override = 0x470,
@@ -427,6 +479,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "eqosw",
+		.id = TEGRA186_MEMORY_CLIENT_EQOSW,
 		.sid = TEGRA186_SID_EQOS,
 		.regs = {
 			.override = 0x478,
@@ -434,6 +487,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "ufshcr",
+		.id = TEGRA186_MEMORY_CLIENT_UFSHCR,
 		.sid = TEGRA186_SID_UFSHC,
 		.regs = {
 			.override = 0x480,
@@ -441,6 +495,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "ufshcw",
+		.id = TEGRA186_MEMORY_CLIENT_UFSHCW,
 		.sid = TEGRA186_SID_UFSHC,
 		.regs = {
 			.override = 0x488,
@@ -448,6 +503,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "nvdisplayr",
+		.id = TEGRA186_MEMORY_CLIENT_NVDISPLAYR,
 		.sid = TEGRA186_SID_NVDISPLAY,
 		.regs = {
 			.override = 0x490,
@@ -455,6 +511,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "bpmpr",
+		.id = TEGRA186_MEMORY_CLIENT_BPMPR,
 		.sid = TEGRA186_SID_BPMP,
 		.regs = {
 			.override = 0x498,
@@ -462,6 +519,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "bpmpw",
+		.id = TEGRA186_MEMORY_CLIENT_BPMPW,
 		.sid = TEGRA186_SID_BPMP,
 		.regs = {
 			.override = 0x4a0,
@@ -469,6 +527,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "bpmpdmar",
+		.id = TEGRA186_MEMORY_CLIENT_BPMPDMAR,
 		.sid = TEGRA186_SID_BPMP,
 		.regs = {
 			.override = 0x4a8,
@@ -476,6 +535,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "bpmpdmaw",
+		.id = TEGRA186_MEMORY_CLIENT_BPMPDMAW,
 		.sid = TEGRA186_SID_BPMP,
 		.regs = {
 			.override = 0x4b0,
@@ -483,6 +543,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "aonr",
+		.id = TEGRA186_MEMORY_CLIENT_AONR,
 		.sid = TEGRA186_SID_AON,
 		.regs = {
 			.override = 0x4b8,
@@ -490,6 +551,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "aonw",
+		.id = TEGRA186_MEMORY_CLIENT_AONW,
 		.sid = TEGRA186_SID_AON,
 		.regs = {
 			.override = 0x4c0,
@@ -497,6 +559,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "aondmar",
+		.id = TEGRA186_MEMORY_CLIENT_AONDMAR,
 		.sid = TEGRA186_SID_AON,
 		.regs = {
 			.override = 0x4c8,
@@ -504,6 +567,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "aondmaw",
+		.id = TEGRA186_MEMORY_CLIENT_AONDMAW,
 		.sid = TEGRA186_SID_AON,
 		.regs = {
 			.override = 0x4d0,
@@ -511,6 +575,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "scer",
+		.id = TEGRA186_MEMORY_CLIENT_SCER,
 		.sid = TEGRA186_SID_SCE,
 		.regs = {
 			.override = 0x4d8,
@@ -518,6 +583,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "scew",
+		.id = TEGRA186_MEMORY_CLIENT_SCEW,
 		.sid = TEGRA186_SID_SCE,
 		.regs = {
 			.override = 0x4e0,
@@ -525,6 +591,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "scedmar",
+		.id = TEGRA186_MEMORY_CLIENT_SCEDMAR,
 		.sid = TEGRA186_SID_SCE,
 		.regs = {
 			.override = 0x4e8,
@@ -532,6 +599,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "scedmaw",
+		.id = TEGRA186_MEMORY_CLIENT_SCEDMAW,
 		.sid = TEGRA186_SID_SCE,
 		.regs = {
 			.override = 0x4f0,
@@ -539,6 +607,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "apedmar",
+		.id = TEGRA186_MEMORY_CLIENT_APEDMAR,
 		.sid = TEGRA186_SID_APE,
 		.regs = {
 			.override = 0x4f8,
@@ -546,6 +615,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "apedmaw",
+		.id = TEGRA186_MEMORY_CLIENT_APEDMAW,
 		.sid = TEGRA186_SID_APE,
 		.regs = {
 			.override = 0x500,
@@ -553,6 +623,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "nvdisplayr1",
+		.id = TEGRA186_MEMORY_CLIENT_NVDISPLAYR1,
 		.sid = TEGRA186_SID_NVDISPLAY,
 		.regs = {
 			.override = 0x508,
@@ -560,6 +631,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "vicsrd1",
+		.id = TEGRA186_MEMORY_CLIENT_VICSRD1,
 		.sid = TEGRA186_SID_VIC,
 		.regs = {
 			.override = 0x510,
@@ -567,6 +639,7 @@ static const struct tegra186_mc_client tegra186_mc_clients[] = {
 		},
 	}, {
 		.name = "nvdecsrd1",
+		.id = TEGRA186_MEMORY_CLIENT_NVDECSRD1,
 		.sid = TEGRA186_SID_NVDEC,
 		.regs = {
 			.override = 0x518,
@@ -585,6 +658,7 @@ static const struct tegra186_mc_soc tegra186_mc_soc = {
 static const struct tegra186_mc_client tegra194_mc_clients[] = {
 	{
 		.name = "ptcr",
+		.id = TEGRA194_MEMORY_CLIENT_PTCR,
 		.sid = TEGRA194_SID_PASSTHROUGH,
 		.regs = {
 			.override = 0x000,
@@ -592,6 +666,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "miu7r",
+		.id = TEGRA194_MEMORY_CLIENT_MIU7R,
 		.sid = TEGRA194_SID_MIU,
 		.regs = {
 			.override = 0x008,
@@ -599,6 +674,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "miu7w",
+		.id = TEGRA194_MEMORY_CLIENT_MIU7W,
 		.sid = TEGRA194_SID_MIU,
 		.regs = {
 			.override = 0x010,
@@ -606,6 +682,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "hdar",
+		.id = TEGRA194_MEMORY_CLIENT_HDAR,
 		.sid = TEGRA194_SID_HDA,
 		.regs = {
 			.override = 0x0a8,
@@ -613,6 +690,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "host1xdmar",
+		.id = TEGRA194_MEMORY_CLIENT_HOST1XDMAR,
 		.sid = TEGRA194_SID_HOST1X,
 		.regs = {
 			.override = 0x0b0,
@@ -620,6 +698,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "nvencsrd",
+		.id = TEGRA194_MEMORY_CLIENT_NVENCSRD,
 		.sid = TEGRA194_SID_NVENC,
 		.regs = {
 			.override = 0x0e0,
@@ -627,6 +706,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "satar",
+		.id = TEGRA194_MEMORY_CLIENT_SATAR,
 		.sid = TEGRA194_SID_SATA,
 		.regs = {
 			.override = 0x0f8,
@@ -634,6 +714,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "mpcorer",
+		.id = TEGRA194_MEMORY_CLIENT_MPCORER,
 		.sid = TEGRA194_SID_PASSTHROUGH,
 		.regs = {
 			.override = 0x138,
@@ -641,6 +722,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "nvencswr",
+		.id = TEGRA194_MEMORY_CLIENT_NVENCSWR,
 		.sid = TEGRA194_SID_NVENC,
 		.regs = {
 			.override = 0x158,
@@ -648,6 +730,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "hdaw",
+		.id = TEGRA194_MEMORY_CLIENT_HDAW,
 		.sid = TEGRA194_SID_HDA,
 		.regs = {
 			.override = 0x1a8,
@@ -655,6 +738,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "mpcorew",
+		.id = TEGRA194_MEMORY_CLIENT_MPCOREW,
 		.sid = TEGRA194_SID_PASSTHROUGH,
 		.regs = {
 			.override = 0x1c8,
@@ -662,6 +746,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "sataw",
+		.id = TEGRA194_MEMORY_CLIENT_SATAW,
 		.sid = TEGRA194_SID_SATA,
 		.regs = {
 			.override = 0x1e8,
@@ -669,6 +754,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "ispra",
+		.id = TEGRA194_MEMORY_CLIENT_ISPRA,
 		.sid = TEGRA194_SID_ISP,
 		.regs = {
 			.override = 0x220,
@@ -676,6 +762,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "ispfalr",
+		.id = TEGRA194_MEMORY_CLIENT_ISPFALR,
 		.sid = TEGRA194_SID_ISP_FALCON,
 		.regs = {
 			.override = 0x228,
@@ -683,6 +770,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "ispwa",
+		.id = TEGRA194_MEMORY_CLIENT_ISPWA,
 		.sid = TEGRA194_SID_ISP,
 		.regs = {
 			.override = 0x230,
@@ -690,6 +778,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "ispwb",
+		.id = TEGRA194_MEMORY_CLIENT_ISPWB,
 		.sid = TEGRA194_SID_ISP,
 		.regs = {
 			.override = 0x238,
@@ -697,6 +786,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "xusb_hostr",
+		.id = TEGRA194_MEMORY_CLIENT_XUSB_HOSTR,
 		.sid = TEGRA194_SID_XUSB_HOST,
 		.regs = {
 			.override = 0x250,
@@ -704,6 +794,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "xusb_hostw",
+		.id = TEGRA194_MEMORY_CLIENT_XUSB_HOSTW,
 		.sid = TEGRA194_SID_XUSB_HOST,
 		.regs = {
 			.override = 0x258,
@@ -711,6 +802,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "xusb_devr",
+		.id = TEGRA194_MEMORY_CLIENT_XUSB_DEVR,
 		.sid = TEGRA194_SID_XUSB_DEV,
 		.regs = {
 			.override = 0x260,
@@ -718,6 +810,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "xusb_devw",
+		.id = TEGRA194_MEMORY_CLIENT_XUSB_DEVW,
 		.sid = TEGRA194_SID_XUSB_DEV,
 		.regs = {
 			.override = 0x268,
@@ -725,6 +818,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "sdmmcra",
+		.id = TEGRA194_MEMORY_CLIENT_SDMMCRA,
 		.sid = TEGRA194_SID_SDMMC1,
 		.regs = {
 			.override = 0x300,
@@ -732,6 +826,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "sdmmcr",
+		.id = TEGRA194_MEMORY_CLIENT_SDMMCR,
 		.sid = TEGRA194_SID_SDMMC3,
 		.regs = {
 			.override = 0x310,
@@ -739,6 +834,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "sdmmcrab",
+		.id = TEGRA194_MEMORY_CLIENT_SDMMCRAB,
 		.sid = TEGRA194_SID_SDMMC4,
 		.regs = {
 			.override = 0x318,
@@ -746,6 +842,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "sdmmcwa",
+		.id = TEGRA194_MEMORY_CLIENT_SDMMCWA,
 		.sid = TEGRA194_SID_SDMMC1,
 		.regs = {
 			.override = 0x320,
@@ -753,6 +850,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "sdmmcw",
+		.id = TEGRA194_MEMORY_CLIENT_SDMMCW,
 		.sid = TEGRA194_SID_SDMMC3,
 		.regs = {
 			.override = 0x330,
@@ -760,6 +858,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "sdmmcwab",
+		.id = TEGRA194_MEMORY_CLIENT_SDMMCWAB,
 		.sid = TEGRA194_SID_SDMMC4,
 		.regs = {
 			.override = 0x338,
@@ -767,6 +866,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "vicsrd",
+		.id = TEGRA194_MEMORY_CLIENT_VICSRD,
 		.sid = TEGRA194_SID_VIC,
 		.regs = {
 			.override = 0x360,
@@ -774,6 +874,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "vicswr",
+		.id = TEGRA194_MEMORY_CLIENT_VICSWR,
 		.sid = TEGRA194_SID_VIC,
 		.regs = {
 			.override = 0x368,
@@ -781,6 +882,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "viw",
+		.id = TEGRA194_MEMORY_CLIENT_VIW,
 		.sid = TEGRA194_SID_VI,
 		.regs = {
 			.override = 0x390,
@@ -788,6 +890,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "nvdecsrd",
+		.id = TEGRA194_MEMORY_CLIENT_NVDECSRD,
 		.sid = TEGRA194_SID_NVDEC,
 		.regs = {
 			.override = 0x3c0,
@@ -795,6 +898,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "nvdecswr",
+		.id = TEGRA194_MEMORY_CLIENT_NVDECSWR,
 		.sid = TEGRA194_SID_NVDEC,
 		.regs = {
 			.override = 0x3c8,
@@ -802,6 +906,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "aper",
+		.id = TEGRA194_MEMORY_CLIENT_APER,
 		.sid = TEGRA194_SID_APE,
 		.regs = {
 			.override = 0x3c0,
@@ -809,6 +914,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "apew",
+		.id = TEGRA194_MEMORY_CLIENT_APEW,
 		.sid = TEGRA194_SID_APE,
 		.regs = {
 			.override = 0x3d0,
@@ -816,6 +922,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "nvjpgsrd",
+		.id = TEGRA194_MEMORY_CLIENT_NVJPGSRD,
 		.sid = TEGRA194_SID_NVJPG,
 		.regs = {
 			.override = 0x3f0,
@@ -823,6 +930,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "nvjpgswr",
+		.id = TEGRA194_MEMORY_CLIENT_NVJPGSWR,
 		.sid = TEGRA194_SID_NVJPG,
 		.regs = {
 			.override = 0x3f0,
@@ -831,12 +939,14 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 	}, {
 		.name = "axiapr",
 		.sid = TEGRA194_SID_PASSTHROUGH,
+		.id = TEGRA194_MEMORY_CLIENT_AXIAPR,
 		.regs = {
 			.override = 0x410,
 			.security = 0x414,
 		},
 	}, {
 		.name = "axiapw",
+		.id = TEGRA194_MEMORY_CLIENT_AXIAPW,
 		.sid = TEGRA194_SID_PASSTHROUGH,
 		.regs = {
 			.override = 0x418,
@@ -844,6 +954,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "etrr",
+		.id = TEGRA194_MEMORY_CLIENT_ETRR,
 		.sid = TEGRA194_SID_ETR,
 		.regs = {
 			.override = 0x420,
@@ -851,6 +962,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "etrw",
+		.id = TEGRA194_MEMORY_CLIENT_ETRW,
 		.sid = TEGRA194_SID_ETR,
 		.regs = {
 			.override = 0x428,
@@ -858,6 +970,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "axisr",
+		.id = TEGRA194_MEMORY_CLIENT_AXISR,
 		.sid = TEGRA194_SID_PASSTHROUGH,
 		.regs = {
 			.override = 0x460,
@@ -865,6 +978,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "axisw",
+		.id = TEGRA194_MEMORY_CLIENT_AXISW,
 		.sid = TEGRA194_SID_PASSTHROUGH,
 		.regs = {
 			.override = 0x468,
@@ -872,6 +986,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "eqosr",
+		.id = TEGRA194_MEMORY_CLIENT_EQOSR,
 		.sid = TEGRA194_SID_EQOS,
 		.regs = {
 			.override = 0x470,
@@ -880,12 +995,14 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 	}, {
 		.name = "eqosw",
 		.sid = TEGRA194_SID_EQOS,
+		.id = TEGRA194_MEMORY_CLIENT_EQOSW,
 		.regs = {
 			.override = 0x478,
 			.security = 0x47c,
 		},
 	}, {
 		.name = "ufshcr",
+		.id = TEGRA194_MEMORY_CLIENT_UFSHCR,
 		.sid = TEGRA194_SID_UFSHC,
 		.regs = {
 			.override = 0x480,
@@ -893,6 +1010,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "ufshcw",
+		.id = TEGRA194_MEMORY_CLIENT_UFSHCW,
 		.sid = TEGRA194_SID_UFSHC,
 		.regs = {
 			.override = 0x488,
@@ -900,6 +1018,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "nvdisplayr",
+		.id = TEGRA194_MEMORY_CLIENT_NVDISPLAYR,
 		.sid = TEGRA194_SID_NVDISPLAY,
 		.regs = {
 			.override = 0x490,
@@ -907,6 +1026,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "bpmpr",
+		.id = TEGRA194_MEMORY_CLIENT_BPMPR,
 		.sid = TEGRA194_SID_BPMP,
 		.regs = {
 			.override = 0x498,
@@ -914,6 +1034,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "bpmpw",
+		.id = TEGRA194_MEMORY_CLIENT_BPMPW,
 		.sid = TEGRA194_SID_BPMP,
 		.regs = {
 			.override = 0x4a0,
@@ -921,6 +1042,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "bpmpdmar",
+		.id = TEGRA194_MEMORY_CLIENT_BPMPDMAR,
 		.sid = TEGRA194_SID_BPMP,
 		.regs = {
 			.override = 0x4a8,
@@ -928,6 +1050,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "bpmpdmaw",
+		.id = TEGRA194_MEMORY_CLIENT_BPMPDMAW,
 		.sid = TEGRA194_SID_BPMP,
 		.regs = {
 			.override = 0x4b0,
@@ -935,6 +1058,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "aonr",
+		.id = TEGRA194_MEMORY_CLIENT_AONR,
 		.sid = TEGRA194_SID_AON,
 		.regs = {
 			.override = 0x4b8,
@@ -942,6 +1066,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "aonw",
+		.id = TEGRA194_MEMORY_CLIENT_AONW,
 		.sid = TEGRA194_SID_AON,
 		.regs = {
 			.override = 0x4c0,
@@ -949,6 +1074,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "aondmar",
+		.id = TEGRA194_MEMORY_CLIENT_AONDMAR,
 		.sid = TEGRA194_SID_AON,
 		.regs = {
 			.override = 0x4c8,
@@ -956,6 +1082,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "aondmaw",
+		.id = TEGRA194_MEMORY_CLIENT_AONDMAW,
 		.sid = TEGRA194_SID_AON,
 		.regs = {
 			.override = 0x4d0,
@@ -963,6 +1090,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "scer",
+		.id = TEGRA194_MEMORY_CLIENT_SCER,
 		.sid = TEGRA194_SID_SCE,
 		.regs = {
 			.override = 0x4d8,
@@ -970,6 +1098,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "scew",
+		.id = TEGRA194_MEMORY_CLIENT_SCEW,
 		.sid = TEGRA194_SID_SCE,
 		.regs = {
 			.override = 0x4e0,
@@ -977,6 +1106,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "scedmar",
+		.id = TEGRA194_MEMORY_CLIENT_SCEDMAR,
 		.sid = TEGRA194_SID_SCE,
 		.regs = {
 			.override = 0x4e8,
@@ -984,6 +1114,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "scedmaw",
+		.id = TEGRA194_MEMORY_CLIENT_SCEDMAW,
 		.sid = TEGRA194_SID_SCE,
 		.regs = {
 			.override = 0x4f0,
@@ -991,6 +1122,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "apedmar",
+		.id = TEGRA194_MEMORY_CLIENT_APEDMAR,
 		.sid = TEGRA194_SID_APE,
 		.regs = {
 			.override = 0x4f8,
@@ -998,6 +1130,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "apedmaw",
+		.id = TEGRA194_MEMORY_CLIENT_APEDMAW,
 		.sid = TEGRA194_SID_APE,
 		.regs = {
 			.override = 0x500,
@@ -1005,6 +1138,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "nvdisplayr1",
+		.id = TEGRA194_MEMORY_CLIENT_NVDISPLAYR1,
 		.sid = TEGRA194_SID_NVDISPLAY,
 		.regs = {
 			.override = 0x508,
@@ -1012,6 +1146,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "vicsrd1",
+		.id = TEGRA194_MEMORY_CLIENT_VICSRD1,
 		.sid = TEGRA194_SID_VIC,
 		.regs = {
 			.override = 0x510,
@@ -1019,6 +1154,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "nvdecsrd1",
+		.id = TEGRA194_MEMORY_CLIENT_NVDECSRD1,
 		.sid = TEGRA194_SID_NVDEC,
 		.regs = {
 			.override = 0x518,
@@ -1026,6 +1162,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "miu0r",
+		.id = TEGRA194_MEMORY_CLIENT_MIU0R,
 		.sid = TEGRA194_SID_MIU,
 		.regs = {
 			.override = 0x530,
@@ -1034,12 +1171,14 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 	}, {
 		.name = "miu0w",
 		.sid = TEGRA194_SID_MIU,
+		.id = TEGRA194_MEMORY_CLIENT_MIU0W,
 		.regs = {
 			.override = 0x538,
 			.security = 0x53c,
 		},
 	}, {
 		.name = "miu1r",
+		.id = TEGRA194_MEMORY_CLIENT_MIU1R,
 		.sid = TEGRA194_SID_MIU,
 		.regs = {
 			.override = 0x540,
@@ -1047,6 +1186,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "miu1w",
+		.id = TEGRA194_MEMORY_CLIENT_MIU1W,
 		.sid = TEGRA194_SID_MIU,
 		.regs = {
 			.override = 0x548,
@@ -1054,6 +1194,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "miu2r",
+		.id = TEGRA194_MEMORY_CLIENT_MIU2R,
 		.sid = TEGRA194_SID_MIU,
 		.regs = {
 			.override = 0x570,
@@ -1061,6 +1202,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "miu2w",
+		.id = TEGRA194_MEMORY_CLIENT_MIU2W,
 		.sid = TEGRA194_SID_MIU,
 		.regs = {
 			.override = 0x578,
@@ -1068,6 +1210,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "miu3r",
+		.id = TEGRA194_MEMORY_CLIENT_MIU3R,
 		.sid = TEGRA194_SID_MIU,
 		.regs = {
 			.override = 0x580,
@@ -1075,6 +1218,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "miu3w",
+		.id = TEGRA194_MEMORY_CLIENT_MIU3W,
 		.sid = TEGRA194_SID_MIU,
 		.regs = {
 			.override = 0x588,
@@ -1082,6 +1226,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "miu4r",
+		.id = TEGRA194_MEMORY_CLIENT_MIU4R,
 		.sid = TEGRA194_SID_MIU,
 		.regs = {
 			.override = 0x590,
@@ -1089,6 +1234,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "miu4w",
+		.id = TEGRA194_MEMORY_CLIENT_MIU4W,
 		.sid = TEGRA194_SID_MIU,
 		.regs = {
 			.override = 0x598,
@@ -1096,6 +1242,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "dpmur",
+		.id = TEGRA194_MEMORY_CLIENT_DPMUR,
 		.sid = TEGRA194_SID_PASSTHROUGH,
 		.regs = {
 			.override = 0x598,
@@ -1103,6 +1250,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "vifalr",
+		.id = TEGRA194_MEMORY_CLIENT_VIFALR,
 		.sid = TEGRA194_SID_VI_FALCON,
 		.regs = {
 			.override = 0x5e0,
@@ -1110,6 +1258,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "vifalw",
+		.id = TEGRA194_MEMORY_CLIENT_VIFALW,
 		.sid = TEGRA194_SID_VI_FALCON,
 		.regs = {
 			.override = 0x5e8,
@@ -1117,6 +1266,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "dla0rda",
+		.id = TEGRA194_MEMORY_CLIENT_DLA0RDA,
 		.sid = TEGRA194_SID_NVDLA0,
 		.regs = {
 			.override = 0x5f0,
@@ -1124,6 +1274,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "dla0falrdb",
+		.id = TEGRA194_MEMORY_CLIENT_DLA0FALRDB,
 		.sid = TEGRA194_SID_NVDLA0,
 		.regs = {
 			.override = 0x5f8,
@@ -1131,6 +1282,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "dla0wra",
+		.id = TEGRA194_MEMORY_CLIENT_DLA0WRA,
 		.sid = TEGRA194_SID_NVDLA0,
 		.regs = {
 			.override = 0x600,
@@ -1138,6 +1290,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "dla0falwrb",
+		.id = TEGRA194_MEMORY_CLIENT_DLA0FALWRB,
 		.sid = TEGRA194_SID_NVDLA0,
 		.regs = {
 			.override = 0x608,
@@ -1145,6 +1298,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "dla1rda",
+		.id = TEGRA194_MEMORY_CLIENT_DLA1RDA,
 		.sid = TEGRA194_SID_NVDLA1,
 		.regs = {
 			.override = 0x610,
@@ -1152,6 +1306,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "dla1falrdb",
+		.id = TEGRA194_MEMORY_CLIENT_DLA1FALRDB,
 		.sid = TEGRA194_SID_NVDLA1,
 		.regs = {
 			.override = 0x618,
@@ -1159,6 +1314,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "dla1wra",
+		.id = TEGRA194_MEMORY_CLIENT_DLA1WRA,
 		.sid = TEGRA194_SID_NVDLA1,
 		.regs = {
 			.override = 0x620,
@@ -1166,6 +1322,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "dla1falwrb",
+		.id = TEGRA194_MEMORY_CLIENT_DLA1FALWRB,
 		.sid = TEGRA194_SID_NVDLA1,
 		.regs = {
 			.override = 0x628,
@@ -1173,6 +1330,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pva0rda",
+		.id = TEGRA194_MEMORY_CLIENT_PVA0RDA,
 		.sid = TEGRA194_SID_PVA0,
 		.regs = {
 			.override = 0x630,
@@ -1180,6 +1338,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pva0rdb",
+		.id = TEGRA194_MEMORY_CLIENT_PVA0RDB,
 		.sid = TEGRA194_SID_PVA0,
 		.regs = {
 			.override = 0x638,
@@ -1187,6 +1346,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pva0rdc",
+		.id = TEGRA194_MEMORY_CLIENT_PVA0RDC,
 		.sid = TEGRA194_SID_PVA0,
 		.regs = {
 			.override = 0x640,
@@ -1194,6 +1354,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pva0wra",
+		.id = TEGRA194_MEMORY_CLIENT_PVA0WRA,
 		.sid = TEGRA194_SID_PVA0,
 		.regs = {
 			.override = 0x648,
@@ -1201,6 +1362,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pva0wrb",
+		.id = TEGRA194_MEMORY_CLIENT_PVA0WRB,
 		.sid = TEGRA194_SID_PVA0,
 		.regs = {
 			.override = 0x650,
@@ -1208,6 +1370,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pva0wrc",
+		.id = TEGRA194_MEMORY_CLIENT_PVA0WRC,
 		.sid = TEGRA194_SID_PVA0,
 		.regs = {
 			.override = 0x658,
@@ -1215,6 +1378,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pva1rda",
+		.id = TEGRA194_MEMORY_CLIENT_PVA1RDA,
 		.sid = TEGRA194_SID_PVA1,
 		.regs = {
 			.override = 0x660,
@@ -1222,6 +1386,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pva1rdb",
+		.id = TEGRA194_MEMORY_CLIENT_PVA1RDB,
 		.sid = TEGRA194_SID_PVA1,
 		.regs = {
 			.override = 0x668,
@@ -1229,6 +1394,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pva1rdc",
+		.id = TEGRA194_MEMORY_CLIENT_PVA1RDC,
 		.sid = TEGRA194_SID_PVA1,
 		.regs = {
 			.override = 0x670,
@@ -1236,6 +1402,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pva1wra",
+		.id = TEGRA194_MEMORY_CLIENT_PVA1WRA,
 		.sid = TEGRA194_SID_PVA1,
 		.regs = {
 			.override = 0x678,
@@ -1243,6 +1410,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pva1wrb",
+		.id = TEGRA194_MEMORY_CLIENT_PVA1WRB,
 		.sid = TEGRA194_SID_PVA1,
 		.regs = {
 			.override = 0x680,
@@ -1250,6 +1418,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pva1wrc",
+		.id = TEGRA194_MEMORY_CLIENT_PVA1WRC,
 		.sid = TEGRA194_SID_PVA1,
 		.regs = {
 			.override = 0x688,
@@ -1257,6 +1426,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "rcer",
+		.id = TEGRA194_MEMORY_CLIENT_RCER,
 		.sid = TEGRA194_SID_RCE,
 		.regs = {
 			.override = 0x690,
@@ -1264,6 +1434,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "rcew",
+		.id = TEGRA194_MEMORY_CLIENT_RCEW,
 		.sid = TEGRA194_SID_RCE,
 		.regs = {
 			.override = 0x698,
@@ -1271,6 +1442,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "rcedmar",
+		.id = TEGRA194_MEMORY_CLIENT_RCEDMAR,
 		.sid = TEGRA194_SID_RCE,
 		.regs = {
 			.override = 0x6a0,
@@ -1278,6 +1450,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "rcedmaw",
+		.id = TEGRA194_MEMORY_CLIENT_RCEDMAW,
 		.sid = TEGRA194_SID_RCE,
 		.regs = {
 			.override = 0x6a8,
@@ -1285,6 +1458,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "nvenc1srd",
+		.id = TEGRA194_MEMORY_CLIENT_NVENC1SRD,
 		.sid = TEGRA194_SID_NVENC1,
 		.regs = {
 			.override = 0x6b0,
@@ -1292,6 +1466,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "nvenc1swr",
+		.id = TEGRA194_MEMORY_CLIENT_NVENC1SWR,
 		.sid = TEGRA194_SID_NVENC1,
 		.regs = {
 			.override = 0x6b8,
@@ -1299,6 +1474,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pcie0r",
+		.id = TEGRA194_MEMORY_CLIENT_PCIE0R,
 		.sid = TEGRA194_SID_PCIE0,
 		.regs = {
 			.override = 0x6c0,
@@ -1306,6 +1482,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pcie0w",
+		.id = TEGRA194_MEMORY_CLIENT_PCIE0W,
 		.sid = TEGRA194_SID_PCIE0,
 		.regs = {
 			.override = 0x6c8,
@@ -1313,6 +1490,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pcie1r",
+		.id = TEGRA194_MEMORY_CLIENT_PCIE1R,
 		.sid = TEGRA194_SID_PCIE1,
 		.regs = {
 			.override = 0x6d0,
@@ -1320,6 +1498,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pcie1w",
+		.id = TEGRA194_MEMORY_CLIENT_PCIE1W,
 		.sid = TEGRA194_SID_PCIE1,
 		.regs = {
 			.override = 0x6d8,
@@ -1327,6 +1506,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pcie2ar",
+		.id = TEGRA194_MEMORY_CLIENT_PCIE2AR,
 		.sid = TEGRA194_SID_PCIE2,
 		.regs = {
 			.override = 0x6e0,
@@ -1334,6 +1514,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pcie2aw",
+		.id = TEGRA194_MEMORY_CLIENT_PCIE2AW,
 		.sid = TEGRA194_SID_PCIE2,
 		.regs = {
 			.override = 0x6e8,
@@ -1341,6 +1522,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pcie3r",
+		.id = TEGRA194_MEMORY_CLIENT_PCIE3R,
 		.sid = TEGRA194_SID_PCIE3,
 		.regs = {
 			.override = 0x6f0,
@@ -1348,6 +1530,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pcie3w",
+		.id = TEGRA194_MEMORY_CLIENT_PCIE3W,
 		.sid = TEGRA194_SID_PCIE3,
 		.regs = {
 			.override = 0x6f8,
@@ -1355,6 +1538,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pcie4r",
+		.id = TEGRA194_MEMORY_CLIENT_PCIE4R,
 		.sid = TEGRA194_SID_PCIE4,
 		.regs = {
 			.override = 0x700,
@@ -1362,6 +1546,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pcie4w",
+		.id = TEGRA194_MEMORY_CLIENT_PCIE4W,
 		.sid = TEGRA194_SID_PCIE4,
 		.regs = {
 			.override = 0x708,
@@ -1369,6 +1554,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pcie5r",
+		.id = TEGRA194_MEMORY_CLIENT_PCIE5R,
 		.sid = TEGRA194_SID_PCIE5,
 		.regs = {
 			.override = 0x710,
@@ -1376,6 +1562,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pcie5w",
+		.id = TEGRA194_MEMORY_CLIENT_PCIE5W,
 		.sid = TEGRA194_SID_PCIE5,
 		.regs = {
 			.override = 0x718,
@@ -1383,6 +1570,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "ispfalw",
+		.id = TEGRA194_MEMORY_CLIENT_ISPFALW,
 		.sid = TEGRA194_SID_ISP_FALCON,
 		.regs = {
 			.override = 0x720,
@@ -1390,6 +1578,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "dla0rda1",
+		.id = TEGRA194_MEMORY_CLIENT_DLA0RDA1,
 		.sid = TEGRA194_SID_NVDLA0,
 		.regs = {
 			.override = 0x748,
@@ -1397,6 +1586,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "dla1rda1",
+		.id = TEGRA194_MEMORY_CLIENT_DLA1RDA1,
 		.sid = TEGRA194_SID_NVDLA1,
 		.regs = {
 			.override = 0x750,
@@ -1404,6 +1594,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pva0rda1",
+		.id = TEGRA194_MEMORY_CLIENT_PVA0RDA1,
 		.sid = TEGRA194_SID_PVA0,
 		.regs = {
 			.override = 0x758,
@@ -1411,6 +1602,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pva0rdb1",
+		.id = TEGRA194_MEMORY_CLIENT_PVA0RDB1,
 		.sid = TEGRA194_SID_PVA0,
 		.regs = {
 			.override = 0x760,
@@ -1418,6 +1610,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pva1rda1",
+		.id = TEGRA194_MEMORY_CLIENT_PVA1RDA1,
 		.sid = TEGRA194_SID_PVA1,
 		.regs = {
 			.override = 0x768,
@@ -1425,6 +1618,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pva1rdb1",
+		.id = TEGRA194_MEMORY_CLIENT_PVA1RDB1,
 		.sid = TEGRA194_SID_PVA1,
 		.regs = {
 			.override = 0x770,
@@ -1432,6 +1626,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pcie5r1",
+		.id = TEGRA194_MEMORY_CLIENT_PCIE5R1,
 		.sid = TEGRA194_SID_PCIE5,
 		.regs = {
 			.override = 0x778,
@@ -1439,6 +1634,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "nvencsrd1",
+		.id = TEGRA194_MEMORY_CLIENT_NVENCSRD1,
 		.sid = TEGRA194_SID_NVENC,
 		.regs = {
 			.override = 0x780,
@@ -1446,6 +1642,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "nvenc1srd1",
+		.id = TEGRA194_MEMORY_CLIENT_NVENC1SRD1,
 		.sid = TEGRA194_SID_NVENC1,
 		.regs = {
 			.override = 0x788,
@@ -1453,6 +1650,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "ispra1",
+		.id = TEGRA194_MEMORY_CLIENT_ISPRA1,
 		.sid = TEGRA194_SID_ISP,
 		.regs = {
 			.override = 0x790,
@@ -1460,6 +1658,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "pcie0r1",
+		.id = TEGRA194_MEMORY_CLIENT_PCIE0R1,
 		.sid = TEGRA194_SID_PCIE0,
 		.regs = {
 			.override = 0x798,
@@ -1467,6 +1666,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "nvdec1srd",
+		.id = TEGRA194_MEMORY_CLIENT_NVDEC1SRD,
 		.sid = TEGRA194_SID_NVDEC1,
 		.regs = {
 			.override = 0x7c8,
@@ -1474,6 +1674,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "nvdec1srd1",
+		.id = TEGRA194_MEMORY_CLIENT_NVDEC1SRD1,
 		.sid = TEGRA194_SID_NVDEC1,
 		.regs = {
 			.override = 0x7d0,
@@ -1481,6 +1682,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "nvdec1swr",
+		.id = TEGRA194_MEMORY_CLIENT_NVDEC1SWR,
 		.sid = TEGRA194_SID_NVDEC1,
 		.regs = {
 			.override = 0x7d8,
@@ -1488,6 +1690,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "miu5r",
+		.id = TEGRA194_MEMORY_CLIENT_MIU5R,
 		.sid = TEGRA194_SID_MIU,
 		.regs = {
 			.override = 0x7e0,
@@ -1495,6 +1698,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "miu5w",
+		.id = TEGRA194_MEMORY_CLIENT_MIU5W,
 		.sid = TEGRA194_SID_MIU,
 		.regs = {
 			.override = 0x7e8,
@@ -1502,6 +1706,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "miu6r",
+		.id = TEGRA194_MEMORY_CLIENT_MIU6R,
 		.sid = TEGRA194_SID_MIU,
 		.regs = {
 			.override = 0x7f0,
@@ -1509,6 +1714,7 @@ static const struct tegra186_mc_client tegra194_mc_clients[] = {
 		},
 	}, {
 		.name = "miu6w",
+		.id = TEGRA194_MEMORY_CLIENT_MIU6W,
 		.sid = TEGRA194_SID_MIU,
 		.regs = {
 			.override = 0x7f8,
-- 
2.30.2


_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 3/9] memory: tegra: Implement SID override programming
  2021-03-25 13:03 [PATCH 0/9] arm64: tegra: Prevent early SMMU faults Thierry Reding
  2021-03-25 13:03 ` [PATCH 1/9] memory: tegra: Move internal data structures into separate header Thierry Reding
  2021-03-25 13:03 ` [PATCH 2/9] memory: tegra: Add memory client IDs to tables Thierry Reding
@ 2021-03-25 13:03 ` Thierry Reding
  2021-03-25 14:27   ` Robin Murphy
  2021-03-25 13:03 ` [PATCH 4/9] iommu/arm-smmu: Implement ->probe_finalize() Thierry Reding
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: Thierry Reding @ 2021-03-25 13:03 UTC (permalink / raw)
  To: Thierry Reding, Will Deacon, Robin Murphy, Joerg Roedel,
	Krzysztof Kozlowski
  Cc: iommu, Jon Hunter, Nicolin Chen, linux-tegra, linux-arm-kernel

From: Thierry Reding <treding@nvidia.com>

Instead of programming all SID overrides during early boot, perform the
operation on-demand after the SMMU translations have been set up for a
device. This reuses data from device tree to match memory clients for a
device and programs the SID specified in device tree, which corresponds
to the SID used for the SMMU context banks for the device.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/memory/tegra/tegra186.c | 70 +++++++++++++++++++++++++++++++++
 include/soc/tegra/mc.h          | 10 +++++
 2 files changed, 80 insertions(+)

diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c
index efa922d51d83..a89e8e40d875 100644
--- a/drivers/memory/tegra/tegra186.c
+++ b/drivers/memory/tegra/tegra186.c
@@ -4,6 +4,7 @@
  */
 
 #include <linux/io.h>
+#include <linux/iommu.h>
 #include <linux/module.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of_device.h>
@@ -19,6 +20,10 @@
 #include <dt-bindings/memory/tegra194-mc.h>
 #endif
 
+#define MC_SID_STREAMID_OVERRIDE_MASK GENMASK(7, 0)
+#define MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED BIT(16)
+#define MC_SID_STREAMID_SECURITY_OVERRIDE BIT(8)
+
 struct tegra186_mc_client {
 	const char *name;
 	unsigned int id;
@@ -1808,6 +1813,71 @@ static struct platform_driver tegra186_mc_driver = {
 };
 module_platform_driver(tegra186_mc_driver);
 
+static void tegra186_mc_client_sid_override(struct tegra_mc *mc,
+					    const struct tegra186_mc_client *client,
+					    unsigned int sid)
+{
+	u32 value, old;
+
+	value = readl(mc->regs + client->regs.security);
+	if ((value & MC_SID_STREAMID_SECURITY_OVERRIDE) == 0) {
+		/*
+		 * If the secure firmware has locked this down the override
+		 * for this memory client, there's nothing we can do here.
+		 */
+		if (value & MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED)
+			return;
+
+		/*
+		 * Otherwise, try to set the override itself. Typically the
+		 * secure firmware will never have set this configuration.
+		 * Instead, it will either have disabled write access to
+		 * this field, or it will already have set an explicit
+		 * override itself.
+		 */
+		WARN_ON((value & MC_SID_STREAMID_SECURITY_OVERRIDE) == 0);
+
+		value |= MC_SID_STREAMID_SECURITY_OVERRIDE;
+		writel(value, mc->regs + client->regs.security);
+	}
+
+	value = readl(mc->regs + client->regs.override);
+	old = value & MC_SID_STREAMID_OVERRIDE_MASK;
+
+	if (old != sid) {
+		dev_dbg(mc->dev, "overriding SID %x for %s with %x\n", old,
+			client->name, sid);
+		writel(sid, mc->regs + client->regs.override);
+	}
+}
+
+int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev)
+{
+	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+	struct of_phandle_args args;
+	unsigned int i, index = 0;
+
+	while (!of_parse_phandle_with_args(dev->of_node, "interconnects", "#interconnect-cells",
+					   index, &args)) {
+		if (args.np == mc->dev->of_node && args.args_count != 0) {
+			for (i = 0; i < mc->soc->num_clients; i++) {
+				const struct tegra186_mc_client *client = &mc->soc->clients[i];
+
+				if (client->id == args.args[0]) {
+					u32 sid = fwspec->ids[0] & MC_SID_STREAMID_OVERRIDE_MASK;
+
+					tegra186_mc_client_sid_override(mc, client, sid);
+				}
+			}
+		}
+
+		index++;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(tegra186_mc_probe_device);
+
 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
 MODULE_DESCRIPTION("NVIDIA Tegra186 Memory Controller driver");
 MODULE_LICENSE("GPL v2");
diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h
index 7be8441c6e9e..73d5ecf0e76a 100644
--- a/include/soc/tegra/mc.h
+++ b/include/soc/tegra/mc.h
@@ -168,4 +168,14 @@ devm_tegra_memory_controller_get(struct device *dev)
 }
 #endif
 
+#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
+    IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
+int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev);
+#else
+static inline int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev)
+{
+	return 0;
+}
+#endif
+
 #endif /* __SOC_TEGRA_MC_H__ */
-- 
2.30.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 4/9] iommu/arm-smmu: Implement ->probe_finalize()
  2021-03-25 13:03 [PATCH 0/9] arm64: tegra: Prevent early SMMU faults Thierry Reding
                   ` (2 preceding siblings ...)
  2021-03-25 13:03 ` [PATCH 3/9] memory: tegra: Implement SID override programming Thierry Reding
@ 2021-03-25 13:03 ` Thierry Reding
  2021-03-25 14:27   ` Robin Murphy
  2021-03-25 13:03 ` [PATCH 5/9] iommu/arm-smmu: tegra: Detect number of instances at runtime Thierry Reding
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: Thierry Reding @ 2021-03-25 13:03 UTC (permalink / raw)
  To: Thierry Reding, Will Deacon, Robin Murphy, Joerg Roedel,
	Krzysztof Kozlowski
  Cc: iommu, Jon Hunter, Nicolin Chen, linux-tegra, linux-arm-kernel

From: Thierry Reding <treding@nvidia.com>

Implement a ->probe_finalize() callback that can be used by vendor
implementations to perform extra programming necessary after devices
have been attached to the SMMU.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 17 +++++++++++++++++
 drivers/iommu/arm/arm-smmu/arm-smmu.h |  1 +
 2 files changed, 18 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index d8c6bfde6a61..4589e76543a8 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -1447,6 +1447,22 @@ static void arm_smmu_release_device(struct device *dev)
 	iommu_fwspec_free(dev);
 }
 
+static void arm_smmu_probe_finalize(struct device *dev)
+{
+	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+	struct arm_smmu_master_cfg *cfg;
+	struct arm_smmu_device *smmu;
+
+	if (!fwspec || fwspec->ops != &arm_smmu_ops)
+		return;
+
+	cfg = dev_iommu_priv_get(dev);
+	smmu = cfg->smmu;
+
+	if (smmu->impl->probe_finalize)
+		smmu->impl->probe_finalize(smmu, dev);
+}
+
 static struct iommu_group *arm_smmu_device_group(struct device *dev)
 {
 	struct arm_smmu_master_cfg *cfg = dev_iommu_priv_get(dev);
@@ -1630,6 +1646,7 @@ static struct iommu_ops arm_smmu_ops = {
 	.iova_to_phys		= arm_smmu_iova_to_phys,
 	.probe_device		= arm_smmu_probe_device,
 	.release_device		= arm_smmu_release_device,
+	.probe_finalize		= arm_smmu_probe_finalize,
 	.device_group		= arm_smmu_device_group,
 	.domain_get_attr	= arm_smmu_domain_get_attr,
 	.domain_set_attr	= arm_smmu_domain_set_attr,
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
index d2a2d1bc58ba..6779db30cebb 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
@@ -439,6 +439,7 @@ struct arm_smmu_impl {
 				  struct device *dev, int start);
 	void (*write_s2cr)(struct arm_smmu_device *smmu, int idx);
 	void (*write_sctlr)(struct arm_smmu_device *smmu, int idx, u32 reg);
+	void (*probe_finalize)(struct arm_smmu_device *smmu, struct device *dev);
 };
 
 #define INVALID_SMENDX			-1
-- 
2.30.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 5/9] iommu/arm-smmu: tegra: Detect number of instances at runtime
  2021-03-25 13:03 [PATCH 0/9] arm64: tegra: Prevent early SMMU faults Thierry Reding
                   ` (3 preceding siblings ...)
  2021-03-25 13:03 ` [PATCH 4/9] iommu/arm-smmu: Implement ->probe_finalize() Thierry Reding
@ 2021-03-25 13:03 ` Thierry Reding
  2021-03-25 14:27   ` Robin Murphy
  2021-03-25 13:03 ` [PATCH 6/9] iommu/arm-smmu: tegra: Implement SID override programming Thierry Reding
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: Thierry Reding @ 2021-03-25 13:03 UTC (permalink / raw)
  To: Thierry Reding, Will Deacon, Robin Murphy, Joerg Roedel,
	Krzysztof Kozlowski
  Cc: iommu, Jon Hunter, Nicolin Chen, linux-tegra, linux-arm-kernel

From: Thierry Reding <treding@nvidia.com>

Parse the reg property in device tree and detect the number of instances
represented by a device tree node. This is subsequently needed in order
to support single-instance SMMUs with the Tegra implementation because
additional programming is needed to properly configure the SID override
registers in the memory controller.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c | 49 ++++++++++++++------
 1 file changed, 34 insertions(+), 15 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c b/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c
index 29117444e5a0..5b1170b028f0 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c
@@ -20,13 +20,19 @@
  * The third instance usage is through standard arm-smmu driver itself and
  * is out of scope of this implementation.
  */
-#define NUM_SMMU_INSTANCES 2
+#define MAX_SMMU_INSTANCES 2
 
 struct nvidia_smmu {
-	struct arm_smmu_device	smmu;
-	void __iomem		*bases[NUM_SMMU_INSTANCES];
+	struct arm_smmu_device smmu;
+	void __iomem *bases[MAX_SMMU_INSTANCES];
+	unsigned int num_instances;
 };
 
+static inline struct nvidia_smmu *to_nvidia_smmu(struct arm_smmu_device *smmu)
+{
+	return container_of(smmu, struct nvidia_smmu, smmu);
+}
+
 static inline void __iomem *nvidia_smmu_page(struct arm_smmu_device *smmu,
 					     unsigned int inst, int page)
 {
@@ -47,9 +53,10 @@ static u32 nvidia_smmu_read_reg(struct arm_smmu_device *smmu,
 static void nvidia_smmu_write_reg(struct arm_smmu_device *smmu,
 				  int page, int offset, u32 val)
 {
+	struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu);
 	unsigned int i;
 
-	for (i = 0; i < NUM_SMMU_INSTANCES; i++) {
+	for (i = 0; i < nvidia->num_instances; i++) {
 		void __iomem *reg = nvidia_smmu_page(smmu, i, page) + offset;
 
 		writel_relaxed(val, reg);
@@ -67,9 +74,10 @@ static u64 nvidia_smmu_read_reg64(struct arm_smmu_device *smmu,
 static void nvidia_smmu_write_reg64(struct arm_smmu_device *smmu,
 				    int page, int offset, u64 val)
 {
+	struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu);
 	unsigned int i;
 
-	for (i = 0; i < NUM_SMMU_INSTANCES; i++) {
+	for (i = 0; i < nvidia->num_instances; i++) {
 		void __iomem *reg = nvidia_smmu_page(smmu, i, page) + offset;
 
 		writeq_relaxed(val, reg);
@@ -79,6 +87,7 @@ static void nvidia_smmu_write_reg64(struct arm_smmu_device *smmu,
 static void nvidia_smmu_tlb_sync(struct arm_smmu_device *smmu, int page,
 				 int sync, int status)
 {
+	struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu);
 	unsigned int delay;
 
 	arm_smmu_writel(smmu, page, sync, 0);
@@ -90,7 +99,7 @@ static void nvidia_smmu_tlb_sync(struct arm_smmu_device *smmu, int page,
 			u32 val = 0;
 			unsigned int i;
 
-			for (i = 0; i < NUM_SMMU_INSTANCES; i++) {
+			for (i = 0; i < nvidia->num_instances; i++) {
 				void __iomem *reg;
 
 				reg = nvidia_smmu_page(smmu, i, page) + status;
@@ -112,9 +121,10 @@ static void nvidia_smmu_tlb_sync(struct arm_smmu_device *smmu, int page,
 
 static int nvidia_smmu_reset(struct arm_smmu_device *smmu)
 {
+	struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu);
 	unsigned int i;
 
-	for (i = 0; i < NUM_SMMU_INSTANCES; i++) {
+	for (i = 0; i < nvidia->num_instances; i++) {
 		u32 val;
 		void __iomem *reg = nvidia_smmu_page(smmu, i, ARM_SMMU_GR0) +
 				    ARM_SMMU_GR0_sGFSR;
@@ -157,8 +167,9 @@ static irqreturn_t nvidia_smmu_global_fault(int irq, void *dev)
 	unsigned int inst;
 	irqreturn_t ret = IRQ_NONE;
 	struct arm_smmu_device *smmu = dev;
+	struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu);
 
-	for (inst = 0; inst < NUM_SMMU_INSTANCES; inst++) {
+	for (inst = 0; inst < nvidia->num_instances; inst++) {
 		irqreturn_t irq_ret;
 
 		irq_ret = nvidia_smmu_global_fault_inst(irq, smmu, inst);
@@ -202,11 +213,13 @@ static irqreturn_t nvidia_smmu_context_fault(int irq, void *dev)
 	struct arm_smmu_device *smmu;
 	struct iommu_domain *domain = dev;
 	struct arm_smmu_domain *smmu_domain;
+	struct nvidia_smmu *nvidia;
 
 	smmu_domain = container_of(domain, struct arm_smmu_domain, domain);
 	smmu = smmu_domain->smmu;
+	nvidia = to_nvidia_smmu(smmu);
 
-	for (inst = 0; inst < NUM_SMMU_INSTANCES; inst++) {
+	for (inst = 0; inst < nvidia->num_instances; inst++) {
 		irqreturn_t irq_ret;
 
 		/*
@@ -241,6 +254,7 @@ struct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu)
 	struct device *dev = smmu->dev;
 	struct nvidia_smmu *nvidia_smmu;
 	struct platform_device *pdev = to_platform_device(dev);
+	unsigned int i;
 
 	nvidia_smmu = devm_krealloc(dev, smmu, sizeof(*nvidia_smmu), GFP_KERNEL);
 	if (!nvidia_smmu)
@@ -248,14 +262,19 @@ struct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu)
 
 	/* Instance 0 is ioremapped by arm-smmu.c. */
 	nvidia_smmu->bases[0] = smmu->base;
+	nvidia_smmu->num_instances++;
+
+	for (i = 1; i < MAX_SMMU_INSTANCES; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res)
+			break;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (!res)
-		return ERR_PTR(-ENODEV);
+		nvidia_smmu->bases[i] = devm_ioremap_resource(dev, res);
+		if (IS_ERR(nvidia_smmu->bases[i]))
+			return ERR_CAST(nvidia_smmu->bases[i]);
 
-	nvidia_smmu->bases[1] = devm_ioremap_resource(dev, res);
-	if (IS_ERR(nvidia_smmu->bases[1]))
-		return ERR_CAST(nvidia_smmu->bases[1]);
+		nvidia_smmu->num_instances++;
+	}
 
 	nvidia_smmu->smmu.impl = &nvidia_smmu_impl;
 
-- 
2.30.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 6/9] iommu/arm-smmu: tegra: Implement SID override programming
  2021-03-25 13:03 [PATCH 0/9] arm64: tegra: Prevent early SMMU faults Thierry Reding
                   ` (4 preceding siblings ...)
  2021-03-25 13:03 ` [PATCH 5/9] iommu/arm-smmu: tegra: Detect number of instances at runtime Thierry Reding
@ 2021-03-25 13:03 ` Thierry Reding
  2021-03-25 13:03 ` [PATCH 7/9] iommu/arm-smmu: Use Tegra implementation on Tegra186 Thierry Reding
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Thierry Reding @ 2021-03-25 13:03 UTC (permalink / raw)
  To: Thierry Reding, Will Deacon, Robin Murphy, Joerg Roedel,
	Krzysztof Kozlowski
  Cc: iommu, Jon Hunter, Nicolin Chen, linux-tegra, linux-arm-kernel

From: Thierry Reding <treding@nvidia.com>

The secure firmware keeps some SID override registers set as passthrough
in order to allow devices such as the display controller to operate with
no knowledge of SMMU translations until an operating system driver takes
over. This is needed in order to seamlessly transition from the firmware
framebuffer to the OS framebuffer.

Upon successfully attaching a device to the SMMU and in the process
creating identity mappings for memory regions that are being accessed,
the Tegra implementation will call into the memory controller driver to
program the override SIDs appropriately.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c | 32 ++++++++++++++++++--
 1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c b/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c
index 5b1170b028f0..127b51e6445f 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c
@@ -7,6 +7,8 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
+#include <soc/tegra/mc.h>
+
 #include "arm-smmu.h"
 
 /*
@@ -15,10 +17,17 @@
  * interleaved IOVA accesses across them and translates accesses from
  * non-isochronous HW devices.
  * Third one is used for translating accesses from isochronous HW devices.
+ *
+ * In addition, the SMMU driver needs to coordinate with the memory controller
+ * driver to ensure that the right SID override is programmed for any given
+ * memory client. This is necessary to allow for use-case such as seamlessly
+ * handing over the display controller configuration from the firmware to the
+ * kernel.
+ *
  * This implementation supports programming of the two instances that must
- * be programmed identically.
- * The third instance usage is through standard arm-smmu driver itself and
- * is out of scope of this implementation.
+ * be programmed identically and takes care of invoking the memory controller
+ * driver for SID override programming after devices have been attached to an
+ * SMMU instance.
  */
 #define MAX_SMMU_INSTANCES 2
 
@@ -26,6 +35,7 @@ struct nvidia_smmu {
 	struct arm_smmu_device smmu;
 	void __iomem *bases[MAX_SMMU_INSTANCES];
 	unsigned int num_instances;
+	struct tegra_mc *mc;
 };
 
 static inline struct nvidia_smmu *to_nvidia_smmu(struct arm_smmu_device *smmu)
@@ -237,6 +247,17 @@ static irqreturn_t nvidia_smmu_context_fault(int irq, void *dev)
 	return ret;
 }
 
+static void nvidia_smmu_probe_finalize(struct arm_smmu_device *smmu, struct device *dev)
+{
+	struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu);
+	int err;
+
+	err = tegra186_mc_probe_device(nvidia->mc, dev);
+	if (err < 0)
+		dev_err(smmu->dev, "memory controller probe failed for %s: %d\n",
+			dev_name(dev), err);
+}
+
 static const struct arm_smmu_impl nvidia_smmu_impl = {
 	.read_reg = nvidia_smmu_read_reg,
 	.write_reg = nvidia_smmu_write_reg,
@@ -246,6 +267,7 @@ static const struct arm_smmu_impl nvidia_smmu_impl = {
 	.tlb_sync = nvidia_smmu_tlb_sync,
 	.global_fault = nvidia_smmu_global_fault,
 	.context_fault = nvidia_smmu_context_fault,
+	.probe_finalize = nvidia_smmu_probe_finalize,
 };
 
 struct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu)
@@ -260,6 +282,10 @@ struct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu)
 	if (!nvidia_smmu)
 		return ERR_PTR(-ENOMEM);
 
+	nvidia_smmu->mc = devm_tegra_memory_controller_get(dev);
+	if (IS_ERR(nvidia_smmu->mc))
+		return ERR_CAST(nvidia_smmu->mc);
+
 	/* Instance 0 is ioremapped by arm-smmu.c. */
 	nvidia_smmu->bases[0] = smmu->base;
 	nvidia_smmu->num_instances++;
-- 
2.30.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 7/9] iommu/arm-smmu: Use Tegra implementation on Tegra186
  2021-03-25 13:03 [PATCH 0/9] arm64: tegra: Prevent early SMMU faults Thierry Reding
                   ` (5 preceding siblings ...)
  2021-03-25 13:03 ` [PATCH 6/9] iommu/arm-smmu: tegra: Implement SID override programming Thierry Reding
@ 2021-03-25 13:03 ` Thierry Reding
  2021-03-25 14:27   ` Robin Murphy
  2021-03-25 13:03 ` [PATCH 8/9] arm64: tegra: Hook up memory controller to SMMU " Thierry Reding
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: Thierry Reding @ 2021-03-25 13:03 UTC (permalink / raw)
  To: Thierry Reding, Will Deacon, Robin Murphy, Joerg Roedel,
	Krzysztof Kozlowski
  Cc: iommu, Jon Hunter, Nicolin Chen, linux-tegra, linux-arm-kernel

From: Thierry Reding <treding@nvidia.com>

Tegra186 requires the same SID override programming as Tegra194 in order
to seamlessly transition from the firmware framebuffer to the Linux
framebuffer, so the Tegra implementation needs to be used on Tegra186
devices as well.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu-impl.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
index 136872e77195..9f465e146799 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
@@ -211,7 +211,8 @@ struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu)
 	if (of_property_read_bool(np, "calxeda,smmu-secure-config-access"))
 		smmu->impl = &calxeda_impl;
 
-	if (of_device_is_compatible(np, "nvidia,tegra194-smmu"))
+	if (of_device_is_compatible(np, "nvidia,tegra194-smmu") ||
+	    of_device_is_compatible(np, "nvidia,tegra186-smmu"))
 		return nvidia_smmu_impl_init(smmu);
 
 	smmu = qcom_smmu_impl_init(smmu);
-- 
2.30.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 8/9] arm64: tegra: Hook up memory controller to SMMU on Tegra186
  2021-03-25 13:03 [PATCH 0/9] arm64: tegra: Prevent early SMMU faults Thierry Reding
                   ` (6 preceding siblings ...)
  2021-03-25 13:03 ` [PATCH 7/9] iommu/arm-smmu: Use Tegra implementation on Tegra186 Thierry Reding
@ 2021-03-25 13:03 ` Thierry Reding
  2021-03-25 13:03 ` [PATCH 9/9] arm64: tegra: Enable SMMU support on Tegra194 Thierry Reding
  2021-03-26 15:29 ` [PATCH 0/9] arm64: tegra: Prevent early SMMU faults Dmitry Osipenko
  9 siblings, 0 replies; 23+ messages in thread
From: Thierry Reding @ 2021-03-25 13:03 UTC (permalink / raw)
  To: Thierry Reding, Will Deacon, Robin Murphy, Joerg Roedel,
	Krzysztof Kozlowski
  Cc: iommu, Jon Hunter, Nicolin Chen, linux-tegra, linux-arm-kernel

From: Thierry Reding <treding@nvidia.com>

On Tegra186 and later, the memory controller needs to be programmed in
coordination with any of the ARM SMMU instances to configure the stream
ID used for each memory client.

To support this, add a phandle reference to the memory controller to the
SMMU device tree node.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index 9f75bbf00cf7..e9fdf9e18d37 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -1152,6 +1152,8 @@ smmu: iommu@12000000 {
 		stream-match-mask = <0x7f80>;
 		#global-interrupts = <1>;
 		#iommu-cells = <1>;
+
+		nvidia,memory-controller = <&mc>;
 	};
 
 	host1x@13e00000 {
-- 
2.30.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 9/9] arm64: tegra: Enable SMMU support on Tegra194
  2021-03-25 13:03 [PATCH 0/9] arm64: tegra: Prevent early SMMU faults Thierry Reding
                   ` (7 preceding siblings ...)
  2021-03-25 13:03 ` [PATCH 8/9] arm64: tegra: Hook up memory controller to SMMU " Thierry Reding
@ 2021-03-25 13:03 ` Thierry Reding
  2021-03-26 15:29 ` [PATCH 0/9] arm64: tegra: Prevent early SMMU faults Dmitry Osipenko
  9 siblings, 0 replies; 23+ messages in thread
From: Thierry Reding @ 2021-03-25 13:03 UTC (permalink / raw)
  To: Thierry Reding, Will Deacon, Robin Murphy, Joerg Roedel,
	Krzysztof Kozlowski
  Cc: iommu, Jon Hunter, Nicolin Chen, linux-tegra, linux-arm-kernel

From: Thierry Reding <treding@nvidia.com>

Add the device tree node for the dual-SMMU found on Tegra194 and hook up
peripherals such as host1x, BPMP, HDA, SDMMC, EQOS and VIC.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra194.dtsi | 86 ++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
index 9449156fae39..3c1231a9ff62 100644
--- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
@@ -62,6 +62,7 @@ ethernet@2490000 {
 			interconnects = <&mc TEGRA194_MEMORY_CLIENT_EQOSR &emc>,
 					<&mc TEGRA194_MEMORY_CLIENT_EQOSW &emc>;
 			interconnect-names = "dma-mem", "write";
+			iommus = <&smmu TEGRA194_SID_EQOS>;
 			status = "disabled";
 
 			snps,write-requests = <1>;
@@ -733,6 +734,7 @@ sdmmc1: mmc@3400000 {
 			interconnects = <&mc TEGRA194_MEMORY_CLIENT_SDMMCRA &emc>,
 					<&mc TEGRA194_MEMORY_CLIENT_SDMMCWA &emc>;
 			interconnect-names = "dma-mem", "write";
+			iommus = <&smmu TEGRA194_SID_SDMMC1>;
 			nvidia,pad-autocal-pull-up-offset-3v3-timeout =
 									<0x07>;
 			nvidia,pad-autocal-pull-down-offset-3v3-timeout =
@@ -759,6 +761,7 @@ sdmmc3: mmc@3440000 {
 			interconnects = <&mc TEGRA194_MEMORY_CLIENT_SDMMCR &emc>,
 					<&mc TEGRA194_MEMORY_CLIENT_SDMMCW &emc>;
 			interconnect-names = "dma-mem", "write";
+			iommus = <&smmu TEGRA194_SID_SDMMC3>;
 			nvidia,pad-autocal-pull-up-offset-1v8 = <0x00>;
 			nvidia,pad-autocal-pull-down-offset-1v8 = <0x7a>;
 			nvidia,pad-autocal-pull-up-offset-3v3-timeout = <0x07>;
@@ -790,6 +793,7 @@ sdmmc4: mmc@3460000 {
 			interconnects = <&mc TEGRA194_MEMORY_CLIENT_SDMMCRAB &emc>,
 					<&mc TEGRA194_MEMORY_CLIENT_SDMMCWAB &emc>;
 			interconnect-names = "dma-mem", "write";
+			iommus = <&smmu TEGRA194_SID_SDMMC4>;
 			nvidia,pad-autocal-pull-up-offset-hs400 = <0x00>;
 			nvidia,pad-autocal-pull-down-offset-hs400 = <0x00>;
 			nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x0a>;
@@ -821,6 +825,7 @@ hda@3510000 {
 			interconnects = <&mc TEGRA194_MEMORY_CLIENT_HDAR &emc>,
 					<&mc TEGRA194_MEMORY_CLIENT_HDAW &emc>;
 			interconnect-names = "dma-mem", "write";
+			iommus = <&smmu TEGRA194_SID_HDA>;
 			status = "disabled";
 		};
 
@@ -1300,6 +1305,84 @@ pmc: pmc@c360000 {
 			interrupt-controller;
 		};
 
+		smmu: iommu@12000000 {
+			compatible = "nvidia,tegra194-smmu", "arm,mmu-500";
+			reg = <0x12000000 0x800000>,
+			      <0x11000000 0x800000>;
+			interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>;
+			stream-match-mask = <0x7f80>;
+			#global-interrupts = <2>;
+			#iommu-cells = <1>;
+
+			nvidia,memory-controller = <&mc>;
+			status = "okay";
+		};
+
 		host1x@13e00000 {
 			compatible = "nvidia,tegra194-host1x";
 			reg = <0x13e00000 0x10000>,
@@ -1319,6 +1402,7 @@ host1x@13e00000 {
 			ranges = <0x15000000 0x15000000 0x01000000>;
 			interconnects = <&mc TEGRA194_MEMORY_CLIENT_HOST1XDMAR &emc>;
 			interconnect-names = "dma-mem";
+			iommus = <&smmu TEGRA194_SID_HOST1X>;
 
 			display-hub@15200000 {
 				compatible = "nvidia,tegra194-display";
@@ -1430,6 +1514,7 @@ vic@15340000 {
 				interconnects = <&mc TEGRA194_MEMORY_CLIENT_VICSRD &emc>,
 						<&mc TEGRA194_MEMORY_CLIENT_VICSWR &emc>;
 				interconnect-names = "dma-mem", "write";
+				iommus = <&smmu TEGRA194_SID_VIC>;
 			};
 
 			dpaux0: dpaux@155c0000 {
@@ -2136,6 +2221,7 @@ bpmp: bpmp {
 				<&mc TEGRA194_MEMORY_CLIENT_BPMPDMAR &emc>,
 				<&mc TEGRA194_MEMORY_CLIENT_BPMPDMAW &emc>;
 		interconnect-names = "read", "write", "dma-mem", "dma-write";
+		iommus = <&smmu TEGRA194_SID_BPMP>;
 
 		bpmp_i2c: i2c {
 			compatible = "nvidia,tegra186-bpmp-i2c";
-- 
2.30.2

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH 3/9] memory: tegra: Implement SID override programming
  2021-03-25 13:03 ` [PATCH 3/9] memory: tegra: Implement SID override programming Thierry Reding
@ 2021-03-25 14:27   ` Robin Murphy
  2021-03-25 15:02     ` Thierry Reding
  0 siblings, 1 reply; 23+ messages in thread
From: Robin Murphy @ 2021-03-25 14:27 UTC (permalink / raw)
  To: Thierry Reding, Will Deacon, Joerg Roedel, Krzysztof Kozlowski
  Cc: iommu, Jon Hunter, Nicolin Chen, linux-tegra, linux-arm-kernel

On 2021-03-25 13:03, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> Instead of programming all SID overrides during early boot, perform the
> operation on-demand after the SMMU translations have been set up for a
> device. This reuses data from device tree to match memory clients for a
> device and programs the SID specified in device tree, which corresponds
> to the SID used for the SMMU context banks for the device.

Can you clarify what exactly the SID override does? I'm guessing it's 
more than just changing the ID presented to the SMMU from one value to 
another, since that alone wouldn't help under disable_bypass.

> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>   drivers/memory/tegra/tegra186.c | 70 +++++++++++++++++++++++++++++++++
>   include/soc/tegra/mc.h          | 10 +++++
>   2 files changed, 80 insertions(+)
> 
> diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c
> index efa922d51d83..a89e8e40d875 100644
> --- a/drivers/memory/tegra/tegra186.c
> +++ b/drivers/memory/tegra/tegra186.c
> @@ -4,6 +4,7 @@
>    */
>   
>   #include <linux/io.h>
> +#include <linux/iommu.h>
>   #include <linux/module.h>
>   #include <linux/mod_devicetable.h>
>   #include <linux/of_device.h>
> @@ -19,6 +20,10 @@
>   #include <dt-bindings/memory/tegra194-mc.h>
>   #endif
>   
> +#define MC_SID_STREAMID_OVERRIDE_MASK GENMASK(7, 0)
> +#define MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED BIT(16)
> +#define MC_SID_STREAMID_SECURITY_OVERRIDE BIT(8)
> +
>   struct tegra186_mc_client {
>   	const char *name;
>   	unsigned int id;
> @@ -1808,6 +1813,71 @@ static struct platform_driver tegra186_mc_driver = {
>   };
>   module_platform_driver(tegra186_mc_driver);
>   
> +static void tegra186_mc_client_sid_override(struct tegra_mc *mc,
> +					    const struct tegra186_mc_client *client,
> +					    unsigned int sid)
> +{
> +	u32 value, old;
> +
> +	value = readl(mc->regs + client->regs.security);
> +	if ((value & MC_SID_STREAMID_SECURITY_OVERRIDE) == 0) {
> +		/*
> +		 * If the secure firmware has locked this down the override
> +		 * for this memory client, there's nothing we can do here.
> +		 */
> +		if (value & MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED)
> +			return;

How likely is that in practice? If it's anything more than vanishingly 
rare then that would seem to be a strong pointer back towards 
persevering with the common solution that will work for everyone.

> +
> +		/*
> +		 * Otherwise, try to set the override itself. Typically the
> +		 * secure firmware will never have set this configuration.
> +		 * Instead, it will either have disabled write access to
> +		 * this field, or it will already have set an explicit
> +		 * override itself.
> +		 */
> +		WARN_ON((value & MC_SID_STREAMID_SECURITY_OVERRIDE) == 0);

Given the context that's just WARN_ON(1), but either way I'm struggling 
to understand who the report is for and what they're supposed to do 
about it :/

Robin.

> +
> +		value |= MC_SID_STREAMID_SECURITY_OVERRIDE;
> +		writel(value, mc->regs + client->regs.security);
> +	}
> +
> +	value = readl(mc->regs + client->regs.override);
> +	old = value & MC_SID_STREAMID_OVERRIDE_MASK;
> +
> +	if (old != sid) {
> +		dev_dbg(mc->dev, "overriding SID %x for %s with %x\n", old,
> +			client->name, sid);
> +		writel(sid, mc->regs + client->regs.override);
> +	}
> +}
> +
> +int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev)
> +{
> +	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> +	struct of_phandle_args args;
> +	unsigned int i, index = 0;
> +
> +	while (!of_parse_phandle_with_args(dev->of_node, "interconnects", "#interconnect-cells",
> +					   index, &args)) {
> +		if (args.np == mc->dev->of_node && args.args_count != 0) {
> +			for (i = 0; i < mc->soc->num_clients; i++) {
> +				const struct tegra186_mc_client *client = &mc->soc->clients[i];
> +
> +				if (client->id == args.args[0]) {
> +					u32 sid = fwspec->ids[0] & MC_SID_STREAMID_OVERRIDE_MASK;
> +
> +					tegra186_mc_client_sid_override(mc, client, sid);
> +				}
> +			}
> +		}
> +
> +		index++;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(tegra186_mc_probe_device);
> +
>   MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
>   MODULE_DESCRIPTION("NVIDIA Tegra186 Memory Controller driver");
>   MODULE_LICENSE("GPL v2");
> diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h
> index 7be8441c6e9e..73d5ecf0e76a 100644
> --- a/include/soc/tegra/mc.h
> +++ b/include/soc/tegra/mc.h
> @@ -168,4 +168,14 @@ devm_tegra_memory_controller_get(struct device *dev)
>   }
>   #endif
>   
> +#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
> +    IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
> +int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev);
> +#else
> +static inline int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev)
> +{
> +	return 0;
> +}
> +#endif
> +
>   #endif /* __SOC_TEGRA_MC_H__ */
> 
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 5/9] iommu/arm-smmu: tegra: Detect number of instances at runtime
  2021-03-25 13:03 ` [PATCH 5/9] iommu/arm-smmu: tegra: Detect number of instances at runtime Thierry Reding
@ 2021-03-25 14:27   ` Robin Murphy
  0 siblings, 0 replies; 23+ messages in thread
From: Robin Murphy @ 2021-03-25 14:27 UTC (permalink / raw)
  To: Thierry Reding, Will Deacon, Joerg Roedel, Krzysztof Kozlowski
  Cc: iommu, Jon Hunter, Nicolin Chen, linux-tegra, linux-arm-kernel

On 2021-03-25 13:03, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> Parse the reg property in device tree and detect the number of instances
> represented by a device tree node. This is subsequently needed in order
> to support single-instance SMMUs with the Tegra implementation because
> additional programming is needed to properly configure the SID override
> registers in the memory controller.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>   drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c | 49 ++++++++++++++------
>   1 file changed, 34 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c b/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c
> index 29117444e5a0..5b1170b028f0 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c
> @@ -20,13 +20,19 @@
>    * The third instance usage is through standard arm-smmu driver itself and
>    * is out of scope of this implementation.
>    */
> -#define NUM_SMMU_INSTANCES 2
> +#define MAX_SMMU_INSTANCES 2
>   
>   struct nvidia_smmu {
> -	struct arm_smmu_device	smmu;
> -	void __iomem		*bases[NUM_SMMU_INSTANCES];
> +	struct arm_smmu_device smmu;
> +	void __iomem *bases[MAX_SMMU_INSTANCES];
> +	unsigned int num_instances;

Surely it would make more sense to just add a second set of 
implementation ops without all the overrides that aren't needed for a 
single instance?

Also note that the binding currently requires the Tegra-specific 
compatible to have exactly two regions.

Robin.

>   };
>   
> +static inline struct nvidia_smmu *to_nvidia_smmu(struct arm_smmu_device *smmu)
> +{
> +	return container_of(smmu, struct nvidia_smmu, smmu);
> +}
> +
>   static inline void __iomem *nvidia_smmu_page(struct arm_smmu_device *smmu,
>   					     unsigned int inst, int page)
>   {
> @@ -47,9 +53,10 @@ static u32 nvidia_smmu_read_reg(struct arm_smmu_device *smmu,
>   static void nvidia_smmu_write_reg(struct arm_smmu_device *smmu,
>   				  int page, int offset, u32 val)
>   {
> +	struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu);
>   	unsigned int i;
>   
> -	for (i = 0; i < NUM_SMMU_INSTANCES; i++) {
> +	for (i = 0; i < nvidia->num_instances; i++) {
>   		void __iomem *reg = nvidia_smmu_page(smmu, i, page) + offset;
>   
>   		writel_relaxed(val, reg);
> @@ -67,9 +74,10 @@ static u64 nvidia_smmu_read_reg64(struct arm_smmu_device *smmu,
>   static void nvidia_smmu_write_reg64(struct arm_smmu_device *smmu,
>   				    int page, int offset, u64 val)
>   {
> +	struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu);
>   	unsigned int i;
>   
> -	for (i = 0; i < NUM_SMMU_INSTANCES; i++) {
> +	for (i = 0; i < nvidia->num_instances; i++) {
>   		void __iomem *reg = nvidia_smmu_page(smmu, i, page) + offset;
>   
>   		writeq_relaxed(val, reg);
> @@ -79,6 +87,7 @@ static void nvidia_smmu_write_reg64(struct arm_smmu_device *smmu,
>   static void nvidia_smmu_tlb_sync(struct arm_smmu_device *smmu, int page,
>   				 int sync, int status)
>   {
> +	struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu);
>   	unsigned int delay;
>   
>   	arm_smmu_writel(smmu, page, sync, 0);
> @@ -90,7 +99,7 @@ static void nvidia_smmu_tlb_sync(struct arm_smmu_device *smmu, int page,
>   			u32 val = 0;
>   			unsigned int i;
>   
> -			for (i = 0; i < NUM_SMMU_INSTANCES; i++) {
> +			for (i = 0; i < nvidia->num_instances; i++) {
>   				void __iomem *reg;
>   
>   				reg = nvidia_smmu_page(smmu, i, page) + status;
> @@ -112,9 +121,10 @@ static void nvidia_smmu_tlb_sync(struct arm_smmu_device *smmu, int page,
>   
>   static int nvidia_smmu_reset(struct arm_smmu_device *smmu)
>   {
> +	struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu);
>   	unsigned int i;
>   
> -	for (i = 0; i < NUM_SMMU_INSTANCES; i++) {
> +	for (i = 0; i < nvidia->num_instances; i++) {
>   		u32 val;
>   		void __iomem *reg = nvidia_smmu_page(smmu, i, ARM_SMMU_GR0) +
>   				    ARM_SMMU_GR0_sGFSR;
> @@ -157,8 +167,9 @@ static irqreturn_t nvidia_smmu_global_fault(int irq, void *dev)
>   	unsigned int inst;
>   	irqreturn_t ret = IRQ_NONE;
>   	struct arm_smmu_device *smmu = dev;
> +	struct nvidia_smmu *nvidia = to_nvidia_smmu(smmu);
>   
> -	for (inst = 0; inst < NUM_SMMU_INSTANCES; inst++) {
> +	for (inst = 0; inst < nvidia->num_instances; inst++) {
>   		irqreturn_t irq_ret;
>   
>   		irq_ret = nvidia_smmu_global_fault_inst(irq, smmu, inst);
> @@ -202,11 +213,13 @@ static irqreturn_t nvidia_smmu_context_fault(int irq, void *dev)
>   	struct arm_smmu_device *smmu;
>   	struct iommu_domain *domain = dev;
>   	struct arm_smmu_domain *smmu_domain;
> +	struct nvidia_smmu *nvidia;
>   
>   	smmu_domain = container_of(domain, struct arm_smmu_domain, domain);
>   	smmu = smmu_domain->smmu;
> +	nvidia = to_nvidia_smmu(smmu);
>   
> -	for (inst = 0; inst < NUM_SMMU_INSTANCES; inst++) {
> +	for (inst = 0; inst < nvidia->num_instances; inst++) {
>   		irqreturn_t irq_ret;
>   
>   		/*
> @@ -241,6 +254,7 @@ struct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu)
>   	struct device *dev = smmu->dev;
>   	struct nvidia_smmu *nvidia_smmu;
>   	struct platform_device *pdev = to_platform_device(dev);
> +	unsigned int i;
>   
>   	nvidia_smmu = devm_krealloc(dev, smmu, sizeof(*nvidia_smmu), GFP_KERNEL);
>   	if (!nvidia_smmu)
> @@ -248,14 +262,19 @@ struct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu)
>   
>   	/* Instance 0 is ioremapped by arm-smmu.c. */
>   	nvidia_smmu->bases[0] = smmu->base;
> +	nvidia_smmu->num_instances++;
> +
> +	for (i = 1; i < MAX_SMMU_INSTANCES; i++) {
> +		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
> +		if (!res)
> +			break;
>   
> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> -	if (!res)
> -		return ERR_PTR(-ENODEV);
> +		nvidia_smmu->bases[i] = devm_ioremap_resource(dev, res);
> +		if (IS_ERR(nvidia_smmu->bases[i]))
> +			return ERR_CAST(nvidia_smmu->bases[i]);
>   
> -	nvidia_smmu->bases[1] = devm_ioremap_resource(dev, res);
> -	if (IS_ERR(nvidia_smmu->bases[1]))
> -		return ERR_CAST(nvidia_smmu->bases[1]);
> +		nvidia_smmu->num_instances++;
> +	}
>   
>   	nvidia_smmu->smmu.impl = &nvidia_smmu_impl;
>   
> 
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 4/9] iommu/arm-smmu: Implement ->probe_finalize()
  2021-03-25 13:03 ` [PATCH 4/9] iommu/arm-smmu: Implement ->probe_finalize() Thierry Reding
@ 2021-03-25 14:27   ` Robin Murphy
  0 siblings, 0 replies; 23+ messages in thread
From: Robin Murphy @ 2021-03-25 14:27 UTC (permalink / raw)
  To: Thierry Reding, Will Deacon, Joerg Roedel, Krzysztof Kozlowski
  Cc: iommu, Jon Hunter, Nicolin Chen, linux-tegra, linux-arm-kernel

On 2021-03-25 13:03, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> Implement a ->probe_finalize() callback that can be used by vendor
> implementations to perform extra programming necessary after devices
> have been attached to the SMMU.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>   drivers/iommu/arm/arm-smmu/arm-smmu.c | 17 +++++++++++++++++
>   drivers/iommu/arm/arm-smmu/arm-smmu.h |  1 +
>   2 files changed, 18 insertions(+)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> index d8c6bfde6a61..4589e76543a8 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> @@ -1447,6 +1447,22 @@ static void arm_smmu_release_device(struct device *dev)
>   	iommu_fwspec_free(dev);
>   }
>   
> +static void arm_smmu_probe_finalize(struct device *dev)
> +{
> +	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> +	struct arm_smmu_master_cfg *cfg;
> +	struct arm_smmu_device *smmu;
> +
> +	if (!fwspec || fwspec->ops != &arm_smmu_ops)
> +		return;

I think we can trust the IOMMU core not to call things in the wrong 
order, and if the fwspec has changed since it was validated in 
.probe_device then the world is probably on fire anyway.

Robin.

> +
> +	cfg = dev_iommu_priv_get(dev);
> +	smmu = cfg->smmu;
> +
> +	if (smmu->impl->probe_finalize)
> +		smmu->impl->probe_finalize(smmu, dev);
> +}
> +
>   static struct iommu_group *arm_smmu_device_group(struct device *dev)
>   {
>   	struct arm_smmu_master_cfg *cfg = dev_iommu_priv_get(dev);
> @@ -1630,6 +1646,7 @@ static struct iommu_ops arm_smmu_ops = {
>   	.iova_to_phys		= arm_smmu_iova_to_phys,
>   	.probe_device		= arm_smmu_probe_device,
>   	.release_device		= arm_smmu_release_device,
> +	.probe_finalize		= arm_smmu_probe_finalize,
>   	.device_group		= arm_smmu_device_group,
>   	.domain_get_attr	= arm_smmu_domain_get_attr,
>   	.domain_set_attr	= arm_smmu_domain_set_attr,
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> index d2a2d1bc58ba..6779db30cebb 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> @@ -439,6 +439,7 @@ struct arm_smmu_impl {
>   				  struct device *dev, int start);
>   	void (*write_s2cr)(struct arm_smmu_device *smmu, int idx);
>   	void (*write_sctlr)(struct arm_smmu_device *smmu, int idx, u32 reg);
> +	void (*probe_finalize)(struct arm_smmu_device *smmu, struct device *dev);
>   };
>   
>   #define INVALID_SMENDX			-1
> 
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 7/9] iommu/arm-smmu: Use Tegra implementation on Tegra186
  2021-03-25 13:03 ` [PATCH 7/9] iommu/arm-smmu: Use Tegra implementation on Tegra186 Thierry Reding
@ 2021-03-25 14:27   ` Robin Murphy
  0 siblings, 0 replies; 23+ messages in thread
From: Robin Murphy @ 2021-03-25 14:27 UTC (permalink / raw)
  To: Thierry Reding, Will Deacon, Joerg Roedel, Krzysztof Kozlowski
  Cc: iommu, Jon Hunter, Nicolin Chen, linux-tegra, linux-arm-kernel

On 2021-03-25 13:03, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> Tegra186 requires the same SID override programming as Tegra194 in order
> to seamlessly transition from the firmware framebuffer to the Linux
> framebuffer, so the Tegra implementation needs to be used on Tegra186
> devices as well.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>   drivers/iommu/arm/arm-smmu/arm-smmu-impl.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
> index 136872e77195..9f465e146799 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
> @@ -211,7 +211,8 @@ struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu)
>   	if (of_property_read_bool(np, "calxeda,smmu-secure-config-access"))
>   		smmu->impl = &calxeda_impl;
>   
> -	if (of_device_is_compatible(np, "nvidia,tegra194-smmu"))
> +	if (of_device_is_compatible(np, "nvidia,tegra194-smmu") ||
> +	    of_device_is_compatible(np, "nvidia,tegra186-smmu"))

Binding update?

Robin.

>   		return nvidia_smmu_impl_init(smmu);
>   
>   	smmu = qcom_smmu_impl_init(smmu);
> 
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 3/9] memory: tegra: Implement SID override programming
  2021-03-25 14:27   ` Robin Murphy
@ 2021-03-25 15:02     ` Thierry Reding
  0 siblings, 0 replies; 23+ messages in thread
From: Thierry Reding @ 2021-03-25 15:02 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Krzysztof Kozlowski, iommu, Jon Hunter, Nicolin Chen,
	linux-tegra, Will Deacon, linux-arm-kernel


[-- Attachment #1.1: Type: text/plain, Size: 5062 bytes --]

On Thu, Mar 25, 2021 at 02:27:10PM +0000, Robin Murphy wrote:
> On 2021-03-25 13:03, Thierry Reding wrote:
> > From: Thierry Reding <treding@nvidia.com>
> > 
> > Instead of programming all SID overrides during early boot, perform the
> > operation on-demand after the SMMU translations have been set up for a
> > device. This reuses data from device tree to match memory clients for a
> > device and programs the SID specified in device tree, which corresponds
> > to the SID used for the SMMU context banks for the device.
> 
> Can you clarify what exactly the SID override does? I'm guessing it's more
> than just changing the ID presented to the SMMU from one value to another,
> since that alone wouldn't help under disable_bypass.

My understanding is that this override is basically one level higher
than the SMMU. There's a special override SID (0x7f) that can be used to
avoid memory accesses to go through the SMMU at all. That is, as long as
that passthrough SID is configured for a memory client, accesses by that
client will be routed around the SMMU. Only if a valid SID is programmed
in this override will accesses for a memory client be routed to the
SMMU.

> > Signed-off-by: Thierry Reding <treding@nvidia.com>
> > ---
> >   drivers/memory/tegra/tegra186.c | 70 +++++++++++++++++++++++++++++++++
> >   include/soc/tegra/mc.h          | 10 +++++
> >   2 files changed, 80 insertions(+)
> > 
> > diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c
> > index efa922d51d83..a89e8e40d875 100644
> > --- a/drivers/memory/tegra/tegra186.c
> > +++ b/drivers/memory/tegra/tegra186.c
> > @@ -4,6 +4,7 @@
> >    */
> >   #include <linux/io.h>
> > +#include <linux/iommu.h>
> >   #include <linux/module.h>
> >   #include <linux/mod_devicetable.h>
> >   #include <linux/of_device.h>
> > @@ -19,6 +20,10 @@
> >   #include <dt-bindings/memory/tegra194-mc.h>
> >   #endif
> > +#define MC_SID_STREAMID_OVERRIDE_MASK GENMASK(7, 0)
> > +#define MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED BIT(16)
> > +#define MC_SID_STREAMID_SECURITY_OVERRIDE BIT(8)
> > +
> >   struct tegra186_mc_client {
> >   	const char *name;
> >   	unsigned int id;
> > @@ -1808,6 +1813,71 @@ static struct platform_driver tegra186_mc_driver = {
> >   };
> >   module_platform_driver(tegra186_mc_driver);
> > +static void tegra186_mc_client_sid_override(struct tegra_mc *mc,
> > +					    const struct tegra186_mc_client *client,
> > +					    unsigned int sid)
> > +{
> > +	u32 value, old;
> > +
> > +	value = readl(mc->regs + client->regs.security);
> > +	if ((value & MC_SID_STREAMID_SECURITY_OVERRIDE) == 0) {
> > +		/*
> > +		 * If the secure firmware has locked this down the override
> > +		 * for this memory client, there's nothing we can do here.
> > +		 */
> > +		if (value & MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED)
> > +			return;
> 
> How likely is that in practice? If it's anything more than vanishingly rare
> then that would seem to be a strong pointer back towards persevering with
> the common solution that will work for everyone.

The idea behind this patch series is basically to use this mechanism in
order to avoid the murky waters between ARM SMMU driver probe and SMMU
device probe, so that we can avoid the early identity mappings that make
things so complicated.

So in other words until the device has been attached to the SMMU (at
which point it's expected that any identity mappings will have been
created), the device will remain in passthrough mode through the SID
override mechanism. After the device has been attached, we'd lock the
SID to the proper value and hence enable SMMU translation.

In a typical setup it would actually be fairly common to encounter the
above. The firmware will pre-program the SID overrides and lock down the
configuration for most devices. The only one that will stay unconfigured
at the moment is display, specifically because it is the only device
that may not be in a quiescent state during boot. For all other devices
write access to the SID override register is disabled and the above just
abandons early because the subsequent operations would just be
discarded.

> > +		/*
> > +		 * Otherwise, try to set the override itself. Typically the
> > +		 * secure firmware will never have set this configuration.
> > +		 * Instead, it will either have disabled write access to
> > +		 * this field, or it will already have set an explicit
> > +		 * override itself.
> > +		 */
> > +		WARN_ON((value & MC_SID_STREAMID_SECURITY_OVERRIDE) == 0);
> 
> Given the context that's just WARN_ON(1), but either way I'm struggling to
> understand who the report is for and what they're supposed to do about it :/

This is mostly for myself, or anyone else looking at the integration of
all this. I don't expect this to ever happen. If it does it basically
means that the firmware isn't programming things the way they are
expected to be programmed. It's a sanity check, basically.

Thierry

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 156 bytes --]

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/9] memory: tegra: Move internal data structures into separate header
  2021-03-25 13:03 ` [PATCH 1/9] memory: tegra: Move internal data structures into separate header Thierry Reding
@ 2021-03-25 15:12   ` Dmitry Osipenko
  2021-03-25 15:52     ` Thierry Reding
  0 siblings, 1 reply; 23+ messages in thread
From: Dmitry Osipenko @ 2021-03-25 15:12 UTC (permalink / raw)
  To: Thierry Reding, Will Deacon, Robin Murphy, Joerg Roedel,
	Krzysztof Kozlowski
  Cc: linux-tegra, iommu, Nicolin Chen, linux-arm-kernel, Jon Hunter

25.03.2021 16:03, Thierry Reding пишет:
> From: Thierry Reding <treding@nvidia.com>
> 
> From Tegra20 through Tegra210, either the GART or SMMU drivers need
> access to the internals of the memory controller driver because they are
> tightly coupled (in fact, the GART and SMMU are part of the memory
> controller). On later chips, a separate hardware block implements the
> SMMU functionality, so this is no longer needed. However, we still want
> to reuse some of the existing infrastructure on later chips, so split
> the memory controller internals into a separate header file to avoid
> conflicts with the implementation on newer chips.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  drivers/iommu/tegra-gart.c      |  2 +-
>  drivers/iommu/tegra-smmu.c      |  2 +-
>  drivers/memory/tegra/mc.h       |  2 +-
>  drivers/memory/tegra/tegra186.c | 12 ++++---
>  include/soc/tegra/mc-internal.h | 62 +++++++++++++++++++++++++++++++++
>  include/soc/tegra/mc.h          | 50 --------------------------
>  6 files changed, 72 insertions(+), 58 deletions(-)
>  create mode 100644 include/soc/tegra/mc-internal.h

What about to make T186 to re-use the existing tegra_mc struct? Seems
there is nothing special in that struct which doesn't fit for the newer
SoCs. Please notice that both SMMU and GART are already optional and all
the SoC differences are specified within the tegra_mc_soc. It looks to
me that this could be a much nicer and cleaner variant.
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/9] memory: tegra: Move internal data structures into separate header
  2021-03-25 15:12   ` Dmitry Osipenko
@ 2021-03-25 15:52     ` Thierry Reding
  2021-03-25 16:11       ` Dmitry Osipenko
  0 siblings, 1 reply; 23+ messages in thread
From: Thierry Reding @ 2021-03-25 15:52 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Krzysztof Kozlowski, Will Deacon, Jon Hunter, iommu,
	Nicolin Chen, linux-tegra, Robin Murphy, linux-arm-kernel


[-- Attachment #1.1: Type: text/plain, Size: 2283 bytes --]

On Thu, Mar 25, 2021 at 06:12:51PM +0300, Dmitry Osipenko wrote:
> 25.03.2021 16:03, Thierry Reding пишет:
> > From: Thierry Reding <treding@nvidia.com>
> > 
> > From Tegra20 through Tegra210, either the GART or SMMU drivers need
> > access to the internals of the memory controller driver because they are
> > tightly coupled (in fact, the GART and SMMU are part of the memory
> > controller). On later chips, a separate hardware block implements the
> > SMMU functionality, so this is no longer needed. However, we still want
> > to reuse some of the existing infrastructure on later chips, so split
> > the memory controller internals into a separate header file to avoid
> > conflicts with the implementation on newer chips.
> > 
> > Signed-off-by: Thierry Reding <treding@nvidia.com>
> > ---
> >  drivers/iommu/tegra-gart.c      |  2 +-
> >  drivers/iommu/tegra-smmu.c      |  2 +-
> >  drivers/memory/tegra/mc.h       |  2 +-
> >  drivers/memory/tegra/tegra186.c | 12 ++++---
> >  include/soc/tegra/mc-internal.h | 62 +++++++++++++++++++++++++++++++++
> >  include/soc/tegra/mc.h          | 50 --------------------------
> >  6 files changed, 72 insertions(+), 58 deletions(-)
> >  create mode 100644 include/soc/tegra/mc-internal.h
> 
> What about to make T186 to re-use the existing tegra_mc struct? Seems
> there is nothing special in that struct which doesn't fit for the newer
> SoCs. Please notice that both SMMU and GART are already optional and all
> the SoC differences are specified within the tegra_mc_soc. It looks to
> me that this could be a much nicer and cleaner variant.

The problem is that much of the interesting bits in tegra_mc_soc are
basically incompatible between the two. For instance the tegra_mc_client
and tegra186_mc_client structures, while they have the same purpose,
have completely different content. I didn't see a way to unify that
without overly complicating things by making half of the fields
basically optional on one or the other SoC generation.

Maybe one option would be to split tegra_mc into a tegra_mc_common and
then derive tegra_mc and tegra186_mc from that. That way we could share
the common bits while still letting the chip-specific differences be
handled separately.

Thierry

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 156 bytes --]

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/9] memory: tegra: Move internal data structures into separate header
  2021-03-25 15:52     ` Thierry Reding
@ 2021-03-25 16:11       ` Dmitry Osipenko
  2021-03-26 13:21         ` Dmitry Osipenko
  0 siblings, 1 reply; 23+ messages in thread
From: Dmitry Osipenko @ 2021-03-25 16:11 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Krzysztof Kozlowski, Will Deacon, Jon Hunter, iommu,
	Nicolin Chen, linux-tegra, Robin Murphy, linux-arm-kernel

25.03.2021 18:52, Thierry Reding пишет:
> On Thu, Mar 25, 2021 at 06:12:51PM +0300, Dmitry Osipenko wrote:
>> 25.03.2021 16:03, Thierry Reding пишет:
>>> From: Thierry Reding <treding@nvidia.com>
>>>
>>> From Tegra20 through Tegra210, either the GART or SMMU drivers need
>>> access to the internals of the memory controller driver because they are
>>> tightly coupled (in fact, the GART and SMMU are part of the memory
>>> controller). On later chips, a separate hardware block implements the
>>> SMMU functionality, so this is no longer needed. However, we still want
>>> to reuse some of the existing infrastructure on later chips, so split
>>> the memory controller internals into a separate header file to avoid
>>> conflicts with the implementation on newer chips.
>>>
>>> Signed-off-by: Thierry Reding <treding@nvidia.com>
>>> ---
>>>  drivers/iommu/tegra-gart.c      |  2 +-
>>>  drivers/iommu/tegra-smmu.c      |  2 +-
>>>  drivers/memory/tegra/mc.h       |  2 +-
>>>  drivers/memory/tegra/tegra186.c | 12 ++++---
>>>  include/soc/tegra/mc-internal.h | 62 +++++++++++++++++++++++++++++++++
>>>  include/soc/tegra/mc.h          | 50 --------------------------
>>>  6 files changed, 72 insertions(+), 58 deletions(-)
>>>  create mode 100644 include/soc/tegra/mc-internal.h
>>
>> What about to make T186 to re-use the existing tegra_mc struct? Seems
>> there is nothing special in that struct which doesn't fit for the newer
>> SoCs. Please notice that both SMMU and GART are already optional and all
>> the SoC differences are specified within the tegra_mc_soc. It looks to
>> me that this could be a much nicer and cleaner variant.
> 
> The problem is that much of the interesting bits in tegra_mc_soc are
> basically incompatible between the two. For instance the tegra_mc_client
> and tegra186_mc_client structures, while they have the same purpose,
> have completely different content. I didn't see a way to unify that
> without overly complicating things by making half of the fields
> basically optional on one or the other SoC generation.

The additional fields aren't problem for T20, which doesn't need most of
the fields. I'd try to go with the additional fields for now and see how
it will look like, if it will be bothering too much, then we may
consider to refactor the drivers more thoroughly (later on, in a
separate series), with a better/nicer separation and taking into account
a potential modularization support by the MC drivers.

Using a union for the exclusive fields also could work, although always
need to be extra careful with the unions.

> Maybe one option would be to split tegra_mc into a tegra_mc_common and
> then derive tegra_mc and tegra186_mc from that. That way we could share
> the common bits while still letting the chip-specific differences be
> handled separately.

But isn't tegra_mc already a superset of tegra186_mc? I think the
tegra186_mc_client is the main difference here.
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/9] memory: tegra: Move internal data structures into separate header
  2021-03-25 16:11       ` Dmitry Osipenko
@ 2021-03-26 13:21         ` Dmitry Osipenko
  0 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2021-03-26 13:21 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Krzysztof Kozlowski, Will Deacon, Jon Hunter, iommu,
	Nicolin Chen, linux-tegra, Robin Murphy, linux-arm-kernel

25.03.2021 19:11, Dmitry Osipenko пишет:
> 25.03.2021 18:52, Thierry Reding пишет:
>> On Thu, Mar 25, 2021 at 06:12:51PM +0300, Dmitry Osipenko wrote:
>>> 25.03.2021 16:03, Thierry Reding пишет:
>>>> From: Thierry Reding <treding@nvidia.com>
>>>>
>>>> From Tegra20 through Tegra210, either the GART or SMMU drivers need
>>>> access to the internals of the memory controller driver because they are
>>>> tightly coupled (in fact, the GART and SMMU are part of the memory
>>>> controller). On later chips, a separate hardware block implements the
>>>> SMMU functionality, so this is no longer needed. However, we still want
>>>> to reuse some of the existing infrastructure on later chips, so split
>>>> the memory controller internals into a separate header file to avoid
>>>> conflicts with the implementation on newer chips.
>>>>
>>>> Signed-off-by: Thierry Reding <treding@nvidia.com>
>>>> ---
>>>>  drivers/iommu/tegra-gart.c      |  2 +-
>>>>  drivers/iommu/tegra-smmu.c      |  2 +-
>>>>  drivers/memory/tegra/mc.h       |  2 +-
>>>>  drivers/memory/tegra/tegra186.c | 12 ++++---
>>>>  include/soc/tegra/mc-internal.h | 62 +++++++++++++++++++++++++++++++++
>>>>  include/soc/tegra/mc.h          | 50 --------------------------
>>>>  6 files changed, 72 insertions(+), 58 deletions(-)
>>>>  create mode 100644 include/soc/tegra/mc-internal.h
>>>
>>> What about to make T186 to re-use the existing tegra_mc struct? Seems
>>> there is nothing special in that struct which doesn't fit for the newer
>>> SoCs. Please notice that both SMMU and GART are already optional and all
>>> the SoC differences are specified within the tegra_mc_soc. It looks to
>>> me that this could be a much nicer and cleaner variant.
>>
>> The problem is that much of the interesting bits in tegra_mc_soc are
>> basically incompatible between the two. For instance the tegra_mc_client
>> and tegra186_mc_client structures, while they have the same purpose,
>> have completely different content. I didn't see a way to unify that
>> without overly complicating things by making half of the fields
>> basically optional on one or the other SoC generation.
> 
> The additional fields aren't problem for T20, which doesn't need most of
> the fields. I'd try to go with the additional fields for now and see how
> it will look like, if it will be bothering too much, then we may
> consider to refactor the drivers more thoroughly (later on, in a
> separate series), with a better/nicer separation and taking into account
> a potential modularization support by the MC drivers.
> 
> Using a union for the exclusive fields also could work, although always
> need to be extra careful with the unions.
> 
>> Maybe one option would be to split tegra_mc into a tegra_mc_common and
>> then derive tegra_mc and tegra186_mc from that. That way we could share
>> the common bits while still letting the chip-specific differences be
>> handled separately.
> 
> But isn't tegra_mc already a superset of tegra186_mc? I think the
> tegra186_mc_client is the main difference here.
> 

Another thing we could do is to optimize the size of tegra_mc_client, but not sure whether it's worthwhile to care about extra ~3KB of data.

This slims down tegra_mc_client by two times:

 diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
index edea9b2b406e..1d652bfc6b44 100644
--- a/drivers/memory/tegra/mc.c
+++ b/drivers/memory/tegra/mc.c
@@ -317,11 +317,11 @@ static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc)
 	/* write latency allowance defaults */
 	for (i = 0; i < mc->soc->num_clients; i++) {
 		const struct tegra_mc_la *la = &mc->soc->clients[i].la;
-		u32 value;
+		u32 value, la_mask = la->mask, la_def = la->def;
 
 		value = mc_readl(mc, la->reg);
-		value &= ~(la->mask << la->shift);
-		value |= (la->def & la->mask) << la->shift;
+		value &= ~(la_mask << la->shift);
+		value |= (la_def & la_mask) << la->shift;
 		mc_writel(mc, value, la->reg);
 	}
 
diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c
index 46332fa82d10..ecf05484d656 100644
--- a/drivers/memory/tegra/tegra30.c
+++ b/drivers/memory/tegra/tegra30.c
@@ -1157,7 +1157,7 @@ static void tegra30_mc_tune_client_latency(struct tegra_mc *mc,
 	u32 arb_tolerance_compensation_nsec, arb_tolerance_compensation_div;
 	const struct tegra_mc_la *la = &client->la;
 	unsigned int fifo_size = client->fifo_size;
-	u32 arb_nsec, la_ticks, value;
+	u32 arb_nsec, la_ticks, value, la_mask;
 
 	/* see 18.4.1 Client Configuration in Tegra3 TRM v03p */
 	if (bandwidth_mbytes_sec)
@@ -1214,11 +1214,12 @@ static void tegra30_mc_tune_client_latency(struct tegra_mc *mc,
 	 * client may wait in the EMEM arbiter before it becomes a high-priority
 	 * request.
 	 */
+	la_mask = la->mask;
 	la_ticks = arb_nsec / mc->tick;
-	la_ticks = min(la_ticks, la->mask);
+	la_ticks = min(la_ticks, la_mask);
 
 	value = mc_readl(mc, la->reg);
-	value &= ~(la->mask << la->shift);
+	value &= ~(la_mask << la->shift);
 	value |= la_ticks << la->shift;
 	mc_writel(mc, value, la->reg);
 }
diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h
index d2fbe6a8b25b..e7a994d16c8e 100644
--- a/include/soc/tegra/mc.h
+++ b/include/soc/tegra/mc.h
@@ -18,8 +18,8 @@ struct device;
 struct page;
 
 struct tegra_smmu_enable {
-	unsigned int reg;
-	unsigned int bit;
+	u16 reg;
+	u8 bit;
 };
 
 struct tegra_mc_timing {
@@ -30,22 +30,22 @@ struct tegra_mc_timing {
 
 /* latency allowance */
 struct tegra_mc_la {
-	unsigned int reg;
-	unsigned int shift;
-	unsigned int mask;
-	unsigned int def;
+	u16 reg;
+	u8 shift;
+	u8 mask;
+	u8 def;
 };
 
 struct tegra_mc_client {
-	unsigned int id;
 	const char *name;
-	unsigned int swgroup;
 
-	unsigned int fifo_size;
+	u8 id;
+	u8 swgroup;
+	u16 fifo_size;
 
 	struct tegra_smmu_enable smmu;
 	struct tegra_mc_la la;
-};
+} __packed;
 
 struct tegra_smmu_swgroup {
 	const char *name;

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH 0/9] arm64: tegra: Prevent early SMMU faults
  2021-03-25 13:03 [PATCH 0/9] arm64: tegra: Prevent early SMMU faults Thierry Reding
                   ` (8 preceding siblings ...)
  2021-03-25 13:03 ` [PATCH 9/9] arm64: tegra: Enable SMMU support on Tegra194 Thierry Reding
@ 2021-03-26 15:29 ` Dmitry Osipenko
  2021-03-26 16:35   ` Thierry Reding
  9 siblings, 1 reply; 23+ messages in thread
From: Dmitry Osipenko @ 2021-03-26 15:29 UTC (permalink / raw)
  To: Thierry Reding, Will Deacon, Robin Murphy, Joerg Roedel,
	Krzysztof Kozlowski
  Cc: linux-tegra, iommu, Nicolin Chen, linux-arm-kernel, Jon Hunter

25.03.2021 16:03, Thierry Reding пишет:
> From: Thierry Reding <treding@nvidia.com>
> 
> Hi,
> 
> this is a set of patches that is the result of earlier discussions
> regarding early identity mappings that are needed to avoid SMMU faults
> during early boot.
> 
> The goal here is to avoid early identity mappings altogether and instead
> postpone the need for the identity mappings to when devices are attached
> to the SMMU. This works by making the SMMU driver coordinate with the
> memory controller driver on when to start enforcing SMMU translations.
> This makes Tegra behave in a more standard way and pushes the code to
> deal with the Tegra-specific programming into the NVIDIA SMMU
> implementation.

It is an interesting idea which inspired me to try to apply a somewhat similar thing to Tegra SMMU driver by holding the SMMU ASID enable-bit until display driver allows to toggle it. This means that we will need an extra small tegra-specific SMMU API function, but it should be okay.

I typed a patch and seems it's working good, I'll prepare a proper patch if you like it.

What do you think about this:

diff --git a/drivers/gpu/drm/grate/dc.c b/drivers/gpu/drm/grate/dc.c
index 45a41586f153..8874cfba40a1 100644
--- a/drivers/gpu/drm/grate/dc.c
+++ b/drivers/gpu/drm/grate/dc.c
@@ -17,6 +17,7 @@
 #include <linux/reset.h>
 
 #include <soc/tegra/common.h>
+#include <soc/tegra/mc.h>
 #include <soc/tegra/pmc.h>
 
 #include <drm/drm_atomic.h>
@@ -2640,6 +2641,11 @@ static int tegra_dc_init(struct host1x_client *client)
 		return err;
 	}
 
+	if (dc->soc->sync_smmu) {
+		struct iommu_domain *domain = iommu_get_domain_for_dev(dc->dev);
+		tegra_smmu_sync_domain(domain, dc->dev);
+	}
+
 	if (dc->soc->wgrps)
 		primary = tegra_dc_add_shared_planes(drm, dc);
 	else
@@ -2824,6 +2830,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
 	.has_win_b_vfilter_mem_client = true,
 	.has_win_c_without_vert_filter = true,
 	.plane_tiled_memory_bandwidth_x2 = false,
+	.sync_smmu = false,
 };
 
 static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
@@ -2846,6 +2853,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
 	.has_win_b_vfilter_mem_client = true,
 	.has_win_c_without_vert_filter = false,
 	.plane_tiled_memory_bandwidth_x2 = true,
+	.sync_smmu = true,
 };
 
 static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
@@ -2868,6 +2876,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
 	.has_win_b_vfilter_mem_client = false,
 	.has_win_c_without_vert_filter = false,
 	.plane_tiled_memory_bandwidth_x2 = true,
+	.sync_smmu = true,
 };
 
 static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
@@ -2890,6 +2899,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
 	.has_win_b_vfilter_mem_client = false,
 	.has_win_c_without_vert_filter = false,
 	.plane_tiled_memory_bandwidth_x2 = false,
+	.sync_smmu = true,
 };
 
 static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
@@ -2912,6 +2922,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
 	.has_win_b_vfilter_mem_client = false,
 	.has_win_c_without_vert_filter = false,
 	.plane_tiled_memory_bandwidth_x2 = false,
+	.sync_smmu = true,
 };
 
 static const struct tegra_windowgroup_soc tegra186_dc_wgrps[] = {
@@ -2961,6 +2972,7 @@ static const struct tegra_dc_soc_info tegra186_dc_soc_info = {
 	.wgrps = tegra186_dc_wgrps,
 	.num_wgrps = ARRAY_SIZE(tegra186_dc_wgrps),
 	.plane_tiled_memory_bandwidth_x2 = false,
+	.sync_smmu = false,
 };
 
 static const struct tegra_windowgroup_soc tegra194_dc_wgrps[] = {
@@ -3010,6 +3022,7 @@ static const struct tegra_dc_soc_info tegra194_dc_soc_info = {
 	.wgrps = tegra194_dc_wgrps,
 	.num_wgrps = ARRAY_SIZE(tegra194_dc_wgrps),
 	.plane_tiled_memory_bandwidth_x2 = false,
+	.sync_smmu = false,
 };
 
 static const struct of_device_id tegra_dc_of_match[] = {
diff --git a/drivers/gpu/drm/grate/dc.h b/drivers/gpu/drm/grate/dc.h
index 316a56131cf1..e0057bf7be99 100644
--- a/drivers/gpu/drm/grate/dc.h
+++ b/drivers/gpu/drm/grate/dc.h
@@ -91,6 +91,7 @@ struct tegra_dc_soc_info {
 	bool has_win_b_vfilter_mem_client;
 	bool has_win_c_without_vert_filter;
 	bool plane_tiled_memory_bandwidth_x2;
+	bool sync_smmu;
 };
 
 struct tegra_dc {
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 602aab98c079..e750b1844a88 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -47,6 +47,9 @@ struct tegra_smmu {
 	struct dentry *debugfs;
 
 	struct iommu_device iommu;	/* IOMMU Core code handle */
+
+	bool display_synced[2];
+	bool display_enabled[2];
 };
 
 struct tegra_smmu_as {
@@ -78,6 +81,10 @@ static inline u32 smmu_readl(struct tegra_smmu *smmu, unsigned long offset)
 	return readl(smmu->regs + offset);
 }
 
+/* all Tegra SoCs use the same group IDs for displays */
+#define SMMU_SWGROUP_DC		1
+#define SMMU_SWGROUP_DCB	2
+
 #define SMMU_CONFIG 0x010
 #define  SMMU_CONFIG_ENABLE (1 << 0)
 
@@ -253,6 +260,20 @@ static inline void smmu_flush(struct tegra_smmu *smmu)
 	smmu_readl(smmu, SMMU_PTB_ASID);
 }
 
+static int smmu_swgroup_to_display_id(unsigned int swgroup)
+{
+	switch (swgroup) {
+	case SMMU_SWGROUP_DC:
+		return 0;
+
+	case SMMU_SWGROUP_DCB:
+		return 1;
+
+	default:
+		return -1;
+	}
+}
+
 static int tegra_smmu_alloc_asid(struct tegra_smmu *smmu, unsigned int *idp)
 {
 	unsigned long id;
@@ -352,10 +373,21 @@ tegra_smmu_find_swgroup(struct tegra_smmu *smmu, unsigned int swgroup)
 static void tegra_smmu_enable(struct tegra_smmu *smmu, unsigned int swgroup,
 			      unsigned int asid)
 {
+	const int disp_id = smmu_swgroup_to_display_id(swgroup);
 	const struct tegra_smmu_swgroup *group;
 	unsigned int i;
 	u32 value;
 
+	if (disp_id >= 0) {
+		smmu->display_enabled[disp_id] = true;
+
+		if (!smmu->display_synced[disp_id]) {
+			pr_debug("%s deferred for swgroup %u\n",
+				 __func__, swgroup);
+			return;
+		}
+	}
+
 	group = tegra_smmu_find_swgroup(smmu, swgroup);
 	if (group) {
 		value = smmu_readl(smmu, group->reg);
@@ -385,10 +417,14 @@ static void tegra_smmu_enable(struct tegra_smmu *smmu, unsigned int swgroup,
 static void tegra_smmu_disable(struct tegra_smmu *smmu, unsigned int swgroup,
 			       unsigned int asid)
 {
+	const int disp_id = smmu_swgroup_to_display_id(swgroup);
 	const struct tegra_smmu_swgroup *group;
 	unsigned int i;
 	u32 value;
 
+	if (disp_id >= 0)
+		smmu->display_enabled[disp_id] = false;
+
 	group = tegra_smmu_find_swgroup(smmu, swgroup);
 	if (group) {
 		value = smmu_readl(smmu, group->reg);
@@ -410,6 +446,32 @@ static void tegra_smmu_disable(struct tegra_smmu *smmu, unsigned int swgroup,
 	}
 }
 
+void tegra_smmu_sync_domain(struct iommu_domain *domain, struct device *dev)
+{
+	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+	struct tegra_smmu *smmu = dev_iommu_priv_get(dev);
+	unsigned int index;
+
+	if (!fwspec || !domain)
+		return;
+
+	for (index = 0; index < fwspec->num_ids; index++) {
+		const unsigned int swgroup = fwspec->ids[index];
+		const int disp_id = smmu_swgroup_to_display_id(swgroup);
+
+		if (disp_id < 0 || smmu->display_synced[disp_id])
+			continue;
+
+		smmu->display_synced[disp_id] = true;
+
+		if (!smmu->display_enabled[disp_id])
+			continue;
+
+		tegra_smmu_enable(smmu, swgroup, to_smmu_as(domain)->id);
+	}
+}
+EXPORT_SYMBOL_GPL(tegra_smmu_sync_domain);
+
 static int tegra_smmu_as_prepare(struct tegra_smmu *smmu,
 				 struct tegra_smmu_as *as)
 {
diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h
index cfd3b35e23e5..ac1f3226b2ac 100644
--- a/include/soc/tegra/mc.h
+++ b/include/soc/tegra/mc.h
@@ -15,6 +15,7 @@
 
 struct clk;
 struct device;
+struct iommu_domain;
 struct page;
 
 struct tegra_smmu_enable {
@@ -88,6 +89,7 @@ struct tegra_smmu *tegra_smmu_probe(struct device *dev,
 				    const struct tegra_smmu_soc *soc,
 				    struct tegra_mc *mc);
 void tegra_smmu_remove(struct tegra_smmu *smmu);
+void tegra_smmu_sync_domain(struct iommu_domain *domain, struct device *dev);
 #else
 static inline struct tegra_smmu *
 tegra_smmu_probe(struct device *dev, const struct tegra_smmu_soc *soc,
@@ -99,6 +101,11 @@ tegra_smmu_probe(struct device *dev, const struct tegra_smmu_soc *soc,
 static inline void tegra_smmu_remove(struct tegra_smmu *smmu)
 {
 }
+
+static inline void tegra_smmu_sync_domain(struct iommu_domain *domain,
+					  struct device *dev)
+{
+}
 #endif
 
 #ifdef CONFIG_TEGRA_IOMMU_GART
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH 0/9] arm64: tegra: Prevent early SMMU faults
  2021-03-26 15:29 ` [PATCH 0/9] arm64: tegra: Prevent early SMMU faults Dmitry Osipenko
@ 2021-03-26 16:35   ` Thierry Reding
  2021-03-26 16:55     ` Dmitry Osipenko
  0 siblings, 1 reply; 23+ messages in thread
From: Thierry Reding @ 2021-03-26 16:35 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Krzysztof Kozlowski, Will Deacon, Jon Hunter, iommu,
	Nicolin Chen, linux-tegra, Robin Murphy, linux-arm-kernel


[-- Attachment #1.1: Type: text/plain, Size: 2139 bytes --]

On Fri, Mar 26, 2021 at 06:29:28PM +0300, Dmitry Osipenko wrote:
> 25.03.2021 16:03, Thierry Reding пишет:
> > From: Thierry Reding <treding@nvidia.com>
> > 
> > Hi,
> > 
> > this is a set of patches that is the result of earlier discussions
> > regarding early identity mappings that are needed to avoid SMMU faults
> > during early boot.
> > 
> > The goal here is to avoid early identity mappings altogether and instead
> > postpone the need for the identity mappings to when devices are attached
> > to the SMMU. This works by making the SMMU driver coordinate with the
> > memory controller driver on when to start enforcing SMMU translations.
> > This makes Tegra behave in a more standard way and pushes the code to
> > deal with the Tegra-specific programming into the NVIDIA SMMU
> > implementation.
> 
> It is an interesting idea which inspired me to try to apply a somewhat similar thing to Tegra SMMU driver by holding the SMMU ASID enable-bit until display driver allows to toggle it. This means that we will need an extra small tegra-specific SMMU API function, but it should be okay.
> 
> I typed a patch and seems it's working good, I'll prepare a proper patch if you like it.

That would actually be working around the problem that this patch was
supposed to prepare for. The reason for this current patch series is to
make sure SMMU translation isn't enabled until a device has actually
been attached to the SMMU. Once it has been attached, the assumption is
that any identity mappings will have been created.

One Tegra SMMU that shouldn't be a problem because translations aren't
enabled until device attach time. So in other words this patch set is to
get Tegra186 and later to parity with earlier chips from this point of
view.

I think the problem that you're trying to work around is better solved
by establishing these identity mappings. I do have patches to implement
this for Tegra210 and earlier, though they may require additional work
if you have bootloaders that don't use standard DT bindings for passing
information about the framebuffer to the kernel.

Thierry

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 156 bytes --]

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 0/9] arm64: tegra: Prevent early SMMU faults
  2021-03-26 16:35   ` Thierry Reding
@ 2021-03-26 16:55     ` Dmitry Osipenko
  2021-03-26 22:05       ` Dmitry Osipenko
  0 siblings, 1 reply; 23+ messages in thread
From: Dmitry Osipenko @ 2021-03-26 16:55 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Krzysztof Kozlowski, Will Deacon, Jon Hunter, iommu,
	Nicolin Chen, linux-tegra, Robin Murphy, linux-arm-kernel

26.03.2021 19:35, Thierry Reding пишет:
> On Fri, Mar 26, 2021 at 06:29:28PM +0300, Dmitry Osipenko wrote:
>> 25.03.2021 16:03, Thierry Reding пишет:
>>> From: Thierry Reding <treding@nvidia.com>
>>>
>>> Hi,
>>>
>>> this is a set of patches that is the result of earlier discussions
>>> regarding early identity mappings that are needed to avoid SMMU faults
>>> during early boot.
>>>
>>> The goal here is to avoid early identity mappings altogether and instead
>>> postpone the need for the identity mappings to when devices are attached
>>> to the SMMU. This works by making the SMMU driver coordinate with the
>>> memory controller driver on when to start enforcing SMMU translations.
>>> This makes Tegra behave in a more standard way and pushes the code to
>>> deal with the Tegra-specific programming into the NVIDIA SMMU
>>> implementation.
>>
>> It is an interesting idea which inspired me to try to apply a somewhat similar thing to Tegra SMMU driver by holding the SMMU ASID enable-bit until display driver allows to toggle it. This means that we will need an extra small tegra-specific SMMU API function, but it should be okay.
>>
>> I typed a patch and seems it's working good, I'll prepare a proper patch if you like it.
> 
> That would actually be working around the problem that this patch was
> supposed to prepare for. The reason for this current patch series is to
> make sure SMMU translation isn't enabled until a device has actually
> been attached to the SMMU. Once it has been attached, the assumption is
> that any identity mappings will have been created.
> 
> One Tegra SMMU that shouldn't be a problem because translations aren't
> enabled until device attach time. So in other words this patch set is to
> get Tegra186 and later to parity with earlier chips from this point of
> view.
> 
> I think the problem that you're trying to work around is better solved
> by establishing these identity mappings. I do have patches to implement
> this for Tegra210 and earlier, though they may require additional work
> if you have bootloaders that don't use standard DT bindings for passing
> information about the framebuffer to the kernel.

I'm not sure what else reasonable could be done without upgrading to a
very specific version of firmware, which definitely isn't a variant for
older devices which have a wild variety of bootloaders, customized
use-cases and etc.

We could add a kludge that I'm suggesting as a universal fallback
solution, it should work well for all cases that I care about.

So we could have the variant with identity mappings, and if mapping
isn't provided, then fall back to the kludge.
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 0/9] arm64: tegra: Prevent early SMMU faults
  2021-03-26 16:55     ` Dmitry Osipenko
@ 2021-03-26 22:05       ` Dmitry Osipenko
  0 siblings, 0 replies; 23+ messages in thread
From: Dmitry Osipenko @ 2021-03-26 22:05 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Krzysztof Kozlowski, Will Deacon, Jon Hunter, iommu,
	Nicolin Chen, linux-tegra, Robin Murphy, linux-arm-kernel

26.03.2021 19:55, Dmitry Osipenko пишет:
> 26.03.2021 19:35, Thierry Reding пишет:
>> On Fri, Mar 26, 2021 at 06:29:28PM +0300, Dmitry Osipenko wrote:
>>> 25.03.2021 16:03, Thierry Reding пишет:
>>>> From: Thierry Reding <treding@nvidia.com>
>>>>
>>>> Hi,
>>>>
>>>> this is a set of patches that is the result of earlier discussions
>>>> regarding early identity mappings that are needed to avoid SMMU faults
>>>> during early boot.
>>>>
>>>> The goal here is to avoid early identity mappings altogether and instead
>>>> postpone the need for the identity mappings to when devices are attached
>>>> to the SMMU. This works by making the SMMU driver coordinate with the
>>>> memory controller driver on when to start enforcing SMMU translations.
>>>> This makes Tegra behave in a more standard way and pushes the code to
>>>> deal with the Tegra-specific programming into the NVIDIA SMMU
>>>> implementation.
>>>
>>> It is an interesting idea which inspired me to try to apply a somewhat similar thing to Tegra SMMU driver by holding the SMMU ASID enable-bit until display driver allows to toggle it. This means that we will need an extra small tegra-specific SMMU API function, but it should be okay.
>>>
>>> I typed a patch and seems it's working good, I'll prepare a proper patch if you like it.
>>
>> That would actually be working around the problem that this patch was
>> supposed to prepare for. The reason for this current patch series is to
>> make sure SMMU translation isn't enabled until a device has actually
>> been attached to the SMMU. Once it has been attached, the assumption is
>> that any identity mappings will have been created.
>>
>> One Tegra SMMU that shouldn't be a problem because translations aren't
>> enabled until device attach time. So in other words this patch set is to
>> get Tegra186 and later to parity with earlier chips from this point of
>> view.
>>
>> I think the problem that you're trying to work around is better solved
>> by establishing these identity mappings. I do have patches to implement
>> this for Tegra210 and earlier, though they may require additional work
>> if you have bootloaders that don't use standard DT bindings for passing
>> information about the framebuffer to the kernel.
> 
> I'm not sure what else reasonable could be done without upgrading to a
> very specific version of firmware, which definitely isn't a variant for
> older devices which have a wild variety of bootloaders, customized
> use-cases and etc.
> 
> We could add a kludge that I'm suggesting as a universal fallback
> solution, it should work well for all cases that I care about.
> 
> So we could have the variant with identity mappings, and if mapping
> isn't provided, then fall back to the kludge.
> 

I tried a slightly different variant of the kludge by holding the ASID's
enable till the first mapping is created for the display clients and
IOMMU_DOMAIN_DMA now works properly (no EMEM errors on boot and etc) and
without a need to change the DC driver.

I also tried to remove the arm_iommu_detach_device() from the VDE driver
and we now have 3 implicit domains in use (DRM, HX, VDE[wasted]) + 1
explicit (VDE) on T30, which works okay for today. So technically we
could support the IOMMU_DOMAIN_DMA with a couple small changes right now
or at least revert the hacks that were needed for Nyan.

But in order to enable IOMMU_DOMAIN_DMA properly, we will need to do
something about the DMA mappings first in the DRM driver and I also
found that implicit IOMMU somehow doesn't work for host1x driver at all,
so this needs to be fixed too.
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2021-03-26 22:05 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-25 13:03 [PATCH 0/9] arm64: tegra: Prevent early SMMU faults Thierry Reding
2021-03-25 13:03 ` [PATCH 1/9] memory: tegra: Move internal data structures into separate header Thierry Reding
2021-03-25 15:12   ` Dmitry Osipenko
2021-03-25 15:52     ` Thierry Reding
2021-03-25 16:11       ` Dmitry Osipenko
2021-03-26 13:21         ` Dmitry Osipenko
2021-03-25 13:03 ` [PATCH 2/9] memory: tegra: Add memory client IDs to tables Thierry Reding
2021-03-25 13:03 ` [PATCH 3/9] memory: tegra: Implement SID override programming Thierry Reding
2021-03-25 14:27   ` Robin Murphy
2021-03-25 15:02     ` Thierry Reding
2021-03-25 13:03 ` [PATCH 4/9] iommu/arm-smmu: Implement ->probe_finalize() Thierry Reding
2021-03-25 14:27   ` Robin Murphy
2021-03-25 13:03 ` [PATCH 5/9] iommu/arm-smmu: tegra: Detect number of instances at runtime Thierry Reding
2021-03-25 14:27   ` Robin Murphy
2021-03-25 13:03 ` [PATCH 6/9] iommu/arm-smmu: tegra: Implement SID override programming Thierry Reding
2021-03-25 13:03 ` [PATCH 7/9] iommu/arm-smmu: Use Tegra implementation on Tegra186 Thierry Reding
2021-03-25 14:27   ` Robin Murphy
2021-03-25 13:03 ` [PATCH 8/9] arm64: tegra: Hook up memory controller to SMMU " Thierry Reding
2021-03-25 13:03 ` [PATCH 9/9] arm64: tegra: Enable SMMU support on Tegra194 Thierry Reding
2021-03-26 15:29 ` [PATCH 0/9] arm64: tegra: Prevent early SMMU faults Dmitry Osipenko
2021-03-26 16:35   ` Thierry Reding
2021-03-26 16:55     ` Dmitry Osipenko
2021-03-26 22:05       ` Dmitry Osipenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).