interconnect: Add imx support via devfreq
Subsystems (4)
cover interconnect: Add imx support via devfreq
This series adds 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 is implemented as distinct devfreq drivers instead.
The imx interconnect provider doesn't communicate with devfreq directly but rather computes "minimum frequencies" for nodes along the path and creates dev_pm_qos requests.
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 avoids introducing "virtual" devices but it means that DT bindings of main NOC includes properties for both devfreq and interconnect.
Only the ddrc and main noc are scalable right now but more can be added.
Also available on a github branch (with various unrelated changes):
https://github.com/cdleonard/linux/tree/next
Testing currently requires NXP branch of atf+uboot
Martin: I believe you should be able to use this to control DRAM frequency from video by just adding interconnect consumer code to nwl-dsi. Sample code:
https://github.com/cdleonard/linux/commit/43772762aa5045f1ce5623740f9a4baef988d083 https://github.com/cdleonard/linux/commit/7b601e981b1f517b5d98b43bde292972ded13086
Changes since RFCv6:
* Replace scalable-nodes stuff with just a fsl,ddrc property. Future scalable nodes can be added as additional phandles on the NOC
* Allow building interconnect drivers as modules
* Handle icc_provider_del errors in imx_icc_unregister (like EBUSY).
* Rename imx-devfreq to imx-bus, similar to exynos-bus
* Explain why imx bus clock enabling is not required
* All dependencies accepted (some time ago).
Changes since RFCv5:
* Replace scanning for interconnect-node-id with explicit scalable-nodes/scalable-node-ids property on NoC.
* Now passes make dtbs_check
* Remove struct imx_icc_provider
* Switch to of_icc_xlate_onecell
* Use of_find_device_by_node to fetch QoS target, this causes fewer probe deferrals, removes dependency on devfreq API and even allows reloading ddrc module at runtime
* Add imx_icc_node_destroy helper
* Remove 0/1 on DEFINE_BUS_SLAVE/MASTER which created spurious links
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/cover/11021563/
Leonard Crestez (8):
dt-bindings: interconnect: Add bindings for imx8m noc PM / devfreq: Add generic imx bus scaling driver PM / devfreq: imx: Register interconnect device
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
.../bindings/interconnect/fsl,imx8m-noc.yaml | 138 ++++++++ arch/arm64/boot/dts/freescale/imx8mm.dtsi | 24 ++ arch/arm64/boot/dts/freescale/imx8mn.dtsi | 24 ++ arch/arm64/boot/dts/freescale/imx8mq.dtsi | 24 ++ drivers/devfreq/Kconfig | 9 + drivers/devfreq/Makefile | 1 + drivers/devfreq/imx-bus.c | 181 +++++++++++ drivers/interconnect/Kconfig | 1 + drivers/interconnect/Makefile | 1 + drivers/interconnect/imx/Kconfig | 17 + drivers/interconnect/imx/Makefile | 9 + drivers/interconnect/imx/imx.c | 298 ++++++++++++++++++ drivers/interconnect/imx/imx.h | 62 ++++ drivers/interconnect/imx/imx8mm.c | 108 +++++++ drivers/interconnect/imx/imx8mn.c | 97 ++++++ drivers/interconnect/imx/imx8mq.c | 106 +++++++ include/dt-bindings/interconnect/imx8mm.h | 49 +++ include/dt-bindings/interconnect/imx8mn.h | 41 +++ include/dt-bindings/interconnect/imx8mq.h | 48 +++ 19 files changed, 1238 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml create mode 100644 drivers/devfreq/imx-bus.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
PATCH 1/8 dt-bindings: interconnect: Add bindings for imx8m noc
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.
Main NOC node acts as interconnect provider if #interconnect-cells is present. Currently there is a single imx interconnect provider for the whole SOC.
Other pieces of scalable interconnects can be present, each with their own OPP table.
--- .../bindings/interconnect/fsl,imx8m-noc.yaml | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +138 -0
@@ -0,0 +1,138 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interconnect/fsl,imx8m-noc.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 + - const: fsl, imx8m-nic + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + operating-points-v2: true + opp-table: true + + fsl,ddrc: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: + Phandle to DDR Controller. + + '#interconnect-cells': + description: + If specified then also act as an interconnect provider. Should only be + set once per soc on the main noc. + const: 1 + +required: + - compatible + - clocks + +additionalProperties: false + +examples: + - | +#include <dt-bindings/clock/imx8mm-clock.h> +#include <dt-bindings/interconnect/imx8mm.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> + +noc: interconnect@32700000 { + compatible = "fsl,imx8mm-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MM_CLK_NOC>; + #interconnect-cells = <1>; + + /* Used to make requests for DEV_PM_QOS_MIN_FREQUENCY: */ + fsl,scalable-node-ids = <IMX8MM_ICN_NOC>, + <IMX8MM_ICN_MIPI>, + <IMX8MM_ICS_DRAM>; + fsl,scalable-nodes = <&noc>, + <&pl301_mipi>, + <&ddrc>; + + /* For passive governor: */ + devfreq = <&ddrc>; + + operating-points-v2 = <&noc_opp_table>; + noc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-133M { + opp-hz = /bits/ 64 <133333333>; + }; + opp-800M { + opp-hz = /bits/ 64 <800000000>; + }; + }; +}; + +pl301_mipi: interconnect@32500000 { + compatible = "fsl,imx8m-nic"; + reg = <0x32500000 0x100000>; + clocks = <&clk IMX8MM_CLK_DISP_AXI>; + operating-points-v2 = <&pl301_mipi_opp_table>; + + pl301_mipi_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-200M { + opp-hz = /bits/ 64 <200000000>; + }; + opp-500M { + opp-hz = /bits/ 64 <500000000>; + }; + }; +}; + +ddrc: memory-controller@3d400000 { + compatible = "fsl,imx8mm-ddrc", "fsl,imx8m-ddrc"; + reg = <0x3d400000 0x400000>; + glock-names = "core", "pll", "alt", "apb"; + clocks = <&clk IMX8MM_CLK_DRAM_CORE>, + <&clk IMX8MM_DRAM_PLL>, + <&clk IMX8MM_CLK_DRAM_ALT>, + <&clk IMX8MM_CLK_DRAM_APB>; + /* For ondemand governor: */ + devfreq-events = <&ddr_pmu>; +}; + +ddr_pmu: ddr-pmu@3d800000 { + compatible = "fsl,imx8mm-ddr-pmu", "fsl,imx8m-ddr-pmu"; + reg = <0x3d800000 0x400000>; + interrupt-parent = <&gic>; + interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; +};
Signature · 1 line
2.17.1
Rob Herring
maintainerRe: [PATCH 1/8] dt-bindings: interconnect: Add bindings for imx8m noc
Quoted 8 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.
Main NOC node acts as interconnect provider if #interconnect-cells is present. Currently there is a single imx interconnect provider for the whole SOC.
Quoted 9 lines
Other pieces of scalable interconnects can be present, each with their own OPP table.
Signed-off-by Leonard Crestez <[email protected]>--- .../bindings/interconnect/fsl,imx8m-noc.yaml | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml
My bot found errors running 'make dt_binding_check' on your patch:
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml: while parsing a block mapping
in "<unicode string>", line 4, column 1
did not find expected key
in "<unicode string>", line 79, column 9Documentation/devicetree/bindings/Makefile:12: recipe for target 'Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.example.dts' failed make[1]: *** [Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.example.dts] Error 1
make[1]: *** Waiting for unfinished jobs....
Makefile:1262: recipe for target 'dt_binding_check' failed
make: *** [dt_binding_check] Error 2
See https://patchwork.ozlabs.org/patch/1261720
If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure dt-schema is up to date:
pip3 install git+https://github.com/devicetree-org/dt-schema.git@master --upgrade
Please check and re-submit.
PATCH 2/8 PM / devfreq: Add generic imx bus scaling 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 map register areas.
--- drivers/devfreq/Kconfig | 9 +++ drivers/devfreq/Makefile | 1 + drivers/devfreq/imx-bus.c | 142 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 drivers/devfreq/imx-bus.c
drivers/devfreq/Kconfig +9 -0
@@ -99,10 +99,19 @@ config ARM_IMX8M_DDRC_DEVFREQ select DEVFREQ_GOV_USERSPACE help This adds the DEVFREQ driver for the i.MX8M DDR Controller. It allows adjusting DRAM frequency. +config ARM_IMX_BUS_DEVFREQ + tristate "i.MX Generic Bus DEVFREQ Driver" + depends on ARCH_MXC || COMPILE_TEST + select DEVFREQ_GOV_PASSIVE + select DEVFREQ_GOV_USERSPACE + help + This adds the generic DEVFREQ driver for i.MX interconnects. It + allows adjusting NIC/NOC frequency. + 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
@@ -7,10 +7,11 @@ obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o 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_BUS_DEVFREQ) += imx-bus.o obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.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
drivers/devfreq/imx-bus.c new file +142 -0
142 lines not on this page · raw message
Signature · 1 line
2.17.1
Chanwoo Choi
maintainerRe: [PATCH 2/8] PM / devfreq: Add generic imx bus scaling driver
Hi,
Looks good to me. I added the comments.
But, it need to add the dt binding documentation for this device.
The old email of Artur Świgoń is not used. On next time,
use following the new email address Because when I reply the mail, always show the fail message from thunderbird due to the Artur's old email. <[email protected]> -> <[email protected]>
Quoted 19 lines · Leonard Crestez
Add initial support for dynamic frequency switching on pieces of the imx interconnect fabric.
All this driver does is set a clk rate based on an opp table, it does not map register areas.
Signed-off-by Leonard Crestez <[email protected]>--- drivers/devfreq/Kconfig | 9 +++ drivers/devfreq/Makefile | 1 + drivers/devfreq/imx-bus.c | 142 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 drivers/devfreq/imx-bus.cdrivers/devfreq/Kconfig +0
-0
drivers/devfreq/Kconfig config ARM_IMX8M_DDRC_DEVFREQ · line 108
Quoted 10 lines
drivers/devfreq/Kconfig +5
-0@@ -99,10 +99,19 @@ config ARM_IMX8M_DDRC_DEVFREQ select DEVFREQ_GOV_USERSPACE help This adds the DEVFREQ driver for the i.MX8M DDR Controller. It allows adjusting DRAM frequency. +config ARM_IMX_BUS_DEVFREQ + tristate "i.MX Generic Bus DEVFREQ Driver" + depends on ARCH_MXC || COMPILE_TEST + select DEVFREQ_GOV_PASSIVE + select DEVFREQ_GOV_USERSPACE
Maybe, you would update it by using passive governor? But, in this version, it doesn't handle the any passive governor.
Quoted 14 lines
drivers/devfreq/Kconfig +4
-0+ help + This adds the generic DEVFREQ driver for i.MX interconnects. It + allows adjusting NIC/NOC frequency. + 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 +0
-0
drivers/devfreq/Makefile obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o · line 12
Quoted 6 lines
drivers/devfreq/Makefile +1
-0@@ -7,10 +7,11 @@ obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o 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_BUS_DEVFREQ) += imx-bus.o
The ARM_IMX_BUS_DEVFREQ config is under ARM_IMX8M_DDRC_DEVFREQ and imx-bus.o is over imx8m-ddrc.o. Need to edit the sequence.
Quoted 20 lines
drivers/devfreq/Makefile +0
-0obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.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.odrivers/devfreq/imx-bus.c new file +9
-0@@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright 2019 NXP +*/ + +#include <linux/clk.h> +#include <linux/devfreq.h> +#include <linux/device.h> +#include <linux/module.h>
drivers/devfreq/imx-bus.c line 19
Quoted 10 lines
drivers/devfreq/imx-bus.c new file +10
-0+#include <linux/of_device.h> +#include <linux/pm_opp.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +struct imx_bus { +struct devfreq_dev_profile profile; +struct devfreq *devfreq; +struct clk *clk; +struct devfreq_passive_data passive_data;
This patch doesn't touch the passive_data.
Quoted 7 lines
drivers/devfreq/imx-bus.c new file +7
-0+}; + +static int imx_bus_target (struct device *dev, +unsigned long *freq,u32 flags) +{ +struct imx_bus *priv =dev_get_drvdata (dev); +struct dev_pm_opp *new_opp;
drivers/devfreq/imx-bus.c line 36
Quoted 10 lines
drivers/devfreq/imx-bus.c new file +10
-0+unsigned long new_freq; +int ret; + + new_opp =devfreq_recommended_opp (dev, freq, flags); +if (IS_ERR (new_opp)) { + ret =PTR_ERR (new_opp); +dev_err (dev,"failed to get recommended opp: %d\n" , ret); +return ret; + } + new_freq =dev_pm_opp_get_freq (new_opp);
It doesn't need. Because the new frequency is stored to 'freq' by calling devfreq_recommended_opp().
drivers/devfreq/imx-bus.c line 39
Quoted 3 lines
drivers/devfreq/imx-bus.c new file +3
-0+dev_pm_opp_put (new_opp); + +return clk_set_rate (priv->clk, new_freq);
nitpick. you can use dev_pm_opp_set_rate(). But, I'm not forcing to use it.
Quoted 31 lines
drivers/devfreq/imx-bus.c new file +31
-0+} + +static int imx_bus_get_cur_freq (struct device *dev,unsigned long *freq) +{ +struct imx_bus *priv =dev_get_drvdata (dev); + + *freq =clk_get_rate (priv->clk); + +return 0 ; +} + +static int imx_bus_get_dev_status (struct device *dev, +struct devfreq_dev_status *stat) +{ +struct imx_bus *priv =dev_get_drvdata (dev); + + stat->busy_time =0 ; + stat->total_time =0 ; + stat->current_frequency =clk_get_rate (priv->clk); + +return 0 ; +} + +static void imx_bus_exit (struct device *dev) +{ +dev_pm_opp_of_remove_table (dev); +} + +static int imx_bus_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev;
drivers/devfreq/imx-bus.c line 80
Quoted 10 lines
drivers/devfreq/imx-bus.c new file +10
-0+struct imx_bus *priv; +const char *gov =DEVFREQ_GOV_USERSPACE ; +int ret; + + priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + +/* +* Fetch the clock to adjust but don't explictly enable.
Need to fix typo.
s/explictly/explicitly
Quoted 63 lines
drivers/devfreq/imx-bus.c new file +62
-0+* +* For imx bus clock clk_set_rate is safe no matter if the clock is on +* or off and some peripheral side-buses might be off unless enabled by +* drivers for devices on those specific buses. +* +* Rate adjustment on a disabled bus clock just takes effect later. +*/ + priv->clk =devm_clk_get (dev,NULL ); +if (IS_ERR (priv->clk)) { + ret =PTR_ERR (priv->clk); +dev_err (dev,"failed to fetch clk: %d\n" , ret); +return ret; + } +platform_set_drvdata (pdev, priv); + + ret =dev_pm_opp_of_add_table (dev); +if (ret <0 ) { +dev_err (dev,"failed to get OPP table\n" ); +return ret; + } + + priv->profile.polling_ms =1000 ; + priv->profile.target = imx_bus_target; + priv->profile.get_dev_status = imx_bus_get_dev_status; + priv->profile.exit = imx_bus_exit; + priv->profile.get_cur_freq = imx_bus_get_cur_freq; + priv->profile.initial_freq =clk_get_rate (priv->clk); + + priv->devfreq =devm_devfreq_add_device (dev, &priv->profile, + gov,NULL ); +if (IS_ERR (priv->devfreq)) { + ret =PTR_ERR (priv->devfreq); +dev_err (dev,"failed to add devfreq device: %d\n" , ret); + goto err; + } + +return 0 ; + +err: +dev_pm_opp_of_remove_table (dev); +return ret; +} + +static const struct of_device_id imx_bus_of_match[] = { + { .compatible ="fsl,imx8m-noc" , }, + { .compatible ="fsl,imx8m-nic" , }, + {/* sentinel */ }, +}; +MODULE_DEVICE_TABLE (of, imx_bus_of_match); + +static struct platform_driver imx_bus_platdrv = { + .probe = imx_bus_probe, + .driver = { + .name ="imx-bus-devfreq" , + .of_match_table =of_match_ptr (imx_bus_of_match), + }, +}; +module_platform_driver (imx_bus_platdrv); + +MODULE_DESCRIPTION ("Generic i.MX bus frequency scaling driver" ); +MODULE_AUTHOR ("Leonard Crestez <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );
Signature · 3 lines
Best Regards, Chanwoo Choi Samsung Electronics
Re: [PATCH 2/8] PM / devfreq: Add generic imx bus scaling driver
Quoted 4 lines · Chanwoo Choi
Hi,
Looks good to me. I added the comments.
But, it need to add the dt binding documentation for this device.
DT bindings were included:
https://patchwork.kernel.org/patch/11458981/
Quoted 4 lines
The old email of Artur Świgoń is not used. On next time,
use following the new email address Because when I reply the mail, always show the fail message from thunderbird due to the Artur's old email. <[email protected]> -> <[email protected]>
Yeah, I received multiple bounces because of this.
Quoted 25 lines · Leonard Crestez
Quoted 24 lines
Add initial support for dynamic frequency switching on pieces of the imx interconnect fabric.
All this driver does is set a clk rate based on an opp table, it does not map register areas.
Signed-off-by Leonard Crestez <[email protected]>--- drivers/devfreq/Kconfig | 9 +++ drivers/devfreq/Makefile | 1 + drivers/devfreq/imx-bus.c | 142 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+)create mode 100644
drivers/devfreq/imx-bus.cdrivers/devfreq/Kconfig +0
-0@@ -99,10 +99,19 @@ config ARM_IMX8M_DDRC_DEVFREQ select DEVFREQ_GOV_USERSPACE help This adds the DEVFREQ driver for the i.MX8M DDR Controller. It allows adjusting DRAM frequency.
Quoted 8 lines
drivers/devfreq/Kconfig config ARM_IMX8M_DDRC_DEVFREQ · line 108
Quoted 5 lines
drivers/devfreq/Kconfig +5
-0+config ARM_IMX_BUS_DEVFREQ + tristate "i.MX Generic Bus DEVFREQ Driver" + depends on ARCH_MXC || COMPILE_TEST + select DEVFREQ_GOV_PASSIVE + select DEVFREQ_GOV_USERSPACEMaybe, you would update it by using passive governor? But, in this version, it doesn't handle the any passive governor.
dropped
Quoted 17 lines
Quoted 17 lines
drivers/devfreq/Kconfig +4
-0+ help + This adds the generic DEVFREQ driver for i.MX interconnects. It + allows adjusting NIC/NOC frequency. + 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 +0
-0@@ -7,10 +7,11 @@ obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o
Quoted 6 lines
drivers/devfreq/Makefile obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o · line 12
Quoted 3 lines
drivers/devfreq/Makefile +1
-0# DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o +obj-$(CONFIG_ARM_IMX_BUS_DEVFREQ) += imx-bus.oThe
ARM_IMX_BUS_DEVFREQconfig is underARM_IMX8M_DDRC_DEVFREQand imx-bus.o is over imx8m-ddrc.o. Need to edit the sequence.
Reordered kconfig to match. 8M_DDRC sorts before _BUS alphabetically but it's pettier this way, and matches tegra.
Quoted 24 lines
Quoted 24 lines
drivers/devfreq/Makefile +0
-0obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.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.odrivers/devfreq/imx-bus.c new file +13
-0@@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright 2019 NXP +*/ + +#include <linux/clk.h> +#include <linux/devfreq.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/pm_opp.h> +#include <linux/platform_device.h> +#include <linux/slab.h>
Quoted 8 lines
drivers/devfreq/imx-bus.c line 19
Quoted 6 lines
drivers/devfreq/imx-bus.c new file +6
-0+ +struct imx_bus { +struct devfreq_dev_profile profile; +struct devfreq *devfreq; +struct clk *clk; +struct devfreq_passive_data passive_data;This patch doesn't touch the
passive_data.
dropped
Quoted 12 lines
Quoted 12 lines
drivers/devfreq/imx-bus.c new file +12
-0+}; + +static int imx_bus_target (struct device *dev, +unsigned long *freq,u32 flags) +{ +struct imx_bus *priv =dev_get_drvdata (dev); +struct dev_pm_opp *new_opp; +unsigned long new_freq; +int ret; + + new_opp =devfreq_recommended_opp (dev, freq, flags); +if (IS_ERR (new_opp)) {
Quoted 8 lines
drivers/devfreq/imx-bus.c line 36
Quoted 5 lines
drivers/devfreq/imx-bus.c new file +5
-0+ ret =PTR_ERR (new_opp); +dev_err (dev,"failed to get recommended opp: %d\n" , ret); +return ret; + } + new_freq =dev_pm_opp_get_freq (new_opp);It doesn't need. Because the new frequency is stored to 'freq' by calling
devfreq_recommended_opp().
fixed
Quoted 5 lines
drivers/devfreq/imx-bus.c line 39
Quoted 3 lines
drivers/devfreq/imx-bus.c new file +3
-0+dev_pm_opp_put (new_opp); + +return clk_set_rate (priv->clk, new_freq);nitpick. you can use
dev_pm_opp_set_rate(). But, I'm not forcing to use it.
Switched to dev_pm_opp_set_rate.
It might be interesting to add regulators control later, on some chips the main NOC can run at different voltages.
Quoted 37 lines
Quoted 37 lines
drivers/devfreq/imx-bus.c new file +36
-0+} + +static int imx_bus_get_cur_freq (struct device *dev,unsigned long *freq) +{ +struct imx_bus *priv =dev_get_drvdata (dev); + + *freq =clk_get_rate (priv->clk); + +return 0 ; +} + +static int imx_bus_get_dev_status (struct device *dev, +struct devfreq_dev_status *stat) +{ +struct imx_bus *priv =dev_get_drvdata (dev); + + stat->busy_time =0 ; + stat->total_time =0 ; + stat->current_frequency =clk_get_rate (priv->clk); + +return 0 ; +} + +static void imx_bus_exit (struct device *dev) +{ +dev_pm_opp_of_remove_table (dev); +} + +static int imx_bus_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct imx_bus *priv; +const char *gov =DEVFREQ_GOV_USERSPACE ; +int ret; + + priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL );
Quoted 8 lines
drivers/devfreq/imx-bus.c line 80
Quoted 5 lines
drivers/devfreq/imx-bus.c new file +5
-0+if (!priv) +return -ENOMEM ; + +/* +* Fetch the clock to adjust but don't explictly enable. Need to fix typo.
s/explictly/explicitly
fixed
Quoted 65 lines
Quoted 63 lines
drivers/devfreq/imx-bus.c new file +62
-0+* +* For imx bus clock clk_set_rate is safe no matter if the clock is on +* or off and some peripheral side-buses might be off unless enabled by +* drivers for devices on those specific buses. +* +* Rate adjustment on a disabled bus clock just takes effect later. +*/ + priv->clk =devm_clk_get (dev,NULL ); +if (IS_ERR (priv->clk)) { + ret =PTR_ERR (priv->clk); +dev_err (dev,"failed to fetch clk: %d\n" , ret); +return ret; + } +platform_set_drvdata (pdev, priv); + + ret =dev_pm_opp_of_add_table (dev); +if (ret <0 ) { +dev_err (dev,"failed to get OPP table\n" ); +return ret; + } + + priv->profile.polling_ms =1000 ; + priv->profile.target = imx_bus_target; + priv->profile.get_dev_status = imx_bus_get_dev_status; + priv->profile.exit = imx_bus_exit; + priv->profile.get_cur_freq = imx_bus_get_cur_freq; + priv->profile.initial_freq =clk_get_rate (priv->clk); + + priv->devfreq =devm_devfreq_add_device (dev, &priv->profile, + gov,NULL ); +if (IS_ERR (priv->devfreq)) { + ret =PTR_ERR (priv->devfreq); +dev_err (dev,"failed to add devfreq device: %d\n" , ret); + goto err; + } + +return 0 ; + +err: +dev_pm_opp_of_remove_table (dev); +return ret; +} + +static const struct of_device_id imx_bus_of_match[] = { + { .compatible ="fsl,imx8m-noc" , }, + { .compatible ="fsl,imx8m-nic" , }, + {/* sentinel */ }, +}; +MODULE_DEVICE_TABLE (of, imx_bus_of_match); + +static struct platform_driver imx_bus_platdrv = { + .probe = imx_bus_probe, + .driver = { + .name ="imx-bus-devfreq" , + .of_match_table =of_match_ptr (imx_bus_of_match), + }, +}; +module_platform_driver (imx_bus_platdrv); + +MODULE_DESCRIPTION ("Generic i.MX bus frequency scaling driver" ); +MODULE_AUTHOR ("Leonard Crestez <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );
Chanwoo Choi
maintainerRe: [PATCH 2/8] PM / devfreq: Add generic imx bus scaling driver
Quoted 9 lines · Leonard Crestez
Quoted 4 lines · Chanwoo Choi
Hi,
Looks good to me. I added the comments.
But, it need to add the dt binding documentation for this device.DT bindings were included:
The dt-binding document for this driver is required under Documentation/devicetree/binding/devfreq.
It is difficult to catch where is the dt-binding document for this driver for who don't know the detailed history of this driver. I don't said that add the duplicate documentation But, at least the some document have to point out the reference.
Quoted 257 lines
Quoted 5 lines
The old email of Artur Świgoń is not used. On next time,
use following the new email address Because when I reply the mail, always show the fail message from thunderbird due to the Artur's old email. <[email protected]> -> <[email protected]>Yeah, I received multiple bounces because of this.
Quoted 25 lines · Leonard Crestez
Quoted 24 lines
Add initial support for dynamic frequency switching on pieces of the imx interconnect fabric.
All this driver does is set a clk rate based on an opp table, it does not map register areas.
Signed-off-by Leonard Crestez <[email protected]>--- drivers/devfreq/Kconfig | 9 +++ drivers/devfreq/Makefile | 1 + drivers/devfreq/imx-bus.c | 142 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+)create mode 100644
drivers/devfreq/imx-bus.cdrivers/devfreq/Kconfig +0
-0@@ -99,10 +99,19 @@ config ARM_IMX8M_DDRC_DEVFREQ select DEVFREQ_GOV_USERSPACE help This adds the DEVFREQ driver for the i.MX8M DDR Controller. It allows adjusting DRAM frequency.Quoted 8 lines
drivers/devfreq/Kconfig config ARM_IMX8M_DDRC_DEVFREQ · line 108
Quoted 5 lines
drivers/devfreq/Kconfig +5
-0+config ARM_IMX_BUS_DEVFREQ + tristate "i.MX Generic Bus DEVFREQ Driver" + depends on ARCH_MXC || COMPILE_TEST + select DEVFREQ_GOV_PASSIVE + select DEVFREQ_GOV_USERSPACEMaybe, you would update it by using passive governor? But, in this version, it doesn't handle the any passive governor.
dropped
Quoted 17 lines
Quoted 17 lines
drivers/devfreq/Kconfig +4
-0+ help + This adds the generic DEVFREQ driver for i.MX interconnects. It + allows adjusting NIC/NOC frequency. + 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 +0
-0@@ -7,10 +7,11 @@ obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.oQuoted 6 lines
drivers/devfreq/Makefile obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o · line 12
Quoted 3 lines
drivers/devfreq/Makefile +1
-0# DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o +obj-$(CONFIG_ARM_IMX_BUS_DEVFREQ) += imx-bus.oThe
ARM_IMX_BUS_DEVFREQconfig is underARM_IMX8M_DDRC_DEVFREQand imx-bus.o is over imx8m-ddrc.o. Need to edit the sequence.Reordered kconfig to match. 8M_DDRC sorts before
_BUSalphabetically but it's pettier this way, and matches tegra.Quoted 24 lines
Quoted 24 lines
drivers/devfreq/Makefile +0
-0obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.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.odrivers/devfreq/imx-bus.c new file +13
-0@@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright 2019 NXP +*/ + +#include <linux/clk.h> +#include <linux/devfreq.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/pm_opp.h> +#include <linux/platform_device.h> +#include <linux/slab.h> Quoted 8 lines
drivers/devfreq/imx-bus.c line 19
Quoted 6 lines
drivers/devfreq/imx-bus.c new file +6
-0+ +struct imx_bus { +struct devfreq_dev_profile profile; +struct devfreq *devfreq; +struct clk *clk; +struct devfreq_passive_data passive_data;This patch doesn't touch the
passive_data.dropped
Quoted 12 lines
Quoted 12 lines
drivers/devfreq/imx-bus.c new file +12
-0+}; + +static int imx_bus_target (struct device *dev, +unsigned long *freq,u32 flags) +{ +struct imx_bus *priv =dev_get_drvdata (dev); +struct dev_pm_opp *new_opp; +unsigned long new_freq; +int ret; + + new_opp =devfreq_recommended_opp (dev, freq, flags); +if (IS_ERR (new_opp)) {Quoted 8 lines
drivers/devfreq/imx-bus.c line 36
Quoted 5 lines
drivers/devfreq/imx-bus.c new file +5
-0+ ret =PTR_ERR (new_opp); +dev_err (dev,"failed to get recommended opp: %d\n" , ret); +return ret; + } + new_freq =dev_pm_opp_get_freq (new_opp);It doesn't need. Because the new frequency is stored to 'freq' by calling
devfreq_recommended_opp().fixed
Quoted 5 lines
drivers/devfreq/imx-bus.c line 39
Quoted 3 lines
drivers/devfreq/imx-bus.c new file +3
-0+dev_pm_opp_put (new_opp); + +return clk_set_rate (priv->clk, new_freq);nitpick. you can use
dev_pm_opp_set_rate(). But, I'm not forcing to use it.Switched to
dev_pm_opp_set_rate.It might be interesting to add regulators control later, on some chips the main NOC can run at different voltages.
Quoted 37 lines
Quoted 37 lines
drivers/devfreq/imx-bus.c new file +36
-0+} + +static int imx_bus_get_cur_freq (struct device *dev,unsigned long *freq) +{ +struct imx_bus *priv =dev_get_drvdata (dev); + + *freq =clk_get_rate (priv->clk); + +return 0 ; +} + +static int imx_bus_get_dev_status (struct device *dev, +struct devfreq_dev_status *stat) +{ +struct imx_bus *priv =dev_get_drvdata (dev); + + stat->busy_time =0 ; + stat->total_time =0 ; + stat->current_frequency =clk_get_rate (priv->clk); + +return 0 ; +} + +static void imx_bus_exit (struct device *dev) +{ +dev_pm_opp_of_remove_table (dev); +} + +static int imx_bus_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct imx_bus *priv; +const char *gov =DEVFREQ_GOV_USERSPACE ; +int ret; + + priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL );Quoted 8 lines
drivers/devfreq/imx-bus.c line 80
Quoted 5 lines
drivers/devfreq/imx-bus.c new file +5
-0+if (!priv) +return -ENOMEM ; + +/* +* Fetch the clock to adjust but don't explictly enable. Need to fix typo.
s/explictly/explicitlyfixed
Quoted 65 lines
Quoted 63 lines
drivers/devfreq/imx-bus.c new file +62
-0+* +* For imx bus clock clk_set_rate is safe no matter if the clock is on +* or off and some peripheral side-buses might be off unless enabled by +* drivers for devices on those specific buses. +* +* Rate adjustment on a disabled bus clock just takes effect later. +*/ + priv->clk =devm_clk_get (dev,NULL ); +if (IS_ERR (priv->clk)) { + ret =PTR_ERR (priv->clk); +dev_err (dev,"failed to fetch clk: %d\n" , ret); +return ret; + } +platform_set_drvdata (pdev, priv); + + ret =dev_pm_opp_of_add_table (dev); +if (ret <0 ) { +dev_err (dev,"failed to get OPP table\n" ); +return ret; + } + + priv->profile.polling_ms =1000 ; + priv->profile.target = imx_bus_target; + priv->profile.get_dev_status = imx_bus_get_dev_status; + priv->profile.exit = imx_bus_exit; + priv->profile.get_cur_freq = imx_bus_get_cur_freq; + priv->profile.initial_freq =clk_get_rate (priv->clk); + + priv->devfreq =devm_devfreq_add_device (dev, &priv->profile, + gov,NULL ); +if (IS_ERR (priv->devfreq)) { + ret =PTR_ERR (priv->devfreq); +dev_err (dev,"failed to add devfreq device: %d\n" , ret); + goto err; + } + +return 0 ; + +err: +dev_pm_opp_of_remove_table (dev); +return ret; +} + +static const struct of_device_id imx_bus_of_match[] = { + { .compatible ="fsl,imx8m-noc" , }, + { .compatible ="fsl,imx8m-nic" , }, + {/* sentinel */ }, +}; +MODULE_DEVICE_TABLE (of, imx_bus_of_match); + +static struct platform_driver imx_bus_platdrv = { + .probe = imx_bus_probe, + .driver = { + .name ="imx-bus-devfreq" , + .of_match_table =of_match_ptr (imx_bus_of_match), + }, +}; +module_platform_driver (imx_bus_platdrv); + +MODULE_DESCRIPTION ("Generic i.MX bus frequency scaling driver" ); +MODULE_AUTHOR ("Leonard Crestez <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );
Signature · 3 lines
Best Regards, Chanwoo Choi Samsung Electronics
Re: [PATCH 2/8] PM / devfreq: Add generic imx bus scaling driver
Quoted 7 lines · Chanwoo Choi
Quoted 6 lines · Leonard Crestez
Quoted 4 lines · Chanwoo Choi
Hi,
Looks good to me. I added the comments.
But, it need to add the dt binding documentation for this device.
Quoted 6 lines
Quoted 3 lines
DT bindings were included:
The dt-binding document for this driver is required under
Documentation/devicetree/binding/devfreq.
Bindings for imx8m-ddrc were at one point posted for devicetree/bindings/devfreq but Rob Herring suggested to move them under "memory-controller" instead and I expect same logic makes sense here. Link to previous discussion:
https://patchwork.kernel.org/patch/11221919/
DT bindings should try to describe "hardware" rather than "drivers" and an "interconnect" is a class of hardware while "devfreq" isn't.
Not only that but the main noc has properties parsed by interconnect driver.
Quoted 4 lines
It is difficult to catch where is the dt-binding document for this driver for who don't know the detailed history of this driver. I don't said that add the duplicate documentation But, at least the some document have to point out the reference.
What I usually do to find information about a device is grep for the compat string in the entire tree.
Quoted 258 lines
Quoted 256 lines
Quoted 4 lines
The old email of Artur Świgoń is not used. On next time,
use following the new email address Because when I reply the mail, always show the fail message from thunderbird due to the Artur's old email. <[email protected]> -> <[email protected]>Yeah, I received multiple bounces because of this.
Quoted 25 lines · Leonard Crestez
Quoted 24 lines
Add initial support for dynamic frequency switching on pieces of the imx interconnect fabric.
All this driver does is set a clk rate based on an opp table, it does not map register areas.
Signed-off-by Leonard Crestez <[email protected]>--- drivers/devfreq/Kconfig | 9 +++ drivers/devfreq/Makefile | 1 + drivers/devfreq/imx-bus.c | 142 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+)create mode 100644
drivers/devfreq/imx-bus.cdrivers/devfreq/Kconfig +0
-0@@ -99,10 +99,19 @@ config ARM_IMX8M_DDRC_DEVFREQ select DEVFREQ_GOV_USERSPACE help This adds the DEVFREQ driver for the i.MX8M DDR Controller. It allows adjusting DRAM frequency.Quoted 8 lines
drivers/devfreq/Kconfig config ARM_IMX8M_DDRC_DEVFREQ · line 108
Quoted 5 lines
drivers/devfreq/Kconfig +5
-0+config ARM_IMX_BUS_DEVFREQ + tristate "i.MX Generic Bus DEVFREQ Driver" + depends on ARCH_MXC || COMPILE_TEST + select DEVFREQ_GOV_PASSIVE + select DEVFREQ_GOV_USERSPACEMaybe, you would update it by using passive governor? But, in this version, it doesn't handle the any passive governor.
dropped
Quoted 17 lines
Quoted 17 lines
drivers/devfreq/Kconfig +4
-0+ help + This adds the generic DEVFREQ driver for i.MX interconnects. It + allows adjusting NIC/NOC frequency. + 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 +0
-0@@ -7,10 +7,11 @@ obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.oQuoted 6 lines
drivers/devfreq/Makefile obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o · line 12
Quoted 3 lines
drivers/devfreq/Makefile +1
-0# DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o +obj-$(CONFIG_ARM_IMX_BUS_DEVFREQ) += imx-bus.oThe
ARM_IMX_BUS_DEVFREQconfig is underARM_IMX8M_DDRC_DEVFREQand imx-bus.o is over imx8m-ddrc.o. Need to edit the sequence.Reordered kconfig to match. 8M_DDRC sorts before
_BUSalphabetically but it's pettier this way, and matches tegra.Quoted 24 lines
Quoted 24 lines
drivers/devfreq/Makefile +0
-0obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.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.odrivers/devfreq/imx-bus.c new file +13
-0@@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright 2019 NXP +*/ + +#include <linux/clk.h> +#include <linux/devfreq.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/pm_opp.h> +#include <linux/platform_device.h> +#include <linux/slab.h> Quoted 8 lines
drivers/devfreq/imx-bus.c line 19
Quoted 6 lines
drivers/devfreq/imx-bus.c new file +6
-0+ +struct imx_bus { +struct devfreq_dev_profile profile; +struct devfreq *devfreq; +struct clk *clk; +struct devfreq_passive_data passive_data;This patch doesn't touch the
passive_data.dropped
Quoted 12 lines
Quoted 12 lines
drivers/devfreq/imx-bus.c new file +12
-0+}; + +static int imx_bus_target (struct device *dev, +unsigned long *freq,u32 flags) +{ +struct imx_bus *priv =dev_get_drvdata (dev); +struct dev_pm_opp *new_opp; +unsigned long new_freq; +int ret; + + new_opp =devfreq_recommended_opp (dev, freq, flags); +if (IS_ERR (new_opp)) {Quoted 8 lines
drivers/devfreq/imx-bus.c line 36
Quoted 5 lines
drivers/devfreq/imx-bus.c new file +5
-0+ ret =PTR_ERR (new_opp); +dev_err (dev,"failed to get recommended opp: %d\n" , ret); +return ret; + } + new_freq =dev_pm_opp_get_freq (new_opp);It doesn't need. Because the new frequency is stored to 'freq' by calling
devfreq_recommended_opp().fixed
Quoted 5 lines
drivers/devfreq/imx-bus.c line 39
Quoted 3 lines
drivers/devfreq/imx-bus.c new file +3
-0+dev_pm_opp_put (new_opp); + +return clk_set_rate (priv->clk, new_freq);nitpick. you can use
dev_pm_opp_set_rate(). But, I'm not forcing to use it.Switched to
dev_pm_opp_set_rate.It might be interesting to add regulators control later, on some chips the main NOC can run at different voltages.
Quoted 37 lines
Quoted 37 lines
drivers/devfreq/imx-bus.c new file +36
-0+} + +static int imx_bus_get_cur_freq (struct device *dev,unsigned long *freq) +{ +struct imx_bus *priv =dev_get_drvdata (dev); + + *freq =clk_get_rate (priv->clk); + +return 0 ; +} + +static int imx_bus_get_dev_status (struct device *dev, +struct devfreq_dev_status *stat) +{ +struct imx_bus *priv =dev_get_drvdata (dev); + + stat->busy_time =0 ; + stat->total_time =0 ; + stat->current_frequency =clk_get_rate (priv->clk); + +return 0 ; +} + +static void imx_bus_exit (struct device *dev) +{ +dev_pm_opp_of_remove_table (dev); +} + +static int imx_bus_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct imx_bus *priv; +const char *gov =DEVFREQ_GOV_USERSPACE ; +int ret; + + priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL );Quoted 8 lines
drivers/devfreq/imx-bus.c line 80
Quoted 5 lines
drivers/devfreq/imx-bus.c new file +5
-0+if (!priv) +return -ENOMEM ; + +/* +* Fetch the clock to adjust but don't explictly enable. Need to fix typo.
s/explictly/explicitlyfixed
Quoted 65 lines
Quoted 63 lines
drivers/devfreq/imx-bus.c new file +62
-0+* +* For imx bus clock clk_set_rate is safe no matter if the clock is on +* or off and some peripheral side-buses might be off unless enabled by +* drivers for devices on those specific buses. +* +* Rate adjustment on a disabled bus clock just takes effect later. +*/ + priv->clk =devm_clk_get (dev,NULL ); +if (IS_ERR (priv->clk)) { + ret =PTR_ERR (priv->clk); +dev_err (dev,"failed to fetch clk: %d\n" , ret); +return ret; + } +platform_set_drvdata (pdev, priv); + + ret =dev_pm_opp_of_add_table (dev); +if (ret <0 ) { +dev_err (dev,"failed to get OPP table\n" ); +return ret; + } + + priv->profile.polling_ms =1000 ; + priv->profile.target = imx_bus_target; + priv->profile.get_dev_status = imx_bus_get_dev_status; + priv->profile.exit = imx_bus_exit; + priv->profile.get_cur_freq = imx_bus_get_cur_freq; + priv->profile.initial_freq =clk_get_rate (priv->clk); + + priv->devfreq =devm_devfreq_add_device (dev, &priv->profile, + gov,NULL ); +if (IS_ERR (priv->devfreq)) { + ret =PTR_ERR (priv->devfreq); +dev_err (dev,"failed to add devfreq device: %d\n" , ret); + goto err; + } + +return 0 ; + +err: +dev_pm_opp_of_remove_table (dev); +return ret; +} + +static const struct of_device_id imx_bus_of_match[] = { + { .compatible ="fsl,imx8m-noc" , }, + { .compatible ="fsl,imx8m-nic" , }, + {/* sentinel */ }, +}; +MODULE_DEVICE_TABLE (of, imx_bus_of_match); + +static struct platform_driver imx_bus_platdrv = { + .probe = imx_bus_probe, + .driver = { + .name ="imx-bus-devfreq" , + .of_match_table =of_match_ptr (imx_bus_of_match), + }, +}; +module_platform_driver (imx_bus_platdrv); + +MODULE_DESCRIPTION ("Generic i.MX bus frequency scaling driver" ); +MODULE_AUTHOR ("Leonard Crestez <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );
Chanwoo Choi
maintainerRe: [PATCH 2/8] PM / devfreq: Add generic imx bus scaling driver
Quoted 20 lines · Leonard Crestez
Quoted 7 lines · Chanwoo Choi
Quoted 6 lines · Leonard Crestez
Quoted 4 lines · Chanwoo Choi
Hi,
Looks good to me. I added the comments.
But, it need to add the dt binding documentation for this device.Quoted 6 lines
Quoted 3 lines
DT bindings were included:
The dt-binding document for this driver is required under
Documentation/devicetree/binding/devfreq.Bindings for imx8m-ddrc were at one point posted for devicetree/bindings/devfreq but Rob Herring suggested to move them under "memory-controller" instead and I expect same logic makes sense here. Link to previous discussion:
Quoted 6 lines
https://patchwork.kernel.org/patch/11221919/
DT bindings should try to describe "hardware" rather than "drivers" and an "interconnect" is a class of hardware while "devfreq" isn't.
Not only that but the main noc has properties parsed by interconnect driver.
OK. Thanks for reply.
Quoted 270 lines
Quoted 5 lines
It is difficult to catch where is the dt-binding document for this driver for who don't know the detailed history of this driver. I don't said that add the duplicate documentation But, at least the some document have to point out the reference.
What I usually do to find information about a device is grep for the compat string in the entire tree.
Quoted 258 lines
Quoted 256 lines
Quoted 4 lines
The old email of Artur Świgoń is not used. On next time,
use following the new email address Because when I reply the mail, always show the fail message from thunderbird due to the Artur's old email. <[email protected]> -> <[email protected]>Yeah, I received multiple bounces because of this.
Quoted 25 lines · Leonard Crestez
Quoted 24 lines
Add initial support for dynamic frequency switching on pieces of the imx interconnect fabric.
All this driver does is set a clk rate based on an opp table, it does not map register areas.
Signed-off-by Leonard Crestez <[email protected]>--- drivers/devfreq/Kconfig | 9 +++ drivers/devfreq/Makefile | 1 + drivers/devfreq/imx-bus.c | 142 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+)create mode 100644
drivers/devfreq/imx-bus.cdrivers/devfreq/Kconfig +0
-0@@ -99,10 +99,19 @@ config ARM_IMX8M_DDRC_DEVFREQ select DEVFREQ_GOV_USERSPACE help This adds the DEVFREQ driver for the i.MX8M DDR Controller. It allows adjusting DRAM frequency.Quoted 8 lines
drivers/devfreq/Kconfig config ARM_IMX8M_DDRC_DEVFREQ · line 108
Quoted 5 lines
drivers/devfreq/Kconfig +5
-0+config ARM_IMX_BUS_DEVFREQ + tristate "i.MX Generic Bus DEVFREQ Driver" + depends on ARCH_MXC || COMPILE_TEST + select DEVFREQ_GOV_PASSIVE + select DEVFREQ_GOV_USERSPACEMaybe, you would update it by using passive governor? But, in this version, it doesn't handle the any passive governor.
dropped
Quoted 17 lines
Quoted 17 lines
drivers/devfreq/Kconfig +4
-0+ help + This adds the generic DEVFREQ driver for i.MX interconnects. It + allows adjusting NIC/NOC frequency. + 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 +0
-0@@ -7,10 +7,11 @@ obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.oQuoted 6 lines
drivers/devfreq/Makefile obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o · line 12
Quoted 3 lines
drivers/devfreq/Makefile +1
-0# DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o +obj-$(CONFIG_ARM_IMX_BUS_DEVFREQ) += imx-bus.oThe
ARM_IMX_BUS_DEVFREQconfig is underARM_IMX8M_DDRC_DEVFREQand imx-bus.o is over imx8m-ddrc.o. Need to edit the sequence.Reordered kconfig to match. 8M_DDRC sorts before
_BUSalphabetically but it's pettier this way, and matches tegra.Quoted 24 lines
Quoted 24 lines
drivers/devfreq/Makefile +0
-0obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.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.odrivers/devfreq/imx-bus.c new file +13
-0@@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright 2019 NXP +*/ + +#include <linux/clk.h> +#include <linux/devfreq.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/pm_opp.h> +#include <linux/platform_device.h> +#include <linux/slab.h> Quoted 8 lines
drivers/devfreq/imx-bus.c line 19
Quoted 6 lines
drivers/devfreq/imx-bus.c new file +6
-0+ +struct imx_bus { +struct devfreq_dev_profile profile; +struct devfreq *devfreq; +struct clk *clk; +struct devfreq_passive_data passive_data;This patch doesn't touch the
passive_data.dropped
Quoted 12 lines
Quoted 12 lines
drivers/devfreq/imx-bus.c new file +12
-0+}; + +static int imx_bus_target (struct device *dev, +unsigned long *freq,u32 flags) +{ +struct imx_bus *priv =dev_get_drvdata (dev); +struct dev_pm_opp *new_opp; +unsigned long new_freq; +int ret; + + new_opp =devfreq_recommended_opp (dev, freq, flags); +if (IS_ERR (new_opp)) {Quoted 8 lines
drivers/devfreq/imx-bus.c line 36
Quoted 5 lines
drivers/devfreq/imx-bus.c new file +5
-0+ ret =PTR_ERR (new_opp); +dev_err (dev,"failed to get recommended opp: %d\n" , ret); +return ret; + } + new_freq =dev_pm_opp_get_freq (new_opp);It doesn't need. Because the new frequency is stored to 'freq' by calling
devfreq_recommended_opp().fixed
Quoted 5 lines
drivers/devfreq/imx-bus.c line 39
Quoted 3 lines
drivers/devfreq/imx-bus.c new file +3
-0+dev_pm_opp_put (new_opp); + +return clk_set_rate (priv->clk, new_freq);nitpick. you can use
dev_pm_opp_set_rate(). But, I'm not forcing to use it.Switched to
dev_pm_opp_set_rate.It might be interesting to add regulators control later, on some chips the main NOC can run at different voltages.
Quoted 37 lines
Quoted 37 lines
drivers/devfreq/imx-bus.c new file +36
-0+} + +static int imx_bus_get_cur_freq (struct device *dev,unsigned long *freq) +{ +struct imx_bus *priv =dev_get_drvdata (dev); + + *freq =clk_get_rate (priv->clk); + +return 0 ; +} + +static int imx_bus_get_dev_status (struct device *dev, +struct devfreq_dev_status *stat) +{ +struct imx_bus *priv =dev_get_drvdata (dev); + + stat->busy_time =0 ; + stat->total_time =0 ; + stat->current_frequency =clk_get_rate (priv->clk); + +return 0 ; +} + +static void imx_bus_exit (struct device *dev) +{ +dev_pm_opp_of_remove_table (dev); +} + +static int imx_bus_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct imx_bus *priv; +const char *gov =DEVFREQ_GOV_USERSPACE ; +int ret; + + priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL );Quoted 8 lines
drivers/devfreq/imx-bus.c line 80
Quoted 5 lines
drivers/devfreq/imx-bus.c new file +5
-0+if (!priv) +return -ENOMEM ; + +/* +* Fetch the clock to adjust but don't explictly enable. Need to fix typo.
s/explictly/explicitlyfixed
Quoted 65 lines
Quoted 63 lines
drivers/devfreq/imx-bus.c new file +62
-0+* +* For imx bus clock clk_set_rate is safe no matter if the clock is on +* or off and some peripheral side-buses might be off unless enabled by +* drivers for devices on those specific buses. +* +* Rate adjustment on a disabled bus clock just takes effect later. +*/ + priv->clk =devm_clk_get (dev,NULL ); +if (IS_ERR (priv->clk)) { + ret =PTR_ERR (priv->clk); +dev_err (dev,"failed to fetch clk: %d\n" , ret); +return ret; + } +platform_set_drvdata (pdev, priv); + + ret =dev_pm_opp_of_add_table (dev); +if (ret <0 ) { +dev_err (dev,"failed to get OPP table\n" ); +return ret; + } + + priv->profile.polling_ms =1000 ; + priv->profile.target = imx_bus_target; + priv->profile.get_dev_status = imx_bus_get_dev_status; + priv->profile.exit = imx_bus_exit; + priv->profile.get_cur_freq = imx_bus_get_cur_freq; + priv->profile.initial_freq =clk_get_rate (priv->clk); + + priv->devfreq =devm_devfreq_add_device (dev, &priv->profile, + gov,NULL ); +if (IS_ERR (priv->devfreq)) { + ret =PTR_ERR (priv->devfreq); +dev_err (dev,"failed to add devfreq device: %d\n" , ret); + goto err; + } + +return 0 ; + +err: +dev_pm_opp_of_remove_table (dev); +return ret; +} + +static const struct of_device_id imx_bus_of_match[] = { + { .compatible ="fsl,imx8m-noc" , }, + { .compatible ="fsl,imx8m-nic" , }, + {/* sentinel */ }, +}; +MODULE_DEVICE_TABLE (of, imx_bus_of_match); + +static struct platform_driver imx_bus_platdrv = { + .probe = imx_bus_probe, + .driver = { + .name ="imx-bus-devfreq" , + .of_match_table =of_match_ptr (imx_bus_of_match), + }, +}; +module_platform_driver (imx_bus_platdrv); + +MODULE_DESCRIPTION ("Generic i.MX bus frequency scaling driver" ); +MODULE_AUTHOR ("Leonard Crestez <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );
Signature · 3 lines
Best Regards, Chanwoo Choi Samsung Electronics
PATCH 3/8 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-bus.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
drivers/devfreq/imx-bus.c +39 -0
@@ -15,10 +15,11 @@struct imx_bus {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_bus_target (struct device *dev,unsigned long *freq,u32 flags) {
@@ -60,11 +61,42 @@ static int imx_bus_get_dev_status(struct device *dev,return 0 ; }static void imx_bus_exit (struct device *dev) { +struct imx_bus *priv =dev_get_drvdata (dev); +dev_pm_opp_of_remove_table (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) +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->devfreq)); +return PTR_ERR (priv->devfreq); + } + +return 0 ; }static int imx_bus_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;
@@ -112,18 +144,25 @@ static int imx_bus_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_bus_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_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,imx8m-noc" , }, { .compatible ="fsl,imx8m-nic" , }, {/* sentinel */ }, };MODULE_DEVICE_TABLE (of, imx_bus_of_match);
Signature · 1 line
2.17.1
Chanwoo Choi
maintainerRe: [PATCH 3/8] PM / devfreq: imx: Register interconnect device
Hi Leonard,
Quoted 32 lines · Leonard Crestez
There is no single device which can represent the imx interconnect. Instead of adding a virtual one just make the main &noc act as the global interconnect provider.
The imx interconnect provider driver will scale the NOC and DDRC based on bandwidth request. More scalable nodes can be added in the future, for example for audio/display/vpu/gpu NICs.
Signed-off-by Leonard Crestez <[email protected]>--- drivers/devfreq/imx-bus.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)drivers/devfreq/imx-bus.c +1
-0@@ -15,10 +15,11 @@struct imx_bus {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_bus_target (struct device *dev,unsigned long *freq,u32 flags) {@@ -60,11 +61,42 @@ static int imx_bus_get_dev_status(struct device *dev,return 0 ; }
drivers/devfreq/imx-bus.c static int imx_bus_get_dev_status(struct device *dev, · line 72
Quoted 10 lines
drivers/devfreq/imx-bus.c +6
-0static void imx_bus_exit (struct device *dev) { +struct imx_bus *priv =dev_get_drvdata (dev); +dev_pm_opp_of_remove_table (dev); +platform_device_unregister (priv->icc_pdev); +} + +/* imx_bus_init_icc() - register matching icc provider if required */
Better to add following comments without 'imx_bus_init_icc() -' comment. /* Register matching icc provider if required */
Quoted 5 lines
drivers/devfreq/imx-bus.c +5
-0+static int imx_bus_init_icc (struct device *dev) +{ +struct imx_bus *priv =dev_get_drvdata (dev); +const char *icc_driver_name; +
drivers/devfreq/imx-bus.c static int imx_bus_get_dev_status(struct device *dev, · line 87
Quoted 10 lines
drivers/devfreq/imx-bus.c +10
-0+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) +return 0 ;
Recommend to add the error or warning message.
Quoted 16 lines
drivers/devfreq/imx-bus.c +10
-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->devfreq)); +return PTR_ERR (priv->devfreq); + } + +return 0 ; }static int imx_bus_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;
drivers/devfreq/imx-bus.c static int imx_bus_probe(struct platform_device *pdev) · line 150
Quoted 7 lines
drivers/devfreq/imx-bus.c +2
-0@@ -112,18 +144,25 @@ static int imx_bus_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_bus_init_icc (dev); +if (ret)
Recommend to add the error message.
Quoted 19 lines
drivers/devfreq/imx-bus.c +5
-0+ goto err; +return 0 ; err:dev_pm_opp_of_remove_table (dev);return ret; }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,imx8m-noc" , }, { .compatible ="fsl,imx8m-nic" , }, {/* sentinel */ }, };MODULE_DEVICE_TABLE (of, imx_bus_of_match);
Signature · 3 lines
Best Regards, Chanwoo Choi Samsung Electronics
Re: [PATCH 3/8] PM / devfreq: imx: Register interconnect device
Quoted 36 lines · Chanwoo Choi
Hi Leonard,
Quoted 33 lines · Leonard Crestez
There is no single device which can represent the imx interconnect. Instead of adding a virtual one just make the main &noc act as the global interconnect provider.
The imx interconnect provider driver will scale the NOC and DDRC based on bandwidth request. More scalable nodes can be added in the future, for example for audio/display/vpu/gpu NICs.
Signed-off-by Leonard Crestez <[email protected]>--- drivers/devfreq/imx-bus.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)drivers/devfreq/imx-bus.c +1
-0@@ -15,10 +15,11 @@struct imx_bus {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_bus_target (struct device *dev,unsigned long *freq,u32 flags) {@@ -60,11 +61,42 @@ static int imx_bus_get_dev_status(struct device *dev,return 0 ; }
Quoted 12 lines
drivers/devfreq/imx-bus.c static int imx_bus_get_dev_status(struct device *dev, · line 72
Quoted 9 lines
drivers/devfreq/imx-bus.c +6
-0static void imx_bus_exit (struct device *dev) { +struct imx_bus *priv =dev_get_drvdata (dev); +dev_pm_opp_of_remove_table (dev); +platform_device_unregister (priv->icc_pdev); +} + +/* imx_bus_init_icc() - register matching icc provider if required */ Better to add following comments without '
imx_bus_init_icc()-' comment. /* Register matching icc provider if required */
This form looks like standard kernel-doc
Quoted 9 lines
Quoted 9 lines
drivers/devfreq/imx-bus.c +9
-0+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" );
Quoted 8 lines
drivers/devfreq/imx-bus.c static int imx_bus_get_dev_status(struct device *dev, · line 87
Quoted 6 lines
drivers/devfreq/imx-bus.c +6
-0+return 0 ; + } + + icc_driver_name =of_device_get_match_data (dev); +if (!icc_driver_name) +return 0 ;Recommend to add the error or warning message.
Makes sense, imx8m-nic shouldn't have #interconnect-cells so if this condition is reach an error should be printed.
Quoted 21 lines
Quoted 21 lines
drivers/devfreq/imx-bus.c +10
-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->devfreq)); +return PTR_ERR (priv->devfreq); + } + +return 0 ; }static int imx_bus_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;@@ -112,18 +144,25 @@ static int imx_bus_probe(struct platform_device *pdev) ret =PTR_ERR (priv->devfreq);dev_err (dev,"failed to add devfreq device: %d\n" , ret); goto err; }
Quoted 4 lines
drivers/devfreq/imx-bus.c static int imx_bus_probe(struct platform_device *pdev) · line 150
Quoted 2 lines
drivers/devfreq/imx-bus.c +2
-0+ ret =imx_bus_init_icc (dev); +if (ret)Recommend to add the error message.
imx_bus_init_icc already prints errors. Printing again here would always result in a second message.
Quoted 9 lines
Quoted 9 lines
drivers/devfreq/imx-bus.c +2
-0+ goto err; +return 0 ; err:dev_pm_opp_of_remove_table (dev);return ret; }
Quoted 10 lines
drivers/devfreq/imx-bus.c static int imx_bus_probe(struct platform_device *pdev) · line 168
Quoted 10 lines
drivers/devfreq/imx-bus.c +3
-0static 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,imx8m-noc" , }, { .compatible ="fsl,imx8m-nic" , }, {/* sentinel */ }, };MODULE_DEVICE_TABLE (of, imx_bus_of_match);
_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
PATCH 4/8 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 interconnect provider is probed through the main NOC device and other adjustable nodes on the same graph are found from a fsl,scalable-nodes phandle array property.
--- drivers/interconnect/Kconfig | 1 + drivers/interconnect/Makefile | 1 + drivers/interconnect/imx/Kconfig | 5 + drivers/interconnect/imx/Makefile | 3 + drivers/interconnect/imx/imx.c | 298 ++++++++++++++++++++++++++++++ drivers/interconnect/imx/imx.h | 62 +++++++ 6 files changed, 370 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
@@ -3,5 +3,6 @@ CFLAGS_core.o := -I$(src) 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 + tristate "i.MX interconnect drivers" + depends on ARCH_MXC || COMPILE_TEST + help + Generic interconnect drivers for i.MX SOCs
drivers/interconnect/imx/Makefile new file +3 -0
@@ -0,0 +1,3 @@ +imx-interconnect-objs := imx.o + +obj-$(CONFIG_INTERCONNECT_IMX) += imx-interconnect.o
drivers/interconnect/imx/imx.c new file +298 -0
298 lines not on this page · raw message
drivers/interconnect/imx/imx.h new file +62 -0
62 lines not on this page · raw message
Signature · 1 line
2.17.1
PATCH 5/8 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 | 2 + drivers/interconnect/imx/imx8mm.c | 108 ++++++++++++++++++++++ include/dt-bindings/interconnect/imx8mm.h | 49 ++++++++++ 4 files changed, 163 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 tristate "i.MX interconnect drivers" depends on ARCH_MXC || COMPILE_TEST help Generic interconnect drivers for i.MX SOCs + +config INTERCONNECT_IMX8MM + tristate "i.MX8MM interconnect driver" + depends on INTERCONNECT_IMX
drivers/interconnect/imx/Makefile +2 -0
@@ -1,3 +1,5 @@ imx-interconnect-objs := imx.o +imx8mm-interconnect-objs := imx8mm.o obj-$(CONFIG_INTERCONNECT_IMX) += imx-interconnect.o +obj-$(CONFIG_INTERCONNECT_IMX8MM) += imx8mm-interconnect.o
drivers/interconnect/imx/imx8mm.c new file +108 -0
108 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
PATCH 6/8 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 | 2 + drivers/interconnect/imx/imx8mq.c | 106 ++++++++++++++++++++++ include/dt-bindings/interconnect/imx8mq.h | 48 ++++++++++ 4 files changed, 160 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 drivers for i.MX SOCs config INTERCONNECT_IMX8MM tristate "i.MX8MM interconnect driver" depends on INTERCONNECT_IMX + +config INTERCONNECT_IMX8MQ + tristate "i.MX8MQ interconnect driver" + depends on INTERCONNECT_IMX
drivers/interconnect/imx/Makefile +2 -0
@@ -1,5 +1,7 @@ imx-interconnect-objs := imx.o imx8mm-interconnect-objs := imx8mm.o +imx8mq-interconnect-objs := imx8mq.o obj-$(CONFIG_INTERCONNECT_IMX) += imx-interconnect.o obj-$(CONFIG_INTERCONNECT_IMX8MM) += imx8mm-interconnect.o +obj-$(CONFIG_INTERCONNECT_IMX8MQ) += imx8mq-interconnect.o
drivers/interconnect/imx/imx8mq.c new file +106 -0
106 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
PATCH 7/8 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 | 2 + drivers/interconnect/imx/imx8mn.c | 97 +++++++++++++++++++++++ include/dt-bindings/interconnect/imx8mn.h | 41 ++++++++++ 4 files changed, 144 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 tristate "i.MX8MM interconnect driver" depends on INTERCONNECT_IMX +config INTERCONNECT_IMX8MN + tristate "i.MX8MN interconnect driver" + depends on INTERCONNECT_IMX + config INTERCONNECT_IMX8MQ tristate "i.MX8MQ interconnect driver" depends on INTERCONNECT_IMX
drivers/interconnect/imx/Makefile +2 -0
@@ -1,7 +1,9 @@ imx-interconnect-objs := imx.o imx8mm-interconnect-objs := imx8mm.o imx8mq-interconnect-objs := imx8mq.o +imx8mn-interconnect-objs := imx8mn.o obj-$(CONFIG_INTERCONNECT_IMX) += imx-interconnect.o obj-$(CONFIG_INTERCONNECT_IMX8MM) += imx8mm-interconnect.o obj-$(CONFIG_INTERCONNECT_IMX8MQ) += imx8mq-interconnect.o +obj-$(CONFIG_INTERCONNECT_IMX8MN) += imx8mn-interconnect.o
drivers/interconnect/imx/imx8mn.c new file +97 -0
97 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
PATCH 8/8 arm64: dts: imx8m: Add NOC nodes
In reply to Leonard CrestezAdd nodes for the main interconnect of the imx8m series chips.
These nodes are bound to by devfreq and interconnect drivers.
--- arch/arm64/boot/dts/freescale/imx8mm.dtsi | 24 +++++++++++++++++++++++ arch/arm64/boot/dts/freescale/imx8mn.dtsi | 24 +++++++++++++++++++++++ arch/arm64/boot/dts/freescale/imx8mq.dtsi | 24 +++++++++++++++++++++++ 3 files changed, 72 insertions(+)
arch/arm64/boot/dts/freescale/imx8mm.dtsi +24 -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>;
@@ -860,10 +861,33 @@ status = "disabled"; }; }; + noc: interconnect@32700000 { + compatible = "fsl,imx8mm-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MM_CLK_NOC>; + fsl,ddrc = <&ddrc>; + #interconnect-cells = <1>; + operating-points-v2 = <&noc_opp_table>; + + noc_opp_table: 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>; + }; + }; + }; + aips4: bus@32c00000 { compatible = "fsl,aips-bus", "simple-bus"; reg = <0x32df0000 0x10000>; #address-cells = <1>; #size-cells = <1>;
arch/arm64/boot/dts/freescale/imx8mn.dtsi +24 -0
@@ -6,10 +6,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/thermal/thermal.h> +#include <dt-bindings/interconnect/imx8mn.h> #include "imx8mn-pinfunc.h" / { interrupt-parent = <&gic>;
@@ -751,10 +752,33 @@ status = "disabled"; }; }; + noc: interconnect@32700000 { + compatible = "fsl,imx8mn-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MN_CLK_NOC>; + fsl,ddrc = <&ddrc>; + #interconnect-cells = <1>; + operating-points-v2 = <&noc_opp_table>; + + noc_opp_table: 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>; + }; + }; + }; + aips4: bus@32c00000 { compatible = "fsl,aips-bus", "simple-bus"; reg = <0x32df0000 0x10000>; #address-cells = <1>; #size-cells = <1>;
arch/arm64/boot/dts/freescale/imx8mq.dtsi +24 -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>;
@@ -1026,10 +1027,33 @@ 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>; + fsl,ddrc = <&ddrc>; + #interconnect-cells = <1>; + 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>; + }; + }; + }; + bus@32c00000 { /* AIPS4 */ compatible = "fsl,aips-bus", "simple-bus"; reg = <0x32df0000 0x10000>; #address-cells = <1>; #size-cells = <1>;
Signature · 1 line
2.17.1
Quoted 26 lines · Leonard Crestez
This series adds 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 is implemented as distinct devfreq drivers instead.
The imx interconnect provider doesn't communicate with devfreq directly but rather computes "minimum frequencies" for nodes along the path and creates
dev_pm_qosrequests.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 avoids introducing "virtual" devices but it means that DT bindings of main NOC includes properties for both devfreq and interconnect.
Only the ddrc and main noc are scalable right now but more can be added.
Also available on a github branch (with various unrelated changes):
https://github.com/cdleonard/linux/tree/next
Testing currently requires NXP branch of atf+uboot
Quoted 6 lines
Martin: I believe you should be able to use this to control DRAM frequency from video by just adding interconnect consumer code to nwl-dsi. Sample code:
https://github.com/cdleonard/linux/commit/43772762aa5045f1ce5623740f9a4baef988d083 https://github.com/cdleonard/linux/commit/7b601e981b1f517b5d98b43bde292972ded13086
Thanks for updating this series Leonard! A few questions for my understanding before trying to test:
Isn't the ddrc_opp_table missing in these additions to the DT? That's what I want to scale after all.
If I want to keep calling the "request", now icc_set_bw(), in nwl-dsi:
I'd add an "interconnects" property to the node, but what would be my interconnect master? i.e.: interconnects = <&noc master? &noc IMX8MQ_ICS_DRAM>; At least it's not obvious to me from interconnect/imx/imx8mq.c
the interconnect framework seems to be powerful indeed, but I still need to fully wrap my head around it.
thanks for the help so far,
martin
Quoted 92 lines
Changes since RFCv6:
* Replace scalable-nodes stuff with just a fsl,ddrc property. Future scalable nodes can be added as additional phandles on the NOC
* Allow building interconnect drivers as modules
* Handleicc_provider_delerrors inimx_icc_unregister(like EBUSY).
* Rename imx-devfreq to imx-bus, similar to exynos-bus
* Explain why imx bus clock enabling is not required
* All dependencies accepted (some time ago).Changes since RFCv5:
* Replace scanning for interconnect-node-id with explicit scalable-nodes/scalable-node-ids property on NoC.
* Now passes makedtbs_check
* Remove structimx_icc_provider
* Switch toof_icc_xlate_onecell
* Useof_find_device_by_nodeto fetch QoS target, this causes fewer probe deferrals, removes dependency on devfreq API and even allows reloading ddrc module at runtime
* Addimx_icc_node_destroyhelper
* Remove 0/1 on DEFINE_BUS_SLAVE/MASTER which created spurious linksChanges 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)
* RemoveARCH_MXC_ARM64(never existed in upstream)
* Remove_numlinks, calculate instead
* Replace__BUSFREQ_Hheader 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 anddev_pm_qosinstead 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/cover/11021563/Leonard Crestez (8):
dt-bindings: interconnect: Add bindings for imx8m noc PM / devfreq: Add generic imx bus scaling driver PM / devfreq: imx: Register interconnect device
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.../bindings/interconnect/fsl,imx8m-noc.yaml | 138 ++++++++ arch/arm64/boot/dts/freescale/imx8mm.dtsi | 24 ++ arch/arm64/boot/dts/freescale/imx8mn.dtsi | 24 ++ arch/arm64/boot/dts/freescale/imx8mq.dtsi | 24 ++ drivers/devfreq/Kconfig | 9 + drivers/devfreq/Makefile | 1 + drivers/devfreq/imx-bus.c | 181 +++++++++++ drivers/interconnect/Kconfig | 1 + drivers/interconnect/Makefile | 1 + drivers/interconnect/imx/Kconfig | 17 + drivers/interconnect/imx/Makefile | 9 + drivers/interconnect/imx/imx.c | 298 ++++++++++++++++++ drivers/interconnect/imx/imx.h | 62 ++++ drivers/interconnect/imx/imx8mm.c | 108 +++++++ drivers/interconnect/imx/imx8mn.c | 97 ++++++ drivers/interconnect/imx/imx8mq.c | 106 +++++++ include/dt-bindings/interconnect/imx8mm.h | 49 +++ include/dt-bindings/interconnect/imx8mn.h | 41 +++ include/dt-bindings/interconnect/imx8mq.h | 48 +++ 19 files changed, 1238 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml create mode 100644 drivers/devfreq/imx-bus.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
Hi Martin,
Quoted 37 lines · Martin Kepplinger
Quoted 26 lines · Leonard Crestez
This series adds 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 is implemented as distinct devfreq drivers instead.
The imx interconnect provider doesn't communicate with devfreq directly but rather computes "minimum frequencies" for nodes along the path and creates
dev_pm_qosrequests.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 avoids introducing "virtual" devices but it means that DT bindings of main NOC includes properties for both devfreq and interconnect.
Only the ddrc and main noc are scalable right now but more can be added.
Also available on a github branch (with various unrelated changes):
https://github.com/cdleonard/linux/tree/next
Testing currently requires NXP branch of atf+ubootQuoted 6 lines
Martin: I believe you should be able to use this to control DRAM frequency from video by just adding interconnect consumer code to nwl-dsi. Sample code:
https://github.com/cdleonard/linux/commit/43772762aa5045f1ce5623740f9a4baef988d083 https://github.com/cdleonard/linux/commit/7b601e981b1f517b5d98b43bde292972ded13086Thanks for updating this series Leonard! A few questions for my understanding before trying to test:
Quoted 8 lines
Isn't the
ddrc_opp_tablemissing in these additions to the DT? That's what I want to scale after all.If I want to keep calling the "request", now
icc_set_bw(), in nwl-dsi:
I'd add an "interconnects" property to the node, but what would be my interconnect master? i.e.: interconnects = <&noc master? &nocIMX8MQ_ICS_DRAM>; At least it's not obvious to me frominterconnect/imx/imx8mq.c
The NWL DSI host controller is fed by DCSS or mxsfb so any bandwidth requirements should (as far as I understand things) go into the display controller driver since that's what fetches from RAM. Cheers,
-- Guido
Quoted 107 lines
the interconnect framework seems to be powerful indeed, but I still need to fully wrap my head around it.
thanks for the help so far,
martin
Quoted 83 lines
Changes since RFCv6:
* Replace scalable-nodes stuff with just a fsl,ddrc property. Future scalable nodes can be added as additional phandles on the NOC
* Allow building interconnect drivers as modules
* Handleicc_provider_delerrors inimx_icc_unregister(like EBUSY).
* Rename imx-devfreq to imx-bus, similar to exynos-bus
* Explain why imx bus clock enabling is not required
* All dependencies accepted (some time ago).Changes since RFCv5:
* Replace scanning for interconnect-node-id with explicit scalable-nodes/scalable-node-ids property on NoC.
* Now passes makedtbs_check
* Remove structimx_icc_provider
* Switch toof_icc_xlate_onecell
* Useof_find_device_by_nodeto fetch QoS target, this causes fewer probe deferrals, removes dependency on devfreq API and even allows reloading ddrc module at runtime
* Addimx_icc_node_destroyhelper
* Remove 0/1 on DEFINE_BUS_SLAVE/MASTER which created spurious linksChanges 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)
* RemoveARCH_MXC_ARM64(never existed in upstream)
* Remove_numlinks, calculate instead
* Replace__BUSFREQ_Hheader 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 anddev_pm_qosinstead 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/cover/11021563/Leonard Crestez (8):
dt-bindings: interconnect: Add bindings for imx8m noc PM / devfreq: Add generic imx bus scaling driver PM / devfreq: imx: Register interconnect device
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.../bindings/interconnect/fsl,imx8m-noc.yaml | 138 ++++++++ arch/arm64/boot/dts/freescale/imx8mm.dtsi | 24 ++ arch/arm64/boot/dts/freescale/imx8mn.dtsi | 24 ++ arch/arm64/boot/dts/freescale/imx8mq.dtsi | 24 ++ drivers/devfreq/Kconfig | 9 + drivers/devfreq/Makefile | 1 + drivers/devfreq/imx-bus.c | 181 +++++++++++ drivers/interconnect/Kconfig | 1 + drivers/interconnect/Makefile | 1 + drivers/interconnect/imx/Kconfig | 17 + drivers/interconnect/imx/Makefile | 9 + drivers/interconnect/imx/imx.c | 298 ++++++++++++++++++ drivers/interconnect/imx/imx.h | 62 ++++ drivers/interconnect/imx/imx8mm.c | 108 +++++++ drivers/interconnect/imx/imx8mn.c | 97 ++++++ drivers/interconnect/imx/imx8mq.c | 106 +++++++ include/dt-bindings/interconnect/imx8mm.h | 49 +++ include/dt-bindings/interconnect/imx8mn.h | 41 +++ include/dt-bindings/interconnect/imx8mq.h | 48 +++ 19 files changed, 1238 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml create mode 100644 drivers/devfreq/imx-bus.c create mode 100644 drivers/interconnect/imx/Kconfig create mode 100644 drivers/interconnect/imx/MakefileQuoted 9 lines
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_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Martin Kepplinger
Tested-byQuoted 48 lines · Guido Günther
Hi Martin,
Quoted 37 lines · Martin Kepplinger
Quoted 26 lines · Leonard Crestez
This series adds 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 is implemented as distinct devfreq drivers instead.
The imx interconnect provider doesn't communicate with devfreq directly but rather computes "minimum frequencies" for nodes along the path and creates
dev_pm_qosrequests.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 avoids introducing "virtual" devices but it means that DT bindings of main NOC includes properties for both devfreq and interconnect.
Only the ddrc and main noc are scalable right now but more can be added.
Also available on a github branch (with various unrelated changes):
https://github.com/cdleonard/linux/tree/next
Testing currently requires NXP branch of atf+ubootQuoted 6 lines
Martin: I believe you should be able to use this to control DRAM frequency from video by just adding interconnect consumer code to nwl-dsi. Sample code:
https://github.com/cdleonard/linux/commit/43772762aa5045f1ce5623740f9a4baef988d083 https://github.com/cdleonard/linux/commit/7b601e981b1f517b5d98b43bde292972ded13086Thanks for updating this series Leonard! A few questions for my understanding before trying to test:
Quoted 8 lines
Isn't the
ddrc_opp_tablemissing in these additions to the DT? That's what I want to scale after all.If I want to keep calling the "request", now
icc_set_bw(), in nwl-dsi:
I'd add an "interconnects" property to the node, but what would be my interconnect master? i.e.: interconnects = <&noc master? &nocIMX8MQ_ICS_DRAM>; At least it's not obvious to me frominterconnect/imx/imx8mq.c
Quoted 6 lines
The NWL DSI host controller is fed by DCSS or mxsfb so any bandwidth requirements should (as far as I understand things) go into the display controller driver since that's what fetches from RAM. Cheers,
-- Guido
Hi,
Thanks a lot Leonard and Guido! Here's the tree I'm running, which is your patches based on Linus' tree, with icc request in mxsfb:
https://source.puri.sm/martin.kepplinger/linux-next/commits/5.6-rc7/librem5__integration_devfreq1
The path from icc via pm_qos to devfreq does work (which is great) - however only after setting the minimum frequencies via a governor - I set the "powersave" governor.
After that, frequencies are both set to high / low correctly.
My impression was that I should be able to use the "passive" governor (a passive devfreq device?). What am I missing with using devfreq correctly? Or do I already?
other than the above uncertainty:
thanks so far!
martin
Quoted 37 lines · Martin Kepplinger
Quoted 36 lines · Guido Günther
Hi Martin,
Quoted 34 lines · Martin Kepplinger
Quoted 32 lines · Leonard Crestez
This series adds 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 is implemented as distinct devfreq drivers instead.
The imx interconnect provider doesn't communicate with devfreq directly but rather computes "minimum frequencies" for nodes along the path and creates
dev_pm_qosrequests.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 avoids introducing "virtual" devices but it means that DT bindings of main NOC includes properties for both devfreq and interconnect.
Only the ddrc and main noc are scalable right now but more can be added.
Also available on a github branch (with various unrelated changes):
https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fcdleonard%2Flinux%2Ftree%2Fnext&data=02%7C01%7Cleonard.crestez%40nxp.com%7C52eb55181dce469eb85608d7d487bb93%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637211551737394247&sdata=A0l5FBF%2BT3k7H5HMtRMfX8WfVSqQm9jijgr8aexCoUA%3D&reserved=0Testing currently requires NXP branch of atf+uboot
Martin: I believe you should be able to use this to control DRAM frequency from video by just adding interconnect consumer code to nwl-dsi. Sample code:
https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fcdleonard%2Flinux%2Fcommit%2F43772762aa5045f1ce5623740f9a4baef988d083&data=02%7C01%7Cleonard.crestez%40nxp.com%7C52eb55181dce469eb85608d7d487bb93%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637211551737394247&sdata=%2B%2BGWQTaQLLk98yFRHJ0o3Sks9DHGuKv7twBvn89f1Tg%3D&reserved=0 https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fcdleonard%2Flinux%2Fcommit%2F7b601e981b1f517b5d98b43bde292972ded13086&data=02%7C01%7Cleonard.crestez%40nxp.com%7C52eb55181dce469eb85608d7d487bb93%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637211551737394247&sdata=Jy2%2FI3CE1H3ilmLvZAVhjlPHO3KRNK6%2F9dX%2BS124ROA%3D&reserved=0
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Thanks for updating this series Leonard! A few questions for my understanding before trying to test:
Isn't the
ddrc_opp_tablemissing in these additions to the DT? That's what I want to scale after all.
DDRC OPP table belongs in board file because it can vary with RAM type on boards.
Quoted 11 lines
Quoted 11 lines
Quoted 5 lines
If I want to keep calling the "request", now
icc_set_bw(), in nwl-dsi:
I'd add an "interconnects" property to the node, but what would be my interconnect master? i.e.: interconnects = <&noc master? &nocIMX8MQ_ICS_DRAM>; At least it's not obvious to me frominterconnect/imx/imx8mq.cThe NWL DSI host controller is fed by DCSS or mxsfb so any bandwidth requirements should (as far as I understand things) go into the display controller driver since that's what fetches from RAM. Cheers,
-- Guido
This is correct.
Quoted 9 lines
Thanks a lot Leonard and Guido! Here's the tree I'm running, which is your patches based on Linus' tree, with icc request in mxsfb:
The path from icc via
pm_qosto devfreq does work (which is great) - however only after setting the minimum frequencies via a governor - I set the "powersave" governor.
Quoted 5 lines
After that, frequencies are both set to high / low correctly.
My impression was that I should be able to use the "passive" governor (a passive devfreq device?). What am I missing with using devfreq correctly? Or do I already?
The devfreq governor is something else: it's used to make one devfreq device match frequencies with another devfreq device.
Setting the default governor to "powersave" is correct and roughly matches behavior in NXP kernel.
Quoted 1 line
Tested-by Martin Kepplinger <[email protected]>
Thanks!