linux-pm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC v5 00/10] interconnect: Add imx support via devfreq
@ 2019-10-31 22:51 Leonard Crestez
  2019-10-31 22:52 ` [PATCH RFC v5 01/10] dt-bindings: devfreq: Add bindings for generic imx buses Leonard Crestez
                   ` (9 more replies)
  0 siblings, 10 replies; 15+ messages in thread
From: Leonard Crestez @ 2019-10-31 22:51 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Chanwoo Choi
  Cc: Artur Świgoń,
	Alexandre Bailon, Rafael J. Wysocki, Jacky Bai, Anson Huang,
	Abel Vesa, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Saravana Kannan, Mark Rutland, Viresh Kumar, Shawn Guo,
	Dong Aisheng, Fabio Estevam, Stephen Boyd, Michael Turquette,
	Matthias Kaehlcke, Angus Ainslie, Martin Kepplinger, linux-pm,
	kernel, linux-imx, devicetree, linux-arm-kernel

This series adds upstream DRAM and interconnect scaling support for imx8m
series chips. It uses a per-SOC interconnect provider layered on top of
multiple instances of devfreq for scalable nodes along the interconnect.

Existing qcom interconnect providers mostly translate bandwidth requests into
firmware calls but equivalent firmware on imx8m is much thinner. Scaling
support for individual nodes (NIC/NOC and DDRC) is implemented through
devfreq.

The imx interconnect provider doesn't communicate with devfreq instance
directly but rather computes "minimum frequencies" for nodes along the path
and creates dev_pm_qos requests.

This needs core changes for dev_pm_qos frequency support for devfreq:

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

Since imx interconnect only needs to interact with imx devfreq it would also be
possible to tie them together directly, but it would be a little sad.

Since there is no single devicetree node that can represent the
"interconnect" the main NOC is picked as the "interconnect provider" and
will probe the interconnect platform device if #interconnect-cells is
present. This is a bit odd.

On i.MX there are multiple instances of a few interconnect IPs, this
patch identifies them by enumerating the entire devicetree scanning for
the "interconnect-node-id" property. As far as I see current providers
do this based entirely on compatible string of the interconnect instance
and this seems very odd to me. Do you think we could move this
"interconnect-node-id" approach to core interconnect bindings?

The same interconnect-node-id property is used to identify the DDRC and
this is arguably a hack.

Also as a github branch (with few other changes):
    https://github.com/cdleonard/linux/tree/next_imx_busfreq

This is layered upon imx-ddrc scaling support:
* https://patchwork.kernel.org/project/linux-arm-kernel/list/?series=196459
The DDRC only really interacts by receiving dev_pm_qos requests.

Changes since RFCv4:
* Drop icc proxy nonsense
* Make devfreq driver for NOC probe the ICC driver if
#interconnect-cells is present.
* Move NOC support to interconnect series and rename the node in DT
* Add support for all chips at once, differences are not intereseting
and there is more community interest for 8mq than 8mm.
Link: https://patchwork.kernel.org/cover/11111865/

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 (10):
  dt-bindings: devfreq: Add bindings for generic imx buses
  PM / devfreq: Add generic imx bus driver
  PM / devfreq: imx: Register interconnect device
  PM / devfreq: Add devfreq_get_devfreq_by_node
  interconnect: Add imx core driver
  interconnect: imx: Add platform driver for imx8mm
  interconnect: imx: Add platform driver for imx8mq
  interconnect: imx: Add platform driver for imx8mn
  arm64: dts: imx8m: Add NOC nodes
  arm64: dts: imx8m: Add interconnect provider properties

 .../devicetree/bindings/devfreq/imx.yaml      |  83 ++++++
 arch/arm64/boot/dts/freescale/imx8mm.dtsi     |  26 ++
 arch/arm64/boot/dts/freescale/imx8mn.dtsi     |  26 ++
 arch/arm64/boot/dts/freescale/imx8mq.dtsi     |  26 ++
 drivers/devfreq/Kconfig                       |  12 +
 drivers/devfreq/Makefile                      |   1 +
 drivers/devfreq/devfreq.c                     |  42 ++-
 drivers/devfreq/imx-devfreq.c                 | 185 ++++++++++++
 drivers/interconnect/Kconfig                  |   1 +
 drivers/interconnect/Makefile                 |   1 +
 drivers/interconnect/imx/Kconfig              |  17 ++
 drivers/interconnect/imx/Makefile             |   4 +
 drivers/interconnect/imx/imx.c                | 273 ++++++++++++++++++
 drivers/interconnect/imx/imx.h                |  60 ++++
 drivers/interconnect/imx/imx8mm.c             | 105 +++++++
 drivers/interconnect/imx/imx8mn.c             |  94 ++++++
 drivers/interconnect/imx/imx8mq.c             | 103 +++++++
 include/dt-bindings/interconnect/imx8mm.h     |  49 ++++
 include/dt-bindings/interconnect/imx8mn.h     |  41 +++
 include/dt-bindings/interconnect/imx8mq.h     |  48 +++
 include/linux/devfreq.h                       |   1 +
 21 files changed, 1187 insertions(+), 11 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/devfreq/imx.yaml
 create mode 100644 drivers/devfreq/imx-devfreq.c
 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 drivers/interconnect/imx/imx8mn.c
 create mode 100644 drivers/interconnect/imx/imx8mq.c
 create mode 100644 include/dt-bindings/interconnect/imx8mm.h
 create mode 100644 include/dt-bindings/interconnect/imx8mn.h
 create mode 100644 include/dt-bindings/interconnect/imx8mq.h

-- 
2.17.1


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

* [PATCH RFC v5 01/10] dt-bindings: devfreq: Add bindings for generic imx buses
  2019-10-31 22:51 [PATCH RFC v5 00/10] interconnect: Add imx support via devfreq Leonard Crestez
@ 2019-10-31 22:52 ` Leonard Crestez
  2019-11-04 22:49   ` Rob Herring
  2019-10-31 22:52 ` [PATCH RFC v5 02/10] PM / devfreq: Add generic imx bus driver Leonard Crestez
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 15+ messages in thread
From: Leonard Crestez @ 2019-10-31 22:52 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Chanwoo Choi
  Cc: Artur Świgoń,
	Alexandre Bailon, Rafael J. Wysocki, Jacky Bai, Anson Huang,
	Abel Vesa, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Saravana Kannan, Mark Rutland, Viresh Kumar, Shawn Guo,
	Dong Aisheng, Fabio Estevam, Stephen Boyd, Michael Turquette,
	Matthias Kaehlcke, Angus Ainslie, Martin Kepplinger, linux-pm,
	kernel, linux-imx, devicetree, linux-arm-kernel

Add initial dt bindings for the interconnects inside i.MX chips.
Multiple external IPs are involved but SOC integration means the
software controllable interfaces are very similar.

Single node also acts as interconnect provider if #interconnect-cells is
present.

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
Acked-by: MyungJoo Ham <myungjoo.ham@samsung.com>
---
 .../devicetree/bindings/devfreq/imx.yaml      | 83 +++++++++++++++++++
 1 file changed, 83 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/devfreq/imx.yaml

diff --git a/Documentation/devicetree/bindings/devfreq/imx.yaml b/Documentation/devicetree/bindings/devfreq/imx.yaml
new file mode 100644
index 000000000000..bfc825407764
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/imx.yaml
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/devfreq/imx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Generic i.MX bus frequency device
+
+maintainers:
+  - Leonard Crestez <leonard.crestez@nxp.com>
+
+description: |
+  The i.MX SoC family has multiple buses for which clock frequency (and
+  sometimes voltage) can be adjusted.
+
+  Some of those buses expose register areas mentioned in the memory maps as GPV
+  ("Global Programmers View") but not all. Access to this area might be denied
+  for normal (non-secure) world.
+
+  The buses are based on externally licensed IPs such as ARM NIC-301 and
+  Arteris FlexNOC but DT bindings are specific to the integration of these bus
+  interconnect IPs into imx SOCs.
+
+properties:
+  compatible:
+    oneOf:
+      - items:
+        - enum:
+          - fsl,imx8mn-nic
+          - fsl,imx8mm-nic
+          - fsl,imx8mq-nic
+        - const: fsl,imx8m-nic
+      - items:
+        - enum:
+          - fsl,imx8mn-noc
+          - fsl,imx8mm-noc
+          - fsl,imx8mq-noc
+        - const: fsl,imx8m-noc
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  operating-points-v2: true
+
+  devfreq:
+    description: |
+      Phandle to another devfreq device to match OPPs with by using the
+      passive governor.
+    $ref: "/schemas/types.yaml#/definitions/phandle"
+
+  '#interconnect-cells':
+    description: |
+      If specified then also act as an interconnect provider. Should only be
+      set once per soc on main noc.
+    const: 1
+
+  interconnect-node-id:
+    description: |
+      i.MX chips have multiple scalable buses based on the same IP, this is
+      used to distinguish between. Uses same identifier namespace as consumer
+      "interconnects" property, for example one of the values in
+      "include/dt-bindings/interconnect/imx8mm.h"
+
+    const: 1
+
+required:
+  - compatible
+  - clocks
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/imx8mm-clock.h>
+    noc: noc@32700000 {
+            compatible = "fsl,imx8mm-noc", "fsl,imx8m-noc";
+            reg = <0x32700000 0x100000>;
+            clocks = <&clk IMX8MM_CLK_NOC>;
+            operating-points-v2 = <&noc_opp_table>;
+    };
-- 
2.17.1


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

* [PATCH RFC v5 02/10] PM / devfreq: Add generic imx bus driver
  2019-10-31 22:51 [PATCH RFC v5 00/10] interconnect: Add imx support via devfreq Leonard Crestez
  2019-10-31 22:52 ` [PATCH RFC v5 01/10] dt-bindings: devfreq: Add bindings for generic imx buses Leonard Crestez
@ 2019-10-31 22:52 ` Leonard Crestez
  2019-10-31 22:52 ` [PATCH RFC v5 03/10] PM / devfreq: imx: Register interconnect device Leonard Crestez
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Leonard Crestez @ 2019-10-31 22:52 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Chanwoo Choi
  Cc: Artur Świgoń,
	Alexandre Bailon, Rafael J. Wysocki, Jacky Bai, Anson Huang,
	Abel Vesa, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Saravana Kannan, Mark Rutland, Viresh Kumar, Shawn Guo,
	Dong Aisheng, Fabio Estevam, Stephen Boyd, Michael Turquette,
	Matthias Kaehlcke, Angus Ainslie, Martin Kepplinger, linux-pm,
	kernel, linux-imx, devicetree, linux-arm-kernel

Add initial support for dynamic frequency switching on pieces of the imx
interconnect fabric.

All this driver does is set a clk rate based on an opp table, it does
not even map registers.

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
 drivers/devfreq/Kconfig       |  12 +++
 drivers/devfreq/Makefile      |   1 +
 drivers/devfreq/imx-devfreq.c | 148 ++++++++++++++++++++++++++++++++++
 3 files changed, 161 insertions(+)
 create mode 100644 drivers/devfreq/imx-devfreq.c

diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index defe1d438710..9088a151bafe 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -90,10 +90,22 @@ config ARM_EXYNOS_BUS_DEVFREQ
 	  Each memory bus group could contain many memoby bus block. It reads
 	  PPMU counters of memory controllers by using DEVFREQ-event device
 	  and adjusts the operating frequencies and voltages with OPP support.
 	  This does not yet operate with optimal voltages.
 
+config ARM_IMX_DEVFREQ
+	tristate "i.MX DEVFREQ Driver"
+	depends on ARCH_MXC || COMPILE_TEST
+	select DEVFREQ_GOV_PASSIVE
+	select DEVFREQ_GOV_SIMPLE_ONDEMAND
+	select DEVFREQ_GOV_USERSPACE
+	select PM_OPP
+	help
+	  This adds the DEVFREQ driver for the i.MX family of SoCs.
+	  It allows adjusting frequencies for DDRC (DDR Controller) and various
+	  NICs and NOCs which form the SOC interconnect fabric
+
 config ARM_TEGRA_DEVFREQ
 	tristate "NVIDIA Tegra30/114/124/210 DEVFREQ Driver"
 	depends on ARCH_TEGRA_3x_SOC || ARCH_TEGRA_114_SOC || \
 		ARCH_TEGRA_132_SOC || ARCH_TEGRA_124_SOC || \
 		ARCH_TEGRA_210_SOC || \
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
index 1ac92614b6aa..1c1f35f74d24 100644
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -8,10 +8,11 @@ obj-$(CONFIG_DEVFREQ_GOV_USERSPACE)	+= governor_userspace.o
 obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)	+= governor_passive.o
 
 # DEVFREQ Drivers
 obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)	+= exynos-bus.o
 obj-$(CONFIG_ARM_IMX_DEVFREQ)		+= imx-ddrc.o
+obj-$(CONFIG_ARM_IMX_DEVFREQ)		+= imx-devfreq.o
 obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)	+= rk3399_dmc.o
 obj-$(CONFIG_ARM_TEGRA_DEVFREQ)		+= tegra30-devfreq.o
 obj-$(CONFIG_ARM_TEGRA20_DEVFREQ)	+= tegra20-devfreq.o
 
 # DEVFREQ Event Drivers
diff --git a/drivers/devfreq/imx-devfreq.c b/drivers/devfreq/imx-devfreq.c
new file mode 100644
index 000000000000..5c907b3ab9c0
--- /dev/null
+++ b/drivers/devfreq/imx-devfreq.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <linux/clk.h>
+#include <linux/devfreq.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pm_opp.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+struct imx_devfreq {
+	struct devfreq_dev_profile profile;
+	struct devfreq *devfreq;
+	struct clk *clk;
+	struct devfreq_passive_data passive_data;
+};
+
+static int imx_devfreq_target(struct device *dev, unsigned long *freq, u32 flags)
+{
+	struct imx_devfreq *priv = dev_get_drvdata(dev);
+	struct dev_pm_opp *new_opp;
+	unsigned long new_freq;
+	int ret;
+
+	new_opp = devfreq_recommended_opp(dev, freq, flags);
+	if (IS_ERR(new_opp)) {
+		ret = PTR_ERR(new_opp);
+		dev_err(dev, "failed to get recommended opp: %d\n", ret);
+		return ret;
+	}
+	new_freq = dev_pm_opp_get_freq(new_opp);
+	dev_pm_opp_put(new_opp);
+
+	return clk_set_rate(priv->clk, new_freq);
+}
+
+static int imx_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
+{
+	struct imx_devfreq *priv = dev_get_drvdata(dev);
+
+	*freq = clk_get_rate(priv->clk);
+
+	return 0;
+}
+
+static int imx_devfreq_get_dev_status(struct device *dev,
+		struct devfreq_dev_status *stat)
+{
+	struct imx_devfreq *priv = dev_get_drvdata(dev);
+
+	stat->busy_time = 0;
+	stat->total_time = 0;
+	stat->current_frequency = clk_get_rate(priv->clk);
+
+	return 0;
+}
+
+static void imx_devfreq_exit(struct device *dev)
+{
+	dev_pm_opp_of_remove_table(dev);
+}
+
+static int imx_devfreq_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct imx_devfreq *priv;
+	const char *gov = DEVFREQ_GOV_USERSPACE;
+	void *govdata = NULL;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		ret = PTR_ERR(priv->clk);
+		dev_err(dev, "failed to fetch clk: %d\n", ret);
+		return ret;
+	}
+	platform_set_drvdata(pdev, priv);
+
+	ret = dev_pm_opp_of_add_table(dev);
+	if (ret < 0) {
+		dev_err(dev, "failed to get OPP table\n");
+		return ret;
+	}
+
+	priv->profile.polling_ms = 1000;
+	priv->profile.target = imx_devfreq_target;
+	priv->profile.get_dev_status = imx_devfreq_get_dev_status;
+	priv->profile.exit = imx_devfreq_exit;
+	priv->profile.get_cur_freq = imx_devfreq_get_cur_freq;
+	priv->profile.initial_freq = clk_get_rate(priv->clk);
+
+	/* Handle passive devfreq parent link */
+	priv->passive_data.parent = devfreq_get_devfreq_by_phandle(dev, 0);
+	if (!IS_ERR(priv->passive_data.parent)) {
+		dev_info(dev, "passive link to %s\n",
+				dev_name(priv->passive_data.parent->dev.parent));
+		gov = DEVFREQ_GOV_PASSIVE;
+		govdata = &priv->passive_data;
+	} else if (priv->passive_data.parent != ERR_PTR(-ENODEV)) {
+		// -ENODEV means no parent: not an error.
+		ret = PTR_ERR(priv->passive_data.parent);
+		if (ret != -EPROBE_DEFER)
+			dev_warn(dev, "failed to get passive parent: %d\n", ret);
+		goto err;
+	}
+
+	priv->devfreq = devm_devfreq_add_device(dev, &priv->profile,
+						gov, govdata);
+	if (IS_ERR(priv->devfreq)) {
+		ret = PTR_ERR(priv->devfreq);
+		dev_err(dev, "failed to add devfreq device: %d\n", ret);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	dev_pm_opp_of_remove_table(dev);
+	return ret;
+}
+
+static const struct of_device_id imx_devfreq_of_match[] = {
+	{ .compatible = "fsl,imx8m-noc", },
+	{ .compatible = "fsl,imx8m-nic", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, imx_devfreq_of_match);
+
+static struct platform_driver imx_devfreq_platdrv = {
+	.probe		= imx_devfreq_probe,
+	.driver = {
+		.name	= "imx-devfreq",
+		.of_match_table = of_match_ptr(imx_devfreq_of_match),
+	},
+};
+module_platform_driver(imx_devfreq_platdrv);
+
+MODULE_DESCRIPTION("Generic i.MX bus frequency driver");
+MODULE_AUTHOR("Leonard Crestez <leonard.crestez@nxp.com>");
+MODULE_LICENSE("GPL v2");
-- 
2.17.1


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

* [PATCH RFC v5 03/10] PM / devfreq: imx: Register interconnect device
  2019-10-31 22:51 [PATCH RFC v5 00/10] interconnect: Add imx support via devfreq Leonard Crestez
  2019-10-31 22:52 ` [PATCH RFC v5 01/10] dt-bindings: devfreq: Add bindings for generic imx buses Leonard Crestez
  2019-10-31 22:52 ` [PATCH RFC v5 02/10] PM / devfreq: Add generic imx bus driver Leonard Crestez
@ 2019-10-31 22:52 ` Leonard Crestez
  2019-10-31 22:52 ` [PATCH RFC v5 04/10] PM / devfreq: Add devfreq_get_devfreq_by_node Leonard Crestez
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Leonard Crestez @ 2019-10-31 22:52 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Chanwoo Choi
  Cc: Artur Świgoń,
	Alexandre Bailon, Rafael J. Wysocki, Jacky Bai, Anson Huang,
	Abel Vesa, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Saravana Kannan, Mark Rutland, Viresh Kumar, Shawn Guo,
	Dong Aisheng, Fabio Estevam, Stephen Boyd, Michael Turquette,
	Matthias Kaehlcke, Angus Ainslie, Martin Kepplinger, linux-pm,
	kernel, linux-imx, devicetree, linux-arm-kernel

There is no single device which can represent the imx interconnect.
Instead of adding a virtual one just make the main &noc act as the
global interconnect provider.

The imx interconnect provider driver will scale the NOC and DDRC based
on bandwidth request. More scalable nodes can be added in the future,
for example for audio/display/vpu/gpu NICs.

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

diff --git a/drivers/devfreq/imx-devfreq.c b/drivers/devfreq/imx-devfreq.c
index 5c907b3ab9c0..241d4c00db1f 100644
--- a/drivers/devfreq/imx-devfreq.c
+++ b/drivers/devfreq/imx-devfreq.c
@@ -15,10 +15,11 @@
 struct imx_devfreq {
 	struct devfreq_dev_profile profile;
 	struct devfreq *devfreq;
 	struct clk *clk;
 	struct devfreq_passive_data passive_data;
+	struct platform_device *icc_pdev;
 };
 
 static int imx_devfreq_target(struct device *dev, unsigned long *freq, u32 flags)
 {
 	struct imx_devfreq *priv = dev_get_drvdata(dev);
@@ -59,11 +60,40 @@ static int imx_devfreq_get_dev_status(struct device *dev,
 	return 0;
 }
 
 static void imx_devfreq_exit(struct device *dev)
 {
+	struct imx_devfreq *priv = dev_get_drvdata(dev);
+
 	dev_pm_opp_of_remove_table(dev);
+	platform_device_unregister(priv->icc_pdev);
+}
+
+/* imx_devfreq_init_icc() - register matching icc provider if required */
+static int imx_devfreq_init_icc(struct device *dev)
+{
+	struct imx_devfreq *priv = dev_get_drvdata(dev);
+	const char *icc_driver_name;
+
+	if (!IS_ENABLED(CONFIG_INTERCONNECT_IMX))
+		return 0;
+	if (!of_get_property(dev->of_node, "#interconnect-cells", 0))
+		return 0;
+
+	icc_driver_name = of_device_get_match_data(dev);
+	if (!icc_driver_name)
+		return 0;
+
+	priv->icc_pdev = platform_device_register_data(
+			dev, icc_driver_name, 0, NULL, 0);
+	if (IS_ERR(priv->icc_pdev)) {
+		dev_err(dev, "failed to register icc provider %s: %ld\n",
+				icc_driver_name, PTR_ERR(priv->devfreq));
+		return PTR_ERR(priv->devfreq);
+	}
+
+	return 0;
 }
 
 static int imx_devfreq_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -118,18 +148,25 @@ static int imx_devfreq_probe(struct platform_device *pdev)
 		ret = PTR_ERR(priv->devfreq);
 		dev_err(dev, "failed to add devfreq device: %d\n", ret);
 		goto err;
 	}
 
+	ret = imx_devfreq_init_icc(dev);
+	if (ret)
+		goto err;
+
 	return 0;
 
 err:
 	dev_pm_opp_of_remove_table(dev);
 	return ret;
 }
 
 static const struct of_device_id imx_devfreq_of_match[] = {
+	{ .compatible = "fsl,imx8mq-noc", .data = "imx8mq-interconnect", },
+	{ .compatible = "fsl,imx8mm-noc", .data = "imx8mm-interconnect", },
+	{ .compatible = "fsl,imx8mn-noc", .data = "imx8mn-interconnect", },
 	{ .compatible = "fsl,imx8m-noc", },
 	{ .compatible = "fsl,imx8m-nic", },
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, imx_devfreq_of_match);
-- 
2.17.1


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

* [PATCH RFC v5 04/10] PM / devfreq: Add devfreq_get_devfreq_by_node
  2019-10-31 22:51 [PATCH RFC v5 00/10] interconnect: Add imx support via devfreq Leonard Crestez
                   ` (2 preceding siblings ...)
  2019-10-31 22:52 ` [PATCH RFC v5 03/10] PM / devfreq: imx: Register interconnect device Leonard Crestez
@ 2019-10-31 22:52 ` Leonard Crestez
  2019-10-31 22:52 ` [PATCH RFC v5 05/10] interconnect: Add imx core driver Leonard Crestez
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Leonard Crestez @ 2019-10-31 22:52 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Chanwoo Choi
  Cc: Artur Świgoń,
	Alexandre Bailon, Rafael J. Wysocki, Jacky Bai, Anson Huang,
	Abel Vesa, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Saravana Kannan, Mark Rutland, Viresh Kumar, Shawn Guo,
	Dong Aisheng, Fabio Estevam, Stephen Boyd, Michael Turquette,
	Matthias Kaehlcke, Angus Ainslie, Martin Kepplinger, linux-pm,
	kernel, linux-imx, 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 dab31b63eb10..bc83d0aab279 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -931,10 +931,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
  *
@@ -953,25 +976,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 fb376b5b7281..d4d1ec04aeea 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] 15+ messages in thread

* [PATCH RFC v5 05/10] interconnect: Add imx core driver
  2019-10-31 22:51 [PATCH RFC v5 00/10] interconnect: Add imx support via devfreq Leonard Crestez
                   ` (3 preceding siblings ...)
  2019-10-31 22:52 ` [PATCH RFC v5 04/10] PM / devfreq: Add devfreq_get_devfreq_by_node Leonard Crestez
@ 2019-10-31 22:52 ` Leonard Crestez
  2019-11-12 15:07   ` Georgi Djakov
  2019-10-31 22:52 ` [PATCH RFC v5 06/10] interconnect: imx: Add platform driver for imx8mm Leonard Crestez
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 15+ messages in thread
From: Leonard Crestez @ 2019-10-31 22:52 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Chanwoo Choi
  Cc: Artur Świgoń,
	Alexandre Bailon, Rafael J. Wysocki, Jacky Bai, Anson Huang,
	Abel Vesa, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Saravana Kannan, Mark Rutland, Viresh Kumar, Shawn Guo,
	Dong Aisheng, Fabio Estevam, Stephen Boyd, Michael Turquette,
	Matthias Kaehlcke, Angus Ainslie, Martin Kepplinger, linux-pm,
	kernel, linux-imx, 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    | 273 ++++++++++++++++++++++++++++++
 drivers/interconnect/imx/imx.h    |  60 +++++++
 6 files changed, 341 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 b6ea8f0a6122..f57e77b8731c 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..7d248e01dcf0
--- /dev/null
+++ b/drivers/interconnect/imx/imx.c
@@ -0,0 +1,273 @@
+// 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, "node %s device %s avg_bw %ukBps peak_bw %ukBps min_freq %llukHz\n",
+			node->name, dev_name(node_data->devfreq->dev.parent),
+			node->avg_bw, node->peak_bw, freq);
+
+	if (freq > S32_MAX) {
+		dev_err(dev, "%s can't request more than 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 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;
+
+	/* Find nodes based on interconnect-node-id property */
+	for_each_node_with_property(dn, "interconnect-node-id") {
+		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_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->parent;
+	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] 15+ messages in thread

* [PATCH RFC v5 06/10] interconnect: imx: Add platform driver for imx8mm
  2019-10-31 22:51 [PATCH RFC v5 00/10] interconnect: Add imx support via devfreq Leonard Crestez
                   ` (4 preceding siblings ...)
  2019-10-31 22:52 ` [PATCH RFC v5 05/10] interconnect: Add imx core driver Leonard Crestez
@ 2019-10-31 22:52 ` Leonard Crestez
  2019-10-31 22:52 ` [PATCH RFC v5 07/10] interconnect: imx: Add platform driver for imx8mq Leonard Crestez
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Leonard Crestez @ 2019-10-31 22:52 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Chanwoo Choi
  Cc: Artur Świgoń,
	Alexandre Bailon, Rafael J. Wysocki, Jacky Bai, Anson Huang,
	Abel Vesa, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Saravana Kannan, Mark Rutland, Viresh Kumar, Shawn Guo,
	Dong Aisheng, Fabio Estevam, Stephen Boyd, Michael Turquette,
	Matthias Kaehlcke, Angus Ainslie, Martin Kepplinger, linux-pm,
	kernel, linux-imx, 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] 15+ messages in thread

* [PATCH RFC v5 07/10] interconnect: imx: Add platform driver for imx8mq
  2019-10-31 22:51 [PATCH RFC v5 00/10] interconnect: Add imx support via devfreq Leonard Crestez
                   ` (5 preceding siblings ...)
  2019-10-31 22:52 ` [PATCH RFC v5 06/10] interconnect: imx: Add platform driver for imx8mm Leonard Crestez
@ 2019-10-31 22:52 ` Leonard Crestez
  2019-10-31 22:52 ` [PATCH RFC v5 08/10] interconnect: imx: Add platform driver for imx8mn Leonard Crestez
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 15+ messages in thread
From: Leonard Crestez @ 2019-10-31 22:52 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Chanwoo Choi
  Cc: Artur Świgoń,
	Alexandre Bailon, Rafael J. Wysocki, Jacky Bai, Anson Huang,
	Abel Vesa, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Saravana Kannan, Mark Rutland, Viresh Kumar, Shawn Guo,
	Dong Aisheng, Fabio Estevam, Stephen Boyd, Michael Turquette,
	Matthias Kaehlcke, Angus Ainslie, Martin Kepplinger, linux-pm,
	kernel, linux-imx, devicetree, linux-arm-kernel

Add a platform driver for the i.MX8MQ SoC describing bus topology,
based on internal documentation.

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
 drivers/interconnect/imx/Kconfig          |   4 +
 drivers/interconnect/imx/Makefile         |   1 +
 drivers/interconnect/imx/imx8mq.c         | 103 ++++++++++++++++++++++
 include/dt-bindings/interconnect/imx8mq.h |  48 ++++++++++
 4 files changed, 156 insertions(+)
 create mode 100644 drivers/interconnect/imx/imx8mq.c
 create mode 100644 include/dt-bindings/interconnect/imx8mq.h

diff --git a/drivers/interconnect/imx/Kconfig b/drivers/interconnect/imx/Kconfig
index 15671fe7f600..e0d36355eeb8 100644
--- a/drivers/interconnect/imx/Kconfig
+++ b/drivers/interconnect/imx/Kconfig
@@ -5,5 +5,9 @@ config INTERCONNECT_IMX
 	  Generic interconnect driver for i.MX SOCs
 
 config INTERCONNECT_IMX8MM
 	def_bool y
 	depends on INTERCONNECT_IMX
+
+config INTERCONNECT_IMX8MQ
+	def_bool y
+	depends on INTERCONNECT_IMX
diff --git a/drivers/interconnect/imx/Makefile b/drivers/interconnect/imx/Makefile
index 5f658c1608a6..8c5d6f9e47f5 100644
--- a/drivers/interconnect/imx/Makefile
+++ b/drivers/interconnect/imx/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_INTERCONNECT_IMX) += imx.o
 obj-$(CONFIG_INTERCONNECT_IMX8MM) += imx8mm.o
+obj-$(CONFIG_INTERCONNECT_IMX8MQ) += imx8mq.o
diff --git a/drivers/interconnect/imx/imx8mq.c b/drivers/interconnect/imx/imx8mq.c
new file mode 100644
index 000000000000..1dccb05b6336
--- /dev/null
+++ b/drivers/interconnect/imx/imx8mq.c
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Interconnect framework driver for i.MX SoC
+ *
+ * Copyright (c) 2019, NXP
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/interconnect/imx8mq.h>
+
+#include "imx.h"
+
+static const struct imx_icc_node_adj_desc imx8mq_dram_adj = {
+	.bw_mul = 1,
+	.bw_div = 4,
+};
+
+static const struct imx_icc_node_adj_desc imx8mq_noc_adj = {
+	.bw_mul = 1,
+	.bw_div = 4,
+};
+
+/*
+ * 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", IMX8MQ_ICN_NOC, &imx8mq_noc_adj,
+			IMX8MQ_ICS_DRAM, IMX8MQ_ICN_MAIN),
+
+	DEFINE_BUS_SLAVE("DRAM", IMX8MQ_ICS_DRAM, &imx8mq_dram_adj),
+	DEFINE_BUS_SLAVE("OCRAM", IMX8MQ_ICS_OCRAM, NULL),
+	DEFINE_BUS_MASTER("A53", IMX8MQ_ICM_A53, IMX8MQ_ICN_NOC),
+
+	/* VPUMIX */
+	DEFINE_BUS_MASTER("VPU", IMX8MQ_ICM_VPU, IMX8MQ_ICN_VIDEO),
+	DEFINE_BUS_INTERCONNECT("PL301_VIDEO", IMX8MQ_ICN_VIDEO, NULL, IMX8MQ_ICN_NOC),
+
+	/* GPUMIX */
+	DEFINE_BUS_MASTER("GPU", IMX8MQ_ICM_GPU, IMX8MQ_ICN_GPU),
+	DEFINE_BUS_INTERCONNECT("PL301_GPU", IMX8MQ_ICN_GPU, NULL, IMX8MQ_ICN_NOC),
+
+	/* DISPMIX (only for DCSS) */
+	DEFINE_BUS_MASTER("DC", IMX8MQ_ICM_DCSS, IMX8MQ_ICN_DCSS),
+	DEFINE_BUS_INTERCONNECT("PL301_DC", IMX8MQ_ICN_DCSS, NULL, IMX8MQ_ICN_NOC),
+
+	/* USBMIX */
+	DEFINE_BUS_MASTER("USB1", IMX8MQ_ICM_USB1, IMX8MQ_ICN_USB),
+	DEFINE_BUS_MASTER("USB2", IMX8MQ_ICM_USB2, IMX8MQ_ICN_USB),
+	DEFINE_BUS_INTERCONNECT("PL301_USB", IMX8MQ_ICN_USB, NULL, IMX8MQ_ICN_NOC),
+
+	/* PL301_DISPLAY (IPs other than DCSS, inside SUPERMIX) */
+	DEFINE_BUS_MASTER("CSI1", IMX8MQ_ICM_CSI1, IMX8MQ_ICN_DISPLAY),
+	DEFINE_BUS_MASTER("CSI2", IMX8MQ_ICM_CSI2, IMX8MQ_ICN_DISPLAY),
+	DEFINE_BUS_MASTER("LCDIF", IMX8MQ_ICM_LCDIF, IMX8MQ_ICN_DISPLAY),
+	DEFINE_BUS_INTERCONNECT("PL301_DISPLAY", IMX8MQ_ICN_DISPLAY, NULL, IMX8MQ_ICN_MAIN),
+
+	/* AUDIO */
+	DEFINE_BUS_MASTER("SDMA2", IMX8MQ_ICM_SDMA2, IMX8MQ_ICN_AUDIO),
+	DEFINE_BUS_INTERCONNECT("PL301_AUDIO", IMX8MQ_ICN_AUDIO, NULL, IMX8MQ_ICN_DISPLAY),
+
+	/* ENET */
+	DEFINE_BUS_MASTER("ENET", IMX8MQ_ICM_ENET, IMX8MQ_ICN_ENET),
+	DEFINE_BUS_INTERCONNECT("PL301_ENET", IMX8MQ_ICN_ENET, NULL, IMX8MQ_ICN_MAIN),
+
+	/* OTHER */
+	DEFINE_BUS_MASTER("SDMA1", IMX8MQ_ICM_SDMA1, IMX8MQ_ICN_MAIN),
+	DEFINE_BUS_MASTER("NAND", IMX8MQ_ICM_NAND, IMX8MQ_ICN_MAIN),
+	DEFINE_BUS_MASTER("USDHC1", IMX8MQ_ICM_USDHC1, IMX8MQ_ICN_MAIN),
+	DEFINE_BUS_MASTER("USDHC2", IMX8MQ_ICM_USDHC2, IMX8MQ_ICN_MAIN),
+	DEFINE_BUS_MASTER("PCIE1", IMX8MQ_ICM_PCIE1, IMX8MQ_ICN_MAIN),
+	DEFINE_BUS_MASTER("PCIE2", IMX8MQ_ICM_PCIE2, IMX8MQ_ICN_MAIN),
+	DEFINE_BUS_INTERCONNECT("PL301_MAIN", IMX8MQ_ICN_MAIN, NULL,
+			IMX8MQ_ICN_NOC, IMX8MQ_ICS_OCRAM),
+};
+
+static int imx8mq_icc_probe(struct platform_device *pdev)
+{
+	return imx_icc_register(pdev, nodes, ARRAY_SIZE(nodes));
+}
+
+static int imx8mq_icc_remove(struct platform_device *pdev)
+{
+	return imx_icc_unregister(pdev);
+}
+
+static struct platform_driver imx8mq_icc_driver = {
+	.probe = imx8mq_icc_probe,
+	.remove = imx8mq_icc_remove,
+	.driver = {
+		.name = "imx8mq-interconnect",
+	},
+};
+
+module_platform_driver(imx8mq_icc_driver);
+MODULE_AUTHOR("Leonard Crestez <leonard.crestez@nxp.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/dt-bindings/interconnect/imx8mq.h b/include/dt-bindings/interconnect/imx8mq.h
new file mode 100644
index 000000000000..94701b19f35a
--- /dev/null
+++ b/include/dt-bindings/interconnect/imx8mq.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Interconnect framework driver for i.MX SoC
+ *
+ * Copyright (c) 2019, NXP
+ */
+
+#ifndef __IMX8MQ_ICM_INTERCONNECT_IDS_H
+#define __IMX8MQ_ICM_INTERCONNECT_IDS_H
+
+#define IMX8MQ_ICN_NOC		1
+#define IMX8MQ_ICS_DRAM		2
+#define IMX8MQ_ICS_OCRAM	3
+#define IMX8MQ_ICM_A53		4
+
+#define IMX8MQ_ICM_VPU		5
+#define IMX8MQ_ICN_VIDEO	6
+
+#define IMX8MQ_ICM_GPU		7
+#define IMX8MQ_ICN_GPU		8
+
+#define IMX8MQ_ICM_DCSS		9
+#define IMX8MQ_ICN_DCSS		10
+
+#define IMX8MQ_ICM_USB1		11
+#define IMX8MQ_ICM_USB2		12
+#define IMX8MQ_ICN_USB		13
+
+#define IMX8MQ_ICM_CSI1		14
+#define IMX8MQ_ICM_CSI2		15
+#define IMX8MQ_ICM_LCDIF	16
+#define IMX8MQ_ICN_DISPLAY	17
+
+#define IMX8MQ_ICM_SDMA2	18
+#define IMX8MQ_ICN_AUDIO	19
+
+#define IMX8MQ_ICN_ENET		20
+#define IMX8MQ_ICM_ENET		21
+
+#define IMX8MQ_ICM_SDMA1	22
+#define IMX8MQ_ICM_NAND		23
+#define IMX8MQ_ICM_USDHC1	24
+#define IMX8MQ_ICM_USDHC2	25
+#define IMX8MQ_ICM_PCIE1	26
+#define IMX8MQ_ICM_PCIE2	27
+#define IMX8MQ_ICN_MAIN		28
+
+#endif /* __IMX8MQ_ICM_INTERCONNECT_IDS_H */
-- 
2.17.1


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

* [PATCH RFC v5 08/10] interconnect: imx: Add platform driver for imx8mn
  2019-10-31 22:51 [PATCH RFC v5 00/10] interconnect: Add imx support via devfreq Leonard Crestez
                   ` (6 preceding siblings ...)
  2019-10-31 22:52 ` [PATCH RFC v5 07/10] interconnect: imx: Add platform driver for imx8mq Leonard Crestez
@ 2019-10-31 22:52 ` Leonard Crestez
  2019-10-31 22:52 ` [PATCH RFC v5 09/10] arm64: dts: imx8m: Add NOC nodes Leonard Crestez
  2019-10-31 22:52 ` [PATCH RFC v5 10/10] arm64: dts: imx8m: Add interconnect provider properties Leonard Crestez
  9 siblings, 0 replies; 15+ messages in thread
From: Leonard Crestez @ 2019-10-31 22:52 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Chanwoo Choi
  Cc: Artur Świgoń,
	Alexandre Bailon, Rafael J. Wysocki, Jacky Bai, Anson Huang,
	Abel Vesa, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Saravana Kannan, Mark Rutland, Viresh Kumar, Shawn Guo,
	Dong Aisheng, Fabio Estevam, Stephen Boyd, Michael Turquette,
	Matthias Kaehlcke, Angus Ainslie, Martin Kepplinger, linux-pm,
	kernel, linux-imx, devicetree, linux-arm-kernel

Add a platform driver for the i.MX8MN SoC describing bus topology, based
on internal documentation.

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
 drivers/interconnect/imx/Kconfig          |  4 +
 drivers/interconnect/imx/Makefile         |  1 +
 drivers/interconnect/imx/imx8mn.c         | 94 +++++++++++++++++++++++
 include/dt-bindings/interconnect/imx8mn.h | 41 ++++++++++
 4 files changed, 140 insertions(+)
 create mode 100644 drivers/interconnect/imx/imx8mn.c
 create mode 100644 include/dt-bindings/interconnect/imx8mn.h

diff --git a/drivers/interconnect/imx/Kconfig b/drivers/interconnect/imx/Kconfig
index e0d36355eeb8..bc311e86d255 100644
--- a/drivers/interconnect/imx/Kconfig
+++ b/drivers/interconnect/imx/Kconfig
@@ -6,8 +6,12 @@ config INTERCONNECT_IMX
 
 config INTERCONNECT_IMX8MM
 	def_bool y
 	depends on INTERCONNECT_IMX
 
+config INTERCONNECT_IMX8MN
+	def_bool y
+	depends on INTERCONNECT_IMX
+
 config INTERCONNECT_IMX8MQ
 	def_bool y
 	depends on INTERCONNECT_IMX
diff --git a/drivers/interconnect/imx/Makefile b/drivers/interconnect/imx/Makefile
index 8c5d6f9e47f5..e39d6c6af3b7 100644
--- a/drivers/interconnect/imx/Makefile
+++ b/drivers/interconnect/imx/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_INTERCONNECT_IMX) += imx.o
 obj-$(CONFIG_INTERCONNECT_IMX8MM) += imx8mm.o
+obj-$(CONFIG_INTERCONNECT_IMX8MN) += imx8mn.o
 obj-$(CONFIG_INTERCONNECT_IMX8MQ) += imx8mq.o
diff --git a/drivers/interconnect/imx/imx8mn.c b/drivers/interconnect/imx/imx8mn.c
new file mode 100644
index 000000000000..3141ac42c8e6
--- /dev/null
+++ b/drivers/interconnect/imx/imx8mn.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Interconnect framework driver for i.MX SoC
+ *
+ * Copyright (c) 2019, NXP
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/interconnect/imx8mn.h>
+
+#include "imx.h"
+
+static const struct imx_icc_node_adj_desc imx8mn_dram_adj = {
+	.bw_mul = 1,
+	.bw_div = 4,
+};
+
+static const struct imx_icc_node_adj_desc imx8mn_noc_adj = {
+	.bw_mul = 1,
+	.bw_div = 4,
+};
+
+/*
+ * 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", IMX8MN_ICN_NOC, &imx8mn_noc_adj,
+			IMX8MN_ICS_DRAM, IMX8MN_ICN_MAIN),
+
+	DEFINE_BUS_SLAVE("DRAM", IMX8MN_ICS_DRAM, &imx8mn_dram_adj),
+	DEFINE_BUS_SLAVE("OCRAM", IMX8MN_ICS_OCRAM, NULL),
+	DEFINE_BUS_MASTER("A53", IMX8MN_ICM_A53, IMX8MN_ICN_NOC),
+
+	/* GPUMIX */
+	DEFINE_BUS_MASTER("GPU", IMX8MN_ICM_GPU, IMX8MN_ICN_GPU),
+	DEFINE_BUS_INTERCONNECT("PL301_GPU", IMX8MN_ICN_GPU, NULL, IMX8MN_ICN_NOC),
+
+	/* DISPLAYMIX */
+	DEFINE_BUS_MASTER("CSI1", IMX8MN_ICM_CSI1, IMX8MN_ICN_MIPI),
+	DEFINE_BUS_MASTER("CSI2", IMX8MN_ICM_CSI2, IMX8MN_ICN_MIPI),
+	DEFINE_BUS_MASTER("ISI", IMX8MN_ICM_ISI, IMX8MN_ICN_MIPI),
+	DEFINE_BUS_MASTER("LCDIF", IMX8MN_ICM_LCDIF, IMX8MN_ICN_MIPI),
+	DEFINE_BUS_INTERCONNECT("PL301_MIPI", IMX8MN_ICN_MIPI, NULL, IMX8MN_ICN_NOC),
+
+	/* USB goes straight to NOC */
+	DEFINE_BUS_MASTER("USB", IMX8MN_ICM_USB, IMX8MN_ICN_NOC),
+
+	/* Audio */
+	DEFINE_BUS_MASTER("SDMA2", IMX8MN_ICM_SDMA2, IMX8MN_ICN_AUDIO),
+	DEFINE_BUS_MASTER("SDMA3", IMX8MN_ICM_SDMA3, IMX8MN_ICN_AUDIO),
+	DEFINE_BUS_INTERCONNECT("PL301_AUDIO", IMX8MN_ICN_AUDIO, NULL, IMX8MN_ICN_MAIN),
+
+	/* Ethernet */
+	DEFINE_BUS_MASTER("ENET", IMX8MN_ICM_ENET, IMX8MN_ICN_ENET),
+	DEFINE_BUS_INTERCONNECT("PL301_ENET", IMX8MN_ICN_ENET, NULL, IMX8MN_ICN_MAIN),
+
+	/* Other */
+	DEFINE_BUS_MASTER("SDMA1", IMX8MN_ICM_SDMA1, IMX8MN_ICN_MAIN),
+	DEFINE_BUS_MASTER("NAND", IMX8MN_ICM_NAND, IMX8MN_ICN_MAIN),
+	DEFINE_BUS_MASTER("USDHC1", IMX8MN_ICM_USDHC1, IMX8MN_ICN_MAIN),
+	DEFINE_BUS_MASTER("USDHC2", IMX8MN_ICM_USDHC2, IMX8MN_ICN_MAIN),
+	DEFINE_BUS_MASTER("USDHC3", IMX8MN_ICM_USDHC3, IMX8MN_ICN_MAIN),
+	DEFINE_BUS_INTERCONNECT("PL301_MAIN", IMX8MN_ICN_MAIN, NULL,
+			IMX8MN_ICN_NOC, IMX8MN_ICS_OCRAM),
+};
+
+static int imx8mn_icc_probe(struct platform_device *pdev)
+{
+	return imx_icc_register(pdev, nodes, ARRAY_SIZE(nodes));
+}
+
+static int imx8mn_icc_remove(struct platform_device *pdev)
+{
+	return imx_icc_unregister(pdev);
+}
+
+static struct platform_driver imx8mn_icc_driver = {
+	.probe = imx8mn_icc_probe,
+	.remove = imx8mn_icc_remove,
+	.driver = {
+		.name = "imx8mn-interconnect",
+	},
+};
+
+module_platform_driver(imx8mn_icc_driver);
+MODULE_AUTHOR("Leonard Crestez <leonard.crestez@nxp.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/dt-bindings/interconnect/imx8mn.h b/include/dt-bindings/interconnect/imx8mn.h
new file mode 100644
index 000000000000..03d099dd71f8
--- /dev/null
+++ b/include/dt-bindings/interconnect/imx8mn.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Interconnect framework driver for i.MX SoC
+ *
+ * Copyright (c) 2019, NXP
+ */
+
+#ifndef __IMX8MN_ICM_INTERCONNECT_IDS_H
+#define __IMX8MN_ICM_INTERCONNECT_IDS_H
+
+#define IMX8MN_ICN_NOC		1
+#define IMX8MN_ICS_DRAM		2
+#define IMX8MN_ICS_OCRAM	3
+#define IMX8MN_ICM_A53		4
+
+#define IMX8MN_ICM_GPU		5
+#define IMX8MN_ICN_GPU		6
+
+#define IMX8MN_ICM_CSI1		7
+#define IMX8MN_ICM_CSI2		8
+#define IMX8MN_ICM_ISI		9
+#define IMX8MN_ICM_LCDIF	10
+#define IMX8MN_ICN_MIPI		11
+
+#define IMX8MN_ICM_USB		12
+
+#define IMX8MN_ICM_SDMA2	13
+#define IMX8MN_ICM_SDMA3	14
+#define IMX8MN_ICN_AUDIO	15
+
+#define IMX8MN_ICN_ENET		16
+#define IMX8MN_ICM_ENET		17
+
+#define IMX8MN_ICM_NAND		18
+#define IMX8MN_ICM_SDMA1	19
+#define IMX8MN_ICM_USDHC1	20
+#define IMX8MN_ICM_USDHC2	21
+#define IMX8MN_ICM_USDHC3	22
+#define IMX8MN_ICN_MAIN		23
+
+#endif /* __IMX8MN_ICM_INTERCONNECT_IDS_H */
-- 
2.17.1


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

* [PATCH RFC v5 09/10] arm64: dts: imx8m: Add NOC nodes
  2019-10-31 22:51 [PATCH RFC v5 00/10] interconnect: Add imx support via devfreq Leonard Crestez
                   ` (7 preceding siblings ...)
  2019-10-31 22:52 ` [PATCH RFC v5 08/10] interconnect: imx: Add platform driver for imx8mn Leonard Crestez
@ 2019-10-31 22:52 ` Leonard Crestez
  2019-10-31 22:52 ` [PATCH RFC v5 10/10] arm64: dts: imx8m: Add interconnect provider properties Leonard Crestez
  9 siblings, 0 replies; 15+ messages in thread
From: Leonard Crestez @ 2019-10-31 22:52 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Chanwoo Choi
  Cc: Artur Świgoń,
	Alexandre Bailon, Rafael J. Wysocki, Jacky Bai, Anson Huang,
	Abel Vesa, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Saravana Kannan, Mark Rutland, Viresh Kumar, Shawn Guo,
	Dong Aisheng, Fabio Estevam, Stephen Boyd, Michael Turquette,
	Matthias Kaehlcke, Angus Ainslie, Martin Kepplinger, linux-pm,
	kernel, linux-imx, devicetree, linux-arm-kernel

Add initial support for dynamic frequency scaling of main NOC.

Make DDRC the parent of the NOC (using passive governor) so that the
main NOC is automatically scaled together with DDRC by default.

Support for proactive scaling via interconnect will come later.

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mm.dtsi | 22 ++++++++++++++++++++++
 arch/arm64/boot/dts/freescale/imx8mn.dtsi | 22 ++++++++++++++++++++++
 arch/arm64/boot/dts/freescale/imx8mq.dtsi | 22 ++++++++++++++++++++++
 3 files changed, 66 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
index 5404870d80d5..dc0ab49bbbd2 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
@@ -138,10 +138,24 @@
 			clock-latency-ns = <150000>;
 			opp-suspend;
 		};
 	};
 
+	noc_opp_table: noc-opp-table {
+		compatible = "operating-points-v2";
+
+		opp-150M {
+			opp-hz = /bits/ 64 <150000000>;
+		};
+		opp-375M {
+			opp-hz = /bits/ 64 <375000000>;
+		};
+		opp-750M {
+			opp-hz = /bits/ 64 <750000000>;
+		};
+	};
+
 	memory@40000000 {
 		device_type = "memory";
 		reg = <0x0 0x40000000 0 0x80000000>;
 	};
 
@@ -772,10 +786,18 @@
 				status = "disabled";
 			};
 
 		};
 
+		noc: interconnect@32700000 {
+			compatible = "fsl,imx8mm-noc", "fsl,imx8m-noc";
+			reg = <0x32700000 0x100000>;
+			clocks = <&clk IMX8MM_CLK_NOC>;
+			devfreq = <&ddrc>;
+			operating-points-v2 = <&noc_opp_table>;
+		};
+
 		aips4: bus@32c00000 {
 			compatible = "fsl,aips-bus", "simple-bus";
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0x32c00000 0x32c00000 0x400000>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
index 344dd777635f..6b4a9ba2a8a5 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
@@ -137,10 +137,24 @@
 			clock-latency-ns = <150000>;
 			opp-suspend;
 		};
 	};
 
+	noc_opp_table: noc-opp-table {
+		compatible = "operating-points-v2";
+
+		opp-100M {
+			opp-hz = /bits/ 64 <100000000>;
+		};
+		opp-600M {
+			opp-hz = /bits/ 64 <600000000>;
+		};
+		opp-800M {
+			opp-hz = /bits/ 64 <800000000>;
+		};
+	};
+
 	memory@40000000 {
 		device_type = "memory";
 		reg = <0x0 0x40000000 0 0x80000000>;
 	};
 
@@ -668,10 +682,18 @@
 				status = "disabled";
 			};
 
 		};
 
+		noc: interconnect@32700000 {
+			compatible = "fsl,imx8mn-noc", "fsl,imx8m-noc";
+			reg = <0x32700000 0x100000>;
+			clocks = <&clk IMX8MN_CLK_NOC>;
+			devfreq = <&ddrc>;
+			operating-points-v2 = <&noc_opp_table>;
+		};
+
 		aips4: bus@32c00000 {
 			compatible = "fsl,aips-bus", "simple-bus";
 			reg = <0x32c00000 0x400000>;
 			#address-cells = <1>;
 			#size-cells = <1>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
index 6ef1af41ef68..c42c67eb1d50 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -183,10 +183,24 @@
 			clock-latency-ns = <150000>;
 			opp-suspend;
 		};
 	};
 
+	noc_opp_table: noc-opp-table {
+		compatible = "operating-points-v2";
+
+		opp-133M {
+			opp-hz = /bits/ 64 <133333333>;
+		};
+		opp-400M {
+			opp-hz = /bits/ 64 <400000000>;
+		};
+		opp-800M {
+			opp-hz = /bits/ 64 <800000000>;
+		};
+	};
+
 	pmu {
 		compatible = "arm,cortex-a53-pmu";
 		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-parent = <&gic>;
 		interrupt-affinity = <&A53_0>, <&A53_1>, <&A53_2>, <&A53_3>;
@@ -931,10 +945,18 @@
 				fsl,num-rx-queues = <3>;
 				status = "disabled";
 			};
 		};
 
+		noc: interconnect@32700000 {
+			compatible = "fsl,imx8mq-noc", "fsl,imx8m-noc";
+			reg = <0x32700000 0x100000>;
+			clocks = <&clk IMX8MQ_CLK_NOC>;
+			devfreq = <&ddrc>;
+			operating-points-v2 = <&noc_opp_table>;
+		};
+
 		bus@32c00000 { /* AIPS4 */
 			compatible = "fsl,imx8mq-aips-bus", "simple-bus";
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0x32c00000 0x32c00000 0x400000>;
-- 
2.17.1


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

* [PATCH RFC v5 10/10] arm64: dts: imx8m: Add interconnect provider properties
  2019-10-31 22:51 [PATCH RFC v5 00/10] interconnect: Add imx support via devfreq Leonard Crestez
                   ` (8 preceding siblings ...)
  2019-10-31 22:52 ` [PATCH RFC v5 09/10] arm64: dts: imx8m: Add NOC nodes Leonard Crestez
@ 2019-10-31 22:52 ` Leonard Crestez
  9 siblings, 0 replies; 15+ messages in thread
From: Leonard Crestez @ 2019-10-31 22:52 UTC (permalink / raw)
  To: Georgi Djakov, Rob Herring, Chanwoo Choi
  Cc: Artur Świgoń,
	Alexandre Bailon, Rafael J. Wysocki, Jacky Bai, Anson Huang,
	Abel Vesa, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Saravana Kannan, Mark Rutland, Viresh Kumar, Shawn Guo,
	Dong Aisheng, Fabio Estevam, Stephen Boyd, Michael Turquette,
	Matthias Kaehlcke, Angus Ainslie, Martin Kepplinger, linux-pm,
	kernel, linux-imx, devicetree, linux-arm-kernel

Add #interconnect-cells on main &noc so that it will probe the platform
interconnect providers. Other devices can request icc_paths like this:

	interconnects = <&noc BUS_MASTER_ID &noc BUS_SLAVE_ID>

And interconnect-node-id properties on &noc and &ddrc, the interconnect
provider will scan these and make PM QoS frequency requests in response
to bandwith request from other drivers.

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
 arch/arm64/boot/dts/freescale/imx8mm.dtsi | 4 ++++
 arch/arm64/boot/dts/freescale/imx8mn.dtsi | 4 ++++
 arch/arm64/boot/dts/freescale/imx8mq.dtsi | 4 ++++
 3 files changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
index dc0ab49bbbd2..4a84db1bf6bd 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"
 
 / {
 	interrupt-parent = <&gic>;
@@ -791,10 +792,12 @@
 		noc: interconnect@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";
@@ -881,10 +884,11 @@
 		};
 
 		ddrc: dram-controller@3d400000 {
 			compatible = "fsl,imx8mm-ddrc", "fsl,imx8m-ddrc";
 			reg = <0x3d400000 0x400000>;
+			interconnect-node-id = <IMX8MM_ICS_DRAM>;
 			clock-names = "dram_core",
 				      "dram_pll",
 				      "dram_alt",
 				      "dram_apb";
 			clocks = <&clk IMX8MM_CLK_DRAM_CORE>,
diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
index 6b4a9ba2a8a5..0fd96c976607 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
@@ -5,10 +5,11 @@
 
 #include <dt-bindings/clock/imx8mn-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/interconnect/imx8mn.h>
 
 #include "imx8mn-pinfunc.h"
 
 / {
 	interrupt-parent = <&gic>;
@@ -687,10 +688,12 @@
 		noc: interconnect@32700000 {
 			compatible = "fsl,imx8mn-noc", "fsl,imx8m-noc";
 			reg = <0x32700000 0x100000>;
 			clocks = <&clk IMX8MN_CLK_NOC>;
 			devfreq = <&ddrc>;
+			#interconnect-cells = <1>;
+			interconnect-node-id = <IMX8MN_ICN_NOC>;
 			operating-points-v2 = <&noc_opp_table>;
 		};
 
 		aips4: bus@32c00000 {
 			compatible = "fsl,aips-bus", "simple-bus";
@@ -790,10 +793,11 @@
 				      "dram_apb";
 			clocks = <&clk IMX8MN_CLK_DRAM_CORE>,
 				 <&clk IMX8MN_DRAM_PLL>,
 				 <&clk IMX8MN_CLK_DRAM_ALT>,
 				 <&clk IMX8MN_CLK_DRAM_APB>;
+			interconnect-node-id = <IMX8MN_ICS_DRAM>;
 			devfreq-events = <&ddr_pmu>;
 		};
 
 		ddr_pmu: ddr-pmu@3d800000 {
 			compatible = "fsl,imx8mn-ddr-pmu", "fsl,imx8m-ddr-pmu";
diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
index c42c67eb1d50..6ede02b44931 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -9,10 +9,11 @@
 #include <dt-bindings/reset/imx8mq-reset.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/imx8mq.h>
 #include "imx8mq-pinfunc.h"
 
 / {
 	interrupt-parent = <&gpc>;
 
@@ -950,10 +951,12 @@
 		noc: interconnect@32700000 {
 			compatible = "fsl,imx8mq-noc", "fsl,imx8m-noc";
 			reg = <0x32700000 0x100000>;
 			clocks = <&clk IMX8MQ_CLK_NOC>;
 			devfreq = <&ddrc>;
+			#interconnect-cells = <1>;
+			interconnect-node-id = <IMX8MQ_ICN_NOC>;
 			operating-points-v2 = <&noc_opp_table>;
 		};
 
 		bus@32c00000 { /* AIPS4 */
 			compatible = "fsl,imx8mq-aips-bus", "simple-bus";
@@ -1144,10 +1147,11 @@
 				      "dram_apb";
 			clocks = <&clk IMX8MQ_CLK_DRAM_CORE>,
 				 <&clk IMX8MQ_DRAM_PLL_OUT>,
 				 <&clk IMX8MQ_CLK_DRAM_ALT>,
 				 <&clk IMX8MQ_CLK_DRAM_APB>;
+			interconnect-node-id = <IMX8MQ_ICS_DRAM>;
 			devfreq-events = <&ddr_pmu>;
 		};
 
 		ddr_pmu: ddr-pmu@3d800000 {
 			compatible = "fsl,imx8mq-ddr-pmu", "fsl,imx8m-ddr-pmu";
-- 
2.17.1


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

* Re: [PATCH RFC v5 01/10] dt-bindings: devfreq: Add bindings for generic imx buses
  2019-10-31 22:52 ` [PATCH RFC v5 01/10] dt-bindings: devfreq: Add bindings for generic imx buses Leonard Crestez
@ 2019-11-04 22:49   ` Rob Herring
  2019-11-11 22:28     ` Leonard Crestez
  0 siblings, 1 reply; 15+ messages in thread
From: Rob Herring @ 2019-11-04 22:49 UTC (permalink / raw)
  To: Leonard Crestez
  Cc: Georgi Djakov, Chanwoo Choi, Artur Świgoń,
	Alexandre Bailon, Rafael J. Wysocki, Jacky Bai, Anson Huang,
	Abel Vesa, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Saravana Kannan, Mark Rutland, Viresh Kumar, Shawn Guo,
	Dong Aisheng, Fabio Estevam, Stephen Boyd, Michael Turquette,
	Matthias Kaehlcke, Angus Ainslie, Martin Kepplinger, linux-pm,
	kernel, linux-imx, devicetree, linux-arm-kernel

On Fri, Nov 01, 2019 at 12:52:00AM +0200, Leonard Crestez wrote:
> Add initial dt bindings for the interconnects inside i.MX chips.
> Multiple external IPs are involved but SOC integration means the
> software controllable interfaces are very similar.
> 
> Single node also acts as interconnect provider if #interconnect-cells is
> present.
> 
> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
> Acked-by: MyungJoo Ham <myungjoo.ham@samsung.com>
> ---
>  .../devicetree/bindings/devfreq/imx.yaml      | 83 +++++++++++++++++++

bindings/interconnect/

>  1 file changed, 83 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/devfreq/imx.yaml
> 
> diff --git a/Documentation/devicetree/bindings/devfreq/imx.yaml b/Documentation/devicetree/bindings/devfreq/imx.yaml
> new file mode 100644
> index 000000000000..bfc825407764
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/devfreq/imx.yaml
> @@ -0,0 +1,83 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/devfreq/imx.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Generic i.MX bus frequency device

i.MX8 specific?

> +
> +maintainers:
> +  - Leonard Crestez <leonard.crestez@nxp.com>
> +
> +description: |
> +  The i.MX SoC family has multiple buses for which clock frequency (and
> +  sometimes voltage) can be adjusted.
> +
> +  Some of those buses expose register areas mentioned in the memory maps as GPV
> +  ("Global Programmers View") but not all. Access to this area might be denied
> +  for normal (non-secure) world.
> +
> +  The buses are based on externally licensed IPs such as ARM NIC-301 and
> +  Arteris FlexNOC but DT bindings are specific to the integration of these bus
> +  interconnect IPs into imx SOCs.
> +
> +properties:
> +  compatible:
> +    oneOf:
> +      - items:
> +        - enum:
> +          - fsl,imx8mn-nic
> +          - fsl,imx8mm-nic
> +          - fsl,imx8mq-nic
> +        - const: fsl,imx8m-nic
> +      - items:
> +        - enum:
> +          - fsl,imx8mn-noc
> +          - fsl,imx8mm-noc
> +          - fsl,imx8mq-noc
> +        - const: fsl,imx8m-noc
> +
> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    maxItems: 1
> +
> +  operating-points-v2: true
> +
> +  devfreq:
> +    description: |
> +      Phandle to another devfreq device to match OPPs with by using the
> +      passive governor.
> +    $ref: "/schemas/types.yaml#/definitions/phandle"
> +
> +  '#interconnect-cells':
> +    description: |
> +      If specified then also act as an interconnect provider. Should only be
> +      set once per soc on main noc.
> +    const: 1
> +
> +  interconnect-node-id:

Looks like common property, but it's not...

Generally, we don't do indexes or instance ids. So it needs a better 
explanation or drop this. The driver side looks like an odd marriage 
between interconnect and devfreq drivers that needs better integration, 
but I'm not all that familar with either.

> +    description: |
> +      i.MX chips have multiple scalable buses based on the same IP, this is
> +      used to distinguish between. Uses same identifier namespace as consumer

It's not names, so number space? Just guessing because there's no type 
nor example.

> +      "interconnects" property, for example one of the values in
> +      "include/dt-bindings/interconnect/imx8mm.h"
> +
> +    const: 1
> +
> +required:
> +  - compatible
> +  - clocks
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/imx8mm-clock.h>
> +    noc: noc@32700000 {
> +            compatible = "fsl,imx8mm-noc", "fsl,imx8m-noc";
> +            reg = <0x32700000 0x100000>;
> +            clocks = <&clk IMX8MM_CLK_NOC>;
> +            operating-points-v2 = <&noc_opp_table>;
> +    };
> -- 
> 2.17.1
> 

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

* Re: [PATCH RFC v5 01/10] dt-bindings: devfreq: Add bindings for generic imx buses
  2019-11-04 22:49   ` Rob Herring
@ 2019-11-11 22:28     ` Leonard Crestez
  0 siblings, 0 replies; 15+ messages in thread
From: Leonard Crestez @ 2019-11-11 22:28 UTC (permalink / raw)
  To: Rob Herring, Georgi Djakov
  Cc: Chanwoo Choi, Artur Świgoń,
	Alexandre Bailon, Rafael J. Wysocki, Jacky Bai, Anson Huang,
	Abel Vesa, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Saravana Kannan, Mark Rutland, Viresh Kumar, Shawn Guo,
	Aisheng Dong, Fabio Estevam, Stephen Boyd, Michael Turquette,
	Matthias Kaehlcke, Angus Ainslie, Martin Kepplinger, linux-pm,
	kernel, dl-linux-imx, devicetree, linux-arm-kernel

On 05.11.2019 00:49, Rob Herring wrote:
> On Fri, Nov 01, 2019 at 12:52:00AM +0200, Leonard Crestez wrote:
>> Add initial dt bindings for the interconnects inside i.MX chips.
>> Multiple external IPs are involved but SOC integration means the
>> software controllable interfaces are very similar.
>>
>> Single node also acts as interconnect provider if #interconnect-cells is
>> present.
>>
>> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
>> Acked-by: MyungJoo Ham <myungjoo.ham@samsung.com>
>> ---
>>   .../devicetree/bindings/devfreq/imx.yaml      | 83 +++++++++++++++++++
> 
> bindings/interconnect/

Make sense. The only other two files in devicetree/bindings/devfreq are:
  * rk3399_dmc: a memory controller
  * exynos-bus: arguably an interconnect

>>   1 file changed, 83 insertions(+)
>>   create mode 100644 Documentation/devicetree/bindings/devfreq/imx.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/devfreq/imx.yaml b/Documentation/devicetree/bindings/devfreq/imx.yaml
>> new file mode 100644
>> index 000000000000..bfc825407764
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/devfreq/imx.yaml
>> @@ -0,0 +1,83 @@
>> +# SPDX-License-Identifier: GPL-2.0
>> +%YAML 1.2
>> +---
>> +$id: https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevicetree.org%2Fschemas%2Fdevfreq%2Fimx.yaml%23&amp;data=02%7C01%7Cleonard.crestez%40nxp.com%7C95911400e0834b06269c08d761794cd2%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C1%7C637085045930647253&amp;sdata=88iAXoKObu%2FXBqZu6hNwnOUIffB8GxVLdGeBWiCjClI%3D&amp;reserved=0
>> +$schema: https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevicetree.org%2Fmeta-schemas%2Fcore.yaml%23&amp;data=02%7C01%7Cleonard.crestez%40nxp.com%7C95911400e0834b06269c08d761794cd2%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C1%7C637085045930647253&amp;sdata=0phpsG05ZsYc5SnI3FXZODJpJSEB2tzA5v02r7N%2BY2I%3D&amp;reserved=0
>> +
>> +title: Generic i.MX bus frequency device
> 
> i.MX8 specific?

Not really, but it's initially targeted at imx8m.

>> +maintainers:
>> +  - Leonard Crestez <leonard.crestez@nxp.com>
>> +
>> +description: |
>> +  The i.MX SoC family has multiple buses for which clock frequency (and
>> +  sometimes voltage) can be adjusted.
>> +
>> +  Some of those buses expose register areas mentioned in the memory maps as GPV
>> +  ("Global Programmers View") but not all. Access to this area might be denied
>> +  for normal (non-secure) world.
>> +
>> +  The buses are based on externally licensed IPs such as ARM NIC-301 and
>> +  Arteris FlexNOC but DT bindings are specific to the integration of these bus
>> +  interconnect IPs into imx SOCs.
>> +
>> +properties:
>> +  compatible:
>> +    oneOf:
>> +      - items:
>> +        - enum:
>> +          - fsl,imx8mn-nic
>> +          - fsl,imx8mm-nic
>> +          - fsl,imx8mq-nic
>> +        - const: fsl,imx8m-nic
>> +      - items:
>> +        - enum:
>> +          - fsl,imx8mn-noc
>> +          - fsl,imx8mm-noc
>> +          - fsl,imx8mq-noc
>> +        - const: fsl,imx8m-noc
>> +
>> +  reg:
>> +    maxItems: 1
>> +
>> +  clocks:
>> +    maxItems: 1
>> +
>> +  operating-points-v2: true
>> +
>> +  devfreq:
>> +    description: |
>> +      Phandle to another devfreq device to match OPPs with by using the
>> +      passive governor.
>> +    $ref: "/schemas/types.yaml#/definitions/phandle"
>> +
>> +  '#interconnect-cells':
>> +    description: |
>> +      If specified then also act as an interconnect provider. Should only be
>> +      set once per soc on main noc.
>> +    const: 1
>> +
>> +  interconnect-node-id:
> 
> Looks like common property, but it's not...
> 
> Generally, we don't do indexes or instance ids. So it needs a better
> explanation or drop this. The driver side looks like an odd marriage
> between interconnect and devfreq drivers that needs better integration,
> but I'm not all that familar with either.

Current interconnect drivers all operate by sending messages via a 
mailbox to a system controller which handles bandwidth requests. They 
only perform request aggregation. On imx8m frequency scaling is also 
implemented in the kernel so the NOC becomes almost like a MFD.

The interconnect-node-id is used to find other scalable nodes for the 
same interconnect provider. I can replace this with a "scalable-nodes" 
array like this:

	noc: interconnect@32700000 {
		compatible = "fsl,imx8mq-noc", "fsl,imx8m-noc";
		reg = <0x32700000 0x100000>;
		clocks = <&clk IMX8MQ_CLK_NOC>;
		#interconnect-cells = <1>;
		fsl,scalable-node-ids = <IMX8MQ_ICN_NOC>,
					<IMX8MQ_ICS_DRAM>;
		fsl,scalable-nodes = <&noc>,
				     <&ddrc>;
		operating-points-v2 = <&noc_opp_table>;

		noc_opp_table: opp-table {
			compatible = "operating-points-v2";

			opp-133M {
				opp-hz = /bits/ 64 <133333333>;
			};
			opp-400M {
				opp-hz = /bits/ 64 <400000000>;
			};
			opp-800M {
				opp-hz = /bits/ 64 <800000000>;
			};
		};
	};

	ddrc: dram-controller@3d400000 {
		compatible = "fsl,imx8mq-ddrc", "fsl,imx8m-ddrc";
		reg = <0x3d400000 0x400000>;
		clock-names = "core", "pll", "alt", "apb";
		clocks = <&clk IMX8MQ_CLK_DRAM_CORE>,
			 <&clk IMX8MQ_DRAM_PLL_OUT>,
			 <&clk IMX8MQ_CLK_DRAM_ALT>,
			 <&clk IMX8MQ_CLK_DRAM_APB>;
		devfreq-events = <&ddr_pmu>;
	};

It's a bit strange that the noc references itself but in advanced 
multiple NOC can be be present and there needs to be a way to map from 
the interconnect graph (node ids) to devicetree nodes.

>> +    description: |
>> +      i.MX chips have multiple scalable buses based on the same IP, this is
>> +      used to distinguish between. Uses same identifier namespace as consumer
> 
> It's not names, so number space? Just guessing because there's no type
> nor example.

Maybe "numeric namespace"?

>> +      "interconnects" property, for example one of the values in
>> +      "include/dt-bindings/interconnect/imx8mm.h"
>> +
>> +    const: 1
>> +
>> +required:
>> +  - compatible
>> +  - clocks
>> +
>> +additionalProperties: false
>> +
>> +examples:
>> +  - |
>> +    #include <dt-bindings/clock/imx8mm-clock.h>
>> +    noc: noc@32700000 {
>> +            compatible = "fsl,imx8mm-noc", "fsl,imx8m-noc";
>> +            reg = <0x32700000 0x100000>;
>> +            clocks = <&clk IMX8MM_CLK_NOC>;
>> +            operating-points-v2 = <&noc_opp_table>;
>> +    };
>> -- 
>> 2.17.1

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

* Re: [PATCH RFC v5 05/10] interconnect: Add imx core driver
  2019-10-31 22:52 ` [PATCH RFC v5 05/10] interconnect: Add imx core driver Leonard Crestez
@ 2019-11-12 15:07   ` Georgi Djakov
  2019-11-12 17:25     ` Leonard Crestez
  0 siblings, 1 reply; 15+ messages in thread
From: Georgi Djakov @ 2019-11-12 15:07 UTC (permalink / raw)
  To: Leonard Crestez, Rob Herring, Chanwoo Choi
  Cc: Artur Świgoń,
	Alexandre Bailon, Rafael J. Wysocki, Jacky Bai, Anson Huang,
	Abel Vesa, Krzysztof Kozlowski, MyungJoo Ham, Kyungmin Park,
	Saravana Kannan, Mark Rutland, Viresh Kumar, Shawn Guo,
	Dong Aisheng, Fabio Estevam, Stephen Boyd, Michael Turquette,
	Matthias Kaehlcke, Angus Ainslie, Martin Kepplinger, linux-pm,
	kernel, linux-imx, devicetree, linux-arm-kernel

Hi Leonard,

Thanks for the patch!

On 1.11.19 г. 0:52 ч., Leonard Crestez wrote:
> 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.

Are the adjustable nodes SoC specific? Can we have them here in the driver
instead of 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    | 273 ++++++++++++++++++++++++++++++
>  drivers/interconnect/imx/imx.h    |  60 +++++++
>  6 files changed, 341 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 b6ea8f0a6122..f57e77b8731c 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..7d248e01dcf0
> --- /dev/null
> +++ b/drivers/interconnect/imx/imx.c
> @@ -0,0 +1,273 @@
> +// 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;

What device is this? There is already a *dev in struct icc_provider.
Please add kernel-doc.

> +};
> +
> +/* 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;

Why the sum of average and peak bandwidth?

> +	do_div(freq, node_data->desc->adj->bw_div);
> +	dev_dbg(dev, "node %s device %s avg_bw %ukBps peak_bw %ukBps min_freq %llukHz\n",
> +			node->name, dev_name(node_data->devfreq->dev.parent),
> +			node->avg_bw, node->peak_bw, freq);
> +
> +	if (freq > S32_MAX) {
> +		dev_err(dev, "%s can't request more than 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 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;
> +
> +	/* Find nodes based on interconnect-node-id property */
> +	for_each_node_with_property(dn, "interconnect-node-id") {
> +		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);

Ah, so you need to get the devfreq nodes? So looking at the next
patches it seems that noc and ddrc are the only adjustable nodes?

Maybe we should model them both as interconnect providers, as they
seem to be dealing with the bandwidth/frequency requirements and
changing the clock rates.

Thanks,
Georgi

> +	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_node_put(dn);
> +
> +	return dev_pm_qos_add_request(node_data->devfreq->dev.parent,
> +				      &node_data->qos_req,
> +				      DEV_PM_QOS_MIN_FREQUENCY, 0);
> +}
> +

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

* Re: [PATCH RFC v5 05/10] interconnect: Add imx core driver
  2019-11-12 15:07   ` Georgi Djakov
@ 2019-11-12 17:25     ` Leonard Crestez
  0 siblings, 0 replies; 15+ messages in thread
From: Leonard Crestez @ 2019-11-12 17:25 UTC (permalink / raw)
  To: Georgi Djakov, Chanwoo Choi, Artur Świgoń
  Cc: Rob Herring, Alexandre Bailon, Rafael J. Wysocki, Jacky Bai,
	Anson Huang, Abel Vesa, Krzysztof Kozlowski, MyungJoo Ham,
	Kyungmin Park, Saravana Kannan, Mark Rutland, Viresh Kumar,
	Shawn Guo, Aisheng Dong, Fabio Estevam, Stephen Boyd,
	Michael Turquette, Matthias Kaehlcke, Angus Ainslie,
	Martin Kepplinger, linux-pm, kernel, dl-linux-imx, devicetree,
	linux-arm-kernel

On 12.11.2019 17:08, Georgi Djakov wrote:
> Hi Leonard,
> 
> Thanks for the patch!
> 
> On 1.11.19 г. 0:52 ч., Leonard Crestez wrote:
>> 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.
> 
> Are the adjustable nodes SoC specific? Can we have them here in the driver
> instead of 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    | 273 ++++++++++++++++++++++++++++++
>>   drivers/interconnect/imx/imx.h    |  60 +++++++
>>   6 files changed, 341 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 b6ea8f0a6122..f57e77b8731c 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..7d248e01dcf0
>> --- /dev/null
>> +++ b/drivers/interconnect/imx/imx.c
>> @@ -0,0 +1,273 @@
>> +// 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;
> 
> What device is this? There is already a *dev in struct icc_provider.
> Please add kernel-doc.

This is set as icc_provider->data and used for xlate but it can be 
removed entirely if driver switches to icc_xlate_onecell.

>> +/* 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;
> 
> Why the sum of average and peak bandwidth?

What else?

Averages from all path requests are added and the max() of all per-path 
peak requests is added on top. The average BW is guaranteed to be 
consumed (for example a display controller) and the BW for occasional 
bursts (such as USB) should be reserved on top of that.

Using max(avg, peak) here would make requests for peak BW largely 
ineffective when there's also a large "avg" request.

>> +	do_div(freq, node_data->desc->adj->bw_div);
>> +	dev_dbg(dev, "node %s device %s avg_bw %ukBps peak_bw %ukBps min_freq %llukHz\n",
>> +			node->name, dev_name(node_data->devfreq->dev.parent),
>> +			node->avg_bw, node->peak_bw, freq);
>> +
>> +	if (freq > S32_MAX) {
>> +		dev_err(dev, "%s can't request more than 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 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;
>> +
>> +	/* Find nodes based on interconnect-node-id property */
>> +	for_each_node_with_property(dn, "interconnect-node-id") {
>> +		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);
> 
> Ah, so you need to get the devfreq nodes? So looking at the next
> patches it seems that noc and ddrc are the only adjustable nodes?

I want to add more scalable nodes in the future. imx8mq/8mm/8mn have 
additional NICs (AXI switches with a different implementation) and 
upcoming imx8mp will have additional NOCs and scalable NTTP links.

> Maybe we should model them both as interconnect providers, as they
> seem to be dealing with the bandwidth/frequency requirements and
> changing the clock rates.

The ddrc is not really an interconnect, it only has an AXI slave port. 
In theory it could register itself as a single-node icc provider solely 
so that it can handle the "set" call but that seems hacky.

Current icc driver implementations send aggregated BW requests to a 
separate controller and internally it changes some frequencies, correct? 
What I'm doing is implementing the frequency adjustment part inside the 
kernel as devfreq drivers. These devices have their own OF nodes with 
OPP tables and supply regulators and governors (based on bandwith 
measurement).

It makes a lot of sense to layer the "interconnect" on top of "scalable 
nodes".

--
Regards,
Leonard

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

end of thread, other threads:[~2019-11-12 17:25 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-31 22:51 [PATCH RFC v5 00/10] interconnect: Add imx support via devfreq Leonard Crestez
2019-10-31 22:52 ` [PATCH RFC v5 01/10] dt-bindings: devfreq: Add bindings for generic imx buses Leonard Crestez
2019-11-04 22:49   ` Rob Herring
2019-11-11 22:28     ` Leonard Crestez
2019-10-31 22:52 ` [PATCH RFC v5 02/10] PM / devfreq: Add generic imx bus driver Leonard Crestez
2019-10-31 22:52 ` [PATCH RFC v5 03/10] PM / devfreq: imx: Register interconnect device Leonard Crestez
2019-10-31 22:52 ` [PATCH RFC v5 04/10] PM / devfreq: Add devfreq_get_devfreq_by_node Leonard Crestez
2019-10-31 22:52 ` [PATCH RFC v5 05/10] interconnect: Add imx core driver Leonard Crestez
2019-11-12 15:07   ` Georgi Djakov
2019-11-12 17:25     ` Leonard Crestez
2019-10-31 22:52 ` [PATCH RFC v5 06/10] interconnect: imx: Add platform driver for imx8mm Leonard Crestez
2019-10-31 22:52 ` [PATCH RFC v5 07/10] interconnect: imx: Add platform driver for imx8mq Leonard Crestez
2019-10-31 22:52 ` [PATCH RFC v5 08/10] interconnect: imx: Add platform driver for imx8mn Leonard Crestez
2019-10-31 22:52 ` [PATCH RFC v5 09/10] arm64: dts: imx8m: Add NOC nodes Leonard Crestez
2019-10-31 22:52 ` [PATCH RFC v5 10/10] arm64: dts: imx8m: Add interconnect provider properties 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).