2021-02-19 16:05:27

by Abel Vesa

[permalink] [raw]
Subject: [RFC 00/19] Rework support for i.MX8MQ interconnect with devfreq

This has been on my queue for quite some time now. It is more of a
proof-of-concept.

This rework is done with the compatibility of future i.MX platforms in
mind. For example, the i.MX8MP platform has multiple NoCs. This
patchsets prepares the imx interconnect and imx devfreq for that too.

As of now, none of the drivers involved are being used and there is no
icc consumer on any off the i.MX platforms.

Basically, the steps taken here are the following:

1. Make the dram_apb clock "reparantable" from kernel.
This is needed in order to keep track of the actual parent of the
dram_apb clock in the kernel clock hierarchy. Note that the actual
switch is done EL3 (TF-A).

2. Rework the imx-bus so the actual link between the icc and the
NoCs or the pl301s is not tightly coupled. This allows us to have
as many NoCs as necessary but also allows as to use the same driver
for the pl301s. The pl301s have their own clocks too, so we need to
reduce their rates too.

3. Rework the imx8m-ddrc driver. Remove the support for dts defined
OPPs. The EL3 provides those. So instead of havingi to keep the OPP table in
both EL3 and kernel in sync, we rely on what the EL3 gives us.
Also, when the platform suspends, the bus needs to be running at highest
rate, otherwise there is a chance it might not resume anymore.
By adding the late system sleep PM ops we can handle that easily.

4. Rework the imx interconnect driver to use the fsl,icc-id instead
of the robust imx_icc_node_adj_desc for linking with the target node.
By adding the fsl,icc-id property to all the NoC and pl301 dts nodes,
we can link each icc node to their corresponding NoC, pl301 or dram.
Basically, when the imx interconnect platform specific driver probes,
it will take each node defined for that platform and look-up the
corresponding dts node based on the id and add that as the qos device.

5. Added the fec and usdhc as icc consumers. This is just as an example.
All the other consumers can be added later. Basically, each consumer
will add a path to their device node and in the driver will have to
handle that icc path accordingly.

Abel Vesa (19):
clk: imx8mq: Replace critical with ignore_unused flag for dram_apb
clock
dt-bindings: interconnect: imx8mq: Add missing pl301 and SAI ids
devfreq: imx-bus: Switch governor to powersave
devfreq: imx-bus: Decouple imx-bus from icc made
devfreq: imx8m-ddrc: Change governor to powersave
devfreq: imx8m-ddrc: Use the opps acquired from EL3
devfreq: imx8m-ddrc: Add late system sleep PM ops
interconnect: imx: Switch from imx_icc_node_adj_desc to fsl,icc-id
node assignment
interconnect: imx8: Remove the imx_icc_node_adj_desc
interconnect: imx8mq: Add the pl301_per_m and pl301_wakeup nodes and
subnodes
interconnect: imx8mq: Add of_match_table
interconnect: imx: Add imx_icc_get_bw and imx_icc_aggregate functions
arm64: dts: imx8mq: Add fsl,icc-id property to ddrc node
arm64: dts: imx8mq: Add fsl,icc-id to noc node
arm64: dts: imx8mq: Add all pl301 nodes
arm64: dts: imx8mq: Add the interconnect node
arm64: dts: imx8mq: Add interconnect properties to icc consumer nodes
net: ethernet: fec_main: Add interconnect support
mmc: sdhci-esdhc-imx: Add interconnect support

arch/arm64/boot/dts/freescale/imx8mq.dtsi | 200 +++++++++++++++++++++-
drivers/clk/imx/clk-imx8mq.c | 2 +-
drivers/devfreq/imx-bus.c | 42 +----
drivers/devfreq/imx8m-ddrc.c | 75 +++-----
drivers/interconnect/imx/imx.c | 92 +++++-----
drivers/interconnect/imx/imx.h | 19 +-
drivers/interconnect/imx/imx8mm.c | 32 ++--
drivers/interconnect/imx/imx8mn.c | 28 +--
drivers/interconnect/imx/imx8mq.c | 59 ++++---
drivers/mmc/host/sdhci-esdhc-imx.c | 26 +++
drivers/net/ethernet/freescale/fec.h | 3 +
drivers/net/ethernet/freescale/fec_main.c | 19 ++
include/dt-bindings/interconnect/imx8mq.h | 9 +
scripts/dtc/fdtoverlay | Bin 0 -> 61280 bytes
14 files changed, 393 insertions(+), 213 deletions(-)
create mode 100755 scripts/dtc/fdtoverlay

--
2.29.2


2021-02-19 16:05:34

by Abel Vesa

[permalink] [raw]
Subject: [RFC 06/19] devfreq: imx8m-ddrc: Use the opps acquired from EL3

i.MX8M platforms get their dram OPPs from the EL3.
We don't need to duplicate that in the kernel dram dts node.
We should just trust the OPPs provided by the EL3.

Signed-off-by: Abel Vesa <[email protected]>
---
drivers/devfreq/imx8m-ddrc.c | 49 ++----------------------------------
1 file changed, 2 insertions(+), 47 deletions(-)

diff --git a/drivers/devfreq/imx8m-ddrc.c b/drivers/devfreq/imx8m-ddrc.c
index 3a6c04ba4f2e..33de83acfd8b 100644
--- a/drivers/devfreq/imx8m-ddrc.c
+++ b/drivers/devfreq/imx8m-ddrc.c
@@ -333,38 +333,9 @@ static int imx8m_ddrc_init_freq_info(struct device *dev)
if (freq->dram_core_parent_index == 2 &&
freq->dram_alt_parent_index == 0)
return -ENODEV;
- }
-
- return 0;
-}
-
-static int imx8m_ddrc_check_opps(struct device *dev)
-{
- struct imx8m_ddrc *priv = dev_get_drvdata(dev);
- struct imx8m_ddrc_freq *freq_info;
- struct dev_pm_opp *opp;
- unsigned long freq;
- int i, opp_count;
-
- /* Enumerate DT OPPs and disable those not supported by firmware */
- opp_count = dev_pm_opp_get_opp_count(dev);
- if (opp_count < 0)
- return opp_count;
- for (i = 0, freq = 0; i < opp_count; ++i, ++freq) {
- opp = dev_pm_opp_find_freq_ceil(dev, &freq);
- if (IS_ERR(opp)) {
- dev_err(dev, "Failed enumerating OPPs: %ld\n",
- PTR_ERR(opp));
- return PTR_ERR(opp);
- }
- dev_pm_opp_put(opp);

- freq_info = imx8m_ddrc_find_freq(priv, freq);
- if (!freq_info) {
- dev_info(dev, "Disable unsupported OPP %luHz %luMT/s\n",
- freq, DIV_ROUND_CLOSEST(freq, 250000));
- dev_pm_opp_disable(dev, freq);
- }
+ if (dev_pm_opp_add(dev, freq->rate * 250000, 0))
+ return -ENODEV;
}

return 0;
@@ -372,7 +343,6 @@ static int imx8m_ddrc_check_opps(struct device *dev)

static void imx8m_ddrc_exit(struct device *dev)
{
- dev_pm_opp_of_remove_table(dev);
}

static int imx8m_ddrc_probe(struct platform_device *pdev)
@@ -419,16 +389,6 @@ static int imx8m_ddrc_probe(struct platform_device *pdev)
return ret;
}

- ret = dev_pm_opp_of_add_table(dev);
- if (ret < 0) {
- dev_err(dev, "failed to get OPP table\n");
- return ret;
- }
-
- ret = imx8m_ddrc_check_opps(dev);
- if (ret < 0)
- goto err;
-
priv->profile.polling_ms = 1000;
priv->profile.target = imx8m_ddrc_target;
priv->profile.get_dev_status = imx8m_ddrc_get_dev_status;
@@ -441,13 +401,8 @@ static int imx8m_ddrc_probe(struct platform_device *pdev)
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;
}

--
2.29.2

2021-02-19 16:06:13

by Abel Vesa

[permalink] [raw]
Subject: [RFC 11/19] interconnect: imx8mq: Add of_match_table

The i.MX8MQ driver will probe based on the compatible string
instead of using device data in imx-bus devfreq driver.

Signed-off-by: Abel Vesa <[email protected]>
---
drivers/interconnect/imx/imx8mq.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/drivers/interconnect/imx/imx8mq.c b/drivers/interconnect/imx/imx8mq.c
index 010ad3d76286..64321f1d323b 100644
--- a/drivers/interconnect/imx/imx8mq.c
+++ b/drivers/interconnect/imx/imx8mq.c
@@ -6,6 +6,7 @@
*/

#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/interconnect-provider.h>
#include <dt-bindings/interconnect/imx8mq.h>
@@ -88,12 +89,18 @@ static int imx8mq_icc_remove(struct platform_device *pdev)
return imx_icc_unregister(pdev);
}

+static const struct of_device_id imx8mq_icc_of_match[] = {
+ { .compatible = "fsl,imx8mq-icc" },
+ { /* sentinel */ },
+};
+
static struct platform_driver imx8mq_icc_driver = {
.probe = imx8mq_icc_probe,
.remove = imx8mq_icc_remove,
.driver = {
.name = "imx8mq-interconnect",
.sync_state = icc_sync_state,
+ .of_match_table = of_match_ptr(imx8mq_icc_of_match),
},
};

--
2.29.2

2021-02-19 16:06:20

by Abel Vesa

[permalink] [raw]
Subject: [RFC 04/19] devfreq: imx-bus: Decouple imx-bus from icc made

The link between an imx-bus device and its icc id will be done
through the fsl,icc-id property in each dts node. The imx
interconnect driver will pick up all the dts nodes that have that
property defined and will link them to the rightfull icc id.

Signed-off-by: Abel Vesa <[email protected]>
---
drivers/devfreq/imx-bus.c | 40 +++------------------------------------
1 file changed, 3 insertions(+), 37 deletions(-)

diff --git a/drivers/devfreq/imx-bus.c b/drivers/devfreq/imx-bus.c
index 1c0c92d0eb08..9f0df88b29c1 100644
--- a/drivers/devfreq/imx-bus.c
+++ b/drivers/devfreq/imx-bus.c
@@ -65,36 +65,6 @@ static void imx_bus_exit(struct device *dev)
platform_device_unregister(priv->icc_pdev);
}

-/* imx_bus_init_icc() - register matching icc provider if required */
-static int imx_bus_init_icc(struct device *dev)
-{
- struct imx_bus *priv = dev_get_drvdata(dev);
- const char *icc_driver_name;
-
- if (!of_get_property(dev->of_node, "#interconnect-cells", 0))
- return 0;
- if (!IS_ENABLED(CONFIG_INTERCONNECT_IMX)) {
- dev_warn(dev, "imx interconnect drivers disabled\n");
- return 0;
- }
-
- icc_driver_name = of_device_get_match_data(dev);
- if (!icc_driver_name) {
- dev_err(dev, "unknown interconnect driver\n");
- return 0;
- }
-
- priv->icc_pdev = platform_device_register_data(
- dev, icc_driver_name, -1, 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->icc_pdev));
- return PTR_ERR(priv->icc_pdev);
- }
-
- return 0;
-}
-
static int imx_bus_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -144,10 +114,6 @@ static int imx_bus_probe(struct platform_device *pdev)
goto err;
}

- ret = imx_bus_init_icc(dev);
- if (ret)
- goto err;
-
return 0;

err:
@@ -156,9 +122,9 @@ static int imx_bus_probe(struct platform_device *pdev)
}

static const struct of_device_id imx_bus_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,imx8mq-noc",},
+ { .compatible = "fsl,imx8mm-noc",},
+ { .compatible = "fsl,imx8mn-noc",},
{ .compatible = "fsl,imx8m-noc", },
{ .compatible = "fsl,imx8m-nic", },
{ /* sentinel */ },
--
2.29.2

2021-02-19 16:06:42

by Abel Vesa

[permalink] [raw]
Subject: [RFC 08/19] interconnect: imx: Switch from imx_icc_node_adj_desc to fsl,icc-id node assignment

In order to be able to have more than one NoCs in the interconnect net
we need to decouple the NoC from the dram. So instead of using the
imx_icc_node_adj_desc, we use the fsl,icc-id property that is in
each NoC (or pl301) to the icc node (based on the id) to it.
Along with all the NoC and pl301 nodes in the dts we will have a
interconnect dedicated node. This node will be the actual device of the
icc provider.

Signed-off-by: Abel Vesa <[email protected]>
---
drivers/interconnect/imx/imx.c | 72 +++++++++++++++-------------------
1 file changed, 32 insertions(+), 40 deletions(-)

diff --git a/drivers/interconnect/imx/imx.c b/drivers/interconnect/imx/imx.c
index c770951a909c..db048df80011 100644
--- a/drivers/interconnect/imx/imx.c
+++ b/drivers/interconnect/imx/imx.c
@@ -34,9 +34,9 @@ static int imx_icc_node_set(struct icc_node *node)
if (!node_data->qos_dev)
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",
+ freq = max(node->avg_bw, node->peak_bw);
+
+ dev_dbg(dev, " DBG node %s device %s avg_bw %ukBps peak_bw %ukBps min_freq %llukHz\n",
node->name, dev_name(node_data->qos_dev),
node->avg_bw, node->peak_bw, freq);

@@ -79,41 +79,35 @@ static int imx_icc_node_init_qos(struct icc_provider *provider,
struct icc_node *node)
{
struct imx_icc_node *node_data = node->data;
- const struct imx_icc_node_adj_desc *adj = node_data->desc->adj;
struct device *dev = provider->dev;
- struct device_node *dn = NULL;
struct platform_device *pdev;
+ struct device_node *np = NULL, *dn = NULL;
+ int idx;

- if (adj->main_noc) {
- node_data->qos_dev = dev;
- dev_dbg(dev, "icc node %s[%d] is main noc itself\n",
- node->name, node->id);
- } else {
- dn = of_parse_phandle(dev->of_node, adj->phandle_name, 0);
- if (!dn) {
- dev_warn(dev, "Failed to parse %s\n",
- adj->phandle_name);
- return -ENODEV;
- }
- /* Allow scaling to be disabled on a per-node basis */
- if (!of_device_is_available(dn)) {
- dev_warn(dev, "Missing property %s, skip scaling %s\n",
- adj->phandle_name, node->name);
- of_node_put(dn);
- return 0;
- }
+ for_each_node_with_property(np, "fsl,icc-id") {
+ of_property_read_u32(np, "fsl,icc-id", &idx);
+ if (idx == node_data->desc->id)
+ dn = np;
+ }

- pdev = of_find_device_by_node(dn);
- of_node_put(dn);
- if (!pdev) {
- dev_warn(dev, "node %s[%d] missing device for %pOF\n",
- node->name, node->id, dn);
- return -EPROBE_DEFER;
- }
- node_data->qos_dev = &pdev->dev;
- dev_dbg(dev, "node %s[%d] has device node %pOF\n",
- node->name, node->id, dn);
+ if (!dn)
+ return 0;
+
+ if (!of_device_is_available(dn)) {
+ dev_warn(dev, "%pOF is disabled\n", dn);
+ return 0;
+ }
+
+ pdev = of_find_device_by_node(dn);
+ of_node_put(dn);
+ if (!pdev) {
+ dev_warn(dev, "node %s[%d] missing device for %pOF\n",
+ node->name, node->id, dn);
+ return -EPROBE_DEFER;
}
+ node_data->qos_dev = &pdev->dev;
+ dev_dbg(dev, "node %s[%d] has device node %pOF\n", node->name,
+ node->id, dn);

return dev_pm_qos_add_request(node_data->qos_dev,
&node_data->qos_req,
@@ -151,12 +145,10 @@ static struct icc_node *imx_icc_node_add(struct icc_provider *provider,
node_data->desc = node_desc;
icc_node_add(node, provider);

- if (node_desc->adj) {
- ret = imx_icc_node_init_qos(provider, node);
- if (ret < 0) {
- imx_icc_node_destroy(node);
- return ERR_PTR(ret);
- }
+ ret = imx_icc_node_init_qos(provider, node);
+ if (ret < 0) {
+ imx_icc_node_destroy(node);
+ return ERR_PTR(ret);
}

return node;
@@ -244,7 +236,7 @@ int imx_icc_register(struct platform_device *pdev,
provider->aggregate = icc_std_aggregate;
provider->xlate = of_icc_xlate_onecell;
provider->data = data;
- provider->dev = dev->parent;
+ provider->dev = dev;
platform_set_drvdata(pdev, provider);

ret = icc_provider_add(provider);
--
2.29.2

2021-02-19 16:07:06

by Abel Vesa

[permalink] [raw]
Subject: [RFC 12/19] interconnect: imx: Add imx_icc_get_bw and imx_icc_aggregate functions

The aggregate function will return whatever is the highest
rate for that specific node. The imx_icc_get_bw sets the
initial avg and peak to 0 in order to avoid setting them to
INT_MAX by the interconnect core.

Signed-off-by: Abel Vesa <[email protected]>
---
drivers/interconnect/imx/imx.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/interconnect/imx/imx.c b/drivers/interconnect/imx/imx.c
index db048df80011..5cc1ce55406c 100644
--- a/drivers/interconnect/imx/imx.c
+++ b/drivers/interconnect/imx/imx.c
@@ -25,6 +25,23 @@ struct imx_icc_node {
struct dev_pm_qos_request qos_req;
};

+static int imx_icc_get_bw(struct icc_node *node, u32 *avg, u32 *peak)
+{
+ *avg = 0;
+ *peak = 0;
+
+ return 0;
+}
+
+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 = max(*agg_avg, avg_bw);
+ *agg_peak = max(*agg_peak, peak_bw);
+
+ return 0;
+}
+
static int imx_icc_node_set(struct icc_node *node)
{
struct device *dev = node->provider->dev;
@@ -233,7 +250,8 @@ int imx_icc_register(struct platform_device *pdev,
if (!provider)
return -ENOMEM;
provider->set = imx_icc_set;
- provider->aggregate = icc_std_aggregate;
+ provider->get_bw = imx_icc_get_bw;
+ provider->aggregate = imx_icc_aggregate;
provider->xlate = of_icc_xlate_onecell;
provider->data = data;
provider->dev = dev;
--
2.29.2

2021-02-19 16:07:46

by Abel Vesa

[permalink] [raw]
Subject: [RFC 15/19] arm64: dts: imx8mq: Add all pl301 nodes

Add all the pl301s found on i.MX8MQ, according to the bus diagram.
Each pl301 has its own clock, icc id and opp table. They are probed
by the imx-bus driver.

Signed-off-by: Abel Vesa <[email protected]>
---
arch/arm64/boot/dts/freescale/imx8mq.dtsi | 180 ++++++++++++++++++++++
1 file changed, 180 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
index e30e948648e9..5f9ffa465d6c 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -1447,5 +1447,185 @@ ddr-pmu@3d800000 {
interrupt-parent = <&gic>;
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
};
+
+ pl301_main: pl301@0 {
+ compatible = "fsl,imx8m-nic";
+ clocks = <&clk IMX8MQ_CLK_MAIN_AXI>;
+ operating-points-v2 = <&pl301_main_opp_table>;
+ #interconnect-cells = <0>;
+ fsl,icc-id = <IMX8MQ_ICN_MAIN>;
+
+ pl301_main_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-25M {
+ opp-hz = /bits/ 64 <25000000>;
+ };
+ opp-133M {
+ opp-hz = /bits/ 64 <133333333>;
+ };
+ opp-333M {
+ opp-hz = /bits/ 64 <333333333>;
+ };
+ };
+ };
+
+ pl301_enet: pl301@1 {
+ compatible = "fsl,imx8m-nic";
+ clocks = <&clk IMX8MQ_CLK_ENET_AXI>;
+ operating-points-v2 = <&pl301_enet_opp_table>;
+ #interconnect-cells = <0>;
+ fsl,icc-id = <IMX8MQ_ICN_ENET>;
+
+ pl301_enet_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-25M {
+ opp-hz = /bits/ 64 <25000000>;
+ };
+ opp-266M {
+ opp-hz = /bits/ 64 <266666666>;
+ };
+ };
+ };
+
+ pl301_gpu: pl301@2 {
+ compatible = "fsl,imx8m-nic";
+ clocks = <&clk IMX8MQ_CLK_GPU_AXI>;
+ operating-points-v2 = <&pl301_gpu_opp_table>;
+ #interconnect-cells = <0>;
+ fsl,icc-id = <IMX8MQ_ICN_GPU>;
+
+ pl301_gpu_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-25M {
+ opp-hz = /bits/ 64 <25000000>;
+ };
+ opp-800M {
+ opp-hz = /bits/ 64 <800000000>;
+ };
+ };
+ };
+
+ pl301_dc: pl301@3 {
+ compatible = "fsl,imx8m-nic";
+ clocks = <&clk IMX8MQ_CLK_DISP_AXI>;
+ operating-points-v2 = <&pl301_dc_opp_table>;
+ #interconnect-cells = <0>;
+ fsl,icc-id = <IMX8MQ_ICN_DCSS>;
+
+ pl301_dc_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-25M {
+ opp-hz = /bits/ 64 <25000000>;
+ };
+ opp-800M {
+ opp-hz = /bits/ 64 <800000000>;
+ };
+ };
+ };
+
+ /* PL301_DISPLAY (IPs other than DCSS, inside SUPERMIX) */
+ pl301_display: pl301@4 {
+ compatible = "fsl,imx8m-nic";
+ /* FIXME: don't know which clock yet */
+ clocks = <&clk IMX8MQ_CLK_DUMMY>;
+ operating-points-v2 = <&pl301_display_opp_table>;
+ #interconnect-cells = <0>;
+ fsl,icc-id = <IMX8MQ_ICN_DISPLAY>;
+
+ pl301_display_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-25M {
+ opp-hz = /bits/ 64 <25000000>;
+ };
+ opp-333M {
+ opp-hz = /bits/ 64 <333333333>;
+ };
+ };
+ };
+
+ pl301_audio: pl301@5 {
+ compatible = "fsl,imx8m-nic";
+ clocks = <&clk IMX8MQ_CLK_AUDIO_AHB>;
+ operating-points-v2 = <&pl301_audio_opp_table>;
+ #interconnect-cells = <0>;
+ fsl,icc-id = <IMX8MQ_ICN_AUDIO>;
+
+ pl301_audio_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-25M {
+ opp-hz = /bits/ 64 <25000000>;
+ };
+ opp-500M {
+ opp-hz = /bits/ 64 <500000000>;
+ };
+ };
+ };
+
+ pl301_video: pl301@6 {
+ compatible = "fsl,imx8m-nic";
+ clocks = <&clk IMX8MQ_CLK_VPU_BUS>;
+ operating-points-v2 = <&pl301_video_opp_table>;
+ #interconnect-cells = <0>;
+ fsl,icc-id = <IMX8MQ_ICN_VIDEO>;
+
+ pl301_video_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-25M {
+ opp-hz = /bits/ 64 <25000000>;
+ };
+ opp-500M {
+ opp-hz = /bits/ 64 <500000000>;
+ };
+ };
+ };
+
+ pl301_usb: pl301@7 {
+ compatible = "fsl,imx8m-nic";
+ clocks = <&clk IMX8MQ_CLK_USB_BUS>;
+ operating-points-v2 = <&pl301_usb_opp_table>;
+ #interconnect-cells = <0>;
+ fsl,icc-id = <IMX8MQ_ICN_USB>;
+
+ pl301_usb_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-25M {
+ opp-hz = /bits/ 64 <25000000>;
+ };
+ opp-128M {
+ opp-hz = /bits/ 64 <128000000>;
+ };
+ opp-500M {
+ opp-hz = /bits/ 64 <500000000>;
+ };
+ };
+ };
+
+ pl301_wakeup: pl301@8 {
+ compatible = "fsl,imx8m-nic";
+ /* FIXME: don't know which clock yet */
+ clocks = <&clk IMX8MQ_CLK_DUMMY>;
+ operating-points-v2 = <&pl301_wakeup_opp_table>;
+ #interconnect-cells = <0>;
+ fsl,icc-id = <IMX8MQ_ICN_WAKEUP>;
+
+ pl301_wakeup_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-25M {
+ opp-hz = /bits/ 64 <25000000>;
+ };
+ opp-133M {
+ opp-hz = /bits/ 64 <133333333>;
+ };
+ };
+ };
};
};
--
2.29.2

2021-02-19 16:07:50

by Abel Vesa

[permalink] [raw]
Subject: [RFC 07/19] devfreq: imx8m-ddrc: Add late system sleep PM ops

Seems that, in order to be able to resume from suspend, the dram rate
needs to be the highest one available. Therefore, add the late system
suspend/resume PM ops which set the highest rate on suspend and the
latest one used before suspending on resume.

Signed-off-by: Abel Vesa <[email protected]>
---
drivers/devfreq/imx8m-ddrc.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)

diff --git a/drivers/devfreq/imx8m-ddrc.c b/drivers/devfreq/imx8m-ddrc.c
index 33de83acfd8b..04347dee781b 100644
--- a/drivers/devfreq/imx8m-ddrc.c
+++ b/drivers/devfreq/imx8m-ddrc.c
@@ -72,6 +72,8 @@ struct imx8m_ddrc {
struct clk *dram_alt;
struct clk *dram_apb;

+ unsigned long suspend_rate;
+ unsigned long resume_rate;
int freq_count;
struct imx8m_ddrc_freq freq_table[IMX8M_DDRC_MAX_FREQ_COUNT];
};
@@ -271,6 +273,22 @@ static int imx8m_ddrc_target(struct device *dev, unsigned long *freq, u32 flags)
return ret;
}

+static int imx8m_ddrc_suspend(struct device *dev)
+{
+ struct imx8m_ddrc *priv = dev_get_drvdata(dev);
+
+ priv->resume_rate = clk_get_rate(priv->dram_core);
+
+ return imx8m_ddrc_target(dev, &priv->suspend_rate, 0);
+}
+
+static int imx8m_ddrc_resume(struct device *dev)
+{
+ struct imx8m_ddrc *priv = dev_get_drvdata(dev);
+
+ return imx8m_ddrc_target(dev, &priv->resume_rate, 0);
+}
+
static int imx8m_ddrc_get_cur_freq(struct device *dev, unsigned long *freq)
{
struct imx8m_ddrc *priv = dev_get_drvdata(dev);
@@ -336,6 +354,9 @@ static int imx8m_ddrc_init_freq_info(struct device *dev)

if (dev_pm_opp_add(dev, freq->rate * 250000, 0))
return -ENODEV;
+
+ if (index == 0)
+ priv->suspend_rate = freq->rate * 250000;
}

return 0;
@@ -412,10 +433,15 @@ static const struct of_device_id imx8m_ddrc_of_match[] = {
};
MODULE_DEVICE_TABLE(of, imx8m_ddrc_of_match);

+static const struct dev_pm_ops imx8m_ddrc_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(imx8m_ddrc_suspend, imx8m_ddrc_resume)
+};
+
static struct platform_driver imx8m_ddrc_platdrv = {
.probe = imx8m_ddrc_probe,
.driver = {
.name = "imx8m-ddrc-devfreq",
+ .pm = &imx8m_ddrc_pm_ops,
.of_match_table = of_match_ptr(imx8m_ddrc_of_match),
},
};
--
2.29.2

2021-02-19 16:07:52

by Abel Vesa

[permalink] [raw]
Subject: [RFC 16/19] arm64: dts: imx8mq: Add the interconnect node

The icc node will be probed by the imx8mq interconnect driver.
Will look-up the NoC and all the pl301s (identified by fsl,icc-id property)
and will assign the corresponding icc node to each one of them.
Then, it will register the icc provider.

Signed-off-by: Abel Vesa <[email protected]>
---
arch/arm64/boot/dts/freescale/imx8mq.dtsi | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
index 5f9ffa465d6c..6a64b4bf31f5 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -1627,5 +1627,10 @@ opp-133M {
};
};
};
+
+ icc: interconnect@0 {
+ compatible = "fsl,imx8mq-icc", "fsl,imx8m-icc";
+ #interconnect-cells = <1>;
+ };
};
};
--
2.29.2

2021-02-19 16:08:05

by Abel Vesa

[permalink] [raw]
Subject: [RFC 10/19] interconnect: imx8mq: Add the pl301_per_m and pl301_wakeup nodes and subnodes

According to the bus diagram, there are two more pl301s that need to
be added here. The pl301_per_m which is an intermediary node between
pl301_main and its masters: usdhc1, usdhc2 and sdma. The pl301_wakeup
is an intermediary node between pl301_main and its masters, in this case
all the SAIs.

Signed-off-by: Abel Vesa <[email protected]>
---
drivers/interconnect/imx/imx8mq.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/interconnect/imx/imx8mq.c b/drivers/interconnect/imx/imx8mq.c
index b8c36d668946..010ad3d76286 100644
--- a/drivers/interconnect/imx/imx8mq.c
+++ b/drivers/interconnect/imx/imx8mq.c
@@ -57,14 +57,25 @@ static struct imx_icc_node_desc nodes[] = {
DEFINE_BUS_INTERCONNECT("PL301_ENET", IMX8MQ_ICN_ENET, 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,
IMX8MQ_ICN_NOC, IMX8MQ_ICS_OCRAM),
+ DEFINE_BUS_MASTER("SDMA1", IMX8MQ_ICM_SDMA1, IMX8MQ_ICN_PER_M),
+ DEFINE_BUS_MASTER("USDHC1", IMX8MQ_ICM_USDHC1, IMX8MQ_ICN_PER_M),
+ DEFINE_BUS_MASTER("USDHC2", IMX8MQ_ICM_USDHC2, IMX8MQ_ICN_PER_M),
+ DEFINE_BUS_INTERCONNECT("PL301_PER_M", IMX8MQ_ICN_PER_M,
+ IMX8MQ_ICN_MAIN),
+
+ DEFINE_BUS_MASTER("SAI1", IMX8MQ_ICM_SAI1, IMX8MQ_ICN_WAKEUP),
+ DEFINE_BUS_MASTER("SAI2", IMX8MQ_ICM_SAI2, IMX8MQ_ICN_WAKEUP),
+ DEFINE_BUS_MASTER("SAI3", IMX8MQ_ICM_SAI3, IMX8MQ_ICN_WAKEUP),
+ DEFINE_BUS_MASTER("SAI4", IMX8MQ_ICM_SAI4, IMX8MQ_ICN_WAKEUP),
+ DEFINE_BUS_MASTER("SAI5", IMX8MQ_ICM_SAI5, IMX8MQ_ICN_WAKEUP),
+ DEFINE_BUS_MASTER("SAI6", IMX8MQ_ICM_SAI6, IMX8MQ_ICN_WAKEUP),
+ DEFINE_BUS_INTERCONNECT("PL301_WAKEUP", IMX8MQ_ICN_WAKEUP,
+ IMX8MQ_ICN_MAIN),
};

static int imx8mq_icc_probe(struct platform_device *pdev)
--
2.29.2

2021-02-19 16:08:20

by Abel Vesa

[permalink] [raw]
Subject: [RFC 17/19] arm64: dts: imx8mq: Add interconnect properties to icc consumer nodes

We add all the properties necessary to control the interconnect
based on the required rates all the way from consumers to the dram.
The fsl,icc-rate specifies the minimum required rate the consumer needs
in order to operate.
For now, only the fec, usdhc1 and usdhc2 are added as consumers.

Signed-off-by: Abel Vesa <[email protected]>
---
arch/arm64/boot/dts/freescale/imx8mq.dtsi | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
index 6a64b4bf31f5..43760316052f 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -1112,6 +1112,9 @@ usdhc1: mmc@30b40000 {
"fsl,imx7d-usdhc";
reg = <0x30b40000 0x10000>;
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+ interconnects = <&icc IMX8MQ_ICM_USDHC1 &icc IMX8MQ_ICS_DRAM>;
+ interconnect-names = "path";
+ fsl,icc-rate = <266666>;
clocks = <&clk IMX8MQ_CLK_IPG_ROOT>,
<&clk IMX8MQ_CLK_NAND_USDHC_BUS>,
<&clk IMX8MQ_CLK_USDHC1_ROOT>;
@@ -1127,6 +1130,9 @@ usdhc2: mmc@30b50000 {
"fsl,imx7d-usdhc";
reg = <0x30b50000 0x10000>;
interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+ interconnects = <&icc IMX8MQ_ICM_USDHC2 &icc IMX8MQ_ICS_DRAM>;
+ interconnect-names = "path";
+ fsl,icc-rate = <266666>;
clocks = <&clk IMX8MQ_CLK_IPG_ROOT>,
<&clk IMX8MQ_CLK_NAND_USDHC_BUS>,
<&clk IMX8MQ_CLK_USDHC2_ROOT>;
@@ -1169,6 +1175,9 @@ fec1: ethernet@30be0000 {
<GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+ interconnects = <&icc IMX8MQ_ICM_ENET &icc IMX8MQ_ICS_DRAM>;
+ interconnect-names = "path";
+ fsl,icc-rate = <800000>;
clocks = <&clk IMX8MQ_CLK_ENET1_ROOT>,
<&clk IMX8MQ_CLK_ENET1_ROOT>,
<&clk IMX8MQ_CLK_ENET_TIMER>,
--
2.29.2

2021-02-19 16:08:45

by Abel Vesa

[permalink] [raw]
Subject: [RFC 18/19] net: ethernet: fec_main: Add interconnect support

On probe, if the dts node contains a valid icc path, then look for the
fsl,icc-rate property and get the rate. Also set the icc bandwidth
for that path to the nominal rate needed for fec to function right.
Then enable and disable the path every time the fec is used or not.
This will result in reducing the clock speeds along the icc path
for each pl301 and NoC, but still meet the requirements for all the
other icc consumers.

Signed-off-by: Abel Vesa <[email protected]>
---
drivers/net/ethernet/freescale/fec.h | 3 +++
drivers/net/ethernet/freescale/fec_main.c | 19 +++++++++++++++++++
2 files changed, 22 insertions(+)

diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 0602d5d5d2ee..7611492cb800 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -529,6 +529,9 @@ struct fec_enet_private {
unsigned int num_tx_queues;
unsigned int num_rx_queues;

+ struct icc_path *bus_path;
+ unsigned int bus_rate;
+
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
struct fec_enet_priv_tx_q *tx_queue[FEC_ENET_MAX_TX_QS];
struct fec_enet_priv_rx_q *rx_queue[FEC_ENET_MAX_RX_QS];
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 3db882322b2b..0ed78b390098 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -47,6 +47,7 @@
#include <linux/bitops.h>
#include <linux/io.h>
#include <linux/irq.h>
+#include <linux/interconnect.h>
#include <linux/clk.h>
#include <linux/crc32.h>
#include <linux/platform_device.h>
@@ -3572,6 +3573,18 @@ fec_probe(struct platform_device *pdev)
fep->pdev = pdev;
fep->dev_id = dev_id++;

+ fep->bus_path = devm_of_icc_get(&pdev->dev, "path");
+ if (IS_ERR(fep->bus_path)) {
+ return PTR_ERR(fep->bus_path);
+ } else if (fep->bus_path) {
+ if (of_property_read_u32(np, "fsl,icc-rate", &fep->bus_rate)) {
+ dev_err(&pdev->dev, "icc-rate missing\n");
+ return -EINVAL;
+ }
+
+ icc_set_bw(fep->bus_path, 0, fep->bus_rate);
+ }
+
platform_set_drvdata(pdev, ndev);

if ((of_machine_is_compatible("fsl,imx6q") ||
@@ -3826,6 +3839,8 @@ static int __maybe_unused fec_suspend(struct device *dev)
if (fep->clk_enet_out || fep->reg_phy)
fep->link = 0;

+ icc_disable(fep->bus_path);
+
return 0;
}

@@ -3836,6 +3851,8 @@ static int __maybe_unused fec_resume(struct device *dev)
int ret;
int val;

+ icc_enable(fep->bus_path);
+
if (fep->reg_phy && !(fep->wol_flag & FEC_WOL_FLAG_ENABLE)) {
ret = regulator_enable(fep->reg_phy);
if (ret)
@@ -3884,6 +3901,7 @@ static int __maybe_unused fec_runtime_suspend(struct device *dev)
clk_disable_unprepare(fep->clk_ahb);
clk_disable_unprepare(fep->clk_ipg);

+ icc_disable(fep->bus_path);
return 0;
}

@@ -3893,6 +3911,7 @@ static int __maybe_unused fec_runtime_resume(struct device *dev)
struct fec_enet_private *fep = netdev_priv(ndev);
int ret;

+ icc_enable(fep->bus_path);
ret = clk_prepare_enable(fep->clk_ahb);
if (ret)
return ret;
--
2.29.2

2021-02-19 16:09:30

by Abel Vesa

[permalink] [raw]
Subject: [RFC 13/19] arm64: dts: imx8mq: Add fsl,icc-id property to ddrc node

The fsl,icc-id property here is used to link the icc node
registered by the imx8mq interconnect driver with the ddrc
device.

Signed-off-by: Abel Vesa <[email protected]>
---
arch/arm64/boot/dts/freescale/imx8mq.dtsi | 2 ++
1 file changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
index 17c449e12c2e..ac229a8288cd 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -1433,10 +1433,12 @@ ddrc: memory-controller@3d400000 {
compatible = "fsl,imx8mq-ddrc", "fsl,imx8m-ddrc";
reg = <0x3d400000 0x400000>;
clock-names = "core", "pll", "alt", "apb";
+ fsl,icc-id = <IMX8MQ_ICS_DRAM>;
clocks = <&clk IMX8MQ_CLK_DRAM_CORE>,
<&clk IMX8MQ_DRAM_PLL_OUT>,
<&clk IMX8MQ_CLK_DRAM_ALT>,
<&clk IMX8MQ_CLK_DRAM_APB>;
+ #interconnect-cells = <0>;
};

ddr-pmu@3d800000 {
--
2.29.2

2021-02-19 16:09:30

by Abel Vesa

[permalink] [raw]
Subject: [RFC 14/19] arm64: dts: imx8mq: Add fsl,icc-id to noc node

The fsl,icc-id property here is used to link the icc node
registered by the imx8mq interconnect driver with the noc
device. Remove the fsl,ddrc property since it will not be used
anymore.

Signed-off-by: Abel Vesa <[email protected]>
---
arch/arm64/boot/dts/freescale/imx8mq.dtsi | 4 ++--
scripts/dtc/fdtoverlay | Bin 0 -> 61280 bytes
2 files changed, 2 insertions(+), 2 deletions(-)
create mode 100755 scripts/dtc/fdtoverlay

diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
index ac229a8288cd..e30e948648e9 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -1195,11 +1195,11 @@ fec1: ethernet@30be0000 {
};
};

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

diff --git a/scripts/dtc/fdtoverlay b/scripts/dtc/fdtoverlay
new file mode 100755
index 0000000000000000000000000000000000000000..a2b2746882bf8ceac8d0624a90fc36386cf6ac62
GIT binary patch
literal 61280
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

literal 0
HcmV?d00001

--
2.29.2

2021-02-19 16:09:37

by Abel Vesa

[permalink] [raw]
Subject: [RFC 09/19] interconnect: imx8: Remove the imx_icc_node_adj_desc

Now that the imx generic interconnect doesn't use the
imx_icc_node_adj_desc, we remove it from all the i.MX8M
platform drivers.

Signed-off-by: Abel Vesa <[email protected]>
---
drivers/interconnect/imx/imx.h | 19 ++++-------------
drivers/interconnect/imx/imx8mm.c | 32 +++++++++-------------------
drivers/interconnect/imx/imx8mn.c | 28 +++++++------------------
drivers/interconnect/imx/imx8mq.c | 35 ++++++++++---------------------
4 files changed, 33 insertions(+), 81 deletions(-)

diff --git a/drivers/interconnect/imx/imx.h b/drivers/interconnect/imx/imx.h
index 75da51076c68..5c9f5138f6aa 100644
--- a/drivers/interconnect/imx/imx.h
+++ b/drivers/interconnect/imx/imx.h
@@ -14,15 +14,6 @@

#define IMX_ICC_MAX_LINKS 4

-/*
- * struct imx_icc_node_adj - Describe a dynamic adjustable node
- */
-struct imx_icc_node_adj_desc {
- unsigned int bw_mul, bw_div;
- const char *phandle_name;
- bool main_noc;
-};
-
/*
* struct imx_icc_node - Describe an interconnect node
* @name: name of the node
@@ -35,23 +26,21 @@ struct imx_icc_node_desc {
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, ...) \
+#define DEFINE_BUS_INTERCONNECT(_name, _id, ...) \
{ \
.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, _dest_id)
+ DEFINE_BUS_INTERCONNECT(_name, _id, _dest_id)

-#define DEFINE_BUS_SLAVE(_name, _id, _adj) \
- DEFINE_BUS_INTERCONNECT(_name, _id, _adj)
+#define DEFINE_BUS_SLAVE(_name, _id) \
+ DEFINE_BUS_INTERCONNECT(_name, _id)

int imx_icc_register(struct platform_device *pdev,
struct imx_icc_node_desc *nodes,
diff --git a/drivers/interconnect/imx/imx8mm.c b/drivers/interconnect/imx/imx8mm.c
index 1083490bb391..0c16110bef9d 100644
--- a/drivers/interconnect/imx/imx8mm.c
+++ b/drivers/interconnect/imx/imx8mm.c
@@ -14,18 +14,6 @@

#include "imx.h"

-static const struct imx_icc_node_adj_desc imx8mm_dram_adj = {
- .bw_mul = 1,
- .bw_div = 16,
- .phandle_name = "fsl,ddrc",
-};
-
-static const struct imx_icc_node_adj_desc imx8mm_noc_adj = {
- .bw_mul = 1,
- .bw_div = 16,
- .main_noc = true,
-};
-
/*
* Describe bus masters, slaves and connections between them
*
@@ -33,43 +21,43 @@ static const struct imx_icc_node_adj_desc imx8mm_noc_adj = {
* 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,
+ DEFINE_BUS_INTERCONNECT("NOC", IMX8MM_ICN_NOC,
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_SLAVE("DRAM", IMX8MM_ICS_DRAM),
+ DEFINE_BUS_SLAVE("OCRAM", IMX8MM_ICS_OCRAM),
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),
+ DEFINE_BUS_INTERCONNECT("PL301_VIDEO", IMX8MM_ICN_VIDEO, 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),
+ DEFINE_BUS_INTERCONNECT("PL301_GPU", IMX8MM_ICN_GPU, 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),
+ DEFINE_BUS_INTERCONNECT("PL301_MIPI", IMX8MM_ICN_MIPI, 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),
+ DEFINE_BUS_INTERCONNECT("PL301_HSIO", IMX8MM_ICN_HSIO, 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),
+ DEFINE_BUS_INTERCONNECT("PL301_AUDIO", IMX8MM_ICN_AUDIO, 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),
+ DEFINE_BUS_INTERCONNECT("PL301_ENET", IMX8MM_ICN_ENET, IMX8MM_ICN_MAIN),

/* Other */
DEFINE_BUS_MASTER("SDMA1", IMX8MM_ICM_SDMA1, IMX8MM_ICN_MAIN),
@@ -77,7 +65,7 @@ static struct imx_icc_node_desc nodes[] = {
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,
+ DEFINE_BUS_INTERCONNECT("PL301_MAIN", IMX8MM_ICN_MAIN,
IMX8MM_ICN_NOC, IMX8MM_ICS_OCRAM),
};

diff --git a/drivers/interconnect/imx/imx8mn.c b/drivers/interconnect/imx/imx8mn.c
index ad97e55fd4e5..8d16bd5cf006 100644
--- a/drivers/interconnect/imx/imx8mn.c
+++ b/drivers/interconnect/imx/imx8mn.c
@@ -11,18 +11,6 @@

#include "imx.h"

-static const struct imx_icc_node_adj_desc imx8mn_dram_adj = {
- .bw_mul = 1,
- .bw_div = 4,
- .phandle_name = "fsl,ddrc",
-};
-
-static const struct imx_icc_node_adj_desc imx8mn_noc_adj = {
- .bw_mul = 1,
- .bw_div = 4,
- .main_noc = true,
-};
-
/*
* Describe bus masters, slaves and connections between them
*
@@ -30,23 +18,23 @@ static const struct imx_icc_node_adj_desc imx8mn_noc_adj = {
* 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,
+ DEFINE_BUS_INTERCONNECT("NOC", IMX8MN_ICN_NOC,
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_SLAVE("DRAM", IMX8MN_ICS_DRAM),
+ DEFINE_BUS_SLAVE("OCRAM", IMX8MN_ICS_OCRAM),
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),
+ DEFINE_BUS_INTERCONNECT("PL301_GPU", IMX8MN_ICN_GPU, 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),
+ DEFINE_BUS_INTERCONNECT("PL301_MIPI", IMX8MN_ICN_MIPI, IMX8MN_ICN_NOC),

/* USB goes straight to NOC */
DEFINE_BUS_MASTER("USB", IMX8MN_ICM_USB, IMX8MN_ICN_NOC),
@@ -54,11 +42,11 @@ static struct imx_icc_node_desc nodes[] = {
/* 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),
+ DEFINE_BUS_INTERCONNECT("PL301_AUDIO", IMX8MN_ICN_AUDIO, 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),
+ DEFINE_BUS_INTERCONNECT("PL301_ENET", IMX8MN_ICN_ENET, IMX8MN_ICN_MAIN),

/* Other */
DEFINE_BUS_MASTER("SDMA1", IMX8MN_ICM_SDMA1, IMX8MN_ICN_MAIN),
@@ -66,7 +54,7 @@ static struct imx_icc_node_desc nodes[] = {
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,
+ DEFINE_BUS_INTERCONNECT("PL301_MAIN", IMX8MN_ICN_MAIN
IMX8MN_ICN_NOC, IMX8MN_ICS_OCRAM),
};

diff --git a/drivers/interconnect/imx/imx8mq.c b/drivers/interconnect/imx/imx8mq.c
index d7768d3c6d8a..b8c36d668946 100644
--- a/drivers/interconnect/imx/imx8mq.c
+++ b/drivers/interconnect/imx/imx8mq.c
@@ -12,18 +12,6 @@

#include "imx.h"

-static const struct imx_icc_node_adj_desc imx8mq_dram_adj = {
- .bw_mul = 1,
- .bw_div = 4,
- .phandle_name = "fsl,ddrc",
-};
-
-static const struct imx_icc_node_adj_desc imx8mq_noc_adj = {
- .bw_mul = 1,
- .bw_div = 4,
- .main_noc = true,
-};
-
/*
* Describe bus masters, slaves and connections between them
*
@@ -31,43 +19,42 @@ static const struct imx_icc_node_adj_desc imx8mq_noc_adj = {
* 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_INTERCONNECT("NOC", IMX8MQ_ICN_NOC, 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_SLAVE("DRAM", IMX8MQ_ICS_DRAM),
+ DEFINE_BUS_SLAVE("OCRAM", IMX8MQ_ICS_OCRAM),
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),
+ DEFINE_BUS_INTERCONNECT("PL301_VIDEO", IMX8MQ_ICN_VIDEO, 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),
+ DEFINE_BUS_INTERCONNECT("PL301_GPU", IMX8MQ_ICN_GPU, 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),
+ DEFINE_BUS_INTERCONNECT("PL301_DC", IMX8MQ_ICN_DCSS, 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),
+ DEFINE_BUS_INTERCONNECT("PL301_USB", IMX8MQ_ICN_USB, 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),
+ DEFINE_BUS_INTERCONNECT("PL301_DISPLAY", IMX8MQ_ICN_DISPLAY, 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),
+ DEFINE_BUS_INTERCONNECT("PL301_AUDIO", IMX8MQ_ICN_AUDIO, 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),
+ DEFINE_BUS_INTERCONNECT("PL301_ENET", IMX8MQ_ICN_ENET, IMX8MQ_ICN_MAIN),

/* OTHER */
DEFINE_BUS_MASTER("SDMA1", IMX8MQ_ICM_SDMA1, IMX8MQ_ICN_MAIN),
@@ -76,7 +63,7 @@ static struct imx_icc_node_desc nodes[] = {
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,
+ DEFINE_BUS_INTERCONNECT("PL301_MAIN", IMX8MQ_ICN_MAIN,
IMX8MQ_ICN_NOC, IMX8MQ_ICS_OCRAM),
};

--
2.29.2

2021-02-19 16:11:05

by Abel Vesa

[permalink] [raw]
Subject: [RFC 19/19] mmc: sdhci-esdhc-imx: Add interconnect support

On probe, if the dts node contains a valid icc path, then look for the
fsl,icc-rate property and get the rate. Also set the icc bandwidth
for that path to the nominal rate needed for sdhc to function right.
Then enable and disable the path every time the sdhc is used or not.
This will result in reducing the clock speeds along the icc path
for each pl301 and NoC, but still meet the requirements for all the
other icc consumers.

Signed-off-by: Abel Vesa <[email protected]>
---
drivers/mmc/host/sdhci-esdhc-imx.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index a20459744d21..65c5caf82e0c 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -9,6 +9,7 @@
*/

#include <linux/bitfield.h>
+#include <linux/interconnect.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/delay.h>
@@ -287,6 +288,9 @@ struct pltfm_imx_data {
struct clk *clk_ahb;
struct clk *clk_per;
unsigned int actual_clock;
+ struct icc_path *bus_path;
+ unsigned int bus_rate;
+
enum {
NO_CMD_PENDING, /* no multiblock command pending */
MULTIBLK_IN_PROCESS, /* exact multiblock cmd in process */
@@ -1539,6 +1543,18 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS)
cpu_latency_qos_add_request(&imx_data->pm_qos_req, 0);

+ imx_data->bus_path = devm_of_icc_get(&pdev->dev, "path");
+ if (IS_ERR(imx_data->bus_path)) {
+ return PTR_ERR(imx_data->bus_path);
+ } else if (imx_data->bus_path) {
+ if (of_property_read_u32(pdev->dev.of_node, "fsl,icc-rate", &imx_data->bus_rate)) {
+ dev_err(&pdev->dev, "icc-rate missing\n");
+ return -EINVAL;
+ }
+
+ err = icc_set_bw(imx_data->bus_path, 0, imx_data->bus_rate);
+ }
+
imx_data->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(imx_data->clk_ipg)) {
err = PTR_ERR(imx_data->clk_ipg);
@@ -1720,14 +1736,20 @@ static int sdhci_esdhc_suspend(struct device *dev)

ret = mmc_gpio_set_cd_wake(host->mmc, true);

+ icc_disable(imx_data->bus_path);
+
return ret;
}

static int sdhci_esdhc_resume(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
int ret;

+ icc_enable(imx_data->bus_path);
+
ret = pinctrl_pm_select_default_state(dev);
if (ret)
return ret;
@@ -1779,6 +1801,8 @@ static int sdhci_esdhc_runtime_suspend(struct device *dev)
if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS)
cpu_latency_qos_remove_request(&imx_data->pm_qos_req);

+ icc_disable(imx_data->bus_path);
+
return ret;
}

@@ -1789,6 +1813,8 @@ static int sdhci_esdhc_runtime_resume(struct device *dev)
struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
int err;

+ icc_enable(imx_data->bus_path);
+
if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS)
cpu_latency_qos_add_request(&imx_data->pm_qos_req, 0);

--
2.29.2

2021-02-19 16:33:00

by Abel Vesa

[permalink] [raw]
Subject: Re: [RFC 14/19] arm64: dts: imx8mq: Add fsl,icc-id to noc node

On 21-02-19 18:00:11, Abel Vesa wrote:
> The fsl,icc-id property here is used to link the icc node
> registered by the imx8mq interconnect driver with the noc
> device. Remove the fsl,ddrc property since it will not be used
> anymore.
>
> Signed-off-by: Abel Vesa <[email protected]>
> ---
> arch/arm64/boot/dts/freescale/imx8mq.dtsi | 4 ++--
> scripts/dtc/fdtoverlay | Bin 0 -> 61280 bytes
> 2 files changed, 2 insertions(+), 2 deletions(-)
> create mode 100755 scripts/dtc/fdtoverlay
>
> diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> index ac229a8288cd..e30e948648e9 100644
> --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> @@ -1195,11 +1195,11 @@ fec1: ethernet@30be0000 {
> };
> };
>
> - noc: interconnect@32700000 {
> + noc: noc@32700000 {
> compatible = "fsl,imx8mq-noc", "fsl,imx8m-noc";
> reg = <0x32700000 0x100000>;
> clocks = <&clk IMX8MQ_CLK_NOC>;
> - fsl,ddrc = <&ddrc>;
> + fsl,icc-id = <IMX8MQ_ICN_NOC>;
> #interconnect-cells = <1>;
> operating-points-v2 = <&noc_opp_table>;
>
> diff --git a/scripts/dtc/fdtoverlay b/scripts/dtc/fdtoverlay
> new file mode 100755
> index 0000000000000000000000000000000000000000..a2b2746882bf8ceac8d0624a90fc36386cf6ac62

Agh, "git add ." mistake. Will remove it in the next version.

> GIT binary patch
> literal 61280
> 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
>
> literal 0
> HcmV?d00001
>
> --
> 2.29.2
>

2021-02-21 15:51:54

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [RFC 15/19] arm64: dts: imx8mq: Add all pl301 nodes

On Fri, 19 Feb 2021 at 17:04, Abel Vesa <[email protected]> wrote:
>
> Add all the pl301s found on i.MX8MQ, according to the bus diagram.
> Each pl301 has its own clock, icc id and opp table. They are probed
> by the imx-bus driver.
>
> Signed-off-by: Abel Vesa <[email protected]>
> ---
> arch/arm64/boot/dts/freescale/imx8mq.dtsi | 180 ++++++++++++++++++++++
> 1 file changed, 180 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> index e30e948648e9..5f9ffa465d6c 100644
> --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> @@ -1447,5 +1447,185 @@ ddr-pmu@3d800000 {
> interrupt-parent = <&gic>;
> interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
> };
> +
> + pl301_main: pl301@0 {
> + compatible = "fsl,imx8m-nic";

Does it pass dtc W=1 and dtbs_check without the "reg" property?

Please also name the node in a generic way (see for example DT spec
"2.2.2 Generic Names Recommendation").

Best regards,
Krzysztof

2021-02-22 16:10:55

by Martin Kepplinger

[permalink] [raw]
Subject: Re: [RFC 00/19] Rework support for i.MX8MQ interconnect with devfreq

On 19.02.21 16:59, Abel Vesa wrote:
> This has been on my queue for quite some time now. It is more of a
> proof-of-concept.
>
> This rework is done with the compatibility of future i.MX platforms in
> mind. For example, the i.MX8MP platform has multiple NoCs. This
> patchsets prepares the imx interconnect and imx devfreq for that too.
>
> As of now, none of the drivers involved are being used and there is no
> icc consumer on any off the i.MX platforms.
>
> Basically, the steps taken here are the following:
>
> 1. Make the dram_apb clock "reparantable" from kernel.
> This is needed in order to keep track of the actual parent of the
> dram_apb clock in the kernel clock hierarchy. Note that the actual
> switch is done EL3 (TF-A).
>
> 2. Rework the imx-bus so the actual link between the icc and the
> NoCs or the pl301s is not tightly coupled. This allows us to have
> as many NoCs as necessary but also allows as to use the same driver
> for the pl301s. The pl301s have their own clocks too, so we need to
> reduce their rates too.
>
> 3. Rework the imx8m-ddrc driver. Remove the support for dts defined
> OPPs. The EL3 provides those. So instead of havingi to keep the OPP table in
> both EL3 and kernel in sync, we rely on what the EL3 gives us.
> Also, when the platform suspends, the bus needs to be running at highest
> rate, otherwise there is a chance it might not resume anymore.
> By adding the late system sleep PM ops we can handle that easily.
>
> 4. Rework the imx interconnect driver to use the fsl,icc-id instead
> of the robust imx_icc_node_adj_desc for linking with the target node.
> By adding the fsl,icc-id property to all the NoC and pl301 dts nodes,
> we can link each icc node to their corresponding NoC, pl301 or dram.
> Basically, when the imx interconnect platform specific driver probes,
> it will take each node defined for that platform and look-up the
> corresponding dts node based on the id and add that as the qos device.
>
> 5. Added the fec and usdhc as icc consumers. This is just as an example.
> All the other consumers can be added later. Basically, each consumer
> will add a path to their device node and in the driver will have to
> handle that icc path accordingly.
>

thanks for working on this Abel,

It looks like the icc path requests don't work for me:

when applying this onto v5.11 (without any other workaround in that
area, but some out-of-tree icc-requests like in mxsfb) my rootfs isn't
being mounted anymore. Since you add icc requests to the usdhc driver,
there could be something wrong.

So I revert 19/19 ("mmc: sdhci-esdhc-imx: Add interconnect support") and
then my imx8mq (Librem 5) rootfs system boots, but all frequencies stay
at the minimum (despite the icc request like this:
https://source.puri.sm/martin.kepplinger/linux-next/-/commit/1692de27d1475c53574dd7359c68ba613e0fea10
so I can't use the display).

What could be missing? As I said I'm trying on top of v5.11, (at least I
have the NOC node described:
https://source.puri.sm/martin.kepplinger/linux-next/-/commit/1d74a24c9944d1bf618abdd57d24101368cc8df0
and (with the revert from
https://lore.kernel.org/linux-arm-kernel/20210104120512.gmi2zjz7dzhjussp@fsr-ub1664-175/
devfreq works without your patchset ) Is there anything I'm missing that
is not yet merged in v5.11?

Can I test anything else that would help?

/sys/class/devfreq# cat */cur_freq
133333334
25000000
25641026
25000000
800000000
25000000
0
25000000
25000000
25000000
0

the available freqs look ok (opp table removed from device dts, but you
don't read that anymore anyway):

cat */available_frequencies
133333333 400000000 800000000
25000000 100000000 800000000
25000000 133333333 333333333
25000000 266666666
25000000 800000000
25000000 800000000
25000000 333333333
25000000 500000000
25000000 500000000
25000000 128000000 500000000
25000000 133333333

where ls is:

32700000.noc

3d400000.memory-controller

soc@0:pl301@0

soc@0:pl301@1

soc@0:pl301@2

soc@0:pl301@3

soc@0:pl301@4

soc@0:pl301@5

soc@0:pl301@6

soc@0:pl301@7

soc@0:pl301@8

thanks,
martin

2021-02-23 17:22:24

by Abel Vesa

[permalink] [raw]
Subject: Re: [RFC 00/19] Rework support for i.MX8MQ interconnect with devfreq

On 21-02-22 17:03:13, Martin Kepplinger wrote:
> On 19.02.21 16:59, Abel Vesa wrote:
> > This has been on my queue for quite some time now. It is more of a
> > proof-of-concept.
> >
> > This rework is done with the compatibility of future i.MX platforms in
> > mind. For example, the i.MX8MP platform has multiple NoCs. This
> > patchsets prepares the imx interconnect and imx devfreq for that too.
> >
> > As of now, none of the drivers involved are being used and there is no
> > icc consumer on any off the i.MX platforms.
> >
> > Basically, the steps taken here are the following:
> >
> > 1. Make the dram_apb clock "reparantable" from kernel.
> > This is needed in order to keep track of the actual parent of the
> > dram_apb clock in the kernel clock hierarchy. Note that the actual
> > switch is done EL3 (TF-A).
> >
> > 2. Rework the imx-bus so the actual link between the icc and the
> > NoCs or the pl301s is not tightly coupled. This allows us to have
> > as many NoCs as necessary but also allows as to use the same driver
> > for the pl301s. The pl301s have their own clocks too, so we need to
> > reduce their rates too.
> >
> > 3. Rework the imx8m-ddrc driver. Remove the support for dts defined
> > OPPs. The EL3 provides those. So instead of havingi to keep the OPP table in
> > both EL3 and kernel in sync, we rely on what the EL3 gives us.
> > Also, when the platform suspends, the bus needs to be running at highest
> > rate, otherwise there is a chance it might not resume anymore.
> > By adding the late system sleep PM ops we can handle that easily.
> >
> > 4. Rework the imx interconnect driver to use the fsl,icc-id instead
> > of the robust imx_icc_node_adj_desc for linking with the target node.
> > By adding the fsl,icc-id property to all the NoC and pl301 dts nodes,
> > we can link each icc node to their corresponding NoC, pl301 or dram.
> > Basically, when the imx interconnect platform specific driver probes,
> > it will take each node defined for that platform and look-up the
> > corresponding dts node based on the id and add that as the qos device.
> >
> > 5. Added the fec and usdhc as icc consumers. This is just as an example.
> > All the other consumers can be added later. Basically, each consumer
> > will add a path to their device node and in the driver will have to
> > handle that icc path accordingly.
> >
>
> thanks for working on this Abel,
>
> It looks like the icc path requests don't work for me:
>
> when applying this onto v5.11 (without any other workaround in that area,
> but some out-of-tree icc-requests like in mxsfb) my rootfs isn't being
> mounted anymore. Since you add icc requests to the usdhc driver, there could
> be something wrong.
>
> So I revert 19/19 ("mmc: sdhci-esdhc-imx: Add interconnect support") and
> then my imx8mq (Librem 5) rootfs system boots, but all frequencies stay at
> the minimum (despite the icc request like this:
> https://source.puri.sm/martin.kepplinger/linux-next/-/commit/1692de27d1475c53574dd7359c68ba613e0fea10
> so I can't use the display).
>
> What could be missing? As I said I'm trying on top of v5.11, (at least I
> have the NOC node described:
> https://source.puri.sm/martin.kepplinger/linux-next/-/commit/1d74a24c9944d1bf618abdd57d24101368cc8df0
> and (with the revert from
> https://lore.kernel.org/linux-arm-kernel/20210104120512.gmi2zjz7dzhjussp@fsr-ub1664-175/
> devfreq works without your patchset ) Is there anything I'm missing that is
> not yet merged in v5.11?
>
> Can I test anything else that would help?
>

Sorry about this, I messed up the usdhc change.
I tested mostly with nfs rootfs.

I'll just paste here the things that are missing in order for the USHCs to work.
I'll fold them in the next version of this patch set.

diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
index 43760316052f..90398408b55e 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -1637,6 +1637,25 @@ opp-133M {
};
};

+ pl301_per_m: pl301@9 {
+ compatible = "fsl,imx8m-nic";
+ clocks = <&clk IMX8MQ_CLK_NAND_USDHC_BUS>;
+ operating-points-v2 = <&pl301_per_m_opp_table>;
+ #interconnect-cells = <0>;
+ fsl,icc-id = <IMX8MQ_ICN_PER_M>;
+
+ pl301_per_m_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-25M {
+ opp-hz = /bits/ 64 <25000000>;
+ };
+ opp-133M {
+ opp-hz = /bits/ 64 <133333333>;
+ };
+ };
+ };
+
icc: interconnect@0 {
compatible = "fsl,imx8mq-icc", "fsl,imx8m-icc";
#interconnect-cells = <1>;
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 65c5caf82e0c..cb8d341faf71 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1545,7 +1545,8 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)

imx_data->bus_path = devm_of_icc_get(&pdev->dev, "path");
if (IS_ERR(imx_data->bus_path)) {
- return PTR_ERR(imx_data->bus_path);
+ err = PTR_ERR(imx_data->bus_path);
+ goto free_sdhci;
} else if (imx_data->bus_path) {
if (of_property_read_u32(pdev->dev.of_node, "fsl,icc-rate", &imx_data->bus_rate)) {
dev_err(&pdev->dev, "icc-rate missing\n");

> /sys/class/devfreq# cat */cur_freq
> 133333334
> 25000000
> 25641026
> 25000000
> 800000000
> 25000000
> 0
> 25000000
> 25000000
> 25000000
> 0
>
> the available freqs look ok (opp table removed from device dts, but you
> don't read that anymore anyway):
>
> cat */available_frequencies
> 133333333 400000000 800000000
> 25000000 100000000 800000000
> 25000000 133333333 333333333
> 25000000 266666666
> 25000000 800000000
> 25000000 800000000
> 25000000 333333333
> 25000000 500000000
> 25000000 500000000
> 25000000 128000000 500000000
> 25000000 133333333
>
> where ls is:
>
> 32700000.noc
>
> 3d400000.memory-controller
>
> soc@0:pl301@0
>
> soc@0:pl301@1
>
> soc@0:pl301@2
>
> soc@0:pl301@3
>
> soc@0:pl301@4
>
> soc@0:pl301@5
>
> soc@0:pl301@6
>
> soc@0:pl301@7
>
> soc@0:pl301@8
>
> thanks,

Also, here is this oneliner that allows you to see the transition stats for each node:
for each in `ls -1d /sys/devices/platform/soc@0/*/devfreq/*`; do echo $each; cat $each/trans_stat; done


> martin

2021-02-25 12:18:36

by Martin Kepplinger

[permalink] [raw]
Subject: Re: [RFC 00/19] Rework support for i.MX8MQ interconnect with devfreq

On 23.02.21 18:20, Abel Vesa wrote:
> On 21-02-22 17:03:13, Martin Kepplinger wrote:
>> On 19.02.21 16:59, Abel Vesa wrote:
>>> This has been on my queue for quite some time now. It is more of a
>>> proof-of-concept.
>>>
>>> This rework is done with the compatibility of future i.MX platforms in
>>> mind. For example, the i.MX8MP platform has multiple NoCs. This
>>> patchsets prepares the imx interconnect and imx devfreq for that too.
>>>
>>> As of now, none of the drivers involved are being used and there is no
>>> icc consumer on any off the i.MX platforms.
>>>
>>> Basically, the steps taken here are the following:
>>>
>>> 1. Make the dram_apb clock "reparantable" from kernel.
>>> This is needed in order to keep track of the actual parent of the
>>> dram_apb clock in the kernel clock hierarchy. Note that the actual
>>> switch is done EL3 (TF-A).
>>>
>>> 2. Rework the imx-bus so the actual link between the icc and the
>>> NoCs or the pl301s is not tightly coupled. This allows us to have
>>> as many NoCs as necessary but also allows as to use the same driver
>>> for the pl301s. The pl301s have their own clocks too, so we need to
>>> reduce their rates too.
>>>
>>> 3. Rework the imx8m-ddrc driver. Remove the support for dts defined
>>> OPPs. The EL3 provides those. So instead of havingi to keep the OPP table in
>>> both EL3 and kernel in sync, we rely on what the EL3 gives us.
>>> Also, when the platform suspends, the bus needs to be running at highest
>>> rate, otherwise there is a chance it might not resume anymore.
>>> By adding the late system sleep PM ops we can handle that easily.
>>>
>>> 4. Rework the imx interconnect driver to use the fsl,icc-id instead
>>> of the robust imx_icc_node_adj_desc for linking with the target node.
>>> By adding the fsl,icc-id property to all the NoC and pl301 dts nodes,
>>> we can link each icc node to their corresponding NoC, pl301 or dram.
>>> Basically, when the imx interconnect platform specific driver probes,
>>> it will take each node defined for that platform and look-up the
>>> corresponding dts node based on the id and add that as the qos device.
>>>
>>> 5. Added the fec and usdhc as icc consumers. This is just as an example.
>>> All the other consumers can be added later. Basically, each consumer
>>> will add a path to their device node and in the driver will have to
>>> handle that icc path accordingly.
>>>
>>
>> thanks for working on this Abel,
>>
>> It looks like the icc path requests don't work for me:
>>
>> when applying this onto v5.11 (without any other workaround in that area,
>> but some out-of-tree icc-requests like in mxsfb) my rootfs isn't being
>> mounted anymore. Since you add icc requests to the usdhc driver, there could
>> be something wrong.
>>
>> So I revert 19/19 ("mmc: sdhci-esdhc-imx: Add interconnect support") and
>> then my imx8mq (Librem 5) rootfs system boots, but all frequencies stay at
>> the minimum (despite the icc request like this:
>> https://source.puri.sm/martin.kepplinger/linux-next/-/commit/1692de27d1475c53574dd7359c68ba613e0fea10
>> so I can't use the display).
>>
>> What could be missing? As I said I'm trying on top of v5.11, (at least I
>> have the NOC node described:
>> https://source.puri.sm/martin.kepplinger/linux-next/-/commit/1d74a24c9944d1bf618abdd57d24101368cc8df0
>> and (with the revert from
>> https://lore.kernel.org/linux-arm-kernel/20210104120512.gmi2zjz7dzhjussp@fsr-ub1664-175/
>> devfreq works without your patchset ) Is there anything I'm missing that is
>> not yet merged in v5.11?
>>
>> Can I test anything else that would help?
>>
>
> Sorry about this, I messed up the usdhc change.
> I tested mostly with nfs rootfs.
>
> I'll just paste here the things that are missing in order for the USHCs to work.
> I'll fold them in the next version of this patch set.
>
> diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> index 43760316052f..90398408b55e 100644
> --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> @@ -1637,6 +1637,25 @@ opp-133M {
> };
> };
>
> + pl301_per_m: pl301@9 {
> + compatible = "fsl,imx8m-nic";
> + clocks = <&clk IMX8MQ_CLK_NAND_USDHC_BUS>;
> + operating-points-v2 = <&pl301_per_m_opp_table>;
> + #interconnect-cells = <0>;
> + fsl,icc-id = <IMX8MQ_ICN_PER_M>;
> +
> + pl301_per_m_opp_table: opp-table {
> + compatible = "operating-points-v2";
> +
> + opp-25M {
> + opp-hz = /bits/ 64 <25000000>;
> + };
> + opp-133M {
> + opp-hz = /bits/ 64 <133333333>;
> + };
> + };
> + };
> +
> icc: interconnect@0 {
> compatible = "fsl,imx8mq-icc", "fsl,imx8m-icc";
> #interconnect-cells = <1>;
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 65c5caf82e0c..cb8d341faf71 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -1545,7 +1545,8 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>
> imx_data->bus_path = devm_of_icc_get(&pdev->dev, "path");
> if (IS_ERR(imx_data->bus_path)) {
> - return PTR_ERR(imx_data->bus_path);
> + err = PTR_ERR(imx_data->bus_path);
> + goto free_sdhci;
> } else if (imx_data->bus_path) {
> if (of_property_read_u32(pdev->dev.of_node, "fsl,icc-rate", &imx_data->bus_rate)) {
> dev_err(&pdev->dev, "icc-rate missing\n");
>

when simply booting with this instead of my revert, turning on *all*
kernel debug output, startup stops here:

[ 191.157686] devices_kset: Moving 30b50000.mmc to end of list
[ 191.163388] PM: Moving platform:30b50000.mmc to end of list
[ 191.169003] platform 30b50000.mmc: Retrying from deferred list
[ 191.175305] platform 30b50000.mmc: scheduling asynchronous probe
[ 191.181394] devices_kset: Moving 30b40000.mmc to end of list
[ 191.181493] bus: 'platform': driver_probe_device: matched device
30b50000.mmc with driver sdhci-esdhc-imx
[ 191.187096] PM: Moving platform:30b40000.mmc to end of list
[ 191.196706] bus: 'platform': really_probe: probing driver
sdhci-esdhc-imx with device 30b50000.mmc
[ 191.202270] platform 30b40000.mmc: Retrying from deferred list
[ 191.211361] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl
group usdhc2grp num 9
[ 191.217169] platform 30b40000.mmc: scheduling asynchronous probe
[ 191.225259] pinctrl core: add 9 pinctrl maps

or here:

[ 185.726775] devices_kset: Moving 30b40000.mmc to end of list
[ 185.732476] PM: Moving platform:30b40000.mmc to end of list
[ 185.738090] platform 30b40000.mmc: Retrying from deferred list
[ 185.744453] platform 30b40000.mmc: scheduling asynchronous probe
[ 185.750541] devices_kset: Moving leds to end of list
[ 185.750660] bus: 'platform': driver_probe_device: matched device
30b40000.mmc with driver sdhci-esdhc-imx
[ 185.755556] PM: Moving platform:leds to end of list
[ 185.755575] platform leds: Retrying from deferred list
[ 185.765180] bus: 'platform': really_probe: probing driver
sdhci-esdhc-imx with device 30b40000.mmc
[ 185.770120] bus: 'platform': driver_probe_device: matched device leds
with driver leds-gpio
[ 185.775525] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl
group usdhc1grp num 13
[ 185.784200] bus: 'platform': really_probe: probing driver leds-gpio
with device leds
[ 185.792619] pinctrl core: add 13 pinctrl maps
[ 185.800915] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl
group hubnresetgrp num 2
[ 185.808672] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl
group usdhc1grp100mhz num 13
[ 185.813001] pinctrl core: add 2 pinctrl maps
[ 185.821471] pinctrl core: add 13 pinctrl maps
[ 185.830275] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl
group sdpwrgrp num 2
[ 185.834578] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl
group usdhc1grp200mhz num 13
[ 185.838942] pinctrl core: add 2 pinctrl maps
[ 185.847080] pinctrl core: add 13 pinctrl maps
[ 185.855854] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl
group chargergrp num 2
[ 185.860154] imx8mq-pinctrl 30330000.pinctrl: found group selector 50
for usdhc1grp
[ 185.864480] pinctrl core: add 2 pinctrl maps
[ 185.872864] imx8mq-pinctrl 30330000.pinctrl: found group selector 51
for usdhc1grp100mhz
[ 185.887696] thermal thermal_zone0:
Trip0[type=1,temp=50000]:trend=0,throttle=1
[ 185.892835] imx8mq-pinctrl 30330000.pinctrl: found group selector 52
for usdhc1grp200mhz
[ 185.899966] thermal cooling_device5: cur_state=1
[ 185.908180] sdhci-esdhc-imx 30b40000.mmc: no init pinctrl state
[ 185.908208] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl
group smcgrp num 2

2021-02-26 15:14:26

by Chanwoo Choi

[permalink] [raw]
Subject: Re: [RFC 06/19] devfreq: imx8m-ddrc: Use the opps acquired from EL3

Hi,

On 21. 2. 20. 오전 1:00, Abel Vesa wrote:
> i.MX8M platforms get their dram OPPs from the EL3.
> We don't need to duplicate that in the kernel dram dts node.
> We should just trust the OPPs provided by the EL3.
>
> Signed-off-by: Abel Vesa <[email protected]>
> ---
> drivers/devfreq/imx8m-ddrc.c | 49 ++----------------------------------
> 1 file changed, 2 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/devfreq/imx8m-ddrc.c b/drivers/devfreq/imx8m-ddrc.c
> index 3a6c04ba4f2e..33de83acfd8b 100644
> --- a/drivers/devfreq/imx8m-ddrc.c
> +++ b/drivers/devfreq/imx8m-ddrc.c
> @@ -333,38 +333,9 @@ static int imx8m_ddrc_init_freq_info(struct device *dev)
> if (freq->dram_core_parent_index == 2 &&
> freq->dram_alt_parent_index == 0)
> return -ENODEV;
> - }
> -
> - return 0;
> -}
> -
> -static int imx8m_ddrc_check_opps(struct device *dev)
> -{
> - struct imx8m_ddrc *priv = dev_get_drvdata(dev);
> - struct imx8m_ddrc_freq *freq_info;
> - struct dev_pm_opp *opp;
> - unsigned long freq;
> - int i, opp_count;
> -
> - /* Enumerate DT OPPs and disable those not supported by firmware */
> - opp_count = dev_pm_opp_get_opp_count(dev);
> - if (opp_count < 0)
> - return opp_count;
> - for (i = 0, freq = 0; i < opp_count; ++i, ++freq) {
> - opp = dev_pm_opp_find_freq_ceil(dev, &freq);
> - if (IS_ERR(opp)) {
> - dev_err(dev, "Failed enumerating OPPs: %ld\n",
> - PTR_ERR(opp));
> - return PTR_ERR(opp);
> - }
> - dev_pm_opp_put(opp);
>
> - freq_info = imx8m_ddrc_find_freq(priv, freq);
> - if (!freq_info) {
> - dev_info(dev, "Disable unsupported OPP %luHz %luMT/s\n",
> - freq, DIV_ROUND_CLOSEST(freq, 250000));
> - dev_pm_opp_disable(dev, freq);
> - }
> + if (dev_pm_opp_add(dev, freq->rate * 250000, 0))
> + return -ENODEV;
> }
>
> return 0;
> @@ -372,7 +343,6 @@ static int imx8m_ddrc_check_opps(struct device *dev)
>
> static void imx8m_ddrc_exit(struct device *dev)
> {
> - dev_pm_opp_of_remove_table(dev);
> }
>
> static int imx8m_ddrc_probe(struct platform_device *pdev)
> @@ -419,16 +389,6 @@ static int imx8m_ddrc_probe(struct platform_device *pdev)
> return ret;
> }
>
> - ret = dev_pm_opp_of_add_table(dev);
> - if (ret < 0) {
> - dev_err(dev, "failed to get OPP table\n");
> - return ret;
> - }
> -
> - ret = imx8m_ddrc_check_opps(dev);
> - if (ret < 0)
> - goto err;

In the devfreq_add_device(), if devfreq->profile->freq_table is NULL,
set_freq_table() function fill out the devfreq->profile->freq_table by
using the OPP information.

After this patch, devfreq->profile.freq_table is NULL and there are no
any OPP entries for this device, I think that this driver cannot add
devfreq device without any frequency information. Is it working without
any device frequency information?

> -
> priv->profile.polling_ms = 1000;
> priv->profile.target = imx8m_ddrc_target;
> priv->profile.get_dev_status = imx8m_ddrc_get_dev_status;
> @@ -441,13 +401,8 @@ static int imx8m_ddrc_probe(struct platform_device *pdev)
> 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;
> }
>
>

2021-02-26 15:26:24

by Chanwoo Choi

[permalink] [raw]
Subject: Re: [RFC 07/19] devfreq: imx8m-ddrc: Add late system sleep PM ops



On 21. 2. 20. 오전 1:00, Abel Vesa wrote:
> Seems that, in order to be able to resume from suspend, the dram rate
> needs to be the highest one available. Therefore, add the late system
> suspend/resume PM ops which set the highest rate on suspend and the
> latest one used before suspending on resume.
>
> Signed-off-by: Abel Vesa <[email protected]>
> ---
> drivers/devfreq/imx8m-ddrc.c | 26 ++++++++++++++++++++++++++
> 1 file changed, 26 insertions(+)
>
> diff --git a/drivers/devfreq/imx8m-ddrc.c b/drivers/devfreq/imx8m-ddrc.c
> index 33de83acfd8b..04347dee781b 100644
> --- a/drivers/devfreq/imx8m-ddrc.c
> +++ b/drivers/devfreq/imx8m-ddrc.c
> @@ -72,6 +72,8 @@ struct imx8m_ddrc {
> struct clk *dram_alt;
> struct clk *dram_apb;
>
> + unsigned long suspend_rate;
> + unsigned long resume_rate;
> int freq_count;
> struct imx8m_ddrc_freq freq_table[IMX8M_DDRC_MAX_FREQ_COUNT];
> };
> @@ -271,6 +273,22 @@ static int imx8m_ddrc_target(struct device *dev, unsigned long *freq, u32 flags)
> return ret;
> }
>
> +static int imx8m_ddrc_suspend(struct device *dev)
> +{
> + struct imx8m_ddrc *priv = dev_get_drvdata(dev);
> +
> + priv->resume_rate = clk_get_rate(priv->dram_core);
> +
> + return imx8m_ddrc_target(dev, &priv->suspend_rate, 0);
> +}
> +
> +static int imx8m_ddrc_resume(struct device *dev)
> +{
> + struct imx8m_ddrc *priv = dev_get_drvdata(dev);
> +
> + return imx8m_ddrc_target(dev, &priv->resume_rate, 0);
> +}
> +
> static int imx8m_ddrc_get_cur_freq(struct device *dev, unsigned long *freq)
> {
> struct imx8m_ddrc *priv = dev_get_drvdata(dev);
> @@ -336,6 +354,9 @@ static int imx8m_ddrc_init_freq_info(struct device *dev)
>
> if (dev_pm_opp_add(dev, freq->rate * 250000, 0))
> return -ENODEV;
> +
> + if (index == 0)
> + priv->suspend_rate = freq->rate * 250000;
> }
>
> return 0;
> @@ -412,10 +433,15 @@ static const struct of_device_id imx8m_ddrc_of_match[] = {
> };
> MODULE_DEVICE_TABLE(of, imx8m_ddrc_of_match);
>
> +static const struct dev_pm_ops imx8m_ddrc_pm_ops = {
> + SET_LATE_SYSTEM_SLEEP_PM_OPS(imx8m_ddrc_suspend, imx8m_ddrc_resume)
> +};

Are there any reason to use suspend_late instead of suspend?
Usually, it is enough to change the frequency on normal suspend() step.
The devfreq supports the 'opp-suspend' property[1]. If you keep the OPP
entries on DT, you simply support your goal with 'opp-suspend'.

[1]
https://elixir.bootlin.com/linux/latest/source/Documentation/devicetree/bindings/opp/opp.txt#L156

> +
> static struct platform_driver imx8m_ddrc_platdrv = {
> .probe = imx8m_ddrc_probe,
> .driver = {
> .name = "imx8m-ddrc-devfreq",
> + .pm = &imx8m_ddrc_pm_ops,
> .of_match_table = of_match_ptr(imx8m_ddrc_of_match),
> },
> };
>

2021-02-26 16:56:55

by Chanwoo Choi

[permalink] [raw]
Subject: Re: [RFC 04/19] devfreq: imx-bus: Decouple imx-bus from icc made



On 21. 2. 20. 오전 1:00, Abel Vesa wrote:
> The link between an imx-bus device and its icc id will be done
> through the fsl,icc-id property in each dts node. The imx
> interconnect driver will pick up all the dts nodes that have that
> property defined and will link them to the rightfull icc id.
>
> Signed-off-by: Abel Vesa <[email protected]>
> ---
> drivers/devfreq/imx-bus.c | 40 +++------------------------------------
> 1 file changed, 3 insertions(+), 37 deletions(-)
>
> diff --git a/drivers/devfreq/imx-bus.c b/drivers/devfreq/imx-bus.c
> index 1c0c92d0eb08..9f0df88b29c1 100644
> --- a/drivers/devfreq/imx-bus.c
> +++ b/drivers/devfreq/imx-bus.c
> @@ -65,36 +65,6 @@ static void imx_bus_exit(struct device *dev)
> platform_device_unregister(priv->icc_pdev);
> }
>
> -/* imx_bus_init_icc() - register matching icc provider if required */
> -static int imx_bus_init_icc(struct device *dev)
> -{
> - struct imx_bus *priv = dev_get_drvdata(dev);
> - const char *icc_driver_name;
> -
> - if (!of_get_property(dev->of_node, "#interconnect-cells", 0))
> - return 0;
> - if (!IS_ENABLED(CONFIG_INTERCONNECT_IMX)) {
> - dev_warn(dev, "imx interconnect drivers disabled\n");
> - return 0;
> - }
> -
> - icc_driver_name = of_device_get_match_data(dev);
> - if (!icc_driver_name) {
> - dev_err(dev, "unknown interconnect driver\n");
> - return 0;
> - }
> -
> - priv->icc_pdev = platform_device_register_data(
> - dev, icc_driver_name, -1, 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->icc_pdev));
> - return PTR_ERR(priv->icc_pdev);
> - }
> -
> - return 0;
> -}
> -
> static int imx_bus_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> @@ -144,10 +114,6 @@ static int imx_bus_probe(struct platform_device *pdev)
> goto err;
> }
>
> - ret = imx_bus_init_icc(dev);
> - if (ret)
> - goto err;
> -
> return 0;
>
> err:
> @@ -156,9 +122,9 @@ static int imx_bus_probe(struct platform_device *pdev)
> }
>
> static const struct of_device_id imx_bus_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,imx8mq-noc",},
> + { .compatible = "fsl,imx8mm-noc",},
> + { .compatible = "fsl,imx8mn-noc",},
> { .compatible = "fsl,imx8m-noc", },
> { .compatible = "fsl,imx8m-nic", },
> { /* sentinel */ },
>

For this patch, you need to get the ack of use of new 'fsl,icc-id
property'. IMO, looks good to me.

Acked-by: Chanwoo Choi <[email protected]>


And you must update the DT binding document.
[1] Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml

Thanks,
Chanwoo Choi

2021-02-26 23:08:58

by Chanwoo Choi

[permalink] [raw]
Subject: Re: [RFC 00/19] Rework support for i.MX8MQ interconnect with devfreq

Hi,

You missed sending the patches to linux-pm mailing list.
On next version, please send it linux-pm.

Thanks,
Chanwoo Choi

On 21. 2. 20. 오전 12:59, Abel Vesa wrote:
> This has been on my queue for quite some time now. It is more of a
> proof-of-concept.
>
> This rework is done with the compatibility of future i.MX platforms in
> mind. For example, the i.MX8MP platform has multiple NoCs. This
> patchsets prepares the imx interconnect and imx devfreq for that too.
>
> As of now, none of the drivers involved are being used and there is no
> icc consumer on any off the i.MX platforms.
>
> Basically, the steps taken here are the following:
>
> 1. Make the dram_apb clock "reparantable" from kernel.
> This is needed in order to keep track of the actual parent of the
> dram_apb clock in the kernel clock hierarchy. Note that the actual
> switch is done EL3 (TF-A).
>
> 2. Rework the imx-bus so the actual link between the icc and the
> NoCs or the pl301s is not tightly coupled. This allows us to have
> as many NoCs as necessary but also allows as to use the same driver
> for the pl301s. The pl301s have their own clocks too, so we need to
> reduce their rates too.
>
> 3. Rework the imx8m-ddrc driver. Remove the support for dts defined
> OPPs. The EL3 provides those. So instead of havingi to keep the OPP table in
> both EL3 and kernel in sync, we rely on what the EL3 gives us.
> Also, when the platform suspends, the bus needs to be running at highest
> rate, otherwise there is a chance it might not resume anymore.
> By adding the late system sleep PM ops we can handle that easily.
>
> 4. Rework the imx interconnect driver to use the fsl,icc-id instead
> of the robust imx_icc_node_adj_desc for linking with the target node.
> By adding the fsl,icc-id property to all the NoC and pl301 dts nodes,
> we can link each icc node to their corresponding NoC, pl301 or dram.
> Basically, when the imx interconnect platform specific driver probes,
> it will take each node defined for that platform and look-up the
> corresponding dts node based on the id and add that as the qos device.
>
> 5. Added the fec and usdhc as icc consumers. This is just as an example.
> All the other consumers can be added later. Basically, each consumer
> will add a path to their device node and in the driver will have to
> handle that icc path accordingly.
>
> Abel Vesa (19):
> clk: imx8mq: Replace critical with ignore_unused flag for dram_apb
> clock
> dt-bindings: interconnect: imx8mq: Add missing pl301 and SAI ids
> devfreq: imx-bus: Switch governor to powersave
> devfreq: imx-bus: Decouple imx-bus from icc made
> devfreq: imx8m-ddrc: Change governor to powersave
> devfreq: imx8m-ddrc: Use the opps acquired from EL3
> devfreq: imx8m-ddrc: Add late system sleep PM ops
> interconnect: imx: Switch from imx_icc_node_adj_desc to fsl,icc-id
> node assignment
> interconnect: imx8: Remove the imx_icc_node_adj_desc
> interconnect: imx8mq: Add the pl301_per_m and pl301_wakeup nodes and
> subnodes
> interconnect: imx8mq: Add of_match_table
> interconnect: imx: Add imx_icc_get_bw and imx_icc_aggregate functions
> arm64: dts: imx8mq: Add fsl,icc-id property to ddrc node
> arm64: dts: imx8mq: Add fsl,icc-id to noc node
> arm64: dts: imx8mq: Add all pl301 nodes
> arm64: dts: imx8mq: Add the interconnect node
> arm64: dts: imx8mq: Add interconnect properties to icc consumer nodes
> net: ethernet: fec_main: Add interconnect support
> mmc: sdhci-esdhc-imx: Add interconnect support
>
> arch/arm64/boot/dts/freescale/imx8mq.dtsi | 200 +++++++++++++++++++++-
> drivers/clk/imx/clk-imx8mq.c | 2 +-
> drivers/devfreq/imx-bus.c | 42 +----
> drivers/devfreq/imx8m-ddrc.c | 75 +++-----
> drivers/interconnect/imx/imx.c | 92 +++++-----
> drivers/interconnect/imx/imx.h | 19 +-
> drivers/interconnect/imx/imx8mm.c | 32 ++--
> drivers/interconnect/imx/imx8mn.c | 28 +--
> drivers/interconnect/imx/imx8mq.c | 59 ++++---
> drivers/mmc/host/sdhci-esdhc-imx.c | 26 +++
> drivers/net/ethernet/freescale/fec.h | 3 +
> drivers/net/ethernet/freescale/fec_main.c | 19 ++
> include/dt-bindings/interconnect/imx8mq.h | 9 +
> scripts/dtc/fdtoverlay | Bin 0 -> 61280 bytes
> 14 files changed, 393 insertions(+), 213 deletions(-)
> create mode 100755 scripts/dtc/fdtoverlay
>

2021-03-09 11:47:30

by Abel Vesa

[permalink] [raw]
Subject: Re: [RFC 00/19] Rework support for i.MX8MQ interconnect with devfreq

On 21-02-25 13:13:17, Martin Kepplinger wrote:
> On 23.02.21 18:20, Abel Vesa wrote:
> > On 21-02-22 17:03:13, Martin Kepplinger wrote:
> > > On 19.02.21 16:59, Abel Vesa wrote:
> > > > This has been on my queue for quite some time now. It is more of a
> > > > proof-of-concept.
> > > >
> > > > This rework is done with the compatibility of future i.MX platforms in
> > > > mind. For example, the i.MX8MP platform has multiple NoCs. This
> > > > patchsets prepares the imx interconnect and imx devfreq for that too.
> > > >
> > > > As of now, none of the drivers involved are being used and there is no
> > > > icc consumer on any off the i.MX platforms.
> > > >
> > > > Basically, the steps taken here are the following:
> > > >
> > > > 1. Make the dram_apb clock "reparantable" from kernel.
> > > > This is needed in order to keep track of the actual parent of the
> > > > dram_apb clock in the kernel clock hierarchy. Note that the actual
> > > > switch is done EL3 (TF-A).
> > > >
> > > > 2. Rework the imx-bus so the actual link between the icc and the
> > > > NoCs or the pl301s is not tightly coupled. This allows us to have
> > > > as many NoCs as necessary but also allows as to use the same driver
> > > > for the pl301s. The pl301s have their own clocks too, so we need to
> > > > reduce their rates too.
> > > >
> > > > 3. Rework the imx8m-ddrc driver. Remove the support for dts defined
> > > > OPPs. The EL3 provides those. So instead of havingi to keep the OPP table in
> > > > both EL3 and kernel in sync, we rely on what the EL3 gives us.
> > > > Also, when the platform suspends, the bus needs to be running at highest
> > > > rate, otherwise there is a chance it might not resume anymore.
> > > > By adding the late system sleep PM ops we can handle that easily.
> > > >
> > > > 4. Rework the imx interconnect driver to use the fsl,icc-id instead
> > > > of the robust imx_icc_node_adj_desc for linking with the target node.
> > > > By adding the fsl,icc-id property to all the NoC and pl301 dts nodes,
> > > > we can link each icc node to their corresponding NoC, pl301 or dram.
> > > > Basically, when the imx interconnect platform specific driver probes,
> > > > it will take each node defined for that platform and look-up the
> > > > corresponding dts node based on the id and add that as the qos device.
> > > >
> > > > 5. Added the fec and usdhc as icc consumers. This is just as an example.
> > > > All the other consumers can be added later. Basically, each consumer
> > > > will add a path to their device node and in the driver will have to
> > > > handle that icc path accordingly.
> > > >
> > >
> > > thanks for working on this Abel,
> > >
> > > It looks like the icc path requests don't work for me:
> > >
> > > when applying this onto v5.11 (without any other workaround in that area,
> > > but some out-of-tree icc-requests like in mxsfb) my rootfs isn't being
> > > mounted anymore. Since you add icc requests to the usdhc driver, there could
> > > be something wrong.
> > >
> > > So I revert 19/19 ("mmc: sdhci-esdhc-imx: Add interconnect support") and
> > > then my imx8mq (Librem 5) rootfs system boots, but all frequencies stay at
> > > the minimum (despite the icc request like this:
> > > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fsource.puri.sm%2Fmartin.kepplinger%2Flinux-next%2F-%2Fcommit%2F1692de27d1475c53574dd7359c68ba613e0fea10&amp;data=04%7C01%7Cabel.vesa%40nxp.com%7C9e5a3fe7a3af4aabb84f08d8d986c042%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637498520072719555%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=9ItFarG22Tr%2Bj5MPmZU5xnMc%2B1Sx0o3563L5gdceIi4%3D&amp;reserved=0
> > > so I can't use the display).
> > >
> > > What could be missing? As I said I'm trying on top of v5.11, (at least I
> > > have the NOC node described:
> > > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fsource.puri.sm%2Fmartin.kepplinger%2Flinux-next%2F-%2Fcommit%2F1d74a24c9944d1bf618abdd57d24101368cc8df0&amp;data=04%7C01%7Cabel.vesa%40nxp.com%7C9e5a3fe7a3af4aabb84f08d8d986c042%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637498520072719555%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=dX%2BM7jyyg3SzhtE3Q1QUfVkmbbzg70A57DHndDQ4KcI%3D&amp;reserved=0
> > > and (with the revert from
> > > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Flinux-arm-kernel%2F20210104120512.gmi2zjz7dzhjussp%40fsr-ub1664-175%2F&amp;data=04%7C01%7Cabel.vesa%40nxp.com%7C9e5a3fe7a3af4aabb84f08d8d986c042%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637498520072719555%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=HBVSYJHqLEheNckGyNRf2kDVfVCRoX9zs%2BXO9si8WMw%3D&amp;reserved=0
> > > devfreq works without your patchset ) Is there anything I'm missing that is
> > > not yet merged in v5.11?
> > >
> > > Can I test anything else that would help?
> > >
> >
> > Sorry about this, I messed up the usdhc change.
> > I tested mostly with nfs rootfs.
> >
> > I'll just paste here the things that are missing in order for the USHCs to work.
> > I'll fold them in the next version of this patch set.
> >
> > diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> > index 43760316052f..90398408b55e 100644
> > --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> > +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> > @@ -1637,6 +1637,25 @@ opp-133M {
> > };
> > };
> > + pl301_per_m: pl301@9 {
> > + compatible = "fsl,imx8m-nic";
> > + clocks = <&clk IMX8MQ_CLK_NAND_USDHC_BUS>;
> > + operating-points-v2 = <&pl301_per_m_opp_table>;
> > + #interconnect-cells = <0>;
> > + fsl,icc-id = <IMX8MQ_ICN_PER_M>;
> > +
> > + pl301_per_m_opp_table: opp-table {
> > + compatible = "operating-points-v2";
> > +
> > + opp-25M {
> > + opp-hz = /bits/ 64 <25000000>;
> > + };
> > + opp-133M {
> > + opp-hz = /bits/ 64 <133333333>;
> > + };
> > + };
> > + };
> > +
> > icc: interconnect@0 {
> > compatible = "fsl,imx8mq-icc", "fsl,imx8m-icc";
> > #interconnect-cells = <1>;
> > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> > index 65c5caf82e0c..cb8d341faf71 100644
> > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > @@ -1545,7 +1545,8 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
> > imx_data->bus_path = devm_of_icc_get(&pdev->dev, "path");
> > if (IS_ERR(imx_data->bus_path)) {
> > - return PTR_ERR(imx_data->bus_path);
> > + err = PTR_ERR(imx_data->bus_path);
> > + goto free_sdhci;
> > } else if (imx_data->bus_path) {
> > if (of_property_read_u32(pdev->dev.of_node, "fsl,icc-rate", &imx_data->bus_rate)) {
> > dev_err(&pdev->dev, "icc-rate missing\n");
> >
>
> when simply booting with this instead of my revert, turning on *all* kernel
> debug output, startup stops here:
>
> [ 191.157686] devices_kset: Moving 30b50000.mmc to end of list
> [ 191.163388] PM: Moving platform:30b50000.mmc to end of list
> [ 191.169003] platform 30b50000.mmc: Retrying from deferred list
> [ 191.175305] platform 30b50000.mmc: scheduling asynchronous probe
> [ 191.181394] devices_kset: Moving 30b40000.mmc to end of list
> [ 191.181493] bus: 'platform': driver_probe_device: matched device
> 30b50000.mmc with driver sdhci-esdhc-imx
> [ 191.187096] PM: Moving platform:30b40000.mmc to end of list
> [ 191.196706] bus: 'platform': really_probe: probing driver sdhci-esdhc-imx
> with device 30b50000.mmc
> [ 191.202270] platform 30b40000.mmc: Retrying from deferred list
> [ 191.211361] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl group
> usdhc2grp num 9
> [ 191.217169] platform 30b40000.mmc: scheduling asynchronous probe
> [ 191.225259] pinctrl core: add 9 pinctrl maps
>
> or here:
>
> [ 185.726775] devices_kset: Moving 30b40000.mmc to end of list
> [ 185.732476] PM: Moving platform:30b40000.mmc to end of list
> [ 185.738090] platform 30b40000.mmc: Retrying from deferred list
> [ 185.744453] platform 30b40000.mmc: scheduling asynchronous probe
> [ 185.750541] devices_kset: Moving leds to end of list
> [ 185.750660] bus: 'platform': driver_probe_device: matched device
> 30b40000.mmc with driver sdhci-esdhc-imx
> [ 185.755556] PM: Moving platform:leds to end of list
> [ 185.755575] platform leds: Retrying from deferred list
> [ 185.765180] bus: 'platform': really_probe: probing driver sdhci-esdhc-imx
> with device 30b40000.mmc
> [ 185.770120] bus: 'platform': driver_probe_device: matched device leds
> with driver leds-gpio
> [ 185.775525] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl group
> usdhc1grp num 13
> [ 185.784200] bus: 'platform': really_probe: probing driver leds-gpio with
> device leds
> [ 185.792619] pinctrl core: add 13 pinctrl maps
> [ 185.800915] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl group
> hubnresetgrp num 2
> [ 185.808672] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl group
> usdhc1grp100mhz num 13
> [ 185.813001] pinctrl core: add 2 pinctrl maps
> [ 185.821471] pinctrl core: add 13 pinctrl maps
> [ 185.830275] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl group
> sdpwrgrp num 2
> [ 185.834578] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl group
> usdhc1grp200mhz num 13
> [ 185.838942] pinctrl core: add 2 pinctrl maps
> [ 185.847080] pinctrl core: add 13 pinctrl maps
> [ 185.855854] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl group
> chargergrp num 2
> [ 185.860154] imx8mq-pinctrl 30330000.pinctrl: found group selector 50 for
> usdhc1grp
> [ 185.864480] pinctrl core: add 2 pinctrl maps
> [ 185.872864] imx8mq-pinctrl 30330000.pinctrl: found group selector 51 for
> usdhc1grp100mhz
> [ 185.887696] thermal thermal_zone0:
> Trip0[type=1,temp=50000]:trend=0,throttle=1
> [ 185.892835] imx8mq-pinctrl 30330000.pinctrl: found group selector 52 for
> usdhc1grp200mhz
> [ 185.899966] thermal cooling_device5: cur_state=1
> [ 185.908180] sdhci-esdhc-imx 30b40000.mmc: no init pinctrl state
> [ 185.908208] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl group
> smcgrp num 2
>

Give this one a try:

https://git.kernel.org/pub/scm/linux/kernel/git/abelvesa/linux.git/log/?h=imx8mq/icc_devfreq

2021-03-24 10:26:58

by Martin Kepplinger

[permalink] [raw]
Subject: Re: [RFC 00/19] Rework support for i.MX8MQ interconnect with devfreq

Am Dienstag, dem 09.03.2021 um 13:43 +0200 schrieb Abel Vesa:
> On 21-02-25 13:13:17, Martin Kepplinger wrote:
> > On 23.02.21 18:20, Abel Vesa wrote:
> > > On 21-02-22 17:03:13, Martin Kepplinger wrote:
> > > > On 19.02.21 16:59, Abel Vesa wrote:
> > > > > This has been on my queue for quite some time now. It is more
> > > > > of a
> > > > > proof-of-concept.
> > > > >
> > > > > This rework is done with the compatibility of future i.MX
> > > > > platforms in
> > > > > mind. For example, the i.MX8MP platform has multiple NoCs.
> > > > > This
> > > > > patchsets prepares the imx interconnect and imx devfreq for
> > > > > that too.
> > > > >
> > > > > As of now, none of the drivers involved are being used and
> > > > > there is no
> > > > > icc consumer on any off the i.MX platforms.
> > > > >
> > > > > Basically, the steps taken here are the following:
> > > > >
> > > > > 1. Make the dram_apb clock "reparantable" from kernel.
> > > > > This is needed in order to keep track of the actual parent of
> > > > > the
> > > > > dram_apb clock in the kernel clock hierarchy. Note that the
> > > > > actual
> > > > > switch is done EL3 (TF-A).
> > > > >
> > > > > 2. Rework the imx-bus so the actual link between the icc and
> > > > > the
> > > > > NoCs or the pl301s is not tightly coupled. This allows us to
> > > > > have
> > > > > as many NoCs as necessary but also allows as to use the same
> > > > > driver
> > > > > for the pl301s. The pl301s have their own clocks too, so we
> > > > > need to
> > > > > reduce their rates too.
> > > > >
> > > > > 3. Rework the imx8m-ddrc driver. Remove the support for dts
> > > > > defined
> > > > > OPPs. The EL3 provides those. So instead of havingi to keep
> > > > > the OPP table in
> > > > > both EL3 and kernel in sync, we rely on what the EL3 gives
> > > > > us.
> > > > > Also, when the platform suspends, the bus needs to be running
> > > > > at highest
> > > > > rate, otherwise there is a chance it might not resume
> > > > > anymore.
> > > > > By adding the late system sleep PM ops we can handle that
> > > > > easily.
> > > > >
> > > > > 4. Rework the imx interconnect driver to use the fsl,icc-id
> > > > > instead
> > > > > of the robust imx_icc_node_adj_desc for linking with the
> > > > > target node.
> > > > > By adding the fsl,icc-id property to all the NoC and pl301
> > > > > dts nodes,
> > > > > we can link each icc node to their corresponding NoC, pl301
> > > > > or dram.
> > > > > Basically, when the imx interconnect platform specific driver
> > > > > probes,
> > > > > it will take each node defined for that platform and look-up
> > > > > the
> > > > > corresponding dts node based on the id and add that as the
> > > > > qos device.
> > > > >
> > > > > 5. Added the fec and usdhc as icc consumers. This is just as
> > > > > an example.
> > > > > All the other consumers can be added later. Basically, each
> > > > > consumer
> > > > > will add a path to their device node and in the driver will
> > > > > have to
> > > > > handle that icc path accordingly.
> > > > >
> > > >
> > > > thanks for working on this Abel,
> > > >
> > > > It looks like the icc path requests don't work for me:
> > > >
> > > > when applying this onto v5.11 (without any other workaround in
> > > > that area,
> > > > but some out-of-tree icc-requests like in mxsfb) my rootfs
> > > > isn't being
> > > > mounted anymore. Since you add icc requests to the usdhc
> > > > driver, there could
> > > > be something wrong.
> > > >
> > > > So I revert 19/19 ("mmc: sdhci-esdhc-imx: Add interconnect
> > > > support") and
> > > > then my imx8mq (Librem 5) rootfs system boots, but all
> > > > frequencies stay at
> > > > the minimum (despite the icc request like this:
> > > > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fsource.puri.sm%2Fmartin.kepplinger%2Flinux-next%2F-%2Fcommit%2F1692de27d1475c53574dd7359c68ba613e0fea10&amp;data=04%7C01%7Cabel.vesa%40nxp.com%7C9e5a3fe7a3af4aabb84f08d8d986c042%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637498520072719555%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=9ItFarG22Tr%2Bj5MPmZU5xnMc%2B1Sx0o3563L5gdceIi4%3D&amp;reserved=0
> > > > so I can't use the display).
> > > >
> > > > What could be missing? As I said I'm trying on top of v5.11,
> > > > (at least I
> > > > have the NOC node described:
> > > > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fsource.puri.sm%2Fmartin.kepplinger%2Flinux-next%2F-%2Fcommit%2F1d74a24c9944d1bf618abdd57d24101368cc8df0&amp;data=04%7C01%7Cabel.vesa%40nxp.com%7C9e5a3fe7a3af4aabb84f08d8d986c042%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637498520072719555%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=dX%2BM7jyyg3SzhtE3Q1QUfVkmbbzg70A57DHndDQ4KcI%3D&amp;reserved=0
> > > > and (with the revert from
> > > > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.kernel.org%2Flinux-arm-kernel%2F20210104120512.gmi2zjz7dzhjussp%40fsr-ub1664-175%2F&amp;data=04%7C01%7Cabel.vesa%40nxp.com%7C9e5a3fe7a3af4aabb84f08d8d986c042%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637498520072719555%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=HBVSYJHqLEheNckGyNRf2kDVfVCRoX9zs%2BXO9si8WMw%3D&amp;reserved=0
> > > > devfreq works without your patchset ) Is there anything I'm
> > > > missing that is
> > > > not yet merged in v5.11?
> > > >
> > > > Can I test anything else that would help?
> > > >
> > >
> > > Sorry about this, I messed up the usdhc change.
> > > I tested mostly with nfs rootfs.
> > >
> > > I'll just paste here the things that are missing in order for the
> > > USHCs to work.
> > > I'll fold them in the next version of this patch set.
> > >
> > > diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> > > b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> > > index 43760316052f..90398408b55e 100644
> > > --- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> > > +++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
> > > @@ -1637,6 +1637,25 @@ opp-133M {
> > >                          };
> > >                  };
> > > +               pl301_per_m: pl301@9 {
> > > +                       compatible = "fsl,imx8m-nic";
> > > +                       clocks = <&clk
> > > IMX8MQ_CLK_NAND_USDHC_BUS>;
> > > +                       operating-points-v2 =
> > > <&pl301_per_m_opp_table>;
> > > +                       #interconnect-cells = <0>;
> > > +                       fsl,icc-id = <IMX8MQ_ICN_PER_M>;
> > > +
> > > +                       pl301_per_m_opp_table: opp-table {
> > > +                               compatible = "operating-points-
> > > v2";
> > > +
> > > +                               opp-25M {
> > > +                                       opp-hz = /bits/ 64
> > > <25000000>;
> > > +                               };
> > > +                               opp-133M {
> > > +                                       opp-hz = /bits/ 64
> > > <133333333>;
> > > +                               };
> > > +                       };
> > > +               };
> > > +
> > >                  icc: interconnect@0 {
> > >                          compatible = "fsl,imx8mq-icc",
> > > "fsl,imx8m-icc";
> > >                          #interconnect-cells = <1>;
> > > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c
> > > b/drivers/mmc/host/sdhci-esdhc-imx.c
> > > index 65c5caf82e0c..cb8d341faf71 100644
> > > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > > @@ -1545,7 +1545,8 @@ static int sdhci_esdhc_imx_probe(struct
> > > platform_device *pdev)
> > >          imx_data->bus_path = devm_of_icc_get(&pdev->dev,
> > > "path");
> > >          if (IS_ERR(imx_data->bus_path)) {
> > > -               return PTR_ERR(imx_data->bus_path);
> > > +               err = PTR_ERR(imx_data->bus_path);
> > > +               goto free_sdhci;
> > >          } else if (imx_data->bus_path) {
> > >                  if (of_property_read_u32(pdev->dev.of_node,
> > > "fsl,icc-rate", &imx_data->bus_rate)) {
> > >                          dev_err(&pdev->dev, "icc-rate
> > > missing\n");
> > >
> >
> > when simply booting with this instead of my revert, turning on
> > *all* kernel
> > debug output, startup stops here:
> >
> > [  191.157686] devices_kset: Moving 30b50000.mmc to end of list
> > [  191.163388] PM: Moving platform:30b50000.mmc to end of list
> > [  191.169003] platform 30b50000.mmc: Retrying from deferred list
> > [  191.175305] platform 30b50000.mmc: scheduling asynchronous probe
> > [  191.181394] devices_kset: Moving 30b40000.mmc to end of list
> > [  191.181493] bus: 'platform': driver_probe_device: matched device
> > 30b50000.mmc with driver sdhci-esdhc-imx
> > [  191.187096] PM: Moving platform:30b40000.mmc to end of list
> > [  191.196706] bus: 'platform': really_probe: probing driver sdhci-
> > esdhc-imx
> > with device 30b50000.mmc
> > [  191.202270] platform 30b40000.mmc: Retrying from deferred list
> > [  191.211361] imx8mq-pinctrl 30330000.pinctrl: maps: function
> > pinctrl group
> > usdhc2grp num 9
> > [  191.217169] platform 30b40000.mmc: scheduling asynchronous probe
> > [  191.225259] pinctrl core: add 9 pinctrl maps
> >
> > or here:
> >
> > [  185.726775] devices_kset: Moving 30b40000.mmc to end of list
> > [  185.732476] PM: Moving platform:30b40000.mmc to end of list
> > [  185.738090] platform 30b40000.mmc: Retrying from deferred list
> > [  185.744453] platform 30b40000.mmc: scheduling asynchronous probe
> > [  185.750541] devices_kset: Moving leds to end of list
> > [  185.750660] bus: 'platform': driver_probe_device: matched device
> > 30b40000.mmc with driver sdhci-esdhc-imx
> > [  185.755556] PM: Moving platform:leds to end of list
> > [  185.755575] platform leds: Retrying from deferred list
> > [  185.765180] bus: 'platform': really_probe: probing driver sdhci-
> > esdhc-imx
> > with device 30b40000.mmc
> > [  185.770120] bus: 'platform': driver_probe_device: matched device
> > leds
> > with driver leds-gpio
> > [  185.775525] imx8mq-pinctrl 30330000.pinctrl: maps: function
> > pinctrl group
> > usdhc1grp num 13
> > [  185.784200] bus: 'platform': really_probe: probing driver leds-
> > gpio with
> > device leds
> > [  185.792619] pinctrl core: add 13 pinctrl maps
> > [  185.800915] imx8mq-pinctrl 30330000.pinctrl: maps: function
> > pinctrl group
> > hubnresetgrp num 2
> > [  185.808672] imx8mq-pinctrl 30330000.pinctrl: maps: function
> > pinctrl group
> > usdhc1grp100mhz num 13
> > [  185.813001] pinctrl core: add 2 pinctrl maps
> > [  185.821471] pinctrl core: add 13 pinctrl maps
> > [  185.830275] imx8mq-pinctrl 30330000.pinctrl: maps: function
> > pinctrl group
> > sdpwrgrp num 2
> > [  185.834578] imx8mq-pinctrl 30330000.pinctrl: maps: function
> > pinctrl group
> > usdhc1grp200mhz num 13
> > [  185.838942] pinctrl core: add 2 pinctrl maps
> > [  185.847080] pinctrl core: add 13 pinctrl maps
> > [  185.855854] imx8mq-pinctrl 30330000.pinctrl: maps: function
> > pinctrl group
> > chargergrp num 2
> > [  185.860154] imx8mq-pinctrl 30330000.pinctrl: found group
> > selector 50 for
> > usdhc1grp
> > [  185.864480] pinctrl core: add 2 pinctrl maps
> > [  185.872864] imx8mq-pinctrl 30330000.pinctrl: found group
> > selector 51 for
> > usdhc1grp100mhz
> > [  185.887696] thermal thermal_zone0:
> > Trip0[type=1,temp=50000]:trend=0,throttle=1
> > [  185.892835] imx8mq-pinctrl 30330000.pinctrl: found group
> > selector 52 for
> > usdhc1grp200mhz
> > [  185.899966] thermal cooling_device5: cur_state=1
> > [  185.908180] sdhci-esdhc-imx 30b40000.mmc: no init pinctrl state
> > [  185.908208] imx8mq-pinctrl 30330000.pinctrl: maps: function
> > pinctrl group
> > smcgrp num 2
> >
>
> Give this one a try:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/abelvesa/linux.git/log/?h=imx8mq/icc_devfreq
>

sorry this took a while. with this patchset booting still stops here
for me:

[ 1.360301] i2c i2c-1: IMX I2C adapter registered
[ 1.382796] i2c i2c-2: IMX I2C adapter registered
[ 1.403487] i2c i2c-3: IMX I2C adapter registered
[ 1.420996] led-backlight backlight-dsi: Not enough levels defined
[ 1.442857] etnaviv etnaviv: bound 38000000.gpu (ops gpu_ops)
[ 1.448713] etnaviv-gpu 38000000.gpu: model: GC7000, revision: 6214
[ 1.457320] [drm] Initialized etnaviv 1.3.0 20151214 for etnaviv on
minor 0
[ 1.471080] imx-cpufreq-dt imx-cpufreq-dt: cpu speed grade 3 mkt
segment 0 supported-hw 0x8 0x1

and *all* output enabled:



[ 191.116154] thermal thermal_zone0:
Trip0[type=1,temp=50000]:trend=0,throttle=1
[ 191.116164] thermal cooling_device5: cur_state=0
[ 191.116171] thermal cooling_device5: old_target=-1, target=1
[ 191.116182] thermal cooling_device5: zone0->target=1
[ 191.116210] thermal cooling_device5: set to state 1
[ 191.116228] thermal thermal_zone0:
Trip1[type=1,temp=60000]:trend=0,throttle=0
[ 191.116241] thermal cooling_device0: cur_state=0
[ 191.116249] thermal cooling_device0: old_target=-1, target=-1
[ 191.116263] thermal cooling_device1: cur_state=0
[ 191.116268] thermal cooling_device1: old_target=-1, target=-1
[ 191.116281] thermal cooling_device2: cur_state=0
[ 191.116290] thermal cooling_device2: old_target=-1, target=-1
[ 191.116302] thermal cooling_device3: cur_state=0
[ 191.116310] thermal cooling_device3: old_target=-1, target=-1
[ 191.116322] cpufreq: initialization complete
[ 191.116343] cpu cpu1: cpufreq_add_dev: adding CPU1
[ 191.116353] cpufreq: cpufreq_online: bringing CPU1 online
[ 191.116373] cpu cpu2: cpufreq_add_dev: adding CPU2
[ 191.116382] cpufreq: cpufreq_online: bringing CPU2 online
[ 191.116396] cpu cpu3: cpufreq_add_dev: adding CPU3
[ 191.116405] cpufreq: cpufreq_online: bringing CPU3 online
[ 191.116433] cpufreq: driver cpufreq-dt up and running
[ 191.116447] driver: 'cpufreq-dt': driver_bound: bound to device
'cpufreq-dt'
[ 191.116479] kobject: 'cpufreq-dt' ((____ptrval____)):
kobject_uevent_env
[ 191.116497] kobject: 'cpufreq-dt' ((____ptrval____)):
fill_kobj_path: path = '/devices/platform/imx-cpufreq-dt/cpufreq-dt'
[ 191.116518] bus: 'platform': really_probe: bound device cpufreq-dt
to driver cpufreq-dt
[ 191.116558] driver: 'imx-cpufreq-dt': driver_bound: bound to device
'imx-cpufreq-dt'
[ 191.116573] kobject: 'imx-cpufreq-dt' ((____ptrval____)):
kobject_uevent_env
[ 191.116585] kobject: 'imx-cpufreq-dt' ((____ptrval____)):
fill_kobj_path: path = '/devices/platform/imx-cpufreq-dt'
[ 191.116603] bus: 'platform': really_probe: bound device imx-cpufreq-
dt to driver imx-cpufreq-dt
[ 191.116624] devices_kset: Moving leds to end of list
[ 191.116637] PM: Moving platform:leds to end of list
[ 191.116650] platform leds: Retrying from deferred list
[ 191.116997] bus: 'platform': driver_probe_device: matched device
leds with driver leds-gpio
[ 191.117022] bus: 'platform': really_probe: probing driver leds-gpio
with device leds
[ 191.117146] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl
group hubnresetgrp num 2
[ 191.117164] pinctrl core: add 2 pinctrl maps
[ 191.117247] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl
group sdpwrgrp num 2
[ 191.117261] pinctrl core: add 2 pinctrl maps
[ 191.117283] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl
group chargergrp num 2
[ 191.117299] pinctrl core: add 2 pinctrl maps
[ 191.117321] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl
group smcgrp num 2
[ 191.117337] pinctrl core: add 2 pinctrl maps
[ 191.117362] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl
group gnssgrp num 2
[ 191.117383] pinctrl core: add 2 pinctrl maps
[ 191.117445] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl
group wwanpwrgrp num 2
[ 191.117459] pinctrl core: add 2 pinctrl maps
[ 191.117486] imx8mq-pinctrl 30330000.pinctrl: maps: function pinctrl
group wwangrp num 4
[ 191.117497] pinctrl core: add 4 pinctrl maps
[ 191.117562] imx8mq-pinctrl 30330000.pinctrl: found group selector 22
for hubnresetgrp
[ 191.117604] imx8mq-pinctrl 30330000.pinctrl: found group selector 41
for sdpwrgrp
[ 191.117617] imx8mq-pinctrl 30330000.pinctrl: found group selector 4
for chargergrp
[ 191.117658] imx8mq-pinctrl 30330000.pinctrl: found group selector 42
for smcgrp
[ 191.117671] imx8mq-pinctrl 30330000.pinctrl: found group selector 16
for gnssgrp
[ 191.117707] imx8mq-pinctrl 30330000.pinctrl: found group selector 59
for wwanpwrgrp
[ 191.117747] imx8mq-pinctrl 30330000.pinctrl: found group selector 58
for wwangrp
[ 191.117789] leds-gpio leds: no init pinctrl state
[ 191.117799] imx8mq-pinctrl 30330000.pinctrl: request pin 22
(MX8MQ_IOMUXC_GPIO1_IO12) for leds
[ 191.117814] imx8mq-pinctrl 30330000.pinctrl: enable function pinctrl
group hubnresetgrp
[ 191.117831] imx8mq-pinctrl 30330000.pinctrl: write: offset 0x58 val
0x0
[ 191.117843] imx8mq-pinctrl 30330000.pinctrl: pinconf set pin
MX8MQ_IOMUXC_GPIO1_IO12
[ 191.117852] imx8mq-pinctrl 30330000.pinctrl: write: offset 0x2c0 val
0x83
[ 191.117860] imx8mq-pinctrl 30330000.pinctrl: request pin 13
(MX8MQ_IOMUXC_GPIO1_IO03) for leds
[ 191.117871] imx8mq-pinctrl 30330000.pinctrl: enable function pinctrl
group sdpwrgrp
[ 191.117881] imx8mq-pinctrl 30330000.pinctrl: write: offset 0x34 val
0x0
[ 191.117888] imx8mq-pinctrl 30330000.pinctrl: pinconf set pin
MX8MQ_IOMUXC_GPIO1_IO03
[ 191.117899] imx8mq-pinctrl 30330000.pinctrl: write: offset 0x29c val
0x83
[ 191.117910] imx8mq-pinctrl 30330000.pinctrl: request pin 63
(MX8MQ_IOMUXC_NAND_CE1_B) for leds
[ 191.117921] imx8mq-pinctrl 30330000.pinctrl: enable function pinctrl
group chargergrp
[ 191.117930] imx8mq-pinctrl 30330000.pinctrl: write: offset 0xfc val
0x5
[ 191.117936] imx8mq-pinctrl 30330000.pinctrl: pinconf set pin
MX8MQ_IOMUXC_NAND_CE1_B
[ 191.117947] imx8mq-pinctrl 30330000.pinctrl: write: offset 0x364 val
0x3
[ 191.117955] imx8mq-pinctrl 30330000.pinctrl: request pin 16
(MX8MQ_IOMUXC_GPIO1_IO06) for leds
[ 191.117964] imx8mq-pinctrl 30330000.pinctrl: enable function pinctrl
group smcgrp
[ 191.117976] imx8mq-pinctrl 30330000.pinctrl: write: offset 0x40 val
0x0
[ 191.117984] imx8mq-pinctrl 30330000.pinctrl: pinconf set pin
MX8MQ_IOMUXC_GPIO1_IO06
[ 191.117992] imx8mq-pinctrl 30330000.pinctrl: write: offset 0x2a8 val
0x83
[ 191.118001] imx8mq-pinctrl 30330000.pinctrl: request pin 18
(MX8MQ_IOMUXC_GPIO1_IO08) for leds
[ 191.118011] imx8mq-pinctrl 30330000.pinctrl: enable function pinctrl
group gnssgrp
[ 191.118021] imx8mq-pinctrl 30330000.pinctrl: write: offset 0x48 val
0x0
[ 191.118029] imx8mq-pinctrl 30330000.pinctrl: pinconf set pin
MX8MQ_IOMUXC_GPIO1_IO08
[ 191.118037] imx8mq-pinctrl 30330000.pinctrl: write: offset 0x2b0 val
0x83
[ 191.118048] imx8mq-pinctrl 30330000.pinctrl: request pin 79
(MX8MQ_IOMUXC_NAND_WP_B) for leds
[ 191.118059] imx8mq-pinctrl 30330000.pinctrl: enable function pinctrl
group wwanpwrgrp
[ 191.118070] imx8mq-pinctrl 30330000.pinctrl: write: offset 0x13c val
0x5
[ 191.118078] imx8mq-pinctrl 30330000.pinctrl: pinconf set pin
MX8MQ_IOMUXC_NAND_WP_B
[ 191.118084] imx8mq-pinctrl 30330000.pinctrl: write: offset 0x3a4 val
0x83
[ 191.118096] imx8mq-pinctrl 30330000.pinctrl: request pin 62
(MX8MQ_IOMUXC_NAND_CE0_B) for leds
[ 191.118106] imx8mq-pinctrl 30330000.pinctrl: request pin 77
(MX8MQ_IOMUXC_NAND_READY_B) for leds
[ 191.118113] imx8mq-pinctrl 30330000.pinctrl: request pin 74
(MX8MQ_IOMUXC_NAND_DATA07) for leds
[ 191.118125] imx8mq-pinctrl 30330000.pinctrl: enable function pinctrl
group wwangrp
[ 191.118134] imx8mq-pinctrl 30330000.pinctrl: write: offset 0xf8 val
0x5
[ 191.118144] imx8mq-pinctrl 30330000.pinctrl: write: offset 0x134 val
0x5
[ 191.118154] imx8mq-pinctrl 30330000.pinctrl: write: offset 0x128 val
0x5
[ 191.118160] imx8mq-pinctrl 30330000.pinctrl: pinconf set pin
MX8MQ_IOMUXC_NAND_CE0_B
[ 191.118170] imx8mq-pinctrl 30330000.pinctrl: write: offset 0x360 val
0x83
[ 191.118178] imx8mq-pinctrl 30330000.pinctrl: pinconf set pin
MX8MQ_IOMUXC_NAND_READY_B
[ 191.118185] imx8mq-pinctrl 30330000.pinctrl: write: offset 0x39c val
0x83
[ 191.118194] imx8mq-pinctrl 30330000.pinctrl: pinconf set pin
MX8MQ_IOMUXC_NAND_DATA07
[ 191.118205] imx8mq-pinctrl 30330000.pinctrl: write: offset 0x390 val
0x83
[ 191.118217] leds-gpio leds: no sleep pinctrl state
[ 191.118226] leds-gpio leds: no idle pinctrl state
[ 191.118252] leds-gpio leds: device is not dma coherent
[ 191.118265] leds-gpio leds: device is not behind an iommu
[ 191.118515] of_get_named_gpiod_flags: parsed 'gpios' property of
node '/leds/chg-en[0]' - status (0)
[ 191.118599] imx8mq-pinctrl 30330000.pinctrl: request pin 63
(MX8MQ_IOMUXC_NAND_CE1_B) for 30220000.gpio:66
[ 191.118654] gpio gpiochip2: Persistence not supported for GPIO 2
[ 191.118674] gpio-66 (?): no flags found for gpios
[ 191.118827] device: 'chg_en': device_add
[ 191.118846] kobject: 'leds' ((____ptrval____)):
kobject_add_internal: parent: 'leds', set: '(null)'
[ 191.118870] kobject: 'chg_en' ((____ptrval____)):
kobject_add_internal: parent: 'leds', set: 'devices'
[ 191.118963] PM: Adding info for No Bus:chg_en
[ 191.118972] kobject: 'chg_en' ((____ptrval____)): kobject_uevent_env
[ 191.118992] kobject: 'chg_en' ((____ptrval____)): fill_kobj_path:
path = '/devices/platform/leds/leds/chg_en'
[ 191.119049] leds-gpio leds: Registered led device: (null)
[ 191.119098] of_get_named_gpiod_flags: parsed 'gpios' property of
node '/leds/flash-strobe[0]' - status (0)
[ 191.119125] imx8mq-pinctrl 30330000.pinctrl: request pin 31
(MX8MQ_IOMUXC_ENET_TD0) for 30200000.gpio:21
[ 191.119144] gpio gpiochip0: Persistence not supported for GPIO 21
[ 191.119154] gpio-21 (?): no flags found for gpios
[ 191.119215] device: 'flash_strobe': device_add
[ 191.119223] kobject: 'flash_strobe' ((____ptrval____)):
kobject_add_internal: parent: 'leds', set: 'devices'
[ 191.119286] PM: Adding info for No Bus:flash_strobe
[ 191.119296] kobject: 'flash_strobe' ((____ptrval____)):
kobject_uevent_env
[ 191.119314] kobject: 'flash_strobe' ((____ptrval____)):
fill_kobj_path: path = '/devices/platform/leds/leds/flash_strobe'
[ 191.119412] leds-gpio leds: Registered led device: (null)
[ 191.119433] of_get_named_gpiod_flags: parsed 'gpios' property of
node '/leds/hub-nreset[0]' - status (0)
[ 191.119452] imx8mq-pinctrl 30330000.pinctrl: request pin 22
(MX8MQ_IOMUXC_GPIO1_IO12) for 30200000.gpio:12
[ 191.119465] gpio gpiochip0: Persistence not supported for GPIO 12
[ 191.119472] gpio-12 (?): no flags found for gpios
[ 191.119507] device: 'hub_nreset': device_add
[ 191.119515] kobject: 'hub_nreset' ((____ptrval____)):
kobject_add_internal: parent: 'leds', set: 'devices'
[ 191.119560] PM: Adding info for No Bus:hub_nreset
[ 191.119568] kobject: 'hub_nreset' ((____ptrval____)):
kobject_uevent_env
[ 191.119591] kobject: 'hub_nreset' ((____ptrval____)):
fill_kobj_path: path = '/devices/platform/leds/leds/hub_nreset'
[ 191.119609] leds-gpio leds: Registered led device: (null)
[ 191.119638] of_get_named_gpiod_flags: parsed 'gpios' property of
node '/leds/sd-en[0]' - status (0)
[ 191.119657] imx8mq-pinctrl 30330000.pinctrl: request pin 13
(MX8MQ_IOMUXC_GPIO1_IO03) for 30200000.gpio:3
[ 191.119667] gpio gpiochip0: Persistence not supported for GPIO 3
[ 191.119675] gpio-3 (?): no flags found for gpios
[ 191.119715] device: 'sd_en': device_add
[ 191.119723] kobject: 'sd_en' ((____ptrval____)):
kobject_add_internal: parent: 'leds', set: 'devices'
[ 191.119787] PM: Adding info for No Bus:sd_en
[ 191.119794] kobject: 'sd_en' ((____ptrval____)): kobject_uevent_env
[ 191.119822] kobject: 'sd_en' ((____ptrval____)): fill_kobj_path:
path = '/devices/platform/leds/leds/sd_en'
[ 191.119838] leds-gpio leds: Registered led device: (null)
[ 191.119861] of_get_named_gpiod_flags: parsed 'gpios' property of
node '/leds/gnss-nreset[0]' - status (0)
[ 191.119882] imx8mq-pinctrl 30330000.pinctrl: request pin 18
(MX8MQ_IOMUXC_GPIO1_IO08) for 30200000.gpio:8
[ 191.119893] gpio gpiochip0: Persistence not supported for GPIO 8
[ 191.119903] gpio-8 (?): no flags found for gpios
[ 191.119941] device: 'gnss_nreset': device_add
[ 191.119947] kobject: 'gnss_nreset' ((____ptrval____)):
kobject_add_internal: parent: 'leds', set: 'devices'
[ 191.120017] PM: Adding info for No Bus:gnss_nreset
[ 191.120023] kobject: 'gnss_nreset' ((____ptrval____)):
kobject_uevent_env
[ 191.120067] kobject: 'gnss_nreset' ((____ptrval____)):
fill_kobj_path: path = '/devices/platform/leds/leds/gnss_nreset'
[ 191.120084] leds-gpio leds: Registered led device: (null)
[ 191.120108] of_get_named_gpiod_flags: parsed 'gpios' property of
node '/leds/smc-en[0]' - status (0)
[ 191.120131] imx8mq-pinctrl 30330000.pinctrl: request pin 16
(MX8MQ_IOMUXC_GPIO1_IO06) for 30200000.gpio:6
[ 191.120142] gpio gpiochip0: Persistence not supported for GPIO 6
[ 191.120148] gpio-6 (?): no flags found for gpios
[ 191.120185] device: 'smc_en': device_add
[ 191.120191] kobject: 'smc_en' ((____ptrval____)):
kobject_add_internal: parent: 'leds', set: 'devices'
[ 191.120289] PM: Adding info for No Bus:smc_en
[ 191.120298] kobject: 'smc_en' ((____ptrval____)): kobject_uevent_env
[ 191.120316] kobject: 'smc_en' ((____ptrval____)): fill_kobj_path:
path = '/devices/platform/leds/leds/smc_en'
[ 191.120337] leds-gpio leds: Registered led device: (null)
[ 191.120359] of_get_named_gpiod_flags: parsed 'gpios' property of
node '/leds/wwan-en[0]' - status (0)
[ 191.120377] imx8mq-pinctrl 30330000.pinctrl: request pin 79
(MX8MQ_IOMUXC_NAND_WP_B) for 30220000.gpio:82
[ 191.120390] gpio gpiochip2: Persistence not supported for GPIO 18
[ 191.120398] gpio-82 (?): no flags found for gpios
[ 191.120433] device: 'wwan_en': device_add
[ 191.120443] kobject: 'wwan_en' ((____ptrval____)):
kobject_add_internal: parent: 'leds', set: 'devices'
[ 191.120491] PM: Adding info for No Bus:wwan_en
[ 191.120500] kobject: 'wwan_en' ((____ptrval____)):
kobject_uevent_env
[ 191.120516] kobject: 'wwan_en' ((____ptrval____)): fill_kobj_path:
path = '/devices/platform/leds/leds/wwan_en'
[ 191.120534] leds-gpio leds: Registered led device: (null)
[ 191.120566] of_get_named_gpiod_flags: parsed 'gpios' property of
node '/leds/wwan-nreset[0]' - status (0)
[ 191.120584] imx8mq-pinctrl 30330000.pinctrl: request pin 62
(MX8MQ_IOMUXC_NAND_CE0_B) for 30220000.gpio:65
[ 191.120596] gpio gpiochip2: Persistence not supported for GPIO 1
[ 191.120603] gpio-65 (?): no flags found for gpios
[ 191.120644] device: 'wwan_nreset': device_add
[ 191.120652] kobject: 'wwan_nreset' ((____ptrval____)):
kobject_add_internal: parent: 'leds', set: 'devices'
[ 191.120702] PM: Adding info for No Bus:wwan_nreset
[ 191.120708] kobject: 'wwan_nreset' ((____ptrval____)):
kobject_uevent_env
[ 191.120732] kobject: 'wwan_nreset' ((____ptrval____)):
fill_kobj_path: path = '/devices/platform/leds/leds/wwan_nreset'
[ 191.120749] leds-gpio leds: Registered led device: (null)
[ 191.120771] of_get_named_gpiod_flags: parsed 'gpios' property of
node '/leds/wwan-disable[0]' - status (0)
[ 191.120789] imx8mq-pinctrl 30330000.pinctrl: request pin 77
(MX8MQ_IOMUXC_NAND_READY_B) for 30220000.gpio:80
[ 191.120803] gpio gpiochip2: Persistence not supported for GPIO 16
[ 191.120812] gpio-80 (?): no flags found for gpios
[ 191.120855] device: 'wwan_disable': device_add
[ 191.120861] kobject: 'wwan_disable' ((____ptrval____)):
kobject_add_internal: parent: 'leds', set: 'devices'
[ 191.120928] PM: Adding info for No Bus:wwan_disable
[ 191.120935] kobject: 'wwan_disable' ((____ptrval____)):
kobject_uevent_env
[ 191.120949] kobject: 'wwan_disable' ((____ptrval____)):
fill_kobj_path: path = '/devices/platform/leds/leds/wwan_disable'
[ 191.120973] leds-gpio leds: Registered led device: (null)
[ 191.120992] of_get_named_gpiod_flags: parsed 'gpios' property of
node '/leds/wwan-dis2[0]' - status (0)
[ 191.121012] imx8mq-pinctrl 30330000.pinctrl: request pin 74
(MX8MQ_IOMUXC_NAND_DATA07) for 30220000.gpio:77
[ 191.121024] gpio gpiochip2: Persistence not supported for GPIO 13
[ 191.121031] gpio-77 (?): no flags found for gpios
[ 191.121073] device: 'wwan_dis2': device_add
[ 191.121079] kobject: 'wwan_dis2' ((____ptrval____)):
kobject_add_internal: parent: 'leds', set: 'devices'
[ 191.121124] PM: Adding info for No Bus:wwan_dis2
[ 191.121132] kobject: 'wwan_dis2' ((____ptrval____)):
kobject_uevent_env
[ 191.121149] kobject: 'wwan_dis2' ((____ptrval____)): fill_kobj_path:
path = '/devices/platform/leds/leds/wwan_dis2'
[ 191.121172] leds-gpio leds: Registered led device: (null)
[ 191.121187] driver: 'leds-gpio': driver_bound: bound to device
'leds'
[ 191.121233] leds-gpio leds: Dropping the link to 30330000.pinctrl
[ 191.121255] device: 'platform:30330000.pinctrl--platform:leds':
device_unregister
[ 191.121287] kernfs subsystem: removing
[ 191.121359] kernfs platform:30330000.pinctrl--platform:leds:
removing
[ 191.121385] kernfs consumer: removing
[ 191.121397] kernfs supplier: removing
[ 191.121423] kernfs supplier:platform:30330000.pinctrl: removing
[ 191.121446] kernfs consumer:platform:leds: removing
[ 191.121475] kernfs uevent: removing
[ 191.121492] kernfs status: removing
[ 191.121502] kernfs auto_remove_on: removing
[ 191.121512] kernfs runtime_pm: removing
[ 191.121524] kernfs sync_state_only: removing
[ 191.131697] i2c i2c-3: <i2c_imx_acked> ACK received
[ 191.137259] kobject: 'platform:30330000.pinctrl--platform:leds'
((____ptrval____)): kobject_uevent_env
[ 191.144497] i2c i2c-3: <i2c_imx_write> write data
[ 191.149398] kobject: 'platform:30330000.pinctrl--platform:leds'
((____ptrval____)): fill_kobj_path: path =
'/devices/virtual/devlink/platform:30330000.pinctrl--platform:leds'
[ 191.154111] i2c i2c-3: <i2c_imx_write> write byte: B0=0x0
[ 191.157842] kernfs platform:30330000.pinctrl--platform:leds:
removing
[ 191.164227] i2c i2c-3: <i2c_imx_trx_complete> TRX complete
[ 191.168240] kobject: 'platform:30330000.pinctrl--platform:leds'
((____ptrval____)): kobject_cleanup, parent 0000000000000000
[ 191.178594] i2c i2c-3: <i2c_imx_acked> ACK received
[ 191.185118] kobject: 'platform:30330000.pinctrl--platform:leds'
((____ptrval____)): calling ktype release
[ 191.189332] i2c i2c-3: <i2c_imx_xfer_common> repeated start
[ 191.195319] kobject: 'platform:30330000.pinctrl--platform:leds':
free name
[ 191.200506] i2c i2c-3: <i2c_imx_bus_busy>
[ 191.200536] i2c i2c-3: <i2c_imx_xfer_common> transfer message: 1
[ 191.206919] leds-gpio leds: Dropping the link to 30220000.gpio
[ 191.212056] i2c i2c-3: <i2c_imx_read> write slave address: addr=0x6d
[ 191.219768] device: 'platform:30220000.gpio--platform:leds':
device_unregister
[ 191.226918] i2c i2c-3: <i2c_imx_trx_complete> TRX complete
[ 191.234771] kernfs subsystem: removing
[ 191.241527] i2c i2c-3: <i2c_imx_acked> ACK received