interconnect: Add imx support via devfreq
Subsystems (4)
v6 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.
This depends on other series for devfreq pm/qos and ddrc:
https://patchwork.kernel.org/cover/11244283/ https://patchwork.kernel.org/cover/11212887/ https://patchwork.kernel.org/project/linux-arm-kernel/list/?series=196443
Also available as a github branch (with various unrelated changes):
https://github.com/cdleonard/linux/tree/next_imx_busfreq
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 (9):
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
arm64: dts: imx8m: Add interconnect provider properties
.../bindings/interconnect/fsl,imx8m-noc.yaml | 104 ++++++ arch/arm64/boot/dts/freescale/imx8mm.dtsi | 28 ++ arch/arm64/boot/dts/freescale/imx8mn.dtsi | 28 ++ arch/arm64/boot/dts/freescale/imx8mq.dtsi | 28 ++ drivers/devfreq/Kconfig | 9 + drivers/devfreq/Makefile | 1 + drivers/devfreq/imx-devfreq.c | 187 +++++++++++ drivers/interconnect/Kconfig | 1 + drivers/interconnect/Makefile | 1 + drivers/interconnect/imx/Kconfig | 17 + drivers/interconnect/imx/Makefile | 4 + drivers/interconnect/imx/imx.c | 301 ++++++++++++++++++ drivers/interconnect/imx/imx.h | 60 ++++ drivers/interconnect/imx/imx8mm.c | 105 ++++++ drivers/interconnect/imx/imx8mn.c | 94 ++++++ drivers/interconnect/imx/imx8mq.c | 103 ++++++ include/dt-bindings/interconnect/imx8mm.h | 49 +++ include/dt-bindings/interconnect/imx8mn.h | 41 +++ include/dt-bindings/interconnect/imx8mq.h | 48 +++ 19 files changed, 1209 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml create mode 100644 drivers/devfreq/imx-devfreq.c create mode 100644 drivers/interconnect/imx/Kconfig create mode 100644 drivers/interconnect/imx/Makefile create mode 100644 drivers/interconnect/imx/imx.c create mode 100644 drivers/interconnect/imx/imx.h create mode 100644 drivers/interconnect/imx/imx8mm.c create mode 100644 drivers/interconnect/imx/imx8mn.c create mode 100644 drivers/interconnect/imx/imx8mq.c create mode 100644 include/dt-bindings/interconnect/imx8mm.h create mode 100644 include/dt-bindings/interconnect/imx8mn.h create mode 100644 include/dt-bindings/interconnect/imx8mq.h
Signature · 1 line
2.17.1
RFC PATCH v6 1/9 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.
Multiple interconnects can be present, each with their own OPP table.
--- .../bindings/interconnect/fsl,imx8m-noc.yaml | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +104 -0
@@ -0,0 +1,104 @@ +# 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 + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + operating-points-v2: true + opp-table: true + + devfreq: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: + Phandle to another devfreq device to match OPPs with by using the + passive governor. + + '#interconnect-cells': + description: + If specified then also act as an interconnect provider. Should only be + set once per soc on main noc. + const: 1 + + fsl,scalable-node-ids: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Array of node ids for scalable nodes. Uses same numeric identifier + namespace as the consumer "interconnects" binding. + + fsl,scalable-nodes: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: + Array of phandles to scalable nodes. Must be of same length as + fsl,scalable-node-ids. + +required: + - compatible + - clocks + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/imx8mq-clock.h> + #include <dt-bindings/interconnect/imx8mq.h> + noc: interconnect@32700000 { + compatible = "fsl,imx8mq-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MQ_CLK_NOC>; + #interconnect-cells = <1>; + fsl,scalable-node-ids = <IMX8MQ_ICN_NOC>, + <IMX8MQ_ICS_DRAM>; + fsl,scalable-nodes = <&noc>, + <&ddrc>; + operating-points-v2 = <&noc_opp_table>; + + noc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-133M { + opp-hz = /bits/ 64 <133333333>; + }; + opp-800M { + opp-hz = /bits/ 64 <800000000>; + }; + }; + };
Signature · 1 line
2.17.1
Chanwoo Choi
maintainerRe: [PATCH RFC v6 1/9] dt-bindings: interconnect: Add bindings for imx8m noc
Quoted 63 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.
Multiple interconnects can be present, each with their own OPP table.
Signed-off-by Leonard Crestez <[email protected]>--- .../bindings/interconnect/fsl,imx8m-noc.yaml | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yamlDocumentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +42
-0@@ -0,0 +1,104 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: https://protect2.fireeye.com/url?k=0c13f3e0-51df3f45-0c1278af-0cc47a30d446-77e809543b673ffd&u=http://devicetree.org/schemas/interconnect/fsl,imx8m-noc.yaml# +$schema: https://protect2.fireeye.com/url?k=87c672dc-da0abe79-87c7f993-0cc47a30d446-414d3b4d0127419a&u=http://devicetree.org/meta-schemas/core.yaml# + +title: Generic i.MX bus frequency device + +maintainers: + - Leonard Crestez <[email protected]> + +description: | + The i.MX SoC family has multiple buses for which clock frequency (and + sometimes voltage) can be adjusted. + + Some of those buses expose register areas mentioned in the memory maps as GPV + ("Global Programmers View") but not all. Access to this area might be denied + for normal (non-secure) world. + + The buses are based on externally licensed IPs such as ARM NIC-301 and + Arteris FlexNOC but DT bindings are specific to the integration of these bus + interconnect IPs into imx SOCs. + +properties: + compatible: + oneOf: + - items: + - enum: + - fsl,imx8mn-nic + - fsl,imx8mm-nic + - fsl,imx8mq-nic + - const: fsl,imx8m-nic + - items: + - enum: + - fsl,imx8mn-noc + - fsl,imx8mm-noc + - fsl,imx8mq-noc + - const: fsl,imx8m-noc + + reg: + maxItems: 1 +
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml line 52
Quoted 10 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +10
-0+ clocks: + maxItems: 1 + + operating-points-v2: true + opp-table: true + + devfreq: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: + Phandle to another devfreq device to match OPPs with by using the
Better to use 'parent' instead of 'another' word for improving the understanding.
Quoted 18 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +18
-0+ passive governor. + + '#interconnect-cells': + description: + If specified then also act as an interconnect provider. Should only be + set once per soc on main noc. + const: 1 + + fsl,scalable-node-ids: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Array of node ids for scalable nodes. Uses same numeric identifier + namespace as the consumer "interconnects" binding. + + fsl,scalable-nodes: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: + Array of phandles to scalable nodes. Must be of same length as
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml line 80
Quoted 10 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +10
-0+ fsl,scalable-node-ids. + +required: + - compatible + - clocks + +additionalProperties: false + +examples: + - |
Is it enough example to understand the relation between imx8m-ddrc.c, imx-devfreq.c and imx interconnect driver?
In my case, if possible, hope to show the more detailed example. This example seems that don't contain the ddrc dt node (imx8m-ddrc.c).
Quoted 25 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +24
-0+ #include <dt-bindings/clock/imx8mq-clock.h> + #include <dt-bindings/interconnect/imx8mq.h> + noc: interconnect@32700000 { + compatible = "fsl,imx8mq-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MQ_CLK_NOC>; + #interconnect-cells = <1>; + fsl,scalable-node-ids = <IMX8MQ_ICN_NOC>, + <IMX8MQ_ICS_DRAM>; + fsl,scalable-nodes = <&noc>, + <&ddrc>; + operating-points-v2 = <&noc_opp_table>; + + noc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-133M { + opp-hz = /bits/ 64 <133333333>; + }; + opp-800M { + opp-hz = /bits/ 64 <800000000>; + }; + }; + };
Signature · 3 lines
Best Regards, Chanwoo Choi Samsung Electronics
Chanwoo Choi
maintainerRe: [PATCH RFC v6 1/9] dt-bindings: interconnect: Add bindings for imx8m noc
Hi,
Quoted 68 lines · Chanwoo Choi
Quoted 67 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.
Multiple interconnects can be present, each with their own OPP table.
Signed-off-by Leonard Crestez <[email protected]>--- .../bindings/interconnect/fsl,imx8m-noc.yaml | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yamlDocumentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +46
-0@@ -0,0 +1,104 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: https://protect2.fireeye.com/url?k=0c13f3e0-51df3f45-0c1278af-0cc47a30d446-77e809543b673ffd&u=http://devicetree.org/schemas/interconnect/fsl,imx8m-noc.yaml# +$schema: https://protect2.fireeye.com/url?k=87c672dc-da0abe79-87c7f993-0cc47a30d446-414d3b4d0127419a&u=http://devicetree.org/meta-schemas/core.yaml# + +title: Generic i.MX bus frequency device + +maintainers: + - Leonard Crestez <[email protected]> + +description: | + The i.MX SoC family has multiple buses for which clock frequency (and + sometimes voltage) can be adjusted. + + Some of those buses expose register areas mentioned in the memory maps as GPV + ("Global Programmers View") but not all. Access to this area might be denied + for normal (non-secure) world. + + The buses are based on externally licensed IPs such as ARM NIC-301 and + Arteris FlexNOC but DT bindings are specific to the integration of these bus + interconnect IPs into imx SOCs. + +properties: + compatible: + oneOf: + - items: + - enum: + - fsl,imx8mn-nic + - fsl,imx8mm-nic + - fsl,imx8mq-nic + - const: fsl,imx8m-nic + - items: + - enum: + - fsl,imx8mn-noc + - fsl,imx8mm-noc + - fsl,imx8mq-noc + - const: fsl,imx8m-noc + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + operating-points-v2: true
Quoted 8 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml line 52
Quoted 6 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +6
-0+ opp-table: true + + devfreq: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: + Phandle to another devfreq device to match OPPs with by using theBetter to use 'parent' instead of 'another' word for improving the understanding.
I think that 'devfreq' is not proper way to get the parent node
in devicetree. Because 'devfreq' name is linuxium. The property name didn't indicate the any h/w device. So, I'll make 'devfreq' property deprecated.
So, you better to make the specific property for this device driver like as following: and use devfreq_get_devfreq_by_node() function which is developed by you in order to get the devfreq instance node.
fsl,parent-device = <&parent devfreq device>;
[1] [PATCH RFC v5 04/10] PM / devfreq: Add devfreq_get_devfreq_by_node
Quoted 64 lines
Quoted 19 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +18
-0+ passive governor. + + '#interconnect-cells': + description: + If specified then also act as an interconnect provider. Should only be + set once per soc on main noc. + const: 1 + + fsl,scalable-node-ids: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Array of node ids for scalable nodes. Uses same numeric identifier + namespace as the consumer "interconnects" binding. + + fsl,scalable-nodes: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: + Array of phandles to scalable nodes. Must be of same length asDocumentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml line 80
Quoted 10 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +10
-0+ fsl,scalable-node-ids. + +required: + - compatible + - clocks + +additionalProperties: false + +examples: + - |Is it enough example to understand the relation between
imx8m-ddrc.c,imx-devfreq.cand imx interconnect driver?In my case, if possible, hope to show the more detailed example. This example seems that don't contain the ddrc dt node (
imx8m-ddrc.c).Quoted 25 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +24
-0+ #include <dt-bindings/clock/imx8mq-clock.h> + #include <dt-bindings/interconnect/imx8mq.h> + noc: interconnect@32700000 { + compatible = "fsl,imx8mq-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MQ_CLK_NOC>; + #interconnect-cells = <1>; + fsl,scalable-node-ids = <IMX8MQ_ICN_NOC>, + <IMX8MQ_ICS_DRAM>; + fsl,scalable-nodes = <&noc>, + <&ddrc>; + operating-points-v2 = <&noc_opp_table>; + + noc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-133M { + opp-hz = /bits/ 64 <133333333>; + }; + opp-800M { + opp-hz = /bits/ 64 <800000000>; + }; + }; + };
Signature · 3 lines
Best Regards, Chanwoo Choi Samsung Electronics
Re: [PATCH RFC v6 1/9] dt-bindings: interconnect: Add bindings for imx8m noc
Quoted 84 lines · Chanwoo Choi
Hi,
Quoted 68 lines · Chanwoo Choi
Quoted 67 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.
Multiple interconnects can be present, each with their own OPP table.
Signed-off-by Leonard Crestez <[email protected]>--- .../bindings/interconnect/fsl,imx8m-noc.yaml | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+)create mode 100644
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yamlDocumentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +46
-0@@ -0,0 +1,104 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fprotect2.fireeye.com%2Furl%3Fk%3D0c13f3e0-51df3f45-0c1278af-0cc47a30d446-77e809543b673ffd%26u%3Dhttp%3A%2F%2Fdevicetree.org%2Fschemas%2Finterconnect%2Ffsl%2Cimx8m-noc.yaml%23&data=02%7C01%7Cleonard.crestez%40nxp.com%7C2d1f1868afa140702a6b08d781d6ab68%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637120631307418544&sdata=H2q5nQlKYyLIivkBYUTaRD1Nu3WcnphPJny3k%2BK%2BGFE%3D&reserved=0 +$schema: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fprotect2.fireeye.com%2Furl%3Fk%3D87c672dc-da0abe79-87c7f993-0cc47a30d446-414d3b4d0127419a%26u%3Dhttp%3A%2F%2Fdevicetree.org%2Fmeta-schemas%2Fcore.yaml%23&data=02%7C01%7Cleonard.crestez%40nxp.com%7C2d1f1868afa140702a6b08d781d6ab68%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637120631307418544&sdata=T6PgQ1DWI4OLOx3gifRRt%2FNImdVrgDUoswZ%2FNKw3oR8%3D&reserved=0 + +title: Generic i.MX bus frequency device + +maintainers: + - Leonard Crestez <[email protected]> + +description: | + The i.MX SoC family has multiple buses for which clock frequency (and + sometimes voltage) can be adjusted. + + Some of those buses expose register areas mentioned in the memory maps as GPV + ("Global Programmers View") but not all. Access to this area might be denied + for normal (non-secure) world. + + The buses are based on externally licensed IPs such as ARM NIC-301 and + Arteris FlexNOC but DT bindings are specific to the integration of these bus + interconnect IPs into imx SOCs. + +properties: + compatible: + oneOf: + - items: + - enum: + - fsl,imx8mn-nic + - fsl,imx8mm-nic + - fsl,imx8mq-nic + - const: fsl,imx8m-nic + - items: + - enum: + - fsl,imx8mn-noc + - fsl,imx8mm-noc + - fsl,imx8mq-noc + - const: fsl,imx8m-noc + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + operating-points-v2: trueQuoted 8 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml line 52
Quoted 6 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +6
-0+ opp-table: true + + devfreq: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: + Phandle to another devfreq device to match OPPs with by using theBetter to use 'parent' instead of 'another' word for improving the understanding.
I think that 'devfreq' is not proper way to get the parent node
in devicetree. Because 'devfreq' name is linuxium. The property name didn't indicate the any h/w device. So, I'll make 'devfreq' property deprecated.
Quoted 5 lines
So, you better to make the specific property for this device driver like as following: and use
devfreq_get_devfreq_by_node()function which is developed by you in order to get the devfreq instance node.fsl,parent-device = <&parent devfreq device>;
This is only a "parent" in the sense that it's assigned to devfreq_passive.data.parent. The "devfreq" name is indeed too generic.
The DDRC can measure bandwith usage and I want to use the passive governor to make the main NOC match OPPs. But at the bus level DDRC only has AXI and APB slave ports.
Buses on imx don't have a parent/child relationship; in fact there are even a few cycles.
Quoted 39 lines
[1] [PATCH RFC v5 04/10] PM / devfreq: Add
devfreq_get_devfreq_by_nodeQuoted 36 lines
Quoted 19 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +18
-0+ passive governor. + + '#interconnect-cells': + description: + If specified then also act as an interconnect provider. Should only be + set once per soc on main noc. + const: 1 + + fsl,scalable-node-ids: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Array of node ids for scalable nodes. Uses same numeric identifier + namespace as the consumer "interconnects" binding. + + fsl,scalable-nodes: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: + Array of phandles to scalable nodes. Must be of same length asDocumentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml line 80
Quoted 10 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +10
-0+ fsl,scalable-node-ids. + +required: + - compatible + - clocks + +additionalProperties: false + +examples: + - |Is it enough example to understand the relation between
imx8m-ddrc.c,imx-devfreq.cand imx interconnect driver?In my case, if possible, hope to show the more detailed example. This example seems that don't contain the ddrc dt node (
imx8m-ddrc.c).
OK, I'll elaborate explanation on noc binding.
Quoted 17 lines
Quoted 17 lines
Quoted 17 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +16
-0+ #include <dt-bindings/clock/imx8mq-clock.h> + #include <dt-bindings/interconnect/imx8mq.h> + noc: interconnect@32700000 { + compatible = "fsl,imx8mq-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MQ_CLK_NOC>; + #interconnect-cells = <1>; + fsl,scalable-node-ids = <IMX8MQ_ICN_NOC>, + <IMX8MQ_ICS_DRAM>; + fsl,scalable-nodes = <&noc>, + <&ddrc>; + operating-points-v2 = <&noc_opp_table>; + + noc_opp_table: opp-table { + compatible = "operating-points-v2"; +
Quoted 8 lines
Quoted 8 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml line 104
Quoted 8 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +8
-0+ opp-133M { + opp-hz = /bits/ 64 <133333333>; + }; + opp-800M { + opp-hz = /bits/ 64 <800000000>; + }; + }; + };
_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Chanwoo Choi
maintainerRe: [PATCH RFC v6 1/9] dt-bindings: interconnect: Add bindings for imx8m noc
Quoted 85 lines · Leonard Crestez
Quoted 84 lines · Chanwoo Choi
Hi,
Quoted 68 lines · Chanwoo Choi
Quoted 67 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.
Multiple interconnects can be present, each with their own OPP table.
Signed-off-by Leonard Crestez <[email protected]>--- .../bindings/interconnect/fsl,imx8m-noc.yaml | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+)create mode 100644
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yamlDocumentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +46
-0@@ -0,0 +1,104 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: https://protect2.fireeye.com/url?k=8570eb5a-d8a45732-85716015-0cc47a3356b2-92a5b92cc514d07e&u=https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fprotect2.fireeye.com%2Furl%3Fk%3D0c13f3e0-51df3f45-0c1278af-0cc47a30d446-77e809543b673ffd%26u%3Dhttp%3A%2F%2Fdevicetree.org%2Fschemas%2Finterconnect%2Ffsl%2Cimx8m-noc.yaml%23&data=02%7C01%7Cleonard.crestez%40nxp.com%7C2d1f1868afa140702a6b08d781d6ab68%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637120631307418544&sdata=H2q5nQlKYyLIivkBYUTaRD1Nu3WcnphPJny3k%2BK%2BGFE%3D&reserved=0 +$schema: https://protect2.fireeye.com/url?k=f7cec483-aa1a78eb-f7cf4fcc-0cc47a3356b2-4154a3c43886f5ed&u=https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fprotect2.fireeye.com%2Furl%3Fk%3D87c672dc-da0abe79-87c7f993-0cc47a30d446-414d3b4d0127419a%26u%3Dhttp%3A%2F%2Fdevicetree.org%2Fmeta-schemas%2Fcore.yaml%23&data=02%7C01%7Cleonard.crestez%40nxp.com%7C2d1f1868afa140702a6b08d781d6ab68%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637120631307418544&sdata=T6PgQ1DWI4OLOx3gifRRt%2FNImdVrgDUoswZ%2FNKw3oR8%3D&reserved=0 + +title: Generic i.MX bus frequency device + +maintainers: + - Leonard Crestez <[email protected]> + +description: | + The i.MX SoC family has multiple buses for which clock frequency (and + sometimes voltage) can be adjusted. + + Some of those buses expose register areas mentioned in the memory maps as GPV + ("Global Programmers View") but not all. Access to this area might be denied + for normal (non-secure) world. + + The buses are based on externally licensed IPs such as ARM NIC-301 and + Arteris FlexNOC but DT bindings are specific to the integration of these bus + interconnect IPs into imx SOCs. + +properties: + compatible: + oneOf: + - items: + - enum: + - fsl,imx8mn-nic + - fsl,imx8mm-nic + - fsl,imx8mq-nic + - const: fsl,imx8m-nic + - items: + - enum: + - fsl,imx8mn-noc + - fsl,imx8mm-noc + - fsl,imx8mq-noc + - const: fsl,imx8m-noc + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + operating-points-v2: trueQuoted 8 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml line 52
Quoted 6 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +6
-0+ opp-table: true + + devfreq: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: + Phandle to another devfreq device to match OPPs with by using theBetter to use 'parent' instead of 'another' word for improving the understanding.
I think that 'devfreq' is not proper way to get the parent node
in devicetree. Because 'devfreq' name is linuxium. The property name didn't indicate the any h/w device. So, I'll make 'devfreq' property deprecated.
Quoted 8 lines
Quoted 5 lines
So, you better to make the specific property for this device driver like as following: and use
devfreq_get_devfreq_by_node()function which is developed by you in order to get the devfreq instance node.fsl,parent-device = <&parent devfreq device>;This is only a "parent" in the sense that it's assigned to devfreq_passive.data.parent. The "devfreq" name is indeed too generic.
I thought that 'devfreq' property name is generic. But, it's not proper for DT binding because DT file show the h/w and the relation of h/w. 'devfreq' property name has not meant h/w.
So that devfreq core doesn't force to use the specific property name to get the devfreq parent instance on DT. Just, devfreq core will provide devfreq_get_devfreq_by_node() function.
I developed it on devfre-testing branch[2]. Before I'm sending the these patches, you can check them.
[1] https://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git/commit/?h=devfreq-testing&id=f3678b4e6b75dccfe8bb87d005da2d68c70fdeab
[2] https://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git/log/?h=devfreq-testing
Quoted 3 lines
The DDRC can measure bandwith usage and I want to use the passive governor to make the main NOC match OPPs.
which one use the passive governor? And which one is the parent devfreq device for devfreq device using passive governor?
In my case, it is difficult to catch the relationship between devices. I'd like you to explain the detailed relationship on binding document for user.
Quoted 1 line
But at the bus level DDRC only has AXI and APB slave ports.
'DDRC' indicates the 'drivers/devfreq/imx8m-ddrc.c?
Quoted 3 lines
Buses on imx don't have a parent/child relationship; in fact there are even a few cycles.
You mentioned that 'imx don't have a parent/child relationship', Why do you use 'passive' governor? It is difficult to understand the hierarchy of imx.
Quoted 37 lines
Quoted 37 lines
[1] [PATCH RFC v5 04/10] PM / devfreq: Add
devfreq_get_devfreq_by_nodeQuoted 33 lines
Quoted 19 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +18
-0+ passive governor. + + '#interconnect-cells': + description: + If specified then also act as an interconnect provider. Should only be + set once per soc on main noc. + const: 1 + + fsl,scalable-node-ids: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Array of node ids for scalable nodes. Uses same numeric identifier + namespace as the consumer "interconnects" binding. + + fsl,scalable-nodes: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: + Array of phandles to scalable nodes. Must be of same length asDocumentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml line 80
Quoted 10 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +10
-0+ fsl,scalable-node-ids. + +required: + - compatible + - clocks + +additionalProperties: false + +examples: + - |Is it enough example to understand the relation between
imx8m-ddrc.c,imx-devfreq.cand imx interconnect driver?
Quoted 5 lines
Quoted 3 lines
Quoted 3 lines
In my case, if possible, hope to show the more detailed example. This example seems that don't contain the ddrc dt node (
imx8m-ddrc.c).OK, I'll elaborate explanation on noc binding.
Thanks. If possible, you better to add almost example cases.
Quoted 28 lines
Quoted 26 lines
Quoted 26 lines
Quoted 26 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +24
-0+ #include <dt-bindings/clock/imx8mq-clock.h> + #include <dt-bindings/interconnect/imx8mq.h> + noc: interconnect@32700000 { + compatible = "fsl,imx8mq-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MQ_CLK_NOC>; + #interconnect-cells = <1>; + fsl,scalable-node-ids = <IMX8MQ_ICN_NOC>, + <IMX8MQ_ICS_DRAM>; + fsl,scalable-nodes = <&noc>, + <&ddrc>; + operating-points-v2 = <&noc_opp_table>; + + noc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-133M { + opp-hz = /bits/ 64 <133333333>; + }; + opp-800M { + opp-hz = /bits/ 64 <800000000>; + }; + }; + };
Signature · 3 lines
Best Regards, Chanwoo Choi Samsung Electronics
Re: [PATCH RFC v6 1/9] dt-bindings: interconnect: Add bindings for imx8m noc
Quoted 126 lines · Chanwoo Choi
Quoted 85 lines · Leonard Crestez
Quoted 84 lines · Chanwoo Choi
Hi,
Quoted 68 lines · Chanwoo Choi
Quoted 67 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.
Multiple interconnects can be present, each with their own OPP table.
Signed-off-by Leonard Crestez <[email protected]>--- .../bindings/interconnect/fsl,imx8m-noc.yaml | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+)create mode 100644
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yamlDocumentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +46
-0@@ -0,0 +1,104 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fprotect2.fireeye.com%2Furl%3Fk%3D8570eb5a-d8a45732-85716015-0cc47a3356b2-92a5b92cc514d07e%26u%3Dhttps%3A%2F%2Feur01.safelinks.protection.outlook.com%2F%3Furl%3Dhttps%253A%252F%252Fprotect2.fireeye.com%252Furl%253Fk%253D0c13f3e0-51df3f45-0c1278af-0cc47a30d446-77e809543b673ffd%2526u%253Dhttp%253A%252F%252Fdevicetree.org%252Fschemas%252Finterconnect%252Ffsl%252Cimx8m-noc.yaml%2523%26amp%3Bdata%3D02%257C01%257Cleonard.crestez%2540nxp.com%257C2d1f1868afa140702a6b08d781d6ab68%257C686ea1d3bc2b4c6fa92cd99c5c301635%257C0%257C0%257C637120631307418544%26amp%3Bsdata%3DH2q5nQlKYyLIivkBYUTaRD1Nu3WcnphPJny3k%252BK%252BGFE%253D%26amp%3Breserved%3D0&data=02%7C01%7Cleonard.crestez%40nxp.com%7C769d8e354f3b4d00b84508d782854a17%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637121381290437871&sdata=HYMJJHWyiKRhf7GDjKoOwjDpcZuYqlFlmRrDZnIRx5w%3D&reserved=0 +$schema: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fprotect2.fireeye.com%2Furl%3Fk%3Df7cec483-aa1a78eb-f7cf4fcc-0cc47a3356b2-4154a3c43886f5ed%26u%3Dhttps%3A%2F%2Feur01.safelinks.protection.outlook.com%2F%3Furl%3Dhttps%253A%252F%252Fprotect2.fireeye.com%252Furl%253Fk%253D87c672dc-da0abe79-87c7f993-0cc47a30d446-414d3b4d0127419a%2526u%253Dhttp%253A%252F%252Fdevicetree.org%252Fmeta-schemas%252Fcore.yaml%2523%26amp%3Bdata%3D02%257C01%257Cleonard.crestez%2540nxp.com%257C2d1f1868afa140702a6b08d781d6ab68%257C686ea1d3bc2b4c6fa92cd99c5c301635%257C0%257C0%257C637120631307418544%26amp%3Bsdata%3DT6PgQ1DWI4OLOx3gifRRt%252FNImdVrgDUoswZ%252FNKw3oR8%253D%26amp%3Breserved%3D0&data=02%7C01%7Cleonard.crestez%40nxp.com%7C769d8e354f3b4d00b84508d782854a17%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637121381290437871&sdata=fIbrUUOUtZ5nt%2FH1tm3dzaI1J%2FGn5Gc54ms93HnBnQg%3D&reserved=0 + +title: Generic i.MX bus frequency device + +maintainers: + - Leonard Crestez <[email protected]> + +description: | + The i.MX SoC family has multiple buses for which clock frequency (and + sometimes voltage) can be adjusted. + + Some of those buses expose register areas mentioned in the memory maps as GPV + ("Global Programmers View") but not all. Access to this area might be denied + for normal (non-secure) world. + + The buses are based on externally licensed IPs such as ARM NIC-301 and + Arteris FlexNOC but DT bindings are specific to the integration of these bus + interconnect IPs into imx SOCs. + +properties: + compatible: + oneOf: + - items: + - enum: + - fsl,imx8mn-nic + - fsl,imx8mm-nic + - fsl,imx8mq-nic + - const: fsl,imx8m-nic + - items: + - enum: + - fsl,imx8mn-noc + - fsl,imx8mm-noc + - fsl,imx8mq-noc + - const: fsl,imx8m-noc + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + operating-points-v2: trueQuoted 8 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml line 52
Quoted 6 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +6
-0+ opp-table: true + + devfreq: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: + Phandle to another devfreq device to match OPPs with by using theBetter to use 'parent' instead of 'another' word for improving the understanding.
I think that 'devfreq' is not proper way to get the parent node
in devicetree. Because 'devfreq' name is linuxium. The property name didn't indicate the any h/w device. So, I'll make 'devfreq' property deprecated.Quoted 8 lines
Quoted 5 lines
So, you better to make the specific property for this device driver like as following: and use
devfreq_get_devfreq_by_node()function which is developed by you in order to get the devfreq instance node.fsl,parent-device = <&parent devfreq device>;This is only a "parent" in the sense that it's assigned to devfreq_passive.data.parent. The "devfreq" name is indeed too generic.
I thought that 'devfreq' property name is generic. But, it's not proper for DT binding because DT file show the h/w and the relation of h/w. 'devfreq' property name has not meant h/w.
So that devfreq core doesn't force to use the specific property name to get the devfreq parent instance on DT. Just, devfreq core will provide
devfreq_get_devfreq_by_node()function.I developed it on devfre-testing branch[2]. Before I'm sending the these patches, you can check them.
[1] https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.kernel.org%2Fpub%2Fscm%2Flinux%2Fkernel%2Fgit%2Fchanwoo%2Flinux.git%2Fcommit%2F%3Fh%3Ddevfreq-testing%26id%3Df3678b4e6b75dccfe8bb87d005da2d68c70fdeab&data=02%7C01%7Cleonard.crestez%40nxp.com%7C769d8e354f3b4d00b84508d782854a17%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637121381290437871&sdata=R21Tv1QgofBvMYb2VaxFjKSerwQ3tl8kakcYRyALmgM%3D&reserved=0
[2] https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.kernel.org%2Fpub%2Fscm%2Flinux%2Fkernel%2Fgit%2Fchanwoo%2Flinux.git%2Flog%2F%3Fh%3Ddevfreq-testing&data=02%7C01%7Cleonard.crestez%40nxp.com%7C769d8e354f3b4d00b84508d782854a17%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637121381290437871&sdata=uH0d9LvrbCHgZJdrPJNJ8c8w45J7x1QyM7t5I3j%2BpSw%3D&reserved=0Quoted 3 lines
The DDRC can measure bandwith usage and I want to use the passive governor to make the main NOC match OPPs.
which one use the passive governor? And which one is the parent devfreq device for devfreq device using passive governor?
In my case, it is difficult to catch the relationship between devices. I'd like you to explain the detailed relationship on binding document for user.
Quoted 1 line
But at the bus level DDRC only has AXI and APB slave ports.
'DDRC' indicates the '
drivers/devfreq/imx8m-ddrc.c?Quoted 1 line
Quoted 6 lines
Quoted 2 lines
Buses on imx don't have a parent/child relationship; in fact there are even a few cycles.
You mentioned that 'imx don't have a parent/child relationship', Why do you use 'passive' governor? It is difficult to understand the hierarchy of imx.
The imx8m has a main NOC in the center between the CPU and the DDRC (dram controller) with many other peripheral buses around the NOC.
Here's /sys/kernel/debug/interconnect/interconnect_graph on imx8mm:
https://gist.github.com/cdleonard/84d103dafc9131fcb8ca9a494822a131#file-imx8mm-svg
A lot of stuff is omitted, it mostly just includes high-performance bus masters.
DDRC has a performance monitor attached which can measure current bandwith and feed it to an ondemand governor. I want to use passive governor on the NOC so that it matches frequencies with DDRC and scales proportionally, otherwise if NOC is at low frequency then dynamically scaling up the DDRC might be ineffective.
Perhaps you could explain how parent/child relationships work on exynos?
Quoted 73 lines
Quoted 35 lines
Quoted 35 lines
[1] [PATCH RFC v5 04/10] PM / devfreq: Add
devfreq_get_devfreq_by_nodeQuoted 33 lines
Quoted 19 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +18
-0+ passive governor. + + '#interconnect-cells': + description: + If specified then also act as an interconnect provider. Should only be + set once per soc on main noc. + const: 1 + + fsl,scalable-node-ids: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Array of node ids for scalable nodes. Uses same numeric identifier + namespace as the consumer "interconnects" binding. + + fsl,scalable-nodes: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: + Array of phandles to scalable nodes. Must be of same length asDocumentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml line 80
Quoted 10 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +10
-0+ fsl,scalable-node-ids. + +required: + - compatible + - clocks + +additionalProperties: false + +examples: + - |Is it enough example to understand the relation between
imx8m-ddrc.c,imx-devfreq.cand imx interconnect driver?Quoted 5 lines
Quoted 3 lines
Quoted 3 lines
In my case, if possible, hope to show the more detailed example. This example seems that don't contain the ddrc dt node (
imx8m-ddrc.c).OK, I'll elaborate explanation on noc binding.
Thanks. If possible, you better to add almost example cases.
Quoted 28 lines
Quoted 26 lines
Quoted 26 lines
Quoted 26 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +24
-0+ #include <dt-bindings/clock/imx8mq-clock.h> + #include <dt-bindings/interconnect/imx8mq.h> + noc: interconnect@32700000 { + compatible = "fsl,imx8mq-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MQ_CLK_NOC>; + #interconnect-cells = <1>; + fsl,scalable-node-ids = <IMX8MQ_ICN_NOC>, + <IMX8MQ_ICS_DRAM>; + fsl,scalable-nodes = <&noc>, + <&ddrc>; + operating-points-v2 = <&noc_opp_table>; + + noc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-133M { + opp-hz = /bits/ 64 <133333333>; + }; + opp-800M { + opp-hz = /bits/ 64 <800000000>; + }; + }; + };
Re: [PATCH RFC v6 1/9] dt-bindings: interconnect: Add bindings for imx8m noc
2019년 12월 19일 (목) 오후 11:33, Leonard Crestez <[email protected]>님이 작성:
Quoted 131 lines · Chanwoo Choi
Quoted 129 lines · Leonard Crestez
Quoted 85 lines · Chanwoo Choi
Quoted 84 lines
Hi,
Quoted 68 lines · Chanwoo Choi
Quoted 67 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.
Multiple interconnects can be present, each with their own OPP table.
Signed-off-by Leonard Crestez <[email protected]>--- .../bindings/interconnect/fsl,imx8m-noc.yaml | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+)create mode 100644
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yamlDocumentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +46
-0@@ -0,0 +1,104 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fprotect2.fireeye.com%2Furl%3Fk%3D8570eb5a-d8a45732-85716015-0cc47a3356b2-92a5b92cc514d07e%26u%3Dhttps%3A%2F%2Feur01.safelinks.protection.outlook.com%2F%3Furl%3Dhttps%253A%252F%252Fprotect2.fireeye.com%252Furl%253Fk%253D0c13f3e0-51df3f45-0c1278af-0cc47a30d446-77e809543b673ffd%2526u%253Dhttp%253A%252F%252Fdevicetree.org%252Fschemas%252Finterconnect%252Ffsl%252Cimx8m-noc.yaml%2523%26amp%3Bdata%3D02%257C01%257Cleonard.crestez%2540nxp.com%257C2d1f1868afa140702a6b08d781d6ab68%257C686ea1d3bc2b4c6fa92cd99c5c301635%257C0%257C0%257C637120631307418544%26amp%3Bsdata%3DH2q5nQlKYyLIivkBYUTaRD1Nu3WcnphPJny3k%252BK%252BGFE%253D%26amp%3Breserved%3D0&data=02%7C01%7Cleonard.crestez%40nxp.com%7C769d8e354f3b4d00b84508d782854a17%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637121381290437871&sdata=HYMJJHWyiKRhf7GDjKoOwjDpcZuYqlFlmRrDZnIRx5w%3D&reserved=0 +$schema: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fprotect2.fireeye.com%2Furl%3Fk%3Df7cec483-aa1a78eb-f7cf4fcc-0cc47a3356b2-4154a3c43886f5ed%26u%3Dhttps%3A%2F%2Feur01.safelinks.protection.outlook.com%2F%3Furl%3Dhttps%253A%252F%252Fprotect2.fireeye.com%252Furl%253Fk%253D87c672dc-da0abe79-87c7f993-0cc47a30d446-414d3b4d0127419a%2526u%253Dhttp%253A%252F%252Fdevicetree.org%252Fmeta-schemas%252Fcore.yaml%2523%26amp%3Bdata%3D02%257C01%257Cleonard.crestez%2540nxp.com%257C2d1f1868afa140702a6b08d781d6ab68%257C686ea1d3bc2b4c6fa92cd99c5c301635%257C0%257C0%257C637120631307418544%26amp%3Bsdata%3DT6PgQ1DWI4OLOx3gifRRt%252FNImdVrgDUoswZ%252FNKw3oR8%253D%26amp%3Breserved%3D0&data=02%7C01%7Cleonard.crestez%40nxp.com%7C769d8e354f3b4d00b84508d782854a17%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637121381290437871&sdata=fIbrUUOUtZ5nt%2FH1tm3dzaI1J%2FGn5Gc54ms93HnBnQg%3D&reserved=0 + +title: Generic i.MX bus frequency device + +maintainers: + - Leonard Crestez <[email protected]> + +description: | + The i.MX SoC family has multiple buses for which clock frequency (and + sometimes voltage) can be adjusted. + + Some of those buses expose register areas mentioned in the memory maps as GPV + ("Global Programmers View") but not all. Access to this area might be denied + for normal (non-secure) world. + + The buses are based on externally licensed IPs such as ARM NIC-301 and + Arteris FlexNOC but DT bindings are specific to the integration of these bus + interconnect IPs into imx SOCs. + +properties: + compatible: + oneOf: + - items: + - enum: + - fsl,imx8mn-nic + - fsl,imx8mm-nic + - fsl,imx8mq-nic + - const: fsl,imx8m-nic + - items: + - enum: + - fsl,imx8mn-noc + - fsl,imx8mm-noc + - fsl,imx8mq-noc + - const: fsl,imx8m-noc + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + operating-points-v2: trueQuoted 8 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml line 52
Quoted 6 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +6
-0+ opp-table: true + + devfreq: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: + Phandle to another devfreq device to match OPPs with by using theBetter to use 'parent' instead of 'another' word for improving the understanding.
I think that 'devfreq' is not proper way to get the parent node
in devicetree. Because 'devfreq' name is linuxium. The property name didn't indicate the any h/w device. So, I'll make 'devfreq' property deprecated.Quoted 8 lines
Quoted 5 lines
So, you better to make the specific property for this device driver like as following: and use
devfreq_get_devfreq_by_node()function which is developed by you in order to get the devfreq instance node.fsl,parent-device = <&parent devfreq device>;This is only a "parent" in the sense that it's assigned to devfreq_passive.data.parent. The "devfreq" name is indeed too generic.
I thought that 'devfreq' property name is generic. But, it's not proper for DT binding because DT file show the h/w and the relation of h/w. 'devfreq' property name has not meant h/w.
So that devfreq core doesn't force to use the specific property name to get the devfreq parent instance on DT. Just, devfreq core will provide
devfreq_get_devfreq_by_node()function.I developed it on devfre-testing branch[2]. Before I'm sending the these patches, you can check them.
[1] https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.kernel.org%2Fpub%2Fscm%2Flinux%2Fkernel%2Fgit%2Fchanwoo%2Flinux.git%2Fcommit%2F%3Fh%3Ddevfreq-testing%26id%3Df3678b4e6b75dccfe8bb87d005da2d68c70fdeab&data=02%7C01%7Cleonard.crestez%40nxp.com%7C769d8e354f3b4d00b84508d782854a17%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637121381290437871&sdata=R21Tv1QgofBvMYb2VaxFjKSerwQ3tl8kakcYRyALmgM%3D&reserved=0
[2] https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.kernel.org%2Fpub%2Fscm%2Flinux%2Fkernel%2Fgit%2Fchanwoo%2Flinux.git%2Flog%2F%3Fh%3Ddevfreq-testing&data=02%7C01%7Cleonard.crestez%40nxp.com%7C769d8e354f3b4d00b84508d782854a17%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637121381290437871&sdata=uH0d9LvrbCHgZJdrPJNJ8c8w45J7x1QyM7t5I3j%2BpSw%3D&reserved=0Quoted 3 lines
The DDRC can measure bandwith usage and I want to use the passive governor to make the main NOC match OPPs.
which one use the passive governor? And which one is the parent devfreq device for devfreq device using passive governor?
In my case, it is difficult to catch the relationship between devices. I'd like you to explain the detailed relationship on binding document for user.
Quoted 1 line
But at the bus level DDRC only has AXI and APB slave ports.
'DDRC' indicates the '
drivers/devfreq/imx8m-ddrc.c?Quoted 3 lines
Buses on imx don't have a parent/child relationship; in fact there are even a few cycles.
Quoted 6 lines
Quoted 3 lines
You mentioned that 'imx don't have a parent/child relationship', Why do you use 'passive' governor? It is difficult to understand the hierarchy of imx.
The imx8m has a main NOC in the center between the CPU and the DDRC (dram controller) with many other peripheral buses around the NOC.
Actually, if this dt binding document contains the relationship between ddrc(imx8m-ddrc.c)
, imx-bus.c(bus) and interconnect node, it is more easy to understand the hierarchy
of bus/ddrc. In my case, it is difficult because the binding document doesn't include the enough example. But, I'll expect them as you mentioned on your reply.
Quoted 3 lines
Here's
/sys/kernel/debug/interconnect/interconnect_graphon imx8mm:
https://gist.github.com/cdleonard/84d103dafc9131fcb8ca9a494822a131#file-imx8mm-svg
It is the interconnect node graph. I hope to know the relationship when bus(imx-bus.c)
uses the 'passive governor' and which is the
Quoted 7 lines
A lot of stuff is omitted, it mostly just includes high-performance bus masters.
DDRC has a performance monitor attached which can measure current bandwith and feed it to an ondemand governor. I want to use passive governor on the NOC so that it matches frequencies with DDRC and scales
I have the following questions. If you explain the more detailed descritpion and add multiple dt bidning example, I'll expect that I can understand the following my questions.
- Which one will use the 'passive governor'?
- DDRC is parent devfreq device for imx bus(imx-bus.c) using passive governor?
- Why imx bus(imx-bus.c) use the userspace governor?
- Which the relationship between imx bus(imx-bus.c) using userspace governor and imx bus(imx-bus.c) using passive governor?
Quoted 4 lines
proportionally, otherwise if NOC is at low frequency then dynamically scaling up the DDRC might be ineffective.
Perhaps you could explain how parent/child relationships work on exynos?
Right. So, I wrote[1] why exynos-bus.c have to use the passive governor and how to make the hierarchy/relationship between exynos-bus(parent devfreq device
using devfreq governor except for passive governor)
and exynos-bus (child devfreq device using only passive governor).
[1] Documentation/devicetree/bindings/devfreq/exynos-bus.txt
Quoted 76 lines
Quoted 74 lines
Quoted 36 lines
Quoted 36 lines
[1] [PATCH RFC v5 04/10] PM / devfreq: Add
devfreq_get_devfreq_by_nodeQuoted 33 lines
Quoted 19 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +18
-0+ passive governor. + + '#interconnect-cells': + description: + If specified then also act as an interconnect provider. Should only be + set once per soc on main noc. + const: 1 + + fsl,scalable-node-ids: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Array of node ids for scalable nodes. Uses same numeric identifier + namespace as the consumer "interconnects" binding. + + fsl,scalable-nodes: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: + Array of phandles to scalable nodes. Must be of same length asDocumentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml line 80
Quoted 10 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +10
-0+ fsl,scalable-node-ids. + +required: + - compatible + - clocks + +additionalProperties: false + +examples: + - |Is it enough example to understand the relation between
imx8m-ddrc.c,imx-devfreq.cand imx interconnect driver?Quoted 5 lines
Quoted 3 lines
Quoted 3 lines
In my case, if possible, hope to show the more detailed example. This example seems that don't contain the ddrc dt node (
imx8m-ddrc.c).OK, I'll elaborate explanation on noc binding.
Thanks. If possible, you better to add almost example cases.
Quoted 28 lines
Quoted 26 lines
Quoted 26 lines
Quoted 26 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +24
-0+ #include <dt-bindings/clock/imx8mq-clock.h> + #include <dt-bindings/interconnect/imx8mq.h> + noc: interconnect@32700000 { + compatible = "fsl,imx8mq-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MQ_CLK_NOC>; + #interconnect-cells = <1>; + fsl,scalable-node-ids = <IMX8MQ_ICN_NOC>, + <IMX8MQ_ICS_DRAM>; + fsl,scalable-nodes = <&noc>, + <&ddrc>; + operating-points-v2 = <&noc_opp_table>; + + noc_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-133M { + opp-hz = /bits/ 64 <133333333>; + }; + opp-800M { + opp-hz = /bits/ 64 <800000000>; + }; + }; + };
Signature · 2 lines
Best Regards, Chanwoo Choi
Re: [PATCH RFC v6 1/9] dt-bindings: interconnect: Add bindings for imx8m noc
Quoted 163 lines · Chanwoo Choi
2019년 12월 19일 (목) 오후 11:33, Leonard Crestez <[email protected]>님이 작성:
Quoted 131 lines · Chanwoo Choi
Quoted 129 lines · Leonard Crestez
Quoted 85 lines · Chanwoo Choi
Quoted 84 lines
Hi,
Quoted 68 lines · Chanwoo Choi
Quoted 67 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.
Multiple interconnects can be present, each with their own OPP table.
Signed-off-by Leonard Crestez <[email protected]>--- .../bindings/interconnect/fsl,imx8m-noc.yaml | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+)create mode 100644
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yamlDocumentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +46
-0@@ -0,0 +1,104 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fprotect2.fireeye.com%2Furl%3Fk%3D8570eb5a-d8a45732-85716015-0cc47a3356b2-92a5b92cc514d07e%26u%3Dhttps%3A%2F%2Feur01.safelinks.protection.outlook.com%2F%3Furl%3Dhttps%253A%252F%252Fprotect2.fireeye.com%252Furl%253Fk%253D0c13f3e0-51df3f45-0c1278af-0cc47a30d446-77e809543b673ffd%2526u%253Dhttp%253A%252F%252Fdevicetree.org%252Fschemas%252Finterconnect%252Ffsl%252Cimx8m-noc.yaml%2523%26amp%3Bdata%3D02%257C01%257Cleonard.crestez%2540nxp.com%257C2d1f1868afa140702a6b08d781d6ab68%257C686ea1d3bc2b4c6fa92cd99c5c301635%257C0%257C0%257C637120631307418544%26amp%3Bsdata%3DH2q5nQlKYyLIivkBYUTaRD1Nu3WcnphPJny3k%252BK%252BGFE%253D%26amp%3Breserved%3D0&data=02%7C01%7Cleonard.crestez%40nxp.com%7C40406bfd0f134eeddb3208d7849c0968%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637123678022512623&sdata=IYSYlNtA0fYKLkTr4OjyHkKa6FAi2m8UFr4nXZ9pr7s%3D&reserved=0 +$schema: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fprotect2.fireeye.com%2Furl%3Fk%3Df7cec483-aa1a78eb-f7cf4fcc-0cc47a3356b2-4154a3c43886f5ed%26u%3Dhttps%3A%2F%2Feur01.safelinks.protection.outlook.com%2F%3Furl%3Dhttps%253A%252F%252Fprotect2.fireeye.com%252Furl%253Fk%253D87c672dc-da0abe79-87c7f993-0cc47a30d446-414d3b4d0127419a%2526u%253Dhttp%253A%252F%252Fdevicetree.org%252Fmeta-schemas%252Fcore.yaml%2523%26amp%3Bdata%3D02%257C01%257Cleonard.crestez%2540nxp.com%257C2d1f1868afa140702a6b08d781d6ab68%257C686ea1d3bc2b4c6fa92cd99c5c301635%257C0%257C0%257C637120631307418544%26amp%3Bsdata%3DT6PgQ1DWI4OLOx3gifRRt%252FNImdVrgDUoswZ%252FNKw3oR8%253D%26amp%3Breserved%3D0&data=02%7C01%7Cleonard.crestez%40nxp.com%7C40406bfd0f134eeddb3208d7849c0968%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637123678022512623&sdata=nrbPGpgBci5DDm6qRROeFa78hARR9UCXeP59TnPtCuI%3D&reserved=0 + +title: Generic i.MX bus frequency device + +maintainers: + - Leonard Crestez <[email protected]> + +description: | + The i.MX SoC family has multiple buses for which clock frequency (and + sometimes voltage) can be adjusted. + + Some of those buses expose register areas mentioned in the memory maps as GPV + ("Global Programmers View") but not all. Access to this area might be denied + for normal (non-secure) world. + + The buses are based on externally licensed IPs such as ARM NIC-301 and + Arteris FlexNOC but DT bindings are specific to the integration of these bus + interconnect IPs into imx SOCs. + +properties: + compatible: + oneOf: + - items: + - enum: + - fsl,imx8mn-nic + - fsl,imx8mm-nic + - fsl,imx8mq-nic + - const: fsl,imx8m-nic + - items: + - enum: + - fsl,imx8mn-noc + - fsl,imx8mm-noc + - fsl,imx8mq-noc + - const: fsl,imx8m-noc + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + operating-points-v2: trueQuoted 8 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml line 52
Quoted 6 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +6
-0+ opp-table: true + + devfreq: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: + Phandle to another devfreq device to match OPPs with by using theBetter to use 'parent' instead of 'another' word for improving the understanding.
I think that 'devfreq' is not proper way to get the parent node
in devicetree. Because 'devfreq' name is linuxium. The property name didn't indicate the any h/w device. So, I'll make 'devfreq' property deprecated.Quoted 8 lines
Quoted 5 lines
So, you better to make the specific property for this device driver like as following: and use
devfreq_get_devfreq_by_node()function which is developed by you in order to get the devfreq instance node.fsl,parent-device = <&parent devfreq device>;This is only a "parent" in the sense that it's assigned to devfreq_passive.data.parent. The "devfreq" name is indeed too generic.
I thought that 'devfreq' property name is generic. But, it's not proper for DT binding because DT file show the h/w and the relation of h/w. 'devfreq' property name has not meant h/w.
So that devfreq core doesn't force to use the specific property name to get the devfreq parent instance on DT. Just, devfreq core will provide
devfreq_get_devfreq_by_node()function.I developed it on devfre-testing branch[2]. Before I'm sending the these patches, you can check them.
[1] https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.kernel.org%2Fpub%2Fscm%2Flinux%2Fkernel%2Fgit%2Fchanwoo%2Flinux.git%2Fcommit%2F%3Fh%3Ddevfreq-testing%26id%3Df3678b4e6b75dccfe8bb87d005da2d68c70fdeab&data=02%7C01%7Cleonard.crestez%40nxp.com%7C40406bfd0f134eeddb3208d7849c0968%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637123678022512623&sdata=AhMMx8MZB7HIvYaChWFdSu9JMFGPHyz%2B8W%2Fk7pevofY%3D&reserved=0
[2] https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.kernel.org%2Fpub%2Fscm%2Flinux%2Fkernel%2Fgit%2Fchanwoo%2Flinux.git%2Flog%2F%3Fh%3Ddevfreq-testing&data=02%7C01%7Cleonard.crestez%40nxp.com%7C40406bfd0f134eeddb3208d7849c0968%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637123678022522615&sdata=29FP1He7PT%2B2NdYeyBIjAk2reqCeOmM5aJgnXotFQzI%3D&reserved=0Quoted 3 lines
The DDRC can measure bandwith usage and I want to use the passive governor to make the main NOC match OPPs.
which one use the passive governor? And which one is the parent devfreq device for devfreq device using passive governor?
In my case, it is difficult to catch the relationship between devices. I'd like you to explain the detailed relationship on binding document for user.
Quoted 1 line
But at the bus level DDRC only has AXI and APB slave ports.
'DDRC' indicates the '
drivers/devfreq/imx8m-ddrc.c?Quoted 3 lines
Buses on imx don't have a parent/child relationship; in fact there are even a few cycles.
Quoted 6 lines
Quoted 3 lines
You mentioned that 'imx don't have a parent/child relationship', Why do you use 'passive' governor? It is difficult to understand the hierarchy of imx.
The imx8m has a main NOC in the center between the CPU and the DDRC (dram controller) with many other peripheral buses around the NOC.
Actually, if this dt binding document contains the relationship between ddrc(imx8m-ddrc.c)
, imx-bus.c(bus) and interconnect node, it is more easy to understand the hierarchy
of bus/ddrc. In my case, it is difficult because the binding document doesn't include the enough example. But, I'll expect them as you mentioned on your reply.Quoted 3 lines
Here's
/sys/kernel/debug/interconnect/interconnect_graphon imx8mm:
https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgist.github.com%2Fcdleonard%2F84d103dafc9131fcb8ca9a494822a131%23file-imx8mm-svg&data=02%7C01%7Cleonard.crestez%40nxp.com%7C40406bfd0f134eeddb3208d7849c0968%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637123678022522615&sdata=anAPK7CpjdRtE7S%2FRPo0TY08OgC2EWmuHk58nBfZ1og%3D&reserved=0It is the interconnect node graph. I hope to know the relationship when bus(imx-bus.c)
uses the 'passive governor' and which is theQuoted 7 lines
A lot of stuff is omitted, it mostly just includes high-performance bus masters.
DDRC has a performance monitor attached which can measure current bandwith and feed it to an ondemand governor. I want to use passive governor on the NOC so that it matches frequencies with DDRC and scales
Quoted 8 lines
I have the following questions. If you explain the more detailed descritpion and add multiple dt bidning example, I'll expect that I can understand the following my questions.
- Which one will use the 'passive governor'?
- DDRC is parent devfreq device for imx bus(imx-bus.c) using passive governor?
- Why imx bus(imx-bus.c) use the userspace governor?
- Which the relationship between imx bus(imx-bus.c) using userspace governor and imx bus(imx-bus.c) using passive governor?
NOC would use the passive governor with devfreq_passive_data.parent sent to DDRC so that it matches rates when DDRC uses ondemand governor. This is a minor feature meant to make ondemand scaling behave more usefully, otherwise NOC might be a bottleneck for when CPU uses lots of ram bandwidth. It would make sense to split it into a separate patch.
The same imx-bus driver can also be used for peripheral buses (for example PL301_MIPI using imx8m-nic compatible) and in that case it will just use the userspace governor by default.
Useful scaling for the mipi bus would be performed via interconenct: the display controller (LCDIF) could request bandwidth along an icc_path that goes: LCDIF->PL301_MIPI->NOC->DDRC and then the interconnect provider would aggregate requests and translate them into separate minimum frequencies for PL301_MIPI, NOC and DDRC.
Camera devices would share this path while GPU and VPUs would only share NOC and DDRC. This detail is specific to 8mm, interconnect graph is different on 8mq and 8mn.
The "interconnect" driver is very loosely coupled to "devfreq" drivers:
it just makes QOS_MIN_FREQUENCY requests. There is already a distinct driver for imx8m-ddrc and in theory fsl,imx8m-noc and fsl,imx8m-nic could have distinct drivers as well. It would be pointless because all they currently do is set a single clock rate so they're all handled by a single imx-bus driver, similar to exynos-bus.
The interconnect driver shares the imx8m-noc binding with imx-bus because "virtual nodes" are strongly discouraged as they don't "describe hardware". Earlier versions of the series had a virtual node.
Quoted 5 lines
Quoted 4 lines
proportionally, otherwise if NOC is at low frequency then dynamically scaling up the DDRC might be ineffective.
Perhaps you could explain how parent/child relationships work on exynos?
Quoted 51 lines
Right. So, I wrote[1] why
exynos-bus.chave to use the passive governor and how to make the hierarchy/relationship between exynos-bus(parent devfreq device
using devfreq governor except for passive governor)
and exynos-bus (child devfreq device using only passive governor).[1]
Documentation/devicetree/bindings/devfreq/exynos-bus.txtQuoted 43 lines
Quoted 43 lines
Quoted 36 lines
Quoted 36 lines
[1] [PATCH RFC v5 04/10] PM / devfreq: Add
devfreq_get_devfreq_by_nodeQuoted 33 lines
Quoted 19 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +18
-0+ passive governor. + + '#interconnect-cells': + description: + If specified then also act as an interconnect provider. Should only be + set once per soc on main noc. + const: 1 + + fsl,scalable-node-ids: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Array of node ids for scalable nodes. Uses same numeric identifier + namespace as the consumer "interconnects" binding. + + fsl,scalable-nodes: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: + Array of phandles to scalable nodes. Must be of same length asDocumentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml line 80
Quoted 10 lines
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yaml new file +10
-0+ fsl,scalable-node-ids. + +required: + - compatible + - clocks + +additionalProperties: false + +examples: + - |Is it enough example to understand the relation between
imx8m-ddrc.c,imx-devfreq.cand imx interconnect driver?Quoted 5 lines
Quoted 3 lines
Quoted 3 lines
In my case, if possible, hope to show the more detailed example. This example seems that don't contain the ddrc dt node (
imx8m-ddrc.c).OK, I'll elaborate explanation on noc binding.
Thanks. If possible, you better to add almost example cases.
Here's a more elaborate example:
#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>;
};RFC PATCH v6 2/9 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-devfreq.c | 150 ++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 drivers/devfreq/imx-devfreq.c
drivers/devfreq/Kconfig +9 -0
@@ -98,10 +98,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_DEVFREQ + tristate "i.MX Generic 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
@@ -8,10 +8,11 @@ obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o # DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o +obj-$(CONFIG_ARM_IMX_DEVFREQ) += imx-devfreq.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o # DEVFREQ Event Drivers
drivers/devfreq/imx-devfreq.c new file +150 -0
150 lines not on this page · raw message
Signature · 1 line
2.17.1
Re: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
Hi Leonard,
Quoted 6 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.
Is this working with mainline ATF or does it still need to be used with your modified ATF code ?
Thanks
Angus
Quoted 207 lines
Signed-off-by Leonard Crestez <[email protected]>--- drivers/devfreq/Kconfig | 9 ++ drivers/devfreq/Makefile | 1 + drivers/devfreq/imx-devfreq.c | 150 ++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 drivers/devfreq/imx-devfreq.cdrivers/devfreq/Kconfig +0
-0@@ -98,10 +98,19 @@ config ARM_IMX8M_DDRC_DEVFREQ select DEVFREQ_GOV_USERSPACE help This adds the DEVFREQ driver for the i.MX8M DDR Controller. Itallows
drivers/devfreq/Kconfig +9
-0adjusting DRAM frequency. +config ARM_IMX_DEVFREQ + tristate "i.MX Generic 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 +0
-0@@ -8,10 +8,11 @@ obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) +=governor_userspace.o
obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o# DEVFREQ Drivers
obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o
obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.odrivers/devfreq/Makefile +1
-0+obj-$(CONFIG_ARM_IMX_DEVFREQ) += imx-devfreq.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o # DEVFREQ Event Driversdrivers/devfreq/imx-devfreq.c new file +42
-0@@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright 2019 NXP +*/ + +#include <linux/clk.h> +#include <linux/devfreq.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/pm_opp.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +struct imx_devfreq { +struct devfreq_dev_profile profile; +struct devfreq *devfreq; +struct clk *clk; +struct devfreq_passive_data passive_data; +}; + +static int imx_devfreq_target (struct device *dev, +unsigned long *freq,u32 flags) +{ +struct imx_devfreq *priv =dev_get_drvdata (dev); +struct dev_pm_opp *new_opp; +unsigned long new_freq; +int ret; + + new_opp =devfreq_recommended_opp (dev, freq, flags); +if (IS_ERR (new_opp)) { + ret =PTR_ERR (new_opp); +dev_err (dev,"failed to get recommended opp: %d\n" , ret); +return ret; + } + new_freq =dev_pm_opp_get_freq (new_opp); +dev_pm_opp_put (new_opp); + +return clk_set_rate (priv->clk, new_freq); +} + +static int imx_devfreq_get_cur_freq(struct device *dev, unsigned long*freq)
drivers/devfreq/imx-devfreq.c new file +108
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + *freq =clk_get_rate (priv->clk); + +return 0 ; +} + +static int imx_devfreq_get_dev_status (struct device *dev, +struct devfreq_dev_status *stat) +{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + stat->busy_time =0 ; + stat->total_time =0 ; + stat->current_frequency =clk_get_rate (priv->clk); + +return 0 ; +} + +static void imx_devfreq_exit (struct device *dev) +{ +dev_pm_opp_of_remove_table (dev); +} + +static int imx_devfreq_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct imx_devfreq *priv; +const char *gov =DEVFREQ_GOV_USERSPACE ; +void *govdata =NULL ; +int ret; + + priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + priv->clk =devm_clk_get (dev,NULL ); +if (IS_ERR (priv->clk)) { + ret =PTR_ERR (priv->clk); +dev_err (dev,"failed to fetch clk: %d\n" , ret); +return ret; + } +platform_set_drvdata (pdev, priv); + + ret =dev_pm_opp_of_add_table (dev); +if (ret <0 ) { +dev_err (dev,"failed to get OPP table\n" ); +return ret; + } + + priv->profile.polling_ms =1000 ; + priv->profile.target = imx_devfreq_target; + priv->profile.get_dev_status = imx_devfreq_get_dev_status; + priv->profile.exit = imx_devfreq_exit; + priv->profile.get_cur_freq = imx_devfreq_get_cur_freq; + priv->profile.initial_freq =clk_get_rate (priv->clk); + +/* Handle passive devfreq parent link */ + priv->passive_data.parent =devfreq_get_devfreq_by_phandle (dev,0 ); +if (!IS_ERR (priv->passive_data.parent)) { +dev_info (dev,"setup passive link to %s\n" , +dev_name (priv->passive_data.parent->dev.parent)); + gov =DEVFREQ_GOV_PASSIVE ; + govdata = &priv->passive_data; + }else if (priv->passive_data.parent !=ERR_PTR (-ENODEV )) { +// -ENODEV means no parent: not an error. + ret =PTR_ERR (priv->passive_data.parent); +if (ret != -EPROBE_DEFER ) +dev_warn (dev,"failed to get initialize passive parent: %d\n" , + ret); + goto err; + } + + priv->devfreq =devm_devfreq_add_device (dev, &priv->profile, + gov, govdata); +if (IS_ERR (priv->devfreq)) { + ret =PTR_ERR (priv->devfreq); +dev_err (dev,"failed to add devfreq device: %d\n" , ret); + goto err; + } + +return 0 ; + +err: +dev_pm_opp_of_remove_table (dev); +return ret; +} + +static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8m-noc" , }, + { .compatible ="fsl,imx8m-nic" , }, + {/* sentinel */ }, +}; +MODULE_DEVICE_TABLE (of, imx_devfreq_of_match); + +static struct platform_driver imx_devfreq_platdrv = { + .probe = imx_devfreq_probe, + .driver = { + .name ="imx-devfreq" , + .of_match_table =of_match_ptr (imx_devfreq_of_match), + }, +}; +module_platform_driver (imx_devfreq_platdrv); + +MODULE_DESCRIPTION ("Generic i.MX bus frequency driver" ); +MODULE_AUTHOR ("Leonard Crestez <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );
Re: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
Quoted 7 lines · Angus Ainslie
Hi Leonard,
Quoted 4 lines · Leonard Crestez
Add initial support for dynamic frequency switching on pieces of the imx
interconnect fabric.
Quoted 6 lines
Quoted 3 lines
All this driver does is set a clk rate based on an opp table, it does not map register areas.
Is this working with mainline ATF or does it still need to be used with your modified ATF code ?
This series doesn't perform SMC calls, that's done by the imx8m-ddrc
driver: https://patchwork.kernel.org/cover/11244283/
This particular patch allows switching NOC frequency but that's just clk_set_rate.
DDRC frequency switching requires the imx branch of ATF (v2.0 + ~200 patches) otherwise you will get probe failures. Source for imx atf is published here: https://source.codeaurora.org/external/imx/imx-atf/
For your particular 8mq B0 case slightly different setpoints are used and the fix is not in any public release yet so you need this:
https://github.com/cdleonard/arm-trusted-firmware/commits/imx_2.0.y_busfreq
Is "mainline ATF" an important criteria for Purism?
--
Regards,
Leonard
Re: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
Hi Leonard,
Quoted 25 lines · Leonard Crestez
Quoted 7 lines · Angus Ainslie
Hi Leonard,
Quoted 4 lines · Leonard Crestez
Add initial support for dynamic frequency switching on pieces of the imx
interconnect fabric.Quoted 6 lines
Quoted 3 lines
All this driver does is set a clk rate based on an opp table, it does not map register areas.
Is this working with mainline ATF or does it still need to be used with your modified ATF code ?
This series doesn't perform SMC calls, that's done by the imx8m-ddrc
driver: https://patchwork.kernel.org/cover/11244283/This particular patch allows switching NOC frequency but that's just
clk_set_rate.DDRC frequency switching requires the imx branch of ATF (v2.0 + ~200 patches) otherwise you will get probe failures. Source for imx atf is published here: https://source.codeaurora.org/external/imx/imx-atf/
Quoted 6 lines
For your particular 8mq B0 case slightly different setpoints are used and the fix is not in any public release yet so you need this:
https://github.com/cdleonard/arm-trusted-firmware/commits/imx_2.0.y_busfreq
Is "mainline ATF" an important criteria for Purism?
Sorry for jumping in here. Just asking myself if the nxp-atf is required for a mainline kernel for the imx8mq devices?
Thanks,
Marco
Quoted 9 lines
--
Regards,
Leonard_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Signature · 4 lines
Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
Re: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
In reply to Leonard CrestezHi Leonard,
Quoted 18 lines · Leonard Crestez
Quoted 7 lines · Angus Ainslie
Hi Leonard,
Quoted 4 lines · Leonard Crestez
Add initial support for dynamic frequency switching on pieces of the imx
interconnect fabric.Quoted 6 lines
Quoted 3 lines
All this driver does is set a clk rate based on an opp table, it does not map register areas.
Is this working with mainline ATF or does it still need to be used with your modified ATF code ?
This series doesn't perform SMC calls, that's done by the imx8m-ddrc
driver: https://patchwork.kernel.org/cover/11244283/
Quoted 6 lines
This particular patch allows switching NOC frequency but that's just
clk_set_rate.DDRC frequency switching requires the imx branch of ATF (v2.0 + ~200 patches) otherwise you will get probe failures. Source for imx atf is published here: https://source.codeaurora.org/external/imx/imx-atf/
Ok I was under the impression that the imx_2.0.y_busfreq branch below was based on this. Shouldn't those patches be added to the imx ATF ?
Quoted 6 lines
For your particular 8mq B0 case slightly different setpoints are used and the fix is not in any public release yet so you need this:
https://github.com/cdleonard/arm-trusted-firmware/commits/imx_2.0.y_busfreq
We also have 2n14w ( is that B1 ? ) imx8mq's that we are working with.
Quoted 2 lines
Is "mainline ATF" an important criteria for Purism?
Yes we intend to bring all of our patches to mainline and were hoping that NXP would be doing the same. Shouldn't a mainline kernel run on a mainline ATF ?
Thanks
Angus
Quoted 3 lines
--
Regards,
Leonard
_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Re: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
Quoted 24 lines · Angus Ainslie
Hi Leonard,
Quoted 21 lines · Leonard Crestez
Quoted 7 lines · Angus Ainslie
Hi Leonard,
Quoted 4 lines · Leonard Crestez
Add initial support for dynamic frequency switching on pieces of the imx
interconnect fabric.Quoted 6 lines
Quoted 3 lines
All this driver does is set a clk rate based on an opp table, it does not map register areas.
Is this working with mainline ATF or does it still need to be used with your modified ATF code ?
This series doesn't perform SMC calls, that's done by the imx8m-ddrc
driver: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.kernel.org%2Fcover%2F11244283%2F&data=02%7C01%7Cleonard.crestez%40nxp.com%7C186d3c14d8bc41216e3b08d76dd0106d%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637098612732915017&sdata=ER10Ts4hk2Ft7%2FWBZ7r8lyFkB6un1VRwk0rSvRMm3ew%3D&reserved=0This particular patch allows switching NOC frequency but that's just
clk_set_rate.
Quoted 6 lines
Quoted 3 lines
DDRC frequency switching requires the imx branch of ATF (v2.0 + ~200
patches) otherwise you will get probe failures. Source for imx atf is
published here: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fsource.codeaurora.org%2Fexternal%2Fimx%2Fimx-atf%2F&data=02%7C01%7Cleonard.crestez%40nxp.com%7C186d3c14d8bc41216e3b08d76dd0106d%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637098612732915017&sdata=KcdzTQaW4xxualeRUU%2B9LjBeq99wUtzDBxrHWLVbkDo%3D&reserved=0Ok I was under the impression that the imx_2.0.y_busfreq branch below was based on this. Shouldn't those patches be added to the imx ATF ?
Already done, it's just that CAF public releases are only made after internal testing. TF-A is open-source so I push patches to my personal github to help more adventurous developers.
Quoted 7 lines
Quoted 5 lines
For your particular 8mq B0 case slightly different setpoints are used and the fix is not in any public release yet so you need this:
We also have 2n14w ( is that B1 ? ) imx8mq's that we are working with.
Errata is e11327 and does not appear on 2N14W:
https://www.nxp.com/docs/en/errata/IMX8MDQLQ_1N14W.pdf
https://www.nxp.com/docs/en/errata/IMX8MDQLQ_2N14W.pdf
You should be able to test with a published release:
https://source.codeaurora.org/external/imx/imx-atf/log/?h=imx_4.19.35_1.1.0
Quoted 5 lines
Quoted 1 line
Is "mainline ATF" an important criteria for Purism?
Yes we intend to bring all of our patches to mainline and were hoping that NXP would be doing the same. Shouldn't a mainline kernel run on a mainline ATF ?
You can still use mainline ATF (tested right now) but the imx8m-ddrc driver won't probe.
The ability to mix and match different branches of firmware and kernel is very useful for testing. There might be slight incompatibilities but in theory if a feature depends on both firmware and kernel support then it should gracefully degrade rather than crash or hang.
ATF support for this feature will be mainlined eventually, I picked the linux side first because review is more challenging and changes are much larger relative to what we have in our internal tree.
--
Regards,
Leonard
Re: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
Quoted 7 lines · Leonard Crestez
Quoted 6 lines · Angus Ainslie
Hi Leonard,
Quoted 2 lines · Leonard Crestez
On 20.11.2019 16:08, Angus Ainslie wrote:
Is "mainline ATF" an important criteria for Purism?
Quoted 7 lines
Quoted 3 lines
Yes we intend to bring all of our patches to mainline and were hoping that NXP would be doing the same. Shouldn't a mainline kernel run on a mainline ATF ?
You can still use mainline ATF (tested right now) but the imx8m-ddrc driver won't probe.
Sorry I was talking about the DDR frequency scaling specifically.
Quoted 4 lines
The ability to mix and match different branches of firmware and kernel is very useful for testing. There might be slight incompatibilities but in theory if a feature depends on both firmware and kernel support then it should gracefully degrade rather than crash or hang.
I saw the check you put in for the correct ATF version and that's very helpful thanks.
Quoted 5 lines
ATF support for this feature will be mainlined eventually, I picked the linux side first because review is more challenging and changes are much larger relative to what we have in our internal tree.
Do you have a patch against mainline ATF that we can test this feature with ?
Thanks
Angus
Quoted 3 lines
--
Regards,
Leonard
Re: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
Quoted 24 lines · Angus Ainslie
Quoted 7 lines · Leonard Crestez
Quoted 6 lines · Angus Ainslie
Hi Leonard,
Quoted 2 lines · Leonard Crestez
On 20.11.2019 16:08, Angus Ainslie wrote:
Is "mainline ATF" an important criteria for Purism?Quoted 6 lines
Quoted 3 lines
Yes we intend to bring all of our patches to mainline and were hoping that NXP would be doing the same. Shouldn't a mainline kernel run on a mainline ATF ?
You can still use mainline ATF (tested right now) but the imx8m-ddrc driver won't probe.
Sorry I was talking about the DDR frequency scaling specifically. >
Quoted 4 lines
The ability to mix and match different branches of firmware and kernel is very useful for testing. There might be slight incompatibilities but in theory if a feature depends on both firmware and kernel support then it should gracefully degrade rather than crash or hang.
I saw the check you put in for the correct ATF version and that's very helpful thanks.
Quoted 6 lines
Quoted 3 lines
ATF support for this feature will be mainlined eventually, I picked the linux side first because review is more challenging and changes are much larger relative to what we have in our internal tree.
Do you have a patch against mainline ATF that we can test this feature with ?
Not right now, and imx atf is based on a slightly older version so some porting effort might be required.
--
Regards,
Leonard
_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Re: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
Quoted 29 lines · Leonard Crestez
Quoted 28 lines · Angus Ainslie
Quoted 7 lines · Leonard Crestez
Quoted 6 lines · Angus Ainslie
Hi Leonard,
Quoted 2 lines · Leonard Crestez
On 20.11.2019 16:08, Angus Ainslie wrote:
Is "mainline ATF" an important criteria for Purism?Quoted 6 lines
Quoted 3 lines
Yes we intend to bring all of our patches to mainline and were hoping that NXP would be doing the same. Shouldn't a mainline kernel run on a mainline ATF ?
You can still use mainline ATF (tested right now) but the imx8m-ddrc driver won't probe.
Sorry I was talking about the DDR frequency scaling specifically. >
Quoted 4 lines
The ability to mix and match different branches of firmware and kernel is very useful for testing. There might be slight incompatibilities but in theory if a feature depends on both firmware and kernel support then it should gracefully degrade rather than crash or hang.
I saw the check you put in for the correct ATF version and that's very helpful thanks.
Quoted 3 lines
ATF support for this feature will be mainlined eventually, I picked the linux side first because review is more challenging and changes are much larger relative to what we have in our internal tree.
Quoted 6 lines
Quoted 2 lines
Do you have a patch against mainline ATF that we can test this feature with ?
Not right now, and imx atf is based on a slightly older version so some porting effort might be required.
Hi Leonard,
Have you, by chance, looked at the mainline ATF side for your devfreq work in the meantime? I'd happily test. (btw. the linux driver fails "nicely" there.)
thanks,
martin
Re: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
Quoted 37 lines · Martin Kepplinger
Quoted 29 lines · Leonard Crestez
Quoted 28 lines · Angus Ainslie
Quoted 7 lines · Leonard Crestez
Quoted 6 lines · Angus Ainslie
Hi Leonard,
Quoted 2 lines · Leonard Crestez
On 20.11.2019 16:08, Angus Ainslie wrote:
Is "mainline ATF" an important criteria for Purism?Quoted 6 lines
Quoted 3 lines
Yes we intend to bring all of our patches to mainline and were hoping that NXP would be doing the same. Shouldn't a mainline kernel run on a mainline ATF ?
You can still use mainline ATF (tested right now) but the imx8m-ddrc driver won't probe.
Sorry I was talking about the DDR frequency scaling specifically. >
Quoted 4 lines
The ability to mix and match different branches of firmware and kernel is very useful for testing. There might be slight incompatibilities but in theory if a feature depends on both firmware and kernel support then it should gracefully degrade rather than crash or hang.
I saw the check you put in for the correct ATF version and that's very helpful thanks.
Quoted 3 lines
ATF support for this feature will be mainlined eventually, I picked the linux side first because review is more challenging and changes are much larger relative to what we have in our internal tree.
Quoted 6 lines
Quoted 2 lines
Do you have a patch against mainline ATF that we can test this feature with ?
Not right now, and imx atf is based on a slightly older version so some porting effort might be required.
Quoted 6 lines
Hi Leonard,
Have you, by chance, looked at the mainline ATF side for your devfreq work in the meantime? I'd happily test. (btw. the linux driver fails "nicely" there.)
hi again. Do you have any plans regarding the ATF implementation of IMX_SIP_DDR_DVFS in mainline yet? The kernel is only one half of the devfreq solution after all. I'm asking just to schedule my work a bit :)
thanks,
martin
Chanwoo Choi
maintainerRe: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
In reply to Leonard CrestezHi,
Quoted 73 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-devfreq.c | 150 ++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 drivers/devfreq/imx-devfreq.cdrivers/devfreq/Kconfig +9
-0@@ -98,10 +98,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_DEVFREQ + tristate "i.MX Generic 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@@ -8,10 +8,11 @@ obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o # DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o +obj-$(CONFIG_ARM_IMX_DEVFREQ) += imx-devfreq.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o # DEVFREQ Event Driversdrivers/devfreq/imx-devfreq.c new file +13
-0@@ -0,0 +1,150 @@ +// 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>
drivers/devfreq/imx-devfreq.c line 23
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ +struct imx_devfreq { +struct devfreq_dev_profile profile; +struct devfreq *devfreq; +struct clk *clk; +struct devfreq_passive_data passive_data; +}; + +static int imx_devfreq_target (struct device *dev, +unsigned long *freq,u32 flags)
Don't use space for the indentation. Please use only tab.
Quoted 19 lines
drivers/devfreq/imx-devfreq.c new file +19
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); +struct dev_pm_opp *new_opp; +unsigned long new_freq; +int ret; + + new_opp =devfreq_recommended_opp (dev, freq, flags); +if (IS_ERR (new_opp)) { + ret =PTR_ERR (new_opp); +dev_err (dev,"failed to get recommended opp: %d\n" , ret); +return ret; + } + new_freq =dev_pm_opp_get_freq (new_opp); +dev_pm_opp_put (new_opp); + +return clk_set_rate (priv->clk, new_freq); +} + +static int imx_devfreq_get_cur_freq (struct device *dev,unsigned long *freq)
drivers/devfreq/imx-devfreq.c line 52
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + *freq =clk_get_rate (priv->clk); + +return 0 ; +} + +static int imx_devfreq_get_dev_status (struct device *dev, +struct devfreq_dev_status *stat)
ditto. Please use tab for the indentation.
Quoted 9 lines
drivers/devfreq/imx-devfreq.c new file +9
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + stat->busy_time =0 ; + stat->total_time =0 ; + stat->current_frequency =clk_get_rate (priv->clk); + +return 0 ; +}
drivers/devfreq/imx-devfreq.c line 71
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ +static void imx_devfreq_exit (struct device *dev) +{ +dev_pm_opp_of_remove_table (dev); +} + +static int imx_devfreq_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct imx_devfreq *priv;
How about changing the variable name 'priv' to 'imx' or 'imx_data'? because it is not easy to catch the role of 'priv' from variable name.
drivers/devfreq/imx-devfreq.c line 73
Quoted 2 lines
drivers/devfreq/imx-devfreq.c new file +2
-0+const char *gov =DEVFREQ_GOV_USERSPACE ; +void *govdata =NULL ;
How about changing the variable name 'govdata' to 'gov_data'?
- govdata -> gov_data
drivers/devfreq/imx-devfreq.c line 80
Quoted 7 lines
drivers/devfreq/imx-devfreq.c new file +7
-0+int ret; + + priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + priv->clk =devm_clk_get (dev,NULL );
nitpick: because the clock-name is not mandatory. Don't need to specify the clock name to inform the role of clock of other developer/user?
For example, "ddr", "bus" and so on.
Quoted 25 lines
drivers/devfreq/imx-devfreq.c new file +25
-0+if (IS_ERR (priv->clk)) { + ret =PTR_ERR (priv->clk); +dev_err (dev,"failed to fetch clk: %d\n" , ret); +return ret; + } +platform_set_drvdata (pdev, priv); + + ret =dev_pm_opp_of_add_table (dev); +if (ret <0 ) { +dev_err (dev,"failed to get OPP table\n" ); +return ret; + } + + priv->profile.polling_ms =1000 ; + priv->profile.target = imx_devfreq_target; + priv->profile.get_dev_status = imx_devfreq_get_dev_status; + priv->profile.exit = imx_devfreq_exit; + priv->profile.get_cur_freq = imx_devfreq_get_cur_freq; + priv->profile.initial_freq =clk_get_rate (priv->clk); + +/* Handle passive devfreq parent link */ + priv->passive_data.parent =devfreq_get_devfreq_by_phandle (dev,0 ); +if (!IS_ERR (priv->passive_data.parent)) { +dev_info (dev,"setup passive link to %s\n" , +dev_name (priv->passive_data.parent->dev.parent));
drivers/devfreq/imx-devfreq.c line 115
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ gov =DEVFREQ_GOV_PASSIVE ; + govdata = &priv->passive_data; + }else if (priv->passive_data.parent !=ERR_PTR (-ENODEV )) { +// -ENODEV means no parent: not an error. + ret =PTR_ERR (priv->passive_data.parent); +if (ret != -EPROBE_DEFER ) +dev_warn (dev,"failed to get initialize passive parent: %d\n" , + ret); + goto err; + }
You better to change the exception handling as following: It is more simple.
} else if (PTR_ERR(priv->passive_data.parent) == -EPROBE_DEFER)
|| PTR_ERR(priv->passive_data.parent) == -ENODEV) {
goto err;
} else {
ret = PTR_ERR(priv->passive_data.parent);
dev_err(dev, "failed to get initialize passive parent: %d\n", ret);
goto err;
}Quoted 23 lines
drivers/devfreq/imx-devfreq.c new file +23
-0+ + priv->devfreq =devm_devfreq_add_device (dev, &priv->profile, + gov, govdata); +if (IS_ERR (priv->devfreq)) { + ret =PTR_ERR (priv->devfreq); +dev_err (dev,"failed to add devfreq device: %d\n" , ret); + goto err; + } + +return 0 ; + +err: +dev_pm_opp_of_remove_table (dev); +return ret; +} + +static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8m-noc" , }, + { .compatible ="fsl,imx8m-nic" , }, + {/* sentinel */ }, +}; +MODULE_DEVICE_TABLE (of, imx_devfreq_of_match); +
drivers/devfreq/imx-devfreq.c line 148
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+static struct platform_driver imx_devfreq_platdrv = { + .probe = imx_devfreq_probe, + .driver = { + .name ="imx-devfreq" , + .of_match_table =of_match_ptr (imx_devfreq_of_match), + }, +}; +module_platform_driver (imx_devfreq_platdrv); + +MODULE_DESCRIPTION ("Generic i.MX bus frequency driver" );
If this driver is for bus frequency, you better to use 'bus' for the clock-name for the readability.
Quoted 3 lines
drivers/devfreq/imx-devfreq.c new file +2
-0+MODULE_AUTHOR ("Leonard Crestez <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );
Signature · 3 lines
Best Regards, Chanwoo Choi Samsung Electronics
Chanwoo Choi
maintainerRe: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
Quoted 162 lines · Chanwoo Choi
Hi,
Quoted 73 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-devfreq.c | 150 ++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 drivers/devfreq/imx-devfreq.cdrivers/devfreq/Kconfig +9
-0@@ -98,10 +98,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_DEVFREQ + tristate "i.MX Generic 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@@ -8,10 +8,11 @@ obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o # DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o +obj-$(CONFIG_ARM_IMX_DEVFREQ) += imx-devfreq.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o # DEVFREQ Event Driversdrivers/devfreq/imx-devfreq.c new file +13
-0@@ -0,0 +1,150 @@ +// 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> drivers/devfreq/imx-devfreq.c line 23
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ +struct imx_devfreq { +struct devfreq_dev_profile profile; +struct devfreq *devfreq; +struct clk *clk; +struct devfreq_passive_data passive_data; +}; + +static int imx_devfreq_target (struct device *dev, +unsigned long *freq,u32 flags)Don't use space for the indentation. Please use only tab.
Quoted 19 lines
drivers/devfreq/imx-devfreq.c new file +19
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); +struct dev_pm_opp *new_opp; +unsigned long new_freq; +int ret; + + new_opp =devfreq_recommended_opp (dev, freq, flags); +if (IS_ERR (new_opp)) { + ret =PTR_ERR (new_opp); +dev_err (dev,"failed to get recommended opp: %d\n" , ret); +return ret; + } + new_freq =dev_pm_opp_get_freq (new_opp); +dev_pm_opp_put (new_opp); + +return clk_set_rate (priv->clk, new_freq); +} + +static int imx_devfreq_get_cur_freq (struct device *dev,unsigned long *freq)drivers/devfreq/imx-devfreq.c line 52
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + *freq =clk_get_rate (priv->clk); + +return 0 ; +} + +static int imx_devfreq_get_dev_status (struct device *dev, +struct devfreq_dev_status *stat)ditto. Please use tab for the indentation.
Quoted 9 lines
drivers/devfreq/imx-devfreq.c new file +9
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + stat->busy_time =0 ; + stat->total_time =0 ; + stat->current_frequency =clk_get_rate (priv->clk); + +return 0 ; +}drivers/devfreq/imx-devfreq.c line 71
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ +static void imx_devfreq_exit (struct device *dev) +{ +dev_pm_opp_of_remove_table (dev); +} + +static int imx_devfreq_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct imx_devfreq *priv;How about changing the variable name 'priv' to 'imx' or '
imx_data'? because it is not easy to catch the role of 'priv' from variable name.drivers/devfreq/imx-devfreq.c line 73
Quoted 2 lines
drivers/devfreq/imx-devfreq.c new file +2
-0+const char *gov =DEVFREQ_GOV_USERSPACE ; +void *govdata =NULL ;How about changing the variable name 'govdata' to '
gov_data'?
- govdata ->gov_datadrivers/devfreq/imx-devfreq.c line 80
Quoted 7 lines
drivers/devfreq/imx-devfreq.c new file +7
-0+int ret; + + priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + priv->clk =devm_clk_get (dev,NULL );nitpick: because the clock-name is not mandatory. Don't need to specify the clock name to inform the role of clock of other developer/user?
Quoted 1 line
For example, "ddr", "bus" and so on.
And, this driver doesn't include the 'clk_prepare_enable'. how to enable the clock?
Quoted 90 lines
Quoted 26 lines
drivers/devfreq/imx-devfreq.c new file +25
-0+if (IS_ERR (priv->clk)) { + ret =PTR_ERR (priv->clk); +dev_err (dev,"failed to fetch clk: %d\n" , ret); +return ret; + } +platform_set_drvdata (pdev, priv); + + ret =dev_pm_opp_of_add_table (dev); +if (ret <0 ) { +dev_err (dev,"failed to get OPP table\n" ); +return ret; + } + + priv->profile.polling_ms =1000 ; + priv->profile.target = imx_devfreq_target; + priv->profile.get_dev_status = imx_devfreq_get_dev_status; + priv->profile.exit = imx_devfreq_exit; + priv->profile.get_cur_freq = imx_devfreq_get_cur_freq; + priv->profile.initial_freq =clk_get_rate (priv->clk); + +/* Handle passive devfreq parent link */ + priv->passive_data.parent =devfreq_get_devfreq_by_phandle (dev,0 ); +if (!IS_ERR (priv->passive_data.parent)) { +dev_info (dev,"setup passive link to %s\n" , +dev_name (priv->passive_data.parent->dev.parent));drivers/devfreq/imx-devfreq.c line 115
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ gov =DEVFREQ_GOV_PASSIVE ; + govdata = &priv->passive_data; + }else if (priv->passive_data.parent !=ERR_PTR (-ENODEV )) { +// -ENODEV means no parent: not an error. + ret =PTR_ERR (priv->passive_data.parent); +if (ret != -EPROBE_DEFER ) +dev_warn (dev,"failed to get initialize passive parent: %d\n" , + ret); + goto err; + }You better to change the exception handling as following: It is more simple.
} else if (PTR_ERR(priv->passive_data.parent) == -EPROBE_DEFER) || PTR_ERR(priv->passive_data.parent) == -ENODEV) { goto err; } else { ret = PTR_ERR(priv->passive_data.parent); dev_err(dev, "failed to get initialize passive parent: %d\n", ret); goto err; }Quoted 23 lines
drivers/devfreq/imx-devfreq.c new file +23
-0+ + priv->devfreq =devm_devfreq_add_device (dev, &priv->profile, + gov, govdata); +if (IS_ERR (priv->devfreq)) { + ret =PTR_ERR (priv->devfreq); +dev_err (dev,"failed to add devfreq device: %d\n" , ret); + goto err; + } + +return 0 ; + +err: +dev_pm_opp_of_remove_table (dev); +return ret; +} + +static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8m-noc" , }, + { .compatible ="fsl,imx8m-nic" , }, + {/* sentinel */ }, +}; +MODULE_DEVICE_TABLE (of, imx_devfreq_of_match); +drivers/devfreq/imx-devfreq.c line 148
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+static struct platform_driver imx_devfreq_platdrv = { + .probe = imx_devfreq_probe, + .driver = { + .name ="imx-devfreq" , + .of_match_table =of_match_ptr (imx_devfreq_of_match), + }, +}; +module_platform_driver (imx_devfreq_platdrv); + +MODULE_DESCRIPTION ("Generic i.MX bus frequency driver" );If this driver is for bus frequency, you better to use 'bus' for the clock-name for the readability.
Quoted 3 lines
drivers/devfreq/imx-devfreq.c new file +2
-0+MODULE_AUTHOR ("Leonard Crestez <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );
Signature · 3 lines
Best Regards, Chanwoo Choi Samsung Electronics
Chanwoo Choi
maintainerRe: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
Hi,
Also, I think that 'devfreq' word is not proper for device driver name. imx-bus.c or imx-noc.c or others to inform the role of this driver of developer.
And, I have a question.
This driver adds the devfreq device with either passive governor or userspace governor.
As I understood, the devfreq device with passive governor will be operated with imx8m-ddrc.c driver.
But, when is operating with userspace governor?
I think that you better to add the explanation to description for two scenarios how to operate with interconnect provider on either passive governor or userspace governor usage case.
Quoted 260 lines · Chanwoo Choi
Quoted 162 lines · Chanwoo Choi
Hi,
Quoted 73 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-devfreq.c | 150 ++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 drivers/devfreq/imx-devfreq.cdrivers/devfreq/Kconfig +9
-0@@ -98,10 +98,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_DEVFREQ + tristate "i.MX Generic 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@@ -8,10 +8,11 @@ obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o # DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o +obj-$(CONFIG_ARM_IMX_DEVFREQ) += imx-devfreq.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o # DEVFREQ Event Driversdrivers/devfreq/imx-devfreq.c new file +13
-0@@ -0,0 +1,150 @@ +// 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> drivers/devfreq/imx-devfreq.c line 23
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ +struct imx_devfreq { +struct devfreq_dev_profile profile; +struct devfreq *devfreq; +struct clk *clk; +struct devfreq_passive_data passive_data; +}; + +static int imx_devfreq_target (struct device *dev, +unsigned long *freq,u32 flags)Don't use space for the indentation. Please use only tab.
Quoted 19 lines
drivers/devfreq/imx-devfreq.c new file +19
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); +struct dev_pm_opp *new_opp; +unsigned long new_freq; +int ret; + + new_opp =devfreq_recommended_opp (dev, freq, flags); +if (IS_ERR (new_opp)) { + ret =PTR_ERR (new_opp); +dev_err (dev,"failed to get recommended opp: %d\n" , ret); +return ret; + } + new_freq =dev_pm_opp_get_freq (new_opp); +dev_pm_opp_put (new_opp); + +return clk_set_rate (priv->clk, new_freq); +} + +static int imx_devfreq_get_cur_freq (struct device *dev,unsigned long *freq)drivers/devfreq/imx-devfreq.c line 52
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + *freq =clk_get_rate (priv->clk); + +return 0 ; +} + +static int imx_devfreq_get_dev_status (struct device *dev, +struct devfreq_dev_status *stat)ditto. Please use tab for the indentation.
Quoted 9 lines
drivers/devfreq/imx-devfreq.c new file +9
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + stat->busy_time =0 ; + stat->total_time =0 ; + stat->current_frequency =clk_get_rate (priv->clk); + +return 0 ; +}drivers/devfreq/imx-devfreq.c line 71
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ +static void imx_devfreq_exit (struct device *dev) +{ +dev_pm_opp_of_remove_table (dev); +} + +static int imx_devfreq_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct imx_devfreq *priv;How about changing the variable name 'priv' to 'imx' or '
imx_data'? because it is not easy to catch the role of 'priv' from variable name.drivers/devfreq/imx-devfreq.c line 73
Quoted 2 lines
drivers/devfreq/imx-devfreq.c new file +2
-0+const char *gov =DEVFREQ_GOV_USERSPACE ; +void *govdata =NULL ;How about changing the variable name 'govdata' to '
gov_data'?
- govdata ->gov_datadrivers/devfreq/imx-devfreq.c line 80
Quoted 7 lines
drivers/devfreq/imx-devfreq.c new file +7
-0+int ret; + + priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + priv->clk =devm_clk_get (dev,NULL );nitpick: because the clock-name is not mandatory. Don't need to specify the clock name to inform the role of clock of other developer/user?
Quoted 1 line
For example, "ddr", "bus" and so on.
And, this driver doesn't include the '
clk_prepare_enable'. how to enable the clock?Quoted 90 lines
Quoted 26 lines
drivers/devfreq/imx-devfreq.c new file +25
-0+if (IS_ERR (priv->clk)) { + ret =PTR_ERR (priv->clk); +dev_err (dev,"failed to fetch clk: %d\n" , ret); +return ret; + } +platform_set_drvdata (pdev, priv); + + ret =dev_pm_opp_of_add_table (dev); +if (ret <0 ) { +dev_err (dev,"failed to get OPP table\n" ); +return ret; + } + + priv->profile.polling_ms =1000 ; + priv->profile.target = imx_devfreq_target; + priv->profile.get_dev_status = imx_devfreq_get_dev_status; + priv->profile.exit = imx_devfreq_exit; + priv->profile.get_cur_freq = imx_devfreq_get_cur_freq; + priv->profile.initial_freq =clk_get_rate (priv->clk); + +/* Handle passive devfreq parent link */ + priv->passive_data.parent =devfreq_get_devfreq_by_phandle (dev,0 ); +if (!IS_ERR (priv->passive_data.parent)) { +dev_info (dev,"setup passive link to %s\n" , +dev_name (priv->passive_data.parent->dev.parent));drivers/devfreq/imx-devfreq.c line 115
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ gov =DEVFREQ_GOV_PASSIVE ; + govdata = &priv->passive_data; + }else if (priv->passive_data.parent !=ERR_PTR (-ENODEV )) { +// -ENODEV means no parent: not an error. + ret =PTR_ERR (priv->passive_data.parent); +if (ret != -EPROBE_DEFER ) +dev_warn (dev,"failed to get initialize passive parent: %d\n" , + ret); + goto err; + }You better to change the exception handling as following: It is more simple.
} else if (PTR_ERR(priv->passive_data.parent) == -EPROBE_DEFER) || PTR_ERR(priv->passive_data.parent) == -ENODEV) { goto err; } else { ret = PTR_ERR(priv->passive_data.parent); dev_err(dev, "failed to get initialize passive parent: %d\n", ret); goto err; }Quoted 23 lines
drivers/devfreq/imx-devfreq.c new file +23
-0+ + priv->devfreq =devm_devfreq_add_device (dev, &priv->profile, + gov, govdata); +if (IS_ERR (priv->devfreq)) { + ret =PTR_ERR (priv->devfreq); +dev_err (dev,"failed to add devfreq device: %d\n" , ret); + goto err; + } + +return 0 ; + +err: +dev_pm_opp_of_remove_table (dev); +return ret; +} + +static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8m-noc" , }, + { .compatible ="fsl,imx8m-nic" , }, + {/* sentinel */ }, +}; +MODULE_DEVICE_TABLE (of, imx_devfreq_of_match); +drivers/devfreq/imx-devfreq.c line 148
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+static struct platform_driver imx_devfreq_platdrv = { + .probe = imx_devfreq_probe, + .driver = { + .name ="imx-devfreq" , + .of_match_table =of_match_ptr (imx_devfreq_of_match), + }, +}; +module_platform_driver (imx_devfreq_platdrv); + +MODULE_DESCRIPTION ("Generic i.MX bus frequency driver" );If this driver is for bus frequency, you better to use 'bus' for the clock-name for the readability.
Quoted 3 lines
drivers/devfreq/imx-devfreq.c new file +2
-0+MODULE_AUTHOR ("Leonard Crestez <[email protected]>" ); +MODULE_LICENSE ("GPL v2" );
Signature · 3 lines
Best Regards, Chanwoo Choi Samsung Electronics
Re: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
Quoted 4 lines · Chanwoo Choi
Hi,
Also, I think that 'devfreq' word is not proper for device driver name.
imx-bus.corimx-noc.cor others to inform the role of this driver of developer.
I'll rename to "imx-bus". Calling it "imx-noc" is not appropriate because I also want to use it for PL301 NICs.
Quoted 7 lines
And, I have a question.
This driver adds the devfreq device with either passive governor or userspace governor.As I understood, the devfreq device with passive governor will be operated with
imx8m-ddrc.cdriver.
But, when is operating with userspace governor?
There are multiple scalable buses inside the SOC, for example there's a NIC for display controllers and one for (pci+usb). They can use userspace governor for explicit frequency control.
Quoted 3 lines
I think that you better to add the explanation to description for two scenarios how to operate with interconnect provider on either passive governor or userspace governor usage case.
I'll elaborate the example in bindings.
Quoted 82 lines · Chanwoo Choi
Quoted 81 lines · Chanwoo Choi
Quoted 80 lines
Hi,
Quoted 77 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-devfreq.c | 150 ++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+)create mode 100644
drivers/devfreq/imx-devfreq.cdrivers/devfreq/Kconfig +9
-0@@ -98,10 +98,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_DEVFREQ + tristate "i.MX Generic 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@@ -8,10 +8,11 @@ obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o # DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o +obj-$(CONFIG_ARM_IMX_DEVFREQ) += imx-devfreq.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o # DEVFREQ Event Driversdrivers/devfreq/imx-devfreq.c new file +17
-0@@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright 2019 NXP +*/ + +#include <linux/clk.h> +#include <linux/devfreq.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/pm_opp.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +struct imx_devfreq { +struct devfreq_dev_profile profile; +struct devfreq *devfreq;
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/devfreq/imx-devfreq.c line 23
Quoted 6 lines
drivers/devfreq/imx-devfreq.c new file +6
-0+struct clk *clk; +struct devfreq_passive_data passive_data; +}; + +static int imx_devfreq_target (struct device *dev, +unsigned long *freq,u32 flags)Don't use space for the indentation. Please use only tab.
OK
Quoted 46 lines
Quoted 46 lines
Quoted 46 lines
Quoted 19 lines
drivers/devfreq/imx-devfreq.c new file +19
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); +struct dev_pm_opp *new_opp; +unsigned long new_freq; +int ret; + + new_opp =devfreq_recommended_opp (dev, freq, flags); +if (IS_ERR (new_opp)) { + ret =PTR_ERR (new_opp); +dev_err (dev,"failed to get recommended opp: %d\n" , ret); +return ret; + } + new_freq =dev_pm_opp_get_freq (new_opp); +dev_pm_opp_put (new_opp); + +return clk_set_rate (priv->clk, new_freq); +} + +static int imx_devfreq_get_cur_freq (struct device *dev,unsigned long *freq)drivers/devfreq/imx-devfreq.c line 52
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + *freq =clk_get_rate (priv->clk); + +return 0 ; +} + +static int imx_devfreq_get_dev_status (struct device *dev, +struct devfreq_dev_status *stat)ditto. Please use tab for the indentation.
Quoted 14 lines
drivers/devfreq/imx-devfreq.c new file +14
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + stat->busy_time =0 ; + stat->total_time =0 ; + stat->current_frequency =clk_get_rate (priv->clk); + +return 0 ; +} + +static void imx_devfreq_exit (struct device *dev) +{ +dev_pm_opp_of_remove_table (dev); +}
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/devfreq/imx-devfreq.c line 71
Quoted 5 lines
drivers/devfreq/imx-devfreq.c new file +5
-0+ +static int imx_devfreq_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct imx_devfreq *priv;How about changing the variable name 'priv' to 'imx' or '
imx_data'? because it is not easy to catch the role of 'priv' from variable name.
The name "priv" refers to private data of current device: it is short and not ambiguous in this context. I don't think that mentioning "imx" adds any additional useful information.
It doesn't seem like there's much of a convention for "local variable containing private data", for example exynos-bus.c uses "struct exynos_bus* bus" internally.
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
drivers/devfreq/imx-devfreq.c line 73
Quoted 3 lines
drivers/devfreq/imx-devfreq.c new file +2
-0+const char *gov =DEVFREQ_GOV_USERSPACE ; +void *govdata =NULL ;How about changing the variable name 'govdata' to '
gov_data'?
- govdata ->gov_data
OK
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
drivers/devfreq/imx-devfreq.c line 80
Quoted 7 lines
drivers/devfreq/imx-devfreq.c new file +7
-0+int ret; + + priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + priv->clk =devm_clk_get (dev,NULL );nitpick: because the clock-name is not mandatory. Don't need to specify the clock name to inform the role of clock of other developer/user?
Quoted 1 line
Quoted 1 line
Quoted 1 line
For example, "ddr", "bus" and so on.
I'll call this bus, but I'm not sure it's useful when a single clock is involved.
Quoted 2 lines
Quoted 2 lines
And, this driver doesn't include the '
clk_prepare_enable'. how to enable the clock?
Clocks are either always on or perhaps controlled by some other peripheral. This driver only provides scaling.
Quoted 38 lines
Quoted 38 lines
Quoted 38 lines
Quoted 25 lines
drivers/devfreq/imx-devfreq.c new file +25
-0+if (IS_ERR (priv->clk)) { + ret =PTR_ERR (priv->clk); +dev_err (dev,"failed to fetch clk: %d\n" , ret); +return ret; + } +platform_set_drvdata (pdev, priv); + + ret =dev_pm_opp_of_add_table (dev); +if (ret <0 ) { +dev_err (dev,"failed to get OPP table\n" ); +return ret; + } + + priv->profile.polling_ms =1000 ; + priv->profile.target = imx_devfreq_target; + priv->profile.get_dev_status = imx_devfreq_get_dev_status; + priv->profile.exit = imx_devfreq_exit; + priv->profile.get_cur_freq = imx_devfreq_get_cur_freq; + priv->profile.initial_freq =clk_get_rate (priv->clk); + +/* Handle passive devfreq parent link */ + priv->passive_data.parent =devfreq_get_devfreq_by_phandle (dev,0 ); +if (!IS_ERR (priv->passive_data.parent)) { +dev_info (dev,"setup passive link to %s\n" , +dev_name (priv->passive_data.parent->dev.parent));drivers/devfreq/imx-devfreq.c line 115
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ gov =DEVFREQ_GOV_PASSIVE ; + govdata = &priv->passive_data; + }else if (priv->passive_data.parent !=ERR_PTR (-ENODEV )) { +// -ENODEV means no parent: not an error. + ret =PTR_ERR (priv->passive_data.parent); +if (ret != -EPROBE_DEFER ) +dev_warn (dev,"failed to get initialize passive parent: %d\n" , + ret); + goto err; + }You better to change the exception handling as following: It is more simple.
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
} else if (PTR_ERR(priv->passive_data.parent) == -EPROBE_DEFER) || PTR_ERR(priv->passive_data.parent) == -ENODEV) { goto err; } else { ret = PTR_ERR(priv->passive_data.parent); dev_err(dev, "failed to get initialize passive parent: %d\n", ret); goto err; }
But -ENODEV is not an error, it means no passive parent was found.
Quoted 27 lines
Quoted 27 lines
Quoted 27 lines
Quoted 27 lines
drivers/devfreq/imx-devfreq.c new file +27
-0+ priv->devfreq =devm_devfreq_add_device (dev, &priv->profile, + gov, govdata); +if (IS_ERR (priv->devfreq)) { + ret =PTR_ERR (priv->devfreq); +dev_err (dev,"failed to add devfreq device: %d\n" , ret); + goto err; + } + +return 0 ; + +err: +dev_pm_opp_of_remove_table (dev); +return ret; +} + +static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8m-noc" , }, + { .compatible ="fsl,imx8m-nic" , }, + {/* sentinel */ }, +}; +MODULE_DEVICE_TABLE (of, imx_devfreq_of_match); + +static struct platform_driver imx_devfreq_platdrv = { + .probe = imx_devfreq_probe, + .driver = { + .name ="imx-devfreq" , + .of_match_table =of_match_ptr (imx_devfreq_of_match),
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/devfreq/imx-devfreq.c line 148
Quoted 5 lines
drivers/devfreq/imx-devfreq.c new file +5
-0+ }, +}; +module_platform_driver (imx_devfreq_platdrv); + +MODULE_DESCRIPTION ("Generic i.MX bus frequency driver" );If this driver is for bus frequency, you better to use 'bus' for the clock-name for the readability.
OK
Chanwoo Choi
maintainerRe: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
Quoted 8 lines · Leonard Crestez
Quoted 4 lines · Chanwoo Choi
Hi,
Also, I think that 'devfreq' word is not proper for device driver name.
imx-bus.corimx-noc.cor others to inform the role of this driver of developer.I'll rename to "imx-bus". Calling it "imx-noc" is not appropriate because I also want to use it for PL301 NICs.
OK.
Quoted 13 lines
Quoted 8 lines
And, I have a question.
This driver adds the devfreq device with either passive governor or userspace governor.As I understood, the devfreq device with passive governor will be operated with
imx8m-ddrc.cdriver.
But, when is operating with userspace governor?There are multiple scalable buses inside the SOC, for example there's a NIC for display controllers and one for (pci+usb). They can use userspace governor for explicit frequency control.
Quoted 5 lines
Quoted 3 lines
I think that you better to add the explanation to description for two scenarios how to operate with interconnect provider on either passive governor or userspace governor usage case.
I'll elaborate the example in bindings.
OK.
Quoted 149 lines
Quoted 83 lines · Chanwoo Choi
Quoted 81 lines · Chanwoo Choi
Quoted 80 lines
Hi,
Quoted 77 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-devfreq.c | 150 ++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+)create mode 100644
drivers/devfreq/imx-devfreq.cdrivers/devfreq/Kconfig +9
-0@@ -98,10 +98,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_DEVFREQ + tristate "i.MX Generic 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@@ -8,10 +8,11 @@ obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o # DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o +obj-$(CONFIG_ARM_IMX_DEVFREQ) += imx-devfreq.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o # DEVFREQ Event Driversdrivers/devfreq/imx-devfreq.c new file +17
-0@@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright 2019 NXP +*/ + +#include <linux/clk.h> +#include <linux/devfreq.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/pm_opp.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +struct imx_devfreq { +struct devfreq_dev_profile profile; +struct devfreq *devfreq;Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/devfreq/imx-devfreq.c line 23
Quoted 6 lines
drivers/devfreq/imx-devfreq.c new file +6
-0+struct clk *clk; +struct devfreq_passive_data passive_data; +}; + +static int imx_devfreq_target (struct device *dev, +unsigned long *freq,u32 flags)Don't use space for the indentation. Please use only tab.
OK
Quoted 46 lines
Quoted 46 lines
Quoted 46 lines
Quoted 19 lines
drivers/devfreq/imx-devfreq.c new file +19
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); +struct dev_pm_opp *new_opp; +unsigned long new_freq; +int ret; + + new_opp =devfreq_recommended_opp (dev, freq, flags); +if (IS_ERR (new_opp)) { + ret =PTR_ERR (new_opp); +dev_err (dev,"failed to get recommended opp: %d\n" , ret); +return ret; + } + new_freq =dev_pm_opp_get_freq (new_opp); +dev_pm_opp_put (new_opp); + +return clk_set_rate (priv->clk, new_freq); +} + +static int imx_devfreq_get_cur_freq (struct device *dev,unsigned long *freq)drivers/devfreq/imx-devfreq.c line 52
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + *freq =clk_get_rate (priv->clk); + +return 0 ; +} + +static int imx_devfreq_get_dev_status (struct device *dev, +struct devfreq_dev_status *stat)ditto. Please use tab for the indentation.
Quoted 14 lines
drivers/devfreq/imx-devfreq.c new file +14
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + stat->busy_time =0 ; + stat->total_time =0 ; + stat->current_frequency =clk_get_rate (priv->clk); + +return 0 ; +} + +static void imx_devfreq_exit (struct device *dev) +{ +dev_pm_opp_of_remove_table (dev); +}Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/devfreq/imx-devfreq.c line 71
Quoted 5 lines
drivers/devfreq/imx-devfreq.c new file +5
-0+ +static int imx_devfreq_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct imx_devfreq *priv;How about changing the variable name 'priv' to 'imx' or '
imx_data'? because it is not easy to catch the role of 'priv' from variable name.
Quoted 7 lines
The name "priv" refers to private data of current device: it is short and not ambiguous in this context. I don't think that mentioning "imx" adds any additional useful information.
It doesn't seem like there's much of a convention for "local variable containing private data", for example
exynos-bus.cuses "struct exynos_bus* bus" internally.
OK. it is nitpick. Keep your style.
Quoted 24 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
drivers/devfreq/imx-devfreq.c line 73
Quoted 4 lines
drivers/devfreq/imx-devfreq.c new file +2
-0+const char *gov =DEVFREQ_GOV_USERSPACE ; +void *govdata =NULL ;How about changing the variable name 'govdata' to '
gov_data'?
- govdata ->gov_dataOK
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
drivers/devfreq/imx-devfreq.c line 80
Quoted 7 lines
drivers/devfreq/imx-devfreq.c new file +7
-0+int ret; + + priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + priv->clk =devm_clk_get (dev,NULL );nitpick: because the clock-name is not mandatory. Don't need to specify the clock name to inform the role of clock of other developer/user?
Quoted 1 line
Quoted 1 line
Quoted 1 line
For example, "ddr", "bus" and so on.
Quoted 8 lines
I'll call this bus, but I'm not sure it's useful when a single clock is involved.
Quoted 2 lines
Quoted 2 lines
And, this driver doesn't include the '
clk_prepare_enable'. how to enable the clock?Clocks are either always on or perhaps controlled by some other peripheral. This driver only provides scaling.
It is not proper use-case of clock. If device driver want to control the clock, it have to be enabled on device driver.
Even it clock is always, the user don't know the state of clock. Also, user can't know what kind of device driver control the clock.
It have to be controlled on this device driver
before changing the clock frequency.
Quoted 48 lines
Quoted 39 lines
Quoted 39 lines
Quoted 39 lines
Quoted 26 lines
drivers/devfreq/imx-devfreq.c new file +25
-0+if (IS_ERR (priv->clk)) { + ret =PTR_ERR (priv->clk); +dev_err (dev,"failed to fetch clk: %d\n" , ret); +return ret; + } +platform_set_drvdata (pdev, priv); + + ret =dev_pm_opp_of_add_table (dev); +if (ret <0 ) { +dev_err (dev,"failed to get OPP table\n" ); +return ret; + } + + priv->profile.polling_ms =1000 ; + priv->profile.target = imx_devfreq_target; + priv->profile.get_dev_status = imx_devfreq_get_dev_status; + priv->profile.exit = imx_devfreq_exit; + priv->profile.get_cur_freq = imx_devfreq_get_cur_freq; + priv->profile.initial_freq =clk_get_rate (priv->clk); + +/* Handle passive devfreq parent link */ + priv->passive_data.parent =devfreq_get_devfreq_by_phandle (dev,0 ); +if (!IS_ERR (priv->passive_data.parent)) { +dev_info (dev,"setup passive link to %s\n" , +dev_name (priv->passive_data.parent->dev.parent));drivers/devfreq/imx-devfreq.c line 115
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ gov =DEVFREQ_GOV_PASSIVE ; + govdata = &priv->passive_data; + }else if (priv->passive_data.parent !=ERR_PTR (-ENODEV )) { +// -ENODEV means no parent: not an error. + ret =PTR_ERR (priv->passive_data.parent); +if (ret != -EPROBE_DEFER ) +dev_warn (dev,"failed to get initialize passive parent: %d\n" , + ret); + goto err; + }You better to change the exception handling as following: It is more simple.
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
} else if (PTR_ERR(priv->passive_data.parent) == -EPROBE_DEFER) || PTR_ERR(priv->passive_data.parent) == -ENODEV) { goto err; } else { ret = PTR_ERR(priv->passive_data.parent); dev_err(dev, "failed to get initialize passive parent: %d\n", ret); goto err; }
Quoted 1 line
But
-ENODEVis not an error, it means no passive parent was found.
OK. just I want to make 'if statement' more simple. This style is complicated.
Quoted 40 lines
Quoted 28 lines
Quoted 28 lines
Quoted 28 lines
Quoted 28 lines
drivers/devfreq/imx-devfreq.c new file +27
-0+ priv->devfreq =devm_devfreq_add_device (dev, &priv->profile, + gov, govdata); +if (IS_ERR (priv->devfreq)) { + ret =PTR_ERR (priv->devfreq); +dev_err (dev,"failed to add devfreq device: %d\n" , ret); + goto err; + } + +return 0 ; + +err: +dev_pm_opp_of_remove_table (dev); +return ret; +} + +static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8m-noc" , }, + { .compatible ="fsl,imx8m-nic" , }, + {/* sentinel */ }, +}; +MODULE_DEVICE_TABLE (of, imx_devfreq_of_match); + +static struct platform_driver imx_devfreq_platdrv = { + .probe = imx_devfreq_probe, + .driver = { + .name ="imx-devfreq" , + .of_match_table =of_match_ptr (imx_devfreq_of_match),Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/devfreq/imx-devfreq.c line 148
Quoted 5 lines
drivers/devfreq/imx-devfreq.c new file +5
-0+ }, +}; +module_platform_driver (imx_devfreq_platdrv); + +MODULE_DESCRIPTION ("Generic i.MX bus frequency driver" );If this driver is for bus frequency, you better to use 'bus' for the clock-name for the readability.
OK
Signature · 3 lines
Best Regards, Chanwoo Choi Samsung Electronics
Re: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
Quoted 25 lines · Chanwoo Choi
Quoted 8 lines · Leonard Crestez
Quoted 4 lines · Chanwoo Choi
Hi,
Also, I think that 'devfreq' word is not proper for device driver name.
imx-bus.corimx-noc.cor others to inform the role of this driver of developer.I'll rename to "imx-bus". Calling it "imx-noc" is not appropriate because I also want to use it for PL301 NICs.
OK.
Quoted 13 lines
Quoted 8 lines
And, I have a question.
This driver adds the devfreq device with either passive governor or userspace governor.As I understood, the devfreq device with passive governor will be operated with
imx8m-ddrc.cdriver.
But, when is operating with userspace governor?There are multiple scalable buses inside the SOC, for example there's a NIC for display controllers and one for (pci+usb). They can use userspace governor for explicit frequency control.
Quoted 101 lines
Quoted 5 lines
Quoted 3 lines
I think that you better to add the explanation to description for two scenarios how to operate with interconnect provider on either passive governor or userspace governor usage case.
I'll elaborate the example in bindings.
OK.
Quoted 93 lines
Quoted 83 lines · Chanwoo Choi
Quoted 81 lines · Chanwoo Choi
Quoted 80 lines
Hi,
Quoted 77 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-devfreq.c | 150 ++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+)create mode 100644
drivers/devfreq/imx-devfreq.cdrivers/devfreq/Kconfig +9
-0@@ -98,10 +98,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_DEVFREQ + tristate "i.MX Generic 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@@ -8,10 +8,11 @@ obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o # DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o +obj-$(CONFIG_ARM_IMX_DEVFREQ) += imx-devfreq.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o # DEVFREQ Event Driversdrivers/devfreq/imx-devfreq.c new file +17
-0@@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright 2019 NXP +*/ + +#include <linux/clk.h> +#include <linux/devfreq.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/pm_opp.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +struct imx_devfreq { +struct devfreq_dev_profile profile; +struct devfreq *devfreq;Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/devfreq/imx-devfreq.c line 23
Quoted 6 lines
drivers/devfreq/imx-devfreq.c new file +6
-0+struct clk *clk; +struct devfreq_passive_data passive_data; +}; + +static int imx_devfreq_target (struct device *dev, +unsigned long *freq,u32 flags)Don't use space for the indentation. Please use only tab.
OK
The spaces are required in order to align arguments to open paranthesis. Should I drop that?
It seems that check_patch.pl and process/coding-style.rst doesn't have a strong opinion on this; my personal preference is for long argument lists to just use double indentation.
Quoted 98 lines
Quoted 55 lines
Quoted 46 lines
Quoted 46 lines
Quoted 46 lines
Quoted 19 lines
drivers/devfreq/imx-devfreq.c new file +19
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); +struct dev_pm_opp *new_opp; +unsigned long new_freq; +int ret; + + new_opp =devfreq_recommended_opp (dev, freq, flags); +if (IS_ERR (new_opp)) { + ret =PTR_ERR (new_opp); +dev_err (dev,"failed to get recommended opp: %d\n" , ret); +return ret; + } + new_freq =dev_pm_opp_get_freq (new_opp); +dev_pm_opp_put (new_opp); + +return clk_set_rate (priv->clk, new_freq); +} + +static int imx_devfreq_get_cur_freq (struct device *dev,unsigned long *freq)drivers/devfreq/imx-devfreq.c line 52
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + *freq =clk_get_rate (priv->clk); + +return 0 ; +} + +static int imx_devfreq_get_dev_status (struct device *dev, +struct devfreq_dev_status *stat)ditto. Please use tab for the indentation.
Quoted 14 lines
drivers/devfreq/imx-devfreq.c new file +14
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + stat->busy_time =0 ; + stat->total_time =0 ; + stat->current_frequency =clk_get_rate (priv->clk); + +return 0 ; +} + +static void imx_devfreq_exit (struct device *dev) +{ +dev_pm_opp_of_remove_table (dev); +}Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/devfreq/imx-devfreq.c line 71
Quoted 5 lines
drivers/devfreq/imx-devfreq.c new file +5
-0+ +static int imx_devfreq_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct imx_devfreq *priv;How about changing the variable name 'priv' to 'imx' or '
imx_data'? because it is not easy to catch the role of 'priv' from variable name.Quoted 7 lines
The name "priv" refers to private data of current device: it is short and not ambiguous in this context. I don't think that mentioning "imx" adds any additional useful information.
It doesn't seem like there's much of a convention for "local variable containing private data", for example
exynos-bus.cuses "struct exynos_bus* bus" internally.OK. it is nitpick. Keep your style.
Quoted 24 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
drivers/devfreq/imx-devfreq.c line 73
Quoted 4 lines
drivers/devfreq/imx-devfreq.c new file +2
-0+const char *gov =DEVFREQ_GOV_USERSPACE ; +void *govdata =NULL ;How about changing the variable name 'govdata' to '
gov_data'?
- govdata ->gov_dataOK
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
drivers/devfreq/imx-devfreq.c line 80
Quoted 7 lines
drivers/devfreq/imx-devfreq.c new file +7
-0+int ret; + + priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + priv->clk =devm_clk_get (dev,NULL );nitpick: because the clock-name is not mandatory. Don't need to specify the clock name to inform the role of clock of other developer/user?
Quoted 1 line
Quoted 1 line
Quoted 1 line
For example, "ddr", "bus" and so on.
Quoted 8 lines
I'll call this bus, but I'm not sure it's useful when a single clock is involved.
Quoted 2 lines
Quoted 2 lines
And, this driver doesn't include the '
clk_prepare_enable'. how to enable the clock?Clocks are either always on or perhaps controlled by some other peripheral. This driver only provides scaling.
Quoted 8 lines
It is not proper use-case of clock. If device driver want to control the clock, it have to be enabled on device driver.
Even it clock is always, the user don't know the state of clock. Also, user can't know what kind of device driver control the clock.
It have to be controlled on this device driver
before changing the clock frequency.
From clock framework perspective prepare/enable and rate bits can be
controlled separately.
Many peripherals are grouped with their own bus (for example a PL301 NIC) which is normally off and only gets enabled when explicitly requested by drivers. If this devfreq driver always enabled bus clocks then it would waste power for no reason.
For example a display controller will first enable clocks to allow access to device registers, then configure a resolution and make a bandwith request which gets translated a min_freq request. Then when the display is blanked the entire display bus should be powered off, even if this makes control registers inaccessible.
This series only enables scaling for the main NOC which can't be turned off anyway.
Quoted 47 lines
Quoted 47 lines
Quoted 46 lines
Quoted 46 lines
Quoted 46 lines
Quoted 25 lines
drivers/devfreq/imx-devfreq.c new file +25
-0+if (IS_ERR (priv->clk)) { + ret =PTR_ERR (priv->clk); +dev_err (dev,"failed to fetch clk: %d\n" , ret); +return ret; + } +platform_set_drvdata (pdev, priv); + + ret =dev_pm_opp_of_add_table (dev); +if (ret <0 ) { +dev_err (dev,"failed to get OPP table\n" ); +return ret; + } + + priv->profile.polling_ms =1000 ; + priv->profile.target = imx_devfreq_target; + priv->profile.get_dev_status = imx_devfreq_get_dev_status; + priv->profile.exit = imx_devfreq_exit; + priv->profile.get_cur_freq = imx_devfreq_get_cur_freq; + priv->profile.initial_freq =clk_get_rate (priv->clk); + +/* Handle passive devfreq parent link */ + priv->passive_data.parent =devfreq_get_devfreq_by_phandle (dev,0 ); +if (!IS_ERR (priv->passive_data.parent)) { +dev_info (dev,"setup passive link to %s\n" , +dev_name (priv->passive_data.parent->dev.parent));drivers/devfreq/imx-devfreq.c line 115
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ gov =DEVFREQ_GOV_PASSIVE ; + govdata = &priv->passive_data; + }else if (priv->passive_data.parent !=ERR_PTR (-ENODEV )) { +// -ENODEV means no parent: not an error. + ret =PTR_ERR (priv->passive_data.parent); +if (ret != -EPROBE_DEFER ) +dev_warn (dev,"failed to get initialize passive parent: %d\n" , + ret); + goto err; + }You better to change the exception handling as following: It is more simple.
} else if (PTR_ERR(priv->passive_data.parent) == -EPROBE_DEFER) || PTR_ERR(priv->passive_data.parent) == -ENODEV) { goto err; } else { ret = PTR_ERR(priv->passive_data.parent); dev_err(dev, "failed to get initialize passive parent: %d\n", ret); goto err; }
Quoted 4 lines
Quoted 1 line
But
-ENODEVis not an error, it means no passive parent was found.OK. just I want to make 'if statement' more simple. This style is complicated.
I can avoid handling EPROBE_DEFER in a nested if.
Quoted 35 lines
Quoted 35 lines
Quoted 35 lines
Quoted 35 lines
Quoted 35 lines
Quoted 22 lines
drivers/devfreq/imx-devfreq.c new file +22
-0+ priv->devfreq =devm_devfreq_add_device (dev, &priv->profile, + gov, govdata); +if (IS_ERR (priv->devfreq)) { + ret =PTR_ERR (priv->devfreq); +dev_err (dev,"failed to add devfreq device: %d\n" , ret); + goto err; + } + +return 0 ; + +err: +dev_pm_opp_of_remove_table (dev); +return ret; +} + +static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8m-noc" , }, + { .compatible ="fsl,imx8m-nic" , }, + {/* sentinel */ }, +}; +MODULE_DEVICE_TABLE (of, imx_devfreq_of_match); +drivers/devfreq/imx-devfreq.c line 148
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+static struct platform_driver imx_devfreq_platdrv = { + .probe = imx_devfreq_probe, + .driver = { + .name ="imx-devfreq" , + .of_match_table =of_match_ptr (imx_devfreq_of_match), + }, +}; +module_platform_driver (imx_devfreq_platdrv); + +MODULE_DESCRIPTION ("Generic i.MX bus frequency driver" );If this driver is for bus frequency, you better to use 'bus' for the clock-name for the readability.
Chanwoo Choi
maintainerRe: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
Quoted 126 lines · Leonard Crestez
Quoted 125 lines · Chanwoo Choi
Quoted 8 lines · Leonard Crestez
Quoted 4 lines · Chanwoo Choi
Hi,
Also, I think that 'devfreq' word is not proper for device driver name.
imx-bus.corimx-noc.cor others to inform the role of this driver of developer.I'll rename to "imx-bus". Calling it "imx-noc" is not appropriate because I also want to use it for PL301 NICs.
OK.
Quoted 13 lines
Quoted 8 lines
And, I have a question.
This driver adds the devfreq device with either passive governor or userspace governor.As I understood, the devfreq device with passive governor will be operated with
imx8m-ddrc.cdriver.
But, when is operating with userspace governor?There are multiple scalable buses inside the SOC, for example there's a NIC for display controllers and one for (pci+usb). They can use userspace governor for explicit frequency control.
Quoted 5 lines
Quoted 3 lines
I think that you better to add the explanation to description for two scenarios how to operate with interconnect provider on either passive governor or userspace governor usage case.
I'll elaborate the example in bindings.
OK.
Quoted 92 lines
Quoted 91 lines · Chanwoo Choi
Quoted 89 lines · Chanwoo Choi
Quoted 88 lines
Hi,
Quoted 73 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-devfreq.c | 150 ++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+)create mode 100644
drivers/devfreq/imx-devfreq.cdrivers/devfreq/Kconfig +9
-0@@ -98,10 +98,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_DEVFREQ + tristate "i.MX Generic 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@@ -8,10 +8,11 @@ obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o # DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o +obj-$(CONFIG_ARM_IMX_DEVFREQ) += imx-devfreq.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o # DEVFREQ Event Driversdrivers/devfreq/imx-devfreq.c new file +13
-0@@ -0,0 +1,150 @@ +// 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> drivers/devfreq/imx-devfreq.c line 23
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ +struct imx_devfreq { +struct devfreq_dev_profile profile; +struct devfreq *devfreq; +struct clk *clk; +struct devfreq_passive_data passive_data; +}; + +static int imx_devfreq_target (struct device *dev, +unsigned long *freq,u32 flags)Don't use space for the indentation. Please use only tab.
Quoted 8 lines
Quoted 1 line
Quoted 1 line
OK
The spaces are required in order to align arguments to open paranthesis. Should I drop that?
It seems that check_patch.pl and
process/coding-style.rstdoesn't have a strong opinion on this; my personal preference is for long argument lists to just use double indentation.
Generally, almost patches use the tab for the indentation. I don't use space for the indentation. If use the tab for the indentation, it is not harmful for the readability.
If use the space for the pretty to make the alignment between parameter, I think it it not good.
Quoted 108 lines
Quoted 99 lines
Quoted 56 lines
Quoted 47 lines
Quoted 47 lines
Quoted 47 lines
Quoted 20 lines
drivers/devfreq/imx-devfreq.c new file +19
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); +struct dev_pm_opp *new_opp; +unsigned long new_freq; +int ret; + + new_opp =devfreq_recommended_opp (dev, freq, flags); +if (IS_ERR (new_opp)) { + ret =PTR_ERR (new_opp); +dev_err (dev,"failed to get recommended opp: %d\n" , ret); +return ret; + } + new_freq =dev_pm_opp_get_freq (new_opp); +dev_pm_opp_put (new_opp); + +return clk_set_rate (priv->clk, new_freq); +} + +static int imx_devfreq_get_cur_freq (struct device *dev,unsigned long *freq)drivers/devfreq/imx-devfreq.c line 52
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + *freq =clk_get_rate (priv->clk); + +return 0 ; +} + +static int imx_devfreq_get_dev_status (struct device *dev, +struct devfreq_dev_status *stat)ditto. Please use tab for the indentation.
Quoted 14 lines
drivers/devfreq/imx-devfreq.c new file +14
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + stat->busy_time =0 ; + stat->total_time =0 ; + stat->current_frequency =clk_get_rate (priv->clk); + +return 0 ; +} + +static void imx_devfreq_exit (struct device *dev) +{ +dev_pm_opp_of_remove_table (dev); +}Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/devfreq/imx-devfreq.c line 71
Quoted 5 lines
drivers/devfreq/imx-devfreq.c new file +5
-0+ +static int imx_devfreq_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct imx_devfreq *priv;How about changing the variable name 'priv' to 'imx' or '
imx_data'? because it is not easy to catch the role of 'priv' from variable name.Quoted 7 lines
The name "priv" refers to private data of current device: it is short and not ambiguous in this context. I don't think that mentioning "imx" adds any additional useful information.
It doesn't seem like there's much of a convention for "local variable containing private data", for example
exynos-bus.cuses "struct exynos_bus* bus" internally.OK. it is nitpick. Keep your style.
Quoted 24 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
drivers/devfreq/imx-devfreq.c line 73
Quoted 4 lines
drivers/devfreq/imx-devfreq.c new file +2
-0+const char *gov =DEVFREQ_GOV_USERSPACE ; +void *govdata =NULL ;How about changing the variable name 'govdata' to '
gov_data'?
- govdata ->gov_dataOK
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
drivers/devfreq/imx-devfreq.c line 80
Quoted 7 lines
drivers/devfreq/imx-devfreq.c new file +7
-0+int ret; + + priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + priv->clk =devm_clk_get (dev,NULL );nitpick: because the clock-name is not mandatory. Don't need to specify the clock name to inform the role of clock of other developer/user?
Quoted 1 line
Quoted 1 line
Quoted 1 line
For example, "ddr", "bus" and so on.
Quoted 8 lines
I'll call this bus, but I'm not sure it's useful when a single clock is involved.
Quoted 2 lines
Quoted 2 lines
And, this driver doesn't include the '
clk_prepare_enable'. how to enable the clock?Clocks are either always on or perhaps controlled by some other peripheral. This driver only provides scaling.
Quoted 8 lines
It is not proper use-case of clock. If device driver want to control the clock, it have to be enabled on device driver.
Even it clock is always, the user don't know the state of clock. Also, user can't know what kind of device driver control the clock.
It have to be controlled on this device driver
before changing the clock frequency.
Quoted 7 lines
From clock framework perspective prepare/enable and rate bits can be
controlled separately.Many peripherals are grouped with their own bus (for example a PL301 NIC) which is normally off and only gets enabled when explicitly requested by drivers. If this devfreq driver always enabled bus clocks then it would waste power for no reason.
You can save the power with following sequence. You are keeping the following sequence without any problem.
clk_prepare_enable() clk_set_rate() clk_disable_unprepare()
clk API support the reference count for the clock user.
It doesn't affect the any behavior of other device sharing the bus clock and waste any power-consumption because it will always restore the reference count after changing the clock rate.
Quoted 57 lines
For example a display controller will first enable clocks to allow access to device registers, then configure a resolution and make a bandwith request which gets translated a
min_freqrequest. Then when the display is blanked the entire display bus should be powered off, even if this makes control registers inaccessible.This series only enables scaling for the main NOC which can't be turned off anyway.
Quoted 47 lines
Quoted 47 lines
Quoted 46 lines
Quoted 46 lines
Quoted 46 lines
Quoted 25 lines
drivers/devfreq/imx-devfreq.c new file +25
-0+if (IS_ERR (priv->clk)) { + ret =PTR_ERR (priv->clk); +dev_err (dev,"failed to fetch clk: %d\n" , ret); +return ret; + } +platform_set_drvdata (pdev, priv); + + ret =dev_pm_opp_of_add_table (dev); +if (ret <0 ) { +dev_err (dev,"failed to get OPP table\n" ); +return ret; + } + + priv->profile.polling_ms =1000 ; + priv->profile.target = imx_devfreq_target; + priv->profile.get_dev_status = imx_devfreq_get_dev_status; + priv->profile.exit = imx_devfreq_exit; + priv->profile.get_cur_freq = imx_devfreq_get_cur_freq; + priv->profile.initial_freq =clk_get_rate (priv->clk); + +/* Handle passive devfreq parent link */ + priv->passive_data.parent =devfreq_get_devfreq_by_phandle (dev,0 ); +if (!IS_ERR (priv->passive_data.parent)) { +dev_info (dev,"setup passive link to %s\n" , +dev_name (priv->passive_data.parent->dev.parent));drivers/devfreq/imx-devfreq.c line 115
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ gov =DEVFREQ_GOV_PASSIVE ; + govdata = &priv->passive_data; + }else if (priv->passive_data.parent !=ERR_PTR (-ENODEV )) { +// -ENODEV means no parent: not an error. + ret =PTR_ERR (priv->passive_data.parent); +if (ret != -EPROBE_DEFER ) +dev_warn (dev,"failed to get initialize passive parent: %d\n" , + ret); + goto err; + }You better to change the exception handling as following: It is more simple.
} else if (PTR_ERR(priv->passive_data.parent) == -EPROBE_DEFER) || PTR_ERR(priv->passive_data.parent) == -ENODEV) { goto err; } else { ret = PTR_ERR(priv->passive_data.parent); dev_err(dev, "failed to get initialize passive parent: %d\n", ret); goto err; }
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
But
-ENODEVis not an error, it means no passive parent was found.OK. just I want to make 'if statement' more simple. This style is complicated.
I can avoid handling
EPROBE_DEFERin a nested if.
Anyway, if you make the exception more simple, I'm ok.
Quoted 40 lines
Quoted 36 lines
Quoted 36 lines
Quoted 36 lines
Quoted 36 lines
Quoted 36 lines
Quoted 23 lines
drivers/devfreq/imx-devfreq.c new file +22
-0+ priv->devfreq =devm_devfreq_add_device (dev, &priv->profile, + gov, govdata); +if (IS_ERR (priv->devfreq)) { + ret =PTR_ERR (priv->devfreq); +dev_err (dev,"failed to add devfreq device: %d\n" , ret); + goto err; + } + +return 0 ; + +err: +dev_pm_opp_of_remove_table (dev); +return ret; +} + +static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8m-noc" , }, + { .compatible ="fsl,imx8m-nic" , }, + {/* sentinel */ }, +}; +MODULE_DEVICE_TABLE (of, imx_devfreq_of_match); +drivers/devfreq/imx-devfreq.c line 147
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+static struct platform_driver imx_devfreq_platdrv = { + .probe = imx_devfreq_probe, + .driver = { + .name ="imx-devfreq" , + .of_match_table =of_match_ptr (imx_devfreq_of_match), + }, +}; +module_platform_driver (imx_devfreq_platdrv); + +MODULE_DESCRIPTION ("Generic i.MX bus frequency driver" );If this driver is for bus frequency, you better to use 'bus' for the clock-name for the readability.
Signature · 3 lines
Best Regards, Chanwoo Choi Samsung Electronics
Re: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
Quoted 136 lines · Chanwoo Choi
Quoted 126 lines · Leonard Crestez
Quoted 125 lines · Chanwoo Choi
Quoted 8 lines · Leonard Crestez
Quoted 4 lines · Chanwoo Choi
Hi,
Also, I think that 'devfreq' word is not proper for device driver name.
imx-bus.corimx-noc.cor others to inform the role of this driver of developer.I'll rename to "imx-bus". Calling it "imx-noc" is not appropriate because I also want to use it for PL301 NICs.
OK.
Quoted 13 lines
Quoted 8 lines
And, I have a question.
This driver adds the devfreq device with either passive governor or userspace governor.As I understood, the devfreq device with passive governor will be operated with
imx8m-ddrc.cdriver.
But, when is operating with userspace governor?There are multiple scalable buses inside the SOC, for example there's a NIC for display controllers and one for (pci+usb). They can use userspace governor for explicit frequency control.
Quoted 5 lines
Quoted 3 lines
I think that you better to add the explanation to description for two scenarios how to operate with interconnect provider on either passive governor or userspace governor usage case.
I'll elaborate the example in bindings.
OK.
Quoted 92 lines
Quoted 91 lines · Chanwoo Choi
Quoted 89 lines · Chanwoo Choi
Quoted 88 lines
Hi,
Quoted 73 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-devfreq.c | 150 ++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+)create mode 100644
drivers/devfreq/imx-devfreq.cdrivers/devfreq/Kconfig +9
-0@@ -98,10 +98,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_DEVFREQ + tristate "i.MX Generic 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@@ -8,10 +8,11 @@ obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o # DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o +obj-$(CONFIG_ARM_IMX_DEVFREQ) += imx-devfreq.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o # DEVFREQ Event Driversdrivers/devfreq/imx-devfreq.c new file +13
-0@@ -0,0 +1,150 @@ +// 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> drivers/devfreq/imx-devfreq.c line 23
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ +struct imx_devfreq { +struct devfreq_dev_profile profile; +struct devfreq *devfreq; +struct clk *clk; +struct devfreq_passive_data passive_data; +}; + +static int imx_devfreq_target (struct device *dev, +unsigned long *freq,u32 flags)Don't use space for the indentation. Please use only tab.
Quoted 8 lines
Quoted 1 line
Quoted 1 line
OK
The spaces are required in order to align arguments to open paranthesis. Should I drop that?
It seems that check_patch.pl and
process/coding-style.rstdoesn't have a strong opinion on this; my personal preference is for long argument lists to just use double indentation.
Quoted 6 lines
Generally, almost patches use the tab for the indentation. I don't use space for the indentation. If use the tab for the indentation, it is not harmful for the readability.
If use the space for the pretty to make the alignment between parameter, I think it it not good.
OK, I'll just use two tabs. This also matches my personal preference.
Quoted 117 lines
Quoted 107 lines
Quoted 98 lines
Quoted 55 lines
Quoted 46 lines
Quoted 46 lines
Quoted 46 lines
Quoted 19 lines
drivers/devfreq/imx-devfreq.c new file +19
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); +struct dev_pm_opp *new_opp; +unsigned long new_freq; +int ret; + + new_opp =devfreq_recommended_opp (dev, freq, flags); +if (IS_ERR (new_opp)) { + ret =PTR_ERR (new_opp); +dev_err (dev,"failed to get recommended opp: %d\n" , ret); +return ret; + } + new_freq =dev_pm_opp_get_freq (new_opp); +dev_pm_opp_put (new_opp); + +return clk_set_rate (priv->clk, new_freq); +} + +static int imx_devfreq_get_cur_freq (struct device *dev,unsigned long *freq)drivers/devfreq/imx-devfreq.c line 52
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + *freq =clk_get_rate (priv->clk); + +return 0 ; +} + +static int imx_devfreq_get_dev_status (struct device *dev, +struct devfreq_dev_status *stat)ditto. Please use tab for the indentation.
Quoted 14 lines
drivers/devfreq/imx-devfreq.c new file +14
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + stat->busy_time =0 ; + stat->total_time =0 ; + stat->current_frequency =clk_get_rate (priv->clk); + +return 0 ; +} + +static void imx_devfreq_exit (struct device *dev) +{ +dev_pm_opp_of_remove_table (dev); +}Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/devfreq/imx-devfreq.c line 71
Quoted 5 lines
drivers/devfreq/imx-devfreq.c new file +5
-0+ +static int imx_devfreq_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct imx_devfreq *priv;How about changing the variable name 'priv' to 'imx' or '
imx_data'? because it is not easy to catch the role of 'priv' from variable name.Quoted 7 lines
The name "priv" refers to private data of current device: it is short and not ambiguous in this context. I don't think that mentioning "imx" adds any additional useful information.
It doesn't seem like there's much of a convention for "local variable containing private data", for example
exynos-bus.cuses "struct exynos_bus* bus" internally.OK. it is nitpick. Keep your style.
Quoted 24 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
drivers/devfreq/imx-devfreq.c line 73
Quoted 4 lines
drivers/devfreq/imx-devfreq.c new file +2
-0+const char *gov =DEVFREQ_GOV_USERSPACE ; +void *govdata =NULL ;How about changing the variable name 'govdata' to '
gov_data'?
- govdata ->gov_dataOK
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
drivers/devfreq/imx-devfreq.c line 80
Quoted 7 lines
drivers/devfreq/imx-devfreq.c new file +7
-0+int ret; + + priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + priv->clk =devm_clk_get (dev,NULL );nitpick: because the clock-name is not mandatory. Don't need to specify the clock name to inform the role of clock of other developer/user?
Quoted 1 line
Quoted 1 line
Quoted 1 line
For example, "ddr", "bus" and so on.
Quoted 8 lines
I'll call this bus, but I'm not sure it's useful when a single clock is involved.
Quoted 2 lines
Quoted 2 lines
And, this driver doesn't include the '
clk_prepare_enable'. how to enable the clock?Clocks are either always on or perhaps controlled by some other peripheral. This driver only provides scaling.
Quoted 8 lines
It is not proper use-case of clock. If device driver want to control the clock, it have to be enabled on device driver.
Even it clock is always, the user don't know the state of clock. Also, user can't know what kind of device driver control the clock.
It have to be controlled on this device driver
before changing the clock frequency.Quoted 7 lines
From clock framework perspective prepare/enable and rate bits can be
controlled separately.Many peripherals are grouped with their own bus (for example a PL301 NIC) which is normally off and only gets enabled when explicitly requested by drivers. If this devfreq driver always enabled bus clocks then it would waste power for no reason.
You can save the power with following sequence. You are keeping the following sequence without any problem.
Quoted 8 lines
clk_prepare_enable() clk_set_rate() clk_disable_unprepare()clk API support the reference count for the clock user.
It doesn't affect the any behavior of other device sharing the bus clock and waste any power-consumption because it will always restore the reference count after changing the clock rate.
But this doesn't serve any purpose?
In some cases (depending on clock flags like CLK_SET_RATE_GATE or CLK_SET_RATE_UNGATE flags) the clk_set_rate function can require than clocks are either on or off and otherwise return an error.
For imx bus clocks there is no such requirement.
Quoted 56 lines
Quoted 56 lines
For example a display controller will first enable clocks to allow access to device registers, then configure a resolution and make a bandwith request which gets translated a
min_freqrequest. Then when the display is blanked the entire display bus should be powered off, even if this makes control registers inaccessible.This series only enables scaling for the main NOC which can't be turned off anyway.
Quoted 47 lines
Quoted 47 lines
Quoted 46 lines
Quoted 46 lines
Quoted 46 lines
Quoted 25 lines
drivers/devfreq/imx-devfreq.c new file +25
-0+if (IS_ERR (priv->clk)) { + ret =PTR_ERR (priv->clk); +dev_err (dev,"failed to fetch clk: %d\n" , ret); +return ret; + } +platform_set_drvdata (pdev, priv); + + ret =dev_pm_opp_of_add_table (dev); +if (ret <0 ) { +dev_err (dev,"failed to get OPP table\n" ); +return ret; + } + + priv->profile.polling_ms =1000 ; + priv->profile.target = imx_devfreq_target; + priv->profile.get_dev_status = imx_devfreq_get_dev_status; + priv->profile.exit = imx_devfreq_exit; + priv->profile.get_cur_freq = imx_devfreq_get_cur_freq; + priv->profile.initial_freq =clk_get_rate (priv->clk); + +/* Handle passive devfreq parent link */ + priv->passive_data.parent =devfreq_get_devfreq_by_phandle (dev,0 ); +if (!IS_ERR (priv->passive_data.parent)) { +dev_info (dev,"setup passive link to %s\n" , +dev_name (priv->passive_data.parent->dev.parent));drivers/devfreq/imx-devfreq.c line 115
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ gov =DEVFREQ_GOV_PASSIVE ; + govdata = &priv->passive_data; + }else if (priv->passive_data.parent !=ERR_PTR (-ENODEV )) { +// -ENODEV means no parent: not an error. + ret =PTR_ERR (priv->passive_data.parent); +if (ret != -EPROBE_DEFER ) +dev_warn (dev,"failed to get initialize passive parent: %d\n" , + ret); + goto err; + }You better to change the exception handling as following: It is more simple.
} else if (PTR_ERR(priv->passive_data.parent) == -EPROBE_DEFER) || PTR_ERR(priv->passive_data.parent) == -ENODEV) { goto err; } else { ret = PTR_ERR(priv->passive_data.parent); dev_err(dev, "failed to get initialize passive parent: %d\n", ret); goto err; }
Quoted 51 lines
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
But
-ENODEVis not an error, it means no passive parent was found.OK. just I want to make 'if statement' more simple. This style is complicated.
I can avoid handling
EPROBE_DEFERin a nested if.Anyway, if you make the exception more simple, I'm ok.
Quoted 40 lines
Quoted 36 lines
Quoted 36 lines
Quoted 36 lines
Quoted 36 lines
Quoted 36 lines
Quoted 23 lines
drivers/devfreq/imx-devfreq.c new file +22
-0+ priv->devfreq =devm_devfreq_add_device (dev, &priv->profile, + gov, govdata); +if (IS_ERR (priv->devfreq)) { + ret =PTR_ERR (priv->devfreq); +dev_err (dev,"failed to add devfreq device: %d\n" , ret); + goto err; + } + +return 0 ; + +err: +dev_pm_opp_of_remove_table (dev); +return ret; +} + +static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8m-noc" , }, + { .compatible ="fsl,imx8m-nic" , }, + {/* sentinel */ }, +}; +MODULE_DEVICE_TABLE (of, imx_devfreq_of_match); +drivers/devfreq/imx-devfreq.c line 147
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+static struct platform_driver imx_devfreq_platdrv = { + .probe = imx_devfreq_probe, + .driver = { + .name ="imx-devfreq" , + .of_match_table =of_match_ptr (imx_devfreq_of_match), + }, +}; +module_platform_driver (imx_devfreq_platdrv); + +MODULE_DESCRIPTION ("Generic i.MX bus frequency driver" );If this driver is for bus frequency, you better to use 'bus' for the clock-name for the readability.
_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Re: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
Hi,
2019년 12월 18일 (수) 오후 7:11, Leonard Crestez <[email protected]>님이 작성:
Quoted 273 lines · Chanwoo Choi
Quoted 136 lines · Leonard Crestez
Quoted 126 lines · Chanwoo Choi
Quoted 125 lines · Leonard Crestez
Quoted 8 lines · Chanwoo Choi
Quoted 4 lines
Hi,
Also, I think that 'devfreq' word is not proper for device driver name.
imx-bus.corimx-noc.cor others to inform the role of this driver of developer.I'll rename to "imx-bus". Calling it "imx-noc" is not appropriate because I also want to use it for PL301 NICs.
OK.
Quoted 13 lines
Quoted 8 lines
And, I have a question.
This driver adds the devfreq device with either passive governor or userspace governor.As I understood, the devfreq device with passive governor will be operated with
imx8m-ddrc.cdriver.
But, when is operating with userspace governor?There are multiple scalable buses inside the SOC, for example there's a NIC for display controllers and one for (pci+usb). They can use userspace governor for explicit frequency control.
Quoted 5 lines
Quoted 3 lines
I think that you better to add the explanation to description for two scenarios how to operate with interconnect provider on either passive governor or userspace governor usage case.
I'll elaborate the example in bindings.
OK.
Quoted 92 lines
Quoted 91 lines · Chanwoo Choi
Quoted 89 lines · Chanwoo Choi
Quoted 88 lines
Hi,
Quoted 73 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-devfreq.c | 150 ++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+)create mode 100644
drivers/devfreq/imx-devfreq.cdrivers/devfreq/Kconfig +9
-0@@ -98,10 +98,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_DEVFREQ + tristate "i.MX Generic 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@@ -8,10 +8,11 @@ obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o # DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o +obj-$(CONFIG_ARM_IMX_DEVFREQ) += imx-devfreq.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o # DEVFREQ Event Driversdrivers/devfreq/imx-devfreq.c new file +13
-0@@ -0,0 +1,150 @@ +// 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> drivers/devfreq/imx-devfreq.c line 23
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ +struct imx_devfreq { +struct devfreq_dev_profile profile; +struct devfreq *devfreq; +struct clk *clk; +struct devfreq_passive_data passive_data; +}; + +static int imx_devfreq_target (struct device *dev, +unsigned long *freq,u32 flags)Don't use space for the indentation. Please use only tab.
Quoted 8 lines
Quoted 1 line
Quoted 1 line
OK
The spaces are required in order to align arguments to open paranthesis. Should I drop that?
It seems that check_patch.pl and
process/coding-style.rstdoesn't have a strong opinion on this; my personal preference is for long argument lists to just use double indentation.Quoted 6 lines
Generally, almost patches use the tab for the indentation. I don't use space for the indentation. If use the tab for the indentation, it is not harmful for the readability.
If use the space for the pretty to make the alignment between parameter, I think it it not good.
OK, I'll just use two tabs. This also matches my personal preference.
Quoted 117 lines
Quoted 107 lines
Quoted 98 lines
Quoted 55 lines
Quoted 46 lines
Quoted 46 lines
Quoted 46 lines
Quoted 19 lines
drivers/devfreq/imx-devfreq.c new file +19
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); +struct dev_pm_opp *new_opp; +unsigned long new_freq; +int ret; + + new_opp =devfreq_recommended_opp (dev, freq, flags); +if (IS_ERR (new_opp)) { + ret =PTR_ERR (new_opp); +dev_err (dev,"failed to get recommended opp: %d\n" , ret); +return ret; + } + new_freq =dev_pm_opp_get_freq (new_opp); +dev_pm_opp_put (new_opp); + +return clk_set_rate (priv->clk, new_freq); +} + +static int imx_devfreq_get_cur_freq (struct device *dev,unsigned long *freq)drivers/devfreq/imx-devfreq.c line 52
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + *freq =clk_get_rate (priv->clk); + +return 0 ; +} + +static int imx_devfreq_get_dev_status (struct device *dev, +struct devfreq_dev_status *stat)ditto. Please use tab for the indentation.
Quoted 14 lines
drivers/devfreq/imx-devfreq.c new file +14
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + stat->busy_time =0 ; + stat->total_time =0 ; + stat->current_frequency =clk_get_rate (priv->clk); + +return 0 ; +} + +static void imx_devfreq_exit (struct device *dev) +{ +dev_pm_opp_of_remove_table (dev); +}Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/devfreq/imx-devfreq.c line 71
Quoted 5 lines
drivers/devfreq/imx-devfreq.c new file +5
-0+ +static int imx_devfreq_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct imx_devfreq *priv;How about changing the variable name 'priv' to 'imx' or '
imx_data'? because it is not easy to catch the role of 'priv' from variable name.Quoted 7 lines
The name "priv" refers to private data of current device: it is short and not ambiguous in this context. I don't think that mentioning "imx" adds any additional useful information.
It doesn't seem like there's much of a convention for "local variable containing private data", for example
exynos-bus.cuses "struct exynos_bus* bus" internally.OK. it is nitpick. Keep your style.
Quoted 24 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
drivers/devfreq/imx-devfreq.c line 73
Quoted 4 lines
drivers/devfreq/imx-devfreq.c new file +2
-0+const char *gov =DEVFREQ_GOV_USERSPACE ; +void *govdata =NULL ;How about changing the variable name 'govdata' to '
gov_data'?
- govdata ->gov_dataOK
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
drivers/devfreq/imx-devfreq.c line 80
Quoted 7 lines
drivers/devfreq/imx-devfreq.c new file +7
-0+int ret; + + priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + priv->clk =devm_clk_get (dev,NULL );nitpick: because the clock-name is not mandatory. Don't need to specify the clock name to inform the role of clock of other developer/user?
Quoted 1 line
Quoted 1 line
Quoted 1 line
For example, "ddr", "bus" and so on.
Quoted 8 lines
I'll call this bus, but I'm not sure it's useful when a single clock is involved.
Quoted 2 lines
Quoted 2 lines
And, this driver doesn't include the '
clk_prepare_enable'. how to enable the clock?Clocks are either always on or perhaps controlled by some other peripheral. This driver only provides scaling.
Quoted 8 lines
It is not proper use-case of clock. If device driver want to control the clock, it have to be enabled on device driver.
Even it clock is always, the user don't know the state of clock. Also, user can't know what kind of device driver control the clock.
It have to be controlled on this device driver
before changing the clock frequency.Quoted 7 lines
From clock framework perspective prepare/enable and rate bits can be
controlled separately.Many peripherals are grouped with their own bus (for example a PL301 NIC) which is normally off and only gets enabled when explicitly requested by drivers. If this devfreq driver always enabled bus clocks then it would waste power for no reason.
You can save the power with following sequence. You are keeping the following sequence without any problem.
Quoted 8 lines
clk_prepare_enable() clk_set_rate() clk_disable_unprepare()clk API support the reference count for the clock user.
It doesn't affect the any behavior of other device sharing the bus clock and waste any power-consumption because it will always restore the reference count after changing the clock rate.
Quoted 7 lines
But this doesn't serve any purpose?
In some cases (depending on clock flags like
CLK_SET_RATE_GATEorCLK_SET_RATE_UNGATEflags) theclk_set_ratefunction can require than clocks are either on or off and otherwise return an error.For imx bus clocks there is no such requirement.
If you guarantee that it is not required on all board related to imx, please add this comment when calling clk_set_rate(). Because the user who don't know the history and character, don't understand why don't enable or disable for clock.
I'll agree if you add the comment why don't need to enable/disable control on this driver.
Quoted 109 lines
Quoted 108 lines
Quoted 57 lines
For example a display controller will first enable clocks to allow access to device registers, then configure a resolution and make a bandwith request which gets translated a
min_freqrequest. Then when the display is blanked the entire display bus should be powered off, even if this makes control registers inaccessible.This series only enables scaling for the main NOC which can't be turned off anyway.
Quoted 47 lines
Quoted 47 lines
Quoted 46 lines
Quoted 46 lines
Quoted 46 lines
Quoted 25 lines
drivers/devfreq/imx-devfreq.c new file +25
-0+if (IS_ERR (priv->clk)) { + ret =PTR_ERR (priv->clk); +dev_err (dev,"failed to fetch clk: %d\n" , ret); +return ret; + } +platform_set_drvdata (pdev, priv); + + ret =dev_pm_opp_of_add_table (dev); +if (ret <0 ) { +dev_err (dev,"failed to get OPP table\n" ); +return ret; + } + + priv->profile.polling_ms =1000 ; + priv->profile.target = imx_devfreq_target; + priv->profile.get_dev_status = imx_devfreq_get_dev_status; + priv->profile.exit = imx_devfreq_exit; + priv->profile.get_cur_freq = imx_devfreq_get_cur_freq; + priv->profile.initial_freq =clk_get_rate (priv->clk); + +/* Handle passive devfreq parent link */ + priv->passive_data.parent =devfreq_get_devfreq_by_phandle (dev,0 ); +if (!IS_ERR (priv->passive_data.parent)) { +dev_info (dev,"setup passive link to %s\n" , +dev_name (priv->passive_data.parent->dev.parent));drivers/devfreq/imx-devfreq.c line 115
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ gov =DEVFREQ_GOV_PASSIVE ; + govdata = &priv->passive_data; + }else if (priv->passive_data.parent !=ERR_PTR (-ENODEV )) { +// -ENODEV means no parent: not an error. + ret =PTR_ERR (priv->passive_data.parent); +if (ret != -EPROBE_DEFER ) +dev_warn (dev,"failed to get initialize passive parent: %d\n" , + ret); + goto err; + }You better to change the exception handling as following: It is more simple.
} else if (PTR_ERR(priv->passive_data.parent) == -EPROBE_DEFER) || PTR_ERR(priv->passive_data.parent) == -ENODEV) { goto err; } else { ret = PTR_ERR(priv->passive_data.parent); dev_err(dev, "failed to get initialize passive parent: %d\n", ret); goto err; }Quoted 6 lines
Quoted 4 lines
Quoted 1 line
But
-ENODEVis not an error, it means no passive parent was found.OK. just I want to make 'if statement' more simple. This style is complicated.
I can avoid handling
EPROBE_DEFERin a nested if.Anyway, if you make the exception more simple, I'm ok.
Quoted 40 lines
Quoted 36 lines
Quoted 36 lines
Quoted 36 lines
Quoted 36 lines
Quoted 36 lines
Quoted 23 lines
drivers/devfreq/imx-devfreq.c new file +22
-0+ priv->devfreq =devm_devfreq_add_device (dev, &priv->profile, + gov, govdata); +if (IS_ERR (priv->devfreq)) { + ret =PTR_ERR (priv->devfreq); +dev_err (dev,"failed to add devfreq device: %d\n" , ret); + goto err; + } + +return 0 ; + +err: +dev_pm_opp_of_remove_table (dev); +return ret; +} + +static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8m-noc" , }, + { .compatible ="fsl,imx8m-nic" , }, + {/* sentinel */ }, +}; +MODULE_DEVICE_TABLE (of, imx_devfreq_of_match); +drivers/devfreq/imx-devfreq.c line 147
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+static struct platform_driver imx_devfreq_platdrv = { + .probe = imx_devfreq_probe, + .driver = { + .name ="imx-devfreq" , + .of_match_table =of_match_ptr (imx_devfreq_of_match), + }, +}; +module_platform_driver (imx_devfreq_platdrv); + +MODULE_DESCRIPTION ("Generic i.MX bus frequency driver" );If this driver is for bus frequency, you better to use 'bus' for the clock-name for the readability.
Signature · 2 lines
Best Regards, Chanwoo Choi
Re: [PATCH RFC v6 2/9] PM / devfreq: Add generic imx bus scaling driver
2019년 12월 18일 (수) 오후 7:46, Chanwoo Choi <[email protected]>님이 작성:
Quoted 278 lines
Hi,
2019년 12월 18일 (수) 오후 7:11, Leonard Crestez <[email protected]>님이 작성:
Quoted 274 lines · Chanwoo Choi
Quoted 136 lines · Leonard Crestez
Quoted 126 lines · Chanwoo Choi
Quoted 125 lines · Leonard Crestez
Quoted 8 lines · Chanwoo Choi
Quoted 4 lines
Hi,
Also, I think that 'devfreq' word is not proper for device driver name.
imx-bus.corimx-noc.cor others to inform the role of this driver of developer.I'll rename to "imx-bus". Calling it "imx-noc" is not appropriate because I also want to use it for PL301 NICs.
OK.
Quoted 13 lines
Quoted 8 lines
And, I have a question.
This driver adds the devfreq device with either passive governor or userspace governor.As I understood, the devfreq device with passive governor will be operated with
imx8m-ddrc.cdriver.
But, when is operating with userspace governor?There are multiple scalable buses inside the SOC, for example there's a NIC for display controllers and one for (pci+usb). They can use userspace governor for explicit frequency control.
Quoted 5 lines
Quoted 3 lines
I think that you better to add the explanation to description for two scenarios how to operate with interconnect provider on either passive governor or userspace governor usage case.
I'll elaborate the example in bindings.
OK.
Quoted 92 lines
Quoted 91 lines · Chanwoo Choi
Quoted 89 lines · Chanwoo Choi
Quoted 88 lines
Hi,
Quoted 73 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-devfreq.c | 150 ++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+)create mode 100644
drivers/devfreq/imx-devfreq.cdrivers/devfreq/Kconfig +9
-0@@ -98,10 +98,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_DEVFREQ + tristate "i.MX Generic 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@@ -8,10 +8,11 @@ obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o # DEVFREQ Drivers obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o +obj-$(CONFIG_ARM_IMX_DEVFREQ) += imx-devfreq.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o # DEVFREQ Event Driversdrivers/devfreq/imx-devfreq.c new file +13
-0@@ -0,0 +1,150 @@ +// 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> drivers/devfreq/imx-devfreq.c line 23
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ +struct imx_devfreq { +struct devfreq_dev_profile profile; +struct devfreq *devfreq; +struct clk *clk; +struct devfreq_passive_data passive_data; +}; + +static int imx_devfreq_target (struct device *dev, +unsigned long *freq,u32 flags)Don't use space for the indentation. Please use only tab.
Quoted 8 lines
Quoted 1 line
Quoted 1 line
OK
The spaces are required in order to align arguments to open paranthesis. Should I drop that?
It seems that check_patch.pl and
process/coding-style.rstdoesn't have a strong opinion on this; my personal preference is for long argument lists to just use double indentation.Quoted 6 lines
Generally, almost patches use the tab for the indentation. I don't use space for the indentation. If use the tab for the indentation, it is not harmful for the readability.
If use the space for the pretty to make the alignment between parameter, I think it it not good.
OK, I'll just use two tabs. This also matches my personal preference.
Quoted 117 lines
Quoted 107 lines
Quoted 98 lines
Quoted 55 lines
Quoted 46 lines
Quoted 46 lines
Quoted 46 lines
Quoted 19 lines
drivers/devfreq/imx-devfreq.c new file +19
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); +struct dev_pm_opp *new_opp; +unsigned long new_freq; +int ret; + + new_opp =devfreq_recommended_opp (dev, freq, flags); +if (IS_ERR (new_opp)) { + ret =PTR_ERR (new_opp); +dev_err (dev,"failed to get recommended opp: %d\n" , ret); +return ret; + } + new_freq =dev_pm_opp_get_freq (new_opp); +dev_pm_opp_put (new_opp); + +return clk_set_rate (priv->clk, new_freq); +} + +static int imx_devfreq_get_cur_freq (struct device *dev,unsigned long *freq)drivers/devfreq/imx-devfreq.c line 52
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + *freq =clk_get_rate (priv->clk); + +return 0 ; +} + +static int imx_devfreq_get_dev_status (struct device *dev, +struct devfreq_dev_status *stat)ditto. Please use tab for the indentation.
Quoted 14 lines
drivers/devfreq/imx-devfreq.c new file +14
-0+{ +struct imx_devfreq *priv =dev_get_drvdata (dev); + + stat->busy_time =0 ; + stat->total_time =0 ; + stat->current_frequency =clk_get_rate (priv->clk); + +return 0 ; +} + +static void imx_devfreq_exit (struct device *dev) +{ +dev_pm_opp_of_remove_table (dev); +}Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/devfreq/imx-devfreq.c line 71
Quoted 5 lines
drivers/devfreq/imx-devfreq.c new file +5
-0+ +static int imx_devfreq_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct imx_devfreq *priv;How about changing the variable name 'priv' to 'imx' or '
imx_data'? because it is not easy to catch the role of 'priv' from variable name.Quoted 7 lines
The name "priv" refers to private data of current device: it is short and not ambiguous in this context. I don't think that mentioning "imx" adds any additional useful information.
It doesn't seem like there's much of a convention for "local variable containing private data", for example
exynos-bus.cuses "struct exynos_bus* bus" internally.OK. it is nitpick. Keep your style.
Quoted 24 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
drivers/devfreq/imx-devfreq.c line 73
Quoted 4 lines
drivers/devfreq/imx-devfreq.c new file +2
-0+const char *gov =DEVFREQ_GOV_USERSPACE ; +void *govdata =NULL ;How about changing the variable name 'govdata' to '
gov_data'?
- govdata ->gov_dataOK
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
drivers/devfreq/imx-devfreq.c line 80
Quoted 7 lines
drivers/devfreq/imx-devfreq.c new file +7
-0+int ret; + + priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + priv->clk =devm_clk_get (dev,NULL );nitpick: because the clock-name is not mandatory. Don't need to specify the clock name to inform the role of clock of other developer/user?
Quoted 1 line
Quoted 1 line
Quoted 1 line
For example, "ddr", "bus" and so on.
Quoted 8 lines
I'll call this bus, but I'm not sure it's useful when a single clock is involved.
Quoted 2 lines
Quoted 2 lines
And, this driver doesn't include the '
clk_prepare_enable'. how to enable the clock?Clocks are either always on or perhaps controlled by some other peripheral. This driver only provides scaling.
Quoted 8 lines
It is not proper use-case of clock. If device driver want to control the clock, it have to be enabled on device driver.
Even it clock is always, the user don't know the state of clock. Also, user can't know what kind of device driver control the clock.
It have to be controlled on this device driver
before changing the clock frequency.Quoted 7 lines
From clock framework perspective prepare/enable and rate bits can be
controlled separately.Many peripherals are grouped with their own bus (for example a PL301 NIC) which is normally off and only gets enabled when explicitly requested by drivers. If this devfreq driver always enabled bus clocks then it would waste power for no reason.
You can save the power with following sequence. You are keeping the following sequence without any problem.
Quoted 8 lines
clk_prepare_enable() clk_set_rate() clk_disable_unprepare()clk API support the reference count for the clock user.
It doesn't affect the any behavior of other device sharing the bus clock and waste any power-consumption because it will always restore the reference count after changing the clock rate.But this doesn't serve any purpose?
Again thinking, it show the at least sequence to control the clock. To do this sequence, it doesn't affect the behavior of any device driver which share the clock. And it show the clock is well-controlled by this device driver.
Quoted 6 lines
Quoted 6 lines
In some cases (depending on clock flags like
CLK_SET_RATE_GATEorCLK_SET_RATE_UNGATEflags) theclk_set_ratefunction can require than clocks are either on or off and otherwise return an error.For imx bus clocks there is no such requirement.
Usually, the clock is enabled before using it. It doesn't depend on the any arch or SoC.
CCF define the this rule for the clock control.
Quoted 124 lines
If you guarantee that it is not required on all board related to imx, please add this comment when calling
clk_set_rate(). Because the user who don't know the history and character, don't understand why don't enable or disable for clock.I'll agree if you add the comment why don't need to enable/disable control on this driver.
Quoted 100 lines
Quoted 100 lines
Quoted 57 lines
For example a display controller will first enable clocks to allow access to device registers, then configure a resolution and make a bandwith request which gets translated a
min_freqrequest. Then when the display is blanked the entire display bus should be powered off, even if this makes control registers inaccessible.This series only enables scaling for the main NOC which can't be turned off anyway.
Quoted 47 lines
Quoted 47 lines
Quoted 46 lines
Quoted 46 lines
Quoted 46 lines
Quoted 25 lines
drivers/devfreq/imx-devfreq.c new file +25
-0+if (IS_ERR (priv->clk)) { + ret =PTR_ERR (priv->clk); +dev_err (dev,"failed to fetch clk: %d\n" , ret); +return ret; + } +platform_set_drvdata (pdev, priv); + + ret =dev_pm_opp_of_add_table (dev); +if (ret <0 ) { +dev_err (dev,"failed to get OPP table\n" ); +return ret; + } + + priv->profile.polling_ms =1000 ; + priv->profile.target = imx_devfreq_target; + priv->profile.get_dev_status = imx_devfreq_get_dev_status; + priv->profile.exit = imx_devfreq_exit; + priv->profile.get_cur_freq = imx_devfreq_get_cur_freq; + priv->profile.initial_freq =clk_get_rate (priv->clk); + +/* Handle passive devfreq parent link */ + priv->passive_data.parent =devfreq_get_devfreq_by_phandle (dev,0 ); +if (!IS_ERR (priv->passive_data.parent)) { +dev_info (dev,"setup passive link to %s\n" , +dev_name (priv->passive_data.parent->dev.parent));drivers/devfreq/imx-devfreq.c line 115
Quoted 10 lines
drivers/devfreq/imx-devfreq.c new file +10
-0+ gov =DEVFREQ_GOV_PASSIVE ; + govdata = &priv->passive_data; + }else if (priv->passive_data.parent !=ERR_PTR (-ENODEV )) { +// -ENODEV means no parent: not an error. + ret =PTR_ERR (priv->passive_data.parent); +if (ret != -EPROBE_DEFER ) +dev_warn (dev,"failed to get initialize passive parent: %d\n" , + ret); + goto err; + }You better to change the exception handling as following: It is more simple.
} else if (PTR_ERR(priv->passive_data.parent) == -EPROBE_DEFER) || PTR_ERR(priv->passive_data.parent) == -ENODEV) { goto err; } else { ret = PTR_ERR(priv->passive_data.parent); dev_err(dev, "failed to get initialize passive parent: %d\n", ret); goto err; }Quoted 6 lines
Quoted 4 lines
Quoted 1 line
But
-ENODEVis not an error, it means no passive parent was found.OK. just I want to make 'if statement' more simple. This style is complicated.
I can avoid handling
EPROBE_DEFERin a nested if.Anyway, if you make the exception more simple, I'm ok.
Quoted 34 lines
Quoted 34 lines
Quoted 34 lines
Quoted 34 lines
Quoted 34 lines
Quoted 34 lines
Quoted 33 lines
drivers/devfreq/imx-devfreq.c new file +32
-0+ priv->devfreq =devm_devfreq_add_device (dev, &priv->profile, + gov, govdata); +if (IS_ERR (priv->devfreq)) { + ret =PTR_ERR (priv->devfreq); +dev_err (dev,"failed to add devfreq device: %d\n" , ret); + goto err; + } + +return 0 ; + +err: +dev_pm_opp_of_remove_table (dev); +return ret; +} + +static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8m-noc" , }, + { .compatible ="fsl,imx8m-nic" , }, + {/* sentinel */ }, +}; +MODULE_DEVICE_TABLE (of, imx_devfreq_of_match); + +static struct platform_driver imx_devfreq_platdrv = { + .probe = imx_devfreq_probe, + .driver = { + .name ="imx-devfreq" , + .of_match_table =of_match_ptr (imx_devfreq_of_match), + }, +}; +module_platform_driver (imx_devfreq_platdrv); + +MODULE_DESCRIPTION ("Generic i.MX bus frequency driver" );Quoted 9 lines
Quoted 8 lines
Quoted 6 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
If this driver is for bus frequency, you better to use 'bus' for the clock-name for the readability.
--
Best Regards,
Chanwoo Choi
Signature · 2 lines
Best Regards, Chanwoo Choi
RFC PATCH v6 3/9 PM / devfreq: imx: Register interconnect device
In reply to Leonard CrestezThere is no single device which can represent the imx interconnect. Instead of adding a virtual one just make the main &noc act as the global interconnect provider.
The imx interconnect provider driver will scale the NOC and DDRC based on bandwidth request. More scalable nodes can be added in the future, for example for audio/display/vpu/gpu NICs.
--- drivers/devfreq/imx-devfreq.c | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)
drivers/devfreq/imx-devfreq.c +37 -0
@@ -15,10 +15,11 @@struct imx_devfreq {struct devfreq_dev_profile profile;struct devfreq *devfreq;struct clk *clk;struct devfreq_passive_data passive_data; +struct platform_device *icc_pdev; };static int imx_devfreq_target (struct device *dev,unsigned long *freq,u32 flags) {
@@ -60,11 +61,40 @@ static int imx_devfreq_get_dev_status(struct device *dev,return 0 ; }static void imx_devfreq_exit (struct device *dev) { +struct imx_devfreq *priv =dev_get_drvdata (dev); +dev_pm_opp_of_remove_table (dev); +platform_device_unregister (priv->icc_pdev); +} + +/* imx_devfreq_init_icc() - register matching icc provider if required */ +static int imx_devfreq_init_icc (struct device *dev) +{ +struct imx_devfreq *priv =dev_get_drvdata (dev); +const char *icc_driver_name; + +if (!IS_ENABLED (CONFIG_INTERCONNECT_IMX )) +return 0 ; +if (!of_get_property (dev->of_node,"#interconnect-cells" ,0 )) +return 0 ; + + icc_driver_name =of_device_get_match_data (dev); +if (!icc_driver_name) +return 0 ; + + priv->icc_pdev =platform_device_register_data ( + dev, icc_driver_name,0 ,NULL ,0 ); +if (IS_ERR (priv->icc_pdev)) { +dev_err (dev,"failed to register icc provider %s: %ld\n" , + icc_driver_name,PTR_ERR (priv->devfreq)); +return PTR_ERR (priv->devfreq); + } + +return 0 ; }static int imx_devfreq_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;
@@ -120,18 +150,25 @@ static int imx_devfreq_probe(struct platform_device *pdev) ret =PTR_ERR (priv->devfreq);dev_err (dev,"failed to add devfreq device: %d\n" , ret); goto err; } + ret =imx_devfreq_init_icc (dev); +if (ret) + goto err; +return 0 ; err:dev_pm_opp_of_remove_table (dev);return ret; }static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8mq-noc" , .data ="imx8mq-interconnect" , }, + { .compatible ="fsl,imx8mm-noc" , .data ="imx8mm-interconnect" , }, + { .compatible ="fsl,imx8mn-noc" , .data ="imx8mn-interconnect" , }, { .compatible ="fsl,imx8m-noc" , }, { .compatible ="fsl,imx8m-nic" , }, {/* sentinel */ }, };MODULE_DEVICE_TABLE (of, imx_devfreq_of_match);
Signature · 1 line
2.17.1
Chanwoo Choi
maintainerRe: [PATCH RFC v6 3/9] PM / devfreq: imx: Register interconnect device
Hi,
Quoted 39 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-devfreq.c | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)drivers/devfreq/imx-devfreq.c +4
-0@@ -15,10 +15,11 @@struct imx_devfreq {struct devfreq_dev_profile profile;struct devfreq *devfreq;struct clk *clk;struct devfreq_passive_data passive_data; +struct platform_device *icc_pdev; };static int imx_devfreq_target (struct device *dev,unsigned long *freq,u32 flags) {@@ -60,11 +61,40 @@ static int imx_devfreq_get_dev_status(struct device *dev,return 0 ; }static void imx_devfreq_exit (struct device *dev) { +struct imx_devfreq *priv =dev_get_drvdata (dev); +dev_pm_opp_of_remove_table (dev); +platform_device_unregister (priv->icc_pdev);
drivers/devfreq/imx-devfreq.c static int imx_devfreq_get_dev_status(struct device *dev, · line 79
Quoted 10 lines
drivers/devfreq/imx-devfreq.c +10
-0+} + +/* imx_devfreq_init_icc() - register matching icc provider if required */ +static int imx_devfreq_init_icc (struct device *dev) +{ +struct imx_devfreq *priv =dev_get_drvdata (dev); +const char *icc_driver_name; + +if (!IS_ENABLED (CONFIG_INTERCONNECT_IMX )) +return 0 ;
It is not proper to check the enable state of CONFIG_INTERCONNECT_IMX configuration on device driver. Why don't you add the 'select CONFIG_INTERCONNECT_IMX' on Kconfig?
Quoted 48 lines
drivers/devfreq/imx-devfreq.c +23
-0+if (!of_get_property (dev->of_node,"#interconnect-cells" ,0 )) +return 0 ; + + icc_driver_name =of_device_get_match_data (dev); +if (!icc_driver_name) +return 0 ; + + priv->icc_pdev =platform_device_register_data ( + dev, icc_driver_name,0 ,NULL ,0 ); +if (IS_ERR (priv->icc_pdev)) { +dev_err (dev,"failed to register icc provider %s: %ld\n" , + icc_driver_name,PTR_ERR (priv->devfreq)); +return PTR_ERR (priv->devfreq); + } + +return 0 ; }static int imx_devfreq_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;@@ -120,18 +150,25 @@ static int imx_devfreq_probe(struct platform_device *pdev) ret =PTR_ERR (priv->devfreq);dev_err (dev,"failed to add devfreq device: %d\n" , ret); goto err; } + ret =imx_devfreq_init_icc (dev); +if (ret) + goto err; +return 0 ; err:dev_pm_opp_of_remove_table (dev);return ret; }static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8mq-noc" , .data ="imx8mq-interconnect" , }, + { .compatible ="fsl,imx8mm-noc" , .data ="imx8mm-interconnect" , }, + { .compatible ="fsl,imx8mn-noc" , .data ="imx8mn-interconnect" , }, { .compatible ="fsl,imx8m-noc" , }, { .compatible ="fsl,imx8m-nic" , }, {/* sentinel */ }, };MODULE_DEVICE_TABLE (of, imx_devfreq_of_match);
Signature · 3 lines
Best Regards, Chanwoo Choi Samsung Electronics
Re: [PATCH RFC v6 3/9] PM / devfreq: imx: Register interconnect device
Quoted 47 lines · Chanwoo Choi
Hi,
Quoted 44 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-devfreq.c | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)drivers/devfreq/imx-devfreq.c +9
-0@@ -15,10 +15,11 @@struct imx_devfreq {struct devfreq_dev_profile profile;struct devfreq *devfreq;struct clk *clk;struct devfreq_passive_data passive_data; +struct platform_device *icc_pdev; };static int imx_devfreq_target (struct device *dev,unsigned long *freq,u32 flags) {@@ -60,11 +61,40 @@ static int imx_devfreq_get_dev_status(struct device *dev,return 0 ; }static void imx_devfreq_exit (struct device *dev) { +struct imx_devfreq *priv =dev_get_drvdata (dev); +dev_pm_opp_of_remove_table (dev); +platform_device_unregister (priv->icc_pdev); +} + +/* imx_devfreq_init_icc() - register matching icc provider if required */ +static int imx_devfreq_init_icc (struct device *dev) +{
Quoted 8 lines
drivers/devfreq/imx-devfreq.c static int imx_devfreq_get_dev_status(struct device *dev, · line 79
Quoted 5 lines
drivers/devfreq/imx-devfreq.c +5
-0+struct imx_devfreq *priv =dev_get_drvdata (dev); +const char *icc_driver_name; + +if (!IS_ENABLED (CONFIG_INTERCONNECT_IMX )) +return 0 ;It is not proper to check the enable state of
CONFIG_INTERCONNECT_IMXconfiguration on device driver. Why don't you add the 'selectCONFIG_INTERCONNECT_IMX' onKconfig?
Because it's optional.
You can disable interconnect support and just tweak frequencies using the devfreq sysfs API. But indeed would only really be useful for debugging.
Quoted 47 lines
Quoted 47 lines
drivers/devfreq/imx-devfreq.c +23
-0+if (!of_get_property (dev->of_node,"#interconnect-cells" ,0 )) +return 0 ; + + icc_driver_name =of_device_get_match_data (dev); +if (!icc_driver_name) +return 0 ; + + priv->icc_pdev =platform_device_register_data ( + dev, icc_driver_name,0 ,NULL ,0 ); +if (IS_ERR (priv->icc_pdev)) { +dev_err (dev,"failed to register icc provider %s: %ld\n" , + icc_driver_name,PTR_ERR (priv->devfreq)); +return PTR_ERR (priv->devfreq); + } + +return 0 ; }static int imx_devfreq_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;@@ -120,18 +150,25 @@ static int imx_devfreq_probe(struct platform_device *pdev) ret =PTR_ERR (priv->devfreq);dev_err (dev,"failed to add devfreq device: %d\n" , ret); goto err; } + ret =imx_devfreq_init_icc (dev); +if (ret) + goto err; +return 0 ; err:dev_pm_opp_of_remove_table (dev);return ret; }static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8mq-noc" , .data ="imx8mq-interconnect" , }, + { .compatible ="fsl,imx8mm-noc" , .data ="imx8mm-interconnect" , }, + { .compatible ="fsl,imx8mn-noc" , .data ="imx8mn-interconnect" , }, { .compatible ="fsl,imx8m-noc" , }, { .compatible ="fsl,imx8m-nic" , }, {/* sentinel */ }, };MODULE_DEVICE_TABLE (of, imx_devfreq_of_match);
Chanwoo Choi
maintainerRe: [PATCH RFC v6 3/9] PM / devfreq: imx: Register interconnect device
Quoted 57 lines · Leonard Crestez
Quoted 47 lines · Chanwoo Choi
Hi,
Quoted 44 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-devfreq.c | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)drivers/devfreq/imx-devfreq.c +9
-0@@ -15,10 +15,11 @@struct imx_devfreq {struct devfreq_dev_profile profile;struct devfreq *devfreq;struct clk *clk;struct devfreq_passive_data passive_data; +struct platform_device *icc_pdev; };static int imx_devfreq_target (struct device *dev,unsigned long *freq,u32 flags) {@@ -60,11 +61,40 @@ static int imx_devfreq_get_dev_status(struct device *dev,return 0 ; }static void imx_devfreq_exit (struct device *dev) { +struct imx_devfreq *priv =dev_get_drvdata (dev); +dev_pm_opp_of_remove_table (dev); +platform_device_unregister (priv->icc_pdev); +} + +/* imx_devfreq_init_icc() - register matching icc provider if required */ +static int imx_devfreq_init_icc (struct device *dev) +{Quoted 8 lines
drivers/devfreq/imx-devfreq.c static int imx_devfreq_get_dev_status(struct device *dev, · line 79
Quoted 5 lines
drivers/devfreq/imx-devfreq.c +5
-0+struct imx_devfreq *priv =dev_get_drvdata (dev); +const char *icc_driver_name; + +if (!IS_ENABLED (CONFIG_INTERCONNECT_IMX )) +return 0 ;It is not proper to check the enable state of
CONFIG_INTERCONNECT_IMXconfiguration on device driver. Why don't you add the 'selectCONFIG_INTERCONNECT_IMX' onKconfig?
Quoted 4 lines
Because it's optional.
You can disable interconnect support and just tweak frequencies using the devfreq sysfs API. But indeed would only really be useful for debugging.
Even if it's optional, I don't prefer to use 'IS_ENABLED' macro.
Generally, add or delete the property or value at DT file to either enable or disable the some feature provided by device driver instead of checking the configuration.
If user adds the property/value related to interconnect
and imx-bus.c configuration is enabled, the behavior
related to interconnect on imx-bus.c doesn't work. It make some confusion.
The imx-bus.c have to add the 'select CONFIG_INTERCONNECT_IMX' and hand over the right which use the interconnect feature or not, to user.
If there are any requirement to add the additional property to check whether interconnect feature will be used or not, you can add the extra property. But, I think that it is enough to check the '#interconnect-cells'.
In result, I think that it is right to decide the usage of feature of device driver by user on Devicetree.
Quoted 50 lines
Quoted 48 lines
Quoted 48 lines
drivers/devfreq/imx-devfreq.c +23
-0+if (!of_get_property (dev->of_node,"#interconnect-cells" ,0 )) +return 0 ; + + icc_driver_name =of_device_get_match_data (dev); +if (!icc_driver_name) +return 0 ; + + priv->icc_pdev =platform_device_register_data ( + dev, icc_driver_name,0 ,NULL ,0 ); +if (IS_ERR (priv->icc_pdev)) { +dev_err (dev,"failed to register icc provider %s: %ld\n" , + icc_driver_name,PTR_ERR (priv->devfreq)); +return PTR_ERR (priv->devfreq); + } + +return 0 ; }static int imx_devfreq_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;@@ -120,18 +150,25 @@ static int imx_devfreq_probe(struct platform_device *pdev) ret =PTR_ERR (priv->devfreq);dev_err (dev,"failed to add devfreq device: %d\n" , ret); goto err; } + ret =imx_devfreq_init_icc (dev); +if (ret) + goto err; +return 0 ; err:dev_pm_opp_of_remove_table (dev);return ret; }static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8mq-noc" , .data ="imx8mq-interconnect" , }, + { .compatible ="fsl,imx8mm-noc" , .data ="imx8mm-interconnect" , }, + { .compatible ="fsl,imx8mn-noc" , .data ="imx8mn-interconnect" , }, { .compatible ="fsl,imx8m-noc" , }, { .compatible ="fsl,imx8m-nic" , }, {/* sentinel */ }, };MODULE_DEVICE_TABLE (of, imx_devfreq_of_match);
Signature · 3 lines
Best Regards, Chanwoo Choi Samsung Electronics
Re: [PATCH RFC v6 3/9] PM / devfreq: imx: Register interconnect device
Quoted 65 lines · Chanwoo Choi
Quoted 57 lines · Leonard Crestez
Quoted 47 lines · Chanwoo Choi
Hi,
Quoted 44 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-devfreq.c | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)drivers/devfreq/imx-devfreq.c +9
-0@@ -15,10 +15,11 @@struct imx_devfreq {struct devfreq_dev_profile profile;struct devfreq *devfreq;struct clk *clk;struct devfreq_passive_data passive_data; +struct platform_device *icc_pdev; };static int imx_devfreq_target (struct device *dev,unsigned long *freq,u32 flags) {@@ -60,11 +61,40 @@ static int imx_devfreq_get_dev_status(struct device *dev,return 0 ; }static void imx_devfreq_exit (struct device *dev) { +struct imx_devfreq *priv =dev_get_drvdata (dev); +dev_pm_opp_of_remove_table (dev); +platform_device_unregister (priv->icc_pdev); +} + +/* imx_devfreq_init_icc() - register matching icc provider if required */ +static int imx_devfreq_init_icc (struct device *dev) +{Quoted 8 lines
drivers/devfreq/imx-devfreq.c static int imx_devfreq_get_dev_status(struct device *dev, · line 79
Quoted 5 lines
drivers/devfreq/imx-devfreq.c +5
-0+struct imx_devfreq *priv =dev_get_drvdata (dev); +const char *icc_driver_name; + +if (!IS_ENABLED (CONFIG_INTERCONNECT_IMX )) +return 0 ;It is not proper to check the enable state of
CONFIG_INTERCONNECT_IMXconfiguration on device driver. Why don't you add the 'selectCONFIG_INTERCONNECT_IMX' onKconfig?Quoted 4 lines
Because it's optional.
You can disable interconnect support and just tweak frequencies using the devfreq sysfs API. But indeed would only really be useful for debugging.
Even if it's optional, I don't prefer to use '
IS_ENABLED' macro.
Quoted 7 lines
Generally, add or delete the property or value at DT file to either enable or disable the some feature provided by device driver instead of checking the configuration.
If user adds the property/value related to interconnect
andimx-bus.cconfiguration is enabled, the behavior
related to interconnect onimx-bus.cdoesn't work. It make some confusion.
Maybe I could print a warning if #interconnect-cells is present but CONFIG_INTERCONNECT_IMX is off?
An explicit select in Kconfig seems like a pointless limitation but in practice it would almost never be useful to build one without the other.
Quoted 63 lines
The
imx-bus.chave to add the 'selectCONFIG_INTERCONNECT_IMX' and hand over the right which use the interconnect feature or not, to user.If there are any requirement to add the additional property to check whether interconnect feature will be used or not, you can add the extra property. But, I think that it is enough to check the '#interconnect-cells'.
In result, I think that it is right to decide the usage of feature of device driver by user on Devicetree.
Quoted 50 lines
Quoted 48 lines
Quoted 48 lines
drivers/devfreq/imx-devfreq.c +23
-0+if (!of_get_property (dev->of_node,"#interconnect-cells" ,0 )) +return 0 ; + + icc_driver_name =of_device_get_match_data (dev); +if (!icc_driver_name) +return 0 ; + + priv->icc_pdev =platform_device_register_data ( + dev, icc_driver_name,0 ,NULL ,0 ); +if (IS_ERR (priv->icc_pdev)) { +dev_err (dev,"failed to register icc provider %s: %ld\n" , + icc_driver_name,PTR_ERR (priv->devfreq)); +return PTR_ERR (priv->devfreq); + } + +return 0 ; }static int imx_devfreq_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;@@ -120,18 +150,25 @@ static int imx_devfreq_probe(struct platform_device *pdev) ret =PTR_ERR (priv->devfreq);dev_err (dev,"failed to add devfreq device: %d\n" , ret); goto err; } + ret =imx_devfreq_init_icc (dev); +if (ret) + goto err; +return 0 ; err:dev_pm_opp_of_remove_table (dev);return ret; }static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8mq-noc" , .data ="imx8mq-interconnect" , }, + { .compatible ="fsl,imx8mm-noc" , .data ="imx8mm-interconnect" , }, + { .compatible ="fsl,imx8mn-noc" , .data ="imx8mn-interconnect" , }, { .compatible ="fsl,imx8m-noc" , }, { .compatible ="fsl,imx8m-nic" , }, {/* sentinel */ }, };MODULE_DEVICE_TABLE (of, imx_devfreq_of_match);
Re: [PATCH RFC v6 3/9] PM / devfreq: imx: Register interconnect device
2019년 12월 18일 (수) 오후 7:14, Leonard Crestez <[email protected]>님이 작성:
Quoted 71 lines · Chanwoo Choi
Quoted 69 lines · Leonard Crestez
Quoted 57 lines · Chanwoo Choi
Quoted 47 lines
Hi,
Quoted 44 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-devfreq.c | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)drivers/devfreq/imx-devfreq.c +9
-0@@ -15,10 +15,11 @@struct imx_devfreq {struct devfreq_dev_profile profile;struct devfreq *devfreq;struct clk *clk;struct devfreq_passive_data passive_data; +struct platform_device *icc_pdev; };static int imx_devfreq_target (struct device *dev,unsigned long *freq,u32 flags) {@@ -60,11 +61,40 @@ static int imx_devfreq_get_dev_status(struct device *dev,return 0 ; }static void imx_devfreq_exit (struct device *dev) { +struct imx_devfreq *priv =dev_get_drvdata (dev); +dev_pm_opp_of_remove_table (dev); +platform_device_unregister (priv->icc_pdev); +} + +/* imx_devfreq_init_icc() - register matching icc provider if required */ +static int imx_devfreq_init_icc (struct device *dev) +{Quoted 8 lines
drivers/devfreq/imx-devfreq.c static int imx_devfreq_get_dev_status(struct device *dev, · line 79
Quoted 5 lines
drivers/devfreq/imx-devfreq.c +5
-0+struct imx_devfreq *priv =dev_get_drvdata (dev); +const char *icc_driver_name; + +if (!IS_ENABLED (CONFIG_INTERCONNECT_IMX )) +return 0 ;It is not proper to check the enable state of
CONFIG_INTERCONNECT_IMXconfiguration on device driver. Why don't you add the 'selectCONFIG_INTERCONNECT_IMX' onKconfig?Quoted 4 lines
Because it's optional.
You can disable interconnect support and just tweak frequencies using the devfreq sysfs API. But indeed would only really be useful for debugging.
Even if it's optional, I don't prefer to use '
IS_ENABLED' macro.Generally, add or delete the property or value at DT file to either enable or disable the some feature provided by device driver instead of checking the configuration.
Quoted 6 lines
Quoted 3 lines
If user adds the property/value related to interconnect
andimx-bus.cconfiguration is enabled, the behavior
related to interconnect onimx-bus.cdoesn't work. It make some confusion.Maybe I could print a warning if #interconnect-cells is present but
CONFIG_INTERCONNECT_IMXis off?
Actually, user might think that if imx-bus.c is enabled , CONFIG_INTERCONNECT_MIX is enabled.
Because, the dt binding document of imx-bus.c will contain the property for interconnect.
If device driver support the various feature, the device driver have to enable all configuration in order to support the features for user.
Quoted 3 lines
An explicit select in
Kconfigseems like a pointless limitation but in practice it would almost never be useful to build one without the other.
This patch is for the some CONFIG_INTERCONNECT_IMX driver.
I don't understand why is not meaningful to select CONFIG_INTERCONNECT_IMX in Kconfig?
Quoted 65 lines
Quoted 64 lines
The
imx-bus.chave to add the 'selectCONFIG_INTERCONNECT_IMX' and hand over the right which use the interconnect feature or not, to user.If there are any requirement to add the additional property to check whether interconnect feature will be used or not, you can add the extra property. But, I think that it is enough to check the '#interconnect-cells'.
In result, I think that it is right to decide the usage of feature of device driver by user on Devicetree.
Quoted 50 lines
Quoted 48 lines
Quoted 48 lines
drivers/devfreq/imx-devfreq.c +23
-0+if (!of_get_property (dev->of_node,"#interconnect-cells" ,0 )) +return 0 ; + + icc_driver_name =of_device_get_match_data (dev); +if (!icc_driver_name) +return 0 ; + + priv->icc_pdev =platform_device_register_data ( + dev, icc_driver_name,0 ,NULL ,0 ); +if (IS_ERR (priv->icc_pdev)) { +dev_err (dev,"failed to register icc provider %s: %ld\n" , + icc_driver_name,PTR_ERR (priv->devfreq)); +return PTR_ERR (priv->devfreq); + } + +return 0 ; }static int imx_devfreq_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;@@ -120,18 +150,25 @@ static int imx_devfreq_probe(struct platform_device *pdev) ret =PTR_ERR (priv->devfreq);dev_err (dev,"failed to add devfreq device: %d\n" , ret); goto err; } + ret =imx_devfreq_init_icc (dev); +if (ret) + goto err; +return 0 ; err:dev_pm_opp_of_remove_table (dev);return ret; }static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8mq-noc" , .data ="imx8mq-interconnect" , }, + { .compatible ="fsl,imx8mm-noc" , .data ="imx8mm-interconnect" , }, + { .compatible ="fsl,imx8mn-noc" , .data ="imx8mn-interconnect" , }, { .compatible ="fsl,imx8m-noc" , }, { .compatible ="fsl,imx8m-nic" , }, {/* sentinel */ }, };MODULE_DEVICE_TABLE (of, imx_devfreq_of_match);
Signature · 2 lines
Best Regards, Chanwoo Choi
Re: [PATCH RFC v6 3/9] PM / devfreq: imx: Register interconnect device
Quoted 86 lines · Chanwoo Choi
2019년 12월 18일 (수) 오후 7:14, Leonard Crestez <[email protected]>님이 작성:
Quoted 68 lines · Chanwoo Choi
Quoted 67 lines · Leonard Crestez
Quoted 55 lines · Chanwoo Choi
Quoted 45 lines · Leonard Crestez
Quoted 44 lines
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-devfreq.c | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)drivers/devfreq/imx-devfreq.c +9
-0@@ -15,10 +15,11 @@struct imx_devfreq {struct devfreq_dev_profile profile;struct devfreq *devfreq;struct clk *clk;struct devfreq_passive_data passive_data; +struct platform_device *icc_pdev; };static int imx_devfreq_target (struct device *dev,unsigned long *freq,u32 flags) {@@ -60,11 +61,40 @@ static int imx_devfreq_get_dev_status(struct device *dev,return 0 ; }static void imx_devfreq_exit (struct device *dev) { +struct imx_devfreq *priv =dev_get_drvdata (dev); +dev_pm_opp_of_remove_table (dev); +platform_device_unregister (priv->icc_pdev); +} + +/* imx_devfreq_init_icc() - register matching icc provider if required */ +static int imx_devfreq_init_icc (struct device *dev) +{Quoted 8 lines
drivers/devfreq/imx-devfreq.c static int imx_devfreq_get_dev_status(struct device *dev, · line 79
Quoted 5 lines
drivers/devfreq/imx-devfreq.c +5
-0+struct imx_devfreq *priv =dev_get_drvdata (dev); +const char *icc_driver_name; + +if (!IS_ENABLED (CONFIG_INTERCONNECT_IMX )) +return 0 ;It is not proper to check the enable state of
CONFIG_INTERCONNECT_IMXconfiguration on device driver. Why don't you add the 'selectCONFIG_INTERCONNECT_IMX' onKconfig?Quoted 4 lines
Because it's optional.
You can disable interconnect support and just tweak frequencies using the devfreq sysfs API. But indeed would only really be useful for debugging.
Even if it's optional, I don't prefer to use '
IS_ENABLED' macro.Generally, add or delete the property or value at DT file to either enable or disable the some feature provided by device driver instead of checking the configuration.
Quoted 6 lines
Quoted 3 lines
If user adds the property/value related to interconnect
andimx-bus.cconfiguration is enabled, the behavior
related to interconnect onimx-bus.cdoesn't work. It make some confusion.Maybe I could print a warning if #interconnect-cells is present but
CONFIG_INTERCONNECT_IMXis off?Actually, user might think that if
imx-bus.cis enabled ,CONFIG_INTERCONNECT_MIXis enabled.
Because, the dt binding document ofimx-bus.cwill contain the property for interconnect.If device driver support the various feature, the device driver have to enable all configuration in order to support the features for user.
Quoted 6 lines
Quoted 2 lines
An explicit select in
Kconfigseems like a pointless limitation but in practice it would almost never be useful to build one without the other.This patch is for the some
CONFIG_INTERCONNECT_IMXdriver.
I don't understand why is not meaningful to selectCONFIG_INTERCONNECT_IMXinKconfig?
One issue is that the interconnect graph is described per-soc and there are per-soc config options while imx-bus applies to all. So the "if" condition is not sufficient either; if the per-soc interconnect driver is omitted then the platform device will be added but no driver will be ever be found.
There are ways around this: for example all of imx interconnect could be built as a single module. But I think it's reasonable for devices to be partially functional if some config options are missing and heavy config customization sometimes requires a bit of debugging.
There are various issues when building the current series as "m" but I can solve them and post a final patch which sets all the relevant options on "m" in arm64 defconfig. The it will all "just work" out of the box.
Quoted 59 lines
Quoted 59 lines
Quoted 59 lines
The
imx-bus.chave to add the 'selectCONFIG_INTERCONNECT_IMX' and hand over the right which use the interconnect feature or not, to user.If there are any requirement to add the additional property to check whether interconnect feature will be used or not, you can add the extra property. But, I think that it is enough to check the '#interconnect-cells'.
In result, I think that it is right to decide the usage of feature of device driver by user on Devicetree.
Quoted 48 lines
Quoted 48 lines
Quoted 48 lines
drivers/devfreq/imx-devfreq.c +23
-0+if (!of_get_property (dev->of_node,"#interconnect-cells" ,0 )) +return 0 ; + + icc_driver_name =of_device_get_match_data (dev); +if (!icc_driver_name) +return 0 ; + + priv->icc_pdev =platform_device_register_data ( + dev, icc_driver_name,0 ,NULL ,0 ); +if (IS_ERR (priv->icc_pdev)) { +dev_err (dev,"failed to register icc provider %s: %ld\n" , + icc_driver_name,PTR_ERR (priv->devfreq)); +return PTR_ERR (priv->devfreq); + } + +return 0 ; }static int imx_devfreq_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;@@ -120,18 +150,25 @@ static int imx_devfreq_probe(struct platform_device *pdev) ret =PTR_ERR (priv->devfreq);dev_err (dev,"failed to add devfreq device: %d\n" , ret); goto err; } + ret =imx_devfreq_init_icc (dev); +if (ret) + goto err; +return 0 ; err:dev_pm_opp_of_remove_table (dev);return ret; }static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8mq-noc" , .data ="imx8mq-interconnect" , }, + { .compatible ="fsl,imx8mm-noc" , .data ="imx8mm-interconnect" , }, + { .compatible ="fsl,imx8mn-noc" , .data ="imx8mn-interconnect" , }, { .compatible ="fsl,imx8m-noc" , }, { .compatible ="fsl,imx8m-nic" , }, {/* sentinel */ }, };MODULE_DEVICE_TABLE (of, imx_devfreq_of_match);
Chanwoo Choi
maintainerRe: [PATCH RFC v6 3/9] PM / devfreq: imx: Register interconnect device
Quoted 105 lines · Leonard Crestez
Quoted 86 lines · Chanwoo Choi
2019년 12월 18일 (수) 오후 7:14, Leonard Crestez <[email protected]>님이 작성:
Quoted 68 lines · Chanwoo Choi
Quoted 67 lines · Leonard Crestez
Quoted 55 lines · Chanwoo Choi
Quoted 45 lines · Leonard Crestez
Quoted 44 lines
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-devfreq.c | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)drivers/devfreq/imx-devfreq.c +9
-0@@ -15,10 +15,11 @@struct imx_devfreq {struct devfreq_dev_profile profile;struct devfreq *devfreq;struct clk *clk;struct devfreq_passive_data passive_data; +struct platform_device *icc_pdev; };static int imx_devfreq_target (struct device *dev,unsigned long *freq,u32 flags) {@@ -60,11 +61,40 @@ static int imx_devfreq_get_dev_status(struct device *dev,return 0 ; }static void imx_devfreq_exit (struct device *dev) { +struct imx_devfreq *priv =dev_get_drvdata (dev); +dev_pm_opp_of_remove_table (dev); +platform_device_unregister (priv->icc_pdev); +} + +/* imx_devfreq_init_icc() - register matching icc provider if required */ +static int imx_devfreq_init_icc (struct device *dev) +{Quoted 8 lines
drivers/devfreq/imx-devfreq.c static int imx_devfreq_get_dev_status(struct device *dev, · line 79
Quoted 5 lines
drivers/devfreq/imx-devfreq.c +5
-0+struct imx_devfreq *priv =dev_get_drvdata (dev); +const char *icc_driver_name; + +if (!IS_ENABLED (CONFIG_INTERCONNECT_IMX )) +return 0 ;It is not proper to check the enable state of
CONFIG_INTERCONNECT_IMXconfiguration on device driver. Why don't you add the 'selectCONFIG_INTERCONNECT_IMX' onKconfig?Quoted 4 lines
Because it's optional.
You can disable interconnect support and just tweak frequencies using the devfreq sysfs API. But indeed would only really be useful for debugging.
Even if it's optional, I don't prefer to use '
IS_ENABLED' macro.Generally, add or delete the property or value at DT file to either enable or disable the some feature provided by device driver instead of checking the configuration.
Quoted 6 lines
Quoted 3 lines
If user adds the property/value related to interconnect
andimx-bus.cconfiguration is enabled, the behavior
related to interconnect onimx-bus.cdoesn't work. It make some confusion.Maybe I could print a warning if #interconnect-cells is present but
CONFIG_INTERCONNECT_IMXis off?Actually, user might think that if
imx-bus.cis enabled ,CONFIG_INTERCONNECT_MIXis enabled.
Because, the dt binding document ofimx-bus.cwill contain the property for interconnect.If device driver support the various feature, the device driver have to enable all configuration in order to support the features for user.
Quoted 6 lines
Quoted 2 lines
An explicit select in
Kconfigseems like a pointless limitation but in practice it would almost never be useful to build one without the other.This patch is for the some
CONFIG_INTERCONNECT_IMXdriver.
I don't understand why is not meaningful to selectCONFIG_INTERCONNECT_IMXinKconfig?One issue is that the interconnect graph is described per-soc and there are per-soc config options while imx-bus applies to all. So the "if" condition is not sufficient either; if the per-soc interconnect driver is omitted then the platform device will be added but no driver will be ever be found.
There are ways around this: for example all of imx interconnect could be built as a single module. But I think it's reasonable for devices to be partially functional if some config options are missing and heavy config customization sometimes requires a bit of debugging.
Quoted 4 lines
There are various issues when building the current series as "m" but I can solve them and post a final patch which sets all the relevant options on "m" in arm64 defconfig. The it will all "just work" out of the box.
Sorry. Actually, I don't understand the relationship perfectly between imx-bus and imx-interconnect. As you mentioned, I'll expect the your solution on next version.
Quoted 60 lines
Quoted 60 lines
Quoted 60 lines
Quoted 60 lines
The
imx-bus.chave to add the 'selectCONFIG_INTERCONNECT_IMX' and hand over the right which use the interconnect feature or not, to user.If there are any requirement to add the additional property to check whether interconnect feature will be used or not, you can add the extra property. But, I think that it is enough to check the '#interconnect-cells'.
In result, I think that it is right to decide the usage of feature of device driver by user on Devicetree.
Quoted 48 lines
Quoted 48 lines
Quoted 48 lines
drivers/devfreq/imx-devfreq.c +23
-0+if (!of_get_property (dev->of_node,"#interconnect-cells" ,0 )) +return 0 ; + + icc_driver_name =of_device_get_match_data (dev); +if (!icc_driver_name) +return 0 ; + + priv->icc_pdev =platform_device_register_data ( + dev, icc_driver_name,0 ,NULL ,0 ); +if (IS_ERR (priv->icc_pdev)) { +dev_err (dev,"failed to register icc provider %s: %ld\n" , + icc_driver_name,PTR_ERR (priv->devfreq)); +return PTR_ERR (priv->devfreq); + } + +return 0 ; }static int imx_devfreq_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;@@ -120,18 +150,25 @@ static int imx_devfreq_probe(struct platform_device *pdev) ret =PTR_ERR (priv->devfreq);dev_err (dev,"failed to add devfreq device: %d\n" , ret); goto err; } + ret =imx_devfreq_init_icc (dev); +if (ret) + goto err; +return 0 ; err:dev_pm_opp_of_remove_table (dev);return ret; }static const struct of_device_id imx_devfreq_of_match[] = { + { .compatible ="fsl,imx8mq-noc" , .data ="imx8mq-interconnect" , }, + { .compatible ="fsl,imx8mm-noc" , .data ="imx8mm-interconnect" , }, + { .compatible ="fsl,imx8mn-noc" , .data ="imx8mn-interconnect" , }, { .compatible ="fsl,imx8m-noc" , }, { .compatible ="fsl,imx8m-nic" , }, {/* sentinel */ }, };MODULE_DEVICE_TABLE (of, imx_devfreq_of_match);
Signature · 3 lines
Best Regards, Chanwoo Choi Samsung Electronics
RFC PATCH v6 4/9 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 | 1 + drivers/interconnect/imx/imx.c | 301 ++++++++++++++++++++++++++++++ drivers/interconnect/imx/imx.h | 60 ++++++ 6 files changed, 369 insertions(+) create mode 100644 drivers/interconnect/imx/Kconfig create mode 100644 drivers/interconnect/imx/Makefile create mode 100644 drivers/interconnect/imx/imx.c create mode 100644 drivers/interconnect/imx/imx.h
drivers/interconnect/Kconfig +1 -0
@@ -10,7 +10,8 @@ menuconfig INTERCONNECT If unsure, say no. if INTERCONNECT source "drivers/interconnect/qcom/Kconfig" +source "drivers/interconnect/imx/Kconfig" endif
drivers/interconnect/Makefile +1 -0
@@ -2,5 +2,6 @@ icc-core-objs := core.o obj-$(CONFIG_INTERCONNECT) += icc-core.o obj-$(CONFIG_INTERCONNECT_QCOM) += qcom/ +obj-$(CONFIG_INTERCONNECT_IMX) += imx/
drivers/interconnect/imx/Kconfig new file +5 -0
@@ -0,0 +1,5 @@ +config INTERCONNECT_IMX + bool "i.MX interconnect drivers" + depends on ARCH_MXC || COMPILE_TEST + help + Generic interconnect driver for i.MX SOCs
drivers/interconnect/imx/Makefile new file +1 -0
@@ -0,0 +1 @@ +obj-$(CONFIG_INTERCONNECT_IMX) += imx.o
drivers/interconnect/imx/imx.c new file +301 -0
301 lines not on this page · raw message
drivers/interconnect/imx/imx.h new file +60 -0
60 lines not on this page · raw message
Signature · 1 line
2.17.1
Re: [PATCH RFC v6 4/9] interconnect: Add imx core driver
Hi Leonard,
Thank you for your continuous work on the patches and sorry for not reviewing this earlier.
Quoted 114 lines · Leonard Crestez
This adds support for i.MX SoC family to interconnect framework.
Platform drivers can describe the interconnect graph and several adjustment knobs where icc node bandwidth is converted to a
DEV_PM_QOS_MIN_FREQUENCYrequest.The 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.
Signed-off-by Alexandre Bailon <[email protected]>Signed-off-by Leonard Crestez <[email protected]>--- drivers/interconnect/Kconfig | 1 + drivers/interconnect/Makefile | 1 + drivers/interconnect/imx/Kconfig | 5 + drivers/interconnect/imx/Makefile | 1 + drivers/interconnect/imx/imx.c | 301 ++++++++++++++++++++++++++++++ drivers/interconnect/imx/imx.h | 60 ++++++ 6 files changed, 369 insertions(+) create mode 100644 drivers/interconnect/imx/Kconfig create mode 100644 drivers/interconnect/imx/Makefile create mode 100644 drivers/interconnect/imx/imx.c create mode 100644 drivers/interconnect/imx/imx.hdrivers/interconnect/Kconfig +1
-0@@ -10,7 +10,8 @@ menuconfig INTERCONNECT If unsure, say no. if INTERCONNECT source "drivers/interconnect/qcom/Kconfig" +source "drivers/interconnect/imx/Kconfig" endifdrivers/interconnect/Makefile +1
-0@@ -2,5 +2,6 @@ icc-core-objs := core.o obj-$(CONFIG_INTERCONNECT) += icc-core.o obj-$(CONFIG_INTERCONNECT_QCOM) += qcom/ +obj-$(CONFIG_INTERCONNECT_IMX) += imx/drivers/interconnect/imx/Kconfig new file +5
-0@@ -0,0 +1,5 @@ +config INTERCONNECT_IMX + bool "i.MX interconnect drivers" + depends on ARCH_MXC || COMPILE_TEST + help + Generic interconnect driver for i.MX SOCsdrivers/interconnect/imx/Makefile new file +1
-0@@ -0,0 +1 @@ +obj-$(CONFIG_INTERCONNECT_IMX) += imx.odrivers/interconnect/imx/imx.c new file +41
-0@@ -0,0 +1,301 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Interconnect framework driver for i.MX SoC +* +* Copyright (c) 2019, BayLibre +* Copyright (c) 2019, NXP +* Author: Alexandre Bailon <[email protected]> +* Author: Leonard Crestez <[email protected]> +*/ + +#include <linux/device.h> +#include <linux/interconnect-provider.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/pm_qos.h> + +#include "imx.h" + +/* private icc_node data */ +struct imx_icc_node { +const struct imx_icc_node_desc *desc; +struct device *qos_dev; +struct dev_pm_qos_request qos_req; +}; + +static int imx_icc_aggregate (struct icc_node *node,u32 tag, +u32 avg_bw,u32 peak_bw, +u32 *agg_avg,u32 *agg_peak) +{ + *agg_avg += avg_bw; + *agg_peak =max (*agg_peak, peak_bw); + +return 0 ; +} + +static int imx_icc_node_set (struct icc_node *node) +{ +struct device *dev = node->provider->dev; +struct imx_icc_node *node_data = node->data;
drivers/interconnect/imx/imx.c line 51
Quoted 10 lines
drivers/interconnect/imx/imx.c new file +10
-0+u64 freq; + +if (!node_data->qos_dev) +return 0 ; + + freq = (node->avg_bw + node->peak_bw) * node_data->desc->adj->bw_mul; +do_div (freq, node_data->desc->adj->bw_div); +dev_dbg (dev,"node %s device %s avg_bw %ukBps peak_bw %ukBps min_freq %llukHz\n" , + node->name,dev_name (node_data->qos_dev), + node->avg_bw, node->peak_bw, freq);
Nit: Please align all dev_dbg/dev_err to the open parenthesis.
Quoted 52 lines
drivers/interconnect/imx/imx.c new file +52
-0+ +if (freq >S32_MAX ) { +dev_err (dev,"%s can't request more than S32_MAX freq\n" , + node->name); +return -ERANGE ; + } + +dev_pm_qos_update_request (&node_data->qos_req, freq); + +return 0 ; +} + +static int imx_icc_set (struct icc_node *src,struct icc_node *dst) +{ +return imx_icc_node_set (dst); +} + +/* imx_icc_node_destroy() - Destroy an imx icc_node, including private data */ +static void imx_icc_node_destroy (struct icc_node *node) +{ +struct imx_icc_node *node_data = node->data; + +if (dev_pm_qos_request_active (&node_data->qos_req)) +dev_pm_qos_remove_request (&node_data->qos_req); +put_device (node_data->qos_dev); +icc_node_del (node); +icc_node_destroy (node->id); +} + +static int imx_icc_node_init_qos (struct icc_provider *provider, +struct icc_node *node) +{ +struct imx_icc_node *node_data = node->data; +struct device *dev = provider->dev; +struct device_node *dn =NULL ; +struct platform_device *pdev; +int i, count; +u32 node_id; +int ret; + + count =of_property_count_u32_elems (dev->of_node, +"fsl,scalable-node-ids" ); +if (count <0 ) { +dev_err (dev,"Failed to parse fsl,scalable-node-ids: %d\n" , + count); +return count; + } + +for (i =0 ; i < count; i++) { + ret =of_property_read_u32_index (dev->of_node, +"fsl,scalable-node-ids" , + i, &node_id);
drivers/interconnect/imx/imx.c line 113
Quoted 10 lines
drivers/interconnect/imx/imx.c new file +10
-0+ +if (ret <0 ) { +dev_err (dev,"Failed to parse fsl,scalable-node-ids[%d]: %d\n" , + i, ret); +return ret; + } +if (node_id != node->id) +continue ; + + dn =of_parse_phandle (dev->of_node,"fsl,scalable-nodes" , i);
Why is this needed? I would expect that the interconnect provider driver already knows which nodes are scalable based on the platform compatible string. Then maybe this driver should create devfreq devices for each node that is scalable?
Quoted 20 lines
drivers/interconnect/imx/imx.c new file +20
-0+if (IS_ERR (dn)) { +dev_err (dev,"Failed to parse fsl,scalable-nodes[%d]: %ld\n" , + i,PTR_ERR (dn)); +return PTR_ERR (dn); + } +break ; + } + +/* Allow scaling to be disabled on a per-node basis */ +if (!dn || !of_device_is_available (dn)) +return 0 ; + + pdev =of_find_device_by_node (dn); +of_node_put (dn); +if (!pdev) { +dev_warn (dev,"node %s[%d] missing device for %pOF\n" , + node->name, node->id, dn); +return -EPROBE_DEFER ; + } +
drivers/interconnect/imx/imx.c line 143
Quoted 10 lines
drivers/interconnect/imx/imx.c new file +10
-0+ node_data->qos_dev = &pdev->dev; +dev_info (dev,"node %s[%d] has device node %pOF\n" , + node->name, node->id, dn); +return dev_pm_qos_add_request (node_data->qos_dev, + &node_data->qos_req, +DEV_PM_QOS_MIN_FREQUENCY ,0 ); +} + +static struct icc_node *imx_icc_node_add( + struct icc_provider *provider,
Nit: Move this after the open parenthesis on the line above and then align the line below to the parenthesis and ignore the 80 cols rule.
Quoted 215 lines
drivers/interconnect/imx/imx.c new file +158
-0+ const struct imx_icc_node_desc *node_desc) +{ +struct device *dev = provider->dev; +struct imx_icc_node *node_data; +struct icc_node *node; +int ret; + + node =icc_node_create (node_desc->id); +if (IS_ERR (node)) { +dev_err (dev,"failed to create node %d\n" , node_desc->id); +return node; + } + +if (node->data) { +dev_err (dev,"already created node %s id=%d\n" , + node_desc->name, node_desc->id); +return ERR_PTR (-EEXIST ); + } + + node_data =devm_kzalloc (dev,sizeof (*node_data),GFP_KERNEL ); +if (!node_data) { +icc_node_destroy (node->id); +return ERR_PTR (-ENOMEM ); + } + + node->name = node_desc->name; + node->data = node_data; + node_data->desc = node_desc; +icc_node_add (node, provider); + +if (node_desc->adj) { + ret =imx_icc_node_init_qos (provider, node); +if (ret <0 ) { +imx_icc_node_destroy (node); +return ERR_PTR (ret); + } + } + +return node; +} + +static void imx_icc_unregister_nodes (struct icc_provider *provider) +{ +struct icc_node *node, *tmp; + +list_for_each_entry_safe (node, tmp, &provider->nodes, node_list) +imx_icc_node_destroy (node); +} + +static int imx_icc_register_nodes (struct icc_provider *provider, +const struct imx_icc_node_desc *descs, +int count) +{ +struct icc_onecell_data *provider_data = provider->data; +int ret; +int i; + +for (i =0 ; i < count; i++) { +struct icc_node *node; +const struct imx_icc_node_desc *node_desc = &descs[i]; +size_t j; + + node =imx_icc_node_add (provider, node_desc); +if (IS_ERR (node)) { + ret =PTR_ERR (node); +if (ret != -EPROBE_DEFER ) +dev_err (provider->dev,"failed to add %s: %d\n" , + node_desc->name, ret); + goto err; + } + provider_data->nodes[node->id] = node; + +for (j =0 ; j < node_desc->num_links; j++) { + ret =icc_link_create (node, node_desc->links[j]); +if (ret) { +dev_err (provider->dev,"failed to link node %d to %d: %d\n" , + node->id, node_desc->links[j], ret); + goto err; + } + } + } + +return 0 ; + +err: +imx_icc_unregister_nodes (provider); + +return ret; +} + +static int get_max_node_id (struct imx_icc_node_desc *nodes,int nodes_count) +{ +int i, ret =0 ; + +for (i =0 ; i < nodes_count; ++i) +if (nodes[i].id > ret) + ret = nodes[i].id; + +return ret; +} + +int imx_icc_register (struct platform_device *pdev, +struct imx_icc_node_desc *nodes,int nodes_count) +{ +struct device *dev = &pdev->dev; +struct icc_onecell_data *data; +struct icc_provider *provider; +int max_node_id; +int ret; + +/* icc_onecell_data is indexed by node_id, unlike nodes param */ + max_node_id =get_max_node_id (nodes, nodes_count); + data =devm_kzalloc (dev,struct_size (data, nodes, max_node_id), +GFP_KERNEL ); +if (!data) +return -ENOMEM ; + data->num_nodes = max_node_id; + + provider =devm_kzalloc (dev,sizeof (*provider),GFP_KERNEL ); +if (!provider) +return -ENOMEM ; + provider->set = imx_icc_set; + provider->aggregate = imx_icc_aggregate; + provider->xlate = of_icc_xlate_onecell; + provider->data = data; + provider->dev = dev->parent; +platform_set_drvdata (pdev, provider); + + ret =icc_provider_add (provider); +if (ret) { +dev_err (dev,"error adding interconnect provider: %d\n" , ret); +return ret; + } + + ret =imx_icc_register_nodes (provider, nodes, nodes_count); +if (ret) + goto provider_del; + +pr_info ("registered %s\n" , pdev->name); + +return 0 ; + +provider_del: +icc_provider_del (provider); +return ret; +} +EXPORT_SYMBOL_GPL (imx_icc_register); + +int imx_icc_unregister (struct platform_device *pdev) +{ +struct icc_provider *provider =platform_get_drvdata (pdev); + +icc_provider_del (provider); +imx_icc_unregister_nodes (provider); + +return 0 ; +} +EXPORT_SYMBOL_GPL (imx_icc_unregister);drivers/interconnect/imx/imx.h new file +50
-0@@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Interconnect framework driver for i.MX SoC +* +* Copyright (c) 2019, BayLibre +* Copyright (c) 2019, NXP +* Author: Alexandre Bailon <[email protected]> +* Author: Leonard Crestez <[email protected]> +*/ +#ifndef __DRIVERS_INTERCONNECT_IMX_H +#define __DRIVERS_INTERCONNECT_IMX_H + +#include <linux/kernel.h> + +#define IMX_ICC_MAX_LINKS 4 + +/* +* struct imx_icc_node_adj - Describe a dynamic adjustment knob +*/ +struct imx_icc_node_adj_desc { +unsigned int bw_mul, bw_div; +}; + +/* +* struct imx_icc_node - Describe an interconnect node +* @name: name of the node +* @id: an unique id to identify the node +* @links: an array of slaves' node id +* @num_links: number of id defined in links +*/ +struct imx_icc_node_desc { +const char *name; +u16 id; +u16 links[IMX_ICC_MAX_LINKS ]; +u16 num_links; + +const struct imx_icc_node_adj_desc *adj; +}; + +#define DEFINE_BUS_INTERCONNECT (_name, _id, _adj, ...) \ + { \ + .id = _id, \ + .name = _name, \ + .adj = _adj, \ + .num_links = ARRAY_SIZE(((int[]){ __VA_ARGS__ })), \ + .links = { __VA_ARGS__ }, \ + } + +#define DEFINE_BUS_MASTER (_name, _id, _dest_id) \ + DEFINE_BUS_INTERCONNECT(_name, _id, NULL, _dest_id)
drivers/interconnect/imx/imx.h line 60
Quoted 10 lines
drivers/interconnect/imx/imx.h new file +10
-0+ +#define DEFINE_BUS_SLAVE (_name, _id, _adj) \ + DEFINE_BUS_INTERCONNECT(_name, _id, _adj) + +int imx_icc_register (struct platform_device *pdev, +struct imx_icc_node_desc *nodes, +int nodes_count); +int imx_icc_unregister (struct platform_device *pdev); + +#endif /* __DRIVERS_INTERCONNECT_IMX_H */
The rest look ok to me. We just need to figure out the scalable nodes thing.
Thanks,
Georgi
Re: [PATCH RFC v6 4/9] interconnect: Add imx core driver
Quoted 47 lines · Georgi Djakov
Hi Leonard,
Thank you for your continuous work on the patches and sorry for not reviewing this earlier.
Quoted 42 lines · Leonard Crestez
This adds support for i.MX SoC family to interconnect framework.
Platform drivers can describe the interconnect graph and several adjustment knobs where icc node bandwidth is converted to a
DEV_PM_QOS_MIN_FREQUENCYrequest.The 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.
Signed-off-by Alexandre Bailon <[email protected]>Signed-off-by Leonard Crestez <[email protected]>drivers/interconnect/imx/imx.c new file +29
-0+static int imx_icc_node_init_qos (struct icc_provider *provider, +struct icc_node *node) +{ +struct imx_icc_node *node_data = node->data; +struct device *dev = provider->dev; +struct device_node *dn =NULL ; +struct platform_device *pdev; +int i, count; +u32 node_id; +int ret; + + count =of_property_count_u32_elems (dev->of_node, +"fsl,scalable-node-ids" ); +if (count <0 ) { +dev_err (dev,"Failed to parse fsl,scalable-node-ids: %d\n" , + count); +return count; + } + +for (i =0 ; i < count; i++) { + ret =of_property_read_u32_index (dev->of_node, +"fsl,scalable-node-ids" , + i, &node_id); + +if (ret <0 ) { +dev_err (dev,"Failed to parse fsl,scalable-node-ids[%d]: %d\n" , + i, ret); +return ret; + }
Quoted 8 lines
drivers/interconnect/imx/imx.c line 113
Quoted 4 lines
drivers/interconnect/imx/imx.c new file +4
-0+if (node_id != node->id) +continue ; + + dn =of_parse_phandle (dev->of_node,"fsl,scalable-nodes" , i);Why is this needed? I would expect that the interconnect provider driver already knows which nodes are scalable based on the platform compatible string. Then maybe this driver should create devfreq devices for each node that is scalable?
The scalable nodes are independent devfreq instances which are probed through their own DT compat strings. It's even possible to reload imx8m-ddrc (the driver scaling the dram controller) at runtime.
The most common solution to fetch other devices on DT systems is via phandles and fsl,scalable-nodes is a phandle array. Since the provider is platform-specific and knows the topology of the soc it could even use of_find_node_by_path but that seems very messy. It's also quite brittle, I've seen several bugs caused by DT node renaming.
This support for arbitrary "scalable nodes" might be excessively generic and strict DT compatibility might be difficult to maintain if too much is exposed. Changing per-soc driver data is otherwise easy.
In vendor tree we only ever scale the main NOC and DDRC anyway so equivalent functionality could be achieved with a single "fsl,ddrc" phandle property on the noc.
Support for scaling peripheral buses could be implemented by adding additional properties like "fsl,display-nic". Such a feature would need careful measurement on real hardware anyway.
--
Regards,
Leonard
RFC PATCH v6 5/9 interconnect: imx: Add platform driver for imx8mm
In reply to Leonard CrestezAdd a platform driver for the i.MX8MM SoC describing bus topology.
Bandwidth adjustments is currently only supported on the DDRC and main NOC. Scaling for the vpu/gpu/display NICs could be added in the future.
--- drivers/interconnect/imx/Kconfig | 4 + drivers/interconnect/imx/Makefile | 1 + drivers/interconnect/imx/imx8mm.c | 105 ++++++++++++++++++++++ include/dt-bindings/interconnect/imx8mm.h | 49 ++++++++++ 4 files changed, 159 insertions(+) create mode 100644 drivers/interconnect/imx/imx8mm.c create mode 100644 include/dt-bindings/interconnect/imx8mm.h
drivers/interconnect/imx/Kconfig +4 -0
@@ -1,5 +1,9 @@ config INTERCONNECT_IMX bool "i.MX interconnect drivers" depends on ARCH_MXC || COMPILE_TEST help Generic interconnect driver for i.MX SOCs + +config INTERCONNECT_IMX8MM + def_bool y + depends on INTERCONNECT_IMX
drivers/interconnect/imx/Makefile +1 -0
@@ -1 +1,2 @@ obj-$(CONFIG_INTERCONNECT_IMX) += imx.o +obj-$(CONFIG_INTERCONNECT_IMX8MM) += imx8mm.o
drivers/interconnect/imx/imx8mm.c new file +105 -0
105 lines not on this page · raw message
include/dt-bindings/interconnect/imx8mm.h new file +49 -0
49 lines not on this page · raw message
Signature · 1 line
2.17.1
Re: [PATCH RFC v6 5/9] interconnect: imx: Add platform driver for imx8mm
Hi Leonard,
Quoted 21 lines · Leonard Crestez
Add a platform driver for the i.MX8MM SoC describing bus topology.
Bandwidth adjustments is currently only supported on the DDRC and main NOC. Scaling for the vpu/gpu/display NICs could be added in the future.
Signed-off-by Alexandre Bailon <[email protected]>Signed-off-by Leonard Crestez <[email protected]>--- drivers/interconnect/imx/Kconfig | 4 + drivers/interconnect/imx/Makefile | 1 + drivers/interconnect/imx/imx8mm.c | 105 ++++++++++++++++++++++ include/dt-bindings/interconnect/imx8mm.h | 49 ++++++++++ 4 files changed, 159 insertions(+) create mode 100644 drivers/interconnect/imx/imx8mm.c create mode 100644 include/dt-bindings/interconnect/imx8mm.hdrivers/interconnect/imx/Kconfig +0
-0
drivers/interconnect/imx/Kconfig line 8
Quoted 8 lines
drivers/interconnect/imx/Kconfig +3
-0@@ -1,5 +1,9 @@ config INTERCONNECT_IMX bool "i.MX interconnect drivers" depends on ARCH_MXC || COMPILE_TEST help Generic interconnect driver for i.MX SOCs + +config INTERCONNECT_IMX8MM + def_bool y
Can this be a module?
drivers/interconnect/imx/imx8mm.c
Quoted 12 lines
drivers/interconnect/imx/Kconfig +1
-0+ depends on INTERCONNECT_IMXdrivers/interconnect/imx/Makefile +1
-0@@ -1 +1,2 @@ obj-$(CONFIG_INTERCONNECT_IMX) += imx.o +obj-$(CONFIG_INTERCONNECT_IMX8MM) += imx8mm.odrivers/interconnect/imx/imx8mm.c new file +0
-1--- /dev/null
Thanks,
Georgi
Re: [PATCH RFC v6 5/9] interconnect: imx: Add platform driver for imx8mm
Quoted 19 lines · Georgi Djakov
Hi Leonard,
Quoted 16 lines · Leonard Crestez
Add a platform driver for the i.MX8MM SoC describing bus topology.
Bandwidth adjustments is currently only supported on the DDRC and main NOC. Scaling for the vpu/gpu/display NICs could be added in the future.
Signed-off-by Alexandre Bailon <[email protected]>Signed-off-by Leonard Crestez <[email protected]>--- drivers/interconnect/imx/Kconfig | 4 + drivers/interconnect/imx/Makefile | 1 + drivers/interconnect/imx/imx8mm.c | 105 ++++++++++++++++++++++ include/dt-bindings/interconnect/imx8mm.h | 49 ++++++++++ 4 files changed, 159 insertions(+)create mode 100644
drivers/interconnect/imx/imx8mm.ccreate mode 100644include/dt-bindings/interconnect/imx8mm.h
Quoted 15 lines
drivers/interconnect/imx/Kconfig line 8
Quoted 13 lines
drivers/interconnect/imx/Kconfig +3
-0@@ -1,5 +1,9 @@ config INTERCONNECT_IMX bool "i.MX interconnect drivers" depends on ARCH_MXC || COMPILE_TEST help Generic interconnect driver for i.MX SOCs + +config INTERCONNECT_IMX8MM + def_bool yCan this be a module?
Yes. I'll turn this into a tristate; at the very least it would be useful to check modprobe cycling.
By default imx boots with bus frequency set to "high" so there are no hard dependencies on interconnect.
Historically in our vendor tree we had boot drivers which made bus scaling requests (like sdcard and ethernet) but I'm not sure this is strictly required.
Quoted 16 lines
drivers/interconnect/imx/imx8mm.c
Quoted 12 lines
drivers/interconnect/imx/Kconfig +1
-0+ depends on INTERCONNECT_IMXdrivers/interconnect/imx/Makefile +1
-0@@ -1 +1,2 @@ obj-$(CONFIG_INTERCONNECT_IMX) += imx.o +obj-$(CONFIG_INTERCONNECT_IMX8MM) += imx8mm.odrivers/interconnect/imx/imx8mm.c new file +0
-1--- /dev/nullThanks,
Georgi
RFC PATCH v6 6/9 interconnect: imx: Add platform driver for imx8mq
In reply to Leonard CrestezAdd a platform driver for the i.MX8MQ SoC describing bus topology, based on internal documentation.
--- drivers/interconnect/imx/Kconfig | 4 + drivers/interconnect/imx/Makefile | 1 + drivers/interconnect/imx/imx8mq.c | 103 ++++++++++++++++++++++ include/dt-bindings/interconnect/imx8mq.h | 48 ++++++++++ 4 files changed, 156 insertions(+) create mode 100644 drivers/interconnect/imx/imx8mq.c create mode 100644 include/dt-bindings/interconnect/imx8mq.h
drivers/interconnect/imx/Kconfig +4 -0
@@ -5,5 +5,9 @@ config INTERCONNECT_IMX Generic interconnect driver for i.MX SOCs config INTERCONNECT_IMX8MM def_bool y depends on INTERCONNECT_IMX + +config INTERCONNECT_IMX8MQ + def_bool y + depends on INTERCONNECT_IMX
drivers/interconnect/imx/Makefile +1 -0
@@ -1,2 +1,3 @@ obj-$(CONFIG_INTERCONNECT_IMX) += imx.o obj-$(CONFIG_INTERCONNECT_IMX8MM) += imx8mm.o +obj-$(CONFIG_INTERCONNECT_IMX8MQ) += imx8mq.o
drivers/interconnect/imx/imx8mq.c new file +103 -0
103 lines not on this page · raw message
include/dt-bindings/interconnect/imx8mq.h new file +48 -0
48 lines not on this page · raw message
Signature · 1 line
2.17.1
RFC PATCH v6 7/9 interconnect: imx: Add platform driver for imx8mn
In reply to Leonard CrestezAdd a platform driver for the i.MX8MN SoC describing bus topology, based on internal documentation.
--- drivers/interconnect/imx/Kconfig | 4 + drivers/interconnect/imx/Makefile | 1 + drivers/interconnect/imx/imx8mn.c | 94 +++++++++++++++++++++++ include/dt-bindings/interconnect/imx8mn.h | 41 ++++++++++ 4 files changed, 140 insertions(+) create mode 100644 drivers/interconnect/imx/imx8mn.c create mode 100644 include/dt-bindings/interconnect/imx8mn.h
drivers/interconnect/imx/Kconfig +4 -0
@@ -6,8 +6,12 @@ config INTERCONNECT_IMX config INTERCONNECT_IMX8MM def_bool y depends on INTERCONNECT_IMX +config INTERCONNECT_IMX8MN + def_bool y + depends on INTERCONNECT_IMX + config INTERCONNECT_IMX8MQ def_bool y depends on INTERCONNECT_IMX
drivers/interconnect/imx/Makefile +1 -0
@@ -1,3 +1,4 @@ obj-$(CONFIG_INTERCONNECT_IMX) += imx.o obj-$(CONFIG_INTERCONNECT_IMX8MM) += imx8mm.o +obj-$(CONFIG_INTERCONNECT_IMX8MN) += imx8mn.o obj-$(CONFIG_INTERCONNECT_IMX8MQ) += imx8mq.o
drivers/interconnect/imx/imx8mn.c new file +94 -0
94 lines not on this page · raw message
include/dt-bindings/interconnect/imx8mn.h new file +41 -0
41 lines not on this page · raw message
Signature · 1 line
2.17.1
RFC PATCH v6 8/9 arm64: dts: imx8m: Add NOC nodes
In reply to Leonard CrestezAdd initial support for dynamic frequency scaling of main NOC.
Make DDRC the parent of the NOC (using passive governor) so that the main NOC is automatically scaled together with DDRC by default.
Support for proactive scaling via interconnect will come on top.
--- arch/arm64/boot/dts/freescale/imx8mm.dtsi | 22 ++++++++++++++++++++++ arch/arm64/boot/dts/freescale/imx8mn.dtsi | 22 ++++++++++++++++++++++ arch/arm64/boot/dts/freescale/imx8mq.dtsi | 22 ++++++++++++++++++++++ 3 files changed, 66 insertions(+)
arch/arm64/boot/dts/freescale/imx8mm.dtsi +22 -0
@@ -772,10 +772,32 @@ status = "disabled"; }; }; + noc: interconnect@32700000 { + compatible = "fsl,imx8mm-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MM_CLK_NOC>; + devfreq = <&ddrc>; + operating-points-v2 = <&noc_opp_table>; + + 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"; #address-cells = <1>; #size-cells = <1>; ranges = <0x32c00000 0x32c00000 0x400000>;
arch/arm64/boot/dts/freescale/imx8mn.dtsi +22 -0
@@ -668,10 +668,32 @@ status = "disabled"; }; }; + noc: interconnect@32700000 { + compatible = "fsl,imx8mn-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MN_CLK_NOC>; + devfreq = <&ddrc>; + operating-points-v2 = <&noc_opp_table>; + + 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 = <0x32c00000 0x400000>; #address-cells = <1>; #size-cells = <1>;
arch/arm64/boot/dts/freescale/imx8mq.dtsi +22 -0
@@ -931,10 +931,32 @@ fsl,num-rx-queues = <3>; status = "disabled"; }; }; + noc: interconnect@32700000 { + compatible = "fsl,imx8mq-noc", "fsl,imx8m-noc"; + reg = <0x32700000 0x100000>; + clocks = <&clk IMX8MQ_CLK_NOC>; + devfreq = <&ddrc>; + operating-points-v2 = <&noc_opp_table>; + + 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,imx8mq-aips-bus", "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges = <0x32c00000 0x32c00000 0x400000>;
Signature · 1 line
2.17.1
RFC PATCH v6 9/9 arm64: dts: imx8m: Add interconnect provider properties
In reply to Leonard CrestezAdd #interconnect-cells on main &noc so that it will probe the platform interconnect providers. Other devices can request icc_paths like this:
interconnects = <&noc BUS_MASTER_ID &noc BUS_SLAVE_ID>
And interconnect-node-id properties on &noc and &ddrc, the interconnect provider will scan these and make PM QoS frequency requests in response to banddwith request from other drivers.
--- arch/arm64/boot/dts/freescale/imx8mm.dtsi | 6 ++++++ arch/arm64/boot/dts/freescale/imx8mn.dtsi | 6 ++++++ arch/arm64/boot/dts/freescale/imx8mq.dtsi | 6 ++++++ 3 files changed, 18 insertions(+)
arch/arm64/boot/dts/freescale/imx8mm.dtsi +6 -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>;
@@ -777,10 +778,15 @@ noc: interconnect@32700000 { compatible = "fsl,imx8mm-noc", "fsl,imx8m-noc"; reg = <0x32700000 0x100000>; clocks = <&clk IMX8MM_CLK_NOC>; devfreq = <&ddrc>; + #interconnect-cells = <1>; + fsl,scalable-node-ids = <IMX8MM_ICN_NOC>, + <IMX8MM_ICS_DRAM>; + fsl,scalable-nodes = <&noc>, + <&ddrc>; operating-points-v2 = <&noc_opp_table>; noc_opp_table: opp-table { compatible = "operating-points-v2";
arch/arm64/boot/dts/freescale/imx8mn.dtsi +6 -0
@@ -5,10 +5,11 @@ #include <dt-bindings/clock/imx8mn-clock.h> #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/input/input.h> #include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/interconnect/imx8mn.h> #include "imx8mn-pinfunc.h" / { interrupt-parent = <&gic>;
@@ -673,10 +674,15 @@ noc: interconnect@32700000 { compatible = "fsl,imx8mn-noc", "fsl,imx8m-noc"; reg = <0x32700000 0x100000>; clocks = <&clk IMX8MN_CLK_NOC>; devfreq = <&ddrc>; + #interconnect-cells = <1>; + fsl,scalable-node-ids = <IMX8MN_ICN_NOC>, + <IMX8MN_ICS_DRAM>; + fsl,scalable-nodes = <&noc>, + <&ddrc>; operating-points-v2 = <&noc_opp_table>; noc_opp_table: opp-table { compatible = "operating-points-v2";
arch/arm64/boot/dts/freescale/imx8mq.dtsi +6 -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>;
@@ -936,10 +937,15 @@ noc: interconnect@32700000 { compatible = "fsl,imx8mq-noc", "fsl,imx8m-noc"; reg = <0x32700000 0x100000>; clocks = <&clk IMX8MQ_CLK_NOC>; devfreq = <&ddrc>; + #interconnect-cells = <1>; + fsl,scalable-node-ids = <IMX8MQ_ICN_NOC>, + <IMX8MQ_ICS_DRAM>; + fsl,scalable-nodes = <&noc>, + <&ddrc>; operating-points-v2 = <&noc_opp_table>; noc_opp_table: opp-table { compatible = "operating-points-v2";
Signature · 1 line
2.17.1
Quoted 13 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.
Quoted 8 lines
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.
This depends on other series for devfreq pm/qos and ddrc:
It took a while but all runtime dependencies are included in next-20191210 and the compile-time dependency on DEV_PM_QOS_MIN_FREQUENCY is also included in v5.5-rc1. This series is a bit old but still applies usefully so I thought I'd ask for additional comments instead of a blank resend.
Georgi: can you please take a look at this series and suggest what would make it suitable for inclusion?
Some dubious aspects:
* Existing drivers have multiple providers per SOC (for each internal NOC?) but this is a single driver for the entire SOC topology. Not clear what would be gain from this.
* NOC DT node implements devfreq (because it can be scaled) and interconnect (to avoid virtual DT nodes). Maybe the devfreq NOC scaling implementation could be moved into drivers/interconnect/imx?
It is quite different from qcom providers but hardware/firmware is also very different.
Quoted 83 lines
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://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.kernel.org%2Fcover%2F11078671%2F&data=02%7C01%7Cleonard.crestez%40nxp.com%7Cff0127cbde3e4e6f6c8508d7693eb8d5%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637093590418229667&sdata=c9xKEw9Fjlv%2FqDiWKr7zOUY5zZMWXjNyApBd94Nidnc%3D&reserved=0Changes 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://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.kernel.org%2Fcover%2F11021563%2F&data=02%7C01%7Cleonard.crestez%40nxp.com%7Cff0127cbde3e4e6f6c8508d7693eb8d5%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637093590418229667&sdata=1tEQS9BaHRTjdUYvZJ9%2FJG2BQQGl6hkbPWxiIZ811FY%3D&reserved=0Leonard Crestez (9):
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
arm64: dts: imx8m: Add interconnect provider properties.../bindings/interconnect/fsl,imx8m-noc.yaml | 104 ++++++ arch/arm64/boot/dts/freescale/imx8mm.dtsi | 28 ++ arch/arm64/boot/dts/freescale/imx8mn.dtsi | 28 ++ arch/arm64/boot/dts/freescale/imx8mq.dtsi | 28 ++ drivers/devfreq/Kconfig | 9 + drivers/devfreq/Makefile | 1 + drivers/devfreq/imx-devfreq.c | 187 +++++++++++ drivers/interconnect/Kconfig | 1 + drivers/interconnect/Makefile | 1 + drivers/interconnect/imx/Kconfig | 17 + drivers/interconnect/imx/Makefile | 4 + drivers/interconnect/imx/imx.c | 301 ++++++++++++++++++ drivers/interconnect/imx/imx.h | 60 ++++ drivers/interconnect/imx/imx8mm.c | 105 ++++++ drivers/interconnect/imx/imx8mn.c | 94 ++++++ drivers/interconnect/imx/imx8mq.c | 103 ++++++ include/dt-bindings/interconnect/imx8mm.h | 49 +++ include/dt-bindings/interconnect/imx8mn.h | 41 +++ include/dt-bindings/interconnect/imx8mq.h | 48 +++ 19 files changed, 1209 insertions(+)create mode 100644
Documentation/devicetree/bindings/interconnect/fsl,imx8m-noc.yamlcreate mode 100644drivers/devfreq/imx-devfreq.c
create mode 100644drivers/interconnect/imx/Kconfig
create mode 100644drivers/interconnect/imx/Makefile
create mode 100644drivers/interconnect/imx/imx.c
create mode 100644drivers/interconnect/imx/imx.h
create mode 100644drivers/interconnect/imx/imx8mm.c
create mode 100644drivers/interconnect/imx/imx8mn.c
create mode 100644drivers/interconnect/imx/imx8mq.c
create mode 100644include/dt-bindings/interconnect/imx8mm.h
create mode 100644include/dt-bindings/interconnect/imx8mn.h
create mode 100644include/dt-bindings/interconnect/imx8mq.h