Linux-PM Archive on lore.kernel.org
 help / color / 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
                   ` (7 more replies)
  0 siblings, 8 replies; 10+ 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] 10+ 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
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 10+ 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	[flat|nested] 10+ 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
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 10+ 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	[flat|nested] 10+ 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
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 10+ 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	[flat|nested] 10+ 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
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 10+ 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	[flat|nested] 10+ 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
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 10+ 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	[flat|nested] 10+ 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
  2019-09-16 12:34 ` [RFCv4 0/7] interconnect: Add imx support via devfreq Leonard Crestez
  7 siblings, 0 replies; 10+ 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	[flat|nested] 10+ 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
  7 siblings, 0 replies; 10+ 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	[flat|nested] 10+ 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
  7 siblings, 0 replies; 10+ 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] 10+ 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
  0 siblings, 0 replies; 10+ 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] 10+ messages in thread

end of thread, back to index

Thread overview: 10+ 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-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

Linux-PM Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-pm/0 linux-pm/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-pm linux-pm/ https://lore.kernel.org/linux-pm \
		linux-pm@vger.kernel.org linux-pm@archiver.kernel.org
	public-inbox-index linux-pm


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-pm


AGPL code for this site: git clone https://public-inbox.org/ public-inbox