linux-pm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFCv4 0/7] interconnect: Add imx support via devfreq
@ 2019-08-23 14:36 Leonard Crestez
  2019-08-23 14:36 ` [RFCv4 1/7] PM / devfreq: Add devfreq_get_devfreq_by_node Leonard Crestez
                   ` (8 more replies)
  0 siblings, 9 replies; 19+ messages in thread
From: Leonard Crestez @ 2019-08-23 14:36 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Artur Świgoń, Chanwoo Choi
  Cc: Alexandre Bailon, Krzysztof Kozlowski, MyungJoo Ham,
	Kyungmin Park, Saravana Kannan, Mark Rutland, Viresh Kumar,
	Shawn Guo, Dong Aisheng, Fabio Estevam, Stephen Boyd,
	Michael Turquette, kernel, linux-imx, linux-pm, devicetree,
	linux-arm-kernel

This series add imx support for interconnect via devfreq: the ICC
framework is used to aggregate requests from devices and then those are
converted to DEV_PM_QOS_MIN_FREQUENCY requests for devfreq.

The devfreq parts are posted separately, this series only intersects in
devicetree: https://patchwork.kernel.org/cover/11104113/

Since there is no single devicetree node that can represent the "interconnect"
new API is added to allow individual devfreq nodes to act as parsing proxies
all mapping to a single soc-level icc provider. This is still RFC
because this

The rest of the changes are small and deal with review comments.

Changes since RFCv3:
* Remove the virtual "icc" node and add devfreq nodes as proxy providers
* Fix build on 32-bit arm (reported by kbuilt test robot)
* Remove ARCH_MXC_ARM64 (never existed in upstream)
* Remove _numlinks, calculate instead
* Replace __BUSFREQ_H header guard
* Improve commit message and comment spelling
* Fix checkpatch issues
Link to RFCv3: https://patchwork.kernel.org/cover/11078671/

Changes since RFCv2 and initial work by Alexandre Bailon:
* Relying on devfreq and dev_pm_qos instead of CLK
* No more "platform opp" stuff
* No more special suspend handling: use suspend-opp on devfreq instead.
* Replace all mentions of "busfreq" with "interconnect"
Link to v2: https://patchwork.kernel.org/patch/11056789/

Leonard Crestez (7):
  PM / devfreq: Add devfreq_get_devfreq_by_node
  interconnect: Add of_icc_add_proxy
  dt-bindings: devfreq: imx: Describe interconnect properties
  interconnect: Add imx core driver
  interconnect: imx: Add platform driver for imx8mm
  soc: imx8mm: Register interconnect platform device
  arm64: dts: imx8mm: Add interconnect properties

 .../devicetree/bindings/devfreq/imx-ddrc.yaml |   5 +
 .../devicetree/bindings/devfreq/imx.yaml      |   5 +
 arch/arm64/boot/dts/freescale/imx8mm.dtsi     |   5 +
 drivers/devfreq/devfreq.c                     |  42 ++-
 drivers/interconnect/Kconfig                  |   1 +
 drivers/interconnect/Makefile                 |   1 +
 drivers/interconnect/core.c                   |  88 +++++-
 drivers/interconnect/imx/Kconfig              |   9 +
 drivers/interconnect/imx/Makefile             |   2 +
 drivers/interconnect/imx/imx.c                | 279 ++++++++++++++++++
 drivers/interconnect/imx/imx.h                |  60 ++++
 drivers/interconnect/imx/imx8mm.c             | 105 +++++++
 drivers/soc/imx/soc-imx8.c                    |   4 +
 include/dt-bindings/interconnect/imx8mm.h     |  49 +++
 include/linux/devfreq.h                       |   1 +
 include/linux/interconnect-provider.h         |   7 +
 16 files changed, 645 insertions(+), 18 deletions(-)
 create mode 100644 drivers/interconnect/imx/Kconfig
 create mode 100644 drivers/interconnect/imx/Makefile
 create mode 100644 drivers/interconnect/imx/imx.c
 create mode 100644 drivers/interconnect/imx/imx.h
 create mode 100644 drivers/interconnect/imx/imx8mm.c
 create mode 100644 include/dt-bindings/interconnect/imx8mm.h

-- 
2.17.1


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

* [RFCv4 1/7] PM / devfreq: Add devfreq_get_devfreq_by_node
  2019-08-23 14:36 [RFCv4 0/7] interconnect: Add imx support via devfreq Leonard Crestez
@ 2019-08-23 14:36 ` Leonard Crestez
  2019-08-23 14:36 ` [RFCv4 2/7] interconnect: Add of_icc_add_proxy Leonard Crestez
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 19+ messages in thread
From: Leonard Crestez @ 2019-08-23 14:36 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Artur Świgoń, Chanwoo Choi
  Cc: Alexandre Bailon, Krzysztof Kozlowski, MyungJoo Ham,
	Kyungmin Park, Saravana Kannan, Mark Rutland, Viresh Kumar,
	Shawn Guo, Dong Aisheng, Fabio Estevam, Stephen Boyd,
	Michael Turquette, kernel, linux-imx, linux-pm, devicetree,
	linux-arm-kernel

Split off part of devfreq_get_devfreq_by_phandle into a separate
function. This allows callers to fetch devfreq instances by enumerating
devicetree instead of explicit phandles.

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
 drivers/devfreq/devfreq.c | 42 +++++++++++++++++++++++++++++----------
 include/linux/devfreq.h   |  1 +
 2 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 687deadd08ed..57352a757d79 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -907,10 +907,33 @@ struct devfreq *devm_devfreq_add_device(struct device *dev,
 	return devfreq;
 }
 EXPORT_SYMBOL(devm_devfreq_add_device);
 
 #ifdef CONFIG_OF
+/*
+ * devfreq_get_devfreq_by_node - Get the devfreq device from devicetree
+ * @np - pointer to device_node
+ *
+ * return the instance of devfreq device
+ */
+struct devfreq *devfreq_get_devfreq_by_node(struct device_node *node)
+{
+	struct devfreq *devfreq;
+
+	mutex_lock(&devfreq_list_lock);
+	list_for_each_entry(devfreq, &devfreq_list, node) {
+		if (devfreq->dev.parent
+			&& devfreq->dev.parent->of_node == node) {
+			mutex_unlock(&devfreq_list_lock);
+			return devfreq;
+		}
+	}
+	mutex_unlock(&devfreq_list_lock);
+
+	return ERR_PTR(-EPROBE_DEFER);
+}
+
 /*
  * devfreq_get_devfreq_by_phandle - Get the devfreq device from devicetree
  * @dev - instance to the given device
  * @index - index into list of devfreq
  *
@@ -929,25 +952,22 @@ struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev, int index)
 
 	node = of_parse_phandle(dev->of_node, "devfreq", index);
 	if (!node)
 		return ERR_PTR(-ENODEV);
 
-	mutex_lock(&devfreq_list_lock);
-	list_for_each_entry(devfreq, &devfreq_list, node) {
-		if (devfreq->dev.parent
-			&& devfreq->dev.parent->of_node == node) {
-			mutex_unlock(&devfreq_list_lock);
-			of_node_put(node);
-			return devfreq;
-		}
-	}
-	mutex_unlock(&devfreq_list_lock);
+	devfreq = devfreq_get_devfreq_by_node(node);
 	of_node_put(node);
 
-	return ERR_PTR(-EPROBE_DEFER);
+	return devfreq;
 }
+
 #else
+struct devfreq *devfreq_get_devfreq_by_node(struct device_node *node)
+{
+	return ERR_PTR(-ENODEV);
+}
+
 struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev, int index)
 {
 	return ERR_PTR(-ENODEV);
 }
 #endif /* CONFIG_OF */
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index d2c5bb7add0a..4b5cc80abbe3 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -242,10 +242,11 @@ extern int devm_devfreq_register_notifier(struct device *dev,
 				unsigned int list);
 extern void devm_devfreq_unregister_notifier(struct device *dev,
 				struct devfreq *devfreq,
 				struct notifier_block *nb,
 				unsigned int list);
+extern struct devfreq *devfreq_get_devfreq_by_node(struct device_node *node);
 extern struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev,
 						int index);
 
 #if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
 /**
-- 
2.17.1


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

* [RFCv4 2/7] interconnect: Add of_icc_add_proxy
  2019-08-23 14:36 [RFCv4 0/7] interconnect: Add imx support via devfreq Leonard Crestez
  2019-08-23 14:36 ` [RFCv4 1/7] PM / devfreq: Add devfreq_get_devfreq_by_node Leonard Crestez
@ 2019-08-23 14:36 ` Leonard Crestez
  2019-08-23 14:36 ` [RFCv4 3/7] dt-bindings: devfreq: imx: Describe interconnect properties Leonard Crestez
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 19+ messages in thread
From: Leonard Crestez @ 2019-08-23 14:36 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Artur Świgoń, Chanwoo Choi
  Cc: Alexandre Bailon, Krzysztof Kozlowski, MyungJoo Ham,
	Kyungmin Park, Saravana Kannan, Mark Rutland, Viresh Kumar,
	Shawn Guo, Dong Aisheng, Fabio Estevam, Stephen Boyd,
	Michael Turquette, kernel, linux-imx, linux-pm, devicetree,
	linux-arm-kernel

On many SOCs there is no single node that describes the "interconnect",
instead are multiple pieces of bus fabric which already support scaling.

Add support for mapping multiple device nodes to the same icc_provider
(likely a platform-level singleton). This is implemented at the
devicetree parsing level: just add more device nodes which map to the
same icc_provider instead.

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
 drivers/interconnect/core.c           | 88 ++++++++++++++++++++++++---
 include/linux/interconnect-provider.h |  7 +++
 2 files changed, 88 insertions(+), 7 deletions(-)

diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
index 7b971228df38..01109e335baf 100644
--- a/drivers/interconnect/core.c
+++ b/drivers/interconnect/core.c
@@ -17,12 +17,19 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/overflow.h>
 
+struct of_icc_proxy {
+	struct device_node *of_node;
+	struct icc_provider *provider;
+	struct list_head list_node;
+};
+
 static DEFINE_IDR(icc_idr);
 static LIST_HEAD(icc_providers);
+static LIST_HEAD(icc_proxy_list);
 static DEFINE_MUTEX(icc_lock);
 static struct dentry *icc_debugfs_dir;
 
 /**
  * struct icc_req - constraints that are attached to each node
@@ -267,10 +274,61 @@ struct icc_node *of_icc_xlate_onecell(struct of_phandle_args *spec,
 
 	return icc_data->nodes[idx];
 }
 EXPORT_SYMBOL_GPL(of_icc_xlate_onecell);
 
+struct icc_provider *__of_icc_get_provider(struct device_node *np)
+{
+	struct of_icc_proxy *proxy;
+
+	lockdep_assert_held(&icc_lock);
+	list_for_each_entry(proxy, &icc_proxy_list, list_node)
+		if (proxy->of_node == np)
+			return proxy->provider;
+
+	return NULL;
+}
+
+static int __of_icc_add_proxy(struct device_node *np,
+			      struct icc_provider *provider)
+{
+	struct of_icc_proxy *proxy;
+
+	lockdep_assert_held(&icc_lock);
+	proxy = kmalloc(sizeof(*proxy), GFP_KERNEL);
+	if (!proxy)
+		return -ENOMEM;
+	proxy->of_node = np;
+	proxy->provider = provider;
+	list_add_tail(&proxy->list_node, &icc_proxy_list);
+
+	return 0;
+}
+
+/**
+ * of_icc_add_proxy() - Add another device_node for a provider
+ * @np: OF node to alias from
+ * @provider: Interconnect provider to map to
+ *
+ * Make another device_node map to the same provider.
+ *
+ * This lasts until icc_provider_del.
+ */
+int of_icc_add_proxy(struct device_node *np, struct icc_provider *provider)
+{
+	int ret;
+
+	mutex_lock(&icc_lock);
+
+	ret = __of_icc_add_proxy(np, provider);
+
+	mutex_unlock(&icc_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_icc_add_proxy);
+
 /**
  * of_icc_get_from_provider() - Look-up interconnect node
  * @spec: OF phandle args to use for look-up
  *
  * Looks for interconnect provider under the node specified by @spec and if
@@ -279,23 +337,22 @@ EXPORT_SYMBOL_GPL(of_icc_xlate_onecell);
  * Returns a valid pointer to struct icc_node on success or ERR_PTR()
  * on failure.
  */
 static struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec)
 {
-	struct icc_node *node = ERR_PTR(-EPROBE_DEFER);
 	struct icc_provider *provider;
+	struct icc_node *node;
 
 	if (!spec || spec->args_count != 1)
 		return ERR_PTR(-EINVAL);
 
 	mutex_lock(&icc_lock);
-	list_for_each_entry(provider, &icc_providers, provider_list) {
-		if (provider->dev->of_node == spec->np)
-			node = provider->xlate(spec, provider->data);
-		if (!IS_ERR(node))
-			break;
-	}
+	provider = __of_icc_get_provider(spec->np);
+	if (provider)
+		node = provider->xlate(spec, provider->data);
+	else
+		node = ERR_PTR(-EPROBE_DEFER);
 	mutex_unlock(&icc_lock);
 
 	return node;
 }
 
@@ -744,17 +801,26 @@ EXPORT_SYMBOL_GPL(icc_node_del);
  *
  * Return: 0 on success, or an error code otherwise
  */
 int icc_provider_add(struct icc_provider *provider)
 {
+	int ret;
+
 	if (WARN_ON(!provider->set))
 		return -EINVAL;
 	if (WARN_ON(!provider->xlate))
 		return -EINVAL;
 
 	mutex_lock(&icc_lock);
 
+	if (provider->dev) {
+		ret = __of_icc_add_proxy(provider->dev->of_node, provider);
+		if (ret) {
+			mutex_unlock(&icc_lock);
+			return ret;
+		}
+	}
 	INIT_LIST_HEAD(&provider->nodes);
 	list_add_tail(&provider->provider_list, &icc_providers);
 
 	mutex_unlock(&icc_lock);
 
@@ -770,10 +836,12 @@ EXPORT_SYMBOL_GPL(icc_provider_add);
  *
  * Return: 0 on success, or an error code otherwise
  */
 int icc_provider_del(struct icc_provider *provider)
 {
+	struct of_icc_proxy *proxy, *tmp;
+
 	mutex_lock(&icc_lock);
 	if (provider->users) {
 		pr_warn("interconnect provider still has %d users\n",
 			provider->users);
 		mutex_unlock(&icc_lock);
@@ -785,10 +853,16 @@ int icc_provider_del(struct icc_provider *provider)
 		mutex_unlock(&icc_lock);
 		return -EBUSY;
 	}
 
 	list_del(&provider->provider_list);
+	list_for_each_entry_safe(proxy, tmp, &icc_proxy_list, list_node)
+		if (proxy->provider == provider) {
+			list_del(&proxy->list_node);
+			of_node_put(proxy->of_node);
+			kfree(proxy);
+		}
 	mutex_unlock(&icc_lock);
 
 	return 0;
 }
 EXPORT_SYMBOL_GPL(icc_provider_del);
diff --git a/include/linux/interconnect-provider.h b/include/linux/interconnect-provider.h
index b16f9effa555..e6773ecac164 100644
--- a/include/linux/interconnect-provider.h
+++ b/include/linux/interconnect-provider.h
@@ -98,10 +98,11 @@ int icc_link_create(struct icc_node *node, const int dst_id);
 int icc_link_destroy(struct icc_node *src, struct icc_node *dst);
 void icc_node_add(struct icc_node *node, struct icc_provider *provider);
 void icc_node_del(struct icc_node *node);
 int icc_provider_add(struct icc_provider *provider);
 int icc_provider_del(struct icc_provider *provider);
+int of_icc_add_proxy(struct device_node *np, struct icc_provider *provider);
 
 #else
 
 static inline struct icc_node *icc_node_create(int id)
 {
@@ -138,8 +139,14 @@ static inline int icc_provider_add(struct icc_provider *provider)
 static inline int icc_provider_del(struct icc_provider *provider)
 {
 	return -ENOTSUPP;
 }
 
+static inline int of_icc_add_proxy(struct device_node *np,
+				   struct icc_provider *provider)
+{
+	return -ENOTSUPP;
+}
+
 #endif /* CONFIG_INTERCONNECT */
 
 #endif /* __LINUX_INTERCONNECT_PROVIDER_H */
-- 
2.17.1


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

* [RFCv4 3/7] dt-bindings: devfreq: imx: Describe interconnect properties
  2019-08-23 14:36 [RFCv4 0/7] interconnect: Add imx support via devfreq Leonard Crestez
  2019-08-23 14:36 ` [RFCv4 1/7] PM / devfreq: Add devfreq_get_devfreq_by_node Leonard Crestez
  2019-08-23 14:36 ` [RFCv4 2/7] interconnect: Add of_icc_add_proxy Leonard Crestez
@ 2019-08-23 14:36 ` Leonard Crestez
  2019-09-17 20:19   ` Rob Herring
  2019-08-23 14:36 ` [RFCv4 4/7] interconnect: Add imx core driver Leonard Crestez
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Leonard Crestez @ 2019-08-23 14:36 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Artur Świgoń, Chanwoo Choi
  Cc: Alexandre Bailon, Krzysztof Kozlowski, MyungJoo Ham,
	Kyungmin Park, Saravana Kannan, Mark Rutland, Viresh Kumar,
	Shawn Guo, Dong Aisheng, Fabio Estevam, Stephen Boyd,
	Michael Turquette, kernel, linux-imx, linux-pm, devicetree,
	linux-arm-kernel

The interconnect-node-id property is parsed by the imx interconnect
driver to find nodes on which frequencies can be adjusted.

Add #interconnect-cells so that device drivers can request paths from
bus nodes instead of requiring a separate "virtual" node to represent
the interconnect itself.

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
 Documentation/devicetree/bindings/devfreq/imx-ddrc.yaml | 5 +++++
 Documentation/devicetree/bindings/devfreq/imx.yaml      | 5 +++++
 2 files changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/devfreq/imx-ddrc.yaml b/Documentation/devicetree/bindings/devfreq/imx-ddrc.yaml
index 31db204e6845..014449a9dd01 100644
--- a/Documentation/devicetree/bindings/devfreq/imx-ddrc.yaml
+++ b/Documentation/devicetree/bindings/devfreq/imx-ddrc.yaml
@@ -31,10 +31,15 @@ properties:
       - const: dram_alt
       - const: dram_apb
 
   operating-points-v2: true
 
+  interconnect-node-id:
+    $ref: /schemas/types.yaml#/definitions/uint32
+  '#interconnect-cells':
+    const: 1
+
   devfreq-events:
     description: Phandle of PMU node
     $ref: "/schemas/types.yaml#/definitions/phandle"
 
 required:
diff --git a/Documentation/devicetree/bindings/devfreq/imx.yaml b/Documentation/devicetree/bindings/devfreq/imx.yaml
index 634870496d5e..f2f9b76c752f 100644
--- a/Documentation/devicetree/bindings/devfreq/imx.yaml
+++ b/Documentation/devicetree/bindings/devfreq/imx.yaml
@@ -43,10 +43,15 @@ properties:
   clocks:
     maxItems: 1
 
   operating-points-v2: true
 
+  interconnect-node-id:
+    $ref: /schemas/types.yaml#/definitions/uint32
+  '#interconnect-cells':
+    const: 1
+
   devfreq:
     description: |
       Phandle to another devfreq device to match OPPs with by using the
       passive governor.
     $ref: "/schemas/types.yaml#/definitions/phandle"
-- 
2.17.1


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

* [RFCv4 4/7] interconnect: Add imx core driver
  2019-08-23 14:36 [RFCv4 0/7] interconnect: Add imx support via devfreq Leonard Crestez
                   ` (2 preceding siblings ...)
  2019-08-23 14:36 ` [RFCv4 3/7] dt-bindings: devfreq: imx: Describe interconnect properties Leonard Crestez
@ 2019-08-23 14:36 ` Leonard Crestez
  2019-08-23 14:36 ` [RFCv4 5/7] interconnect: imx: Add platform driver for imx8mm Leonard Crestez
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 19+ messages in thread
From: Leonard Crestez @ 2019-08-23 14:36 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Artur Świgoń, Chanwoo Choi
  Cc: Alexandre Bailon, Krzysztof Kozlowski, MyungJoo Ham,
	Kyungmin Park, Saravana Kannan, Mark Rutland, Viresh Kumar,
	Shawn Guo, Dong Aisheng, Fabio Estevam, Stephen Boyd,
	Michael Turquette, kernel, linux-imx, linux-pm, devicetree,
	linux-arm-kernel

This adds support for i.MX SoC family to interconnect framework.

Platform drivers can describe the interconnect graph and several
adjustment knobs where icc node bandwidth is converted to a
DEV_PM_QOS_MIN_FREQUENCY request.

The adjustable nodes are found based on an "interconnect-node-id"
property by scanning the entire device tree.

The interconnect provider doesn't need an virtual OF node, instead those
same adjustable nodes are registered as proxies which xlate to the
platform-level provider.

The platform device for the interconnect needs to be registered from a
SOC driver (similar to cpufreq).

Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
 drivers/interconnect/Kconfig      |   1 +
 drivers/interconnect/Makefile     |   1 +
 drivers/interconnect/imx/Kconfig  |   5 +
 drivers/interconnect/imx/Makefile |   1 +
 drivers/interconnect/imx/imx.c    | 279 ++++++++++++++++++++++++++++++
 drivers/interconnect/imx/imx.h    |  60 +++++++
 6 files changed, 347 insertions(+)
 create mode 100644 drivers/interconnect/imx/Kconfig
 create mode 100644 drivers/interconnect/imx/Makefile
 create mode 100644 drivers/interconnect/imx/imx.c
 create mode 100644 drivers/interconnect/imx/imx.h

diff --git a/drivers/interconnect/Kconfig b/drivers/interconnect/Kconfig
index bfa4ca3ab7a9..e61802230f90 100644
--- a/drivers/interconnect/Kconfig
+++ b/drivers/interconnect/Kconfig
@@ -10,7 +10,8 @@ menuconfig INTERCONNECT
 	  If unsure, say no.
 
 if INTERCONNECT
 
 source "drivers/interconnect/qcom/Kconfig"
+source "drivers/interconnect/imx/Kconfig"
 
 endif
diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile
index 28f2ab0824d5..20a13b7eb37f 100644
--- a/drivers/interconnect/Makefile
+++ b/drivers/interconnect/Makefile
@@ -2,5 +2,6 @@
 
 icc-core-objs				:= core.o
 
 obj-$(CONFIG_INTERCONNECT)		+= icc-core.o
 obj-$(CONFIG_INTERCONNECT_QCOM)		+= qcom/
+obj-$(CONFIG_INTERCONNECT_IMX)		+= imx/
diff --git a/drivers/interconnect/imx/Kconfig b/drivers/interconnect/imx/Kconfig
new file mode 100644
index 000000000000..7d81d3c83a61
--- /dev/null
+++ b/drivers/interconnect/imx/Kconfig
@@ -0,0 +1,5 @@
+config INTERCONNECT_IMX
+	bool "i.MX interconnect drivers"
+	depends on ARCH_MXC || COMPILE_TEST
+	help
+	  Generic interconnect driver for i.MX SOCs
diff --git a/drivers/interconnect/imx/Makefile b/drivers/interconnect/imx/Makefile
new file mode 100644
index 000000000000..bb92fd9fe4a5
--- /dev/null
+++ b/drivers/interconnect/imx/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_INTERCONNECT_IMX) += imx.o
diff --git a/drivers/interconnect/imx/imx.c b/drivers/interconnect/imx/imx.c
new file mode 100644
index 000000000000..0a04ac723c15
--- /dev/null
+++ b/drivers/interconnect/imx/imx.c
@@ -0,0 +1,279 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Interconnect framework driver for i.MX SoC
+ *
+ * Copyright (c) 2019, BayLibre
+ * Copyright (c) 2019, NXP
+ * Author: Alexandre Bailon <abailon@baylibre.com>
+ * Author: Leonard Crestez <leonard.crestez@nxp.com>
+ */
+
+#include <linux/devfreq.h>
+#include <linux/device.h>
+#include <linux/interconnect-provider.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_qos.h>
+
+#include "imx.h"
+
+/* private icc_provider data */
+struct imx_icc_provider {
+	struct device *dev;
+};
+
+/* private icc_node data */
+struct imx_icc_node {
+	const struct imx_icc_node_desc *desc;
+	struct devfreq *devfreq;
+	struct dev_pm_qos_request qos_req;
+};
+
+static int imx_icc_aggregate(struct icc_node *node, u32 tag,
+			     u32 avg_bw, u32 peak_bw,
+			     u32 *agg_avg, u32 *agg_peak)
+{
+	*agg_avg += avg_bw;
+	*agg_peak = max(*agg_peak, peak_bw);
+
+	return 0;
+}
+
+static struct icc_node *imx_icc_xlate(struct of_phandle_args *spec, void *data)
+{
+	struct imx_icc_provider *desc = data;
+	struct icc_provider *provider = dev_get_drvdata(desc->dev);
+	unsigned int id = spec->args[0];
+	struct icc_node *node;
+
+	list_for_each_entry(node, &provider->nodes, node_list)
+		if (node->id == id)
+			return node;
+
+	return ERR_PTR(-EINVAL);
+}
+
+static int imx_icc_node_set(struct icc_node *node)
+{
+	struct device *dev = node->provider->dev;
+	struct imx_icc_node *node_data = node->data;
+	u64 freq;
+
+	if (!node_data->devfreq)
+		return 0;
+
+	freq = (node->avg_bw + node->peak_bw) * node_data->desc->adj->bw_mul;
+	do_div(freq, node_data->desc->adj->bw_div);
+	dev_dbg(dev, "%s avg_bw %ukBps peak_bw %ukBps min_freq %llukHz\n",
+			node->name, node->avg_bw, node->peak_bw, freq);
+
+	if (freq > S32_MAX) {
+		dev_err(dev, "%s can't request more S32_MAX freq\n",
+				node->name);
+		return -ERANGE;
+	}
+
+	dev_pm_qos_update_request(&node_data->qos_req, freq);
+
+	return 0;
+}
+
+static int imx_icc_set(struct icc_node *src, struct icc_node *dst)
+{
+	return imx_icc_node_set(dst);
+}
+
+static const struct of_device_id imx_icc_node_of_match[] = {
+	{ .compatible = "fsl,imx8m-nic" },
+	{ .compatible = "fsl,imx8m-noc" },
+	{ .compatible = "fsl,imx8m-ddrc" },
+	{},
+};
+
+static int imx_icc_node_init_devfreq(struct device *dev,
+				     struct icc_node *node)
+{
+	struct imx_icc_node *node_data = node->data;
+	struct device_node *dn;
+	u32 node_id;
+	int ret;
+
+	for_each_matching_node(dn, imx_icc_node_of_match) {
+		ret = of_property_read_u32(dn, "interconnect-node-id",
+					   &node_id);
+		if (ret != 0)
+			continue;
+
+		if (node_id == node->id) {
+			of_node_get(dn);
+			break;
+		}
+	}
+
+	if (!dn)
+		return 0;
+
+	dev_info(dev, "node %s[%d] has device node %pOF\n",
+			node->name, node->id, dn);
+	node_data->devfreq = devfreq_get_devfreq_by_node(dn);
+	if (IS_ERR(node_data->devfreq)) {
+		of_node_put(dn);
+		ret = PTR_ERR(node_data->devfreq);
+		dev_err(dev, "failed to fetch devfreq for %s: %d\n",
+				node->name, ret);
+		return ret;
+	}
+
+	of_icc_add_proxy(dn, node->provider);
+	of_node_put(dn);
+
+	return dev_pm_qos_add_request(node_data->devfreq->dev.parent,
+				      &node_data->qos_req,
+				      DEV_PM_QOS_MIN_FREQUENCY, 0);
+}
+
+static struct icc_node *imx_icc_node_add(struct icc_provider *provider,
+		const struct imx_icc_node_desc *node_desc)
+{
+	struct imx_icc_provider *provider_data = provider->data;
+	struct device *dev = provider_data->dev;
+	struct imx_icc_node *node_data;
+	struct icc_node *node;
+	int ret;
+
+	node = icc_node_create(node_desc->id);
+	if (IS_ERR(node)) {
+		dev_err(dev, "failed to create node %d\n", node_desc->id);
+		return node;
+	}
+
+	if (node->data) {
+		dev_err(dev, "already created node %s id=%d\n",
+				node_desc->name, node_desc->id);
+		return ERR_PTR(-EEXIST);
+	}
+
+	node_data = devm_kzalloc(dev, sizeof(*node_data), GFP_KERNEL);
+	if (!node_data) {
+		icc_node_destroy(node->id);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	node->name = node_desc->name;
+	node->data = node_data;
+	node_data->desc = node_desc;
+	icc_node_add(node, provider);
+
+	if (node_desc->adj) {
+		ret = imx_icc_node_init_devfreq(dev, node);
+		if (ret < 0) {
+			icc_node_del(node);
+			icc_node_destroy(node->id);
+			return ERR_PTR(ret);
+		}
+	}
+
+	return node;
+}
+
+static void imx_icc_unregister_nodes(struct icc_provider *provider)
+{
+	struct icc_node *node, *tmp;
+
+	list_for_each_entry_safe(node, tmp, &provider->nodes, node_list) {
+		struct imx_icc_node *node_data = node->data;
+
+		icc_node_del(node);
+		icc_node_destroy(node->id);
+		if (dev_pm_qos_request_active(&node_data->qos_req))
+			dev_pm_qos_remove_request(&node_data->qos_req);
+	}
+}
+
+static int imx_icc_register_nodes(struct icc_provider *provider,
+				  const struct imx_icc_node_desc *descs,
+				  int count)
+{
+	int ret;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		struct icc_node *node;
+		const struct imx_icc_node_desc *node_desc = &descs[i];
+		size_t j;
+
+		node = imx_icc_node_add(provider, node_desc);
+		if (IS_ERR(node)) {
+			ret = PTR_ERR(node);
+			if (ret != -EPROBE_DEFER)
+				dev_err(provider->dev, "failed to add %s: %d\n",
+						node_desc->name, ret);
+			goto err;
+		}
+
+		for (j = 0; j < node_desc->num_links; j++)
+			icc_link_create(node, node_desc->links[j]);
+	}
+
+	return 0;
+
+err:
+	imx_icc_unregister_nodes(provider);
+
+	return ret;
+}
+
+int imx_icc_register(struct platform_device *pdev,
+		     struct imx_icc_node_desc *nodes, int nodes_count)
+{
+	struct device *dev = &pdev->dev;
+	struct imx_icc_provider *provider_data;
+	struct icc_provider *provider;
+	int ret;
+
+	provider_data = devm_kzalloc(dev, sizeof(*provider_data), GFP_KERNEL);
+	if (!provider_data)
+		return -ENOMEM;
+	provider_data->dev = dev;
+
+	provider = devm_kzalloc(dev, sizeof(*provider), GFP_KERNEL);
+	if (!provider)
+		return -ENOMEM;
+	provider->set = imx_icc_set;
+	provider->aggregate = imx_icc_aggregate;
+	provider->xlate = imx_icc_xlate;
+	provider->data = provider_data;
+	provider->dev = dev;
+	platform_set_drvdata(pdev, provider);
+
+	ret = icc_provider_add(provider);
+	if (ret) {
+		dev_err(dev, "error adding interconnect provider: %d\n", ret);
+		return ret;
+	}
+
+	ret = imx_icc_register_nodes(provider, nodes, nodes_count);
+	if (ret)
+		goto provider_del;
+
+	pr_info("registered %s\n", pdev->name);
+
+	return 0;
+
+provider_del:
+	icc_provider_del(provider);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(imx_icc_register);
+
+int imx_icc_unregister(struct platform_device *pdev)
+{
+	struct icc_provider *provider = platform_get_drvdata(pdev);
+
+	icc_provider_del(provider);
+	imx_icc_unregister_nodes(provider);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(imx_icc_unregister);
diff --git a/drivers/interconnect/imx/imx.h b/drivers/interconnect/imx/imx.h
new file mode 100644
index 000000000000..9299b8d941f0
--- /dev/null
+++ b/drivers/interconnect/imx/imx.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Interconnect framework driver for i.MX SoC
+ *
+ * Copyright (c) 2019, BayLibre
+ * Copyright (c) 2019, NXP
+ * Author: Alexandre Bailon <abailon@baylibre.com>
+ * Author: Leonard Crestez <leonard.crestez@nxp.com>
+ */
+#ifndef __DRIVERS_INTERCONNECT_IMX_H
+#define __DRIVERS_INTERCONNECT_IMX_H
+
+#include <linux/kernel.h>
+
+#define IMX_ICC_MAX_LINKS	4
+
+/*
+ * struct imx_icc_node_adj - Describe a dynamic adjustment knob
+ */
+struct imx_icc_node_adj_desc {
+	unsigned int bw_mul, bw_div;
+};
+
+/*
+ * struct imx_icc_node - Describe an interconnect node
+ * @name: name of the node
+ * @id: an unique id to identify the node
+ * @links: an array of slaves' node id
+ * @num_links: number of id defined in links
+ */
+struct imx_icc_node_desc {
+	const char *name;
+	u16 id;
+	u16 links[IMX_ICC_MAX_LINKS];
+	u16 num_links;
+
+	const struct imx_icc_node_adj_desc *adj;
+};
+
+#define DEFINE_BUS_INTERCONNECT(_name, _id, _adj, ...)			\
+	{								\
+		.id = _id,						\
+		.name = _name,						\
+		.adj = _adj,						\
+		.num_links = ARRAY_SIZE(((int[]){ __VA_ARGS__ })),	\
+		.links = { __VA_ARGS__ },				\
+	}
+
+#define DEFINE_BUS_MASTER(_name, _id, _dest_id)				\
+	DEFINE_BUS_INTERCONNECT(_name, _id, NULL, 1, _dest_id)
+
+#define DEFINE_BUS_SLAVE(_name, _id, _adj)				\
+	DEFINE_BUS_INTERCONNECT(_name, _id, _adj, 0)
+
+int imx_icc_register(struct platform_device *pdev,
+		     struct imx_icc_node_desc *nodes,
+		     int nodes_count);
+int imx_icc_unregister(struct platform_device *pdev);
+
+#endif /* __DRIVERS_INTERCONNECT_IMX_H */
-- 
2.17.1


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

* [RFCv4 5/7] interconnect: imx: Add platform driver for imx8mm
  2019-08-23 14:36 [RFCv4 0/7] interconnect: Add imx support via devfreq Leonard Crestez
                   ` (3 preceding siblings ...)
  2019-08-23 14:36 ` [RFCv4 4/7] interconnect: Add imx core driver Leonard Crestez
@ 2019-08-23 14:36 ` Leonard Crestez
  2019-08-23 14:36 ` [RFCv4 6/7] soc: imx8mm: Register interconnect platform device Leonard Crestez
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 19+ messages in thread
From: Leonard Crestez @ 2019-08-23 14:36 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Artur Świgoń, Chanwoo Choi
  Cc: Alexandre Bailon, Krzysztof Kozlowski, MyungJoo Ham,
	Kyungmin Park, Saravana Kannan, Mark Rutland, Viresh Kumar,
	Shawn Guo, Dong Aisheng, Fabio Estevam, Stephen Boyd,
	Michael Turquette, kernel, linux-imx, linux-pm, devicetree,
	linux-arm-kernel

Add a platform driver for the i.MX8MM SoC describing bus topology.

Bandwidth adjustments is currently only supported on the DDRC and main
NOC. Scaling for the vpu/gpu/display NICs could be added in the future.

Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
 drivers/interconnect/imx/Kconfig          |   4 +
 drivers/interconnect/imx/Makefile         |   1 +
 drivers/interconnect/imx/imx8mm.c         | 105 ++++++++++++++++++++++
 include/dt-bindings/interconnect/imx8mm.h |  49 ++++++++++
 4 files changed, 159 insertions(+)
 create mode 100644 drivers/interconnect/imx/imx8mm.c
 create mode 100644 include/dt-bindings/interconnect/imx8mm.h

diff --git a/drivers/interconnect/imx/Kconfig b/drivers/interconnect/imx/Kconfig
index 7d81d3c83a61..15671fe7f600 100644
--- a/drivers/interconnect/imx/Kconfig
+++ b/drivers/interconnect/imx/Kconfig
@@ -1,5 +1,9 @@
 config INTERCONNECT_IMX
 	bool "i.MX interconnect drivers"
 	depends on ARCH_MXC || COMPILE_TEST
 	help
 	  Generic interconnect driver for i.MX SOCs
+
+config INTERCONNECT_IMX8MM
+	def_bool y
+	depends on INTERCONNECT_IMX
diff --git a/drivers/interconnect/imx/Makefile b/drivers/interconnect/imx/Makefile
index bb92fd9fe4a5..5f658c1608a6 100644
--- a/drivers/interconnect/imx/Makefile
+++ b/drivers/interconnect/imx/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_INTERCONNECT_IMX) += imx.o
+obj-$(CONFIG_INTERCONNECT_IMX8MM) += imx8mm.o
diff --git a/drivers/interconnect/imx/imx8mm.c b/drivers/interconnect/imx/imx8mm.c
new file mode 100644
index 000000000000..acc002153729
--- /dev/null
+++ b/drivers/interconnect/imx/imx8mm.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Interconnect framework driver for i.MX SoC
+ *
+ * Copyright (c) 2019, BayLibre
+ * Copyright (c) 2019, NXP
+ * Author: Alexandre Bailon <abailon@baylibre.com>
+ * Author: Leonard Crestez <leonard.crestez@nxp.com>
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/interconnect/imx8mm.h>
+
+#include "imx.h"
+
+static const struct imx_icc_node_adj_desc imx8mm_dram_adj = {
+	.bw_mul = 1,
+	.bw_div = 16,
+};
+
+static const struct imx_icc_node_adj_desc imx8mm_noc_adj = {
+	.bw_mul = 1,
+	.bw_div = 16,
+};
+
+/*
+ * Describe bus masters, slaves and connections between them
+ *
+ * This is a simplified subset of the bus diagram, there are several other
+ * PL301 nics which are skipped/merged into PL301_MAIN
+ */
+static struct imx_icc_node_desc nodes[] = {
+	DEFINE_BUS_INTERCONNECT("NOC", IMX8MM_ICN_NOC, &imx8mm_noc_adj,
+			IMX8MM_ICS_DRAM, IMX8MM_ICN_MAIN),
+
+	DEFINE_BUS_SLAVE("DRAM", IMX8MM_ICS_DRAM, &imx8mm_dram_adj),
+	DEFINE_BUS_SLAVE("OCRAM", IMX8MM_ICS_OCRAM, NULL),
+	DEFINE_BUS_MASTER("A53", IMX8MM_ICM_A53, IMX8MM_ICN_NOC),
+
+	/* VPUMIX */
+	DEFINE_BUS_MASTER("VPU H1", IMX8MM_ICM_VPU_H1, IMX8MM_ICN_VIDEO),
+	DEFINE_BUS_MASTER("VPU G1", IMX8MM_ICM_VPU_G1, IMX8MM_ICN_VIDEO),
+	DEFINE_BUS_MASTER("VPU G2", IMX8MM_ICM_VPU_G2, IMX8MM_ICN_VIDEO),
+	DEFINE_BUS_INTERCONNECT("PL301_VIDEO", IMX8MM_ICN_VIDEO, NULL, IMX8MM_ICN_NOC),
+
+	/* GPUMIX */
+	DEFINE_BUS_MASTER("GPU 2D", IMX8MM_ICM_GPU2D, IMX8MM_ICN_GPU),
+	DEFINE_BUS_MASTER("GPU 3D", IMX8MM_ICM_GPU3D, IMX8MM_ICN_GPU),
+	DEFINE_BUS_INTERCONNECT("PL301_GPU", IMX8MM_ICN_GPU, NULL, IMX8MM_ICN_NOC),
+
+	/* DISPLAYMIX */
+	DEFINE_BUS_MASTER("CSI", IMX8MM_ICM_CSI, IMX8MM_ICN_MIPI),
+	DEFINE_BUS_MASTER("LCDIF", IMX8MM_ICM_LCDIF, IMX8MM_ICN_MIPI),
+	DEFINE_BUS_INTERCONNECT("PL301_MIPI", IMX8MM_ICN_MIPI, NULL, IMX8MM_ICN_NOC),
+
+	/* HSIO */
+	DEFINE_BUS_MASTER("USB1", IMX8MM_ICM_USB1, IMX8MM_ICN_HSIO),
+	DEFINE_BUS_MASTER("USB2", IMX8MM_ICM_USB2, IMX8MM_ICN_HSIO),
+	DEFINE_BUS_MASTER("PCIE", IMX8MM_ICM_PCIE, IMX8MM_ICN_HSIO),
+	DEFINE_BUS_INTERCONNECT("PL301_HSIO", IMX8MM_ICN_HSIO, NULL, IMX8MM_ICN_NOC),
+
+	/* Audio */
+	DEFINE_BUS_MASTER("SDMA2", IMX8MM_ICM_SDMA2, IMX8MM_ICN_AUDIO),
+	DEFINE_BUS_MASTER("SDMA3", IMX8MM_ICM_SDMA3, IMX8MM_ICN_AUDIO),
+	DEFINE_BUS_INTERCONNECT("PL301_AUDIO", IMX8MM_ICN_AUDIO, NULL, IMX8MM_ICN_MAIN),
+
+	/* Ethernet */
+	DEFINE_BUS_MASTER("ENET", IMX8MM_ICM_ENET, IMX8MM_ICN_ENET),
+	DEFINE_BUS_INTERCONNECT("PL301_ENET", IMX8MM_ICN_ENET, NULL, IMX8MM_ICN_MAIN),
+
+	/* Other */
+	DEFINE_BUS_MASTER("SDMA1", IMX8MM_ICM_SDMA1, IMX8MM_ICN_MAIN),
+	DEFINE_BUS_MASTER("NAND", IMX8MM_ICM_NAND, IMX8MM_ICN_MAIN),
+	DEFINE_BUS_MASTER("USDHC1", IMX8MM_ICM_USDHC1, IMX8MM_ICN_MAIN),
+	DEFINE_BUS_MASTER("USDHC2", IMX8MM_ICM_USDHC2, IMX8MM_ICN_MAIN),
+	DEFINE_BUS_MASTER("USDHC3", IMX8MM_ICM_USDHC3, IMX8MM_ICN_MAIN),
+	DEFINE_BUS_INTERCONNECT("PL301_MAIN", IMX8MM_ICN_MAIN, NULL,
+			IMX8MM_ICN_NOC, IMX8MM_ICS_OCRAM),
+};
+
+static int imx8mm_icc_probe(struct platform_device *pdev)
+{
+	return imx_icc_register(pdev, nodes, ARRAY_SIZE(nodes));
+}
+
+static int imx8mm_icc_remove(struct platform_device *pdev)
+{
+	return imx_icc_unregister(pdev);
+}
+
+static struct platform_driver imx8mm_icc_driver = {
+	.probe = imx8mm_icc_probe,
+	.remove = imx8mm_icc_remove,
+	.driver = {
+		.name = "imx8mm-interconnect",
+	},
+};
+
+module_platform_driver(imx8mm_icc_driver);
+MODULE_AUTHOR("Alexandre Bailon <abailon@baylibre.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/dt-bindings/interconnect/imx8mm.h b/include/dt-bindings/interconnect/imx8mm.h
new file mode 100644
index 000000000000..5404f2af15c3
--- /dev/null
+++ b/include/dt-bindings/interconnect/imx8mm.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Interconnect framework driver for i.MX SoC
+ *
+ * Copyright (c) 2019, BayLibre
+ * Author: Alexandre Bailon <abailon@baylibre.com>
+ */
+
+#ifndef __IMX8MM_ICM_INTERCONNECT_IDS_H
+#define __IMX8MM_ICM_INTERCONNECT_IDS_H
+
+#define IMX8MM_ICN_NOC		1
+#define IMX8MM_ICS_DRAM		2
+#define IMX8MM_ICS_OCRAM	3
+#define IMX8MM_ICM_A53		4
+
+#define IMX8MM_ICM_VPU_H1	5
+#define IMX8MM_ICM_VPU_G1	6
+#define IMX8MM_ICM_VPU_G2	7
+#define IMX8MM_ICN_VIDEO	8
+
+#define IMX8MM_ICM_GPU2D	9
+#define IMX8MM_ICM_GPU3D	10
+#define IMX8MM_ICN_GPU		11
+
+#define IMX8MM_ICM_CSI		12
+#define IMX8MM_ICM_LCDIF	13
+#define IMX8MM_ICN_MIPI		14
+
+#define IMX8MM_ICM_USB1		15
+#define IMX8MM_ICM_USB2		16
+#define IMX8MM_ICM_PCIE		17
+#define IMX8MM_ICN_HSIO		18
+
+#define IMX8MM_ICM_SDMA2	19
+#define IMX8MM_ICM_SDMA3	20
+#define IMX8MM_ICN_AUDIO	21
+
+#define IMX8MM_ICN_ENET		22
+#define IMX8MM_ICM_ENET		23
+
+#define IMX8MM_ICN_MAIN		24
+#define IMX8MM_ICM_NAND		25
+#define IMX8MM_ICM_SDMA1	26
+#define IMX8MM_ICM_USDHC1	27
+#define IMX8MM_ICM_USDHC2	28
+#define IMX8MM_ICM_USDHC3	29
+
+#endif /* __IMX8MM_ICM_INTERCONNECT_IDS_H */
-- 
2.17.1


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

* [RFCv4 6/7] soc: imx8mm: Register interconnect platform device
  2019-08-23 14:36 [RFCv4 0/7] interconnect: Add imx support via devfreq Leonard Crestez
                   ` (4 preceding siblings ...)
  2019-08-23 14:36 ` [RFCv4 5/7] interconnect: imx: Add platform driver for imx8mm Leonard Crestez
@ 2019-08-23 14:36 ` Leonard Crestez
  2019-08-23 14:37 ` [RFCv4 7/7] arm64: dts: imx8mm: Add interconnect properties Leonard Crestez
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 19+ messages in thread
From: Leonard Crestez @ 2019-08-23 14:36 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Artur Świgoń, Chanwoo Choi
  Cc: Alexandre Bailon, Krzysztof Kozlowski, MyungJoo Ham,
	Kyungmin Park, Saravana Kannan, Mark Rutland, Viresh Kumar,
	Shawn Guo, Dong Aisheng, Fabio Estevam, Stephen Boyd,
	Michael Turquette, kernel, linux-imx, linux-pm, devicetree,
	linux-arm-kernel

Since there is no virtual devicetree node representing the interconnect
we need to probe the icc device externally. Probing this from the SOC
driver allows the interconnect device to be built as a module.

This is very similar to imx-cpufreq-dt.

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
 drivers/soc/imx/soc-imx8.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/soc/imx/soc-imx8.c b/drivers/soc/imx/soc-imx8.c
index b9831576dd25..24d515a9fdb2 100644
--- a/drivers/soc/imx/soc-imx8.c
+++ b/drivers/soc/imx/soc-imx8.c
@@ -22,10 +22,11 @@
 /* Same as ANADIG_DIGPROG_IMX7D */
 #define ANADIG_DIGPROG_IMX8MM	0x800
 
 struct imx8_soc_data {
 	char *name;
+	char *icc_driver;
 	u32 (*soc_revision)(void);
 };
 
 static u64 soc_uid;
 
@@ -115,10 +116,11 @@ static const struct imx8_soc_data imx8mq_soc_data = {
 };
 
 static const struct imx8_soc_data imx8mm_soc_data = {
 	.name = "i.MX8MM",
 	.soc_revision = imx8mm_soc_revision,
+	.icc_driver = "imx8mm-interconnect",
 };
 
 static const struct imx8_soc_data imx8mn_soc_data = {
 	.name = "i.MX8MN",
 	.soc_revision = imx8mm_soc_revision,
@@ -185,10 +187,12 @@ static int __init imx8_soc_init(void)
 	if (ret)
 		goto free_rev;
 
 	if (IS_ENABLED(CONFIG_ARM_IMX_CPUFREQ_DT))
 		platform_device_register_simple("imx-cpufreq-dt", -1, NULL, 0);
+	if (IS_ENABLED(CONFIG_INTERCONNECT_IMX))
+		platform_device_register_simple(data->icc_driver, -1, NULL, 0);
 
 	return 0;
 
 free_rev:
 	if (strcmp(soc_dev_attr->revision, "unknown"))
-- 
2.17.1


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

* [RFCv4 7/7] arm64: dts: imx8mm: Add interconnect properties
  2019-08-23 14:36 [RFCv4 0/7] interconnect: Add imx support via devfreq Leonard Crestez
                   ` (5 preceding siblings ...)
  2019-08-23 14:36 ` [RFCv4 6/7] soc: imx8mm: Register interconnect platform device Leonard Crestez
@ 2019-08-23 14:37 ` Leonard Crestez
  2019-09-16 12:34 ` [RFCv4 0/7] interconnect: Add imx support via devfreq Leonard Crestez
  2019-09-21  6:06 ` Martin Kepplinger
  8 siblings, 0 replies; 19+ messages in thread
From: Leonard Crestez @ 2019-08-23 14:37 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Artur Świgoń, Chanwoo Choi
  Cc: Alexandre Bailon, Krzysztof Kozlowski, MyungJoo Ham,
	Kyungmin Park, Saravana Kannan, Mark Rutland, Viresh Kumar,
	Shawn Guo, Dong Aisheng, Fabio Estevam, Stephen Boyd,
	Michael Turquette, kernel, linux-imx, linux-pm, devicetree,
	linux-arm-kernel

Add #interconnect-cells and interconnect-node-id properties on devfreq
nodes. The imx interconnect provider will scan these.

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mm.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
index 5474c50784c2..8b5442d8b1b2 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
@@ -6,10 +6,11 @@
 #include <dt-bindings/clock/imx8mm-clock.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/thermal/thermal.h>
+#include <dt-bindings/interconnect/imx8mm.h>
 
 #include "imx8mm-pinfunc.h"
 
 / {
 	compatible = "fsl,imx8mm";
@@ -806,10 +807,12 @@
 		noc: noc@32700000 {
 			compatible = "fsl,imx8mm-noc", "fsl,imx8m-noc";
 			reg = <0x32700000 0x100000>;
 			clocks = <&clk IMX8MM_CLK_NOC>;
 			devfreq = <&ddrc>;
+			#interconnect-cells = <1>;
+			interconnect-node-id = <IMX8MM_ICN_NOC>;
 			operating-points-v2 = <&noc_opp_table>;
 		};
 
 		aips4: bus@32c00000 {
 			compatible = "fsl,aips-bus", "simple-bus";
@@ -896,10 +899,12 @@
 		};
 
 		ddrc: dram-controller@3d400000 {
 			compatible = "fsl,imx8mm-ddrc", "fsl,imx8m-ddrc";
 			reg = <0x3d400000 0x400000>;
+			#interconnect-cells = <1>;
+			interconnect-node-id = <IMX8MM_ICS_DRAM>;
 			clock-names = "dram_core",
 				      "dram_pll",
 				      "dram_alt",
 				      "dram_apb";
 			clocks = <&clk IMX8MM_CLK_DRAM_CORE>,
-- 
2.17.1


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

* Re: [RFCv4 0/7] interconnect: Add imx support via devfreq
  2019-08-23 14:36 [RFCv4 0/7] interconnect: Add imx support via devfreq Leonard Crestez
                   ` (6 preceding siblings ...)
  2019-08-23 14:37 ` [RFCv4 7/7] arm64: dts: imx8mm: Add interconnect properties Leonard Crestez
@ 2019-09-16 12:34 ` Leonard Crestez
  2019-09-25  2:37   ` Georgi Djakov
  2019-09-21  6:06 ` Martin Kepplinger
  8 siblings, 1 reply; 19+ messages in thread
From: Leonard Crestez @ 2019-09-16 12:34 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Mark Rutland, devicetree
  Cc: Artur Świgoń,
	Chanwoo Choi, Alexandre Bailon, Krzysztof Kozlowski,
	MyungJoo Ham, Kyungmin Park, Saravana Kannan, Viresh Kumar,
	Shawn Guo, Aisheng Dong, Fabio Estevam, Stephen Boyd,
	Michael Turquette, kernel, dl-linux-imx, linux-pm,
	linux-arm-kernel

On 23.08.2019 17:37, Leonard Crestez wrote:
> This series add imx support for interconnect via devfreq: the ICC
> framework is used to aggregate requests from devices and then those are
> converted to DEV_PM_QOS_MIN_FREQUENCY requests for devfreq.
>  
> Since there is no single devicetree node that can represent the "interconnect"
> new API is added to allow individual devfreq nodes to act as parsing proxies
> all mapping to a single soc-level icc provider. This is still RFC
> because of this

Any comments? I made a lot of changes relative to previous versions, 
most of them solely to avoid adding a virtual node in DT bindings.

The only current interconnect provider implementation is for qcom and it 
uses a firmware node as the provider node (with #interconnect-cells). 
However there is no obvious equivalent of that for imx and many other SOCs.

On imx there are multiple pieces of scalable fabric which can be defined 
in DT as devfreq devices and it sort of makes sense to add 
#interconnect-cells to those. However when it comes to describing the 
SOC interconnect graph it's much more convenient to have a single 
per-SOC platform driver.

My solution is to add an "icc_proxy" API so that a single platform-level 
interconnect provider can be referenced through multiple DT nodes. Does 
this make sense?

The implementation is not very pretty, the interconnect platform devices 
ends up enumerating the entire devicetree in order to find proxies.

Right now the interconnect API use a relatively standard split between 
consumer and "provider" but I think it might make sense to have a 
separate abstractions for "graph" and "midnode". A "midnode" could act 
as a DT proxy if there is no single representation of the "interconnect" 
and it could support custom scaling for itself (with the default being 
scaling kbps into MIN_FREQ).

There are also other options:
  * Pick one "main" bus and bless it as the "interconnect provider". I 
want to represent buses as devfreq devices so I would have to call from 
devfreq to ICC for registration somehow.
  * Maybe the "no virtual device" rule could be relaxed for the 
interconnect subsystem?

--
Regards,
Leonard

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

* Re: [RFCv4 3/7] dt-bindings: devfreq: imx: Describe interconnect properties
  2019-08-23 14:36 ` [RFCv4 3/7] dt-bindings: devfreq: imx: Describe interconnect properties Leonard Crestez
@ 2019-09-17 20:19   ` Rob Herring
  2019-09-23 17:42     ` Leonard Crestez
  0 siblings, 1 reply; 19+ messages in thread
From: Rob Herring @ 2019-09-17 20:19 UTC (permalink / raw)
  To: Leonard Crestez
  Cc: Georgi Djakov, Artur Świgoń,
	Chanwoo Choi, Alexandre Bailon, Krzysztof Kozlowski,
	MyungJoo Ham, Kyungmin Park, Saravana Kannan, Mark Rutland,
	Viresh Kumar, Shawn Guo, Dong Aisheng, Fabio Estevam,
	Stephen Boyd, Michael Turquette, kernel, linux-imx, linux-pm,
	devicetree, linux-arm-kernel

On Fri, Aug 23, 2019 at 05:36:56PM +0300, Leonard Crestez wrote:
> The interconnect-node-id property is parsed by the imx interconnect
> driver to find nodes on which frequencies can be adjusted.
> 
> Add #interconnect-cells so that device drivers can request paths from
> bus nodes instead of requiring a separate "virtual" node to represent
> the interconnect itself.
> 
> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
> ---
>  Documentation/devicetree/bindings/devfreq/imx-ddrc.yaml | 5 +++++
>  Documentation/devicetree/bindings/devfreq/imx.yaml      | 5 +++++
>  2 files changed, 10 insertions(+)

Please combine this with the other series for devfreq support.

Rob

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

* Re: [RFCv4 0/7] interconnect: Add imx support via devfreq
  2019-08-23 14:36 [RFCv4 0/7] interconnect: Add imx support via devfreq Leonard Crestez
                   ` (7 preceding siblings ...)
  2019-09-16 12:34 ` [RFCv4 0/7] interconnect: Add imx support via devfreq Leonard Crestez
@ 2019-09-21  6:06 ` Martin Kepplinger
  2019-09-23 21:22   ` Leonard Crestez
  8 siblings, 1 reply; 19+ messages in thread
From: Martin Kepplinger @ 2019-09-21  6:06 UTC (permalink / raw)
  To: Leonard Crestez, Georgi Djakov, Rob Herring,
	Artur Świgoń,
	Chanwoo Choi
  Cc: Mark Rutland, Dong Aisheng, linux-arm-kernel, Saravana Kannan,
	linux-pm, Stephen Boyd, Viresh Kumar, Michael Turquette,
	Krzysztof Kozlowski, Kyungmin Park, MyungJoo Ham,
	Alexandre Bailon, kernel, Fabio Estevam, Shawn Guo, devicetree,
	linux-imx

On 23.08.19 16:36, Leonard Crestez wrote:
> This series add imx support for interconnect via devfreq: the ICC
> framework is used to aggregate requests from devices and then those are
> converted to DEV_PM_QOS_MIN_FREQUENCY requests for devfreq.
> 
> The devfreq parts are posted separately, this series only intersects in
> devicetree: https://patchwork.kernel.org/cover/11104113/
> 
> Since there is no single devicetree node that can represent the "interconnect"
> new API is added to allow individual devfreq nodes to act as parsing proxies
> all mapping to a single soc-level icc provider. This is still RFC
> because this
> 
> The rest of the changes are small and deal with review comments.
> 

hi Leonard,

When I run https://github.com/cdleonard/linux/tree/next_imx_busfreq and
https://github.com/cdleonard/arm-trusted-firmware/tree/imx_2.0.y_busfreq
on imx8mq, probe() fails:

[    1.082847] imx-ddrc-devfreq 3d400000.dram-controller: failed to init
firmware freq info: -19
[    1.091434] imx-ddrc-devfreq: probe of 3d400000.dram-controller
rejects match -19

in imx_ddrc_init_freq_info()'s check:

if (priv->freq_count <= 0 || priv->freq_count > IMX_DDRC_MAX_FREQ_COUNT)

That would indicate that I'm missing something in ATF? I'm pretty sure
I'm running your tree though.

Does anything come to your mind what I might be doing wrong? Am I
running your "correct" linux tree? Remember I'm on imx8mq, so I don't
exactly test this RFC of yours.

Also, how are your plans to rebase / update your ATF tree?

And since there's a lot in there: what additions are necessary for this
devfreq to work?

Lastly, how do you test? Is /sys/class/devfreq supposted to get populated?

thanks for your work!

                                    martin


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

* Re: [RFCv4 3/7] dt-bindings: devfreq: imx: Describe interconnect properties
  2019-09-17 20:19   ` Rob Herring
@ 2019-09-23 17:42     ` Leonard Crestez
  2019-09-23 21:03       ` Rob Herring
  0 siblings, 1 reply; 19+ messages in thread
From: Leonard Crestez @ 2019-09-23 17:42 UTC (permalink / raw)
  To: Rob Herring, Georgi Djakov
  Cc: Artur Świgoń,
	Chanwoo Choi, Alexandre Bailon, Krzysztof Kozlowski,
	MyungJoo Ham, Kyungmin Park, Saravana Kannan, Mark Rutland,
	Viresh Kumar, Shawn Guo, Aisheng Dong, Fabio Estevam,
	Stephen Boyd, Michael Turquette, kernel, dl-linux-imx, linux-pm,
	devicetree, linux-arm-kernel

On 17.09.2019 23:20, Rob Herring wrote:
> On Fri, Aug 23, 2019 at 05:36:56PM +0300, Leonard Crestez wrote:
>> The interconnect-node-id property is parsed by the imx interconnect
>> driver to find nodes on which frequencies can be adjusted.
>>
>> Add #interconnect-cells so that device drivers can request paths from
>> bus nodes instead of requiring a separate "virtual" node to represent
>> the interconnect itself.
>>
>> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
>> ---
>>   Documentation/devicetree/bindings/devfreq/imx-ddrc.yaml | 5 +++++
>>   Documentation/devicetree/bindings/devfreq/imx.yaml      | 5 +++++
>>   2 files changed, 10 insertions(+)
> 
> Please combine this with the other series for devfreq support.

I understand that having two series which add to the same bindings file 
is odd but the devfreq and interconnect parts are independent to a very 
large degree and devfreq can be useful on it's own.

The only reason devfreq bindings are updated is to avoid adding a 
"virtual" node for interconnect. Since DT is a big source of confusion 
here can you read https://patchwork.kernel.org/cover/11111865/#22883457 
and maybe offer some advice?

--
Regards,
Leonard

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

* Re: [RFCv4 3/7] dt-bindings: devfreq: imx: Describe interconnect properties
  2019-09-23 17:42     ` Leonard Crestez
@ 2019-09-23 21:03       ` Rob Herring
  2019-09-24 14:39         ` Leonard Crestez
  0 siblings, 1 reply; 19+ messages in thread
From: Rob Herring @ 2019-09-23 21:03 UTC (permalink / raw)
  To: Leonard Crestez
  Cc: Georgi Djakov, Artur Świgoń,
	Chanwoo Choi, Alexandre Bailon, Krzysztof Kozlowski,
	MyungJoo Ham, Kyungmin Park, Saravana Kannan, Mark Rutland,
	Viresh Kumar, Shawn Guo, Aisheng Dong, Fabio Estevam,
	Stephen Boyd, Michael Turquette, kernel, dl-linux-imx, linux-pm,
	devicetree, linux-arm-kernel

On Mon, Sep 23, 2019 at 12:42 PM Leonard Crestez
<leonard.crestez@nxp.com> wrote:
>
> On 17.09.2019 23:20, Rob Herring wrote:
> > On Fri, Aug 23, 2019 at 05:36:56PM +0300, Leonard Crestez wrote:
> >> The interconnect-node-id property is parsed by the imx interconnect
> >> driver to find nodes on which frequencies can be adjusted.
> >>
> >> Add #interconnect-cells so that device drivers can request paths from
> >> bus nodes instead of requiring a separate "virtual" node to represent
> >> the interconnect itself.
> >>
> >> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
> >> ---
> >>   Documentation/devicetree/bindings/devfreq/imx-ddrc.yaml | 5 +++++
> >>   Documentation/devicetree/bindings/devfreq/imx.yaml      | 5 +++++
> >>   2 files changed, 10 insertions(+)
> >
> > Please combine this with the other series for devfreq support.
>
> I understand that having two series which add to the same bindings file
> is odd but the devfreq and interconnect parts are independent to a very
> large degree and devfreq can be useful on it's own.

To start with, I'm suspicious of any 'devfreq' binding because that's
a Linux thing. I somewhat expect that the interconnect binding should
replace the devfreq binding, but I haven't been able to investigate.

> The only reason devfreq bindings are updated is to avoid adding a
> "virtual" node for interconnect. Since DT is a big source of confusion
> here can you read https://patchwork.kernel.org/cover/11111865/#22883457
> and maybe offer some advice?

Design something that matches the structure of the h/w not how Linux
drivers happen to be structured. I can't tell what that is without any
context around adding a couple of properties. Nor do I have the time
to dig into each SoC vendor's bus structure if it's even documented
publicly.

I also don't follow why you need 'interconnect-node-id' and if you do,
it should be a common property.

Rob

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

* Re: [RFCv4 0/7] interconnect: Add imx support via devfreq
  2019-09-21  6:06 ` Martin Kepplinger
@ 2019-09-23 21:22   ` Leonard Crestez
  0 siblings, 0 replies; 19+ messages in thread
From: Leonard Crestez @ 2019-09-23 21:22 UTC (permalink / raw)
  To: Martin Kepplinger, Jacky Bai, Anson Huang
  Cc: Georgi Djakov, Rob Herring, Artur Świgoń,
	Chanwoo Choi, Mark Rutland, Aisheng Dong, linux-arm-kernel,
	Saravana Kannan, linux-pm, Stephen Boyd, Viresh Kumar,
	Michael Turquette, Krzysztof Kozlowski, Kyungmin Park,
	MyungJoo Ham, Alexandre Bailon, kernel, Fabio Estevam, Shawn Guo,
	devicetree, dl-linux-imx, Peng Fan

On 21.09.2019 09:07, Martin Kepplinger wrote:
> On 23.08.19 16:36, Leonard Crestez wrote:
>> This series add imx support for interconnect via devfreq: the ICC
>> framework is used to aggregate requests from devices and then those are
>> converted to DEV_PM_QOS_MIN_FREQUENCY requests for devfreq.
>>
>> The devfreq parts are posted separately, this series only intersects in
>> devicetree.
>>
>> Since there is no single devicetree node that can represent the "interconnect"
>> new API is added to allow individual devfreq nodes to act as parsing proxies
>> all mapping to a single soc-level icc provider. This is still RFC
>> because this
>>
>> The rest of the changes are small and deal with review comments.

> on imx8mq, probe() fails:
> 
> [    1.082847] imx-ddrc-devfreq 3d400000.dram-controller: failed to init
> firmware freq info: -19
> [    1.091434] imx-ddrc-devfreq: probe of 3d400000.dram-controller
> rejects match -19
> 
> in imx_ddrc_init_freq_info()'s check:
> 
> if (priv->freq_count <= 0 || priv->freq_count > IMX_DDRC_MAX_FREQ_COUNT)
> 
> That would indicate that I'm missing something in ATF? I'm pretty sure
> I'm running your tree though.

What is your board and uboot version? I tested on imx8mq-evk (SOC Rev 
B1) with NXP uboot. For example this uboot release works:

https://source.codeaurora.org/external/imx/uboot-imx/log/?h=imx_v2019.04_4.19.35_1.0.0

It is uboot which trains DDR for multiple frequencies and then passes 
that info to ATF. I'm not sure about the steps required to enable this 
for 3rd-party boards, should be same as for busfreq from NXP tree.

Getting this to work on a 3rd-party board would be interesting.

> Does anything come to your mind what I might be doing wrong? Am I
> running your "correct" linux tree? Remember I'm on imx8mq, so I don't
> exactly test this RFC of yours.
> 
> Also, how are your plans to rebase / update your ATF tree?

The ATF changes will show up in a future release of NXP ATF branch, when 
that happens I will drop my branch. NXP ATF releases are on CAF:

     https://source.codeaurora.org/external/imx/imx-atf/

> And since there's a lot in there: what additions are necessary for this
> devfreq to work?

devfreq imx support here: https://patchwork.kernel.org/cover/11104113/
Interconnect support also needs PM QoS support for devfreq:

     https://patchwork.kernel.org/cover/11157649/

> Lastly, how do you test? Is /sys/class/devfreq supposted to get populated?

Yes, and only the devfreq patches are required for that.

# cat /sys/class/devfreq/devfreq0/available_frequencies
25000000 100000000 800000000
# cat /sys/class/devfreq/devfreq0/cur_freq
800000000

You should be able to control frequencies manually with the userspace 
governor:
# echo "userspace" > /sys/class/devfreq/devfreq0/governor
# echo "25000000" > /sys/class/devfreq/devfreq0/userspace/set_freq

This series allows devices to request guaranteed bandwidth for 
themselves through the interconnect subsystem, without it DRAM freq will 
still switch but you'll have problems like display corruption as it 
turns on before freq goes up. You can check that probe worked by doing

# cat /sys/kernel/debug/interconnect/interconnect_summary

--
Regards,
Leonard

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

* Re: [RFCv4 3/7] dt-bindings: devfreq: imx: Describe interconnect properties
  2019-09-23 21:03       ` Rob Herring
@ 2019-09-24 14:39         ` Leonard Crestez
  0 siblings, 0 replies; 19+ messages in thread
From: Leonard Crestez @ 2019-09-24 14:39 UTC (permalink / raw)
  To: Rob Herring, Georgi Djakov
  Cc: Artur Świgoń,
	Chanwoo Choi, Alexandre Bailon, Krzysztof Kozlowski,
	MyungJoo Ham, Kyungmin Park, Saravana Kannan, Mark Rutland,
	Viresh Kumar, Shawn Guo, Aisheng Dong, Fabio Estevam,
	Stephen Boyd, Michael Turquette, kernel, dl-linux-imx, linux-pm,
	devicetree, linux-arm-kernel

On 24.09.2019 00:04, Rob Herring wrote:
> On Mon, Sep 23, 2019 at 12:42 PM Leonard Crestez
> <leonard.crestez@nxp.com> wrote:
>>
>> On 17.09.2019 23:20, Rob Herring wrote:
>>> On Fri, Aug 23, 2019 at 05:36:56PM +0300, Leonard Crestez wrote:
>>>> The interconnect-node-id property is parsed by the imx interconnect
>>>> driver to find nodes on which frequencies can be adjusted.
>>>>
>>>> Add #interconnect-cells so that device drivers can request paths from
>>>> bus nodes instead of requiring a separate "virtual" node to represent
>>>> the interconnect itself.
>>>>
>>>> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
>>>> ---
>>>>    Documentation/devicetree/bindings/devfreq/imx-ddrc.yaml | 5 +++++
>>>>    Documentation/devicetree/bindings/devfreq/imx.yaml      | 5 +++++
>>>>    2 files changed, 10 insertions(+)
>>>
>>> Please combine this with the other series for devfreq support.
>>
>> I understand that having two series which add to the same bindings file
>> is odd but the devfreq and interconnect parts are independent to a very
>> large degree and devfreq can be useful on it's own.
> 
> To start with, I'm suspicious of any 'devfreq' binding because that's
> a Linux thing. I somewhat expect that the interconnect binding should
> replace the devfreq binding, but I haven't been able to investigate.
> 
> Design something that matches the structure of the h/w not how Linux
> drivers happen to be structured. I can't tell what that is without any
> context around adding a couple of properties. Nor do I have the time
> to dig into each SoC vendor's bus structure if it's even documented
> publicly.

Device tree binding files are organized based on linux subsystems but 
otherwise there's little particularly specific to "devfreq" in this new 
binding.

An imx NIC or NOC is a physical component of a SOC which can run at a 
variable clock speed. The device binding uses standard clk and opp 
tables in meaningful ways so that first part is reasonable.

I also want to implement an interconnect provider but an "interconnect" 
is not a single device but rather a graph of discrete buses. Some options:
* Add a custom virtual device, easy but not upstreamable.
* Have a single icc provider device use the individual buses as 
"proxies" for OF parting. Implemented in this series but not very pretty.
* Pick the "main noc" as the single interconnect provider?

Alternatively the approach of defining the graph in the driver could be 
dropped and everything could be described in DT (quite verbose). This 
seems to be what Samsung is doing:

https://patchwork.kernel.org/project/linux-arm-kernel/list/?series=176291

It might even possible to use of_graph; this is complicated but the NICs 
and NOCs do in fact have discrete ports with assignable properties.

 > I also don't follow why you need 'interconnect-node-id' and if you do,
 > it should be a common property.

The "interconnect-node-id" property in devicetree identifies nodes from 
the interconnect graph; for example the DDRC node identifies itself as 
IMX8MM_ICS_DRAM.

--
Regards,
Leonard


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

* Re: [RFCv4 0/7] interconnect: Add imx support via devfreq
  2019-09-16 12:34 ` [RFCv4 0/7] interconnect: Add imx support via devfreq Leonard Crestez
@ 2019-09-25  2:37   ` Georgi Djakov
  2019-09-25 22:52     ` Leonard Crestez
  0 siblings, 1 reply; 19+ messages in thread
From: Georgi Djakov @ 2019-09-25  2:37 UTC (permalink / raw)
  To: Leonard Crestez, Rob Herring, Mark Rutland, devicetree
  Cc: Artur Świgoń,
	Chanwoo Choi, Alexandre Bailon, Krzysztof Kozlowski,
	MyungJoo Ham, Kyungmin Park, Saravana Kannan, Viresh Kumar,
	Shawn Guo, Aisheng Dong, Fabio Estevam, Stephen Boyd,
	Michael Turquette, kernel, dl-linux-imx, linux-pm,
	linux-arm-kernel

Hi Leonard,

On 9/16/19 05:34, Leonard Crestez wrote:
> On 23.08.2019 17:37, Leonard Crestez wrote:
>> This series add imx support for interconnect via devfreq: the ICC
>> framework is used to aggregate requests from devices and then those are
>> converted to DEV_PM_QOS_MIN_FREQUENCY requests for devfreq.
>>  
>> Since there is no single devicetree node that can represent the "interconnect"
>> new API is added to allow individual devfreq nodes to act as parsing proxies
>> all mapping to a single soc-level icc provider. This is still RFC
>> because of this
> 
> Any comments? I made a lot of changes relative to previous versions, 
> most of them solely to avoid adding a virtual node in DT bindings.
> 
> The only current interconnect provider implementation is for qcom and it 
> uses a firmware node as the provider node (with #interconnect-cells). 
> However there is no obvious equivalent of that for imx and many other SOCs.

Not sure if it will help, but have you seen the qcs404 interconnect driver?
There is also mt8183 interconnect provider driver on LKML.

> On imx there are multiple pieces of scalable fabric which can be defined 
> in DT as devfreq devices and it sort of makes sense to add 
> #interconnect-cells to those. However when it comes to describing the 
> SOC interconnect graph it's much more convenient to have a single 
> per-SOC platform driver.

Is all the NoC configuration done only by ATF? Are there any NoC related memory
mapped registers?

Thanks,
Georgi

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

* Re: [RFCv4 0/7] interconnect: Add imx support via devfreq
  2019-09-25  2:37   ` Georgi Djakov
@ 2019-09-25 22:52     ` Leonard Crestez
  2019-09-26  0:51       ` Georgi Djakov
  0 siblings, 1 reply; 19+ messages in thread
From: Leonard Crestez @ 2019-09-25 22:52 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Artur Świgoń, Chanwoo Choi
  Cc: Mark Rutland, devicetree, Alexandre Bailon, Krzysztof Kozlowski,
	MyungJoo Ham, Kyungmin Park, Saravana Kannan, Viresh Kumar,
	Shawn Guo, Aisheng Dong, Fabio Estevam, Stephen Boyd,
	Michael Turquette, kernel, dl-linux-imx, linux-pm,
	linux-arm-kernel

On 25.09.2019 05:38, Georgi Djakov wrote:
> Hi Leonard,
> 
> On 9/16/19 05:34, Leonard Crestez wrote:
>> On 23.08.2019 17:37, Leonard Crestez wrote:
>>> This series add imx support for interconnect via devfreq: the ICC
>>> framework is used to aggregate requests from devices and then those are
>>> converted to DEV_PM_QOS_MIN_FREQUENCY requests for devfreq.
>>>   
>>> Since there is no single devicetree node that can represent the "interconnect"
>>> new API is added to allow individual devfreq nodes to act as parsing proxies
>>> all mapping to a single soc-level icc provider. This is still RFC
>>> because of this
>>
>> Any comments? I made a lot of changes relative to previous versions,
>> most of them solely to avoid adding a virtual node in DT bindings.
>>
>> The only current interconnect provider implementation is for qcom and it
>> uses a firmware node as the provider node (with #interconnect-cells).
>> However there is no obvious equivalent of that for imx and many other SOCs.
> 
> Not sure if it will help, but have you seen the qcs404 interconnect driver?
> There is also mt8183 interconnect provider driver on LKML.

Yes, but only yesterday. The qcs404 driver involves multiple DT devices 
so it seems closer to imx.

As far as I understand from reading qcs404 source:

* There is no struct device representing the entire graph.
* There are multiple NOCs and each registers itself as a separate 
interconnect provider.
* Each NOC registers multiple icc_nodes of various sorts:
   * Device masters and slaves
   * Some nodes representing NoC ports?
   * Multiple internal nodes
* There is single per-SOC master list of QNOCs in the qcs404 driver.
* The QNOCs can reference each other between multiple providers.
* Each NOC registers an icc_provider and a subset of the graph.
* The multiple NoC inside a chip are distinguished by compat strings. 
This seems strange, aren't they really different instantiations of the 
same IP with small config changes?

This design is still quite odd, what would make sense to me is to 
register the "interconnect graph" once and then provide multiple 
"interconnect scalers" which handle the aggregated requests for certain 
specific nodes.

>> On imx there are multiple pieces of scalable fabric which can be defined
>> in DT as devfreq devices and it sort of makes sense to add
>> #interconnect-cells to those. However when it comes to describing the
>> SOC interconnect graph it's much more convenient to have a single
>> per-SOC platform driver.
> 
> Is all the NoC configuration done only by ATF? Are there any NoC related memory
> mapped registers?

Registers are memory-mapped and visible to the A-cores but should only 
be accessed through secure transactions. This means that configuration 
needs be done by ATF in EL3 (we don't support running linux in secure 
world on imx8m). There is no "remote processor" managing this on imx8m.

On older imx6/7 chips we actually have two out-of-tree implementations 
of bus freq switching code: An older one in Linux (used when running in 
secure world) and a different one in optee for running Linux in 
non-secure world.

NoC registers can be used to control some "transaction priority" bits 
but I don't want to expose that part right now.

What determines bandwidth versus power consumption is the NoC clk rate 
and clocks are managed by Linux directly.

DVFS on the RAM controller (DDRC) is also important. That component is 
only a bus slave and frequency switching requires a complex sequence 
inside ATF.

--
Regards,
Leonard

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

* Re: [RFCv4 0/7] interconnect: Add imx support via devfreq
  2019-09-25 22:52     ` Leonard Crestez
@ 2019-09-26  0:51       ` Georgi Djakov
  2019-09-30 12:31         ` Leonard Crestez
  0 siblings, 1 reply; 19+ messages in thread
From: Georgi Djakov @ 2019-09-26  0:51 UTC (permalink / raw)
  To: Leonard Crestez, Rob Herring, Artur Świgoń, Chanwoo Choi
  Cc: Mark Rutland, devicetree, Alexandre Bailon, Krzysztof Kozlowski,
	MyungJoo Ham, Kyungmin Park, Saravana Kannan, Viresh Kumar,
	Shawn Guo, Aisheng Dong, Fabio Estevam, Stephen Boyd,
	Michael Turquette, kernel, dl-linux-imx, linux-pm,
	linux-arm-kernel

On 9/25/19 15:52, Leonard Crestez wrote:
> On 25.09.2019 05:38, Georgi Djakov wrote:
>> Hi Leonard,
>>
>> On 9/16/19 05:34, Leonard Crestez wrote:
>>> On 23.08.2019 17:37, Leonard Crestez wrote:
>>>> This series add imx support for interconnect via devfreq: the ICC
>>>> framework is used to aggregate requests from devices and then those are
>>>> converted to DEV_PM_QOS_MIN_FREQUENCY requests for devfreq.
>>>>   
>>>> Since there is no single devicetree node that can represent the "interconnect"
>>>> new API is added to allow individual devfreq nodes to act as parsing proxies
>>>> all mapping to a single soc-level icc provider. This is still RFC
>>>> because of this
>>>
>>> Any comments? I made a lot of changes relative to previous versions,
>>> most of them solely to avoid adding a virtual node in DT bindings.
>>>
>>> The only current interconnect provider implementation is for qcom and it
>>> uses a firmware node as the provider node (with #interconnect-cells).
>>> However there is no obvious equivalent of that for imx and many other SOCs.
>>
>> Not sure if it will help, but have you seen the qcs404 interconnect driver?
>> There is also mt8183 interconnect provider driver on LKML.
> 
> Yes, but only yesterday. The qcs404 driver involves multiple DT devices 
> so it seems closer to imx.
> 
> As far as I understand from reading qcs404 source:
> 
> * There is no struct device representing the entire graph.
> * There are multiple NOCs and each registers itself as a separate 
> interconnect provider.
> * Each NOC registers multiple icc_nodes of various sorts:
>    * Device masters and slaves
>    * Some nodes representing NoC ports?

Well, all nodes are representing ports.

>    * Multiple internal nodes
> * There is single per-SOC master list of QNOCs in the qcs404 driver.
> * The QNOCs can reference each other between multiple providers.
> * Each NOC registers an icc_provider and a subset of the graph.
> * The multiple NoC inside a chip are distinguished by compat strings. 
> This seems strange, aren't they really different instantiations of the 
> same IP with small config changes?

No, they are different IPs - ahb, axi or custom based.

> This design is still quite odd, what would make sense to me is to 
> register the "interconnect graph" once and then provide multiple 
> "interconnect scalers" which handle the aggregated requests for certain 
> specific nodes.
> 
>>> On imx there are multiple pieces of scalable fabric which can be defined
>>> in DT as devfreq devices and it sort of makes sense to add
>>> #interconnect-cells to those. However when it comes to describing the
>>> SOC interconnect graph it's much more convenient to have a single
>>> per-SOC platform driver.
>>
>> Is all the NoC configuration done only by ATF? Are there any NoC related memory
>> mapped registers?
> 
> Registers are memory-mapped and visible to the A-cores but should only 
> be accessed through secure transactions. This means that configuration 
> needs be done by ATF in EL3 (we don't support running linux in secure 
> world on imx8m). There is no "remote processor" managing this on imx8m.

Can we create some noc DT node with it's memory mapped address and make
it an interconnect provider? Sounds to me like a more correct representation
of the hardware?
Other option would be to bless some PSCI DT node (for example) to be a
provider.

> 
> On older imx6/7 chips we actually have two out-of-tree implementations 
> of bus freq switching code: An older one in Linux (used when running in 
> secure world) and a different one in optee for running Linux in 
> non-secure world.
> 
> NoC registers can be used to control some "transaction priority" bits 
> but I don't want to expose that part right now.

This is very similar to some of the Qcom hardware.

> What determines bandwidth versus power consumption is the NoC clk rate 
> and clocks are managed by Linux directly.

So you will need to describe these clocks in the interconnect provider
DT node like on qcs404.

> DVFS on the RAM controller (DDRC) is also important. That component is 
> only a bus slave and frequency switching requires a complex sequence 
> inside ATF.

Makes sense.

Thanks,
Georgi

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

* Re: [RFCv4 0/7] interconnect: Add imx support via devfreq
  2019-09-26  0:51       ` Georgi Djakov
@ 2019-09-30 12:31         ` Leonard Crestez
  0 siblings, 0 replies; 19+ messages in thread
From: Leonard Crestez @ 2019-09-30 12:31 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Artur Świgoń, Chanwoo Choi
  Cc: Mark Rutland, devicetree, Alexandre Bailon, Krzysztof Kozlowski,
	MyungJoo Ham, Kyungmin Park, Saravana Kannan, Viresh Kumar,
	Shawn Guo, Aisheng Dong, Fabio Estevam, Stephen Boyd,
	Michael Turquette, kernel, dl-linux-imx, linux-pm,
	linux-arm-kernel

On 2019-09-26 3:52 AM, Georgi Djakov wrote:
> On 9/25/19 15:52, Leonard Crestez wrote:
>> On 25.09.2019 05:38, Georgi Djakov wrote:
>>> Hi Leonard,
>>>
>>> On 9/16/19 05:34, Leonard Crestez wrote:
>>>> On 23.08.2019 17:37, Leonard Crestez wrote:
>>>>> This series add imx support for interconnect via devfreq: the ICC
>>>>> framework is used to aggregate requests from devices and then those are
>>>>> converted to DEV_PM_QOS_MIN_FREQUENCY requests for devfreq.
>>>>>    
>>>>> Since there is no single devicetree node that can represent the "interconnect"
>>>>> new API is added to allow individual devfreq nodes to act as parsing proxies
>>>>> all mapping to a single soc-level icc provider. This is still RFC
>>>>> because of this
>>>>
>>>> Any comments? I made a lot of changes relative to previous versions,
>>>> most of them solely to avoid adding a virtual node in DT bindings.
>>>>
>>>> The only current interconnect provider implementation is for qcom and it
>>>> uses a firmware node as the provider node (with #interconnect-cells).
>>>> However there is no obvious equivalent of that for imx and many other SOCs.
>>>
>>> Not sure if it will help, but have you seen the qcs404 interconnect driver?
>>> There is also mt8183 interconnect provider driver on LKML.
>>
>> Yes, but only yesterday. The qcs404 driver involves multiple DT devices
>> so it seems closer to imx.
>>
>> As far as I understand from reading qcs404 source:
>>
>> * There is no struct device representing the entire graph.
>> * There are multiple NOCs and each registers itself as a separate
>> interconnect provider.
>> * Each NOC registers multiple icc_nodes of various sorts:
>>     * Device masters and slaves
>>     * Some nodes representing NoC ports?
> 
> Well, all nodes are representing ports.
> 
>>     * Multiple internal nodes
>> * There is single per-SOC master list of QNOCs in the qcs404 driver.
>> * The QNOCs can reference each other between multiple providers.
>> * Each NOC registers an icc_provider and a subset of the graph.
>> * The multiple NoC inside a chip are distinguished by compat strings.
>> This seems strange, aren't they really different instantiations of the
>> same IP with small config changes?
> 
> No, they are different IPs - ahb, axi or custom based.

On IMX some of the buses are just different instantiations.

Would it make sense to standardize an "interconnect-node-id" to identify 
middle nodes? For example if you have nearly identical "audio" "display" 
"vpu" NICs then this property would make it possible to map from a DT 
done to an ICC graph node.

>> This design is still quite odd, what would make sense to me is to
>> register the "interconnect graph" once and then provide multiple
>> "interconnect scalers" which handle the aggregated requests for certain
>> specific nodes.
>>
>>>> On imx there are multiple pieces of scalable fabric which can be defined
>>>> in DT as devfreq devices and it sort of makes sense to add
>>>> #interconnect-cells to those. However when it comes to describing the
>>>> SOC interconnect graph it's much more convenient to have a single
>>>> per-SOC platform driver.
>>>
>>> Is all the NoC configuration done only by ATF? Are there any NoC related memory
>>> mapped registers?
>>
>> Registers are memory-mapped and visible to the A-cores but should only
>> be accessed through secure transactions. This means that configuration
>> needs be done by ATF in EL3 (we don't support running linux in secure
>> world on imx8m). There is no "remote processor" managing this on imx8m.
> 
> Can we create some noc DT node with it's memory mapped address and make
> it an interconnect provider? Sounds to me like a more correct representation
> of the hardware?

This is what I did, it's just that the initial binding is in this series:
https://patchwork.kernel.org/cover/11104113/
https://patchwork.kernel.org/patch/11104137/
https://patchwork.kernel.org/patch/11104141/

The nodes are scaled via devfreq and interconnect comes "on top" to make 
device bandwidth requests.

I think using devfreq is valuable for example:
  * DDRC can support reactive scaling based on performance counters
  * The NOC can run at different voltages so it should have it's own OPP 
table.

> Other option would be to bless some PSCI DT node (for example) to be a
> provider.

I don't think this can be a good fit, I want to support different 
interconnect nodes with different underlying interfaces on the same SOC.

There is no abstraction layer in firmware so abstractions for different 
interconnect midnodes should be in linux instead.

>> On older imx6/7 chips we actually have two out-of-tree implementations
>> of bus freq switching code: An older one in Linux (used when running in
>> secure world) and a different one in optee for running Linux in
>> non-secure world.
>>
>> NoC registers can be used to control some "transaction priority" bits
>> but I don't want to expose that part right now.
> 
> This is very similar to some of the Qcom hardware.

NoC IP is licensed from Arteris which was bought-out by Qcom. 
Documentation is not public though and there are likely many differences 
versus what Qcom has in their own chips.
>> What determines bandwidth versus power consumption is the NoC clk rate
>> and clocks are managed by Linux directly.
> 
> So you will need to describe these clocks in the interconnect provider
> DT node like on qcs404.

I already implemented the nodes as devfreq provider and DDRC even 
includes ondemand reactive scaling support:

https://patchwork.kernel.org/patch/11104139/
https://patchwork.kernel.org/patch/11104145/
https://patchwork.kernel.org/patch/11104143/

I could just pick the "main" NOC and turn than into the "only" 
interconnect provider. Something like this:

if (has_property(noc_device, "#interconnect-cells")) {
     register_soc_icc_driver(noc_device);
}

This would get rid of the icc_proxy stuff but fetching references to 
other scalable nodes would require some other way to identify them.

--
Regards,
Leonard

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

end of thread, other threads:[~2019-09-30 12:31 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-23 14:36 [RFCv4 0/7] interconnect: Add imx support via devfreq Leonard Crestez
2019-08-23 14:36 ` [RFCv4 1/7] PM / devfreq: Add devfreq_get_devfreq_by_node Leonard Crestez
2019-08-23 14:36 ` [RFCv4 2/7] interconnect: Add of_icc_add_proxy Leonard Crestez
2019-08-23 14:36 ` [RFCv4 3/7] dt-bindings: devfreq: imx: Describe interconnect properties Leonard Crestez
2019-09-17 20:19   ` Rob Herring
2019-09-23 17:42     ` Leonard Crestez
2019-09-23 21:03       ` Rob Herring
2019-09-24 14:39         ` Leonard Crestez
2019-08-23 14:36 ` [RFCv4 4/7] interconnect: Add imx core driver Leonard Crestez
2019-08-23 14:36 ` [RFCv4 5/7] interconnect: imx: Add platform driver for imx8mm Leonard Crestez
2019-08-23 14:36 ` [RFCv4 6/7] soc: imx8mm: Register interconnect platform device Leonard Crestez
2019-08-23 14:37 ` [RFCv4 7/7] arm64: dts: imx8mm: Add interconnect properties Leonard Crestez
2019-09-16 12:34 ` [RFCv4 0/7] interconnect: Add imx support via devfreq Leonard Crestez
2019-09-25  2:37   ` Georgi Djakov
2019-09-25 22:52     ` Leonard Crestez
2019-09-26  0:51       ` Georgi Djakov
2019-09-30 12:31         ` Leonard Crestez
2019-09-21  6:06 ` Martin Kepplinger
2019-09-23 21:22   ` Leonard Crestez

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