linux-pm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC 0/7] Support Tegra210 actmon for dynamic EMC scaling
@ 2025-08-29  4:01 Aaron Kling via B4 Relay
  2025-08-29  4:01 ` [PATCH RFC 1/7] dt-bindings: memory: tegra210: Add memory client IDs Aaron Kling via B4 Relay
                   ` (8 more replies)
  0 siblings, 9 replies; 11+ messages in thread
From: Aaron Kling via B4 Relay @ 2025-08-29  4:01 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Rob Herring, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Chanwoo Choi, Dmitry Osipenko
  Cc: linux-kernel, devicetree, linux-tegra, linux-pm, Aaron Kling

This series adds interconnect support to tegra210 MC and EMC, then
enables actmon. This enables dynamic emc scaling.

This series is marked RFC for two reasons:

1) Calculating rate from bandwidth usage results in double the expected
   rate. I thought this might be due to the ram being 64-bit, but the
   related CFG5 register reports 32-bit on both p2371-2180 and
   p3450-0000. I'm using the calculation used for Tegra124 and haven't
   seen seen anything obviously different between the ram handling on
   these archs to cause a different result. I have considered that the
   number of channels might affect the reporting, and factoring in that
   variable does result in the correct rate, but I don't want to assume
   that's correct without confirmation.

2) I am seeing intermittent instability when transitioning to rates of
   204 MHz or below on p2371-2180. I have noted that if the first
   transition to such a state works, then it continues to work for the
   rest of that boot cycle. But the kernel will often panic the first
   time it tries to downclock. I suspect this is a pre-existing issue
   only brought to light now because nothing would ever lower the clock
   rate previously.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
---
Aaron Kling (7):
      dt-bindings: memory: tegra210: Add memory client IDs
      dt-bindings: devfreq: tegra30-actmon: Add Tegra124 fallback for Tegra210
      soc: tegra: fuse: speedo-tegra210: Add soc speedo 2
      memory: tegra210: Support interconnect framework
      arm64: tegra: tegra210: Add actmon
      arm64: tegra: Add interconnect properties to Tegra210 device-tree
      arm64: tegra: Add OPP tables on Tegra210

 .../bindings/devfreq/nvidia,tegra30-actmon.yaml    |  13 +-
 .../boot/dts/nvidia/tegra210-peripherals-opp.dtsi  | 135 ++++++++++
 arch/arm64/boot/dts/nvidia/tegra210.dtsi           |  43 ++++
 drivers/memory/tegra/Kconfig                       |   1 +
 drivers/memory/tegra/tegra210-emc-core.c           | 276 ++++++++++++++++++++-
 drivers/memory/tegra/tegra210-emc.h                |  25 ++
 drivers/memory/tegra/tegra210.c                    |  81 ++++++
 drivers/soc/tegra/fuse/speedo-tegra210.c           |   1 +
 include/dt-bindings/memory/tegra210-mc.h           |  58 +++++
 9 files changed, 626 insertions(+), 7 deletions(-)
---
base-commit: 8f5ae30d69d7543eee0d70083daf4de8fe15d585
change-id: 20250822-t210-actmon-34904ce7ed0c
prerequisite-change-id: 20250812-tegra210-speedo-470691e8b8cc:v1
prerequisite-patch-id: 81859c81abbe79aed1cfbc95b4f5bcdc5637d6bd
prerequisite-patch-id: 98bda8855bcc57c59b2231b7808d4478301afe68
prerequisite-patch-id: 6e0b69d42ea542dc9f58b410abd5974644f75dc4
prerequisite-patch-id: 9e3b9b2fdb8d9c2264dfa7641d1aec84fb7aedd9
prerequisite-patch-id: ef4bcc4ddba7898b188fb3fc6e414a2662183f91

Best regards,
-- 
Aaron Kling <webgeek1234@gmail.com>



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

* [PATCH RFC 1/7] dt-bindings: memory: tegra210: Add memory client IDs
  2025-08-29  4:01 [PATCH RFC 0/7] Support Tegra210 actmon for dynamic EMC scaling Aaron Kling via B4 Relay
@ 2025-08-29  4:01 ` Aaron Kling via B4 Relay
  2025-08-29  4:01 ` [PATCH RFC 2/7] dt-bindings: devfreq: tegra30-actmon: Add Tegra124 fallback for Tegra210 Aaron Kling via B4 Relay
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Aaron Kling via B4 Relay @ 2025-08-29  4:01 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Rob Herring, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Chanwoo Choi, Dmitry Osipenko
  Cc: linux-kernel, devicetree, linux-tegra, linux-pm, Aaron Kling

From: Aaron Kling <webgeek1234@gmail.com>

Each memory client has unique hardware ID, add these IDs.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
---
 include/dt-bindings/memory/tegra210-mc.h | 58 ++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/include/dt-bindings/memory/tegra210-mc.h b/include/dt-bindings/memory/tegra210-mc.h
index 5e082547f1794cba1f72872782e04d8747863b6d..48474942a000e049142014e3bcc132b88bf1a92d 100644
--- a/include/dt-bindings/memory/tegra210-mc.h
+++ b/include/dt-bindings/memory/tegra210-mc.h
@@ -75,4 +75,62 @@
 #define TEGRA210_MC_RESET_ETR		28
 #define TEGRA210_MC_RESET_TSECB		29
 
+#define TEGRA210_MC_PTCR		0
+#define TEGRA210_MC_DISPLAY0A		1
+#define TEGRA210_MC_DISPLAY0AB		2
+#define TEGRA210_MC_DISPLAY0B		3
+#define TEGRA210_MC_DISPLAY0BB		4
+#define TEGRA210_MC_DISPLAY0C		5
+#define TEGRA210_MC_DISPLAY0CB		6
+#define TEGRA210_MC_AFIR		14
+#define TEGRA210_MC_AVPCARM7R		15
+#define TEGRA210_MC_DISPLAYHC		16
+#define TEGRA210_MC_DISPLAYHCB		17
+#define TEGRA210_MC_HDAR		21
+#define TEGRA210_MC_HOST1XDMAR		22
+#define TEGRA210_MC_HOST1XR		23
+#define TEGRA210_MC_NVENCSRD		28
+#define TEGRA210_MC_PPCSAHBDMAR		29
+#define TEGRA210_MC_PPCSAHBSLVR		30
+#define TEGRA210_MC_SATAR		31
+#define TEGRA210_MC_MPCORER		39
+#define TEGRA210_MC_NVENCSWR		43
+#define TEGRA210_MC_AFIW		49
+#define TEGRA210_MC_AVPCARM7W		50
+#define TEGRA210_MC_HDAW		53
+#define TEGRA210_MC_HOST1XW		54
+#define TEGRA210_MC_MPCOREW		57
+#define TEGRA210_MC_PPCSAHBDMAW		59
+#define TEGRA210_MC_PPCSAHBSLVW		60
+#define TEGRA210_MC_SATAW		61
+#define TEGRA210_MC_ISPRA		68
+#define TEGRA210_MC_ISPWA		70
+#define TEGRA210_MC_ISPWB		71
+#define TEGRA210_MC_XUSB_HOSTR		74
+#define TEGRA210_MC_XUSB_HOSTW		75
+#define TEGRA210_MC_XUSB_DEVR		76
+#define TEGRA210_MC_XUSB_DEVW		77
+#define TEGRA210_MC_ISPRAB		78
+#define TEGRA210_MC_ISPWAB		80
+#define TEGRA210_MC_ISPWBB		81
+#define TEGRA210_MC_TSECSRD		84
+#define TEGRA210_MC_TSECSWR		85
+#define TEGRA210_MC_A9AVPSCR		86
+#define TEGRA210_MC_A9AVPSCW		87
+#define TEGRA210_MC_GPUSRD		88
+#define TEGRA210_MC_GPUSWR		89
+#define TEGRA210_MC_DISPLAYT		90
+#define TEGRA210_MC_SDMMCRA		96
+#define TEGRA210_MC_SDMMCRAA		97
+#define TEGRA210_MC_SDMMCR		98
+#define TEGRA210_MC_SDMMCRAB		99
+#define TEGRA210_MC_SDMMCWA		100
+#define TEGRA210_MC_SDMMCWAA		101
+#define TEGRA210_MC_SDMMCW		102
+#define TEGRA210_MC_SDMMCWAB		103
+#define TEGRA210_MC_VICSRD		108
+#define TEGRA210_MC_VICSWR		109
+#define TEGRA210_MC_VIW			114
+#define TEGRA210_MC_DISPLAYD		115
+
 #endif

-- 
2.50.1



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

* [PATCH RFC 2/7] dt-bindings: devfreq: tegra30-actmon: Add Tegra124 fallback for Tegra210
  2025-08-29  4:01 [PATCH RFC 0/7] Support Tegra210 actmon for dynamic EMC scaling Aaron Kling via B4 Relay
  2025-08-29  4:01 ` [PATCH RFC 1/7] dt-bindings: memory: tegra210: Add memory client IDs Aaron Kling via B4 Relay
@ 2025-08-29  4:01 ` Aaron Kling via B4 Relay
  2025-08-29  4:01 ` [PATCH RFC 3/7] soc: tegra: fuse: speedo-tegra210: Add soc speedo 2 Aaron Kling via B4 Relay
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Aaron Kling via B4 Relay @ 2025-08-29  4:01 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Rob Herring, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Chanwoo Choi, Dmitry Osipenko
  Cc: linux-kernel, devicetree, linux-tegra, linux-pm, Aaron Kling

From: Aaron Kling <webgeek1234@gmail.com>

The Tegra210 actmon is compatible with the existing Tegra124 driver.
Describe the compatibles as such.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
---
 .../devicetree/bindings/devfreq/nvidia,tegra30-actmon.yaml  | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/devfreq/nvidia,tegra30-actmon.yaml b/Documentation/devicetree/bindings/devfreq/nvidia,tegra30-actmon.yaml
index e3379d1067283e36d1bee303187c0205b410f610..ea1dc86bc31f635f91a0e36f908f5c0c4f9a804c 100644
--- a/Documentation/devicetree/bindings/devfreq/nvidia,tegra30-actmon.yaml
+++ b/Documentation/devicetree/bindings/devfreq/nvidia,tegra30-actmon.yaml
@@ -19,11 +19,14 @@ description: |
 
 properties:
   compatible:
-    enum:
-      - nvidia,tegra30-actmon
-      - nvidia,tegra114-actmon
-      - nvidia,tegra124-actmon
-      - nvidia,tegra210-actmon
+    oneOf:
+      - enum:
+          - nvidia,tegra30-actmon
+          - nvidia,tegra114-actmon
+          - nvidia,tegra124-actmon
+      - items:
+          - const: nvidia,tegra210-actmon
+          - const: nvidia,tegra124-actmon
 
   reg:
     maxItems: 1

-- 
2.50.1



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

* [PATCH RFC 3/7] soc: tegra: fuse: speedo-tegra210: Add soc speedo 2
  2025-08-29  4:01 [PATCH RFC 0/7] Support Tegra210 actmon for dynamic EMC scaling Aaron Kling via B4 Relay
  2025-08-29  4:01 ` [PATCH RFC 1/7] dt-bindings: memory: tegra210: Add memory client IDs Aaron Kling via B4 Relay
  2025-08-29  4:01 ` [PATCH RFC 2/7] dt-bindings: devfreq: tegra30-actmon: Add Tegra124 fallback for Tegra210 Aaron Kling via B4 Relay
@ 2025-08-29  4:01 ` Aaron Kling via B4 Relay
  2025-08-29  4:01 ` [PATCH RFC 4/7] memory: tegra210: Support interconnect framework Aaron Kling via B4 Relay
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Aaron Kling via B4 Relay @ 2025-08-29  4:01 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Rob Herring, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Chanwoo Choi, Dmitry Osipenko
  Cc: linux-kernel, devicetree, linux-tegra, linux-pm, Aaron Kling

From: Aaron Kling <webgeek1234@gmail.com>

The Jetson Nano series of modules only have 2 emc table entries,
different from other soc sku's. As the emc driver uses the soc speedo to
populate the emc opp tables, add a new speedo id to uniquely identify
this.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
---
 drivers/soc/tegra/fuse/speedo-tegra210.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/soc/tegra/fuse/speedo-tegra210.c b/drivers/soc/tegra/fuse/speedo-tegra210.c
index 1cdd70c59c0753e602709f9179c0ab67d1b8f5e3..56d7b0858050b7e5bc931a9491d68b1ce7cc427c 100644
--- a/drivers/soc/tegra/fuse/speedo-tegra210.c
+++ b/drivers/soc/tegra/fuse/speedo-tegra210.c
@@ -101,6 +101,7 @@ static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info,
 
 	case 0x8F:
 		if (speedo_rev >= 2) {
+			sku_info->soc_speedo_id = 2;
 			sku_info->cpu_speedo_id = 9;
 			sku_info->gpu_speedo_id = 2;
 			break;

-- 
2.50.1



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

* [PATCH RFC 4/7] memory: tegra210: Support interconnect framework
  2025-08-29  4:01 [PATCH RFC 0/7] Support Tegra210 actmon for dynamic EMC scaling Aaron Kling via B4 Relay
                   ` (2 preceding siblings ...)
  2025-08-29  4:01 ` [PATCH RFC 3/7] soc: tegra: fuse: speedo-tegra210: Add soc speedo 2 Aaron Kling via B4 Relay
@ 2025-08-29  4:01 ` Aaron Kling via B4 Relay
  2025-08-29  4:01 ` [PATCH RFC 5/7] arm64: tegra: tegra210: Add actmon Aaron Kling via B4 Relay
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Aaron Kling via B4 Relay @ 2025-08-29  4:01 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Rob Herring, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Chanwoo Choi, Dmitry Osipenko
  Cc: linux-kernel, devicetree, linux-tegra, linux-pm, Aaron Kling

From: Aaron Kling <webgeek1234@gmail.com>

This makes mc and emc interconnect providers and allows for dynamic
memory clock scaling.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
---
 drivers/memory/tegra/Kconfig             |   1 +
 drivers/memory/tegra/tegra210-emc-core.c | 276 ++++++++++++++++++++++++++++++-
 drivers/memory/tegra/tegra210-emc.h      |  25 +++
 drivers/memory/tegra/tegra210.c          |  81 +++++++++
 4 files changed, 381 insertions(+), 2 deletions(-)

diff --git a/drivers/memory/tegra/Kconfig b/drivers/memory/tegra/Kconfig
index fc5a277918267ee8240f9fb9efeb80275db4790b..2d0be29afe2b9ebf9a0630ef7fb6fb43ff359499 100644
--- a/drivers/memory/tegra/Kconfig
+++ b/drivers/memory/tegra/Kconfig
@@ -55,6 +55,7 @@ config TEGRA210_EMC
 	tristate "NVIDIA Tegra210 External Memory Controller driver"
 	depends on ARCH_TEGRA_210_SOC || COMPILE_TEST
 	select TEGRA210_EMC_TABLE
+	select PM_OPP
 	help
 	  This driver is for the External Memory Controller (EMC) found on
 	  Tegra210 chips. The EMC controls the external DRAM on the board.
diff --git a/drivers/memory/tegra/tegra210-emc-core.c b/drivers/memory/tegra/tegra210-emc-core.c
index e96ca4157d48182574310f8caf72687bed7cc16a..b2ae35353ff5e0059b2ec5ab719c55b23b05bb6a 100644
--- a/drivers/memory/tegra/tegra210-emc-core.c
+++ b/drivers/memory/tegra/tegra210-emc-core.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/of_reserved_mem.h>
 #include <linux/platform_device.h>
+#include <linux/pm_opp.h>
 #include <linux/slab.h>
 #include <linux/thermal.h>
 #include <soc/tegra/fuse.h>
@@ -1569,6 +1570,79 @@ static int tegra210_emc_set_rate(struct device *dev,
 	return 0;
 }
 
+static void tegra_emc_rate_requests_init(struct tegra210_emc *emc)
+{
+	unsigned int i;
+
+	for (i = 0; i < EMC_RATE_TYPE_MAX; i++) {
+		emc->requested_rate[i].min_rate = 0;
+		emc->requested_rate[i].max_rate = ULONG_MAX;
+	}
+}
+
+static int emc_request_rate(struct tegra210_emc *emc,
+			    unsigned long new_min_rate,
+			    unsigned long new_max_rate,
+			    enum emc_rate_request_type type)
+{
+	struct emc_rate_request *req = emc->requested_rate;
+	unsigned long min_rate = 0, max_rate = ULONG_MAX;
+	unsigned int i;
+	int err;
+
+	/* select minimum and maximum rates among the requested rates */
+	for (i = 0; i < EMC_RATE_TYPE_MAX; i++, req++) {
+		if (i == type) {
+			min_rate = max(new_min_rate, min_rate);
+			max_rate = min(new_max_rate, max_rate);
+		} else {
+			min_rate = max(req->min_rate, min_rate);
+			max_rate = min(req->max_rate, max_rate);
+		}
+	}
+
+	if (min_rate > max_rate) {
+		dev_err_ratelimited(emc->dev, "%s: type %u: out of range: %lu %lu\n",
+				    __func__, type, min_rate, max_rate);
+		return -ERANGE;
+	}
+
+	err = clk_set_rate(emc->clk, min_rate);
+	if (err)
+		return err;
+
+	emc->requested_rate[type].min_rate = new_min_rate;
+	emc->requested_rate[type].max_rate = new_max_rate;
+
+	return 0;
+}
+
+static int emc_set_min_rate(struct tegra210_emc *emc, unsigned long rate,
+			    enum emc_rate_request_type type)
+{
+	struct emc_rate_request *req = &emc->requested_rate[type];
+	int ret;
+
+	mutex_lock(&emc->rate_lock);
+	ret = emc_request_rate(emc, rate, req->max_rate, type);
+	mutex_unlock(&emc->rate_lock);
+
+	return ret;
+}
+
+static int emc_set_max_rate(struct tegra210_emc *emc, unsigned long rate,
+			    enum emc_rate_request_type type)
+{
+	struct emc_rate_request *req = &emc->requested_rate[type];
+	int ret;
+
+	mutex_lock(&emc->rate_lock);
+	ret = emc_request_rate(emc, req->min_rate, rate, type);
+	mutex_unlock(&emc->rate_lock);
+
+	return ret;
+}
+
 /*
  * debugfs interface
  *
@@ -1641,7 +1715,7 @@ static int tegra210_emc_debug_min_rate_set(void *data, u64 rate)
 	if (!tegra210_emc_validate_rate(emc, rate))
 		return -EINVAL;
 
-	err = clk_set_min_rate(emc->clk, rate);
+	err = emc_set_min_rate(emc, rate, EMC_RATE_DEBUG);
 	if (err < 0)
 		return err;
 
@@ -1671,7 +1745,7 @@ static int tegra210_emc_debug_max_rate_set(void *data, u64 rate)
 	if (!tegra210_emc_validate_rate(emc, rate))
 		return -EINVAL;
 
-	err = clk_set_max_rate(emc->clk, rate);
+	err = emc_set_max_rate(emc, rate, EMC_RATE_DEBUG);
 	if (err < 0)
 		return err;
 
@@ -1758,6 +1832,188 @@ static void tegra210_emc_debugfs_init(struct tegra210_emc *emc)
 			    &tegra210_emc_debug_temperature_fops);
 }
 
+static inline struct tegra210_emc *
+to_tegra210_emc_provider(struct icc_provider *provider)
+{
+	return container_of(provider, struct tegra210_emc, icc_provider);
+}
+
+static struct icc_node_data *
+emc_of_icc_xlate_extended(const struct of_phandle_args *spec, void *data)
+{
+	struct icc_provider *provider = data;
+	struct icc_node_data *ndata;
+	struct icc_node *node;
+
+	/* External Memory is the only possible ICC route */
+	list_for_each_entry(node, &provider->nodes, node_list) {
+		if (node->id != TEGRA_ICC_EMEM)
+			continue;
+
+		ndata = kzalloc(sizeof(*ndata), GFP_KERNEL);
+		if (!ndata)
+			return ERR_PTR(-ENOMEM);
+
+		/*
+		 * SRC and DST nodes should have matching TAG in order to have
+		 * it set by default for a requested path.
+		 */
+		ndata->tag = TEGRA_MC_ICC_TAG_ISO;
+		ndata->node = node;
+
+		return ndata;
+	}
+
+	return ERR_PTR(-EPROBE_DEFER);
+}
+
+static int emc_icc_set(struct icc_node *src, struct icc_node *dst)
+{
+	struct tegra210_emc *emc = to_tegra210_emc_provider(dst->provider);
+	unsigned long long peak_bw = icc_units_to_bps(dst->peak_bw);
+	unsigned long long avg_bw = icc_units_to_bps(dst->avg_bw);
+	unsigned long long rate = max(avg_bw, peak_bw);
+	unsigned int dram_data_bus_width_bytes;
+	const unsigned int ddr = 2;
+	int err;
+
+	/*
+	 * Tegra210 EMC runs on a clock rate of SDRAM bus. This means that
+	 * EMC clock rate is twice smaller than the peak data rate because
+	 * data is sampled on both EMC clock edges.
+	 */
+	dram_data_bus_width_bytes = emc->dram_bus_width / 8;
+	do_div(rate, ddr * dram_data_bus_width_bytes);
+	rate = min_t(u64, rate, U32_MAX);
+
+	err = emc_set_min_rate(emc, rate, EMC_RATE_ICC);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int tegra_emc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
+{
+	*avg = 0;
+	*peak = 0;
+
+	return 0;
+}
+
+static int tegra_emc_interconnect_init(struct tegra210_emc *emc)
+{
+	const struct tegra_mc_soc *soc = emc->mc->soc;
+	struct icc_node *node;
+	int err;
+
+	emc->icc_provider.dev = emc->dev;
+	emc->icc_provider.set = emc_icc_set;
+	emc->icc_provider.data = &emc->icc_provider;
+	emc->icc_provider.aggregate = soc->icc_ops->aggregate;
+	emc->icc_provider.xlate_extended = emc_of_icc_xlate_extended;
+	emc->icc_provider.get_bw = tegra_emc_icc_get_init_bw;
+
+	icc_provider_init(&emc->icc_provider);
+
+	/* create External Memory Controller node */
+	node = icc_node_create(TEGRA_ICC_EMC);
+	if (IS_ERR(node)) {
+		err = PTR_ERR(node);
+		goto err_msg;
+	}
+
+	node->name = "External Memory Controller";
+	icc_node_add(node, &emc->icc_provider);
+
+	/* link External Memory Controller to External Memory (DRAM) */
+	err = icc_link_create(node, TEGRA_ICC_EMEM);
+	if (err)
+		goto remove_nodes;
+
+	/* create External Memory node */
+	node = icc_node_create(TEGRA_ICC_EMEM);
+	if (IS_ERR(node)) {
+		err = PTR_ERR(node);
+		goto remove_nodes;
+	}
+
+	node->name = "External Memory (DRAM)";
+	icc_node_add(node, &emc->icc_provider);
+
+	err = icc_provider_register(&emc->icc_provider);
+	if (err)
+		goto remove_nodes;
+
+	return 0;
+
+remove_nodes:
+	icc_nodes_remove(&emc->icc_provider);
+err_msg:
+	dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
+
+	return err;
+}
+
+static int tegra_emc_opp_table_init(struct tegra210_emc *emc)
+{
+	u32 hw_version = BIT(tegra_sku_info.soc_speedo_id);
+	struct dev_pm_opp *opp;
+	unsigned long rate;
+	int opp_token, err, max_opps, i;
+
+	err = dev_pm_opp_set_supported_hw(emc->dev, &hw_version, 1);
+	if (err < 0) {
+		dev_err(emc->dev, "failed to set OPP supported HW: %d\n", err);
+		return err;
+	}
+	opp_token = err;
+
+	err = dev_pm_opp_of_add_table(emc->dev);
+	if (err) {
+		if (err == -ENODEV)
+			dev_err(emc->dev, "OPP table not found, please update your device tree\n");
+		else
+			dev_err(emc->dev, "failed to add OPP table: %d\n", err);
+
+		goto put_hw_table;
+	}
+
+	max_opps = dev_pm_opp_get_opp_count(emc->dev);
+	if (max_opps <= 0) {
+		dev_err(emc->dev, "Failed to add OPPs\n");
+		goto remove_table;
+	}
+
+	if (emc->num_timings != max_opps) {
+		dev_err(emc->dev, "OPP table does not match emc table\n");
+		goto remove_table;
+	}
+
+	for (i = 0; i < emc->num_timings; i++) {
+		rate = emc->timings[i].rate * 1000;
+		opp = dev_pm_opp_find_freq_exact(emc->dev, rate, true);
+		if (IS_ERR(opp)) {
+			dev_err(emc->dev, "Rate %lu not found in OPP table\n", rate);
+			goto remove_table;
+		}
+
+		dev_pm_opp_put(opp);
+	}
+
+	dev_info_once(emc->dev, "OPP HW ver. 0x%x, current clock rate %lu MHz\n",
+		      hw_version, clk_get_rate(emc->clk) / 1000000);
+
+	return 0;
+
+remove_table:
+	dev_pm_opp_of_remove_table(emc->dev);
+put_hw_table:
+	dev_pm_opp_put_supported_hw(opp_token);
+
+	return err;
+}
+
 static void tegra210_emc_detect(struct tegra210_emc *emc)
 {
 	u32 value;
@@ -1774,6 +2030,13 @@ static void tegra210_emc_detect(struct tegra210_emc *emc)
 	value = emc_readl(emc, EMC_FBIO_CFG5);
 	emc->dram_type = value & 0x3;
 
+	if (value & EMC_FBIO_CFG5_DRAM_WIDTH_X64)
+		emc->dram_bus_width = 64;
+	else
+		emc->dram_bus_width = 32;
+
+	dev_info_once(emc->dev, "%ubit DRAM bus\n", emc->dram_bus_width);
+
 	/* probe the number of channels */
 	value = emc_readl(emc, EMC_FBIO_CFG7);
 
@@ -1964,8 +2227,16 @@ static int tegra210_emc_probe(struct platform_device *pdev)
 
 	timer_setup(&emc->training, tegra210_emc_train, 0);
 
+	err = tegra_emc_opp_table_init(emc);
+	if (err)
+		return err;
+
+	tegra_emc_rate_requests_init(emc);
+
 	tegra210_emc_debugfs_init(emc);
 
+	tegra_emc_interconnect_init(emc);
+
 	cd = devm_thermal_of_cooling_device_register(emc->dev, np, "emc", emc,
 						     &tegra210_emc_cd_ops);
 	if (IS_ERR(cd)) {
@@ -2050,6 +2321,7 @@ static struct platform_driver tegra210_emc_driver = {
 		.name = "tegra210-emc",
 		.of_match_table = tegra210_emc_of_match,
 		.pm = &tegra210_emc_pm_ops,
+		.sync_state = icc_sync_state,
 	},
 	.probe = tegra210_emc_probe,
 	.remove = tegra210_emc_remove,
diff --git a/drivers/memory/tegra/tegra210-emc.h b/drivers/memory/tegra/tegra210-emc.h
index 8988bcf1529072a7bdc93b185ebe0d51d82c1763..270362268c557056fa9bccea0f228c08630411ae 100644
--- a/drivers/memory/tegra/tegra210-emc.h
+++ b/drivers/memory/tegra/tegra210-emc.h
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk/tegra.h>
+#include <linux/interconnect-provider.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
 
@@ -105,6 +106,7 @@
 #define EMC_FBIO_CFG5_DRAM_TYPE_SHIFT				0
 #define EMC_FBIO_CFG5_DRAM_TYPE_MASK				\
 	(0x3 << EMC_FBIO_CFG5_DRAM_TYPE_SHIFT)
+#define EMC_FBIO_CFG5_DRAM_WIDTH_X64				BIT(4)
 #define EMC_FBIO_CFG5_CMD_TX_DIS				BIT(8)
 
 #define EMC_PDEX2CKE						0x118
@@ -784,6 +786,17 @@ enum {
 #define TRIM_REGS_SIZE 138
 #define BURST_REGS_SIZE 221
 
+enum emc_rate_request_type {
+	EMC_RATE_DEBUG,
+	EMC_RATE_ICC,
+	EMC_RATE_TYPE_MAX,
+};
+
+struct emc_rate_request {
+	unsigned long min_rate;
+	unsigned long max_rate;
+};
+
 struct tegra210_emc_per_channel_regs {
 	u16 bank;
 	u16 offset;
@@ -906,6 +919,7 @@ struct tegra210_emc {
 	unsigned int num_channels;
 	unsigned int num_devices;
 	unsigned int dram_type;
+	unsigned int dram_bus_width;
 
 	struct tegra210_emc_timing *last;
 	struct tegra210_emc_timing *next;
@@ -932,6 +946,17 @@ struct tegra210_emc {
 	} debugfs;
 
 	struct tegra210_clk_emc_provider provider;
+
+	struct icc_provider icc_provider;
+
+	/*
+	 * There are multiple sources in the EMC driver which could request
+	 * a min/max clock rate, these rates are contained in this array.
+	 */
+	struct emc_rate_request requested_rate[EMC_RATE_TYPE_MAX];
+
+	/* protect shared rate-change code path */
+	struct mutex rate_lock;
 };
 
 struct tegra210_emc_sequence {
diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c
index 8ab6498dbe7d2f410d4eb262926c18b77edb0b3d..c5f079b60363f86b9b1382182e71bfcea9e19829 100644
--- a/drivers/memory/tegra/tegra210.c
+++ b/drivers/memory/tegra/tegra210.c
@@ -3,6 +3,9 @@
  * Copyright (C) 2015 NVIDIA CORPORATION.  All rights reserved.
  */
 
+#include <linux/of.h>
+#include <linux/device.h>
+
 #include <dt-bindings/memory/tegra210-mc.h>
 
 #include "mc.h"
@@ -1273,6 +1276,83 @@ static const struct tegra_mc_reset tegra210_mc_resets[] = {
 	TEGRA210_MC_RESET(TSECB,     0x970, 0x974, 13),
 };
 
+static int tegra210_mc_icc_set(struct icc_node *src, struct icc_node *dst)
+{
+	/* TODO: program PTSA */
+	return 0;
+}
+
+static int tegra210_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
+				     u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
+{
+	/*
+	 * ISO clients need to reserve extra bandwidth up-front because
+	 * there could be high bandwidth pressure during initial filling
+	 * of the client's FIFO buffers.  Secondly, we need to take into
+	 * account impurities of the memory subsystem.
+	 */
+	if (tag & TEGRA_MC_ICC_TAG_ISO)
+		peak_bw = tegra_mc_scale_percents(peak_bw, 400);
+
+	*agg_avg += avg_bw;
+	*agg_peak = max(*agg_peak, peak_bw);
+
+	return 0;
+}
+
+static struct icc_node_data *
+tegra210_mc_of_icc_xlate_extended(const struct of_phandle_args *spec, void *data)
+{
+	struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
+	const struct tegra_mc_client *client;
+	unsigned int i, idx = spec->args[0];
+	struct icc_node_data *ndata;
+	struct icc_node *node;
+
+	list_for_each_entry(node, &mc->provider.nodes, node_list) {
+		if (node->id != idx)
+			continue;
+
+		ndata = kzalloc(sizeof(*ndata), GFP_KERNEL);
+		if (!ndata)
+			return ERR_PTR(-ENOMEM);
+
+		client = &mc->soc->clients[idx];
+		ndata->node = node;
+
+		switch (client->swgroup) {
+		case TEGRA_SWGROUP_DC:
+		case TEGRA_SWGROUP_DCB:
+		case TEGRA_SWGROUP_PTC:
+		case TEGRA_SWGROUP_VI:
+			/* these clients are isochronous by default */
+			ndata->tag = TEGRA_MC_ICC_TAG_ISO;
+			break;
+
+		default:
+			ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT;
+			break;
+		}
+
+		return ndata;
+	}
+
+	for (i = 0; i < mc->soc->num_clients; i++) {
+		if (mc->soc->clients[i].id == idx)
+			return ERR_PTR(-EPROBE_DEFER);
+	}
+
+	dev_err(mc->dev, "invalid ICC client ID %u\n", idx);
+
+	return ERR_PTR(-EINVAL);
+}
+
+static const struct tegra_mc_icc_ops tegra210_mc_icc_ops = {
+	.xlate_extended = tegra210_mc_of_icc_xlate_extended,
+	.aggregate = tegra210_mc_icc_aggregate,
+	.set = tegra210_mc_icc_set,
+};
+
 const struct tegra_mc_soc tegra210_mc_soc = {
 	.clients = tegra210_mc_clients,
 	.num_clients = ARRAY_SIZE(tegra210_mc_clients),
@@ -1286,5 +1366,6 @@ const struct tegra_mc_soc tegra210_mc_soc = {
 	.reset_ops = &tegra_mc_reset_ops_common,
 	.resets = tegra210_mc_resets,
 	.num_resets = ARRAY_SIZE(tegra210_mc_resets),
+	.icc_ops = &tegra210_mc_icc_ops,
 	.ops = &tegra30_mc_ops,
 };

-- 
2.50.1



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

* [PATCH RFC 5/7] arm64: tegra: tegra210: Add actmon
  2025-08-29  4:01 [PATCH RFC 0/7] Support Tegra210 actmon for dynamic EMC scaling Aaron Kling via B4 Relay
                   ` (3 preceding siblings ...)
  2025-08-29  4:01 ` [PATCH RFC 4/7] memory: tegra210: Support interconnect framework Aaron Kling via B4 Relay
@ 2025-08-29  4:01 ` Aaron Kling via B4 Relay
  2025-08-29  4:01 ` [PATCH RFC 6/7] arm64: tegra: Add interconnect properties to Tegra210 device-tree Aaron Kling via B4 Relay
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Aaron Kling via B4 Relay @ 2025-08-29  4:01 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Rob Herring, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Chanwoo Choi, Dmitry Osipenko
  Cc: linux-kernel, devicetree, linux-tegra, linux-pm, Aaron Kling

From: Aaron Kling <webgeek1234@gmail.com>

This enables the action monitor to facilitate dynamic frequency scaling.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
---
 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 402b0ede1472af625d9d9e811f5af306d436cc98..6da10db893add44a98fde1666c382511212fd43c 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -485,6 +485,18 @@ flow-controller@60007000 {
 		reg = <0x0 0x60007000 0x0 0x1000>;
 	};
 
+	actmon@6000c800 {
+		compatible = "nvidia,tegra210-actmon", "nvidia,tegra124-actmon";
+		reg = <0x0 0x6000c800 0x0 0x400>;
+		interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&tegra_car TEGRA210_CLK_ACTMON>,
+			 <&tegra_car TEGRA210_CLK_EMC>;
+		clock-names = "actmon", "emc";
+		resets = <&tegra_car 119>;
+		reset-names = "actmon";
+		#cooling-cells = <2>;
+	};
+
 	gpio: gpio@6000d000 {
 		compatible = "nvidia,tegra210-gpio", "nvidia,tegra30-gpio";
 		reg = <0x0 0x6000d000 0x0 0x1000>;

-- 
2.50.1



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

* [PATCH RFC 6/7] arm64: tegra: Add interconnect properties to Tegra210 device-tree
  2025-08-29  4:01 [PATCH RFC 0/7] Support Tegra210 actmon for dynamic EMC scaling Aaron Kling via B4 Relay
                   ` (4 preceding siblings ...)
  2025-08-29  4:01 ` [PATCH RFC 5/7] arm64: tegra: tegra210: Add actmon Aaron Kling via B4 Relay
@ 2025-08-29  4:01 ` Aaron Kling via B4 Relay
  2025-08-29  4:01 ` [PATCH RFC 7/7] arm64: tegra: Add OPP tables on Tegra210 Aaron Kling via B4 Relay
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Aaron Kling via B4 Relay @ 2025-08-29  4:01 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Rob Herring, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Chanwoo Choi, Dmitry Osipenko
  Cc: linux-kernel, devicetree, linux-tegra, linux-pm, Aaron Kling

From: Aaron Kling <webgeek1234@gmail.com>

Add interconnect properties to the Memory Controller, External Memory
Controller and the Display Controller nodes in order to describe hardware
interconnection.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
---
 arch/arm64/boot/dts/nvidia/tegra210.dtsi | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 6da10db893add44a98fde1666c382511212fd43c..2fcc7a28690f7100d49e8b93c4fb77de7947b002 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -202,6 +202,19 @@ dc@54200000 {
 
 			nvidia,outputs = <&dsia &dsib &sor0 &sor1>;
 			nvidia,head = <0>;
+
+			interconnects = <&mc TEGRA210_MC_DISPLAY0A &emc>,
+					<&mc TEGRA210_MC_DISPLAY0B &emc>,
+					<&mc TEGRA210_MC_DISPLAY0C &emc>,
+					<&mc TEGRA210_MC_DISPLAYHC &emc>,
+					<&mc TEGRA210_MC_DISPLAYD &emc>,
+					<&mc TEGRA210_MC_DISPLAYT &emc>;
+			interconnect-names = "wina",
+					     "winb",
+					     "winc",
+					     "cursor",
+					     "wind",
+					     "wint";
 		};
 
 		dc@54240000 {
@@ -217,6 +230,15 @@ dc@54240000 {
 
 			nvidia,outputs = <&dsia &dsib &sor0 &sor1>;
 			nvidia,head = <1>;
+
+			interconnects = <&mc TEGRA210_MC_DISPLAY0AB &emc>,
+					<&mc TEGRA210_MC_DISPLAY0BB &emc>,
+					<&mc TEGRA210_MC_DISPLAY0CB &emc>,
+					<&mc TEGRA210_MC_DISPLAYHCB &emc>;
+			interconnect-names = "wina",
+					     "winb",
+					     "winc",
+					     "cursor";
 		};
 
 		dsia: dsi@54300000 {
@@ -990,6 +1012,7 @@ mc: memory-controller@70019000 {
 
 		#iommu-cells = <1>;
 		#reset-cells = <1>;
+		#interconnect-cells = <1>;
 	};
 
 	emc: external-memory-controller@7001b000 {
@@ -1001,6 +1024,7 @@ emc: external-memory-controller@7001b000 {
 		clock-names = "emc";
 		interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
 		nvidia,memory-controller = <&mc>;
+		#interconnect-cells = <0>;
 		#cooling-cells = <2>;
 	};
 

-- 
2.50.1



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

* [PATCH RFC 7/7] arm64: tegra: Add OPP tables on Tegra210
  2025-08-29  4:01 [PATCH RFC 0/7] Support Tegra210 actmon for dynamic EMC scaling Aaron Kling via B4 Relay
                   ` (5 preceding siblings ...)
  2025-08-29  4:01 ` [PATCH RFC 6/7] arm64: tegra: Add interconnect properties to Tegra210 device-tree Aaron Kling via B4 Relay
@ 2025-08-29  4:01 ` Aaron Kling via B4 Relay
  2025-08-29 14:27 ` [PATCH RFC 0/7] Support Tegra210 actmon for dynamic EMC scaling Rob Herring (Arm)
  2025-09-02 23:51 ` Mikko Perttunen
  8 siblings, 0 replies; 11+ messages in thread
From: Aaron Kling via B4 Relay @ 2025-08-29  4:01 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Rob Herring, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Chanwoo Choi, Dmitry Osipenko
  Cc: linux-kernel, devicetree, linux-tegra, linux-pm, Aaron Kling

From: Aaron Kling <webgeek1234@gmail.com>

This adds OPP tables for actmon and emc, enabling dynamic frequency
scaling for ram.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
---
 .../boot/dts/nvidia/tegra210-peripherals-opp.dtsi  | 135 +++++++++++++++++++++
 arch/arm64/boot/dts/nvidia/tegra210.dtsi           |   7 ++
 2 files changed, 142 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra210-peripherals-opp.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-peripherals-opp.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..bf2527d737932a1f41aa83d61f44d87ba52b0519
--- /dev/null
+++ b/arch/arm64/boot/dts/nvidia/tegra210-peripherals-opp.dtsi
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/ {
+	/* EMC DVFS OPP table */
+	emc_icc_dvfs_opp_table: opp-table-dvfs0 {
+		compatible = "operating-points-v2";
+
+		opp-40800000-800 {
+			opp-microvolt = <800000 800000 1150000>;
+			opp-hz = /bits/ 64 <40800000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp-68000000-800 {
+			opp-microvolt = <800000 800000 1150000>;
+			opp-hz = /bits/ 64 <68000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp-102000000-800 {
+			opp-microvolt = <800000 800000 1150000>;
+			opp-hz = /bits/ 64 <102000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp-204000000-800 {
+			opp-microvolt = <800000 800000 1150000>;
+			opp-hz = /bits/ 64 <204000000>;
+			opp-supported-hw = <0x0007>;
+			opp-suspend;
+		};
+
+		opp-408000000-812 {
+			opp-microvolt = <812000 812000 1150000>;
+			opp-hz = /bits/ 64 <408000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp-665600000-825 {
+			opp-microvolt = <825000 825000 1150000>;
+			opp-hz = /bits/ 64 <665600000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp-800000000-825 {
+			opp-microvolt = <825000 825000 1150000>;
+			opp-hz = /bits/ 64 <800000000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp-1065600000-837 {
+			opp-microvolt = <837000 837000 1150000>;
+			opp-hz = /bits/ 64 <1065600000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp-1331200000-850 {
+			opp-microvolt = <850000 850000 1150000>;
+			opp-hz = /bits/ 64 <1331200000>;
+			opp-supported-hw = <0x0003>;
+		};
+
+		opp-1600000000-887 {
+			opp-microvolt = <887000 887000 1150000>;
+			opp-hz = /bits/ 64 <1600000000>;
+			opp-supported-hw = <0x0007>;
+		};
+	};
+
+	/* EMC bandwidth OPP table */
+	emc_bw_dfs_opp_table: opp-table-dvfs1 {
+		compatible = "operating-points-v2";
+
+		opp-40800000 {
+			opp-hz = /bits/ 64 <40800000>;
+			opp-supported-hw = <0x0003>;
+			opp-peak-kBps = <652800>;
+		};
+
+		opp-68000000 {
+			opp-hz = /bits/ 64 <68000000>;
+			opp-supported-hw = <0x0003>;
+			opp-peak-kBps = <1088000>;
+		};
+
+		opp-102000000 {
+			opp-hz = /bits/ 64 <102000000>;
+			opp-supported-hw = <0x0003>;
+			opp-peak-kBps = <1632000>;
+		};
+
+		opp-204000000 {
+			opp-hz = /bits/ 64 <204000000>;
+			opp-supported-hw = <0x0007>;
+			opp-peak-kBps = <3264000>;
+			opp-suspend;
+		};
+
+		opp-408000000 {
+			opp-hz = /bits/ 64 <408000000>;
+			opp-supported-hw = <0x0003>;
+			opp-peak-kBps = <6528000>;
+		};
+
+		opp-665600000 {
+			opp-hz = /bits/ 64 <665600000>;
+			opp-supported-hw = <0x0003>;
+			opp-peak-kBps = <10649600>;
+		};
+
+		opp-800000000 {
+			opp-hz = /bits/ 64 <800000000>;
+			opp-supported-hw = <0x001F>;
+			opp-peak-kBps = <12800000>;
+		};
+
+		opp-1065600000 {
+			opp-hz = /bits/ 64 <1065600000>;
+			opp-supported-hw = <0x0003>;
+			opp-peak-kBps = <17049600>;
+		};
+
+		opp-1331200000 {
+			opp-hz = /bits/ 64 <1331200000>;
+			opp-supported-hw = <0x0003>;
+			opp-peak-kBps = <21299200>;
+		};
+
+		opp-1600000000 {
+			opp-hz = /bits/ 64 <1600000000>;
+			opp-supported-hw = <0x0007>;
+			opp-peak-kBps = <25600000>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 2fcc7a28690f7100d49e8b93c4fb77de7947b002..f2961c9e12db1cf91254b75389779955f2a0956d 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -9,6 +9,8 @@
 #include <dt-bindings/thermal/tegra124-soctherm.h>
 #include <dt-bindings/soc/tegra-pmc.h>
 
+#include "tegra210-peripherals-opp.dtsi"
+
 / {
 	compatible = "nvidia,tegra210";
 	interrupt-parent = <&lic>;
@@ -516,6 +518,9 @@ actmon@6000c800 {
 		clock-names = "actmon", "emc";
 		resets = <&tegra_car 119>;
 		reset-names = "actmon";
+		operating-points-v2 = <&emc_bw_dfs_opp_table>;
+		interconnects = <&mc TEGRA210_MC_MPCORER &emc>;
+		interconnect-names = "cpu-read";
 		#cooling-cells = <2>;
 	};
 
@@ -1024,6 +1029,8 @@ emc: external-memory-controller@7001b000 {
 		clock-names = "emc";
 		interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
 		nvidia,memory-controller = <&mc>;
+		operating-points-v2 = <&emc_icc_dvfs_opp_table>;
+
 		#interconnect-cells = <0>;
 		#cooling-cells = <2>;
 	};

-- 
2.50.1



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

* Re: [PATCH RFC 0/7] Support Tegra210 actmon for dynamic EMC scaling
  2025-08-29  4:01 [PATCH RFC 0/7] Support Tegra210 actmon for dynamic EMC scaling Aaron Kling via B4 Relay
                   ` (6 preceding siblings ...)
  2025-08-29  4:01 ` [PATCH RFC 7/7] arm64: tegra: Add OPP tables on Tegra210 Aaron Kling via B4 Relay
@ 2025-08-29 14:27 ` Rob Herring (Arm)
  2025-09-02 23:51 ` Mikko Perttunen
  8 siblings, 0 replies; 11+ messages in thread
From: Rob Herring (Arm) @ 2025-08-29 14:27 UTC (permalink / raw)
  To: Aaron Kling
  Cc: Jonathan Hunter, Thierry Reding, Conor Dooley, linux-tegra,
	Kyungmin Park, linux-pm, Dmitry Osipenko, devicetree,
	Chanwoo Choi, Krzysztof Kozlowski, Krzysztof Kozlowski,
	linux-kernel, MyungJoo Ham


On Thu, 28 Aug 2025 23:01:26 -0500, Aaron Kling wrote:
> This series adds interconnect support to tegra210 MC and EMC, then
> enables actmon. This enables dynamic emc scaling.
> 
> This series is marked RFC for two reasons:
> 
> 1) Calculating rate from bandwidth usage results in double the expected
>    rate. I thought this might be due to the ram being 64-bit, but the
>    related CFG5 register reports 32-bit on both p2371-2180 and
>    p3450-0000. I'm using the calculation used for Tegra124 and haven't
>    seen seen anything obviously different between the ram handling on
>    these archs to cause a different result. I have considered that the
>    number of channels might affect the reporting, and factoring in that
>    variable does result in the correct rate, but I don't want to assume
>    that's correct without confirmation.
> 
> 2) I am seeing intermittent instability when transitioning to rates of
>    204 MHz or below on p2371-2180. I have noted that if the first
>    transition to such a state works, then it continues to work for the
>    rest of that boot cycle. But the kernel will often panic the first
>    time it tries to downclock. I suspect this is a pre-existing issue
>    only brought to light now because nothing would ever lower the clock
>    rate previously.
> 
> Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
> ---
> Aaron Kling (7):
>       dt-bindings: memory: tegra210: Add memory client IDs
>       dt-bindings: devfreq: tegra30-actmon: Add Tegra124 fallback for Tegra210
>       soc: tegra: fuse: speedo-tegra210: Add soc speedo 2
>       memory: tegra210: Support interconnect framework
>       arm64: tegra: tegra210: Add actmon
>       arm64: tegra: Add interconnect properties to Tegra210 device-tree
>       arm64: tegra: Add OPP tables on Tegra210
> 
>  .../bindings/devfreq/nvidia,tegra30-actmon.yaml    |  13 +-
>  .../boot/dts/nvidia/tegra210-peripherals-opp.dtsi  | 135 ++++++++++
>  arch/arm64/boot/dts/nvidia/tegra210.dtsi           |  43 ++++
>  drivers/memory/tegra/Kconfig                       |   1 +
>  drivers/memory/tegra/tegra210-emc-core.c           | 276 ++++++++++++++++++++-
>  drivers/memory/tegra/tegra210-emc.h                |  25 ++
>  drivers/memory/tegra/tegra210.c                    |  81 ++++++
>  drivers/soc/tegra/fuse/speedo-tegra210.c           |   1 +
>  include/dt-bindings/memory/tegra210-mc.h           |  58 +++++
>  9 files changed, 626 insertions(+), 7 deletions(-)
> ---
> base-commit: 8f5ae30d69d7543eee0d70083daf4de8fe15d585
> change-id: 20250822-t210-actmon-34904ce7ed0c
> prerequisite-change-id: 20250812-tegra210-speedo-470691e8b8cc:v1
> prerequisite-patch-id: 81859c81abbe79aed1cfbc95b4f5bcdc5637d6bd
> prerequisite-patch-id: 98bda8855bcc57c59b2231b7808d4478301afe68
> prerequisite-patch-id: 6e0b69d42ea542dc9f58b410abd5974644f75dc4
> prerequisite-patch-id: 9e3b9b2fdb8d9c2264dfa7641d1aec84fb7aedd9
> prerequisite-patch-id: ef4bcc4ddba7898b188fb3fc6e414a2662183f91
> 
> Best regards,
> --
> Aaron Kling <webgeek1234@gmail.com>
> 
> 
> 


My bot found new DTB warnings on the .dts files added or changed in this
series.

Some warnings may be from an existing SoC .dtsi. Or perhaps the warnings
are fixed by another series. Ultimately, it is up to the platform
maintainer whether these warnings are acceptable or not. No need to reply
unless the platform maintainer has comments.

If you already ran DT checks and didn't see these error(s), then
make sure dt-schema is up to date:

  pip3 install dtschema --upgrade


This patch series was applied (using b4) to base:
 Base: using specified base-commit 8f5ae30d69d7543eee0d70083daf4de8fe15d585
 Deps: looking for dependencies matching 5 patch-ids
 Deps: Applying prerequisite patch: [PATCH 1/5] dt-bindings: clock: tegra124-dfll: Add property to limit frequency
 Deps: Applying prerequisite patch: [PATCH 2/5] soc: tegra: fuse: speedo-tegra210: Update speedo ids
 Deps: Applying prerequisite patch: [PATCH 3/5] soc: tegra: fuse: speedo-tegra210: Add sku 0x8F
 Deps: Applying prerequisite patch: [PATCH 4/5] clk: tegra: dfll: Support limiting max clock per device
 Deps: Applying prerequisite patch: [PATCH 5/5] arm64: tegra: Limit max cpu frequency on P3450

If this is not the correct base, please add 'base-commit' tag
(or use b4 which does this automatically)

New warnings running 'make CHECK_DTBS=y for arch/arm64/boot/dts/nvidia/' for 20250828-t210-actmon-v1-0-aeb19ec1f244@gmail.com:

arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dtb: external-memory-controller@7001b000 (nvidia,tegra210-emc): '#cooling-cells', '#interconnect-cells', 'operating-points-v2' do not match any of the regexes: '^pinctrl-[0-9]+$'
	from schema $id: http://devicetree.org/schemas/memory-controllers/nvidia,tegra210-emc.yaml#
arch/arm64/boot/dts/nvidia/tegra210-p2371-0000.dtb: external-memory-controller@7001b000 (nvidia,tegra210-emc): '#cooling-cells', '#interconnect-cells', 'operating-points-v2' do not match any of the regexes: '^pinctrl-[0-9]+$'
	from schema $id: http://devicetree.org/schemas/memory-controllers/nvidia,tegra210-emc.yaml#
arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dtb: external-memory-controller@7001b000 (nvidia,tegra210-emc): '#cooling-cells', '#interconnect-cells', 'operating-points-v2' do not match any of the regexes: '^pinctrl-[0-9]+$'
	from schema $id: http://devicetree.org/schemas/memory-controllers/nvidia,tegra210-emc.yaml#
arch/arm64/boot/dts/nvidia/tegra210-smaug.dtb: external-memory-controller@7001b000 (nvidia,tegra210-emc): '#cooling-cells', '#interconnect-cells', 'operating-points-v2' do not match any of the regexes: '^pinctrl-[0-9]+$'
	from schema $id: http://devicetree.org/schemas/memory-controllers/nvidia,tegra210-emc.yaml#
arch/arm64/boot/dts/nvidia/tegra210-p2894-0050-a08.dtb: external-memory-controller@7001b000 (nvidia,tegra210-emc): '#cooling-cells', '#interconnect-cells', 'operating-points-v2' do not match any of the regexes: '^pinctrl-[0-9]+$'
	from schema $id: http://devicetree.org/schemas/memory-controllers/nvidia,tegra210-emc.yaml#
arch/arm64/boot/dts/nvidia/tegra210-p2571.dtb: external-memory-controller@7001b000 (nvidia,tegra210-emc): '#cooling-cells', '#interconnect-cells', 'operating-points-v2' do not match any of the regexes: '^pinctrl-[0-9]+$'
	from schema $id: http://devicetree.org/schemas/memory-controllers/nvidia,tegra210-emc.yaml#






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

* Re: [PATCH RFC 0/7] Support Tegra210 actmon for dynamic EMC scaling
  2025-08-29  4:01 [PATCH RFC 0/7] Support Tegra210 actmon for dynamic EMC scaling Aaron Kling via B4 Relay
                   ` (7 preceding siblings ...)
  2025-08-29 14:27 ` [PATCH RFC 0/7] Support Tegra210 actmon for dynamic EMC scaling Rob Herring (Arm)
@ 2025-09-02 23:51 ` Mikko Perttunen
  2025-09-03  0:55   ` Aaron Kling
  8 siblings, 1 reply; 11+ messages in thread
From: Mikko Perttunen @ 2025-09-02 23:51 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Rob Herring, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Chanwoo Choi, Dmitry Osipenko, webgeek1234
  Cc: linux-kernel, devicetree, linux-tegra, linux-pm, Aaron Kling

On Friday, August 29, 2025 1:01 PM Aaron Kling via B4 Relay wrote:
> This series adds interconnect support to tegra210 MC and EMC, then
> enables actmon. This enables dynamic emc scaling.
> 
> This series is marked RFC for two reasons:
> 
> 1) Calculating rate from bandwidth usage results in double the expected
>    rate. I thought this might be due to the ram being 64-bit, but the
>    related CFG5 register reports 32-bit on both p2371-2180 and
>    p3450-0000. I'm using the calculation used for Tegra124 and haven't
>    seen seen anything obviously different between the ram handling on
>    these archs to cause a different result. I have considered that the
>    number of channels might affect the reporting, and factoring in that
>    variable does result in the correct rate, but I don't want to assume
>    that's correct without confirmation.

My thinking is also that this is due to the channels. L4T says

/*
 * Tegra11 has dual 32-bit memory channels, while
 * Tegra12 has single 64-bit memory channel. Tegra21
 * has either dual 32 bit channels (LP4) or a single
 * 64 bit channel (LP3).
 *
 * MC effectively operates as 64-bit bus.
 */

next to calculating bw_to_freq, and proceeds to use the same divisor for T114 to T210. Regarding the CFG5_DRAM_WIDTH field, I'm guessing it gives the width for one channel, but I'm not sure how it would function for other memory types -- I'm not sure if any Tegra210 devices using memory other than LPDDR4 were ever released.

I also noticed that when running on LPDDR4, the DRAM clock is actually running at 2x EMC rate. But I think this is (slightly inappropriately) papered over by the EMC driver, which actually deals in the DRAM clock rate even if the HW EMC clock might be running at half rate.

> 
> 2) I am seeing intermittent instability when transitioning to rates of
>    204 MHz or below on p2371-2180. I have noted that if the first
>    transition to such a state works, then it continues to work for the
>    rest of that boot cycle. But the kernel will often panic the first
>    time it tries to downclock. I suspect this is a pre-existing issue
>    only brought to light now because nothing would ever lower the clock
>    rate previously.

Not sure about this.

Cheers,
Mikko

> 
> Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
> ---
> Aaron Kling (7):
>       dt-bindings: memory: tegra210: Add memory client IDs
>       dt-bindings: devfreq: tegra30-actmon: Add Tegra124 fallback for Tegra210
>       soc: tegra: fuse: speedo-tegra210: Add soc speedo 2
>       memory: tegra210: Support interconnect framework
>       arm64: tegra: tegra210: Add actmon
>       arm64: tegra: Add interconnect properties to Tegra210 device-tree
>       arm64: tegra: Add OPP tables on Tegra210
> 
>  .../bindings/devfreq/nvidia,tegra30-actmon.yaml    |  13 +-
>  .../boot/dts/nvidia/tegra210-peripherals-opp.dtsi  | 135 ++++++++++
>  arch/arm64/boot/dts/nvidia/tegra210.dtsi           |  43 ++++
>  drivers/memory/tegra/Kconfig                       |   1 +
>  drivers/memory/tegra/tegra210-emc-core.c           | 276 ++++++++++++++++++++-
>  drivers/memory/tegra/tegra210-emc.h                |  25 ++
>  drivers/memory/tegra/tegra210.c                    |  81 ++++++
>  drivers/soc/tegra/fuse/speedo-tegra210.c           |   1 +
>  include/dt-bindings/memory/tegra210-mc.h           |  58 +++++
>  9 files changed, 626 insertions(+), 7 deletions(-)
> ---
> base-commit: 8f5ae30d69d7543eee0d70083daf4de8fe15d585
> change-id: 20250822-t210-actmon-34904ce7ed0c
> prerequisite-change-id: 20250812-tegra210-speedo-470691e8b8cc:v1
> prerequisite-patch-id: 81859c81abbe79aed1cfbc95b4f5bcdc5637d6bd
> prerequisite-patch-id: 98bda8855bcc57c59b2231b7808d4478301afe68
> prerequisite-patch-id: 6e0b69d42ea542dc9f58b410abd5974644f75dc4
> prerequisite-patch-id: 9e3b9b2fdb8d9c2264dfa7641d1aec84fb7aedd9
> prerequisite-patch-id: ef4bcc4ddba7898b188fb3fc6e414a2662183f91
> 
> Best regards,
> 





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

* Re: [PATCH RFC 0/7] Support Tegra210 actmon for dynamic EMC scaling
  2025-09-02 23:51 ` Mikko Perttunen
@ 2025-09-03  0:55   ` Aaron Kling
  0 siblings, 0 replies; 11+ messages in thread
From: Aaron Kling @ 2025-09-03  0:55 UTC (permalink / raw)
  To: Mikko Perttunen
  Cc: Krzysztof Kozlowski, Rob Herring, Conor Dooley, Thierry Reding,
	Jonathan Hunter, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Chanwoo Choi, Dmitry Osipenko, linux-kernel, devicetree,
	linux-tegra, linux-pm

On Tue, Sep 2, 2025 at 6:51 PM Mikko Perttunen <mperttunen@nvidia.com> wrote:
>
> On Friday, August 29, 2025 1:01 PM Aaron Kling via B4 Relay wrote:
> > This series adds interconnect support to tegra210 MC and EMC, then
> > enables actmon. This enables dynamic emc scaling.
> >
> > This series is marked RFC for two reasons:
> >
> > 1) Calculating rate from bandwidth usage results in double the expected
> >    rate. I thought this might be due to the ram being 64-bit, but the
> >    related CFG5 register reports 32-bit on both p2371-2180 and
> >    p3450-0000. I'm using the calculation used for Tegra124 and haven't
> >    seen seen anything obviously different between the ram handling on
> >    these archs to cause a different result. I have considered that the
> >    number of channels might affect the reporting, and factoring in that
> >    variable does result in the correct rate, but I don't want to assume
> >    that's correct without confirmation.
>
> My thinking is also that this is due to the channels. L4T says
>
> /*
>  * Tegra11 has dual 32-bit memory channels, while
>  * Tegra12 has single 64-bit memory channel. Tegra21
>  * has either dual 32 bit channels (LP4) or a single
>  * 64 bit channel (LP3).
>  *
>  * MC effectively operates as 64-bit bus.
>  */
>
> next to calculating bw_to_freq, and proceeds to use the same divisor for T114 to T210. Regarding the CFG5_DRAM_WIDTH field, I'm guessing it gives the width for one channel, but I'm not sure how it would function for other memory types -- I'm not sure if any Tegra210 devices using memory other than LPDDR4 were ever released.

Mmm. "MC effectively operates as 64-bit bus." So I could just hardcode
64-bit dram width and skip reading the CFG5_DRAM_WIDTH field
altogether. And regardless of the layout, if I'm reading that
correctly, the calculation would remain correct. That should get the
numbers I'm expecting on the devkits, but I will verify again before
uploading a new revision.

Aaron

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

end of thread, other threads:[~2025-09-03  0:55 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-29  4:01 [PATCH RFC 0/7] Support Tegra210 actmon for dynamic EMC scaling Aaron Kling via B4 Relay
2025-08-29  4:01 ` [PATCH RFC 1/7] dt-bindings: memory: tegra210: Add memory client IDs Aaron Kling via B4 Relay
2025-08-29  4:01 ` [PATCH RFC 2/7] dt-bindings: devfreq: tegra30-actmon: Add Tegra124 fallback for Tegra210 Aaron Kling via B4 Relay
2025-08-29  4:01 ` [PATCH RFC 3/7] soc: tegra: fuse: speedo-tegra210: Add soc speedo 2 Aaron Kling via B4 Relay
2025-08-29  4:01 ` [PATCH RFC 4/7] memory: tegra210: Support interconnect framework Aaron Kling via B4 Relay
2025-08-29  4:01 ` [PATCH RFC 5/7] arm64: tegra: tegra210: Add actmon Aaron Kling via B4 Relay
2025-08-29  4:01 ` [PATCH RFC 6/7] arm64: tegra: Add interconnect properties to Tegra210 device-tree Aaron Kling via B4 Relay
2025-08-29  4:01 ` [PATCH RFC 7/7] arm64: tegra: Add OPP tables on Tegra210 Aaron Kling via B4 Relay
2025-08-29 14:27 ` [PATCH RFC 0/7] Support Tegra210 actmon for dynamic EMC scaling Rob Herring (Arm)
2025-09-02 23:51 ` Mikko Perttunen
2025-09-03  0:55   ` Aaron Kling

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).