interconnect: Add imx support via devfreq
Subsystems (4)
v5 cover interconnect: Add imx support via devfreq
This series adds upstream DRAM and interconnect scaling support for imx8m series chips. It uses a per-SOC interconnect provider layered on top of multiple instances of devfreq for scalable nodes along the interconnect.
Existing qcom interconnect providers mostly translate bandwidth requests into firmware calls but equivalent firmware on imx8m is much thinner. Scaling support for individual nodes (NIC/NOC and DDRC) is implemented through devfreq.
The imx interconnect provider doesn't communicate with devfreq instance directly but rather computes "minimum frequencies" for nodes along the path and creates dev_pm_qos requests.
This needs core changes for dev_pm_qos frequency support for devfreq:
https://patchwork.kernel.org/project/linux-arm-kernel/list/?series=196443
Since imx interconnect only needs to interact with imx devfreq it would also be possible to tie them together directly, but it would be a little sad.
Since there is no single devicetree node that can represent the "interconnect" the main NOC is picked as the "interconnect provider" and will probe the interconnect platform device if #interconnect-cells is present. This is a bit odd.
On i.MX there are multiple instances of a few interconnect IPs, this patch identifies them by enumerating the entire devicetree scanning for the "interconnect-node-id" property. As far as I see current providers do this based entirely on compatible string of the interconnect instance and this seems very odd to me. Do you think we could move this "interconnect-node-id" approach to core interconnect bindings?
The same interconnect-node-id property is used to identify the DDRC and this is arguably a hack.
Also as a github branch (with few other changes):
https://github.com/cdleonard/linux/tree/next_imx_busfreq
This is layered upon imx-ddrc scaling support:
* https://patchwork.kernel.org/project/linux-arm-kernel/list/?series=196459
The DDRC only really interacts by receiving dev_pm_qos requests.
Changes since RFCv4:
* Drop icc proxy nonsense
* Make devfreq driver for NOC probe the ICC driver if #interconnect-cells is present.
* Move NOC support to interconnect series and rename the node in DT
* Add support for all chips at once, differences are not intereseting and there is more community interest for 8mq than 8mm.
Changes since RFCv3:
* Remove the virtual "icc" node and add devfreq nodes as proxy providers
* Fix build on 32-bit arm (reported by kbuilt test robot)
* Remove ARCH_MXC_ARM64 (never existed in upstream)
* Remove _numlinks, calculate instead
* Replace __BUSFREQ_H header guard
* Improve commit message and comment spelling
* Fix checkpatch issues
Link to RFCv3: https://patchwork.kernel.org/cover/11078671/
Changes since RFCv2 and initial work by Alexandre Bailon:
* Relying on devfreq and dev_pm_qos instead of CLK
* No more "platform opp" stuff
* No more special suspend handling: use suspend-opp on devfreq instead.
* Replace all mentions of "busfreq" with "interconnect"
Link to v2: https://patchwork.kernel.org/patch/11056789/
Leonard Crestez (10):
dt-bindings: devfreq: Add bindings for generic imx buses PM / devfreq: Add generic imx bus driver
PM / devfreq: imx: Register interconnect device PM / devfreq: Add devfreq_get_devfreq_by_node
interconnect: Add imx core driver
interconnect: imx: Add platform driver for imx8mm
interconnect: imx: Add platform driver for imx8mq
interconnect: imx: Add platform driver for imx8mn
arm64: dts: imx8m: Add NOC nodes
arm64: dts: imx8m: Add interconnect provider properties
.../devicetree/bindings/devfreq/imx.yaml | 83 ++++++ arch/arm64/boot/dts/freescale/imx8mm.dtsi | 26 ++ arch/arm64/boot/dts/freescale/imx8mn.dtsi | 26 ++ arch/arm64/boot/dts/freescale/imx8mq.dtsi | 26 ++ drivers/devfreq/Kconfig | 12 + drivers/devfreq/Makefile | 1 + drivers/devfreq/devfreq.c | 42 ++- drivers/devfreq/imx-devfreq.c | 185 ++++++++++++ drivers/interconnect/Kconfig | 1 + drivers/interconnect/Makefile | 1 + drivers/interconnect/imx/Kconfig | 17 ++ drivers/interconnect/imx/Makefile | 4 + drivers/interconnect/imx/imx.c | 273 ++++++++++++++++++ drivers/interconnect/imx/imx.h | 60 ++++ drivers/interconnect/imx/imx8mm.c | 105 +++++++ drivers/interconnect/imx/imx8mn.c | 94 ++++++ drivers/interconnect/imx/imx8mq.c | 103 +++++++ include/dt-bindings/interconnect/imx8mm.h | 49 ++++ include/dt-bindings/interconnect/imx8mn.h | 41 +++ include/dt-bindings/interconnect/imx8mq.h | 48 +++ include/linux/devfreq.h | 1 + 21 files changed, 1187 insertions(+), 11 deletions(-) create mode 100644 Documentation/devicetree/bindings/devfreq/imx.yaml create mode 100644 drivers/devfreq/imx-devfreq.c create mode 100644 drivers/interconnect/imx/Kconfig create mode 100644 drivers/interconnect/imx/Makefile create mode 100644 drivers/interconnect/imx/imx.c create mode 100644 drivers/interconnect/imx/imx.h create mode 100644 drivers/interconnect/imx/imx8mm.c create mode 100644 drivers/interconnect/imx/imx8mn.c create mode 100644 drivers/interconnect/imx/imx8mq.c create mode 100644 include/dt-bindings/interconnect/imx8mm.h create mode 100644 include/dt-bindings/interconnect/imx8mn.h create mode 100644 include/dt-bindings/interconnect/imx8mq.h
Signature · 1 line
2.17.1
RFC PATCH v5 1/10 dt-bindings: devfreq: Add bindings for generic imx buses
Add initial dt bindings for the interconnects inside i.MX chips. Multiple external IPs are involved but SOC integration means the software controllable interfaces are very similar.
Single node also acts as interconnect provider if #interconnect-cells is present.
--- .../devicetree/bindings/devfreq/imx.yaml | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 Documentation/devicetree/bindings/devfreq/imx.yaml
Documentation/devicetree/bindings/devfreq/imx.yaml new file +83 -0
@@ -0,0 +1,83 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/devfreq/imx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Generic i.MX bus frequency device + +maintainers: + - Leonard Crestez <[email protected]> + +description: | + The i.MX SoC family has multiple buses for which clock frequency (and + sometimes voltage) can be adjusted. + + Some of those buses expose register areas mentioned in the memory maps as GPV + ("Global Programmers View") but not all. Access to this area might be denied + for normal (non-secure) world. + + The buses are based on externally licensed IPs such as ARM NIC-301 and + Arteris FlexNOC but DT bindings are specific to the integration of these bus + interconnect IPs into imx SOCs. + +properties: + compatible: + oneOf: + - items: + - enum: + - fsl,imx8mn-nic + - fsl,imx8mm-nic + - fsl,imx8mq-nic + - const: fsl,imx8m-nic + - items: + - enum: + - fsl,imx8mn-noc + - fsl,imx8mm-noc + - fsl,imx8mq-noc + - const: fsl,imx8m-noc + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + operating-points-v2: true + + devfreq: + description: | + Phandle to another devfreq device to match OPPs with by using the + passive governor. + $ref: "/schemas/types.yaml#/definitions/phandle" + + '#interconnect-cells': + description: | + If specified then also act as an interconnect provider. Should only be + set once per soc on main noc. + const: 1 + + interconnect-node-id: + description: | + i.MX chips have multiple scalable buses based on the same IP, this is + used to distinguish between. Uses same identifier namespace as consumer + "interconnects" property, for example one of the values in + "include/dt-bindings/interconnect/imx8mm.h" + + const: 1 + +required: + - compatible + - clocks + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/imx8mm-clock.h> + noc: noc@32700000 { + compatible = "fsl,imx8mm-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MM_CLK_NOC>; + operating-points-v2 = <&noc_opp_table>; + };
Signature · 1 line
2.17.1
Rob Herring
maintainerRe: [PATCH RFC v5 01/10] dt-bindings: devfreq: Add bindings for generic imx buses
Quoted 11 lines · Leonard Crestez
Add initial dt bindings for the interconnects inside i.MX chips. Multiple external IPs are involved but SOC integration means the software controllable interfaces are very similar.
Single node also acts as interconnect provider if #interconnect-cells is present.
Signed-off-by Leonard Crestez <[email protected]>Acked-by MyungJoo Ham <[email protected]>--- .../devicetree/bindings/devfreq/imx.yaml | 83 +++++++++++++++++++
bindings/interconnect/
Quoted 9 lines
1 file changed, 83 insertions(+) create mode 100644 Documentation/devicetree/bindings/devfreq/imx.yamlDocumentation/devicetree/bindings/devfreq/imx.yaml new file +0
-0
Documentation/devicetree/bindings/devfreq/imx.yaml line 7
Quoted 7 lines
Documentation/devicetree/bindings/devfreq/imx.yaml new file +7
-0@@ -0,0 +1,83 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/devfreq/imx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Generic i.MX bus frequency device
i.MX8 specific?
Quoted 43 lines
Documentation/devicetree/bindings/devfreq/imx.yaml new file +43
-0+ +maintainers: + - Leonard Crestez <[email protected]> + +description: | + The i.MX SoC family has multiple buses for which clock frequency (and + sometimes voltage) can be adjusted. + + Some of those buses expose register areas mentioned in the memory maps as GPV + ("Global Programmers View") but not all. Access to this area might be denied + for normal (non-secure) world. + + The buses are based on externally licensed IPs such as ARM NIC-301 and + Arteris FlexNOC but DT bindings are specific to the integration of these bus + interconnect IPs into imx SOCs. + +properties: + compatible: + oneOf: + - items: + - enum: + - fsl,imx8mn-nic + - fsl,imx8mm-nic + - fsl,imx8mq-nic + - const: fsl,imx8m-nic + - items: + - enum: + - fsl,imx8mn-noc + - fsl,imx8mm-noc + - fsl,imx8mq-noc + - const: fsl,imx8m-noc + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + operating-points-v2: true + + devfreq: + description: | + Phandle to another devfreq device to match OPPs with by using the
Documentation/devicetree/bindings/devfreq/imx.yaml line 60
Quoted 10 lines
Documentation/devicetree/bindings/devfreq/imx.yaml new file +10
-0+ passive governor. + $ref: "/schemas/types.yaml#/definitions/phandle" + + '#interconnect-cells': + description: | + If specified then also act as an interconnect provider. Should only be + set once per soc on main noc. + const: 1 + + interconnect-node-id:
Looks like common property, but it's not...
Generally, we don't do indexes or instance ids. So it needs a better explanation or drop this. The driver side looks like an odd marriage between interconnect and devfreq drivers that needs better integration, but I'm not all that familar with either.
Documentation/devicetree/bindings/devfreq/imx.yaml line 63
Quoted 3 lines
Documentation/devicetree/bindings/devfreq/imx.yaml new file +3
-0+ description: | + i.MX chips have multiple scalable buses based on the same IP, this is + used to distinguish between. Uses same identifier namespace as consumer
It's not names, so number space? Just guessing because there's no type nor example.
Quoted 23 lines
Documentation/devicetree/bindings/devfreq/imx.yaml new file +20
-0+ "interconnects" property, for example one of the values in + "include/dt-bindings/interconnect/imx8mm.h" + + const: 1 + +required: + - compatible + - clocks + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/imx8mm-clock.h> + noc: noc@32700000 { + compatible = "fsl,imx8mm-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MM_CLK_NOC>; + operating-points-v2 = <&noc_opp_table>; + };Signature · 1 line
2.17.1
Re: [PATCH RFC v5 01/10] dt-bindings: devfreq: Add bindings for generic imx buses
Quoted 8 lines · Rob Herring
Quoted 7 lines · Leonard Crestez
Add initial dt bindings for the interconnects inside i.MX chips. Multiple external IPs are involved but SOC integration means the software controllable interfaces are very similar.
Single node also acts as interconnect provider if #interconnect-cells is present.
Quoted 6 lines
Quoted 4 lines
Signed-off-by Leonard Crestez <[email protected]>Acked-by MyungJoo Ham <[email protected]>--- .../devicetree/bindings/devfreq/imx.yaml | 83 +++++++++++++++++++bindings/interconnect/
Make sense. The only other two files in devicetree/bindings/devfreq are:
* rk3399_dmc: a memory controller
* exynos-bus: arguably an interconnect
Quoted 18 lines
Quoted 9 lines
1 file changed, 83 insertions(+)create mode 100644
Documentation/devicetree/bindings/devfreq/imx.yamlDocumentation/devicetree/bindings/devfreq/imx.yaml new file +0
-0Documentation/devicetree/bindings/devfreq/imx.yaml line 7
Quoted 7 lines
Documentation/devicetree/bindings/devfreq/imx.yaml new file +7
-0@@ -0,0 +1,83 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevicetree.org%2Fschemas%2Fdevfreq%2Fimx.yaml%23&data=02%7C01%7Cleonard.crestez%40nxp.com%7C95911400e0834b06269c08d761794cd2%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C1%7C637085045930647253&sdata=88iAXoKObu%2FXBqZu6hNwnOUIffB8GxVLdGeBWiCjClI%3D&reserved=0 +$schema: https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevicetree.org%2Fmeta-schemas%2Fcore.yaml%23&data=02%7C01%7Cleonard.crestez%40nxp.com%7C95911400e0834b06269c08d761794cd2%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C1%7C637085045930647253&sdata=0phpsG05ZsYc5SnI3FXZODJpJSEB2tzA5v02r7N%2BY2I%3D&reserved=0 + +title: Generic i.MX bus frequency devicei.MX8 specific?
Not really, but it's initially targeted at imx8m.
Quoted 55 lines
Quoted 42 lines
Documentation/devicetree/bindings/devfreq/imx.yaml new file +42
-0+maintainers: + - Leonard Crestez <[email protected]> + +description: | + The i.MX SoC family has multiple buses for which clock frequency (and + sometimes voltage) can be adjusted. + + Some of those buses expose register areas mentioned in the memory maps as GPV + ("Global Programmers View") but not all. Access to this area might be denied + for normal (non-secure) world. + + The buses are based on externally licensed IPs such as ARM NIC-301 and + Arteris FlexNOC but DT bindings are specific to the integration of these bus + interconnect IPs into imx SOCs. + +properties: + compatible: + oneOf: + - items: + - enum: + - fsl,imx8mn-nic + - fsl,imx8mm-nic + - fsl,imx8mq-nic + - const: fsl,imx8m-nic + - items: + - enum: + - fsl,imx8mn-noc + - fsl,imx8mm-noc + - fsl,imx8mq-noc + - const: fsl,imx8m-noc + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + operating-points-v2: true + + devfreq: + description: | + Phandle to another devfreq device to match OPPs with by using theDocumentation/devicetree/bindings/devfreq/imx.yaml line 60
Quoted 10 lines
Documentation/devicetree/bindings/devfreq/imx.yaml new file +10
-0+ passive governor. + $ref: "/schemas/types.yaml#/definitions/phandle" + + '#interconnect-cells': + description: | + If specified then also act as an interconnect provider. Should only be + set once per soc on main noc. + const: 1 + + interconnect-node-id:Looks like common property, but it's not...
Quoted 4 lines
Generally, we don't do indexes or instance ids. So it needs a better explanation or drop this. The driver side looks like an odd marriage between interconnect and devfreq drivers that needs better integration, but I'm not all that familar with either.
Current interconnect drivers all operate by sending messages via a mailbox to a system controller which handles bandwidth requests. They only perform request aggregation. On imx8m frequency scaling is also implemented in the kernel so the NOC becomes almost like a MFD.
The interconnect-node-id is used to find other scalable nodes for the same interconnect provider. I can replace this with a "scalable-nodes" array like this:
noc: interconnect@32700000 {
compatible = "fsl,imx8mq-noc", "fsl,imx8m-noc";
reg = <0x32700000 0x100000>;
clocks = <&clk IMX8MQ_CLK_NOC>;
#interconnect-cells = <1>;
fsl,scalable-node-ids = <IMX8MQ_ICN_NOC>,
<IMX8MQ_ICS_DRAM>;
fsl,scalable-nodes = <&noc>,
<&ddrc>;
operating-points-v2 = <&noc_opp_table>;
noc_opp_table: opp-table {
compatible = "operating-points-v2";
opp-133M {
opp-hz = /bits/ 64 <133333333>;
};
opp-400M {
opp-hz = /bits/ 64 <400000000>;
};
opp-800M {
opp-hz = /bits/ 64 <800000000>;
};
};
};
ddrc: dram-controller@3d400000 {
compatible = "fsl,imx8mq-ddrc", "fsl,imx8m-ddrc";
reg = <0x3d400000 0x400000>;
clock-names = "core", "pll", "alt", "apb";
clocks = <&clk IMX8MQ_CLK_DRAM_CORE>,
<&clk IMX8MQ_DRAM_PLL_OUT>,
<&clk IMX8MQ_CLK_DRAM_ALT>,
<&clk IMX8MQ_CLK_DRAM_APB>;
devfreq-events = <&ddr_pmu>;
};It's a bit strange that the noc references itself but in advanced multiple NOC can be be present and there needs to be a way to map from the interconnect graph (node ids) to devicetree nodes.
Quoted 6 lines
Documentation/devicetree/bindings/devfreq/imx.yaml line 63
Quoted 3 lines
Documentation/devicetree/bindings/devfreq/imx.yaml new file +3
-0+ description: | + i.MX chips have multiple scalable buses based on the same IP, this is + used to distinguish between. Uses same identifier namespace as consumerIt's not names, so number space? Just guessing because there's no type nor example.
Maybe "numeric namespace"?
Quoted 22 lines
Quoted 22 lines
Documentation/devicetree/bindings/devfreq/imx.yaml new file +20
-0+ "interconnects" property, for example one of the values in + "include/dt-bindings/interconnect/imx8mm.h" + + const: 1 + +required: + - compatible + - clocks + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/imx8mm-clock.h> + noc: noc@32700000 { + compatible = "fsl,imx8mm-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MM_CLK_NOC>; + operating-points-v2 = <&noc_opp_table>; + };Signature · 1 line
2.17.1
RFC PATCH v5 2/10 PM / devfreq: Add generic imx bus driver
In reply to Leonard CrestezAdd initial support for dynamic frequency switching on pieces of the imx interconnect fabric.
All this driver does is set a clk rate based on an opp table, it does not even map registers.
--- drivers/devfreq/Kconfig | 12 +++ drivers/devfreq/Makefile | 1 + drivers/devfreq/imx-devfreq.c | 148 ++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 drivers/devfreq/imx-devfreq.c
drivers/devfreq/Kconfig +12 -0
@@ -90,10 +90,22 @@ config ARM_EXYNOS_BUS_DEVFREQ Each memory bus group could contain many memoby bus block. It reads PPMU counters of memory controllers by using DEVFREQ-event device and adjusts the operating frequencies and voltages with OPP support. This does not yet operate with optimal voltages. +config ARM_IMX_DEVFREQ + tristate "i.MX DEVFREQ Driver" + depends on ARCH_MXC || COMPILE_TEST + select DEVFREQ_GOV_PASSIVE + select DEVFREQ_GOV_SIMPLE_ONDEMAND + select DEVFREQ_GOV_USERSPACE + select PM_OPP + help + This adds the DEVFREQ driver for the i.MX family of SoCs. + It allows adjusting frequencies for DDRC (DDR Controller) and various + NICs and NOCs which form the SOC interconnect fabric + config ARM_TEGRA_DEVFREQ tristate "NVIDIA Tegra30/114/124/210 DEVFREQ Driver" depends on ARCH_TEGRA_3x_SOC || ARCH_TEGRA_114_SOC || \ ARCH_TEGRA_132_SOC || ARCH_TEGRA_124_SOC || \ ARCH_TEGRA_210_SOC || \
drivers/devfreq/Makefile +1 -0
@@ -8,10 +8,11 @@ obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o # DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_IMX_DEVFREQ) += imx-ddrc.o +obj-$(CONFIG_ARM_IMX_DEVFREQ) += imx-devfreq.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o # DEVFREQ Event Drivers
drivers/devfreq/imx-devfreq.c new file +148 -0
148 lines not on this page · raw message
Signature · 1 line
2.17.1
RFC PATCH v5 3/10 PM / devfreq: imx: Register interconnect device
In reply to Leonard CrestezThere is no single device which can represent the imx interconnect. Instead of adding a virtual one just make the main &noc act as the global interconnect provider.
The imx interconnect provider driver will scale the NOC and DDRC based on bandwidth request. More scalable nodes can be added in the future, for example for audio/display/vpu/gpu NICs.
--- drivers/devfreq/imx-devfreq.c | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)
drivers/devfreq/imx-devfreq.c +37 -0
@@ -15,10 +15,11 @@struct imx_devfreq {struct devfreq_dev_profile profile;struct devfreq *devfreq;struct clk *clk;struct devfreq_passive_data passive_data; +struct platform_device *icc_pdev; };static int imx_devfreq_target (struct device *dev,unsigned long *freq,u32 flags) {struct imx_devfreq *priv =dev_get_drvdata (dev);
@@ -59,11 +60,40 @@ static int imx_devfreq_get_dev_status(struct device *dev,return 0 ; }static void imx_devfreq_exit (struct device *dev) { +struct imx_devfreq *priv =dev_get_drvdata (dev); +dev_pm_opp_of_remove_table (dev); +platform_device_unregister (priv->icc_pdev); +} + +/* imx_devfreq_init_icc() - register matching icc provider if required */ +static int imx_devfreq_init_icc (struct device *dev) +{ +struct imx_devfreq *priv =dev_get_drvdata (dev); +const char *icc_driver_name; + +if (!IS_ENABLED (CONFIG_INTERCONNECT_IMX )) +return 0 ; +if (!of_get_property (dev->of_node,"#interconnect-cells" ,0 )) +return 0 ; + + icc_driver_name =of_device_get_match_data (dev); +if (!icc_driver_name) +return 0 ; + + priv->icc_pdev =platform_device_register_data ( + dev, icc_driver_name,0 ,NULL ,0 ); +if (IS_ERR (priv->icc_pdev)) { +dev_err (dev,"failed to register icc provider %s: %ld\n" , + icc_driver_name,PTR_ERR (priv->devfreq)); +return PTR_ERR (priv->devfreq); + } + +return 0 ; }static int imx_devfreq_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;
@@ -118,18 +148,25 @@ static int imx_devfreq_probe(struct platform_device *pdev) ret =PTR_ERR (priv->devfreq);dev_err (dev,"failed to add devfreq device: %d\n" , ret); goto err; } + ret =imx_devfreq_init_icc (dev); +if (ret) + goto err; +return 0 ; err:dev_pm_opp_of_remove_table (dev);return ret; }static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8mq-noc" , .data ="imx8mq-interconnect" , }, + { .compatible ="fsl,imx8mm-noc" , .data ="imx8mm-interconnect" , }, + { .compatible ="fsl,imx8mn-noc" , .data ="imx8mn-interconnect" , }, { .compatible ="fsl,imx8m-noc" , }, { .compatible ="fsl,imx8m-nic" , }, {/* sentinel */ }, };MODULE_DEVICE_TABLE (of, imx_devfreq_of_match);
Signature · 1 line
2.17.1
RFC PATCH v5 4/10 PM / devfreq: Add devfreq_get_devfreq_by_node
In reply to Leonard CrestezSplit off part of devfreq_get_devfreq_by_phandle into a separate function. This allows callers to fetch devfreq instances by enumerating devicetree instead of explicit phandles.
--- drivers/devfreq/devfreq.c | 42 +++++++++++++++++++++++++++++---------- include/linux/devfreq.h | 1 + 2 files changed, 32 insertions(+), 11 deletions(-)
drivers/devfreq/devfreq.c +31 -11
@@ -931,10 +931,33 @@ struct devfreq *devm_devfreq_add_device(struct device *dev,return devfreq; }EXPORT_SYMBOL (devm_devfreq_add_device);#ifdef CONFIG_OF +/* +* devfreq_get_devfreq_by_node - Get the devfreq device from devicetree +* @np - pointer to device_node +* +* return the instance of devfreq device +*/ +struct devfreq *devfreq_get_devfreq_by_node (struct device_node *node) +{ +struct devfreq *devfreq; + +mutex_lock (&devfreq_list_lock); +list_for_each_entry (devfreq, &devfreq_list, node) { +if (devfreq->dev.parent + && devfreq->dev.parent->of_node == node) { +mutex_unlock (&devfreq_list_lock); +return devfreq; + } + } +mutex_unlock (&devfreq_list_lock); + +return ERR_PTR (-EPROBE_DEFER ); +} +/* * devfreq_get_devfreq_by_phandle - Get the devfreq device from devicetree * @dev - instance to the given device * @index - index into list of devfreq *
@@ -953,25 +976,22 @@ struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev, int index) node =of_parse_phandle (dev->of_node,"devfreq" , index);if (!node)return ERR_PTR (-ENODEV ); -mutex_lock (&devfreq_list_lock); -list_for_each_entry (devfreq, &devfreq_list, node) { -if (devfreq->dev.parent - && devfreq->dev.parent->of_node == node) { -mutex_unlock (&devfreq_list_lock); -of_node_put (node); -return devfreq; - } - } -mutex_unlock (&devfreq_list_lock); + devfreq =devfreq_get_devfreq_by_node (node);of_node_put (node); - return ERR_PTR(-EPROBE_DEFER); + return devfreq; } +#else +struct devfreq *devfreq_get_devfreq_by_node (struct device_node *node) +{ +return ERR_PTR (-ENODEV ); +} +struct devfreq *devfreq_get_devfreq_by_phandle (struct device *dev,int index) {return ERR_PTR (-ENODEV ); }#endif /* CONFIG_OF */
include/linux/devfreq.h +1 -0
@@ -242,10 +242,11 @@ extern int devm_devfreq_register_notifier(struct device *dev, unsigned int list);extern void devm_devfreq_unregister_notifier (struct device *dev,struct devfreq *devfreq,struct notifier_block *nb,unsigned int list); +extern struct devfreq *devfreq_get_devfreq_by_node (struct device_node *node);extern struct devfreq *devfreq_get_devfreq_by_phandle (struct device *dev,int index);#if IS_ENABLED (CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND )/**
Signature · 1 line
2.17.1
RFC PATCH v5 5/10 interconnect: Add imx core driver
In reply to Leonard CrestezThis adds support for i.MX SoC family to interconnect framework.
Platform drivers can describe the interconnect graph and several adjustment knobs where icc node bandwidth is converted to a DEV_PM_QOS_MIN_FREQUENCY request.
The adjustable nodes are found based on an "interconnect-node-id" property by scanning the entire device tree.
The interconnect provider doesn't need an virtual OF node, instead those same adjustable nodes are registered as proxies which xlate to the platform-level provider.
The platform device for the interconnect needs to be registered from a SOC driver (similar to cpufreq).
--- drivers/interconnect/Kconfig | 1 + drivers/interconnect/Makefile | 1 + drivers/interconnect/imx/Kconfig | 5 + drivers/interconnect/imx/Makefile | 1 + drivers/interconnect/imx/imx.c | 273 ++++++++++++++++++++++++++++++ drivers/interconnect/imx/imx.h | 60 +++++++ 6 files changed, 341 insertions(+) create mode 100644 drivers/interconnect/imx/Kconfig create mode 100644 drivers/interconnect/imx/Makefile create mode 100644 drivers/interconnect/imx/imx.c create mode 100644 drivers/interconnect/imx/imx.h
drivers/interconnect/Kconfig +1 -0
@@ -10,7 +10,8 @@ menuconfig INTERCONNECT If unsure, say no. if INTERCONNECT source "drivers/interconnect/qcom/Kconfig" +source "drivers/interconnect/imx/Kconfig" endif
drivers/interconnect/Makefile +1 -0
@@ -2,5 +2,6 @@ icc-core-objs := core.o obj-$(CONFIG_INTERCONNECT) += icc-core.o obj-$(CONFIG_INTERCONNECT_QCOM) += qcom/ +obj-$(CONFIG_INTERCONNECT_IMX) += imx/
drivers/interconnect/imx/Kconfig new file +5 -0
@@ -0,0 +1,5 @@ +config INTERCONNECT_IMX + bool "i.MX interconnect drivers" + depends on ARCH_MXC || COMPILE_TEST + help + Generic interconnect driver for i.MX SOCs
drivers/interconnect/imx/Makefile new file +1 -0
@@ -0,0 +1 @@ +obj-$(CONFIG_INTERCONNECT_IMX) += imx.o
drivers/interconnect/imx/imx.c new file +273 -0
273 lines not on this page · raw message
drivers/interconnect/imx/imx.h new file +60 -0
60 lines not on this page · raw message
Signature · 1 line
2.17.1
Re: [PATCH RFC v5 05/10] interconnect: Add imx core driver
Hi Leonard,
Thanks for the patch!
Quoted 8 lines · Leonard Crestez
This adds support for i.MX SoC family to interconnect framework.
Platform drivers can describe the interconnect graph and several adjustment knobs where icc node bandwidth is converted to a
DEV_PM_QOS_MIN_FREQUENCYrequest.The adjustable nodes are found based on an "interconnect-node-id" property by scanning the entire device tree.
Are the adjustable nodes SoC specific? Can we have them here in the driver instead of scanning the entire device tree?
Quoted 83 lines
The interconnect provider doesn't need an virtual OF node, instead those same adjustable nodes are registered as proxies which xlate to the platform-level provider.
The platform device for the interconnect needs to be registered from a SOC driver (similar to cpufreq).
Signed-off-by Alexandre Bailon <[email protected]>Signed-off-by Leonard Crestez <[email protected]>--- drivers/interconnect/Kconfig | 1 + drivers/interconnect/Makefile | 1 + drivers/interconnect/imx/Kconfig | 5 + drivers/interconnect/imx/Makefile | 1 + drivers/interconnect/imx/imx.c | 273 ++++++++++++++++++++++++++++++ drivers/interconnect/imx/imx.h | 60 +++++++ 6 files changed, 341 insertions(+) create mode 100644 drivers/interconnect/imx/Kconfig create mode 100644 drivers/interconnect/imx/Makefile create mode 100644 drivers/interconnect/imx/imx.c create mode 100644 drivers/interconnect/imx/imx.hdrivers/interconnect/Kconfig +1
-0@@ -10,7 +10,8 @@ menuconfig INTERCONNECT If unsure, say no. if INTERCONNECT source "drivers/interconnect/qcom/Kconfig" +source "drivers/interconnect/imx/Kconfig" endifdrivers/interconnect/Makefile +1
-0@@ -2,5 +2,6 @@ icc-core-objs := core.o obj-$(CONFIG_INTERCONNECT) += icc-core.o obj-$(CONFIG_INTERCONNECT_QCOM) += qcom/ +obj-$(CONFIG_INTERCONNECT_IMX) += imx/drivers/interconnect/imx/Kconfig new file +5
-0@@ -0,0 +1,5 @@ +config INTERCONNECT_IMX + bool "i.MX interconnect drivers" + depends on ARCH_MXC || COMPILE_TEST + help + Generic interconnect driver for i.MX SOCsdrivers/interconnect/imx/Makefile new file +1
-0@@ -0,0 +1 @@ +obj-$(CONFIG_INTERCONNECT_IMX) += imx.odrivers/interconnect/imx/imx.c new file +13
-0@@ -0,0 +1,273 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Interconnect framework driver for i.MX SoC +* +* Copyright (c) 2019, BayLibre +* Copyright (c) 2019, NXP +* Author: Alexandre Bailon <[email protected]> +* Author: Leonard Crestez <[email protected]> +*/ + +#include <linux/devfreq.h> +#include <linux/device.h> +#include <linux/interconnect-provider.h>
drivers/interconnect/imx/imx.c line 23
Quoted 10 lines
drivers/interconnect/imx/imx.c new file +10
-0+#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm_qos.h> + +#include "imx.h" + +/* private icc_provider data */ +struct imx_icc_provider { +struct device *dev;
What device is this? There is already a *dev in struct icc_provider. Please add kernel-doc.
Quoted 33 lines
drivers/interconnect/imx/imx.c new file +33
-0+}; + +/* private icc_node data */ +struct imx_icc_node { +const struct imx_icc_node_desc *desc; +struct devfreq *devfreq; +struct dev_pm_qos_request qos_req; +}; + +static int imx_icc_aggregate (struct icc_node *node,u32 tag, +u32 avg_bw,u32 peak_bw, +u32 *agg_avg,u32 *agg_peak) +{ + *agg_avg += avg_bw; + *agg_peak =max (*agg_peak, peak_bw); + +return 0 ; +} + +static struct icc_node *imx_icc_xlate (struct of_phandle_args *spec,void *data) +{ +struct imx_icc_provider *desc = data; +struct icc_provider *provider =dev_get_drvdata (desc->dev); +unsigned int id = spec->args[0 ]; +struct icc_node *node; + +list_for_each_entry (node, &provider->nodes, node_list) +if (node->id == id) +return node; + +return ERR_PTR (-EINVAL ); +} +
drivers/interconnect/imx/imx.c line 66
Quoted 10 lines
drivers/interconnect/imx/imx.c new file +10
-0+static int imx_icc_node_set (struct icc_node *node) +{ +struct device *dev = node->provider->dev; +struct imx_icc_node *node_data = node->data; +u64 freq; + +if (!node_data->devfreq) +return 0 ; + + freq = (node->avg_bw + node->peak_bw) * node_data->desc->adj->bw_mul;
Why the sum of average and peak bandwidth?
Quoted 38 lines
drivers/interconnect/imx/imx.c new file +38
-0+do_div (freq, node_data->desc->adj->bw_div); +dev_dbg (dev,"node %s device %s avg_bw %ukBps peak_bw %ukBps min_freq %llukHz\n" , + node->name,dev_name (node_data->devfreq->dev.parent), + node->avg_bw, node->peak_bw, freq); + +if (freq >S32_MAX ) { +dev_err (dev,"%s can't request more than S32_MAX freq\n" , + node->name); +return -ERANGE ; + } + +dev_pm_qos_update_request (&node_data->qos_req, freq); + +return 0 ; +} + +static int imx_icc_set (struct icc_node *src,struct icc_node *dst) +{ +return imx_icc_node_set (dst); +} + +static int imx_icc_node_init_devfreq (struct device *dev, +struct icc_node *node) +{ +struct imx_icc_node *node_data = node->data; +struct device_node *dn; +u32 node_id; +int ret; + +/* Find nodes based on interconnect-node-id property */ +for_each_node_with_property (dn,"interconnect-node-id" ) { + ret =of_property_read_u32 (dn,"interconnect-node-id" , + &node_id); +if (ret !=0 ) +continue ; + +if (node_id == node->id) { +of_node_get (dn);
drivers/interconnect/imx/imx.c line 114
Quoted 10 lines
drivers/interconnect/imx/imx.c new file +10
-0+break ; + } + } + +if (!dn) +return 0 ; + +dev_info (dev,"node %s[%d] has device node %pOF\n" , + node->name, node->id, dn); + node_data->devfreq =devfreq_get_devfreq_by_node (dn);
Ah, so you need to get the devfreq nodes? So looking at the next patches it seems that noc and ddrc are the only adjustable nodes?
Maybe we should model them both as interconnect providers, as they seem to be dealing with the bandwidth/frequency requirements and changing the clock rates.
Thanks,
Georgi
Quoted 15 lines
drivers/interconnect/imx/imx.c new file +15
-0+if (IS_ERR (node_data->devfreq)) { +of_node_put (dn); + ret =PTR_ERR (node_data->devfreq); +dev_err (dev,"failed to fetch devfreq for %s: %d\n" , + node->name, ret); +return ret; + } + +of_node_put (dn); + +return dev_pm_qos_add_request (node_data->devfreq->dev.parent, + &node_data->qos_req, +DEV_PM_QOS_MIN_FREQUENCY ,0 ); +} +
Re: [PATCH RFC v5 05/10] interconnect: Add imx core driver
Quoted 105 lines · Georgi Djakov
Hi Leonard,
Thanks for the patch!
Quoted 8 lines · Leonard Crestez
This adds support for i.MX SoC family to interconnect framework.
Platform drivers can describe the interconnect graph and several adjustment knobs where icc node bandwidth is converted to a
DEV_PM_QOS_MIN_FREQUENCYrequest.The adjustable nodes are found based on an "interconnect-node-id" property by scanning the entire device tree.
Are the adjustable nodes SoC specific? Can we have them here in the driver instead of scanning the entire device tree?
Quoted 88 lines
The interconnect provider doesn't need an virtual OF node, instead those same adjustable nodes are registered as proxies which xlate to the platform-level provider.
The platform device for the interconnect needs to be registered from a SOC driver (similar to cpufreq).
Signed-off-by Alexandre Bailon <[email protected]>Signed-off-by Leonard Crestez <[email protected]>--- drivers/interconnect/Kconfig | 1 + drivers/interconnect/Makefile | 1 + drivers/interconnect/imx/Kconfig | 5 + drivers/interconnect/imx/Makefile | 1 + drivers/interconnect/imx/imx.c | 273 ++++++++++++++++++++++++++++++ drivers/interconnect/imx/imx.h | 60 +++++++ 6 files changed, 341 insertions(+)create mode 100644
drivers/interconnect/imx/Kconfigcreate mode 100644drivers/interconnect/imx/Makefilecreate mode 100644drivers/interconnect/imx/imx.ccreate mode 100644drivers/interconnect/imx/imx.hdrivers/interconnect/Kconfig +1
-0@@ -10,7 +10,8 @@ menuconfig INTERCONNECT If unsure, say no. if INTERCONNECT source "drivers/interconnect/qcom/Kconfig" +source "drivers/interconnect/imx/Kconfig" endifdrivers/interconnect/Makefile +1
-0@@ -2,5 +2,6 @@ icc-core-objs := core.o obj-$(CONFIG_INTERCONNECT) += icc-core.o obj-$(CONFIG_INTERCONNECT_QCOM) += qcom/ +obj-$(CONFIG_INTERCONNECT_IMX) += imx/drivers/interconnect/imx/Kconfig new file +5
-0@@ -0,0 +1,5 @@ +config INTERCONNECT_IMX + bool "i.MX interconnect drivers" + depends on ARCH_MXC || COMPILE_TEST + help + Generic interconnect driver for i.MX SOCsdrivers/interconnect/imx/Makefile new file +1
-0@@ -0,0 +1 @@ +obj-$(CONFIG_INTERCONNECT_IMX) += imx.odrivers/interconnect/imx/imx.c new file +18
-0@@ -0,0 +1,273 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Interconnect framework driver for i.MX SoC +* +* Copyright (c) 2019, BayLibre +* Copyright (c) 2019, NXP +* Author: Alexandre Bailon <[email protected]> +* Author: Leonard Crestez <[email protected]> +*/ + +#include <linux/devfreq.h> +#include <linux/device.h> +#include <linux/interconnect-provider.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm_qos.h> +
Quoted 8 lines
drivers/interconnect/imx/imx.c line 23
Quoted 5 lines
drivers/interconnect/imx/imx.c new file +5
-0+#include "imx.h" + +/* private icc_provider data */ +struct imx_icc_provider { +struct device *dev;What device is this? There is already a *dev in struct
icc_provider. Please add kernel-doc.
This is set as icc_provider->data and used for xlate but it can be removed entirely if driver switches to icc_xlate_onecell.
Quoted 35 lines
Quoted 35 lines
drivers/interconnect/imx/imx.c new file +35
-0+/* private icc_node data */ +struct imx_icc_node { +const struct imx_icc_node_desc *desc; +struct devfreq *devfreq; +struct dev_pm_qos_request qos_req; +}; + +static int imx_icc_aggregate (struct icc_node *node,u32 tag, +u32 avg_bw,u32 peak_bw, +u32 *agg_avg,u32 *agg_peak) +{ + *agg_avg += avg_bw; + *agg_peak =max (*agg_peak, peak_bw); + +return 0 ; +} + +static struct icc_node *imx_icc_xlate (struct of_phandle_args *spec,void *data) +{ +struct imx_icc_provider *desc = data; +struct icc_provider *provider =dev_get_drvdata (desc->dev); +unsigned int id = spec->args[0 ]; +struct icc_node *node; + +list_for_each_entry (node, &provider->nodes, node_list) +if (node->id == id) +return node; + +return ERR_PTR (-EINVAL ); +} + +static int imx_icc_node_set (struct icc_node *node) +{ +struct device *dev = node->provider->dev; +struct imx_icc_node *node_data = node->data;
Quoted 8 lines
drivers/interconnect/imx/imx.c line 66
Quoted 6 lines
drivers/interconnect/imx/imx.c new file +6
-0+u64 freq; + +if (!node_data->devfreq) +return 0 ; + + freq = (node->avg_bw + node->peak_bw) * node_data->desc->adj->bw_mul;Why the sum of average and peak bandwidth?
What else?
Averages from all path requests are added and the max() of all per-path peak requests is added on top. The average BW is guaranteed to be consumed (for example a display controller) and the BW for occasional bursts (such as USB) should be reserved on top of that.
Using max(avg, peak) here would make requests for peak BW largely ineffective when there's also a large "avg" request.
Quoted 43 lines
Quoted 43 lines
drivers/interconnect/imx/imx.c new file +43
-0+do_div (freq, node_data->desc->adj->bw_div); +dev_dbg (dev,"node %s device %s avg_bw %ukBps peak_bw %ukBps min_freq %llukHz\n" , + node->name,dev_name (node_data->devfreq->dev.parent), + node->avg_bw, node->peak_bw, freq); + +if (freq >S32_MAX ) { +dev_err (dev,"%s can't request more than S32_MAX freq\n" , + node->name); +return -ERANGE ; + } + +dev_pm_qos_update_request (&node_data->qos_req, freq); + +return 0 ; +} + +static int imx_icc_set (struct icc_node *src,struct icc_node *dst) +{ +return imx_icc_node_set (dst); +} + +static int imx_icc_node_init_devfreq (struct device *dev, +struct icc_node *node) +{ +struct imx_icc_node *node_data = node->data; +struct device_node *dn; +u32 node_id; +int ret; + +/* Find nodes based on interconnect-node-id property */ +for_each_node_with_property (dn,"interconnect-node-id" ) { + ret =of_property_read_u32 (dn,"interconnect-node-id" , + &node_id); +if (ret !=0 ) +continue ; + +if (node_id == node->id) { +of_node_get (dn); +break ; + } + } + +if (!dn)
Quoted 8 lines
drivers/interconnect/imx/imx.c line 114
Quoted 5 lines
drivers/interconnect/imx/imx.c new file +5
-0+return 0 ; + +dev_info (dev,"node %s[%d] has device node %pOF\n" , + node->name, node->id, dn); + node_data->devfreq =devfreq_get_devfreq_by_node (dn);Ah, so you need to get the devfreq nodes? So looking at the next patches it seems that noc and ddrc are the only adjustable nodes?
I want to add more scalable nodes in the future. imx8mq/8mm/8mn have additional NICs (AXI switches with a different implementation) and upcoming imx8mp will have additional NOCs and scalable NTTP links.
Quoted 3 lines
Maybe we should model them both as interconnect providers, as they seem to be dealing with the bandwidth/frequency requirements and changing the clock rates.
The ddrc is not really an interconnect, it only has an AXI slave port. In theory it could register itself as a single-node icc provider solely so that it can handle the "set" call but that seems hacky.
Current icc driver implementations send aggregated BW requests to a separate controller and internally it changes some frequencies, correct? What I'm doing is implementing the frequency adjustment part inside the kernel as devfreq drivers. These devices have their own OF nodes with OPP tables and supply regulators and governors (based on bandwith measurement).
It makes a lot of sense to layer the "interconnect" on top of "scalable nodes".
--
Regards,
Leonard
RFC PATCH v5 6/10 interconnect: imx: Add platform driver for imx8mm
In reply to Leonard CrestezAdd a platform driver for the i.MX8MM SoC describing bus topology.
Bandwidth adjustments is currently only supported on the DDRC and main NOC. Scaling for the vpu/gpu/display NICs could be added in the future.
--- drivers/interconnect/imx/Kconfig | 4 + drivers/interconnect/imx/Makefile | 1 + drivers/interconnect/imx/imx8mm.c | 105 ++++++++++++++++++++++ include/dt-bindings/interconnect/imx8mm.h | 49 ++++++++++ 4 files changed, 159 insertions(+) create mode 100644 drivers/interconnect/imx/imx8mm.c create mode 100644 include/dt-bindings/interconnect/imx8mm.h
drivers/interconnect/imx/Kconfig +4 -0
@@ -1,5 +1,9 @@ config INTERCONNECT_IMX bool "i.MX interconnect drivers" depends on ARCH_MXC || COMPILE_TEST help Generic interconnect driver for i.MX SOCs + +config INTERCONNECT_IMX8MM + def_bool y + depends on INTERCONNECT_IMX
drivers/interconnect/imx/Makefile +1 -0
@@ -1 +1,2 @@ obj-$(CONFIG_INTERCONNECT_IMX) += imx.o +obj-$(CONFIG_INTERCONNECT_IMX8MM) += imx8mm.o
drivers/interconnect/imx/imx8mm.c new file +105 -0
105 lines not on this page · raw message
include/dt-bindings/interconnect/imx8mm.h new file +49 -0
49 lines not on this page · raw message
Signature · 1 line
2.17.1
RFC PATCH v5 7/10 interconnect: imx: Add platform driver for imx8mq
In reply to Leonard CrestezAdd a platform driver for the i.MX8MQ SoC describing bus topology, based on internal documentation.
--- drivers/interconnect/imx/Kconfig | 4 + drivers/interconnect/imx/Makefile | 1 + drivers/interconnect/imx/imx8mq.c | 103 ++++++++++++++++++++++ include/dt-bindings/interconnect/imx8mq.h | 48 ++++++++++ 4 files changed, 156 insertions(+) create mode 100644 drivers/interconnect/imx/imx8mq.c create mode 100644 include/dt-bindings/interconnect/imx8mq.h
drivers/interconnect/imx/Kconfig +4 -0
@@ -5,5 +5,9 @@ config INTERCONNECT_IMX Generic interconnect driver for i.MX SOCs config INTERCONNECT_IMX8MM def_bool y depends on INTERCONNECT_IMX + +config INTERCONNECT_IMX8MQ + def_bool y + depends on INTERCONNECT_IMX
drivers/interconnect/imx/Makefile +1 -0
@@ -1,2 +1,3 @@ obj-$(CONFIG_INTERCONNECT_IMX) += imx.o obj-$(CONFIG_INTERCONNECT_IMX8MM) += imx8mm.o +obj-$(CONFIG_INTERCONNECT_IMX8MQ) += imx8mq.o
drivers/interconnect/imx/imx8mq.c new file +103 -0
103 lines not on this page · raw message
include/dt-bindings/interconnect/imx8mq.h new file +48 -0
48 lines not on this page · raw message
Signature · 1 line
2.17.1
RFC PATCH v5 8/10 interconnect: imx: Add platform driver for imx8mn
In reply to Leonard CrestezAdd a platform driver for the i.MX8MN SoC describing bus topology, based on internal documentation.
--- drivers/interconnect/imx/Kconfig | 4 + drivers/interconnect/imx/Makefile | 1 + drivers/interconnect/imx/imx8mn.c | 94 +++++++++++++++++++++++ include/dt-bindings/interconnect/imx8mn.h | 41 ++++++++++ 4 files changed, 140 insertions(+) create mode 100644 drivers/interconnect/imx/imx8mn.c create mode 100644 include/dt-bindings/interconnect/imx8mn.h
drivers/interconnect/imx/Kconfig +4 -0
@@ -6,8 +6,12 @@ config INTERCONNECT_IMX config INTERCONNECT_IMX8MM def_bool y depends on INTERCONNECT_IMX +config INTERCONNECT_IMX8MN + def_bool y + depends on INTERCONNECT_IMX + config INTERCONNECT_IMX8MQ def_bool y depends on INTERCONNECT_IMX
drivers/interconnect/imx/Makefile +1 -0
@@ -1,3 +1,4 @@ obj-$(CONFIG_INTERCONNECT_IMX) += imx.o obj-$(CONFIG_INTERCONNECT_IMX8MM) += imx8mm.o +obj-$(CONFIG_INTERCONNECT_IMX8MN) += imx8mn.o obj-$(CONFIG_INTERCONNECT_IMX8MQ) += imx8mq.o
drivers/interconnect/imx/imx8mn.c new file +94 -0
94 lines not on this page · raw message
include/dt-bindings/interconnect/imx8mn.h new file +41 -0
41 lines not on this page · raw message
Signature · 1 line
2.17.1
RFC PATCH v5 9/10 arm64: dts: imx8m: Add NOC nodes
In reply to Leonard CrestezAdd initial support for dynamic frequency scaling of main NOC.
Make DDRC the parent of the NOC (using passive governor) so that the main NOC is automatically scaled together with DDRC by default.
Support for proactive scaling via interconnect will come later.
--- arch/arm64/boot/dts/freescale/imx8mm.dtsi | 22 ++++++++++++++++++++++ arch/arm64/boot/dts/freescale/imx8mn.dtsi | 22 ++++++++++++++++++++++ arch/arm64/boot/dts/freescale/imx8mq.dtsi | 22 ++++++++++++++++++++++ 3 files changed, 66 insertions(+)
arch/arm64/boot/dts/freescale/imx8mm.dtsi +22 -0
@@ -138,10 +138,24 @@ clock-latency-ns = <150000>; opp-suspend; }; }; + noc_opp_table: noc-opp-table { + compatible = "operating-points-v2"; + + opp-150M { + opp-hz = /bits/ 64 <150000000>; + }; + opp-375M { + opp-hz = /bits/ 64 <375000000>; + }; + opp-750M { + opp-hz = /bits/ 64 <750000000>; + }; + }; + memory@40000000 { device_type = "memory"; reg = <0x0 0x40000000 0 0x80000000>; };
@@ -772,10 +786,18 @@ status = "disabled"; }; }; + noc: interconnect@32700000 { + compatible = "fsl,imx8mm-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MM_CLK_NOC>; + devfreq = <&ddrc>; + operating-points-v2 = <&noc_opp_table>; + }; + aips4: bus@32c00000 { compatible = "fsl,aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges = <0x32c00000 0x32c00000 0x400000>;
arch/arm64/boot/dts/freescale/imx8mn.dtsi +22 -0
@@ -137,10 +137,24 @@ clock-latency-ns = <150000>; opp-suspend; }; }; + noc_opp_table: noc-opp-table { + compatible = "operating-points-v2"; + + opp-100M { + opp-hz = /bits/ 64 <100000000>; + }; + opp-600M { + opp-hz = /bits/ 64 <600000000>; + }; + opp-800M { + opp-hz = /bits/ 64 <800000000>; + }; + }; + memory@40000000 { device_type = "memory"; reg = <0x0 0x40000000 0 0x80000000>; };
@@ -668,10 +682,18 @@ status = "disabled"; }; }; + noc: interconnect@32700000 { + compatible = "fsl,imx8mn-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MN_CLK_NOC>; + devfreq = <&ddrc>; + operating-points-v2 = <&noc_opp_table>; + }; + aips4: bus@32c00000 { compatible = "fsl,aips-bus", "simple-bus"; reg = <0x32c00000 0x400000>; #address-cells = <1>; #size-cells = <1>;
arch/arm64/boot/dts/freescale/imx8mq.dtsi +22 -0
@@ -183,10 +183,24 @@ clock-latency-ns = <150000>; opp-suspend; }; }; + noc_opp_table: noc-opp-table { + compatible = "operating-points-v2"; + + opp-133M { + opp-hz = /bits/ 64 <133333333>; + }; + opp-400M { + opp-hz = /bits/ 64 <400000000>; + }; + opp-800M { + opp-hz = /bits/ 64 <800000000>; + }; + }; + pmu { compatible = "arm,cortex-a53-pmu"; interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>; interrupt-parent = <&gic>; interrupt-affinity = <&A53_0>, <&A53_1>, <&A53_2>, <&A53_3>;
@@ -931,10 +945,18 @@ fsl,num-rx-queues = <3>; status = "disabled"; }; }; + noc: interconnect@32700000 { + compatible = "fsl,imx8mq-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MQ_CLK_NOC>; + devfreq = <&ddrc>; + operating-points-v2 = <&noc_opp_table>; + }; + bus@32c00000 { /* AIPS4 */ compatible = "fsl,imx8mq-aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges = <0x32c00000 0x32c00000 0x400000>;
Signature · 1 line
2.17.1
RFC PATCH v5 10/10 arm64: dts: imx8m: Add interconnect provider properties
In reply to Leonard CrestezAdd #interconnect-cells on main &noc so that it will probe the platform interconnect providers. Other devices can request icc_paths like this:
interconnects = <&noc BUS_MASTER_ID &noc BUS_SLAVE_ID>
And interconnect-node-id properties on &noc and &ddrc, the interconnect provider will scan these and make PM QoS frequency requests in response to bandwith request from other drivers.
--- arch/arm64/boot/dts/freescale/imx8mm.dtsi | 4 ++++ arch/arm64/boot/dts/freescale/imx8mn.dtsi | 4 ++++ arch/arm64/boot/dts/freescale/imx8mq.dtsi | 4 ++++ 3 files changed, 12 insertions(+)
arch/arm64/boot/dts/freescale/imx8mm.dtsi +4 -0
@@ -6,10 +6,11 @@ #include <dt-bindings/clock/imx8mm-clock.h> #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/input/input.h> #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/thermal/thermal.h> +#include <dt-bindings/interconnect/imx8mm.h> #include "imx8mm-pinfunc.h" / { interrupt-parent = <&gic>;
@@ -791,10 +792,12 @@ noc: interconnect@32700000 { compatible = "fsl,imx8mm-noc", "fsl,imx8m-noc"; reg = <0x32700000 0x100000>; clocks = <&clk IMX8MM_CLK_NOC>; devfreq = <&ddrc>; + #interconnect-cells = <1>; + interconnect-node-id = <IMX8MM_ICN_NOC>; operating-points-v2 = <&noc_opp_table>; }; aips4: bus@32c00000 { compatible = "fsl,aips-bus", "simple-bus";
@@ -881,10 +884,11 @@ }; ddrc: dram-controller@3d400000 { compatible = "fsl,imx8mm-ddrc", "fsl,imx8m-ddrc"; reg = <0x3d400000 0x400000>; + interconnect-node-id = <IMX8MM_ICS_DRAM>; clock-names = "dram_core", "dram_pll", "dram_alt", "dram_apb"; clocks = <&clk IMX8MM_CLK_DRAM_CORE>,
arch/arm64/boot/dts/freescale/imx8mn.dtsi +4 -0
@@ -5,10 +5,11 @@ #include <dt-bindings/clock/imx8mn-clock.h> #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/input/input.h> #include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/interconnect/imx8mn.h> #include "imx8mn-pinfunc.h" / { interrupt-parent = <&gic>;
@@ -687,10 +688,12 @@ noc: interconnect@32700000 { compatible = "fsl,imx8mn-noc", "fsl,imx8m-noc"; reg = <0x32700000 0x100000>; clocks = <&clk IMX8MN_CLK_NOC>; devfreq = <&ddrc>; + #interconnect-cells = <1>; + interconnect-node-id = <IMX8MN_ICN_NOC>; operating-points-v2 = <&noc_opp_table>; }; aips4: bus@32c00000 { compatible = "fsl,aips-bus", "simple-bus";
@@ -790,10 +793,11 @@ "dram_apb"; clocks = <&clk IMX8MN_CLK_DRAM_CORE>, <&clk IMX8MN_DRAM_PLL>, <&clk IMX8MN_CLK_DRAM_ALT>, <&clk IMX8MN_CLK_DRAM_APB>; + interconnect-node-id = <IMX8MN_ICS_DRAM>; devfreq-events = <&ddr_pmu>; }; ddr_pmu: ddr-pmu@3d800000 { compatible = "fsl,imx8mn-ddr-pmu", "fsl,imx8m-ddr-pmu";
arch/arm64/boot/dts/freescale/imx8mq.dtsi +4 -0
@@ -9,10 +9,11 @@ #include <dt-bindings/reset/imx8mq-reset.h> #include <dt-bindings/gpio/gpio.h> #include "dt-bindings/input/input.h" #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/thermal/thermal.h> +#include <dt-bindings/interconnect/imx8mq.h> #include "imx8mq-pinfunc.h" / { interrupt-parent = <&gpc>;
@@ -950,10 +951,12 @@ noc: interconnect@32700000 { compatible = "fsl,imx8mq-noc", "fsl,imx8m-noc"; reg = <0x32700000 0x100000>; clocks = <&clk IMX8MQ_CLK_NOC>; devfreq = <&ddrc>; + #interconnect-cells = <1>; + interconnect-node-id = <IMX8MQ_ICN_NOC>; operating-points-v2 = <&noc_opp_table>; }; bus@32c00000 { /* AIPS4 */ compatible = "fsl,imx8mq-aips-bus", "simple-bus";
@@ -1144,10 +1147,11 @@ "dram_apb"; clocks = <&clk IMX8MQ_CLK_DRAM_CORE>, <&clk IMX8MQ_DRAM_PLL_OUT>, <&clk IMX8MQ_CLK_DRAM_ALT>, <&clk IMX8MQ_CLK_DRAM_APB>; + interconnect-node-id = <IMX8MQ_ICS_DRAM>; devfreq-events = <&ddr_pmu>; }; ddr_pmu: ddr-pmu@3d800000 { compatible = "fsl,imx8mq-ddr-pmu", "fsl,imx8m-ddr-pmu";
Signature · 1 line
2.17.1