diff options
author | Linaro CI <ci_notify@linaro.org> | 2019-01-10 11:33:54 +0000 |
---|---|---|
committer | Linaro CI <ci_notify@linaro.org> | 2019-01-10 11:33:54 +0000 |
commit | 7e255844c3141e0ea5fc5275a778679ad9692b92 (patch) | |
tree | 9735644d350d5ba7ae85b894c9fa45db27334855 | |
parent | aedc65bee231fdb79c3728b841549e135c59a69e (diff) | |
parent | 38599ae42265d076ead5e9486a13d22998b3ea49 (diff) |
Merge remote-tracking branch 'bus-scaling/bus-scaling' into integration-linux-qcomlt
# Conflicts:
# arch/arm64/boot/dts/qcom/msm8996.dtsi
30 files changed, 4422 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/interconnect/interconnect.txt b/Documentation/devicetree/bindings/interconnect/interconnect.txt new file mode 100644 index 000000000000..5a3c575b387a --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/interconnect.txt @@ -0,0 +1,60 @@ +Interconnect Provider Device Tree Bindings +========================================= + +The purpose of this document is to define a common set of generic interconnect +providers/consumers properties. + + += interconnect providers = + +The interconnect provider binding is intended to represent the interconnect +controllers in the system. Each provider registers a set of interconnect +nodes, which expose the interconnect related capabilities of the interconnect +to consumer drivers. These capabilities can be throughput, latency, priority +etc. The consumer drivers set constraints on interconnect path (or endpoints) +depending on the use case. Interconnect providers can also be interconnect +consumers, such as in the case where two network-on-chip fabrics interface +directly. + +Required properties: +- compatible : contains the interconnect provider compatible string +- #interconnect-cells : number of cells in a interconnect specifier needed to + encode the interconnect node id + +Example: + + snoc: interconnect@580000 { + compatible = "qcom,msm8916-snoc"; + #interconnect-cells = <1>; + reg = <0x580000 0x14000>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_SNOC_CLK>, + <&rpmcc RPM_SMD_SNOC_A_CLK>; + }; + + += interconnect consumers = + +The interconnect consumers are device nodes which dynamically express their +bandwidth requirements along interconnect paths they are connected to. There +can be multiple interconnect providers on a SoC and the consumer may consume +multiple paths from different providers depending on use case and the +components it has to interact with. + +Required properties: +interconnects : Pairs of phandles and interconnect provider specifier to denote + the edge source and destination ports of the interconnect path. + +Optional properties: +interconnect-names : List of interconnect path name strings sorted in the same + order as the interconnects property. Consumers drivers will use + interconnect-names to match interconnect paths with interconnect + specifier pairs. + +Example: + + sdhci@7864000 { + ... + interconnects = <&pnoc MASTER_SDCC_1 &bimc SLAVE_EBI_CH0>; + interconnect-names = "sdhc-mem"; + }; diff --git a/Documentation/devicetree/bindings/interconnect/qcom,interconnect-smd-rpm.txt b/Documentation/devicetree/bindings/interconnect/qcom,interconnect-smd-rpm.txt new file mode 100644 index 000000000000..2325167f6eaf --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/qcom,interconnect-smd-rpm.txt @@ -0,0 +1,32 @@ +Qualcomm SMD-RPM interconnect driver binding +------------------------------------------------ +The RPM (Resource Power Manager) is a dedicated hardware engine +for managing the shared SoC resources in order to keep the lowest +power profile. It communicates with other hardware subsystems via +the shared memory driver (SMD) back-end and accepts requests for +various resources. + +Required properties : +- compatible : shall contain only one of the following: + "qcom,interconnect-smd-rpm" + +Example: + smd { + compatible = "qcom,smd"; + + rpm { + interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>; + qcom,ipc = <&apcs 8 0>; + qcom,smd-edge = <15>; + + rpm_requests { + compatible = "qcom,rpm-msm8916"; + qcom,smd-channels = "rpm_requests"; + + interconnect-smd-rpm { + compatible = "qcom,interconnect-smd-rpm"; + }; + + }; + }; + }; diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8916.txt b/Documentation/devicetree/bindings/interconnect/qcom,msm8916.txt new file mode 100644 index 000000000000..5763fafee808 --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8916.txt @@ -0,0 +1,41 @@ +Qualcomm MSM8916 Network-On-Chip interconnect driver binding +---------------------------------------------------- + +Required properties : +- compatible : shall contain only one of the following: + "qcom,msm8916-bimc" + "qcom,msm8916-pnoc" + "qcom,msm8916-snoc" +- #interconnect-cells : should contain 1 +- reg : shall contain base register location and length + +Optional properties : +clocks : list of phandles and specifiers to all interconnect bus clocks +clock-names : clock names should include both "bus_clk" and "bus_a_clk" + +Examples: + + snoc: interconnect@580000 { + compatible = "qcom,msm8916-snoc"; + #interconnect-cells = <1>; + reg = <0x580000 0x14000>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_SNOC_CLK>, + <&rpmcc RPM_SMD_SNOC_A_CLK>; + }; + bimc: interconnect@400000 { + compatible = "qcom,msm8916-bimc"; + #interconnect-cells = <1>; + reg = <0x400000 0x62000>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_BIMC_CLK>, + <&rpmcc RPM_SMD_BIMC_A_CLK>; + }; + pnoc: interconnect@500000 { + compatible = "qcom,msm8916-pnoc"; + #interconnect-cells = <1>; + reg = <0x500000 0x11000>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_PCNOC_CLK>, + <&rpmcc RPM_SMD_PCNOC_A_CLK>; + }; diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8996.txt b/Documentation/devicetree/bindings/interconnect/qcom,msm8996.txt new file mode 100644 index 000000000000..26bbc564cd60 --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8996.txt @@ -0,0 +1,95 @@ +Qualcomm MSM8996 Network-On-Chip interconnect driver binding +---------------------------------------------------- + +Required properties : +- compatible : shall contain only one of the following: + "qcom,msm8996-a0noc" + "qcom,msm8996-a1noc" + "qcom,msm8996-a2noc" + "qcom,msm8996-bimc" + "qcom,msm8996-cnoc" + "qcom,msm8996-mmnoc" + "qcom,msm8996-snoc" + "qcom,msm8996-pnoc" +- #interconnect-cells : should contain 1 +- reg : shall contain base register location and length + +Optional properties : +clocks : list of phandles and specifiers to all interconnect bus clocks +clock-names : clock names should include both "bus_clk" and "bus_a_clk" + +Examples: + + bimc: bimc@400000 { + compatible = "qcom,msm8996-bimc"; + #interconnect-cells = <1>; + reg = <0x400000 0x62000>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_BIMC_CLK>, + <&rpmcc RPM_SMD_BIMC_A_CLK>; + }; + + cnoc: cnoc@500000 { + compatible = "qcom,msm8996-cnoc"; + #interconnect-cells = <1>; + reg = <0x500000 0x80>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_CNOC_CLK>, + <&rpmcc RPM_SMD_CNOC_A_CLK>; + }; + + snoc: snoc@520000 { + compatible = "qcom,msm8996-snoc"; + #interconnect-cells = <1>; + reg = <0x520000 0xa100>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_SNOC_CLK>, + <&rpmcc RPM_SMD_SNOC_A_CLK>; + }; + + a0noc: a0noc@540000 { + compatible = "qcom,msm8996-a0noc"; + #interconnect-cells = <1>; + reg = <0x540000 0x5100>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&gcc GCC_AGGRE0_SNOC_AXI_CLK>, + <&gcc GCC_AGGRE0_SNOC_AXI_CLK>; + power-domains = <&gcc AGGRE0_NOC_GDSC>; + }; + + a1noc: a1noc@560000 { + compatible = "qcom,msm8996-a1noc"; + #interconnect-cells = <1>; + reg = <0x560000 0x3100>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_AGGR1_NOC_CLK>, + <&rpmcc RPM_SMD_AGGR1_NOC_A_CLK>; + }; + + a2noc: a2noc@580000 { + compatible = "qcom,msm8996-a2noc"; + #interconnect-cells = <1>; + reg = <0x580000 0x8100>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_AGGR2_NOC_CLK>, + <&rpmcc RPM_SMD_AGGR2_NOC_A_CLK>; + }; + + mmnoc: mmnoc@5a0000 { + compatible = "qcom,msm8996-mmnoc"; + #interconnect-cells = <1>; + reg = <0x5a0000 0xb080>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_MMAXI_CLK>, + <&rpmcc RPM_SMD_MMAXI_A_CLK>; + power-domains = <&mmcc MMAGIC_BIMC_GDSC>; + }; + + pnoc: pnoc@5c0000 { + compatible = "qcom,msm8996-pnoc"; + #interconnect-cells = <1>; + reg = <0x5c0000 0x2480>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_PCNOC_CLK>, + <&rpmcc RPM_SMD_PCNOC_A_CLK>; + }; diff --git a/Documentation/devicetree/bindings/interconnect/qcom,sdm845.txt b/Documentation/devicetree/bindings/interconnect/qcom,sdm845.txt new file mode 100644 index 000000000000..5c4f1d911630 --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/qcom,sdm845.txt @@ -0,0 +1,24 @@ +Qualcomm SDM845 Network-On-Chip interconnect driver binding +----------------------------------------------------------- + +SDM845 interconnect providers support system bandwidth requirements through +RPMh hardware accelerators known as Bus Clock Manager (BCM). The provider is +able to communicate with the BCM through the Resource State Coordinator (RSC) +associated with each execution environment. Provider nodes must reside within +an RPMh device node pertaining to their RSC and each provider maps to a single +RPMh resource. + +Required properties : +- compatible : shall contain only one of the following: + "qcom,sdm845-rsc-hlos" +- #interconnect-cells : should contain 1 + +Examples: + +apps_rsc: rsc { + rsc_hlos: interconnect { + compatible = "qcom,sdm845-rsc-hlos"; + #interconnect-cells = <1>; + }; +}; + diff --git a/Documentation/interconnect/interconnect.rst b/Documentation/interconnect/interconnect.rst new file mode 100644 index 000000000000..b8107dcc4cd3 --- /dev/null +++ b/Documentation/interconnect/interconnect.rst @@ -0,0 +1,94 @@ +.. SPDX-License-Identifier: GPL-2.0 + +===================================== +GENERIC SYSTEM INTERCONNECT SUBSYSTEM +===================================== + +Introduction +------------ + +This framework is designed to provide a standard kernel interface to control +the settings of the interconnects on an SoC. These settings can be throughput, +latency and priority between multiple interconnected devices or functional +blocks. This can be controlled dynamically in order to save power or provide +maximum performance. + +The interconnect bus is hardware with configurable parameters, which can be +set on a data path according to the requests received from various drivers. +An example of interconnect buses are the interconnects between various +components or functional blocks in chipsets. There can be multiple interconnects +on an SoC that can be multi-tiered. + +Below is a simplified diagram of a real-world SoC interconnect bus topology. + +:: + + +----------------+ +----------------+ + | HW Accelerator |--->| M NoC |<---------------+ + +----------------+ +----------------+ | + | | +------------+ + +-----+ +-------------+ V +------+ | | + | DDR | | +--------+ | PCIe | | | + +-----+ | | Slaves | +------+ | | + ^ ^ | +--------+ | | C NoC | + | | V V | | + +------------------+ +------------------------+ | | +-----+ + | |-->| |-->| |-->| CPU | + | |-->| |<--| | +-----+ + | Mem NoC | | S NoC | +------------+ + | |<--| |---------+ | + | |<--| |<------+ | | +--------+ + +------------------+ +------------------------+ | | +-->| Slaves | + ^ ^ ^ ^ ^ | | +--------+ + | | | | | | V + +------+ | +-----+ +-----+ +---------+ +----------------+ +--------+ + | CPUs | | | GPU | | DSP | | Masters |-->| P NoC |-->| Slaves | + +------+ | +-----+ +-----+ +---------+ +----------------+ +--------+ + | + +-------+ + | Modem | + +-------+ + +Terminology +----------- + +Interconnect provider is the software definition of the interconnect hardware. +The interconnect providers on the above diagram are M NoC, S NoC, C NoC, P NoC +and Mem NoC. + +Interconnect node is the software definition of the interconnect hardware +port. Each interconnect provider consists of multiple interconnect nodes, +which are connected to other SoC components including other interconnect +providers. The point on the diagram where the CPUs connect to the memory is +called an interconnect node, which belongs to the Mem NoC interconnect provider. + +Interconnect endpoints are the first or the last element of the path. Every +endpoint is a node, but not every node is an endpoint. + +Interconnect path is everything between two endpoints including all the nodes +that have to be traversed to reach from a source to destination node. It may +include multiple master-slave pairs across several interconnect providers. + +Interconnect consumers are the entities which make use of the data paths exposed +by the providers. The consumers send requests to providers requesting various +throughput, latency and priority. Usually the consumers are device drivers, that +send request based on their needs. An example for a consumer is a video decoder +that supports various formats and image sizes. + +Interconnect providers +---------------------- + +Interconnect provider is an entity that implements methods to initialize and +configure interconnect bus hardware. The interconnect provider drivers should +be registered with the interconnect provider core. + +.. kernel-doc:: include/linux/interconnect-provider.h + +Interconnect consumers +---------------------- + +Interconnect consumers are the clients which use the interconnect APIs to +get paths between endpoints and set their bandwidth/latency/QoS requirements +for these interconnect paths. + +.. kernel-doc:: include/linux/interconnect.h diff --git a/MAINTAINERS b/MAINTAINERS index 32d444476a90..0a78b8e1e2c4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7880,6 +7880,16 @@ L: linux-gpio@vger.kernel.org S: Maintained F: drivers/gpio/gpio-intel-mid.c +INTERCONNECT API +M: Georgi Djakov <georgi.djakov@linaro.org> +S: Maintained +F: Documentation/interconnect/ +F: Documentation/devicetree/bindings/interconnect/ +F: drivers/interconnect/ +F: include/dt-bindings/interconnect/ +F: include/linux/interconnect-provider.h +F: include/linux/interconnect.h + INVENSENSE MPU-3050 GYROSCOPE DRIVER M: Linus Walleij <linus.walleij@linaro.org> L: linux-iio@vger.kernel.org diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index c5348c3da5a2..1190f529a076 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -11,6 +11,7 @@ * GNU General Public License for more details. */ +#include <dt-bindings/interconnect/qcom,msm8916.h> #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/clock/qcom,gcc-msm8916.h> #include <dt-bindings/reset/qcom,gcc-msm8916.h> @@ -1525,6 +1526,42 @@ #size-cells = <0>; }; }; + + bimc: interconnect@400000 { + compatible = "qcom,msm8916-bimc"; + #interconnect-cells = <1>; + reg = <0x400000 0x62000>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_BIMC_CLK>, + <&rpmcc RPM_SMD_BIMC_A_CLK>; + base-offset = <0>; + qos-offset = <0>; + status = "okay"; + }; + + pnoc: interconnect@500000 { + compatible = "qcom,msm8916-pnoc"; + #interconnect-cells = <1>; + reg = <0x500000 0x11000>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_PCNOC_CLK>, + <&rpmcc RPM_SMD_PCNOC_A_CLK>; + base-offset = <0x7000>; + qos-offset = <0x1000>; + status = "okay"; + }; + + snoc: interconnect@580000 { + compatible = "qcom,msm8916-snoc"; + #interconnect-cells = <1>; + reg = <0x580000 0x14000>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_SNOC_CLK>, + <&rpmcc RPM_SMD_SNOC_A_CLK>; + base-offset = <0x7000>; + qos-offset = <0x1000>; + status = "okay"; + }; }; smd { @@ -1544,6 +1581,10 @@ #clock-cells = <1>; }; + interconnect-smd-rpm { + compatible = "qcom,interconnect-smd-rpm"; + }; + smd_rpm_regulators: pm8916-regulators { compatible = "qcom,rpm-pm8916-regulators"; diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index 7a844a474ed1..0979a17d6a92 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -3,6 +3,7 @@ * Copyright (c) 2014-2015, 2018 The Linux Foundation. All rights reserved. */ +#include <dt-bindings/interconnect/qcom,msm8996.h> #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/clock/qcom,gcc-msm8996.h> #include <dt-bindings/clock/qcom,mmcc-msm8996.h> @@ -811,6 +812,10 @@ #clock-cells = <1>; }; + interconnect-smd-rpm { + compatible = "qcom,interconnect-smd-rpm"; + }; + pm8994-regulators { compatible = "qcom,rpm-pm8994-regulators"; @@ -2133,6 +2138,108 @@ qcom,remote-pid = <1>; }; }; + + bimc: bimc@400000 { + compatible = "qcom,msm8996-bimc"; + #interconnect-cells = <1>; + reg = <0x400000 0x62000>; + type = <2>; + base-offset = <0x8000>; + qos-offset = <0x4000>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_BIMC_CLK>, + <&rpmcc RPM_SMD_BIMC_A_CLK>; + status = "okay"; + }; + + cnoc: cnoc@500000 { + compatible = "qcom,msm8996-cnoc"; + #interconnect-cells = <1>; + reg = <0x500000 0x80>; + type = <1>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_CNOC_CLK>, + <&rpmcc RPM_SMD_CNOC_A_CLK>; + status = "okay"; + }; + + snoc: snoc@520000 { + compatible = "qcom,msm8996-snoc"; + #interconnect-cells = <1>; + reg = <0x520000 0xa100>; + type = <1>; + base-offset = <0x4000>; + qos-offset = <0x1000>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_SNOC_CLK>, + <&rpmcc RPM_SMD_SNOC_A_CLK>; + status = "okay"; + }; + + a0noc: a0noc@540000 { + compatible = "qcom,msm8996-a0noc"; + #interconnect-cells = <1>; + reg = <0x540000 0x5100>; + type = <1>; + qcom,base-offset = <0x3000>; + qos-offset = <0x1000>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&gcc GCC_AGGRE0_SNOC_AXI_CLK>, + <&gcc GCC_AGGRE0_SNOC_AXI_CLK>; + power-domains = <&gcc AGGRE0_NOC_GDSC>; + status = "okay"; + }; + + a1noc: a1noc@560000 { + compatible = "qcom,msm8996-a1noc"; + #interconnect-cells = <1>; + reg = <0x560000 0x3100>; + type = <1>; + base-offset = <0x2000>; + qos-offset = <0x1000>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_AGGR1_NOC_CLK>, + <&rpmcc RPM_SMD_AGGR1_NOC_A_CLK>; + status = "okay"; + }; + + a2noc: a2noc@580000 { + compatible = "qcom,msm8996-a2noc"; + #interconnect-cells = <1>; + reg = <0x580000 0x8100>; + base-offset = <0x3000>; + qos-offset = <0x1000>; + type = <1>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_AGGR2_NOC_CLK>, + <&rpmcc RPM_SMD_AGGR2_NOC_A_CLK>; + status = "okay"; + }; + + mmnoc: mmnoc@5a0000 { + compatible = "qcom,msm8996-mmnoc"; + #interconnect-cells = <1>; + reg = <0x5a0000 0xb080>; + type = <1>; + base-offset = <0x4000>; + qos-offset = <0x1000>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_MMAXI_CLK>, + <&rpmcc RPM_SMD_MMAXI_A_CLK>; + power-domains = <&mmcc MMAGIC_BIMC_GDSC>; + status = "okay"; + }; + + pnoc: pnoc@5c0000 { + compatible = "qcom,msm8996-pnoc"; + #interconnect-cells = <1>; + reg = <0x5c0000 0x2480>; + type = <1>; + clock-names = "bus_clk", "bus_a_clk"; + clocks = <&rpmcc RPM_SMD_PCNOC_CLK>, + <&rpmcc RPM_SMD_PCNOC_A_CLK>; + status = "okay"; + }; }; sound: sound { diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index 51c3064a0f05..edae2933dd80 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -1819,6 +1819,11 @@ compatible = "qcom,sdm845-rpmh-clk"; #clock-cells = <1>; }; + + rsc_hlos: interconnect { + compatible = "qcom,sdm845-rsc-hlos"; + #interconnect-cells = <1>; + }; }; intc: interrupt-controller@17a00000 { diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 3a18db960203..0f4e84ba7e3f 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -745,6 +745,11 @@ CONFIG_UNIPHIER_EFUSE=y CONFIG_MESON_EFUSE=m CONFIG_TEE=y CONFIG_OPTEE=y +CONFIG_INTERCONNECT=y +CONFIG_INTERCONNECT_QCOM=y +CONFIG_INTERCONNECT_QCOM_MSM8916=y +CONFIG_INTERCONNECT_QCOM_MSM8996=y +CONFIG_INTERCONNECT_QCOM_SDM845=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y CONFIG_EXT4_FS_POSIX_ACL=y diff --git a/drivers/Kconfig b/drivers/Kconfig index 4f9f99057ff8..45f9decb9848 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -228,4 +228,6 @@ source "drivers/siox/Kconfig" source "drivers/slimbus/Kconfig" +source "drivers/interconnect/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index e1ce029d28fd..bb15b9d0e793 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -186,3 +186,4 @@ obj-$(CONFIG_MULTIPLEXER) += mux/ obj-$(CONFIG_UNISYS_VISORBUS) += visorbus/ obj-$(CONFIG_SIOX) += siox/ obj-$(CONFIG_GNSS) += gnss/ +obj-$(CONFIG_INTERCONNECT) += interconnect/ diff --git a/drivers/interconnect/Kconfig b/drivers/interconnect/Kconfig new file mode 100644 index 000000000000..07a8276fa35a --- /dev/null +++ b/drivers/interconnect/Kconfig @@ -0,0 +1,15 @@ +menuconfig INTERCONNECT + tristate "On-Chip Interconnect management support" + help + Support for management of the on-chip interconnects. + + This framework is designed to provide a generic interface for + managing the interconnects in a SoC. + + If unsure, say no. + +if INTERCONNECT + +source "drivers/interconnect/qcom/Kconfig" + +endif diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile new file mode 100644 index 000000000000..28f2ab0824d5 --- /dev/null +++ b/drivers/interconnect/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 + +icc-core-objs := core.o + +obj-$(CONFIG_INTERCONNECT) += icc-core.o +obj-$(CONFIG_INTERCONNECT_QCOM) += qcom/ diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c new file mode 100644 index 000000000000..64bc25f3f19b --- /dev/null +++ b/drivers/interconnect/core.c @@ -0,0 +1,806 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Interconnect framework core driver + * + * Copyright (c) 2018, Linaro Ltd. + * Author: Georgi Djakov <georgi.djakov@linaro.org> + */ + +#include <linux/debugfs.h> +#include <linux/device.h> +#include <linux/idr.h> +#include <linux/init.h> +#include <linux/interconnect.h> +#include <linux/interconnect-provider.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/slab.h> +#include <linux/of.h> +#include <linux/overflow.h> +#include <linux/uaccess.h> + +static DEFINE_IDR(icc_idr); +static LIST_HEAD(icc_providers); +static DEFINE_MUTEX(icc_lock); +static struct dentry *icc_debugfs_dir; + +/** + * struct icc_req - constraints that are attached to each node + * @req_node: entry in list of requests for the particular @node + * @node: the interconnect node to which this constraint applies + * @dev: reference to the device that sets the constraints + * @avg_bw: an integer describing the average bandwidth in kBps + * @peak_bw: an integer describing the peak bandwidth in kBps + */ +struct icc_req { + struct hlist_node req_node; + struct icc_node *node; + struct device *dev; + u32 avg_bw; + u32 peak_bw; +}; + +/** + * struct icc_path - interconnect path structure + * @tag: path tag + * @num_nodes: number of hops (nodes) + * @reqs: array of the requests applicable to this path of nodes + */ +struct icc_path { + u8 tag; + size_t num_nodes; + struct icc_req reqs[]; +}; + +static void icc_summary_show_one(struct seq_file *s, struct icc_node *n) +{ + if (!n) + return; + + seq_printf(s, "%-30s %12u %12u\n", + n->name, n->avg_bw, n->peak_bw); +} + +static int icc_summary_show(struct seq_file *s, void *data) +{ + struct icc_provider *provider; + + seq_puts(s, " node avg peak\n"); + seq_puts(s, "--------------------------------------------------------\n"); + + mutex_lock(&icc_lock); + + list_for_each_entry(provider, &icc_providers, provider_list) { + struct icc_node *n; + + list_for_each_entry(n, &provider->nodes, node_list) { + struct icc_req *r; + + icc_summary_show_one(s, n); + hlist_for_each_entry(r, &n->req_list, req_node) { + if (!r->dev) + continue; + + seq_printf(s, " %-26s %12u %12u\n", + dev_name(r->dev), r->avg_bw, + r->peak_bw); + } + } + } + + mutex_unlock(&icc_lock); + + return 0; +} + +static int icc_summary_open(struct inode *inode, struct file *file) +{ + return single_open(file, icc_summary_show, inode->i_private); +} + +static const struct file_operations icc_summary_fops = { + .open = icc_summary_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static struct icc_node *node_find(const int id) +{ + return idr_find(&icc_idr, id); +} + +static struct icc_path *path_init(struct device *dev, struct icc_node *dst, + ssize_t num_nodes) +{ + struct icc_node *node = dst; + struct icc_path *path; + int i; + + path = kzalloc(struct_size(path, reqs, num_nodes), GFP_KERNEL); + if (!path) + return ERR_PTR(-ENOMEM); + + path->num_nodes = num_nodes; + + for (i = num_nodes - 1; i >= 0; i--) { + node->provider->users++; + hlist_add_head(&path->reqs[i].req_node, &node->req_list); + path->reqs[i].node = node; + path->reqs[i].dev = dev; + /* reference to previous node was saved during path traversal */ + node = node->reverse; + } + + return path; +} + +static struct icc_path *path_find(struct device *dev, struct icc_node *src, + struct icc_node *dst) +{ + struct icc_path *path = ERR_PTR(-EPROBE_DEFER); + struct icc_node *n, *node = NULL; + struct list_head traverse_list; + struct list_head edge_list; + struct list_head visited_list; + size_t i, depth = 1; + bool found = false; + + INIT_LIST_HEAD(&traverse_list); + INIT_LIST_HEAD(&edge_list); + INIT_LIST_HEAD(&visited_list); + + list_add(&src->search_list, &traverse_list); + src->reverse = NULL; + + do { + list_for_each_entry_safe(node, n, &traverse_list, search_list) { + if (node == dst) { + found = true; + list_splice_init(&edge_list, &visited_list); + list_splice_init(&traverse_list, &visited_list); + break; + } + for (i = 0; i < node->num_links; i++) { + struct icc_node *tmp = node->links[i]; + + if (!tmp) { + path = ERR_PTR(-ENOENT); + goto out; + } + + if (tmp->is_traversed) + continue; + + tmp->is_traversed = true; + tmp->reverse = node; + list_add_tail(&tmp->search_list, &edge_list); + } + } + + if (found) + break; + + list_splice_init(&traverse_list, &visited_list); + list_splice_init(&edge_list, &traverse_list); + + /* count the hops including the source */ + depth++; + + } while (!list_empty(&traverse_list)); + +out: + + /* reset the traversed state */ + list_for_each_entry_reverse(n, &visited_list, search_list) + n->is_traversed = false; + + if (found) + path = path_init(dev, dst, depth); + + return path; +} + +/* + * We want the path to honor all bandwidth requests, so the average and peak + * bandwidth requirements from each consumer are aggregated at each node. + * The aggregation is platform specific, so each platform can customize it by + * implementing its own aggregate() function. + */ + +static int aggregate_requests(struct icc_node *node, u8 tag) +{ + struct icc_provider *p = node->provider; + struct icc_req *r; + + node->avg_bw = 0; + node->peak_bw = 0; + + hlist_for_each_entry(r, &node->req_list, req_node) + p->aggregate(node, tag, r->avg_bw, r->peak_bw, + &node->avg_bw, &node->peak_bw); + + return 0; +} + +static int apply_constraints(struct icc_path *path) +{ + struct icc_node *next, *prev = NULL; + int ret = -EINVAL; + int i; + + for (i = 0; i < path->num_nodes; i++) { + next = path->reqs[i].node; + + /* + * Both endpoints should be valid master-slave pairs of the + * same interconnect provider that will be configured. + */ + if (!prev || next->provider != prev->provider) { + prev = next; + continue; + } + + /* set the constraints */ + ret = next->provider->set(prev, next); + if (ret) + goto out; + + prev = next; + } +out: + return ret; +} + +/* of_icc_xlate_onecell() - Translate function using a single index. + * @spec: OF phandle args to map into an interconnect node. + * @data: private data (pointer to struct icc_onecell_data) + * + * This is a generic translate function that can be used to model simple + * interconnect providers that have one device tree node and provide + * multiple interconnect nodes. A single cell is used as an index into + * an array of icc nodes specified in the icc_onecell_data struct when + * registering the provider. + */ +struct icc_node *of_icc_xlate_onecell(struct of_phandle_args *spec, + void *data) +{ + struct icc_onecell_data *icc_data = data; + unsigned int idx = spec->args[0]; + + if (idx >= icc_data->num_nodes) { + pr_err("%s: invalid index %u\n", __func__, idx); + return ERR_PTR(-EINVAL); + } + + return icc_data->nodes[idx]; +} +EXPORT_SYMBOL_GPL(of_icc_xlate_onecell); + +/** + * of_icc_get_from_provider() - Look-up interconnect node + * @spec: OF phandle args to use for look-up + * + * Looks for interconnect provider under the node specified by @spec and if + * found, uses xlate function of the provider to map phandle args to node. + * + * Returns a valid pointer to struct icc_node on success or ERR_PTR() + * on failure. + */ +static struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec) +{ + struct icc_node *node = ERR_PTR(-EPROBE_DEFER); + struct icc_provider *provider; + + if (!spec || spec->args_count != 1) + return ERR_PTR(-EINVAL); + + mutex_lock(&icc_lock); + list_for_each_entry(provider, &icc_providers, provider_list) { + if (provider->dev->of_node == spec->np) + node = provider->xlate(spec, provider->data); + if (!IS_ERR(node)) + break; + } + mutex_unlock(&icc_lock); + + return node; +} + +/** + * of_icc_get() - get a path handle from a DT node based on name + * @dev: device pointer for the consumer device + * @name: interconnect path name + * + * This function will search for a path between two endpoints and return an + * icc_path handle on success. Use icc_put() to release constraints when they + * are not needed anymore. + * If the interconnect API is disabled, NULL is returned and the consumer + * drivers will still build. Drivers are free to handle this specifically, + * but they don't have to. + * + * Return: icc_path pointer on success or ERR_PTR() on error. NULL is returned + * when the API is disabled or the "interconnects" DT property is missing. + */ +struct icc_path *of_icc_get(struct device *dev, const char *name) +{ + struct icc_path *path = ERR_PTR(-EPROBE_DEFER); + struct icc_node *src_node, *dst_node; + struct device_node *np = NULL; + struct of_phandle_args src_args, dst_args; + int idx = 0; + int ret; + + if (!dev || !dev->of_node) + return ERR_PTR(-ENODEV); + + np = dev->of_node; + + /* + * When the consumer DT node do not have "interconnects" property + * return a NULL path to skip setting constraints. + */ + if (!of_find_property(np, "interconnects", NULL)) + return NULL; + + /* + * We use a combination of phandle and specifier for endpoint. For now + * lets support only global ids and extend this in the future if needed + * without breaking DT compatibility. + */ + if (name) { + idx = of_property_match_string(np, "interconnect-names", name); + if (idx < 0) + return ERR_PTR(idx); + } + + ret = of_parse_phandle_with_args(np, "interconnects", + "#interconnect-cells", idx * 2, + &src_args); + if (ret) + return ERR_PTR(ret); + + of_node_put(src_args.np); + + ret = of_parse_phandle_with_args(np, "interconnects", + "#interconnect-cells", idx * 2 + 1, + &dst_args); + if (ret) + return ERR_PTR(ret); + + of_node_put(dst_args.np); + + src_node = of_icc_get_from_provider(&src_args); + + if (IS_ERR(src_node)) { + if (PTR_ERR(src_node) != -EPROBE_DEFER) + dev_err(dev, "error finding src node: %ld\n", + PTR_ERR(src_node)); + return ERR_CAST(src_node); + } + + dst_node = of_icc_get_from_provider(&dst_args); + + if (IS_ERR(dst_node)) { + if (PTR_ERR(dst_node) != -EPROBE_DEFER) + dev_err(dev, "error finding dst node: %ld\n", + PTR_ERR(dst_node)); + return ERR_CAST(dst_node); + } + + mutex_lock(&icc_lock); + path = path_find(dev, src_node, dst_node); + if (IS_ERR(path)) + dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path)); + mutex_unlock(&icc_lock); + + return path; +} +EXPORT_SYMBOL_GPL(of_icc_get); + +/** + * icc_set_tag() - set tag on a path + * @path: the path we want to tag + * @tag: the tag value + * + * This function allows consumers to append a tag to the path, so that a + * different aggregation could be done based on this tag. + */ +void icc_set_tag(struct icc_path *path, u8 tag) +{ + if (!path) + return; + + path->tag = tag; +} +EXPORT_SYMBOL_GPL(icc_set_tag); + +/** + * icc_set() - set constraints on an interconnect path between two endpoints + * @path: reference to the path returned by icc_get() + * @avg_bw: average bandwidth in kilobytes per second + * @peak_bw: peak bandwidth in kilobytes per second + * + * This function is used by an interconnect consumer to express its own needs + * in terms of bandwidth for a previously requested path between two endpoints. + * The requests are aggregated and each node is updated accordingly. The entire + * path is locked by a mutex to ensure that the set() is completed. + * The @path can be NULL when the "interconnects" DT properties is missing, + * which will mean that no constraints will be set. + * + * Returns 0 on success, or an appropriate error code otherwise. + */ +int icc_set(struct icc_path *path, u32 avg_bw, u32 peak_bw) +{ + struct icc_node *node; + size_t i; + int ret; + + if (!path) + return 0; + + mutex_lock(&icc_lock); + + for (i = 0; i < path->num_nodes; i++) { + node = path->reqs[i].node; + + /* update the consumer request for this path */ + path->reqs[i].avg_bw = avg_bw; + path->reqs[i].peak_bw = peak_bw; + + /* aggregate requests for this node */ + aggregate_requests(node, path->tag); + } + + ret = apply_constraints(path); + if (ret) + pr_debug("interconnect: error applying constraints (%d)\n", + ret); + + mutex_unlock(&icc_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(icc_set); + +/** + * icc_get() - return a handle for path between two endpoints + * @dev: the device requesting the path + * @src_id: source device port id + * @dst_id: destination device port id + * + * This function will search for a path between two endpoints and return an + * icc_path handle on success. Use icc_put() to release + * constraints when they are not needed anymore. + * If the interconnect API is disabled, NULL is returned and the consumer + * drivers will still build. Drivers are free to handle this specifically, + * but they don't have to. + * + * Return: icc_path pointer on success, ERR_PTR() on error or NULL if the + * interconnect API is disabled. + */ +struct icc_path *icc_get(struct device *dev, const int src_id, const int dst_id) +{ + struct icc_node *src, *dst; + struct icc_path *path = ERR_PTR(-EPROBE_DEFER); + + mutex_lock(&icc_lock); + + src = node_find(src_id); + if (!src) + goto out; + + dst = node_find(dst_id); + if (!dst) + goto out; + + path = path_find(dev, src, dst); + if (IS_ERR(path)) + dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path)); + +out: + mutex_unlock(&icc_lock); + return path; +} +EXPORT_SYMBOL_GPL(icc_get); + +/** + * icc_put() - release the reference to the icc_path + * @path: interconnect path + * + * Use this function to release the constraints on a path when the path is + * no longer needed. The constraints will be re-aggregated. + */ +void icc_put(struct icc_path *path) +{ + struct icc_node *node; + size_t i; + int ret; + + if (!path || WARN_ON(IS_ERR(path))) + return; + + ret = icc_set(path, 0, 0); + if (ret) + pr_err("%s: error (%d)\n", __func__, ret); + + mutex_lock(&icc_lock); + for (i = 0; i < path->num_nodes; i++) { + node = path->reqs[i].node; + hlist_del(&path->reqs[i].req_node); + if (!WARN_ON(!node->provider->users)) + node->provider->users--; + } + mutex_unlock(&icc_lock); + + kfree(path); +} +EXPORT_SYMBOL_GPL(icc_put); + +static struct icc_node *icc_node_create_nolock(int id) +{ + struct icc_node *node; + + /* check if node already exists */ + node = node_find(id); + if (node) + return node; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return ERR_PTR(-ENOMEM); + + id = idr_alloc(&icc_idr, node, id, id + 1, GFP_KERNEL); + if (id < 0) { + WARN(1, "%s: couldn't get idr\n", __func__); + kfree(node); + return ERR_PTR(id); + } + + node->id = id; + + return node; +} + +/** + * icc_node_create() - create a node + * @id: node id + * + * Return: icc_node pointer on success, or ERR_PTR() on error + */ +struct icc_node *icc_node_create(int id) +{ + struct icc_node *node; + + mutex_lock(&icc_lock); + + node = icc_node_create_nolock(id); + + mutex_unlock(&icc_lock); + + return node; +} +EXPORT_SYMBOL_GPL(icc_node_create); + +/** + * icc_node_destroy() - destroy a node + * @id: node id + */ +void icc_node_destroy(int id) +{ + struct icc_node *node; + + mutex_lock(&icc_lock); + + node = node_find(id); + if (node) { + idr_remove(&icc_idr, node->id); + WARN_ON(!hlist_empty(&node->req_list)); + } + + mutex_unlock(&icc_lock); + + kfree(node); +} +EXPORT_SYMBOL_GPL(icc_node_destroy); + +/** + * icc_link_create() - create a link between two nodes + * @node: source node id + * @dst_id: destination node id + * + * Create a link between two nodes. The nodes might belong to different + * interconnect providers and the @dst_id node might not exist (if the + * provider driver has not probed yet). So just create the @dst_id node + * and when the actual provider driver is probed, the rest of the node + * data is filled. + * + * Return: 0 on success, or an error code otherwise + */ +int icc_link_create(struct icc_node *node, const int dst_id) +{ + struct icc_node *dst; + struct icc_node **new; + int ret = 0; + + if (!node->provider) + return -EINVAL; + + mutex_lock(&icc_lock); + + dst = node_find(dst_id); + if (!dst) { + dst = icc_node_create_nolock(dst_id); + + if (IS_ERR(dst)) { + ret = PTR_ERR(dst); + goto out; + } + } + + new = krealloc(node->links, + (node->num_links + 1) * sizeof(*node->links), + GFP_KERNEL); + if (!new) { + ret = -ENOMEM; + goto out; + } + + node->links = new; + node->links[node->num_links++] = dst; + +out: + mutex_unlock(&icc_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(icc_link_create); + +/** + * icc_link_destroy() - destroy a link between two nodes + * @src: pointer to source node + * @dst: pointer to destination node + * + * Return: 0 on success, or an error code otherwise + */ +int icc_link_destroy(struct icc_node *src, struct icc_node *dst) +{ + struct icc_node **new; + size_t slot; + int ret = 0; + + if (IS_ERR_OR_NULL(src)) + return -EINVAL; + + if (IS_ERR_OR_NULL(dst)) + return -EINVAL; + + mutex_lock(&icc_lock); + + for (slot = 0; slot < src->num_links; slot++) + if (src->links[slot] == dst) + break; + + if (WARN_ON(slot == src->num_links)) { + ret = -ENXIO; + goto out; + } + + src->links[slot] = src->links[--src->num_links]; + + new = krealloc(src->links, src->num_links * sizeof(*src->links), + GFP_KERNEL); + if (new) + src->links = new; + +out: + mutex_unlock(&icc_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(icc_link_destroy); + +/** + * icc_node_add() - add interconnect node to interconnect provider + * @node: pointer to the interconnect node + * @provider: pointer to the interconnect provider + */ +void icc_node_add(struct icc_node *node, struct icc_provider *provider) +{ + mutex_lock(&icc_lock); + + node->provider = provider; + list_add_tail(&node->node_list, &provider->nodes); + + mutex_unlock(&icc_lock); +} +EXPORT_SYMBOL_GPL(icc_node_add); + +/** + * icc_node_del() - delete interconnect node from interconnect provider + * @node: pointer to the interconnect node + */ +void icc_node_del(struct icc_node *node) +{ + mutex_lock(&icc_lock); + + list_del(&node->node_list); + + mutex_unlock(&icc_lock); +} +EXPORT_SYMBOL_GPL(icc_node_del); + +/** + * icc_provider_add() - add a new interconnect provider + * @provider: the interconnect provider that will be added into topology + * + * Return: 0 on success, or an error code otherwise + */ +int icc_provider_add(struct icc_provider *provider) +{ + if (WARN_ON(!provider->set)) + return -EINVAL; + if (WARN_ON(!provider->xlate)) + return -EINVAL; + + mutex_lock(&icc_lock); + + INIT_LIST_HEAD(&provider->nodes); + list_add_tail(&provider->provider_list, &icc_providers); + + mutex_unlock(&icc_lock); + + dev_dbg(provider->dev, "interconnect provider added to topology\n"); + + return 0; +} +EXPORT_SYMBOL_GPL(icc_provider_add); + +/** + * icc_provider_del() - delete previously added interconnect provider + * @provider: the interconnect provider that will be removed from topology + * + * Return: 0 on success, or an error code otherwise + */ +int icc_provider_del(struct icc_provider *provider) +{ + mutex_lock(&icc_lock); + if (provider->users) { + pr_warn("interconnect provider still has %d users\n", + provider->users); + mutex_unlock(&icc_lock); + return -EBUSY; + } + + if (!list_empty(&provider->nodes)) { + pr_warn("interconnect provider still has nodes\n"); + mutex_unlock(&icc_lock); + return -EBUSY; + } + + list_del(&provider->provider_list); + mutex_unlock(&icc_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(icc_provider_del); + +static int __init icc_init(void) +{ + icc_debugfs_dir = debugfs_create_dir("interconnect", NULL); + debugfs_create_file("interconnect_summary", 0444, + icc_debugfs_dir, NULL, &icc_summary_fops); + return 0; +} + +static void __exit icc_exit(void) +{ + debugfs_remove_recursive(icc_debugfs_dir); +} +module_init(icc_init); +module_exit(icc_exit); + +MODULE_AUTHOR("Georgi Djakov <georgi.djakov@linaro.org>"); +MODULE_DESCRIPTION("Interconnect Driver Core"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig new file mode 100644 index 000000000000..2334da717c4c --- /dev/null +++ b/drivers/interconnect/qcom/Kconfig @@ -0,0 +1,39 @@ +config INTERCONNECT_QCOM + bool "Qualcomm Network-on-Chip interconnect drivers" + depends on ARCH_QCOM + help + Support for Qualcomm's Network-on-Chip interconnect hardware. + +config INTERCONNECT_QCOM_SDM845 + tristate "Qualcomm SDM845 interconnect driver" + depends on INTERCONNECT_QCOM + depends on (QCOM_RPMH && QCOM_COMMAND_DB && OF) || COMPILE_TEST + help + This is a driver for the Qualcomm Network-on-Chip on sdm845-based + platforms. + +config INTERCONNECT_QCOM_SMD_RPM + tristate "Qualcomm SMD RPM interconnect driver" + depends on INTERCONNECT_QCOM + depends on QCOM_SMD_RPM + help + This is a driver for communicating interconnect related configuration + details with a remote processor (RPM) on Qualcomm platforms. + +config INTERCONNECT_QCOM_MSM8916 + tristate "Qualcomm MSM8916 interconnect driver" + depends on INTERCONNECT_QCOM + depends on QCOM_SMD_RPM + select INTERCONNECT_QCOM_SMD_RPM + help + This is a driver for the Qualcomm Network-on-Chip on msm8916-based + platforms. + +config INTERCONNECT_QCOM_MSM8996 + tristate "Qualcomm MSM8996 interconnect driver" + depends on INTERCONNECT_QCOM + depends on QCOM_SMD_RPM + select INTERCONNECT_QCOM_SMD_RPM + help + This is a driver for the Qualcomm Network-on-Chip on msm8996-based + platforms. diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile new file mode 100644 index 000000000000..dc2f8b99a958 --- /dev/null +++ b/drivers/interconnect/qcom/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 + +qnoc-sdm845-objs := sdm845.o +qnoc-smd-rpm-objs := smd-rpm.o +qnoc-msm8916-objs := msm8916.o +qnoc-msm8996-objs := msm8996.o + +obj-$(CONFIG_INTERCONNECT_QCOM_SDM845) += qnoc-sdm845.o +obj-$(CONFIG_INTERCONNECT_QCOM_SMD_RPM) += qnoc-smd-rpm.o +obj-$(CONFIG_INTERCONNECT_QCOM_MSM8916) += qnoc-msm8916.o +obj-$(CONFIG_INTERCONNECT_QCOM_MSM8996) += qnoc-msm8996.o diff --git a/drivers/interconnect/qcom/msm8916.c b/drivers/interconnect/qcom/msm8916.c new file mode 100644 index 000000000000..43963e978f5d --- /dev/null +++ b/drivers/interconnect/qcom/msm8916.c @@ -0,0 +1,517 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Linaro Ltd + * Author: Georgi Djakov <georgi.djakov@linaro.org> + */ + +#include <dt-bindings/interconnect/qcom,msm8916.h> +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/interconnect-provider.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include "msm8916_ids.h" +#include "smd-rpm.h" + +#define RPM_BUS_MASTER_REQ 0x73616d62 +#define RPM_BUS_SLAVE_REQ 0x766c7362 + +#define to_qcom_provider(_provider) \ + container_of(_provider, struct qcom_icc_provider, provider) + +enum qcom_qos_mode { + QCOM_QOS_MODE_BYPASS = 0, + QCOM_QOS_MODE_FIXED, + QCOM_QOS_MODE_MAX, +}; + +struct qcom_icc_provider { + struct icc_provider provider; + void __iomem *base; + struct clk *bus_clk; + struct clk *bus_a_clk; +}; + +#define MSM8916_MAX_LINKS 8 + +/** + * struct qcom_icc_node - Qualcomm specific interconnect nodes + * @name: the node name used in debugfs + * @id: a unique node identifier + * @links: an array of nodes where we can go next while traversing + * @num_links: the total number of @links + * @port: the offset index into the masters QoS register space + * @buswidth: width of the interconnect between a node and the bus (bytes) + * @ap_owned: the AP CPU does the writing to QoS registers + * @qos_mode: QoS mode for ap_owned resources + * @mas_rpm_id: RPM id for devices that are bus masters + * @slv_rpm_id: RPM id for devices that are bus slaves + * @rate: current bus clock rate in Hz + */ +struct qcom_icc_node { + unsigned char *name; + u16 id; + u16 links[MSM8916_MAX_LINKS]; + u16 num_links; + u16 port; + u16 buswidth; + bool ap_owned; + enum qcom_qos_mode qos_mode; + int mas_rpm_id; + int slv_rpm_id; + u64 rate; +}; + +struct qcom_icc_desc { + struct qcom_icc_node **nodes; + size_t num_nodes; +}; + +#define DEFINE_QNODE(_name, _id, _port, _buswidth, _ap_owned, \ + _mas_rpm_id, _slv_rpm_id, _qos_mode, \ + _numlinks, ...) \ + static struct qcom_icc_node _name = { \ + .name = #_name, \ + .id = _id, \ + .port = _port, \ + .buswidth = _buswidth, \ + .ap_owned = _ap_owned, \ + .mas_rpm_id = _mas_rpm_id, \ + .slv_rpm_id = _slv_rpm_id, \ + .qos_mode = _qos_mode, \ + .num_links = _numlinks, \ + .links = { __VA_ARGS__ }, \ + } + +DEFINE_QNODE(bimc_snoc_mas, MSM8916_BIMC_SNOC_MAS, 0, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_BIMC_SNOC_SLV); +DEFINE_QNODE(bimc_snoc_slv, MSM8916_BIMC_SNOC_SLV, 0, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 2, MSM8916_SNOC_INT_0, MSM8916_SNOC_INT_1); +DEFINE_QNODE(mas_apss, MSM8916_MASTER_AMPSS_M0, 0, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 3, MSM8916_SLAVE_EBI_CH0, MSM8916_BIMC_SNOC_MAS, MSM8916_SLAVE_AMPSS_L2); +DEFINE_QNODE(mas_audio, MSM8916_MASTER_LPASS, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_PNOC_MAS_0); +DEFINE_QNODE(mas_blsp_1, MSM8916_MASTER_BLSP_1, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_PNOC_MAS_1); +DEFINE_QNODE(mas_dehr, MSM8916_MASTER_DEHR, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_PNOC_MAS_0); +DEFINE_QNODE(mas_gfx, MSM8916_MASTER_GRAPHICS_3D, 2, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 3, MSM8916_SLAVE_EBI_CH0, MSM8916_BIMC_SNOC_MAS, MSM8916_SLAVE_AMPSS_L2); +DEFINE_QNODE(mas_jpeg, MSM8916_MASTER_JPEG, 6, 16, 1, -1, -1, QCOM_QOS_MODE_BYPASS, 2, MSM8916_SNOC_MM_INT_0, MSM8916_SNOC_MM_INT_2); +DEFINE_QNODE(mas_mdp, MSM8916_MASTER_MDP_PORT0, 7, 16, 1, -1, -1, QCOM_QOS_MODE_BYPASS, 2, MSM8916_SNOC_MM_INT_0, MSM8916_SNOC_MM_INT_2); +DEFINE_QNODE(mas_pnoc_crypto_0, MSM8916_MASTER_CRYPTO_CORE0, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_PNOC_INT_1); +DEFINE_QNODE(mas_pnoc_sdcc_1, MSM8916_MASTER_SDCC_1, 7, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_PNOC_INT_1); +DEFINE_QNODE(mas_pnoc_sdcc_2, MSM8916_MASTER_SDCC_2, 8, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_PNOC_INT_1); +DEFINE_QNODE(mas_qdss_bam, MSM8916_MASTER_QDSS_BAM, 11, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_SNOC_QDSS_INT); +DEFINE_QNODE(mas_qdss_etr, MSM8916_MASTER_QDSS_ETR, 10, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_SNOC_QDSS_INT); +DEFINE_QNODE(mas_snoc_cfg, MSM8916_MASTER_SNOC_CFG, 0, 4, 0, 20, -1, QCOM_QOS_MODE_BYPASS, 1, MSM8916_SNOC_QDSS_INT); +DEFINE_QNODE(mas_spdm, MSM8916_MASTER_SPDM, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_PNOC_MAS_0); +DEFINE_QNODE(mas_tcu0, MSM8916_MASTER_TCU0, 5, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 3, MSM8916_SLAVE_EBI_CH0, MSM8916_BIMC_SNOC_MAS, MSM8916_SLAVE_AMPSS_L2); +DEFINE_QNODE(mas_tcu1, MSM8916_MASTER_TCU1, 6, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 3, MSM8916_SLAVE_EBI_CH0, MSM8916_BIMC_SNOC_MAS, MSM8916_SLAVE_AMPSS_L2); +DEFINE_QNODE(mas_usb_hs, MSM8916_MASTER_USB_HS, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_PNOC_MAS_1); +DEFINE_QNODE(mas_vfe, MSM8916_MASTER_VFE, 9, 16, 1, -1, -1, QCOM_QOS_MODE_BYPASS, 2, MSM8916_SNOC_MM_INT_1, MSM8916_SNOC_MM_INT_2); +DEFINE_QNODE(mas_video, MSM8916_MASTER_VIDEO_P0, 8, 16, 1, -1, -1, QCOM_QOS_MODE_BYPASS, 2, MSM8916_SNOC_MM_INT_0, MSM8916_SNOC_MM_INT_2); +DEFINE_QNODE(mm_int_0, MSM8916_SNOC_MM_INT_0, 0, 16, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_SNOC_MM_INT_BIMC); +DEFINE_QNODE(mm_int_1, MSM8916_SNOC_MM_INT_1, 0, 16, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_SNOC_MM_INT_BIMC); +DEFINE_QNODE(mm_int_2, MSM8916_SNOC_MM_INT_2, 0, 16, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_SNOC_INT_0); +DEFINE_QNODE(mm_int_bimc, MSM8916_SNOC_MM_INT_BIMC, 0, 16, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_SNOC_BIMC_1_MAS); +DEFINE_QNODE(pnoc_int_0, MSM8916_PNOC_INT_0, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 8, MSM8916_PNOC_SNOC_MAS, MSM8916_PNOC_SLV_0, MSM8916_PNOC_SLV_1, MSM8916_PNOC_SLV_2, MSM8916_PNOC_SLV_3, MSM8916_PNOC_SLV_4, MSM8916_PNOC_SLV_8, MSM8916_PNOC_SLV_9); +DEFINE_QNODE(pnoc_int_1, MSM8916_PNOC_INT_1, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_PNOC_SNOC_MAS); +DEFINE_QNODE(pnoc_m_0, MSM8916_PNOC_MAS_0, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_PNOC_INT_0); +DEFINE_QNODE(pnoc_m_1, MSM8916_PNOC_MAS_1, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_PNOC_SNOC_MAS); +DEFINE_QNODE(pnoc_s_0, MSM8916_PNOC_SLV_0, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 5, MSM8916_SLAVE_CLK_CTL, MSM8916_SLAVE_TLMM, MSM8916_SLAVE_TCSR, MSM8916_SLAVE_SECURITY, MSM8916_SLAVE_MSS); +DEFINE_QNODE(pnoc_s_1, MSM8916_PNOC_SLV_1, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 5, MSM8916_SLAVE_IMEM_CFG, MSM8916_SLAVE_CRYPTO_0_CFG, MSM8916_SLAVE_MSG_RAM, MSM8916_SLAVE_PDM, MSM8916_SLAVE_PRNG); +DEFINE_QNODE(pnoc_s_2, MSM8916_PNOC_SLV_2, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 5, MSM8916_SLAVE_SPDM, MSM8916_SLAVE_BOOT_ROM, MSM8916_SLAVE_BIMC_CFG, MSM8916_SLAVE_PNOC_CFG, MSM8916_SLAVE_PMIC_ARB); +DEFINE_QNODE(pnoc_s_3, MSM8916_PNOC_SLV_3, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 5, MSM8916_SLAVE_MPM, MSM8916_SLAVE_SNOC_CFG, MSM8916_SLAVE_RBCPR_CFG, MSM8916_SLAVE_QDSS_CFG, MSM8916_SLAVE_DEHR_CFG); +DEFINE_QNODE(pnoc_s_4, MSM8916_PNOC_SLV_4, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 3, MSM8916_SLAVE_VENUS_CFG, MSM8916_SLAVE_CAMERA_CFG, MSM8916_SLAVE_DISPLAY_CFG); +DEFINE_QNODE(pnoc_s_8, MSM8916_PNOC_SLV_8, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 3, MSM8916_SLAVE_USB_HS, MSM8916_SLAVE_SDCC_1, MSM8916_SLAVE_BLSP_1); +DEFINE_QNODE(pnoc_s_9, MSM8916_PNOC_SLV_9, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 3, MSM8916_SLAVE_SDCC_2, MSM8916_SLAVE_LPASS, MSM8916_SLAVE_GRAPHICS_3D_CFG); +DEFINE_QNODE(pnoc_snoc_mas, MSM8916_PNOC_SNOC_MAS, 0, 8, 0, 29, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_PNOC_SNOC_SLV); +DEFINE_QNODE(pnoc_snoc_slv, MSM8916_PNOC_SNOC_SLV, 0, 8, 0, -1, 45, QCOM_QOS_MODE_FIXED, 3, MSM8916_SNOC_INT_0, MSM8916_SNOC_INT_BIMC, MSM8916_SNOC_INT_1); +DEFINE_QNODE(qdss_int, MSM8916_SNOC_QDSS_INT, 0, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 2, MSM8916_SNOC_INT_0, MSM8916_SNOC_INT_BIMC); +DEFINE_QNODE(slv_apps_l2, MSM8916_SLAVE_AMPSS_L2, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_apss, MSM8916_SLAVE_APSS, 0, 4, 0, -1, 20, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_audio, MSM8916_SLAVE_LPASS, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_bimc_cfg, MSM8916_SLAVE_BIMC_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_blsp_1, MSM8916_SLAVE_BLSP_1, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_boot_rom, MSM8916_SLAVE_BOOT_ROM, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_camera_cfg, MSM8916_SLAVE_CAMERA_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_cats_0, MSM8916_SLAVE_CATS_128, 0, 16, 0, -1, 106, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_cats_1, MSM8916_SLAVE_OCMEM_64, 0, 8, 0, -1, 107, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_clk_ctl, MSM8916_SLAVE_CLK_CTL, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_crypto_0_cfg, MSM8916_SLAVE_CRYPTO_0_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_dehr_cfg, MSM8916_SLAVE_DEHR_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_display_cfg, MSM8916_SLAVE_DISPLAY_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_ebi_ch0, MSM8916_SLAVE_EBI_CH0, 0, 8, 0, -1, 0, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_gfx_cfg, MSM8916_SLAVE_GRAPHICS_3D_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_imem_cfg, MSM8916_SLAVE_IMEM_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_imem, MSM8916_SLAVE_IMEM, 0, 8, 0, -1, 26, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_mpm, MSM8916_SLAVE_MPM, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_msg_ram, MSM8916_SLAVE_MSG_RAM, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_mss, MSM8916_SLAVE_MSS, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_pdm, MSM8916_SLAVE_PDM, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_pmic_arb, MSM8916_SLAVE_PMIC_ARB, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_pnoc_cfg, MSM8916_SLAVE_PNOC_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_prng, MSM8916_SLAVE_PRNG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_qdss_cfg, MSM8916_SLAVE_QDSS_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_qdss_stm, MSM8916_SLAVE_QDSS_STM, 0, 4, 0, -1, 30, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_rbcpr_cfg, MSM8916_SLAVE_RBCPR_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_sdcc_1, MSM8916_SLAVE_SDCC_1, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_sdcc_2, MSM8916_SLAVE_SDCC_2, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_security, MSM8916_SLAVE_SECURITY, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_snoc_cfg, MSM8916_SLAVE_SNOC_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_spdm, MSM8916_SLAVE_SPDM, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_srvc_snoc, MSM8916_SLAVE_SRVC_SNOC, 0, 8, 0, -1, 29, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_tcsr, MSM8916_SLAVE_TCSR, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_tlmm, MSM8916_SLAVE_TLMM, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_usb_hs, MSM8916_SLAVE_USB_HS, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(slv_venus_cfg, MSM8916_SLAVE_VENUS_CFG, 0, 4, 0, -1, -1, QCOM_QOS_MODE_FIXED, 0, 0); +DEFINE_QNODE(snoc_bimc_0_mas, MSM8916_SNOC_BIMC_0_MAS, 0, 8, 0, 3, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_SNOC_BIMC_0_SLV); +DEFINE_QNODE(snoc_bimc_0_slv, MSM8916_SNOC_BIMC_0_SLV, 0, 8, 0, -1, 24, QCOM_QOS_MODE_FIXED, 1, MSM8916_SLAVE_EBI_CH0); +DEFINE_QNODE(snoc_bimc_1_mas, MSM8916_SNOC_BIMC_1_MAS, 0, 16, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_SNOC_BIMC_1_SLV); +DEFINE_QNODE(snoc_bimc_1_slv, MSM8916_SNOC_BIMC_1_SLV, 0, 8, 1, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_SLAVE_EBI_CH0); +DEFINE_QNODE(snoc_int_0, MSM8916_SNOC_INT_0, 0, 8, 0, 99, 130, QCOM_QOS_MODE_FIXED, 3, MSM8916_SLAVE_QDSS_STM, MSM8916_SLAVE_IMEM, MSM8916_SNOC_PNOC_MAS); +DEFINE_QNODE(snoc_int_1, MSM8916_SNOC_INT_1, 0, 8, 0, 100, 131, QCOM_QOS_MODE_FIXED, 3, MSM8916_SLAVE_APSS, MSM8916_SLAVE_CATS_128, MSM8916_SLAVE_OCMEM_64); +DEFINE_QNODE(snoc_int_bimc, MSM8916_SNOC_INT_BIMC, 0, 8, 0, 101, 132, QCOM_QOS_MODE_FIXED, 1, MSM8916_SNOC_BIMC_0_MAS); +DEFINE_QNODE(snoc_pnoc_mas, MSM8916_SNOC_PNOC_MAS, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_SNOC_PNOC_SLV); +DEFINE_QNODE(snoc_pnoc_slv, MSM8916_SNOC_PNOC_SLV, 0, 8, 0, -1, -1, QCOM_QOS_MODE_FIXED, 1, MSM8916_PNOC_INT_0); + +static struct qcom_icc_node *msm8916_snoc_nodes[] = { + [BIMC_SNOC_SLV] = &bimc_snoc_slv, + [MASTER_JPEG] = &mas_jpeg, + [MASTER_MDP_PORT0] = &mas_mdp, + [MASTER_QDSS_BAM] = &mas_qdss_bam, + [MASTER_QDSS_ETR] = &mas_qdss_etr, + [MASTER_SNOC_CFG] = &mas_snoc_cfg, + [MASTER_VFE] = &mas_vfe, + [MASTER_VIDEO_P0] = &mas_video, + [SNOC_MM_INT_0] = &mm_int_0, + [SNOC_MM_INT_1] = &mm_int_1, + [SNOC_MM_INT_2] = &mm_int_2, + [SNOC_MM_INT_BIMC] = &mm_int_bimc, + [PNOC_SNOC_SLV] = &pnoc_snoc_slv, + [SLAVE_APSS] = &slv_apss, + [SLAVE_CATS_128] = &slv_cats_0, + [SLAVE_OCMEM_64] = &slv_cats_1, + [SLAVE_IMEM] = &slv_imem, + [SLAVE_QDSS_STM] = &slv_qdss_stm, + [SLAVE_SRVC_SNOC] = &slv_srvc_snoc, + [SNOC_BIMC_0_MAS] = &snoc_bimc_0_mas, + [SNOC_BIMC_1_MAS] = &snoc_bimc_1_mas, + [SNOC_INT_0] = &snoc_int_0, + [SNOC_INT_1] = &snoc_int_1, + [SNOC_INT_BIMC] = &snoc_int_bimc, + [SNOC_PNOC_MAS] = &snoc_pnoc_mas, + [SNOC_QDSS_INT] = &qdss_int, +}; + +static struct qcom_icc_desc msm8916_snoc = { + .nodes = msm8916_snoc_nodes, + .num_nodes = ARRAY_SIZE(msm8916_snoc_nodes), +}; + +static struct qcom_icc_node *msm8916_bimc_nodes[] = { + [BIMC_SNOC_MAS] = &bimc_snoc_mas, + [MASTER_AMPSS_M0] = &mas_apss, + [MASTER_GRAPHICS_3D] = &mas_gfx, + [MASTER_TCU0] = &mas_tcu0, + [MASTER_TCU1] = &mas_tcu1, + [SLAVE_AMPSS_L2] = &slv_apps_l2, + [SLAVE_EBI_CH0] = &slv_ebi_ch0, + [SNOC_BIMC_0_SLV] = &snoc_bimc_0_slv, + [SNOC_BIMC_1_SLV] = &snoc_bimc_1_slv, +}; + +static struct qcom_icc_desc msm8916_bimc = { + .nodes = msm8916_bimc_nodes, + .num_nodes = ARRAY_SIZE(msm8916_bimc_nodes), +}; + +static struct qcom_icc_node *msm8916_pnoc_nodes[] = { + [MASTER_BLSP_1] = &mas_blsp_1, + [MASTER_DEHR] = &mas_dehr, + [MASTER_LPASS] = &mas_audio, + [MASTER_CRYPTO_CORE0] = &mas_pnoc_crypto_0, + [MASTER_SDCC_1] = &mas_pnoc_sdcc_1, + [MASTER_SDCC_2] = &mas_pnoc_sdcc_2, + [MASTER_SPDM] = &mas_spdm, + [MASTER_USB_HS] = &mas_usb_hs, + [PNOC_INT_0] = &pnoc_int_0, + [PNOC_INT_1] = &pnoc_int_1, + [PNOC_MAS_0] = &pnoc_m_0, + [PNOC_MAS_1] = &pnoc_m_1, + [PNOC_SLV_0] = &pnoc_s_0, + [PNOC_SLV_1] = &pnoc_s_1, + [PNOC_SLV_2] = &pnoc_s_2, + [PNOC_SLV_3] = &pnoc_s_3, + [PNOC_SLV_4] = &pnoc_s_4, + [PNOC_SLV_8] = &pnoc_s_8, + [PNOC_SLV_9] = &pnoc_s_9, + [PNOC_SNOC_MAS] = &pnoc_snoc_mas, + [SLAVE_BIMC_CFG] = &slv_bimc_cfg, + [SLAVE_BLSP_1] = &slv_blsp_1, + [SLAVE_BOOT_ROM] = &slv_boot_rom, + [SLAVE_CAMERA_CFG] = &slv_camera_cfg, + [SLAVE_CLK_CTL] = &slv_clk_ctl, + [SLAVE_CRYPTO_0_CFG] = &slv_crypto_0_cfg, + [SLAVE_DEHR_CFG] = &slv_dehr_cfg, + [SLAVE_DISPLAY_CFG] = &slv_display_cfg, + [SLAVE_GRAPHICS_3D_CFG] = &slv_gfx_cfg, + [SLAVE_IMEM_CFG] = &slv_imem_cfg, + [SLAVE_LPASS] = &slv_audio, + [SLAVE_MPM] = &slv_mpm, + [SLAVE_MSG_RAM] = &slv_msg_ram, + [SLAVE_MSS] = &slv_mss, + [SLAVE_PDM] = &slv_pdm, + [SLAVE_PMIC_ARB] = &slv_pmic_arb, + [SLAVE_PNOC_CFG] = &slv_pnoc_cfg, + [SLAVE_PRNG] = &slv_prng, + [SLAVE_QDSS_CFG] = &slv_qdss_cfg, + [SLAVE_RBCPR_CFG] = &slv_rbcpr_cfg, + [SLAVE_SDCC_1] = &slv_sdcc_1, + [SLAVE_SDCC_2] = &slv_sdcc_2, + [SLAVE_SECURITY] = &slv_security, + [SLAVE_SNOC_CFG] = &slv_snoc_cfg, + [SLAVE_SPDM] = &slv_spdm, + [SLAVE_TCSR] = &slv_tcsr, + [SLAVE_TLMM] = &slv_tlmm, + [SLAVE_USB_HS] = &slv_usb_hs, + [SLAVE_VENUS_CFG] = &slv_venus_cfg, + [SNOC_PNOC_SLV] = &snoc_pnoc_slv, +}; + +static struct qcom_icc_desc msm8916_pnoc = { + .nodes = msm8916_pnoc_nodes, + .num_nodes = ARRAY_SIZE(msm8916_pnoc_nodes), +}; + +static int qcom_icc_aggregate(struct icc_node *node, u8 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 qcom_icc_set(struct icc_node *src, struct icc_node *dst) +{ + struct qcom_icc_provider *qp; + struct qcom_icc_node *qn; + struct icc_provider *provider; + struct icc_node *n; + u64 sum_bw; + u64 max_peak_bw; + u64 rate; + u32 agg_avg = 0; + u32 agg_peak = 0; + int ret = 0; + + qn = src->data; + provider = src->provider; + qp = to_qcom_provider(provider); + + list_for_each_entry(n, &provider->nodes, node_list) + qcom_icc_aggregate(n, 0, n->avg_bw, n->peak_bw, + &agg_avg, &agg_peak); + + sum_bw = icc_units_to_bps(agg_avg); + max_peak_bw = icc_units_to_bps(agg_peak); + + /* set bandwidth */ + if (qn->ap_owned) { + /* TODO: set QoS */ + } else { + /* send message to the RPM processor */ + if (qn->mas_rpm_id != -1) { + ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE, + RPM_BUS_MASTER_REQ, + qn->mas_rpm_id, + sum_bw); + if (ret) { + pr_err("qcom_icc_rpm_smd_send mas %d error %d\n", qn->mas_rpm_id, ret); + return ret; + } + } + + if (qn->slv_rpm_id != -1) { + ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE, + RPM_BUS_SLAVE_REQ, + qn->slv_rpm_id, + sum_bw); + if (ret) { + pr_err("qcom_icc_rpm_smd_send slv error %d\n", + ret); + return ret; + } + } + } + + rate = max(sum_bw, max_peak_bw); + + do_div(rate, qn->buswidth); + + if (qn->rate != rate) { + ret = clk_set_rate(qp->bus_clk, rate); + if (ret) { + pr_err("set clk rate %lld error %d\n", rate, ret); + return ret; + } + + ret = clk_set_rate(qp->bus_a_clk, rate); + if (ret) { + pr_err("set clk rate %lld error %d\n", rate, ret); + return ret; + } + + qn->rate = rate; + } + + return ret; +} + +static int qnoc_probe(struct platform_device *pdev) +{ + const struct qcom_icc_desc *desc; + struct icc_onecell_data *data; + struct icc_provider *provider; + struct qcom_icc_node **qnodes; + struct qcom_icc_provider *qp; + struct icc_node *node; + struct resource *res; + size_t num_nodes, i; + int ret; + + /* wait for RPM */ + if (!qcom_icc_rpm_smd_available()) + return -EPROBE_DEFER; + + desc = of_device_get_match_data(&pdev->dev); + if (!desc) + return -EINVAL; + + qnodes = desc->nodes; + num_nodes = desc->num_nodes; + + qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL); + if (!qp) + return -ENOMEM; + + data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL); + if (!data) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + qp->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(qp->base)) + return PTR_ERR(qp->base); + + qp->bus_clk = devm_clk_get(&pdev->dev, "bus_clk"); + if (IS_ERR(qp->bus_clk)) + return PTR_ERR(qp->bus_clk); + + ret = clk_prepare_enable(qp->bus_clk); + if (ret) { + dev_err(&pdev->dev, "error enabling bus_clk: %d\n", ret); + return ret; + } + + qp->bus_a_clk = devm_clk_get(&pdev->dev, "bus_a_clk"); + if (IS_ERR(qp->bus_a_clk)) + return PTR_ERR(qp->bus_a_clk); + + ret = clk_prepare_enable(qp->bus_a_clk); + if (ret) { + dev_err(&pdev->dev, "error enabling bus_a_clk: %d\n", ret); + clk_disable_unprepare(qp->bus_clk); + return ret; + } + + provider = &qp->provider; + INIT_LIST_HEAD(&provider->nodes); + provider->dev = &pdev->dev; + provider->set = qcom_icc_set; + provider->aggregate = qcom_icc_aggregate; + provider->xlate = of_icc_xlate_onecell; + provider->data = data; + + ret = icc_provider_add(provider); + if (ret) { + dev_err(&pdev->dev, "error adding interconnect provider\n"); + clk_disable_unprepare(qp->bus_clk); + clk_disable_unprepare(qp->bus_a_clk); + return ret; + } + + for (i = 0; i < num_nodes; i++) { + size_t j; + + node = icc_node_create(qnodes[i]->id); + if (IS_ERR(node)) { + ret = PTR_ERR(node); + goto err; + } + + node->name = qnodes[i]->name; + node->data = qnodes[i]; + icc_node_add(node, provider); + + dev_dbg(&pdev->dev, "registered node %s\n", node->name); + + /* populate links */ + for (j = 0; j < qnodes[i]->num_links; j++) + icc_link_create(node, qnodes[i]->links[j]); + + data->nodes[i] = node; + } + data->num_nodes = num_nodes; + + platform_set_drvdata(pdev, qp); + + return ret; +err: + list_for_each_entry(node, &provider->nodes, node_list) { + icc_node_del(node); + icc_node_destroy(node->id); + } + clk_disable_unprepare(qp->bus_clk); + clk_disable_unprepare(qp->bus_a_clk); + icc_provider_del(provider); + + return ret; +} + +static int qnoc_remove(struct platform_device *pdev) +{ + struct qcom_icc_provider *qp = platform_get_drvdata(pdev); + struct icc_provider *provider = &qp->provider; + struct icc_node *n; + + list_for_each_entry(n, &provider->nodes, node_list) { + icc_node_del(n); + icc_node_destroy(n->id); + } + clk_disable_unprepare(qp->bus_clk); + clk_disable_unprepare(qp->bus_a_clk); + + return icc_provider_del(provider); +} + +static const struct of_device_id qnoc_of_match[] = { + { .compatible = "qcom,msm8916-pnoc", .data = &msm8916_pnoc }, + { .compatible = "qcom,msm8916-snoc", .data = &msm8916_snoc }, + { .compatible = "qcom,msm8916-bimc", .data = &msm8916_bimc }, + { }, +}; +MODULE_DEVICE_TABLE(of, qnoc_of_match); + +static struct platform_driver qnoc_driver = { + .probe = qnoc_probe, + .remove = qnoc_remove, + .driver = { + .name = "qnoc-msm8916", + .of_match_table = qnoc_of_match, + }, +}; +module_platform_driver(qnoc_driver); +MODULE_AUTHOR("Georgi Djakov <georgi.djakov@linaro.org>"); +MODULE_DESCRIPTION("Qualcomm msm8916 NoC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/qcom/msm8916_ids.h b/drivers/interconnect/qcom/msm8916_ids.h new file mode 100644 index 000000000000..44963e005950 --- /dev/null +++ b/drivers/interconnect/qcom/msm8916_ids.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Qualcomm MSM8916 interconnect IDs + * + * Copyright (c) 2018, Linaro Ltd. + * Author: Georgi Djakov <georgi.djakov@linaro.org> + */ + +#ifndef __DRIVERS_INTERCONNECT_QCOM_MSM8916_H +#define __DRIVERS_INTERCONNECT_QCOM_MSM8916_H + +#define MSM8916_BIMC_SNOC_MAS 0 +#define MSM8916_BIMC_SNOC_SLV 1 +#define MSM8916_MASTER_AMPSS_M0 2 +#define MSM8916_MASTER_LPASS 3 +#define MSM8916_MASTER_BLSP_1 4 +#define MSM8916_MASTER_DEHR 5 +#define MSM8916_MASTER_GRAPHICS_3D 6 +#define MSM8916_MASTER_JPEG 7 +#define MSM8916_MASTER_MDP_PORT0 8 +#define MSM8916_MASTER_CRYPTO_CORE0 9 +#define MSM8916_MASTER_SDCC_1 10 +#define MSM8916_MASTER_SDCC_2 11 +#define MSM8916_MASTER_QDSS_BAM 12 +#define MSM8916_MASTER_QDSS_ETR 13 +#define MSM8916_MASTER_SNOC_CFG 14 +#define MSM8916_MASTER_SPDM 15 +#define MSM8916_MASTER_TCU0 16 +#define MSM8916_MASTER_TCU1 17 +#define MSM8916_MASTER_USB_HS 18 +#define MSM8916_MASTER_VFE 19 +#define MSM8916_MASTER_VIDEO_P0 20 +#define MSM8916_SNOC_MM_INT_0 21 +#define MSM8916_SNOC_MM_INT_1 22 +#define MSM8916_SNOC_MM_INT_2 23 +#define MSM8916_SNOC_MM_INT_BIMC 24 +#define MSM8916_PNOC_INT_0 25 +#define MSM8916_PNOC_INT_1 26 +#define MSM8916_PNOC_MAS_0 27 +#define MSM8916_PNOC_MAS_1 28 +#define MSM8916_PNOC_SLV_0 29 +#define MSM8916_PNOC_SLV_1 30 +#define MSM8916_PNOC_SLV_2 31 +#define MSM8916_PNOC_SLV_3 32 +#define MSM8916_PNOC_SLV_4 33 +#define MSM8916_PNOC_SLV_8 34 +#define MSM8916_PNOC_SLV_9 35 +#define MSM8916_PNOC_SNOC_MAS 36 +#define MSM8916_PNOC_SNOC_SLV 37 +#define MSM8916_SNOC_QDSS_INT 38 +#define MSM8916_SLAVE_AMPSS_L2 39 +#define MSM8916_SLAVE_APSS 40 +#define MSM8916_SLAVE_LPASS 41 +#define MSM8916_SLAVE_BIMC_CFG 42 +#define MSM8916_SLAVE_BLSP_1 43 +#define MSM8916_SLAVE_BOOT_ROM 44 +#define MSM8916_SLAVE_CAMERA_CFG 45 +#define MSM8916_SLAVE_CATS_128 46 +#define MSM8916_SLAVE_OCMEM_64 47 +#define MSM8916_SLAVE_CLK_CTL 48 +#define MSM8916_SLAVE_CRYPTO_0_CFG 49 +#define MSM8916_SLAVE_DEHR_CFG 50 +#define MSM8916_SLAVE_DISPLAY_CFG 51 +#define MSM8916_SLAVE_EBI_CH0 52 +#define MSM8916_SLAVE_GRAPHICS_3D_CFG 53 +#define MSM8916_SLAVE_IMEM_CFG 54 +#define MSM8916_SLAVE_IMEM 55 +#define MSM8916_SLAVE_MPM 56 +#define MSM8916_SLAVE_MSG_RAM 57 +#define MSM8916_SLAVE_MSS 58 +#define MSM8916_SLAVE_PDM 59 +#define MSM8916_SLAVE_PMIC_ARB 60 +#define MSM8916_SLAVE_PNOC_CFG 61 +#define MSM8916_SLAVE_PRNG 62 +#define MSM8916_SLAVE_QDSS_CFG 63 +#define MSM8916_SLAVE_QDSS_STM 64 +#define MSM8916_SLAVE_RBCPR_CFG 65 +#define MSM8916_SLAVE_SDCC_1 66 +#define MSM8916_SLAVE_SDCC_2 67 +#define MSM8916_SLAVE_SECURITY 68 +#define MSM8916_SLAVE_SNOC_CFG 69 +#define MSM8916_SLAVE_SPDM 70 +#define MSM8916_SLAVE_SRVC_SNOC 71 +#define MSM8916_SLAVE_TCSR 72 +#define MSM8916_SLAVE_TLMM 73 +#define MSM8916_SLAVE_USB_HS 74 +#define MSM8916_SLAVE_VENUS_CFG 75 +#define MSM8916_SNOC_BIMC_0_MAS 76 +#define MSM8916_SNOC_BIMC_0_SLV 77 +#define MSM8916_SNOC_BIMC_1_MAS 78 +#define MSM8916_SNOC_BIMC_1_SLV 79 +#define MSM8916_SNOC_INT_0 80 +#define MSM8916_SNOC_INT_1 81 +#define MSM8916_SNOC_INT_BIMC 82 +#define MSM8916_SNOC_PNOC_MAS 83 +#define MSM8916_SNOC_PNOC_SLV 84 + +#endif diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c new file mode 100644 index 000000000000..c7998281fb87 --- /dev/null +++ b/drivers/interconnect/qcom/msm8996.c @@ -0,0 +1,666 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Linaro Ltd + * Author: Georgi Djakov <georgi.djakov@linaro.org> + */ + +#include <dt-bindings/interconnect/qcom,msm8996.h> +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/interconnect-provider.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include "msm8996_ids.h" +#include "smd-rpm.h" + +#define RPM_MASTER_FIELD_BW 0x00007762 +#define RPM_BUS_MASTER_REQ 0x73616d62 +#define RPM_BUS_SLAVE_REQ 0x766c7362 + +#define to_qcom_provider(_provider) \ + container_of(_provider, struct qcom_icc_provider, provider) + +enum qcom_qos_mode { + QCOM_QOS_MODE_BYPASS = 0, + QCOM_QOS_MODE_FIXED, + QCOM_QOS_MODE_MAX, +}; + +struct qcom_icc_provider { + struct icc_provider provider; + void __iomem *base; + struct clk *bus_clk; + struct clk *bus_a_clk; +}; + +#define MSM8996_MAX_LINKS 38 + +/** + * struct qcom_icc_node - Qualcomm specific interconnect nodes + * @name: the node name used in debugfs + * @id: a unique node identifier + * @links: an array of nodes where we can go next while traversing + * @num_links: the total number of @links + * @port: the offset index into the masters QoS register space + * @agg_ports: the number of aggregation ports on the bus + * @buswidth: width of the interconnect between a node and the bus (bytes) + * @ap_owned: the AP CPU does the writing to QoS registers + * @qos_mode: QoS mode for ap_owned resources + * @mas_rpm_id: RPM id for devices that are bus masters + * @slv_rpm_id: RPM id for devices that are bus slaves + * @rate: current bus clock rate in Hz + */ +struct qcom_icc_node { + unsigned char *name; + u16 id; + u16 links[MSM8996_MAX_LINKS]; + u16 num_links; + u16 port; + u16 agg_ports; + u16 buswidth; + bool ap_owned; + enum qcom_qos_mode qos_mode; + int mas_rpm_id; + int slv_rpm_id; + u64 rate; +}; + +struct qcom_icc_desc { + struct qcom_icc_node **nodes; + size_t num_nodes; +}; + +#define DEFINE_QNODE(_name, _id, _port, _agg_ports, _buswidth, \ + _qos_mode, _ap_owned, _mas_rpm_id, _slv_rpm_id, \ + _numlinks, ...) \ + static struct qcom_icc_node _name = { \ + .name = #_name, \ + .id = _id, \ + .port = _port, \ + .agg_ports = _agg_ports, \ + .buswidth = _buswidth, \ + .qos_mode = _qos_mode, \ + .ap_owned = _ap_owned, \ + .mas_rpm_id = _mas_rpm_id, \ + .slv_rpm_id = _slv_rpm_id, \ + .num_links = _numlinks, \ + .links = { __VA_ARGS__ }, \ + } + +DEFINE_QNODE(mas_a0noc_snoc, MSM8996_A0NOC_SNOC_MAS, 0, 1, 16, QCOM_QOS_MODE_FIXED, 1, 110, -1, 5, MSM8996_SNOC_PNOC_SLV, MSM8996_SLAVE_OCIMEM, MSM8996_SLAVE_APPSS, MSM8996_SNOC_BIMC_SLV, MSM8996_SLAVE_PIMEM); +DEFINE_QNODE(mas_a1noc_snoc, MSM8996_A1NOC_SNOC_MAS, 0, 1, 16, QCOM_QOS_MODE_FIXED, 0, 111, -1, 13, MSM8996_SLAVE_SNOC_VMEM, MSM8996_SLAVE_USB3, MSM8996_SLAVE_PCIE_0, MSM8996_SLAVE_PIMEM, MSM8996_SLAVE_PCIE_2, MSM8996_SLAVE_LPASS, MSM8996_SLAVE_PCIE_1, MSM8996_SLAVE_APPSS, MSM8996_SNOC_BIMC_SLV, MSM8996_SNOC_CNOC_SLV, MSM8996_SNOC_PNOC_SLV, MSM8996_SLAVE_OCIMEM, MSM8996_SLAVE_QDSS_STM); +DEFINE_QNODE(mas_a2noc_snoc, MSM8996_A2NOC_SNOC_MAS, 0, 1, 16, QCOM_QOS_MODE_FIXED, 0, 112, -1, 12, MSM8996_SLAVE_SNOC_VMEM, MSM8996_SLAVE_USB3, MSM8996_SLAVE_PCIE_1, MSM8996_SLAVE_PIMEM, MSM8996_SLAVE_PCIE_2, MSM8996_SLAVE_QDSS_STM, MSM8996_SLAVE_LPASS, MSM8996_SNOC_BIMC_SLV, MSM8996_SNOC_CNOC_SLV, MSM8996_SNOC_PNOC_SLV, MSM8996_SLAVE_OCIMEM, MSM8996_SLAVE_PCIE_0); +DEFINE_QNODE(mas_apps_proc, MSM8996_MASTER_AMPSS_M0, 0, 2, 8, QCOM_QOS_MODE_FIXED, 1, 0, -1, 3, MSM8996_BIMC_SNOC_1_SLV, MSM8996_SLAVE_EBI_CH0, MSM8996_BIMC_SNOC_SLV); +DEFINE_QNODE(mas_bimc_snoc_0, MSM8996_BIMC_SNOC_MAS, 0, 1, 16, QCOM_QOS_MODE_FIXED, 1, 21, -1, 9, MSM8996_SLAVE_SNOC_VMEM, MSM8996_SLAVE_USB3, MSM8996_SLAVE_PIMEM, MSM8996_SLAVE_LPASS, MSM8996_SLAVE_APPSS, MSM8996_SNOC_CNOC_SLV, MSM8996_SNOC_PNOC_SLV, MSM8996_SLAVE_OCIMEM, MSM8996_SLAVE_QDSS_STM); +DEFINE_QNODE(mas_bimc_snoc_1, MSM8996_BIMC_SNOC_1_MAS, 0, 1, 16, QCOM_QOS_MODE_FIXED, 1, 109, -1, 3, MSM8996_SLAVE_PCIE_2, MSM8996_SLAVE_PCIE_1, MSM8996_SLAVE_PCIE_0); +DEFINE_QNODE(mas_blsp_1, MSM8996_MASTER_BLSP_1, 0, 1, 4, QCOM_QOS_MODE_BYPASS, 0, 41, -1, 1, MSM8996_PNOC_A1NOC_SLV); +DEFINE_QNODE(mas_blsp_2, MSM8996_MASTER_BLSP_2, 0, 1, 4, QCOM_QOS_MODE_BYPASS, 0, 39, -1, 1, MSM8996_PNOC_A1NOC_SLV); +DEFINE_QNODE(mas_cnoc_a1noc, MSM8996_CNOC_A1NOC_MAS, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, 116, -1, 1, MSM8996_A1NOC_SNOC_SLV); +DEFINE_QNODE(mas_cnoc_mnoc_cfg, MSM8996_MASTER_CNOC_MNOC_CFG, 0, 1, 8, QCOM_QOS_MODE_BYPASS, 1, 5, -1, 1, MSM8996_SLAVE_SERVICE_MNOC); +DEFINE_QNODE(mas_cnoc_mnoc_mmss_cfg, MSM8996_MASTER_CNOC_MNOC_MMSS_CFG, 0, 1, 8, QCOM_QOS_MODE_BYPASS, 1, 4, -1, 21, MSM8996_SLAVE_MMAGIC_CFG, MSM8996_SLAVE_DSA_MPU_CFG, MSM8996_SLAVE_MMSS_CLK_CFG, MSM8996_SLAVE_CAMERA_THROTTLE_CFG, MSM8996_SLAVE_VENUS_CFG, MSM8996_SLAVE_SMMU_VFE_CFG, MSM8996_SLAVE_MISC_CFG, MSM8996_SLAVE_SMMU_CPP_CFG, MSM8996_SLAVE_GRAPHICS_3D_CFG, MSM8996_SLAVE_DISPLAY_THROTTLE_CFG, MSM8996_SLAVE_VENUS_THROTTLE_CFG, MSM8996_SLAVE_CAMERA_CFG, MSM8996_SLAVE_DISPLAY_CFG, MSM8996_SLAVE_CPR_CFG, MSM8996_SLAVE_SMMU_ROTATOR_CFG, MSM8996_SLAVE_DSA_CFG, MSM8996_SLAVE_SMMU_VENUS_CFG, MSM8996_SLAVE_VMEM_CFG, MSM8996_SLAVE_SMMU_JPEG_CFG, MSM8996_SLAVE_SMMU_MDP_CFG, MSM8996_SLAVE_MNOC_MPU_CFG); +DEFINE_QNODE(mas_cpp, MSM8996_MASTER_CPP, 5, 1, 32, QCOM_QOS_MODE_BYPASS, 1, 115, -1, 1, MSM8996_MNOC_BIMC_SLV); +DEFINE_QNODE(mas_crypto_c0, MSM8996_MASTER_CRYPTO_CORE0, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, 23, -1, 1, MSM8996_A1NOC_SNOC_SLV); +DEFINE_QNODE(mas_hmss, MSM8996_MASTER_HMSS, 4, 1, 8, QCOM_QOS_MODE_FIXED, 1, 118, -1, 3, MSM8996_SLAVE_PIMEM, MSM8996_SLAVE_OCIMEM, MSM8996_SNOC_BIMC_SLV); +DEFINE_QNODE(mas_ipa, MSM8996_MASTER_IPA, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, 59, -1, 1, MSM8996_A2NOC_SNOC_SLV); +DEFINE_QNODE(mas_jpeg, MSM8996_MASTER_JPEG, 7, 1, 32, QCOM_QOS_MODE_BYPASS, 1, 7, -1, 1, MSM8996_MNOC_BIMC_SLV); +DEFINE_QNODE(mas_mdp_p0, MSM8996_MASTER_MDP_PORT0, 1, 1, 32, QCOM_QOS_MODE_BYPASS, 1, 8, -1, 1, MSM8996_MNOC_BIMC_SLV); +DEFINE_QNODE(mas_mdp_p1, MSM8996_MASTER_MDP_PORT1, 2, 1, 32, QCOM_QOS_MODE_BYPASS, 1, 61, -1, 1, MSM8996_MNOC_BIMC_SLV); +DEFINE_QNODE(mas_mnoc_bimc, MSM8996_MNOC_BIMC_MAS, 2, 2, 8, QCOM_QOS_MODE_BYPASS, 1, 2, -1, 4, MSM8996_BIMC_SNOC_1_SLV, MSM8996_SLAVE_HMSS_L3, MSM8996_SLAVE_EBI_CH0, MSM8996_BIMC_SNOC_SLV); +DEFINE_QNODE(mas_oxili, MSM8996_MASTER_GRAPHICS_3D, 1, 2, 8, QCOM_QOS_MODE_BYPASS, 1, 6, -1, 4, MSM8996_BIMC_SNOC_1_SLV, MSM8996_SLAVE_HMSS_L3, MSM8996_SLAVE_EBI_CH0, MSM8996_BIMC_SNOC_SLV); +DEFINE_QNODE(mas_pcie_0, MSM8996_MASTER_PCIE, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, 65, -1, 1, MSM8996_A0NOC_SNOC_SLV); +DEFINE_QNODE(mas_pcie_1, MSM8996_MASTER_PCIE_1, 1, 1, 8, QCOM_QOS_MODE_FIXED, 1, 66, -1, 1, MSM8996_A0NOC_SNOC_SLV); +DEFINE_QNODE(mas_pcie_2, MSM8996_MASTER_PCIE_2, 2, 1, 8, QCOM_QOS_MODE_FIXED, 1, 119, -1, 1, MSM8996_A0NOC_SNOC_SLV); +DEFINE_QNODE(mas_pnoc_a1noc, MSM8996_PNOC_A1NOC_MAS, 1, 1, 8, QCOM_QOS_MODE_FIXED, 0, 117, -1, 1, MSM8996_A1NOC_SNOC_SLV); +DEFINE_QNODE(mas_qdss_bam, MSM8996_MASTER_QDSS_BAM, 2, 1, 16, QCOM_QOS_MODE_FIXED, 1, 19, -1, 5, MSM8996_SLAVE_PIMEM, MSM8996_SLAVE_USB3, MSM8996_SLAVE_OCIMEM, MSM8996_SNOC_BIMC_SLV, MSM8996_SNOC_PNOC_SLV); +DEFINE_QNODE(mas_qdss_dap, MSM8996_MASTER_QDSS_DAP, 0, 1, 8, QCOM_QOS_MODE_BYPASS, 1, 49, -1, 38, MSM8996_SLAVE_QDSS_RBCPR_APU_CFG, MSM8996_SLAVE_RBCPR_CX, MSM8996_SLAVE_A2NOC_SMMU_CFG, MSM8996_SLAVE_A0NOC_MPU_CFG, MSM8996_SLAVE_MESSAGE_RAM, MSM8996_SLAVE_PCIE_0_CFG, MSM8996_SLAVE_TLMM, MSM8996_SLAVE_MPM, MSM8996_SLAVE_A0NOC_SMMU_CFG, MSM8996_SLAVE_EBI1_PHY_CFG, MSM8996_SLAVE_BIMC_CFG, MSM8996_SLAVE_PIMEM_CFG, MSM8996_SLAVE_RBCPR_MX, MSM8996_SLAVE_CLK_CTL, MSM8996_SLAVE_PRNG, MSM8996_SLAVE_PCIE20_AHB2PHY, MSM8996_SLAVE_A2NOC_MPU_CFG, MSM8996_SLAVE_QDSS_CFG, MSM8996_SLAVE_A2NOC_CFG, MSM8996_SLAVE_A0NOC_CFG, MSM8996_SLAVE_UFS_CFG, MSM8996_SLAVE_CRYPTO_0_CFG, MSM8996_CNOC_SNOC_SLV, MSM8996_SLAVE_PCIE_1_CFG, MSM8996_SLAVE_SNOC_CFG, MSM8996_SLAVE_SNOC_MPU_CFG, MSM8996_SLAVE_A1NOC_MPU_CFG, MSM8996_SLAVE_A1NOC_SMMU_CFG, MSM8996_SLAVE_PCIE_2_CFG, MSM8996_SLAVE_CNOC_MNOC_CFG, MSM8996_SLAVE_CNOC_MNOC_MMSS_CFG, MSM8996_SLAVE_PMIC_ARB, MSM8996_SLAVE_IMEM_CFG, MSM8996_SLAVE_A1NOC_CFG, MSM8996_SLAVE_SSC_CFG, MSM8996_SLAVE_TCSR, MSM8996_SLAVE_LPASS_SMMU_CFG, MSM8996_SLAVE_DCC_CFG); +DEFINE_QNODE(mas_qdss_etr, MSM8996_MASTER_QDSS_ETR, 3, 1, 16, QCOM_QOS_MODE_FIXED, 1, 31, -1, 5, MSM8996_SLAVE_PIMEM, MSM8996_SLAVE_USB3, MSM8996_SLAVE_OCIMEM, MSM8996_SNOC_BIMC_SLV, MSM8996_SNOC_PNOC_SLV); +DEFINE_QNODE(mas_rotator, MSM8996_MASTER_ROTATOR, 0, 1, 32, QCOM_QOS_MODE_BYPASS, 1, 120, -1, 1, MSM8996_MNOC_BIMC_SLV); +DEFINE_QNODE(mas_sdcc_1, MSM8996_MASTER_SDCC_1, 0, 1, 8, QCOM_QOS_MODE_BYPASS, 0, 33, -1, 1, MSM8996_PNOC_A1NOC_SLV); +DEFINE_QNODE(mas_sdcc_2, MSM8996_MASTER_SDCC_2, 0, 1, 8, QCOM_QOS_MODE_BYPASS, 0, 35, -1, 1, MSM8996_PNOC_A1NOC_SLV); +DEFINE_QNODE(mas_sdcc_4, MSM8996_MASTER_SDCC_4, 0, 1, 8, QCOM_QOS_MODE_BYPASS, 0, 36, -1, 1, MSM8996_PNOC_A1NOC_SLV); +DEFINE_QNODE(mas_snoc_bimc, MSM8996_SNOC_BIMC_MAS, 0, 2, 8, QCOM_QOS_MODE_BYPASS, 0, 3, -1, 2, MSM8996_SLAVE_HMSS_L3, MSM8996_SLAVE_EBI_CH0); +DEFINE_QNODE(mas_snoc_cfg, MSM8996_MASTER_SNOC_CFG, 0, 1, 16, QCOM_QOS_MODE_FIXED, 1, 20, -1, 1, MSM8996_SLAVE_SERVICE_SNOC); +DEFINE_QNODE(mas_snoc_cnoc, MSM8996_SNOC_CNOC_MAS, 0, 1, 8, QCOM_QOS_MODE_BYPASS, 0, 52, -1, 37, MSM8996_SLAVE_CLK_CTL, MSM8996_SLAVE_RBCPR_CX, MSM8996_SLAVE_A2NOC_SMMU_CFG, MSM8996_SLAVE_A0NOC_MPU_CFG, MSM8996_SLAVE_MESSAGE_RAM, MSM8996_SLAVE_CNOC_MNOC_MMSS_CFG, MSM8996_SLAVE_PCIE_0_CFG, MSM8996_SLAVE_TLMM, MSM8996_SLAVE_MPM, MSM8996_SLAVE_A0NOC_SMMU_CFG, MSM8996_SLAVE_EBI1_PHY_CFG, MSM8996_SLAVE_BIMC_CFG, MSM8996_SLAVE_PIMEM_CFG, MSM8996_SLAVE_RBCPR_MX, MSM8996_SLAVE_PRNG, MSM8996_SLAVE_PCIE20_AHB2PHY, MSM8996_SLAVE_A2NOC_MPU_CFG, MSM8996_SLAVE_QDSS_CFG, MSM8996_SLAVE_A2NOC_CFG, MSM8996_SLAVE_A0NOC_CFG, MSM8996_SLAVE_UFS_CFG, MSM8996_SLAVE_CRYPTO_0_CFG, MSM8996_SLAVE_PCIE_1_CFG, MSM8996_SLAVE_SNOC_CFG, MSM8996_SLAVE_SNOC_MPU_CFG, MSM8996_SLAVE_A1NOC_MPU_CFG, MSM8996_SLAVE_A1NOC_SMMU_CFG, MSM8996_SLAVE_PCIE_2_CFG, MSM8996_SLAVE_CNOC_MNOC_CFG, MSM8996_SLAVE_QDSS_RBCPR_APU_CFG, MSM8996_SLAVE_PMIC_ARB, MSM8996_SLAVE_IMEM_CFG, MSM8996_SLAVE_A1NOC_CFG, MSM8996_SLAVE_SSC_CFG, MSM8996_SLAVE_TCSR, MSM8996_SLAVE_LPASS_SMMU_CFG, MSM8996_SLAVE_DCC_CFG); +DEFINE_QNODE(mas_snoc_pnoc, MSM8996_SNOC_PNOC_MAS, 0, 1, 8, QCOM_QOS_MODE_BYPASS, 0, 44, -1, 9, MSM8996_SLAVE_BLSP_1, MSM8996_SLAVE_BLSP_2, MSM8996_SLAVE_USB_HS, MSM8996_SLAVE_SDCC_1, MSM8996_SLAVE_SDCC_2, MSM8996_SLAVE_SDCC_4, MSM8996_SLAVE_TSIF, MSM8996_SLAVE_PDM, MSM8996_SLAVE_AHB2PHY); +DEFINE_QNODE(mas_snoc_vmem, MSM8996_MASTER_SNOC_VMEM, 0, 1, 32, QCOM_QOS_MODE_BYPASS, 1, 114, -1, 1, MSM8996_SLAVE_VMEM_CFG); +DEFINE_QNODE(mas_tsif, MSM8996_MASTER_TSIF, 0, 1, 4, QCOM_QOS_MODE_BYPASS, 0, 37, -1, 1, MSM8996_PNOC_A1NOC_SLV); +DEFINE_QNODE(mas_ufs, MSM8996_MASTER_UFS, 2, 1, 8, QCOM_QOS_MODE_FIXED, 1, 68, -1, 1, MSM8996_A2NOC_SNOC_SLV); +DEFINE_QNODE(mas_usb3, MSM8996_MASTER_USB3, 3, 1, 8, QCOM_QOS_MODE_FIXED, 1, 32, -1, 1, MSM8996_A2NOC_SNOC_SLV); +DEFINE_QNODE(mas_usb_hs, MSM8996_MASTER_USB_HS, 0, 1, 8, QCOM_QOS_MODE_BYPASS, 0, 42, -1, 1, MSM8996_PNOC_A1NOC_SLV); +DEFINE_QNODE(mas_venus, MSM8996_MASTER_VIDEO_P0, 3, 2, 32, QCOM_QOS_MODE_BYPASS, 1, 9, -1, 1, MSM8996_MNOC_BIMC_SLV); +DEFINE_QNODE(mas_venus_vmem, MSM8996_MASTER_VIDEO_P0_OCMEM, 0, 1, 32, QCOM_QOS_MODE_BYPASS, 1, 121, -1, 1, MSM8996_SLAVE_VMEM_CFG); +DEFINE_QNODE(mas_vfe, MSM8996_MASTER_VFE, 6, 1, 32, QCOM_QOS_MODE_BYPASS, 1, 11, -1, 1, MSM8996_MNOC_BIMC_SLV); +DEFINE_QNODE(slv_a0noc_cfg, MSM8996_SLAVE_A0NOC_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 144, 0, 0); +DEFINE_QNODE(slv_a0noc_mpu_cfg, MSM8996_SLAVE_A0NOC_MPU_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 145, 0, 0); +DEFINE_QNODE(slv_a0noc_smmu_cfg, MSM8996_SLAVE_A0NOC_SMMU_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 146, 0, 0); +DEFINE_QNODE(slv_a0noc_snoc, MSM8996_A0NOC_SNOC_SLV, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 141, 1, MSM8996_A0NOC_SNOC_MAS); +DEFINE_QNODE(slv_a1noc_cfg, MSM8996_SLAVE_A1NOC_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 147, 0, 0); +DEFINE_QNODE(slv_a1noc_mpu_cfg, MSM8996_SLAVE_A1NOC_MPU_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 148, 0, 0); +DEFINE_QNODE(slv_a1noc_smmu_cfg, MSM8996_SLAVE_A1NOC_SMMU_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 149, 0, 0); +DEFINE_QNODE(slv_a1noc_snoc, MSM8996_A1NOC_SNOC_SLV, 0, 1, 8, QCOM_QOS_MODE_FIXED, 0, -1, 142, 1, MSM8996_A1NOC_SNOC_MAS); +DEFINE_QNODE(slv_a2noc_cfg, MSM8996_SLAVE_A2NOC_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 150, 0, 0); +DEFINE_QNODE(slv_a2noc_mpu_cfg, MSM8996_SLAVE_A2NOC_MPU_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 151, 0, 0); +DEFINE_QNODE(slv_a2noc_smmu_cfg, MSM8996_SLAVE_A2NOC_SMMU_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 152, 0, 0); +DEFINE_QNODE(slv_a2noc_snoc, MSM8996_A2NOC_SNOC_SLV, 0, 1, 8, QCOM_QOS_MODE_FIXED, 0, -1, 143, 1, MSM8996_A2NOC_SNOC_MAS); +DEFINE_QNODE(slv_ahb2phy, MSM8996_SLAVE_AHB2PHY, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 153, 0, 0); +DEFINE_QNODE(slv_bimc_cfg, MSM8996_SLAVE_BIMC_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 56, 0, 0); +DEFINE_QNODE(slv_bimc_snoc_0, MSM8996_BIMC_SNOC_SLV, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 2, 1, MSM8996_BIMC_SNOC_MAS); +DEFINE_QNODE(slv_bimc_snoc_1, MSM8996_BIMC_SNOC_1_SLV, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 138, 1, MSM8996_BIMC_SNOC_1_MAS); +DEFINE_QNODE(slv_blsp_1, MSM8996_SLAVE_BLSP_1, 0, 1, 4, QCOM_QOS_MODE_FIXED, 0, -1, 39, 0, 0); +DEFINE_QNODE(slv_blsp_2, MSM8996_SLAVE_BLSP_2, 0, 1, 4, QCOM_QOS_MODE_FIXED, 0, -1, 37, 0, 0); +DEFINE_QNODE(slv_camera_cfg, MSM8996_SLAVE_CAMERA_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 3, 0, 0); +DEFINE_QNODE(slv_camera_throttle_cfg, MSM8996_SLAVE_CAMERA_THROTTLE_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 154, 0, 0); +DEFINE_QNODE(slv_clk_ctl, MSM8996_SLAVE_CLK_CTL, 0, 1, 4, QCOM_QOS_MODE_FIXED, 0, -1, 47, 0, 0); +DEFINE_QNODE(slv_cnoc_a1noc, MSM8996_CNOC_SNOC_SLV, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 75, 1, MSM8996_CNOC_A1NOC_MAS); +DEFINE_QNODE(slv_cnoc_mnoc_cfg, MSM8996_SLAVE_CNOC_MNOC_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 66, 1, MSM8996_MASTER_CNOC_MNOC_CFG); +DEFINE_QNODE(slv_cnoc_mnoc_mmss_cfg, MSM8996_SLAVE_CNOC_MNOC_MMSS_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 58, 1, MSM8996_MASTER_CNOC_MNOC_MMSS_CFG); +DEFINE_QNODE(slv_cpr_apu_cfg, MSM8996_SLAVE_QDSS_RBCPR_APU_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 168, 0, 0); +DEFINE_QNODE(slv_cpr_cfg, MSM8996_SLAVE_CPR_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 6, 0, 0); +DEFINE_QNODE(slv_crypto0_cfg, MSM8996_SLAVE_CRYPTO_0_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 52, 0, 0); +DEFINE_QNODE(slv_dcc_cfg, MSM8996_SLAVE_DCC_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 155, 0, 0); +DEFINE_QNODE(slv_display_cfg, MSM8996_SLAVE_DISPLAY_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 4, 0, 0); +DEFINE_QNODE(slv_display_throttle_cfg, MSM8996_SLAVE_DISPLAY_THROTTLE_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 156, 0, 0); +DEFINE_QNODE(slv_dsa_cfg, MSM8996_SLAVE_DSA_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 157, 0, 0); +DEFINE_QNODE(slv_dsa_mpu_cfg, MSM8996_SLAVE_DSA_MPU_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 158, 0, 0); +DEFINE_QNODE(slv_ebi1_phy_cfg, MSM8996_SLAVE_EBI1_PHY_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 73, 0, 0); +DEFINE_QNODE(slv_ebi, MSM8996_SLAVE_EBI_CH0, 0, 2, 8, QCOM_QOS_MODE_FIXED, 0, -1, 0, 0, 0); +DEFINE_QNODE(slv_hmss_l3, MSM8996_SLAVE_HMSS_L3, 0, 1, 8, QCOM_QOS_MODE_FIXED, 0, -1, 160, 0, 0); +DEFINE_QNODE(slv_hmss, MSM8996_SLAVE_APPSS, 0, 1, 16, QCOM_QOS_MODE_FIXED, 1, -1, 20, 0, 0); +DEFINE_QNODE(slv_imem_cfg, MSM8996_SLAVE_IMEM_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 54, 0, 0); +DEFINE_QNODE(slv_imem, MSM8996_SLAVE_OCIMEM, 0, 1, 16, QCOM_QOS_MODE_FIXED, 0, -1, 26, 0, 0); +DEFINE_QNODE(slv_lpass, MSM8996_SLAVE_LPASS, 0, 1, 16, QCOM_QOS_MODE_FIXED, 1, -1, 21, 0, 0); +DEFINE_QNODE(slv_lpass_smmu_cfg, MSM8996_SLAVE_LPASS_SMMU_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 161, 0, 0); +DEFINE_QNODE(slv_message_ram, MSM8996_SLAVE_MESSAGE_RAM, 0, 1, 4, QCOM_QOS_MODE_FIXED, 0, -1, 55, 0, 0); +DEFINE_QNODE(slv_misc_cfg, MSM8996_SLAVE_MISC_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 8, 0, 0); +DEFINE_QNODE(slv_mmagic_cfg, MSM8996_SLAVE_MMAGIC_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 162, 0, 0); +DEFINE_QNODE(slv_mnoc_bimc, MSM8996_MNOC_BIMC_SLV, 0, 2, 32, QCOM_QOS_MODE_FIXED, 1, -1, 16, 1, MSM8996_MNOC_BIMC_MAS); +DEFINE_QNODE(slv_mnoc_clocks_cfg, MSM8996_SLAVE_MMSS_CLK_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 12, 0, 0); +DEFINE_QNODE(slv_mnoc_mpu_cfg, MSM8996_SLAVE_MNOC_MPU_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 14, 0, 0); +DEFINE_QNODE(slv_mpm, MSM8996_SLAVE_MPM, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 62, 0, 0); +DEFINE_QNODE(slv_oxili_cfg, MSM8996_SLAVE_GRAPHICS_3D_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 11, 0, 0); +DEFINE_QNODE(slv_pcie_0_cfg, MSM8996_SLAVE_PCIE_0_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 88, 0, 0); +DEFINE_QNODE(slv_pcie_0, MSM8996_SLAVE_PCIE_0, 0, 1, 16, QCOM_QOS_MODE_FIXED, 1, -1, 84, 0, 0); +DEFINE_QNODE(slv_pcie_1_cfg, MSM8996_SLAVE_PCIE_1_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 89, 0, 0); +DEFINE_QNODE(slv_pcie_1, MSM8996_SLAVE_PCIE_1, 0, 1, 16, QCOM_QOS_MODE_FIXED, 1, -1, 85, 0, 0); +DEFINE_QNODE(slv_pcie20_ahb2phy, MSM8996_SLAVE_PCIE20_AHB2PHY, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 163, 0, 0); +DEFINE_QNODE(slv_pcie_2_cfg, MSM8996_SLAVE_PCIE_2_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 165, 0, 0); +DEFINE_QNODE(slv_pcie_2, MSM8996_SLAVE_PCIE_2, 0, 1, 16, QCOM_QOS_MODE_FIXED, 1, -1, 164, 0, 0); +DEFINE_QNODE(slv_pdm, MSM8996_SLAVE_PDM, 0, 1, 4, QCOM_QOS_MODE_FIXED, 0, -1, 41, 0, 0); +DEFINE_QNODE(slv_pimem_cfg, MSM8996_SLAVE_PIMEM_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 167, 0, 0); +DEFINE_QNODE(slv_pimem, MSM8996_SLAVE_PIMEM, 0, 1, 16, QCOM_QOS_MODE_FIXED, 0, -1, 166, 0, 0); +DEFINE_QNODE(slv_pmic_arb, MSM8996_SLAVE_PMIC_ARB, 0, 1, 4, QCOM_QOS_MODE_FIXED, 0, -1, 59, 0, 0); +DEFINE_QNODE(slv_pnoc_a1noc, MSM8996_PNOC_A1NOC_SLV, 0, 1, 8, QCOM_QOS_MODE_FIXED, 0, -1, 139, 1, MSM8996_PNOC_A1NOC_MAS); +DEFINE_QNODE(slv_prng, MSM8996_SLAVE_PRNG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 44, 0, 0); +DEFINE_QNODE(slv_qdss_cfg, MSM8996_SLAVE_QDSS_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 63, 0, 0); +DEFINE_QNODE(slv_qdss_stm, MSM8996_SLAVE_QDSS_STM, 0, 1, 16, QCOM_QOS_MODE_FIXED, 0, -1, 30, 0, 0); +DEFINE_QNODE(slv_rbcpr_cx, MSM8996_SLAVE_RBCPR_CX, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 169, 0, 0); +DEFINE_QNODE(slv_rbcpr_mx, MSM8996_SLAVE_RBCPR_MX, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 170, 0, 0); +DEFINE_QNODE(slv_sdcc_1, MSM8996_SLAVE_SDCC_1, 0, 1, 4, QCOM_QOS_MODE_FIXED, 0, -1, 31, 0, 0); +DEFINE_QNODE(slv_sdcc_2, MSM8996_SLAVE_SDCC_2, 0, 1, 4, QCOM_QOS_MODE_FIXED, 0, -1, 33, 0, 0); +DEFINE_QNODE(slv_sdcc_4, MSM8996_SLAVE_SDCC_4, 0, 1, 4, QCOM_QOS_MODE_FIXED, 0, -1, 34, 0, 0); +DEFINE_QNODE(slv_smmu_cpp_cfg, MSM8996_SLAVE_SMMU_CPP_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 171, 0, 0); +DEFINE_QNODE(slv_smmu_jpeg_cfg, MSM8996_SLAVE_SMMU_JPEG_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 172, 0, 0); +DEFINE_QNODE(slv_smmu_mdp_cfg, MSM8996_SLAVE_SMMU_MDP_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 173, 0, 0); +DEFINE_QNODE(slv_smmu_rot_cfg, MSM8996_SLAVE_SMMU_ROTATOR_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 174, 0, 0); +DEFINE_QNODE(slv_smmu_venus_cfg, MSM8996_SLAVE_SMMU_VENUS_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 175, 0, 0); +DEFINE_QNODE(slv_smmu_vfe_cfg, MSM8996_SLAVE_SMMU_VFE_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 176, 0, 0); +DEFINE_QNODE(slv_snoc_bimc, MSM8996_SNOC_BIMC_SLV, 0, 2, 32, QCOM_QOS_MODE_FIXED, 0, -1, 24, 1, MSM8996_SNOC_BIMC_MAS); +DEFINE_QNODE(slv_snoc_cfg, MSM8996_SLAVE_SNOC_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 70, 0, 0); +DEFINE_QNODE(slv_snoc_cnoc, MSM8996_SNOC_CNOC_SLV, 0, 1, 16, QCOM_QOS_MODE_FIXED, 0, -1, 25, 1, MSM8996_SNOC_CNOC_MAS); +DEFINE_QNODE(slv_snoc_mpu_cfg, MSM8996_SLAVE_SNOC_MPU_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 67, 0, 0); +DEFINE_QNODE(slv_snoc_pnoc, MSM8996_SNOC_PNOC_SLV, 0, 1, 16, QCOM_QOS_MODE_FIXED, 0, -1, 28, 1, MSM8996_SNOC_PNOC_MAS); +DEFINE_QNODE(slv_snoc_vmem, MSM8996_SLAVE_SNOC_VMEM, 0, 1, 16, QCOM_QOS_MODE_FIXED, 1, -1, 140, 1, MSM8996_MASTER_SNOC_VMEM); +DEFINE_QNODE(slv_srvc_mnoc, MSM8996_SLAVE_SERVICE_MNOC, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 17, 0, 0); +DEFINE_QNODE(slv_srvc_snoc, MSM8996_SLAVE_SERVICE_SNOC, 0, 1, 16, QCOM_QOS_MODE_FIXED, 1, -1, 29, 0, 0); +DEFINE_QNODE(slv_ssc_cfg, MSM8996_SLAVE_SSC_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 177, 0, 0); +DEFINE_QNODE(slv_tcsr, MSM8996_SLAVE_TCSR, 0, 1, 4, QCOM_QOS_MODE_FIXED, 0, -1, 50, 0, 0); +DEFINE_QNODE(slv_tlmm, MSM8996_SLAVE_TLMM, 0, 1, 4, QCOM_QOS_MODE_FIXED, 0, -1, 51, 0, 0); +DEFINE_QNODE(slv_tsif, MSM8996_SLAVE_TSIF, 0, 1, 4, QCOM_QOS_MODE_FIXED, 0, -1, 35, 0, 0); +DEFINE_QNODE(slv_ufs_cfg, MSM8996_SLAVE_UFS_CFG, 0, 1, 4, QCOM_QOS_MODE_FIXED, 1, -1, 92, 0, 0); +DEFINE_QNODE(slv_usb3, MSM8996_SLAVE_USB3, 0, 1, 16, QCOM_QOS_MODE_FIXED, 1, -1, 22, 0, 0); +DEFINE_QNODE(slv_usb_hs, MSM8996_SLAVE_USB_HS, 0, 1, 4, QCOM_QOS_MODE_FIXED, 0, -1, 40, 0, 0); +DEFINE_QNODE(slv_venus_cfg, MSM8996_SLAVE_VENUS_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 10, 0, 0); +DEFINE_QNODE(slv_venus_throttle_cfg, MSM8996_SLAVE_VENUS_THROTTLE_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 178, 0, 0); +DEFINE_QNODE(slv_vmem_cfg, MSM8996_SLAVE_VMEM_CFG, 0, 1, 8, QCOM_QOS_MODE_FIXED, 1, -1, 180, 0, 0); +DEFINE_QNODE(slv_vmem, MSM8996_SLAVE_VMEM, 0, 1, 32, QCOM_QOS_MODE_FIXED, 1, -1, 179, 0, 0); + +static struct qcom_icc_node *msm8996_snoc_nodes[] = { + [A0NOC_SNOC_MAS] = &mas_a0noc_snoc, + [A0NOC_SNOC_SLV] = &slv_a0noc_snoc, + [A1NOC_SNOC_MAS] = &mas_a1noc_snoc, + [A1NOC_SNOC_SLV] = &slv_a1noc_snoc, + [A2NOC_SNOC_MAS] = &mas_a2noc_snoc, + [A2NOC_SNOC_SLV] = &slv_a2noc_snoc, + [BIMC_SNOC_1_MAS] = &mas_bimc_snoc_1, + [BIMC_SNOC_MAS] = &mas_bimc_snoc_0, + [MASTER_HMSS] = &mas_hmss, + [MASTER_QDSS_BAM] = &mas_qdss_bam, + [MASTER_QDSS_ETR] = &mas_qdss_etr, + [MASTER_SNOC_CFG] = &mas_snoc_cfg, + [SLAVE_APPSS] = &slv_hmss, + [SLAVE_LPASS] = &slv_lpass, + [SLAVE_OCIMEM] = &slv_imem, + [SLAVE_PCIE_0] = &slv_pcie_0, + [SLAVE_PCIE_1] = &slv_pcie_1, + [SLAVE_PCIE_2] = &slv_pcie_2, + [SLAVE_PIMEM] = &slv_pimem, + [SLAVE_QDSS_STM] = &slv_qdss_stm, + [SLAVE_SERVICE_SNOC] = &slv_srvc_snoc, + [SLAVE_SNOC_VMEM] = &slv_snoc_vmem, + [SLAVE_USB3] = &slv_usb3, + [SNOC_BIMC_SLV] = &slv_snoc_bimc, + [SNOC_CNOC_SLV] = &slv_snoc_cnoc, + [SNOC_PNOC_SLV] = &slv_snoc_pnoc, +}; + +static struct qcom_icc_desc msm8996_snoc = { + .nodes = msm8996_snoc_nodes, + .num_nodes = ARRAY_SIZE(msm8996_snoc_nodes), +}; + +static struct qcom_icc_node *msm8996_bimc_nodes[] = { + [BIMC_SNOC_SLV] = &slv_bimc_snoc_0, + [BIMC_SNOC_1_SLV] = &slv_bimc_snoc_1, + [MASTER_AMPSS_M0] = &mas_apps_proc, + [MASTER_GRAPHICS_3D] = &mas_oxili, + [MNOC_BIMC_MAS] = &mas_mnoc_bimc, + [SLAVE_EBI_CH0] = &slv_ebi, + [SLAVE_HMSS_L3] = &slv_hmss_l3, + [SNOC_BIMC_MAS] = &mas_snoc_bimc, +}; + +static struct qcom_icc_desc msm8996_bimc = { + .nodes = msm8996_bimc_nodes, + .num_nodes = ARRAY_SIZE(msm8996_bimc_nodes), +}; + +static struct qcom_icc_node *msm8996_pnoc_nodes[] = { + [MASTER_BLSP_1] = &mas_blsp_1, + [MASTER_BLSP_2] = &mas_blsp_2, + [MASTER_SDCC_1] = &mas_sdcc_1, + [MASTER_SDCC_2] = &mas_sdcc_2, + [MASTER_SDCC_4] = &mas_sdcc_4, + [MASTER_TSIF] = &mas_tsif, + [MASTER_USB_HS] = &mas_usb_hs, + [PNOC_A1NOC_SLV] = &slv_pnoc_a1noc, + [SLAVE_AHB2PHY] = &slv_ahb2phy, + [SLAVE_BLSP_1] = &slv_blsp_1, + [SLAVE_BLSP_2] = &slv_blsp_2, + [SLAVE_PDM] = &slv_pdm, + [SLAVE_SDCC_1] = &slv_sdcc_1, + [SLAVE_SDCC_2] = &slv_sdcc_2, + [SLAVE_SDCC_4] = &slv_sdcc_4, + [SLAVE_TSIF] = &slv_tsif, + [SLAVE_USB_HS] = &slv_usb_hs, + [SNOC_PNOC_MAS] = &mas_snoc_pnoc, +}; + +static struct qcom_icc_desc msm8996_pnoc = { + .nodes = msm8996_pnoc_nodes, + .num_nodes = ARRAY_SIZE(msm8996_pnoc_nodes), +}; + +static struct qcom_icc_node *msm8996_cnoc_nodes[] = { + [CNOC_SNOC_SLV] = &slv_cnoc_a1noc, + [MASTER_QDSS_DAP] = &mas_qdss_dap, + [SLAVE_A0NOC_CFG] = &slv_a0noc_cfg, + [SLAVE_A0NOC_MPU_CFG] = &slv_a0noc_mpu_cfg, + [SLAVE_A0NOC_SMMU_CFG] = &slv_a0noc_smmu_cfg, + [SLAVE_A1NOC_CFG] = &slv_a1noc_cfg, + [SLAVE_A1NOC_MPU_CFG] = &slv_a1noc_mpu_cfg, + [SLAVE_A1NOC_SMMU_CFG] = &slv_a1noc_smmu_cfg, + [SLAVE_A2NOC_CFG] = &slv_a2noc_cfg, + [SLAVE_A2NOC_MPU_CFG] = &slv_a2noc_mpu_cfg, + [SLAVE_A2NOC_SMMU_CFG] = &slv_a2noc_smmu_cfg, + [SLAVE_BIMC_CFG] = &slv_bimc_cfg, + [SLAVE_CLK_CTL] = &slv_clk_ctl, + [SLAVE_CNOC_MNOC_CFG] = &slv_cnoc_mnoc_cfg, + [SLAVE_CNOC_MNOC_MMSS_CFG] &slv_cnoc_mnoc_mmss_cfg, + [SLAVE_CRYPTO_0_CFG] = &slv_crypto0_cfg, + [SLAVE_DCC_CFG] = &slv_dcc_cfg, + [SLAVE_EBI1_PHY_CFG] = &slv_ebi1_phy_cfg, + [SLAVE_IMEM_CFG] = &slv_imem_cfg, + [SLAVE_LPASS_SMMU_CFG] = &slv_lpass_smmu_cfg, + [SLAVE_MESSAGE_RAM] = &slv_message_ram, + [SLAVE_MPM] = &slv_mpm, + [SLAVE_PCIE_0_CFG] = &slv_pcie_0_cfg, + [SLAVE_PCIE_1_CFG] = &slv_pcie_1_cfg, + [SLAVE_PCIE20_AHB2PHY] = &slv_pcie20_ahb2phy, + [SLAVE_PCIE_2_CFG] = &slv_pcie_2_cfg, + [SLAVE_PIMEM_CFG] = &slv_pimem_cfg, + [SLAVE_PMIC_ARB] = &slv_pmic_arb, + [SLAVE_PRNG] = &slv_prng, + [SLAVE_QDSS_CFG] = &slv_qdss_cfg, + [SLAVE_QDSS_RBCPR_APU_CFG] = &slv_cpr_apu_cfg, + [SLAVE_RBCPR_CX] = &slv_rbcpr_cx, + [SLAVE_RBCPR_MX] = &slv_rbcpr_mx, + [SLAVE_SNOC_CFG] = &slv_snoc_cfg, + [SLAVE_SNOC_MPU_CFG] = &slv_snoc_mpu_cfg, + [SLAVE_SSC_CFG] = &slv_ssc_cfg, + [SLAVE_TCSR] = &slv_tcsr, + [SLAVE_TLMM] = &slv_tlmm, + [SLAVE_UFS_CFG] = &slv_ufs_cfg, + [SNOC_CNOC_MAS] = &mas_snoc_cnoc, +}; + +static struct qcom_icc_desc msm8996_cnoc = { + .nodes = msm8996_cnoc_nodes, + .num_nodes = ARRAY_SIZE(msm8996_cnoc_nodes), +}; + +static struct qcom_icc_node *msm8996_mnoc_nodes[] = { + [MASTER_CNOC_MNOC_CFG] = &mas_cnoc_mnoc_cfg, + [MASTER_CNOC_MNOC_MMSS_CFG] = &mas_cnoc_mnoc_mmss_cfg, + [MASTER_CPP] = &mas_cpp, + [MASTER_JPEG] = &mas_jpeg, + [MASTER_MDP_PORT0] = &mas_mdp_p0, + [MASTER_MDP_PORT1] = &mas_mdp_p1, + [MASTER_ROTATOR] = &mas_rotator, + [MASTER_SNOC_VMEM] = &mas_snoc_vmem, + [MASTER_VFE] = &mas_vfe, + [MASTER_VIDEO_P0] = &mas_venus, + [MASTER_VIDEO_P0_OCMEM] = &mas_venus_vmem, + [MNOC_BIMC_SLV] = &slv_mnoc_bimc, + [SLAVE_CAMERA_CFG] = &slv_camera_cfg, + [SLAVE_CAMERA_THROTTLE_CFG] = &slv_camera_throttle_cfg, + [SLAVE_CPR_CFG] = &slv_cpr_cfg, + [SLAVE_DISPLAY_CFG] = &slv_display_cfg, + [SLAVE_DISPLAY_THROTTLE_CFG] = &slv_display_throttle_cfg, + [SLAVE_DSA_CFG] = &slv_dsa_cfg, + [SLAVE_DSA_MPU_CFG] = &slv_dsa_mpu_cfg, + [SLAVE_GRAPHICS_3D_CFG] = &slv_oxili_cfg, + [SLAVE_MISC_CFG] = &slv_misc_cfg, + [SLAVE_MMAGIC_CFG] = &slv_mmagic_cfg, + [SLAVE_MMSS_CLK_CFG] = &slv_mnoc_clocks_cfg, + [SLAVE_MNOC_MPU_CFG] = &slv_mnoc_mpu_cfg, + [SLAVE_SERVICE_MNOC] = &slv_srvc_mnoc, + [SLAVE_SMMU_CPP_CFG] = &slv_smmu_cpp_cfg, + [SLAVE_SMMU_JPEG_CFG] = &slv_smmu_jpeg_cfg, + [SLAVE_SMMU_MDP_CFG] = &slv_smmu_mdp_cfg, + [SLAVE_SMMU_ROTATOR_CFG] = &slv_smmu_rot_cfg, + [SLAVE_SMMU_VENUS_CFG] = &slv_smmu_venus_cfg, + [SLAVE_SMMU_VFE_CFG] = &slv_smmu_vfe_cfg, + [SLAVE_VENUS_CFG] = &slv_venus_cfg, + [SLAVE_VENUS_THROTTLE_CFG] = &slv_venus_throttle_cfg, + [SLAVE_VMEM_CFG] = &slv_vmem_cfg, + [SLAVE_VMEM] = &slv_vmem, +}; + +static struct qcom_icc_desc msm8996_mnoc = { + .nodes = msm8996_mnoc_nodes, + .num_nodes = ARRAY_SIZE(msm8996_mnoc_nodes), +}; + +static struct qcom_icc_node *msm8996_a0noc_nodes[] = { + [MASTER_PCIE] = &mas_pcie_0, + [MASTER_PCIE_1] = &mas_pcie_1, + [MASTER_PCIE_2] = &mas_pcie_2, +}; + +static struct qcom_icc_desc msm8996_a0noc = { + .nodes = msm8996_a0noc_nodes, + .num_nodes = ARRAY_SIZE(msm8996_a0noc_nodes), +}; + +static struct qcom_icc_node *msm8996_a1noc_nodes[] = { + [CNOC_A1NOC_MAS] = &mas_cnoc_a1noc, + [MASTER_CRYPTO_CORE0] = &mas_crypto_c0, + [PNOC_A1NOC_MAS] = &mas_pnoc_a1noc, +}; + +static struct qcom_icc_desc msm8996_a1noc = { + .nodes = msm8996_a1noc_nodes, + .num_nodes = ARRAY_SIZE(msm8996_a1noc_nodes), +}; + +static struct qcom_icc_node *msm8996_a2noc_nodes[] = { + [MASTER_IPA] = &mas_ipa, + [MASTER_UFS] = &mas_ufs, + [MASTER_USB3] = &mas_usb3, +}; + +static struct qcom_icc_desc msm8996_a2noc = { + .nodes = msm8996_a2noc_nodes, + .num_nodes = ARRAY_SIZE(msm8996_a2noc_nodes), +}; + +static int qcom_icc_aggregate(struct icc_node *node, u8 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 qcom_icc_set(struct icc_node *src, struct icc_node *dst) +{ + struct qcom_icc_provider *qp; + struct qcom_icc_node *qn; + struct icc_provider *provider; + struct icc_node *n; + u64 sum_bw; + u64 max_peak_bw; + u64 rate; + u32 agg_avg = 0; + u32 agg_peak = 0; + int ret = 0; + + qn = src->data; + provider = src->provider; + qp = to_qcom_provider(provider); + list_for_each_entry(n, &provider->nodes, node_list) + qcom_icc_aggregate(n, 0, n->avg_bw, n->peak_bw, + &agg_avg, &agg_peak); + + sum_bw = icc_units_to_bps(agg_avg); + max_peak_bw = icc_units_to_bps(agg_peak); + + /* set bandwidth */ + if (qn->ap_owned) { + /* TODO: set QoS */ + } else { + /* send message to the RPM processor */ + + if (qn->mas_rpm_id != -1) { + ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE, + RPM_BUS_MASTER_REQ, + qn->mas_rpm_id, + sum_bw); + if (ret) { + pr_err("qcom_icc_rpm_smd_send mas %d error %d\n", qn->mas_rpm_id, ret); + return ret; + } + } + + if (qn->slv_rpm_id != -1) { + ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE, + RPM_BUS_SLAVE_REQ, + qn->slv_rpm_id, + sum_bw); + if (ret) { + pr_err("qcom_icc_rpm_smd_send slv error %d\n", + ret); + return ret; + } + } + } + + rate = max(sum_bw, max_peak_bw); + + do_div(rate, qn->buswidth); + + if (qn->rate != rate) { + ret = clk_set_rate(qp->bus_clk, rate); + if (ret) { + pr_err("set clk rate %lld error %d\n", rate, ret); + return ret; + } + + ret = clk_set_rate(qp->bus_a_clk, rate); + if (ret) { + pr_err("set clk rate %lld error %d\n", rate, ret); + return ret; + } + + qn->rate = rate; + } + + return ret; +} + +static int qnoc_probe(struct platform_device *pdev) +{ + const struct qcom_icc_desc *desc; + struct icc_onecell_data *data; + struct icc_provider *provider; + struct qcom_icc_node **qnodes; + struct qcom_icc_provider *qp; + struct icc_node *node; + struct resource *res; + size_t num_nodes, i; + int ret; + + /* wait for RPM */ + if (!qcom_icc_rpm_smd_available()) + return -EPROBE_DEFER; + + desc = of_device_get_match_data(&pdev->dev); + if (!desc) + return -EINVAL; + + qnodes = desc->nodes; + num_nodes = desc->num_nodes; + + qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL); + if (!qp) + return -ENOMEM; + + data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL); + if (!data) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + qp->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(qp->base)) + return PTR_ERR(qp->base); + + qp->bus_clk = devm_clk_get(&pdev->dev, "bus_clk"); + if (IS_ERR(qp->bus_clk)) + return PTR_ERR(qp->bus_clk); + + ret = clk_prepare_enable(qp->bus_clk); + if (ret) { + dev_err(&pdev->dev, "error enabling bus_clk: %d\n", ret); + return ret; + } + + qp->bus_a_clk = devm_clk_get(&pdev->dev, "bus_a_clk"); + if (IS_ERR(qp->bus_a_clk)) + return PTR_ERR(qp->bus_a_clk); + + ret = clk_prepare_enable(qp->bus_a_clk); + if (ret) { + dev_err(&pdev->dev, "error enabling bus_a_clk: %d\n", ret); + clk_disable_unprepare(qp->bus_clk); + return ret; + } + + provider = &qp->provider; + INIT_LIST_HEAD(&provider->nodes); + provider->dev = &pdev->dev; + provider->set = qcom_icc_set; + provider->aggregate = qcom_icc_aggregate; + provider->xlate = of_icc_xlate_onecell; + provider->data = data; + + ret = icc_provider_add(provider); + if (ret) { + dev_err(&pdev->dev, "error adding interconnect provider\n"); + clk_disable_unprepare(qp->bus_clk); + clk_disable_unprepare(qp->bus_a_clk); + return ret; + } + + for (i = 0; i < num_nodes; i++) { + size_t j; + + node = icc_node_create(qnodes[i]->id); + if (IS_ERR(node)) { + ret = PTR_ERR(node); + goto err; + } + node->name = qnodes[i]->name; + node->data = qnodes[i]; + icc_node_add(node, provider); + + dev_dbg(&pdev->dev, "registered node %s\n", node->name); + + /* populate links */ + for (j = 0; j < qnodes[i]->num_links; j++) + icc_link_create(node, qnodes[i]->links[j]); + data->nodes[i] = node; + } + data->num_nodes = num_nodes; + + platform_set_drvdata(pdev, qp); + + return ret; +err: + list_for_each_entry(node, &provider->nodes, node_list) { + icc_node_del(node); + icc_node_destroy(node->id); + } + clk_disable_unprepare(qp->bus_clk); + clk_disable_unprepare(qp->bus_a_clk); + icc_provider_del(provider); + + return ret; +} + +static int qnoc_remove(struct platform_device *pdev) +{ + struct qcom_icc_provider *qp = platform_get_drvdata(pdev); + struct icc_provider *provider = &qp->provider; + struct icc_node *n; + + list_for_each_entry(n, &provider->nodes, node_list) { + icc_node_del(n); + icc_node_destroy(n->id); + } + clk_disable_unprepare(qp->bus_clk); + clk_disable_unprepare(qp->bus_a_clk); + + return icc_provider_del(provider); +} + +static const struct of_device_id qnoc_of_match[] = { + { .compatible = "qcom,msm8996-bimc", .data = &msm8996_bimc }, + { .compatible = "qcom,msm8996-cnoc", .data = &msm8996_cnoc }, + { .compatible = "qcom,msm8996-snoc", .data = &msm8996_snoc }, + { .compatible = "qcom,msm8996-a0noc", .data = &msm8996_a0noc }, + { .compatible = "qcom,msm8996-a1noc", .data = &msm8996_a1noc }, + { .compatible = "qcom,msm8996-a2noc", .data = &msm8996_a2noc }, + { .compatible = "qcom,msm8996-mmnoc", .data = &msm8996_mnoc }, + { .compatible = "qcom,msm8996-pnoc", .data = &msm8996_pnoc }, + { }, +}; +MODULE_DEVICE_TABLE(of, qnoc_of_match); + +static struct platform_driver qnoc_driver = { + .probe = qnoc_probe, + .remove = qnoc_remove, + .driver = { + .name = "qnoc-msm8996", + .of_match_table = qnoc_of_match, + }, +}; +module_platform_driver(qnoc_driver); +MODULE_AUTHOR("Georgi Djakov <georgi.djakov@linaro.org>"); +MODULE_DESCRIPTION("Qualcomm msm8996 NoC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/qcom/msm8996_ids.h b/drivers/interconnect/qcom/msm8996_ids.h new file mode 100644 index 000000000000..e025bad65765 --- /dev/null +++ b/drivers/interconnect/qcom/msm8996_ids.h @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Qualcomm MSM8996 interconnect IDs + * + * Copyright (c) 2018, Linaro Ltd. + * Author: Georgi Djakov <georgi.djakov@linaro.org> + */ + +#ifndef __DRIVERS_INTERCONNECT_QCOM_MSM8996_H +#define __DRIVERS_INTERCONNECT_QCOM_MSM8996_H + +#define MSM8996_A0NOC_SNOC_MAS 0 +#define MSM8996_A1NOC_SNOC_MAS 1 +#define MSM8996_A2NOC_SNOC_MAS 2 +#define MSM8996_MASTER_AMPSS_M0 3 +#define MSM8996_BIMC_SNOC_MAS 4 +#define MSM8996_BIMC_SNOC_1_MAS 5 +#define MSM8996_MASTER_BLSP_1 6 +#define MSM8996_MASTER_BLSP_2 7 +#define MSM8996_CNOC_A1NOC_MAS 8 +#define MSM8996_MASTER_CNOC_MNOC_CFG 9 +#define MSM8996_MASTER_CNOC_MNOC_MMSS_CFG 10 +#define MSM8996_MASTER_CPP 11 +#define MSM8996_MASTER_CRYPTO_CORE0 12 +#define MSM8996_MASTER_HMSS 13 +#define MSM8996_MASTER_IPA 14 +#define MSM8996_MASTER_JPEG 15 +#define MSM8996_MASTER_MDP_PORT0 16 +#define MSM8996_MASTER_MDP_PORT1 17 +#define MSM8996_MNOC_BIMC_MAS 18 +#define MSM8996_MASTER_GRAPHICS_3D 19 +#define MSM8996_MASTER_PCIE 20 +#define MSM8996_MASTER_PCIE_1 21 +#define MSM8996_MASTER_PCIE_2 22 +#define MSM8996_PNOC_A1NOC_MAS 23 +#define MSM8996_MASTER_QDSS_BAM 24 +#define MSM8996_MASTER_QDSS_DAP 25 +#define MSM8996_MASTER_QDSS_ETR 26 +#define MSM8996_MASTER_ROTATOR 27 +#define MSM8996_MASTER_SDCC_1 28 +#define MSM8996_MASTER_SDCC_2 29 +#define MSM8996_MASTER_SDCC_4 30 +#define MSM8996_SNOC_BIMC_MAS 31 +#define MSM8996_MASTER_SNOC_CFG 32 +#define MSM8996_SNOC_CNOC_MAS 33 +#define MSM8996_SNOC_PNOC_MAS 34 +#define MSM8996_MASTER_SNOC_VMEM 35 +#define MSM8996_MASTER_TSIF 36 +#define MSM8996_MASTER_UFS 37 +#define MSM8996_MASTER_USB3 38 +#define MSM8996_MASTER_USB_HS 39 +#define MSM8996_MASTER_VIDEO_P0 40 +#define MSM8996_MASTER_VIDEO_P0_OCMEM 41 +#define MSM8996_MASTER_VFE 42 +#define MSM8996_SLAVE_A0NOC_CFG 43 +#define MSM8996_SLAVE_A0NOC_MPU_CFG 44 +#define MSM8996_SLAVE_A0NOC_SMMU_CFG 45 +#define MSM8996_A0NOC_SNOC_SLV 46 +#define MSM8996_SLAVE_A1NOC_CFG 47 +#define MSM8996_SLAVE_A1NOC_MPU_CFG 48 +#define MSM8996_SLAVE_A1NOC_SMMU_CFG 49 +#define MSM8996_A1NOC_SNOC_SLV 50 +#define MSM8996_SLAVE_A2NOC_CFG 51 +#define MSM8996_SLAVE_A2NOC_MPU_CFG 52 +#define MSM8996_SLAVE_A2NOC_SMMU_CFG 53 +#define MSM8996_A2NOC_SNOC_SLV 54 +#define MSM8996_SLAVE_AHB2PHY 55 +#define MSM8996_SLAVE_BIMC_CFG 56 +#define MSM8996_BIMC_SNOC_SLV 57 +#define MSM8996_BIMC_SNOC_1_SLV 58 +#define MSM8996_SLAVE_BLSP_1 59 +#define MSM8996_SLAVE_BLSP_2 60 +#define MSM8996_SLAVE_CAMERA_CFG 61 +#define MSM8996_SLAVE_CAMERA_THROTTLE_CFG 62 +#define MSM8996_SLAVE_CLK_CTL 63 +#define MSM8996_CNOC_SNOC_SLV 64 +#define MSM8996_SLAVE_CNOC_MNOC_CFG 65 +#define MSM8996_SLAVE_CNOC_MNOC_MMSS_CFG 66 +#define MSM8996_SLAVE_QDSS_RBCPR_APU_CFG 67 +#define MSM8996_SLAVE_CPR_CFG 68 +#define MSM8996_SLAVE_CRYPTO_0_CFG 69 +#define MSM8996_SLAVE_DCC_CFG 70 +#define MSM8996_SLAVE_DISPLAY_CFG 71 +#define MSM8996_SLAVE_DISPLAY_THROTTLE_CFG 72 +#define MSM8996_SLAVE_DSA_CFG 73 +#define MSM8996_SLAVE_DSA_MPU_CFG 74 +#define MSM8996_SLAVE_EBI1_PHY_CFG 75 +#define MSM8996_SLAVE_EBI_CH0 76 +#define MSM8996_SLAVE_HMSS_L3 77 +#define MSM8996_SLAVE_APPSS 78 +#define MSM8996_SLAVE_IMEM_CFG 79 +#define MSM8996_SLAVE_OCIMEM 80 +#define MSM8996_SLAVE_LPASS 81 +#define MSM8996_SLAVE_LPASS_SMMU_CFG 82 +#define MSM8996_SLAVE_MESSAGE_RAM 83 +#define MSM8996_SLAVE_MISC_CFG 84 +#define MSM8996_SLAVE_MMAGIC_CFG 85 +#define MSM8996_MNOC_BIMC_SLV 86 +#define MSM8996_SLAVE_MMSS_CLK_CFG 87 +#define MSM8996_SLAVE_MNOC_MPU_CFG 88 +#define MSM8996_SLAVE_MPM 89 +#define MSM8996_SLAVE_GRAPHICS_3D_CFG 90 +#define MSM8996_SLAVE_PCIE_0_CFG 91 +#define MSM8996_SLAVE_PCIE_0 92 +#define MSM8996_SLAVE_PCIE_1_CFG 93 +#define MSM8996_SLAVE_PCIE_1 94 +#define MSM8996_SLAVE_PCIE20_AHB2PHY 95 +#define MSM8996_SLAVE_PCIE_2_CFG 96 +#define MSM8996_SLAVE_PCIE_2 97 +#define MSM8996_SLAVE_PDM 98 +#define MSM8996_SLAVE_PIMEM_CFG 99 +#define MSM8996_SLAVE_PIMEM 100 +#define MSM8996_SLAVE_PMIC_ARB 101 +#define MSM8996_PNOC_A1NOC_SLV 102 +#define MSM8996_SLAVE_PRNG 103 +#define MSM8996_SLAVE_QDSS_CFG 104 +#define MSM8996_SLAVE_QDSS_STM 105 +#define MSM8996_SLAVE_RBCPR_CX 106 +#define MSM8996_SLAVE_RBCPR_MX 107 +#define MSM8996_SLAVE_SDCC_1 108 +#define MSM8996_SLAVE_SDCC_2 109 +#define MSM8996_SLAVE_SDCC_4 110 +#define MSM8996_SLAVE_SMMU_CPP_CFG 111 +#define MSM8996_SLAVE_SMMU_JPEG_CFG 112 +#define MSM8996_SLAVE_SMMU_MDP_CFG 113 +#define MSM8996_SLAVE_SMMU_ROTATOR_CFG 114 +#define MSM8996_SLAVE_SMMU_VENUS_CFG 115 +#define MSM8996_SLAVE_SMMU_VFE_CFG 116 +#define MSM8996_SNOC_BIMC_SLV 117 +#define MSM8996_SLAVE_SNOC_CFG 118 +#define MSM8996_SNOC_CNOC_SLV 119 +#define MSM8996_SLAVE_SNOC_MPU_CFG 120 +#define MSM8996_SNOC_PNOC_SLV 121 +#define MSM8996_SLAVE_SNOC_VMEM 122 +#define MSM8996_SLAVE_SERVICE_MNOC 123 +#define MSM8996_SLAVE_SERVICE_SNOC 124 +#define MSM8996_SLAVE_SSC_CFG 125 +#define MSM8996_SLAVE_TCSR 126 +#define MSM8996_SLAVE_TLMM 127 +#define MSM8996_SLAVE_TSIF 128 +#define MSM8996_SLAVE_UFS_CFG 129 +#define MSM8996_SLAVE_USB3 130 +#define MSM8996_SLAVE_USB_HS 131 +#define MSM8996_SLAVE_VENUS_CFG 132 +#define MSM8996_SLAVE_VENUS_THROTTLE_CFG 133 +#define MSM8996_SLAVE_VMEM_CFG 134 +#define MSM8996_SLAVE_VMEM 135 + +#endif diff --git a/drivers/interconnect/qcom/sdm845.c b/drivers/interconnect/qcom/sdm845.c new file mode 100644 index 000000000000..481842c7edaa --- /dev/null +++ b/drivers/interconnect/qcom/sdm845.c @@ -0,0 +1,887 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + */ + +#include <asm/div64.h> +#include <dt-bindings/interconnect/qcom,sdm845.h> +#include <linux/device.h> +#include <linux/interconnect.h> +#include <linux/interconnect-provider.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/sort.h> + +#include <soc/qcom/cmd-db.h> +#include <soc/qcom/rpmh.h> +#include <soc/qcom/tcs.h> + +#define BCM_TCS_CMD_COMMIT_SHFT 30 +#define BCM_TCS_CMD_COMMIT_MASK 0x40000000 +#define BCM_TCS_CMD_VALID_SHFT 29 +#define BCM_TCS_CMD_VALID_MASK 0x20000000 +#define BCM_TCS_CMD_VOTE_X_SHFT 14 +#define BCM_TCS_CMD_VOTE_MASK 0x3fff +#define BCM_TCS_CMD_VOTE_Y_SHFT 0 +#define BCM_TCS_CMD_VOTE_Y_MASK 0xfffc000 + +#define BCM_TCS_CMD(commit, valid, vote_x, vote_y) \ + (((commit) << BCM_TCS_CMD_COMMIT_SHFT) | \ + ((valid) << BCM_TCS_CMD_VALID_SHFT) | \ + ((cpu_to_le32(vote_x) & \ + BCM_TCS_CMD_VOTE_MASK) << BCM_TCS_CMD_VOTE_X_SHFT) | \ + ((cpu_to_le32(vote_y) & \ + BCM_TCS_CMD_VOTE_MASK) << BCM_TCS_CMD_VOTE_Y_SHFT)) + +#define to_qcom_provider(_provider) \ + container_of(_provider, struct qcom_icc_provider, provider) + +struct qcom_icc_provider { + struct icc_provider provider; + struct device *dev; + struct qcom_icc_bcm **bcms; + size_t num_bcms; +}; + +/** + * struct bcm_db - Auxiliary data pertaining to each Bus Clock Manager (BCM) + * @unit: divisor used to convert bytes/sec bw value to an RPMh msg + * @width: multiplier used to convert bytes/sec bw value to an RPMh msg + * @vcd: virtual clock domain that this bcm belongs to + * @reserved: reserved field + */ +struct bcm_db { + __le32 unit; + __le16 width; + u8 vcd; + u8 reserved; +}; + +#define SDM845_MAX_LINKS 43 +#define SDM845_MAX_BCMS 30 +#define SDM845_MAX_BCM_PER_NODE 2 +#define SDM845_MAX_VCD 10 +#define SDM845_MAX_CTX 2 +#define SDM845_EE_STATE 2 +#define EE_STATE_WAKE 0 +#define EE_STATE_SLEEP 1 +#define AO_CTX 0 +#define DUAL_CTX 1 + +/** + * struct qcom_icc_node - Qualcomm specific interconnect nodes + * @name: the node name used in debugfs + * @links: an array of nodes where we can go next while traversing + * @id: a unique node identifier + * @num_links: the total number of @links + * @channels: num of channels at this node + * @buswidth: width of the interconnect between a node and the bus + * @sum_avg: current sum aggregate value of all avg bw requests + * @max_peak: current max aggregate value of all peak bw requests + * @bcms: list of bcms associated with this logical node + * @num_bcms: num of @bcms + */ +struct qcom_icc_node { + const char *name; + u16 links[SDM845_MAX_LINKS]; + u16 id; + u16 num_links; + u16 channels; + u16 buswidth; + u64 sum_avg[SDM845_MAX_CTX]; + u64 max_peak[SDM845_MAX_CTX]; + struct qcom_icc_bcm *bcms[SDM845_MAX_BCM_PER_NODE]; + size_t num_bcms; +}; + +/** + * struct qcom_icc_bcm - Qualcomm specific hardware accelerator nodes + * known as Bus Clock Manager (BCM) + * @name: the bcm node name used to fetch BCM data from command db + * @type: latency or bandwidth bcm + * @addr: address offsets used when voting to RPMH + * @vote_x: aggregated threshold values, represents sum_bw when @type is bw bcm + * @vote_y: aggregated threshold values, represents peak_bw when @type is bw bcm + * @dirty: flag used to indicate whether the bcm needs to be committed + * @keepalive: flag used to indicate whether a keepalive is required + * @aux_data: auxiliary data used when calculating threshold values and + * communicating with RPMh + * @list: used to link to other bcms when compiling lists for commit + * @num_nodes: total number of @num_nodes + * @nodes: list of qcom_icc_nodes that this BCM encapsulates + */ +struct qcom_icc_bcm { + const char *name; + u32 type; + u32 addr; + u64 vote_x[SDM845_EE_STATE]; + u64 vote_y[SDM845_EE_STATE]; + bool dirty; + bool keepalive; + struct bcm_db aux_data; + struct list_head list; + size_t num_nodes; + struct qcom_icc_node *nodes[]; +}; + +struct qcom_icc_fabric { + struct qcom_icc_node **nodes; + size_t num_nodes; +}; + +struct qcom_icc_desc { + struct qcom_icc_node **nodes; + size_t num_nodes; + struct qcom_icc_bcm **bcms; + size_t num_bcms; +}; + +#define DEFINE_QNODE(_name, _id, _channels, _buswidth, \ + _numlinks, ...) \ + static struct qcom_icc_node _name = { \ + .id = _id, \ + .name = #_name, \ + .channels = _channels, \ + .buswidth = _buswidth, \ + .num_links = _numlinks, \ + .links = { __VA_ARGS__ }, \ + } + +DEFINE_QNODE(qhm_a1noc_cfg, MASTER_A1NOC_CFG, 1, 4, 1, SLAVE_SERVICE_A1NOC); +DEFINE_QNODE(qhm_qup1, MASTER_BLSP_1, 1, 4, 1, SLAVE_A1NOC_SNOC); +DEFINE_QNODE(qhm_tsif, MASTER_TSIF, 1, 4, 1, SLAVE_A1NOC_SNOC); +DEFINE_QNODE(xm_sdc2, MASTER_SDCC_2, 1, 8, 1, SLAVE_A1NOC_SNOC); +DEFINE_QNODE(xm_sdc4, MASTER_SDCC_4, 1, 8, 1, SLAVE_A1NOC_SNOC); +DEFINE_QNODE(xm_ufs_card, MASTER_UFS_CARD, 1, 8, 1, SLAVE_A1NOC_SNOC); +DEFINE_QNODE(xm_ufs_mem, MASTER_UFS_MEM, 1, 8, 1, SLAVE_A1NOC_SNOC); +DEFINE_QNODE(xm_pcie_0, MASTER_PCIE_0, 1, 8, 1, SLAVE_ANOC_PCIE_A1NOC_SNOC); +DEFINE_QNODE(qhm_a2noc_cfg, MASTER_A2NOC_CFG, 1, 4, 1, SLAVE_SERVICE_A2NOC); +DEFINE_QNODE(qhm_qdss_bam, MASTER_QDSS_BAM, 1, 4, 1, SLAVE_A2NOC_SNOC); +DEFINE_QNODE(qhm_qup2, MASTER_BLSP_2, 1, 4, 1, SLAVE_A2NOC_SNOC); +DEFINE_QNODE(qnm_cnoc, MASTER_CNOC_A2NOC, 1, 8, 1, SLAVE_A2NOC_SNOC); +DEFINE_QNODE(qxm_crypto, MASTER_CRYPTO, 1, 8, 1, SLAVE_A2NOC_SNOC); +DEFINE_QNODE(qxm_ipa, MASTER_IPA, 1, 8, 1, SLAVE_A2NOC_SNOC); +DEFINE_QNODE(xm_pcie3_1, MASTER_PCIE_1, 1, 8, 1, SLAVE_ANOC_PCIE_SNOC); +DEFINE_QNODE(xm_qdss_etr, MASTER_QDSS_ETR, 1, 8, 1, SLAVE_A2NOC_SNOC); +DEFINE_QNODE(xm_usb3_0, MASTER_USB3_0, 1, 8, 1, SLAVE_A2NOC_SNOC); +DEFINE_QNODE(xm_usb3_1, MASTER_USB3_1, 1, 8, 1, SLAVE_A2NOC_SNOC); +DEFINE_QNODE(qxm_camnoc_hf0_uncomp, MASTER_CAMNOC_HF0_UNCOMP, 1, 32, 1, SLAVE_CAMNOC_UNCOMP); +DEFINE_QNODE(qxm_camnoc_hf1_uncomp, MASTER_CAMNOC_HF1_UNCOMP, 1, 32, 1, SLAVE_CAMNOC_UNCOMP); +DEFINE_QNODE(qxm_camnoc_sf_uncomp, MASTER_CAMNOC_SF_UNCOMP, 1, 32, 1, SLAVE_CAMNOC_UNCOMP); +DEFINE_QNODE(qhm_spdm, MASTER_SPDM, 1, 4, 1, SLAVE_CNOC_A2NOC); +DEFINE_QNODE(qhm_tic, MASTER_TIC, 1, 4, 43, SLAVE_A1NOC_CFG, SLAVE_A2NOC_CFG, SLAVE_AOP, SLAVE_AOSS, SLAVE_CAMERA_CFG, SLAVE_CLK_CTL, SLAVE_CDSP_CFG, SLAVE_RBCPR_CX_CFG, SLAVE_CRYPTO_0_CFG, SLAVE_DCC_CFG, SLAVE_CNOC_DDRSS, SLAVE_DISPLAY_CFG, SLAVE_GLM, SLAVE_GFX3D_CFG, SLAVE_IMEM_CFG, SLAVE_IPA_CFG, SLAVE_CNOC_MNOC_CFG, SLAVE_PCIE_0_CFG, SLAVE_PCIE_1_CFG, SLAVE_PDM, SLAVE_SOUTH_PHY_CFG, SLAVE_PIMEM_CFG, SLAVE_PRNG, SLAVE_QDSS_CFG, SLAVE_BLSP_2, SLAVE_BLSP_1, SLAVE_SDCC_2, SLAVE_SDCC_4, SLAVE_SNOC_CFG, SLAVE_SPDM_WRAPPER, SLAVE_SPSS_CFG, SLAVE_TCSR, SLAVE_TLMM_NORTH, SLAVE_TLMM_SOUTH, SLAVE_TSIF, SLAVE_UFS_CARD_CFG, SLAVE_UFS_MEM_CFG, SLAVE_USB3_0, SLAVE_USB3_1, SLAVE_VENUS_CFG, SLAVE_VSENSE_CTRL_CFG, SLAVE_CNOC_A2NOC, SLAVE_SERVICE_CNOC); +DEFINE_QNODE(qnm_snoc, MASTER_SNOC_CNOC, 1, 8, 42, SLAVE_A1NOC_CFG, SLAVE_A2NOC_CFG, SLAVE_AOP, SLAVE_AOSS, SLAVE_CAMERA_CFG, SLAVE_CLK_CTL, SLAVE_CDSP_CFG, SLAVE_RBCPR_CX_CFG, SLAVE_CRYPTO_0_CFG, SLAVE_DCC_CFG, SLAVE_CNOC_DDRSS, SLAVE_DISPLAY_CFG, SLAVE_GLM, SLAVE_GFX3D_CFG, SLAVE_IMEM_CFG, SLAVE_IPA_CFG, SLAVE_CNOC_MNOC_CFG, SLAVE_PCIE_0_CFG, SLAVE_PCIE_1_CFG, SLAVE_PDM, SLAVE_SOUTH_PHY_CFG, SLAVE_PIMEM_CFG, SLAVE_PRNG, SLAVE_QDSS_CFG, SLAVE_BLSP_2, SLAVE_BLSP_1, SLAVE_SDCC_2, SLAVE_SDCC_4, SLAVE_SNOC_CFG, SLAVE_SPDM_WRAPPER, SLAVE_SPSS_CFG, SLAVE_TCSR, SLAVE_TLMM_NORTH, SLAVE_TLMM_SOUTH, SLAVE_TSIF, SLAVE_UFS_CARD_CFG, SLAVE_UFS_MEM_CFG, SLAVE_USB3_0, SLAVE_USB3_1, SLAVE_VENUS_CFG, SLAVE_VSENSE_CTRL_CFG, SLAVE_SERVICE_CNOC); +DEFINE_QNODE(xm_qdss_dap, MASTER_QDSS_DAP, 1, 8, 43, SLAVE_A1NOC_CFG, SLAVE_A2NOC_CFG, SLAVE_AOP, SLAVE_AOSS, SLAVE_CAMERA_CFG, SLAVE_CLK_CTL, SLAVE_CDSP_CFG, SLAVE_RBCPR_CX_CFG, SLAVE_CRYPTO_0_CFG, SLAVE_DCC_CFG, SLAVE_CNOC_DDRSS, SLAVE_DISPLAY_CFG, SLAVE_GLM, SLAVE_GFX3D_CFG, SLAVE_IMEM_CFG, SLAVE_IPA_CFG, SLAVE_CNOC_MNOC_CFG, SLAVE_PCIE_0_CFG, SLAVE_PCIE_1_CFG, SLAVE_PDM, SLAVE_SOUTH_PHY_CFG, SLAVE_PIMEM_CFG, SLAVE_PRNG, SLAVE_QDSS_CFG, SLAVE_BLSP_2, SLAVE_BLSP_1, SLAVE_SDCC_2, SLAVE_SDCC_4, SLAVE_SNOC_CFG, SLAVE_SPDM_WRAPPER, SLAVE_SPSS_CFG, SLAVE_TCSR, SLAVE_TLMM_NORTH, SLAVE_TLMM_SOUTH, SLAVE_TSIF, SLAVE_UFS_CARD_CFG, SLAVE_UFS_MEM_CFG, SLAVE_USB3_0, SLAVE_USB3_1, SLAVE_VENUS_CFG, SLAVE_VSENSE_CTRL_CFG, SLAVE_CNOC_A2NOC, SLAVE_SERVICE_CNOC); +DEFINE_QNODE(qhm_cnoc, MASTER_CNOC_DC_NOC, 1, 4, 2, SLAVE_LLCC_CFG, SLAVE_MEM_NOC_CFG); +DEFINE_QNODE(acm_l3, MASTER_APPSS_PROC, 1, 16, 3, SLAVE_GNOC_SNOC, SLAVE_GNOC_MEM_NOC, SLAVE_SERVICE_GNOC); +DEFINE_QNODE(pm_gnoc_cfg, MASTER_GNOC_CFG, 1, 4, 1, SLAVE_SERVICE_GNOC); +DEFINE_QNODE(llcc_mc, MASTER_LLCC, 4, 4, 1, SLAVE_EBI1); +DEFINE_QNODE(acm_tcu, MASTER_TCU_0, 1, 8, 3, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC, SLAVE_MEM_NOC_SNOC); +DEFINE_QNODE(qhm_memnoc_cfg, MASTER_MEM_NOC_CFG, 1, 4, 2, SLAVE_MSS_PROC_MS_MPU_CFG, SLAVE_SERVICE_MEM_NOC); +DEFINE_QNODE(qnm_apps, MASTER_GNOC_MEM_NOC, 2, 32, 1, SLAVE_LLCC); +DEFINE_QNODE(qnm_mnoc_hf, MASTER_MNOC_HF_MEM_NOC, 2, 32, 2, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC); +DEFINE_QNODE(qnm_mnoc_sf, MASTER_MNOC_SF_MEM_NOC, 1, 32, 3, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC, SLAVE_MEM_NOC_SNOC); +DEFINE_QNODE(qnm_snoc_gc, MASTER_SNOC_GC_MEM_NOC, 1, 8, 1, SLAVE_LLCC); +DEFINE_QNODE(qnm_snoc_sf, MASTER_SNOC_SF_MEM_NOC, 1, 16, 2, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC); +DEFINE_QNODE(qxm_gpu, MASTER_GFX3D, 2, 32, 3, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC, SLAVE_MEM_NOC_SNOC); +DEFINE_QNODE(qhm_mnoc_cfg, MASTER_CNOC_MNOC_CFG, 1, 4, 1, SLAVE_SERVICE_MNOC); +DEFINE_QNODE(qxm_camnoc_hf0, MASTER_CAMNOC_HF0, 1, 32, 1, SLAVE_MNOC_HF_MEM_NOC); +DEFINE_QNODE(qxm_camnoc_hf1, MASTER_CAMNOC_HF1, 1, 32, 1, SLAVE_MNOC_HF_MEM_NOC); +DEFINE_QNODE(qxm_camnoc_sf, MASTER_CAMNOC_SF, 1, 32, 1, SLAVE_MNOC_SF_MEM_NOC); +DEFINE_QNODE(qxm_mdp0, MASTER_MDP0, 1, 32, 1, SLAVE_MNOC_HF_MEM_NOC); +DEFINE_QNODE(qxm_mdp1, MASTER_MDP1, 1, 32, 1, SLAVE_MNOC_HF_MEM_NOC); +DEFINE_QNODE(qxm_rot, MASTER_ROTATOR, 1, 32, 1, SLAVE_MNOC_SF_MEM_NOC); +DEFINE_QNODE(qxm_venus0, MASTER_VIDEO_P0, 1, 32, 1, SLAVE_MNOC_SF_MEM_NOC); +DEFINE_QNODE(qxm_venus1, MASTER_VIDEO_P1, 1, 32, 1, SLAVE_MNOC_SF_MEM_NOC); +DEFINE_QNODE(qxm_venus_arm9, MASTER_VIDEO_PROC, 1, 8, 1, SLAVE_MNOC_SF_MEM_NOC); +DEFINE_QNODE(qhm_snoc_cfg, MASTER_SNOC_CFG, 1, 4, 1, SLAVE_SERVICE_SNOC); +DEFINE_QNODE(qnm_aggre1_noc, MASTER_A1NOC_SNOC, 1, 16, 6, SLAVE_APPSS, SLAVE_SNOC_CNOC, SLAVE_SNOC_MEM_NOC_SF, SLAVE_IMEM, SLAVE_PIMEM, SLAVE_QDSS_STM); +DEFINE_QNODE(qnm_aggre2_noc, MASTER_A2NOC_SNOC, 1, 16, 9, SLAVE_APPSS, SLAVE_SNOC_CNOC, SLAVE_SNOC_MEM_NOC_SF, SLAVE_IMEM, SLAVE_PCIE_0, SLAVE_PCIE_1, SLAVE_PIMEM, SLAVE_QDSS_STM, SLAVE_TCU); +DEFINE_QNODE(qnm_gladiator_sodv, MASTER_GNOC_SNOC, 1, 8, 8, SLAVE_APPSS, SLAVE_SNOC_CNOC, SLAVE_IMEM, SLAVE_PCIE_0, SLAVE_PCIE_1, SLAVE_PIMEM, SLAVE_QDSS_STM, SLAVE_TCU); +DEFINE_QNODE(qnm_memnoc, MASTER_MEM_NOC_SNOC, 1, 8, 5, SLAVE_APPSS, SLAVE_SNOC_CNOC, SLAVE_IMEM, SLAVE_PIMEM, SLAVE_QDSS_STM); +DEFINE_QNODE(qnm_pcie_anoc, MASTER_ANOC_PCIE_SNOC, 1, 16, 5, SLAVE_APPSS, SLAVE_SNOC_CNOC, SLAVE_SNOC_MEM_NOC_SF, SLAVE_IMEM, SLAVE_QDSS_STM); +DEFINE_QNODE(qxm_pimem, MASTER_PIMEM, 1, 8, 2, SLAVE_SNOC_MEM_NOC_GC, SLAVE_IMEM); +DEFINE_QNODE(xm_gic, MASTER_GIC, 1, 8, 2, SLAVE_SNOC_MEM_NOC_GC, SLAVE_IMEM); +DEFINE_QNODE(qns_a1noc_snoc, SLAVE_A1NOC_SNOC, 1, 16, 1, MASTER_A1NOC_SNOC); +DEFINE_QNODE(srvc_aggre1_noc, SLAVE_SERVICE_A1NOC, 1, 4, 0); +DEFINE_QNODE(qns_pcie_a1noc_snoc, SLAVE_ANOC_PCIE_A1NOC_SNOC, 1, 16, 1, MASTER_ANOC_PCIE_SNOC); +DEFINE_QNODE(qns_a2noc_snoc, SLAVE_A2NOC_SNOC, 1, 16, 1, MASTER_A2NOC_SNOC); +DEFINE_QNODE(qns_pcie_snoc, SLAVE_ANOC_PCIE_SNOC, 1, 16, 1, MASTER_ANOC_PCIE_SNOC); +DEFINE_QNODE(srvc_aggre2_noc, SLAVE_SERVICE_A2NOC, 1, 4, 0); +DEFINE_QNODE(qns_camnoc_uncomp, SLAVE_CAMNOC_UNCOMP, 1, 32, 0); +DEFINE_QNODE(qhs_a1_noc_cfg, SLAVE_A1NOC_CFG, 1, 4, 1, MASTER_A1NOC_CFG); +DEFINE_QNODE(qhs_a2_noc_cfg, SLAVE_A2NOC_CFG, 1, 4, 1, MASTER_A2NOC_CFG); +DEFINE_QNODE(qhs_aop, SLAVE_AOP, 1, 4, 0); +DEFINE_QNODE(qhs_aoss, SLAVE_AOSS, 1, 4, 0); +DEFINE_QNODE(qhs_camera_cfg, SLAVE_CAMERA_CFG, 1, 4, 0); +DEFINE_QNODE(qhs_clk_ctl, SLAVE_CLK_CTL, 1, 4, 0); +DEFINE_QNODE(qhs_compute_dsp_cfg, SLAVE_CDSP_CFG, 1, 4, 0); +DEFINE_QNODE(qhs_cpr_cx, SLAVE_RBCPR_CX_CFG, 1, 4, 0); +DEFINE_QNODE(qhs_crypto0_cfg, SLAVE_CRYPTO_0_CFG, 1, 4, 0); +DEFINE_QNODE(qhs_dcc_cfg, SLAVE_DCC_CFG, 1, 4, 1, MASTER_CNOC_DC_NOC); +DEFINE_QNODE(qhs_ddrss_cfg, SLAVE_CNOC_DDRSS, 1, 4, 0); +DEFINE_QNODE(qhs_display_cfg, SLAVE_DISPLAY_CFG, 1, 4, 0); +DEFINE_QNODE(qhs_glm, SLAVE_GLM, 1, 4, 0); +DEFINE_QNODE(qhs_gpuss_cfg, SLAVE_GFX3D_CFG, 1, 8, 0); +DEFINE_QNODE(qhs_imem_cfg, SLAVE_IMEM_CFG, 1, 4, 0); +DEFINE_QNODE(qhs_ipa, SLAVE_IPA_CFG, 1, 4, 0); +DEFINE_QNODE(qhs_mnoc_cfg, SLAVE_CNOC_MNOC_CFG, 1, 4, 1, MASTER_CNOC_MNOC_CFG); +DEFINE_QNODE(qhs_pcie0_cfg, SLAVE_PCIE_0_CFG, 1, 4, 0); +DEFINE_QNODE(qhs_pcie_gen3_cfg, SLAVE_PCIE_1_CFG, 1, 4, 0); +DEFINE_QNODE(qhs_pdm, SLAVE_PDM, 1, 4, 0); +DEFINE_QNODE(qhs_phy_refgen_south, SLAVE_SOUTH_PHY_CFG, 1, 4, 0); +DEFINE_QNODE(qhs_pimem_cfg, SLAVE_PIMEM_CFG, 1, 4, 0); +DEFINE_QNODE(qhs_prng, SLAVE_PRNG, 1, 4, 0); +DEFINE_QNODE(qhs_qdss_cfg, SLAVE_QDSS_CFG, 1, 4, 0); +DEFINE_QNODE(qhs_qupv3_north, SLAVE_BLSP_2, 1, 4, 0); +DEFINE_QNODE(qhs_qupv3_south, SLAVE_BLSP_1, 1, 4, 0); +DEFINE_QNODE(qhs_sdc2, SLAVE_SDCC_2, 1, 4, 0); +DEFINE_QNODE(qhs_sdc4, SLAVE_SDCC_4, 1, 4, 0); +DEFINE_QNODE(qhs_snoc_cfg, SLAVE_SNOC_CFG, 1, 4, 1, MASTER_SNOC_CFG); +DEFINE_QNODE(qhs_spdm, SLAVE_SPDM_WRAPPER, 1, 4, 0); +DEFINE_QNODE(qhs_spss_cfg, SLAVE_SPSS_CFG, 1, 4, 0); +DEFINE_QNODE(qhs_tcsr, SLAVE_TCSR, 1, 4, 0); +DEFINE_QNODE(qhs_tlmm_north, SLAVE_TLMM_NORTH, 1, 4, 0); +DEFINE_QNODE(qhs_tlmm_south, SLAVE_TLMM_SOUTH, 1, 4, 0); +DEFINE_QNODE(qhs_tsif, SLAVE_TSIF, 1, 4, 0); +DEFINE_QNODE(qhs_ufs_card_cfg, SLAVE_UFS_CARD_CFG, 1, 4, 0); +DEFINE_QNODE(qhs_ufs_mem_cfg, SLAVE_UFS_MEM_CFG, 1, 4, 0); +DEFINE_QNODE(qhs_usb3_0, SLAVE_USB3_0, 1, 4, 0); +DEFINE_QNODE(qhs_usb3_1, SLAVE_USB3_1, 1, 4, 0); +DEFINE_QNODE(qhs_venus_cfg, SLAVE_VENUS_CFG, 1, 4, 0); +DEFINE_QNODE(qhs_vsense_ctrl_cfg, SLAVE_VSENSE_CTRL_CFG, 1, 4, 0); +DEFINE_QNODE(qns_cnoc_a2noc, SLAVE_CNOC_A2NOC, 1, 8, 1, MASTER_CNOC_A2NOC); +DEFINE_QNODE(srvc_cnoc, SLAVE_SERVICE_CNOC, 1, 4, 0); +DEFINE_QNODE(qhs_llcc, SLAVE_LLCC_CFG, 1, 4, 0); +DEFINE_QNODE(qhs_memnoc, SLAVE_MEM_NOC_CFG, 1, 4, 1, MASTER_MEM_NOC_CFG); +DEFINE_QNODE(qns_gladiator_sodv, SLAVE_GNOC_SNOC, 1, 8, 1, MASTER_GNOC_SNOC); +DEFINE_QNODE(qns_gnoc_memnoc, SLAVE_GNOC_MEM_NOC, 2, 32, 1, MASTER_GNOC_MEM_NOC); +DEFINE_QNODE(srvc_gnoc, SLAVE_SERVICE_GNOC, 1, 4, 0); +DEFINE_QNODE(ebi, SLAVE_EBI1, 4, 4, 0); +DEFINE_QNODE(qhs_mdsp_ms_mpu_cfg, SLAVE_MSS_PROC_MS_MPU_CFG, 1, 4, 0); +DEFINE_QNODE(qns_apps_io, SLAVE_MEM_NOC_GNOC, 1, 32, 0); +DEFINE_QNODE(qns_llcc, SLAVE_LLCC, 4, 16, 1, MASTER_LLCC); +DEFINE_QNODE(qns_memnoc_snoc, SLAVE_MEM_NOC_SNOC, 1, 8, 1, MASTER_MEM_NOC_SNOC); +DEFINE_QNODE(srvc_memnoc, SLAVE_SERVICE_MEM_NOC, 1, 4, 0); +DEFINE_QNODE(qns2_mem_noc, SLAVE_MNOC_SF_MEM_NOC, 1, 32, 1, MASTER_MNOC_SF_MEM_NOC); +DEFINE_QNODE(qns_mem_noc_hf, SLAVE_MNOC_HF_MEM_NOC, 2, 32, 1, MASTER_MNOC_HF_MEM_NOC); +DEFINE_QNODE(srvc_mnoc, SLAVE_SERVICE_MNOC, 1, 4, 0); +DEFINE_QNODE(qhs_apss, SLAVE_APPSS, 1, 8, 0); +DEFINE_QNODE(qns_cnoc, SLAVE_SNOC_CNOC, 1, 8, 1, MASTER_SNOC_CNOC); +DEFINE_QNODE(qns_memnoc_gc, SLAVE_SNOC_MEM_NOC_GC, 1, 8, 1, MASTER_SNOC_GC_MEM_NOC); +DEFINE_QNODE(qns_memnoc_sf, SLAVE_SNOC_MEM_NOC_SF, 1, 16, 1, MASTER_SNOC_SF_MEM_NOC); +DEFINE_QNODE(qxs_imem, SLAVE_IMEM, 1, 8, 0); +DEFINE_QNODE(qxs_pcie, SLAVE_PCIE_0, 1, 8, 0); +DEFINE_QNODE(qxs_pcie_gen3, SLAVE_PCIE_1, 1, 8, 0); +DEFINE_QNODE(qxs_pimem, SLAVE_PIMEM, 1, 8, 0); +DEFINE_QNODE(srvc_snoc, SLAVE_SERVICE_SNOC, 1, 4, 0); +DEFINE_QNODE(xs_qdss_stm, SLAVE_QDSS_STM, 1, 4, 0); +DEFINE_QNODE(xs_sys_tcu_cfg, SLAVE_TCU, 1, 8, 0); + +#define DEFINE_QBCM(_name, _bcmname, _keepalive, _numnodes, ...) \ + static struct qcom_icc_bcm _name = { \ + .name = _bcmname, \ + .keepalive = _keepalive, \ + .num_nodes = _numnodes, \ + .nodes = { __VA_ARGS__ }, \ + } + +DEFINE_QBCM(bcm_acv, "ACV", false, 1, &ebi); +DEFINE_QBCM(bcm_mc0, "MC0", true, 1, &ebi); +DEFINE_QBCM(bcm_sh0, "SH0", true, 1, &qns_llcc); +DEFINE_QBCM(bcm_mm0, "MM0", false, 1, &qns_mem_noc_hf); +DEFINE_QBCM(bcm_sh1, "SH1", false, 1, &qns_apps_io); +DEFINE_QBCM(bcm_mm1, "MM1", false, 7, &qxm_camnoc_hf0_uncomp, &qxm_camnoc_hf1_uncomp, &qxm_camnoc_sf_uncomp, &qxm_camnoc_hf0, &qxm_camnoc_hf1, &qxm_mdp0, &qxm_mdp1); +DEFINE_QBCM(bcm_sh2, "SH2", false, 1, &qns_memnoc_snoc); +DEFINE_QBCM(bcm_mm2, "MM2", false, 1, &qns2_mem_noc); +DEFINE_QBCM(bcm_sh3, "SH3", false, 1, &acm_tcu); +DEFINE_QBCM(bcm_mm3, "MM3", false, 5, &qxm_camnoc_sf, &qxm_rot, &qxm_venus0, &qxm_venus1, &qxm_venus_arm9); +DEFINE_QBCM(bcm_sh5, "SH5", false, 1, &qnm_apps); +DEFINE_QBCM(bcm_sn0, "SN0", true, 1, &qns_memnoc_sf); +DEFINE_QBCM(bcm_ce0, "CE0", false, 1, &qxm_crypto); +DEFINE_QBCM(bcm_cn0, "CN0", false, 47, &qhm_spdm, &qhm_tic, &qnm_snoc, &xm_qdss_dap, &qhs_a1_noc_cfg, &qhs_a2_noc_cfg, &qhs_aop, &qhs_aoss, &qhs_camera_cfg, &qhs_clk_ctl, &qhs_compute_dsp_cfg, &qhs_cpr_cx, &qhs_crypto0_cfg, &qhs_dcc_cfg, &qhs_ddrss_cfg, &qhs_display_cfg, &qhs_glm, &qhs_gpuss_cfg, &qhs_imem_cfg, &qhs_ipa, &qhs_mnoc_cfg, &qhs_pcie0_cfg, &qhs_pcie_gen3_cfg, &qhs_pdm, &qhs_phy_refgen_south, &qhs_pimem_cfg, &qhs_prng, &qhs_qdss_cfg, &qhs_qupv3_north, &qhs_qupv3_south, &qhs_sdc2, &qhs_sdc4, &qhs_snoc_cfg, &qhs_spdm, &qhs_spss_cfg, &qhs_tcsr, &qhs_tlmm_north, &qhs_tlmm_south, &qhs_tsif, &qhs_ufs_card_cfg, &qhs_ufs_mem_cfg, &qhs_usb3_0, &qhs_usb3_1, &qhs_venus_cfg, &qhs_vsense_ctrl_cfg, &qns_cnoc_a2noc, &srvc_cnoc); +DEFINE_QBCM(bcm_qup0, "QUP0", false, 2, &qhm_qup1, &qhm_qup2); +DEFINE_QBCM(bcm_sn1, "SN1", false, 1, &qxs_imem); +DEFINE_QBCM(bcm_sn2, "SN2", false, 1, &qns_memnoc_gc); +DEFINE_QBCM(bcm_sn3, "SN3", false, 1, &qns_cnoc); +DEFINE_QBCM(bcm_sn4, "SN4", false, 1, &qxm_pimem); +DEFINE_QBCM(bcm_sn5, "SN5", false, 1, &xs_qdss_stm); +DEFINE_QBCM(bcm_sn6, "SN6", false, 3, &qhs_apss, &srvc_snoc, &xs_sys_tcu_cfg); +DEFINE_QBCM(bcm_sn7, "SN7", false, 1, &qxs_pcie); +DEFINE_QBCM(bcm_sn8, "SN8", false, 1, &qxs_pcie_gen3); +DEFINE_QBCM(bcm_sn9, "SN9", false, 2, &srvc_aggre1_noc, &qnm_aggre1_noc); +DEFINE_QBCM(bcm_sn11, "SN11", false, 2, &srvc_aggre2_noc, &qnm_aggre2_noc); +DEFINE_QBCM(bcm_sn12, "SN12", false, 2, &qnm_gladiator_sodv, &xm_gic); +DEFINE_QBCM(bcm_sn14, "SN14", false, 1, &qnm_pcie_anoc); +DEFINE_QBCM(bcm_sn15, "SN15", false, 1, &qnm_memnoc); + +static struct qcom_icc_node *rsc_hlos_nodes[] = { + [MASTER_APPSS_PROC] = &acm_l3, + [MASTER_TCU_0] = &acm_tcu, + [MASTER_LLCC] = &llcc_mc, + [MASTER_GNOC_CFG] = &pm_gnoc_cfg, + [MASTER_A1NOC_CFG] = &qhm_a1noc_cfg, + [MASTER_A2NOC_CFG] = &qhm_a2noc_cfg, + [MASTER_CNOC_DC_NOC] = &qhm_cnoc, + [MASTER_MEM_NOC_CFG] = &qhm_memnoc_cfg, + [MASTER_CNOC_MNOC_CFG] = &qhm_mnoc_cfg, + [MASTER_QDSS_BAM] = &qhm_qdss_bam, + [MASTER_BLSP_1] = &qhm_qup1, + [MASTER_BLSP_2] = &qhm_qup2, + [MASTER_SNOC_CFG] = &qhm_snoc_cfg, + [MASTER_SPDM] = &qhm_spdm, + [MASTER_TIC] = &qhm_tic, + [MASTER_TSIF] = &qhm_tsif, + [MASTER_A1NOC_SNOC] = &qnm_aggre1_noc, + [MASTER_A2NOC_SNOC] = &qnm_aggre2_noc, + [MASTER_GNOC_MEM_NOC] = &qnm_apps, + [MASTER_CNOC_A2NOC] = &qnm_cnoc, + [MASTER_GNOC_SNOC] = &qnm_gladiator_sodv, + [MASTER_MEM_NOC_SNOC] = &qnm_memnoc, + [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf, + [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf, + [MASTER_ANOC_PCIE_SNOC] = &qnm_pcie_anoc, + [MASTER_SNOC_CNOC] = &qnm_snoc, + [MASTER_SNOC_GC_MEM_NOC] = &qnm_snoc_gc, + [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf, + [MASTER_CAMNOC_HF0] = &qxm_camnoc_hf0, + [MASTER_CAMNOC_HF0_UNCOMP] = &qxm_camnoc_hf0_uncomp, + [MASTER_CAMNOC_HF1] = &qxm_camnoc_hf1, + [MASTER_CAMNOC_HF1_UNCOMP] = &qxm_camnoc_hf1_uncomp, + [MASTER_CAMNOC_SF] = &qxm_camnoc_sf, + [MASTER_CAMNOC_SF_UNCOMP] = &qxm_camnoc_sf_uncomp, + [MASTER_CRYPTO] = &qxm_crypto, + [MASTER_GFX3D] = &qxm_gpu, + [MASTER_IPA] = &qxm_ipa, + [MASTER_MDP0] = &qxm_mdp0, + [MASTER_MDP1] = &qxm_mdp1, + [MASTER_PIMEM] = &qxm_pimem, + [MASTER_ROTATOR] = &qxm_rot, + [MASTER_VIDEO_P0] = &qxm_venus0, + [MASTER_VIDEO_P1] = &qxm_venus1, + [MASTER_VIDEO_PROC] = &qxm_venus_arm9, + [MASTER_GIC] = &xm_gic, + [MASTER_PCIE_1] = &xm_pcie3_1, + [MASTER_PCIE_0] = &xm_pcie_0, + [MASTER_QDSS_DAP] = &xm_qdss_dap, + [MASTER_QDSS_ETR] = &xm_qdss_etr, + [MASTER_SDCC_2] = &xm_sdc2, + [MASTER_SDCC_4] = &xm_sdc4, + [MASTER_UFS_CARD] = &xm_ufs_card, + [MASTER_UFS_MEM] = &xm_ufs_mem, + [MASTER_USB3_0] = &xm_usb3_0, + [MASTER_USB3_1] = &xm_usb3_1, + [SLAVE_EBI1] = &ebi, + [SLAVE_A1NOC_CFG] = &qhs_a1_noc_cfg, + [SLAVE_A2NOC_CFG] = &qhs_a2_noc_cfg, + [SLAVE_AOP] = &qhs_aop, + [SLAVE_AOSS] = &qhs_aoss, + [SLAVE_APPSS] = &qhs_apss, + [SLAVE_CAMERA_CFG] = &qhs_camera_cfg, + [SLAVE_CLK_CTL] = &qhs_clk_ctl, + [SLAVE_CDSP_CFG] = &qhs_compute_dsp_cfg, + [SLAVE_RBCPR_CX_CFG] = &qhs_cpr_cx, + [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg, + [SLAVE_DCC_CFG] = &qhs_dcc_cfg, + [SLAVE_CNOC_DDRSS] = &qhs_ddrss_cfg, + [SLAVE_DISPLAY_CFG] = &qhs_display_cfg, + [SLAVE_GLM] = &qhs_glm, + [SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg, + [SLAVE_IMEM_CFG] = &qhs_imem_cfg, + [SLAVE_IPA_CFG] = &qhs_ipa, + [SLAVE_LLCC_CFG] = &qhs_llcc, + [SLAVE_MSS_PROC_MS_MPU_CFG] = &qhs_mdsp_ms_mpu_cfg, + [SLAVE_MEM_NOC_CFG] = &qhs_memnoc, + [SLAVE_CNOC_MNOC_CFG] = &qhs_mnoc_cfg, + [SLAVE_PCIE_0_CFG] = &qhs_pcie0_cfg, + [SLAVE_PCIE_1_CFG] = &qhs_pcie_gen3_cfg, + [SLAVE_PDM] = &qhs_pdm, + [SLAVE_SOUTH_PHY_CFG] = &qhs_phy_refgen_south, + [SLAVE_PIMEM_CFG] = &qhs_pimem_cfg, + [SLAVE_PRNG] = &qhs_prng, + [SLAVE_QDSS_CFG] = &qhs_qdss_cfg, + [SLAVE_BLSP_2] = &qhs_qupv3_north, + [SLAVE_BLSP_1] = &qhs_qupv3_south, + [SLAVE_SDCC_2] = &qhs_sdc2, + [SLAVE_SDCC_4] = &qhs_sdc4, + [SLAVE_SNOC_CFG] = &qhs_snoc_cfg, + [SLAVE_SPDM_WRAPPER] = &qhs_spdm, + [SLAVE_SPSS_CFG] = &qhs_spss_cfg, + [SLAVE_TCSR] = &qhs_tcsr, + [SLAVE_TLMM_NORTH] = &qhs_tlmm_north, + [SLAVE_TLMM_SOUTH] = &qhs_tlmm_south, + [SLAVE_TSIF] = &qhs_tsif, + [SLAVE_UFS_CARD_CFG] = &qhs_ufs_card_cfg, + [SLAVE_UFS_MEM_CFG] = &qhs_ufs_mem_cfg, + [SLAVE_USB3_0] = &qhs_usb3_0, + [SLAVE_USB3_1] = &qhs_usb3_1, + [SLAVE_VENUS_CFG] = &qhs_venus_cfg, + [SLAVE_VSENSE_CTRL_CFG] = &qhs_vsense_ctrl_cfg, + [SLAVE_MNOC_SF_MEM_NOC] = &qns2_mem_noc, + [SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc, + [SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc, + [SLAVE_MEM_NOC_GNOC] = &qns_apps_io, + [SLAVE_CAMNOC_UNCOMP] = &qns_camnoc_uncomp, + [SLAVE_SNOC_CNOC] = &qns_cnoc, + [SLAVE_CNOC_A2NOC] = &qns_cnoc_a2noc, + [SLAVE_GNOC_SNOC] = &qns_gladiator_sodv, + [SLAVE_GNOC_MEM_NOC] = &qns_gnoc_memnoc, + [SLAVE_LLCC] = &qns_llcc, + [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf, + [SLAVE_SNOC_MEM_NOC_GC] = &qns_memnoc_gc, + [SLAVE_SNOC_MEM_NOC_SF] = &qns_memnoc_sf, + [SLAVE_MEM_NOC_SNOC] = &qns_memnoc_snoc, + [SLAVE_ANOC_PCIE_A1NOC_SNOC] = &qns_pcie_a1noc_snoc, + [SLAVE_ANOC_PCIE_SNOC] = &qns_pcie_snoc, + [SLAVE_IMEM] = &qxs_imem, + [SLAVE_PCIE_0] = &qxs_pcie, + [SLAVE_PCIE_1] = &qxs_pcie_gen3, + [SLAVE_PIMEM] = &qxs_pimem, + [SLAVE_SERVICE_A1NOC] = &srvc_aggre1_noc, + [SLAVE_SERVICE_A2NOC] = &srvc_aggre2_noc, + [SLAVE_SERVICE_CNOC] = &srvc_cnoc, + [SLAVE_SERVICE_GNOC] = &srvc_gnoc, + [SLAVE_SERVICE_MEM_NOC] = &srvc_memnoc, + [SLAVE_SERVICE_MNOC] = &srvc_mnoc, + [SLAVE_SERVICE_SNOC] = &srvc_snoc, + [SLAVE_QDSS_STM] = &xs_qdss_stm, + [SLAVE_TCU] = &xs_sys_tcu_cfg, +}; + +static struct qcom_icc_bcm *rsc_hlos_bcms[] = { + &bcm_acv, + &bcm_mc0, + &bcm_sh0, + &bcm_mm0, + &bcm_sh1, + &bcm_mm1, + &bcm_sh2, + &bcm_mm2, + &bcm_sh3, + &bcm_mm3, + &bcm_sh5, + &bcm_sn0, + &bcm_ce0, + &bcm_cn0, + &bcm_qup0, + &bcm_sn1, + &bcm_sn2, + &bcm_sn3, + &bcm_sn4, + &bcm_sn5, + &bcm_sn6, + &bcm_sn7, + &bcm_sn8, + &bcm_sn9, + &bcm_sn11, + &bcm_sn12, + &bcm_sn14, + &bcm_sn15, +}; + +static struct qcom_icc_desc sdm845_rsc_hlos = { + .nodes = rsc_hlos_nodes, + .num_nodes = ARRAY_SIZE(rsc_hlos_nodes), + .bcms = rsc_hlos_bcms, + .num_bcms = ARRAY_SIZE(rsc_hlos_bcms), +}; + +static int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev) +{ + struct qcom_icc_node *qn; + const struct bcm_db *data; + size_t data_count; + int i; + + bcm->addr = cmd_db_read_addr(bcm->name); + if (!bcm->addr) { + dev_err(dev, "%s could not find RPMh address\n", + bcm->name); + return -EINVAL; + } + + data = cmd_db_read_aux_data(bcm->name, &data_count); + if (IS_ERR(data)) { + dev_err(dev, "%s command db read error (%ld)\n", + bcm->name, PTR_ERR(data)); + return PTR_ERR(data); + } + if (!data_count) { + dev_err(dev, "%s command db missing or partial aux data\n", + bcm->name); + return -EINVAL; + } + + bcm->aux_data.unit = le32_to_cpu(data->unit); + bcm->aux_data.width = le16_to_cpu(data->width); + bcm->aux_data.vcd = data->vcd; + bcm->aux_data.reserved = data->reserved; + + /* + * Link Qnodes to their respective BCMs + */ + for (i = 0; i < bcm->num_nodes; i++) { + qn = bcm->nodes[i]; + qn->bcms[qn->num_bcms] = bcm; + qn->num_bcms++; + } + + return 0; +} + +inline void tcs_cmd_gen(struct tcs_cmd *cmd, u64 vote_x, u64 vote_y, + u32 addr, bool commit) +{ + bool valid = true; + + if (!cmd) + return; + + if (vote_x == 0 && vote_y == 0) + valid = false; + + if (vote_x > BCM_TCS_CMD_VOTE_MASK) + vote_x = BCM_TCS_CMD_VOTE_MASK; + + if (vote_y > BCM_TCS_CMD_VOTE_MASK) + vote_y = BCM_TCS_CMD_VOTE_MASK; + + cmd->addr = addr; + cmd->data = BCM_TCS_CMD(commit, valid, vote_x, vote_y); + + /* + * Set the wait for completion flag on command that need to be completed + * before the next command. + */ + if (commit) + cmd->wait = true; +} + +static void tcs_list_gen(struct list_head *bcm_list, int ee_state, + struct tcs_cmd tcs_list[SDM845_MAX_VCD], + int n[SDM845_MAX_VCD]) +{ + struct qcom_icc_bcm *bcm; + bool commit; + size_t idx = 0, batch = 0, cur_vcd_size = 0; + + memset(n, 0, sizeof(int) * SDM845_MAX_VCD); + + list_for_each_entry(bcm, bcm_list, list) { + commit = false; + cur_vcd_size++; + if ((list_is_last(&bcm->list, bcm_list)) || + bcm->aux_data.vcd != list_next_entry(bcm, list)->aux_data.vcd) { + commit = true; + cur_vcd_size = 0; + } + tcs_cmd_gen(&tcs_list[idx], bcm->vote_x[ee_state], + bcm->vote_y[ee_state], bcm->addr, commit); + idx++; + n[batch]++; + /* + * Batch the BCMs in such a way that we do not split them in + * multiple payloads when they are under the same VCD. This is + * to ensure that every BCM is committed since we only set the + * commit bit on the last BCM request of every VCD. + */ + if (n[batch] >= MAX_RPMH_PAYLOAD) { + if (!commit) { + n[batch] -= cur_vcd_size; + n[batch + 1] = cur_vcd_size; + } + batch++; + } + } +} + +static void bcm_aggregate(struct qcom_icc_bcm *bcm) +{ + size_t i, ctx_idx; + u64 agg_avg[SDM845_MAX_CTX] = {0}; + u64 agg_peak[SDM845_MAX_CTX] = {0}; + u64 temp; + + for (ctx_idx = 0; ctx_idx < SDM845_MAX_CTX; ctx_idx++) { + for (i = 0; i < bcm->num_nodes; i++) { + temp = bcm->nodes[i]->sum_avg[ctx_idx] * bcm->aux_data.width; + do_div(temp, bcm->nodes[i]->buswidth * bcm->nodes[i]->channels); + agg_avg[ctx_idx] = max(agg_avg[ctx_idx], temp); + + temp = bcm->nodes[i]->max_peak[ctx_idx] * bcm->aux_data.width; + do_div(temp, bcm->nodes[i]->buswidth); + agg_peak[ctx_idx] = max(agg_peak[ctx_idx], temp); + } + } + + temp = agg_avg[AO_CTX] + agg_avg[DUAL_CTX] * 1000ULL; + do_div(temp, bcm->aux_data.unit); + bcm->vote_x[EE_STATE_WAKE] = temp; + + temp = max(agg_peak[AO_CTX], agg_peak[DUAL_CTX]) * 1000ULL; + do_div(temp, bcm->aux_data.unit); + bcm->vote_y[EE_STATE_WAKE] = temp; + + temp = agg_avg[DUAL_CTX] * 1000ULL; + do_div(temp, bcm->aux_data.unit); + bcm->vote_x[EE_STATE_SLEEP] = temp; + + temp = agg_peak[DUAL_CTX] * 1000ULL; + do_div(temp, bcm->aux_data.unit); + bcm->vote_y[EE_STATE_SLEEP] = temp; + + if (bcm->keepalive && bcm->vote_x == 0 && bcm->vote_y == 0) { + bcm->vote_x[EE_STATE_WAKE] = 1; + bcm->vote_y[EE_STATE_WAKE] = 1; + } + + bcm->dirty = false; +} + +static int qcom_icc_aggregate(struct icc_node *node, u8 tag, u32 avg_bw, + u32 peak_bw, u32 *agg_avg, u32 *agg_peak) +{ + size_t i; + struct qcom_icc_node *qn; + u32 ctx_idx = 0; + + qn = node->data; + ctx_idx = (!!tag) ? AO_CTX : DUAL_CTX; + + *agg_avg += avg_bw; + *agg_peak = max_t(u32, *agg_peak, peak_bw); + + qn->sum_avg[ctx_idx] = *agg_avg; + qn->max_peak[ctx_idx] = *agg_peak; + + for (i = 0; i < qn->num_bcms; i++) + qn->bcms[i]->dirty = true; + + return 0; +} + +static int qcom_icc_set(struct icc_node *src, struct icc_node *dst) +{ + struct qcom_icc_provider *qp; + struct icc_node *node; + struct tcs_cmd cmds[SDM845_MAX_BCMS]; + struct list_head commit_list; + int commit_idx[SDM845_MAX_VCD]; + int ret = 0, i; + + if (!src) + node = dst; + else + node = src; + + qp = to_qcom_provider(node->provider); + + INIT_LIST_HEAD(&commit_list); + + for (i = 0; i < qp->num_bcms; i++) { + if (qp->bcms[i]->dirty) { + bcm_aggregate(qp->bcms[i]); + list_add_tail(&qp->bcms[i]->list, &commit_list); + } + } + + /* + * Construct the command list based on a pre ordered list of BCMs + * based on VCD. + */ + tcs_list_gen(&commit_list, EE_STATE_WAKE, cmds, commit_idx); + + if (!commit_idx[0]) + return ret; + + ret = rpmh_invalidate(qp->dev); + if (ret) { + pr_err("Error invalidating RPMH client (%d)\n", ret); + return ret; + } + + ret = rpmh_write_batch(qp->dev, RPMH_ACTIVE_ONLY_STATE, + cmds, commit_idx); + if (ret) { + pr_err("Error sending AMC RPMH requests (%d)\n", ret); + return ret; + } + + INIT_LIST_HEAD(&commit_list); + + for (i = 0; i < qp->num_bcms; i++) { + /* Only generate WAKE and SLEEP commands if a resource's + * requirements change as the execution environment transitions + * between different power states. + */ + if (qp->bcms[i]->vote_x[EE_STATE_WAKE] != + qp->bcms[i]->vote_x[EE_STATE_SLEEP] || + qp->bcms[i]->vote_y[EE_STATE_WAKE] != + qp->bcms[i]->vote_y[EE_STATE_SLEEP]) { + list_add_tail(&qp->bcms[i]->list, &commit_list); + } + } + + tcs_list_gen(&commit_list, EE_STATE_WAKE, cmds, commit_idx); + + ret = rpmh_write_batch(qp->dev, RPMH_WAKE_ONLY_STATE, cmds, commit_idx); + if (ret) { + pr_err("Error sending WAKE RPMH requests (%d)\n", ret); + return ret; + } + + tcs_list_gen(&commit_list, EE_STATE_SLEEP, cmds, commit_idx); + + ret = rpmh_write_batch(qp->dev, RPMH_SLEEP_STATE, cmds, commit_idx); + if (ret) { + pr_err("Error sending SLEEP RPMH requests (%d)\n", ret); + return ret; + } + + return ret; +} + +static int cmp_vcd(const void *_l, const void *_r) +{ + const struct qcom_icc_bcm **l = (const struct qcom_icc_bcm **)_l; + const struct qcom_icc_bcm **r = (const struct qcom_icc_bcm **)_r; + + if (l[0]->aux_data.vcd < r[0]->aux_data.vcd) + return -1; + else if (l[0]->aux_data.vcd == r[0]->aux_data.vcd) + return 0; + else + return 1; +} + +static int qnoc_probe(struct platform_device *pdev) +{ + const struct qcom_icc_desc *desc; + struct icc_onecell_data *data; + struct icc_provider *provider; + struct qcom_icc_node **qnodes; + struct qcom_icc_provider *qp; + struct icc_node *node; + size_t num_nodes, i; + int ret; + + desc = of_device_get_match_data(&pdev->dev); + if (!desc) + return -EINVAL; + + qnodes = desc->nodes; + num_nodes = desc->num_nodes; + + qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL); + if (!qp) + return -ENOMEM; + + data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL); + if (!data) + return -ENOMEM; + + provider = &qp->provider; + provider->dev = &pdev->dev; + provider->set = qcom_icc_set; + provider->aggregate = qcom_icc_aggregate; + provider->xlate = of_icc_xlate_onecell; + INIT_LIST_HEAD(&provider->nodes); + provider->data = data; + + qp->dev = &pdev->dev; + qp->bcms = desc->bcms; + qp->num_bcms = desc->num_bcms; + + ret = icc_provider_add(provider); + if (ret) { + dev_err(&pdev->dev, "error adding interconnect provider\n"); + return ret; + } + + for (i = 0; i < num_nodes; i++) { + size_t j; + + node = icc_node_create(qnodes[i]->id); + if (IS_ERR(node)) { + ret = PTR_ERR(node); + goto err; + } + + node->name = qnodes[i]->name; + node->data = qnodes[i]; + icc_node_add(node, provider); + + dev_dbg(&pdev->dev, "registered node %p %s %d\n", node, + qnodes[i]->name, node->id); + + /* populate links */ + for (j = 0; j < qnodes[i]->num_links; j++) + icc_link_create(node, qnodes[i]->links[j]); + + data->nodes[i] = node; + } + data->num_nodes = num_nodes; + + for (i = 0; i < qp->num_bcms; i++) + qcom_icc_bcm_init(qp->bcms[i], &pdev->dev); + + /* + * Pre sort the BCMs based on VCD for ease of generating a command list + * that groups the BCMs with the same VCD together. VCDs are numbered + * with lowest being the most expensive time wise, ensuring that + * those commands are being sent the earliest in the queue. + */ + sort(qp->bcms, qp->num_bcms, sizeof(*qp->bcms), cmp_vcd, NULL); + + platform_set_drvdata(pdev, qp); + + dev_dbg(&pdev->dev, "Registered SDM845 ICC\n"); + + return ret; +err: + list_for_each_entry(node, &provider->nodes, node_list) { + icc_node_del(node); + icc_node_destroy(node->id); + } + + icc_provider_del(provider); + return ret; +} + +static int qnoc_remove(struct platform_device *pdev) +{ + struct qcom_icc_provider *qp = platform_get_drvdata(pdev); + struct icc_provider *provider = &qp->provider; + struct icc_node *n; + + list_for_each_entry(n, &provider->nodes, node_list) { + icc_node_del(n); + icc_node_destroy(n->id); + } + + return icc_provider_del(provider); +} + +static const struct of_device_id qnoc_of_match[] = { + { .compatible = "qcom,sdm845-rsc-hlos", .data = &sdm845_rsc_hlos }, + { }, +}; +MODULE_DEVICE_TABLE(of, qnoc_of_match); + +static struct platform_driver qnoc_driver = { + .probe = qnoc_probe, + .remove = qnoc_remove, + .driver = { + .name = "qnoc-sdm845", + .of_match_table = qnoc_of_match, + }, +}; +module_platform_driver(qnoc_driver); + +MODULE_AUTHOR("David Dai <daidavid1@codeaurora.org>"); +MODULE_DESCRIPTION("Qualcomm sdm845 NoC driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/qcom/smd-rpm.c b/drivers/interconnect/qcom/smd-rpm.c new file mode 100644 index 000000000000..48b7a2a6eb84 --- /dev/null +++ b/drivers/interconnect/qcom/smd-rpm.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RPM over SMD communication wrapper for interconnects + * + * Copyright (C) 2018 Linaro Ltd + * Author: Georgi Djakov <georgi.djakov@linaro.org> + */ + +#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/soc/qcom/smd-rpm.h> +#include "smd-rpm.h" + +#define RPM_KEY_BW 0x00007762 + +static struct qcom_icc_rpm { + struct qcom_smd_rpm *rpm; +} icc_rpm_smd; + +struct icc_rpm_smd_req { + __le32 key; + __le32 nbytes; + __le32 value; +}; + +bool qcom_icc_rpm_smd_available(void) +{ + if (!icc_rpm_smd.rpm) + return false; + + return true; +} +EXPORT_SYMBOL_GPL(qcom_icc_rpm_smd_available); + +int qcom_icc_rpm_smd_send(int ctx, int rsc_type, int id, u32 val) +{ + struct icc_rpm_smd_req req = { + .key = cpu_to_le32(RPM_KEY_BW), + .nbytes = cpu_to_le32(sizeof(u32)), + .value = cpu_to_le32(val), + }; + + return qcom_rpm_smd_write(icc_rpm_smd.rpm, ctx, rsc_type, id, &req, + sizeof(req)); +} +EXPORT_SYMBOL_GPL(qcom_icc_rpm_smd_send); + +static int qcom_icc_rpm_smd_probe(struct platform_device *pdev) +{ + icc_rpm_smd.rpm = dev_get_drvdata(pdev->dev.parent); + if (!icc_rpm_smd.rpm) { + dev_err(&pdev->dev, "unable to retrieve handle to RPM\n"); + return -ENODEV; + } + + return 0; +} + +static const struct of_device_id qcom_icc_rpm_smd_dt_match[] = { + { .compatible = "qcom,interconnect-smd-rpm", }, + { }, +}; + +MODULE_DEVICE_TABLE(of, qcom_icc_rpm_smd_dt_match); + +static struct platform_driver qcom_interconnect_rpm_smd_driver = { + .driver = { + .name = "qcom-interconnect-smd-rpm", + .of_match_table = qcom_icc_rpm_smd_dt_match, + }, + .probe = qcom_icc_rpm_smd_probe, +}; + +static int __init rpm_smd_interconnect_init(void) +{ + return platform_driver_register(&qcom_interconnect_rpm_smd_driver); +} +subsys_initcall(rpm_smd_interconnect_init); + +static void __exit rpm_smd_interconnect_exit(void) +{ + platform_driver_unregister(&qcom_interconnect_rpm_smd_driver); +} +module_exit(rpm_smd_interconnect_exit) + +MODULE_AUTHOR("Georgi Djakov <georgi.djakov@linaro.org>"); +MODULE_DESCRIPTION("Qualcomm SMD RPM interconnect driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/interconnect/qcom/smd-rpm.h b/drivers/interconnect/qcom/smd-rpm.h new file mode 100644 index 000000000000..11c280eb86dc --- /dev/null +++ b/drivers/interconnect/qcom/smd-rpm.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018, Linaro Ltd. + * Author: Georgi Djakov <georgi.djakov@linaro.org> + */ + +#ifndef __DRIVERS_INTERCONNECT_QCOM_SMD_RPM_H +#define __DRIVERS_INTERCONNECT_QCOM_SMD_RPM_H + +#include <linux/soc/qcom/smd-rpm.h> + +bool qcom_icc_rpm_smd_available(void); +int qcom_icc_rpm_smd_send(int ctx, int rsc_type, int id, u32 val); + +#endif diff --git a/include/dt-bindings/interconnect/qcom,msm8916.h b/include/dt-bindings/interconnect/qcom,msm8916.h new file mode 100644 index 000000000000..7531465dd132 --- /dev/null +++ b/include/dt-bindings/interconnect/qcom,msm8916.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Qualcomm interconnect IDs + * + * Copyright (c) 2018, Linaro Ltd. + * Author: Georgi Djakov <georgi.djakov@linaro.org> + */ + +#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_MSM8916_H +#define __DT_BINDINGS_INTERCONNECT_QCOM_MSM8916_H + +#define BIMC_SNOC_SLV 0 +#define MASTER_JPEG 1 +#define MASTER_MDP_PORT0 2 +#define MASTER_QDSS_BAM 3 +#define MASTER_QDSS_ETR 4 +#define MASTER_SNOC_CFG 5 +#define MASTER_VFE 6 +#define MASTER_VIDEO_P0 7 +#define SNOC_MM_INT_0 8 +#define SNOC_MM_INT_1 9 +#define SNOC_MM_INT_2 10 +#define SNOC_MM_INT_BIMC 11 +#define PNOC_SNOC_SLV 12 +#define SLAVE_APSS 13 +#define SLAVE_CATS_128 14 +#define SLAVE_OCMEM_64 15 +#define SLAVE_IMEM 16 +#define SLAVE_QDSS_STM 17 +#define SLAVE_SRVC_SNOC 18 +#define SNOC_BIMC_0_MAS 19 +#define SNOC_BIMC_1_MAS 20 +#define SNOC_INT_0 21 +#define SNOC_INT_1 22 +#define SNOC_INT_BIMC 23 +#define SNOC_PNOC_MAS 24 +#define SNOC_QDSS_INT 25 + +#define BIMC_SNOC_MAS 0 +#define MASTER_AMPSS_M0 1 +#define MASTER_GRAPHICS_3D 2 +#define MASTER_TCU0 3 +#define MASTER_TCU1 4 +#define SLAVE_AMPSS_L2 5 +#define SLAVE_EBI_CH0 6 +#define SNOC_BIMC_0_SLV 7 +#define SNOC_BIMC_1_SLV 8 + +#define MASTER_BLSP_1 0 +#define MASTER_DEHR 1 +#define MASTER_LPASS 2 +#define MASTER_CRYPTO_CORE0 3 +#define MASTER_SDCC_1 4 +#define MASTER_SDCC_2 5 +#define MASTER_SPDM 6 +#define MASTER_USB_HS 7 +#define PNOC_INT_0 8 +#define PNOC_INT_1 9 +#define PNOC_MAS_0 10 +#define PNOC_MAS_1 11 +#define PNOC_SLV_0 12 +#define PNOC_SLV_1 13 +#define PNOC_SLV_2 14 +#define PNOC_SLV_3 15 +#define PNOC_SLV_4 16 +#define PNOC_SLV_8 17 +#define PNOC_SLV_9 18 +#define PNOC_SNOC_MAS 19 +#define SLAVE_BIMC_CFG 20 +#define SLAVE_BLSP_1 21 +#define SLAVE_BOOT_ROM 22 +#define SLAVE_CAMERA_CFG 23 +#define SLAVE_CLK_CTL 24 +#define SLAVE_CRYPTO_0_CFG 25 +#define SLAVE_DEHR_CFG 26 +#define SLAVE_DISPLAY_CFG 27 +#define SLAVE_GRAPHICS_3D_CFG 28 +#define SLAVE_IMEM_CFG 29 +#define SLAVE_LPASS 30 +#define SLAVE_MPM 31 +#define SLAVE_MSG_RAM 32 +#define SLAVE_MSS 33 +#define SLAVE_PDM 34 +#define SLAVE_PMIC_ARB 35 +#define SLAVE_PNOC_CFG 36 +#define SLAVE_PRNG 37 +#define SLAVE_QDSS_CFG 38 +#define SLAVE_RBCPR_CFG 39 +#define SLAVE_SDCC_1 40 +#define SLAVE_SDCC_2 41 +#define SLAVE_SECURITY 42 +#define SLAVE_SNOC_CFG 43 +#define SLAVE_SPDM 44 +#define SLAVE_TCSR 45 +#define SLAVE_TLMM 46 +#define SLAVE_USB_HS 47 +#define SLAVE_VENUS_CFG 48 +#define SNOC_PNOC_SLV 49 + +#endif diff --git a/include/dt-bindings/interconnect/qcom,msm8996.h b/include/dt-bindings/interconnect/qcom,msm8996.h new file mode 100644 index 000000000000..33cbce89b878 --- /dev/null +++ b/include/dt-bindings/interconnect/qcom,msm8996.h @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Qualcomm interconnect IDs + * + * Copyright (c) 2018, Linaro Ltd. + * Author: Georgi Djakov <georgi.djakov@linaro.org> + */ + +#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_MSM8996_H +#define __DT_BINDINGS_INTERCONNECT_QCOM_MSM8996_H + +#define A0NOC_SNOC_MAS 0 +#define A0NOC_SNOC_SLV 1 +#define A1NOC_SNOC_MAS 2 +#define A1NOC_SNOC_SLV 3 +#define A2NOC_SNOC_MAS 4 +#define A2NOC_SNOC_SLV 5 +#define BIMC_SNOC_1_MAS 6 +#define BIMC_SNOC_MAS 7 +#define MASTER_HMSS 8 +#define MASTER_QDSS_BAM 9 +#define MASTER_QDSS_ETR 10 +#define MASTER_SNOC_CFG 11 +#define SLAVE_APPSS 12 +#define SLAVE_LPASS 13 +#define SLAVE_OCIMEM 14 +#define SLAVE_PCIE_0 15 +#define SLAVE_PCIE_1 16 +#define SLAVE_PCIE_2 17 +#define SLAVE_PIMEM 18 +#define SLAVE_QDSS_STM 19 +#define SLAVE_SERVICE_SNOC 20 +#define SLAVE_SNOC_VMEM 21 +#define SLAVE_USB3 22 +#define SNOC_BIMC_SLV 23 +#define SNOC_CNOC_SLV 24 +#define SNOC_PNOC_SLV 25 + +#define BIMC_SNOC_SLV 0 +#define BIMC_SNOC_1_SLV 1 +#define MASTER_AMPSS_M0 2 +#define MASTER_GRAPHICS_3D 3 +#define MNOC_BIMC_MAS 4 +#define SLAVE_EBI_CH0 5 +#define SLAVE_HMSS_L3 6 +#define SNOC_BIMC_MAS 7 + +#define MASTER_BLSP_1 0 +#define MASTER_BLSP_2 1 +#define MASTER_SDCC_1 2 +#define MASTER_SDCC_2 3 +#define MASTER_SDCC_4 4 +#define MASTER_TSIF 5 +#define MASTER_USB_HS 6 +#define PNOC_A1NOC_SLV 7 +#define SLAVE_AHB2PHY 8 +#define SLAVE_BLSP_1 9 +#define SLAVE_BLSP_2 10 +#define SLAVE_PDM 11 +#define SLAVE_SDCC_1 12 +#define SLAVE_SDCC_2 13 +#define SLAVE_SDCC_4 14 +#define SLAVE_TSIF 15 +#define SLAVE_USB_HS 16 +#define SNOC_PNOC_MAS 17 + +#define CNOC_SNOC_SLV 0 +#define MASTER_QDSS_DAP 1 +#define SLAVE_A0NOC_CFG 2 +#define SLAVE_A0NOC_MPU_CFG 3 +#define SLAVE_A0NOC_SMMU_CFG 4 +#define SLAVE_A1NOC_CFG 5 +#define SLAVE_A1NOC_MPU_CFG 6 +#define SLAVE_A1NOC_SMMU_CFG 7 +#define SLAVE_A2NOC_CFG 8 +#define SLAVE_A2NOC_MPU_CFG 9 +#define SLAVE_A2NOC_SMMU_CFG 10 +#define SLAVE_BIMC_CFG 11 +#define SLAVE_CLK_CTL 12 +#define SLAVE_CNOC_MNOC_CFG 13 +#define SLAVE_CNOC_MNOC_MMSS_CFG 14 +#define SLAVE_CRYPTO_0_CFG 15 +#define SLAVE_DCC_CFG 16 +#define SLAVE_EBI1_PHY_CFG 17 +#define SLAVE_IMEM_CFG 18 +#define SLAVE_LPASS_SMMU_CFG 19 +#define SLAVE_MESSAGE_RAM 20 +#define SLAVE_MPM 21 +#define SLAVE_PCIE_0_CFG 22 +#define SLAVE_PCIE_1_CFG 23 +#define SLAVE_PCIE20_AHB2PHY 24 +#define SLAVE_PCIE_2_CFG 25 +#define SLAVE_PIMEM_CFG 26 +#define SLAVE_PMIC_ARB 27 +#define SLAVE_PRNG 28 +#define SLAVE_QDSS_CFG 29 +#define SLAVE_QDSS_RBCPR_APU_CFG 30 +#define SLAVE_RBCPR_CX 31 +#define SLAVE_RBCPR_MX 32 +#define SLAVE_SNOC_CFG 33 +#define SLAVE_SNOC_MPU_CFG 34 +#define SLAVE_SSC_CFG 35 +#define SLAVE_TCSR 36 +#define SLAVE_TLMM 37 +#define SLAVE_UFS_CFG 38 +#define SNOC_CNOC_MAS 39 + +#define MASTER_CNOC_MNOC_CFG 0 +#define MASTER_CNOC_MNOC_MMSS_CFG 1 +#define MASTER_CPP 2 +#define MASTER_JPEG 3 +#define MASTER_MDP_PORT0 4 +#define MASTER_MDP_PORT1 5 +#define MASTER_ROTATOR 6 +#define MASTER_SNOC_VMEM 7 +#define MASTER_VFE 8 +#define MASTER_VIDEO_P0 9 +#define MASTER_VIDEO_P0_OCMEM 10 +#define MNOC_BIMC_SLV 11 +#define SLAVE_CAMERA_CFG 12 +#define SLAVE_CAMERA_THROTTLE_CFG 13 +#define SLAVE_CPR_CFG 14 +#define SLAVE_DISPLAY_CFG 15 +#define SLAVE_DISPLAY_THROTTLE_CFG 16 +#define SLAVE_DSA_CFG 17 +#define SLAVE_DSA_MPU_CFG 18 +#define SLAVE_GRAPHICS_3D_CFG 19 +#define SLAVE_MISC_CFG 20 +#define SLAVE_MMAGIC_CFG 21 +#define SLAVE_MMSS_CLK_CFG 22 +#define SLAVE_MNOC_MPU_CFG 23 +#define SLAVE_SERVICE_MNOC 24 +#define SLAVE_SMMU_CPP_CFG 25 +#define SLAVE_SMMU_JPEG_CFG 26 +#define SLAVE_SMMU_MDP_CFG 27 +#define SLAVE_SMMU_ROTATOR_CFG 28 +#define SLAVE_SMMU_VENUS_CFG 29 +#define SLAVE_SMMU_VFE_CFG 30 +#define SLAVE_VENUS_CFG 31 +#define SLAVE_VENUS_THROTTLE_CFG 32 +#define SLAVE_VMEM_CFG 33 +#define SLAVE_VMEM 34 + +#define MASTER_PCIE 0 +#define MASTER_PCIE_1 1 +#define MASTER_PCIE_2 2 + +#define CNOC_A1NOC_MAS 0 +#define MASTER_CRYPTO_CORE0 1 +#define PNOC_A1NOC_MAS 2 + +#define MASTER_IPA 0 +#define MASTER_UFS 1 +#define MASTER_USB3 2 + +#endif diff --git a/include/dt-bindings/interconnect/qcom,sdm845.h b/include/dt-bindings/interconnect/qcom,sdm845.h new file mode 100644 index 000000000000..7b2393be7361 --- /dev/null +++ b/include/dt-bindings/interconnect/qcom,sdm845.h @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Qualcomm SDM845 interconnect IDs + * + * Copyright (c) 2018, Linaro Ltd. + * Author: Georgi Djakov <georgi.djakov@linaro.org> + */ + +#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_SDM845_H +#define __DT_BINDINGS_INTERCONNECT_QCOM_SDM845_H + +#define MASTER_A1NOC_CFG 0 +#define MASTER_BLSP_1 1 +#define MASTER_TSIF 2 +#define MASTER_SDCC_2 3 +#define MASTER_SDCC_4 4 +#define MASTER_UFS_CARD 5 +#define MASTER_UFS_MEM 6 +#define MASTER_PCIE_0 7 +#define MASTER_A2NOC_CFG 8 +#define MASTER_QDSS_BAM 9 +#define MASTER_BLSP_2 10 +#define MASTER_CNOC_A2NOC 11 +#define MASTER_CRYPTO 12 +#define MASTER_IPA 13 +#define MASTER_PCIE_1 14 +#define MASTER_QDSS_ETR 15 +#define MASTER_USB3_0 16 +#define MASTER_USB3_1 17 +#define MASTER_CAMNOC_HF0_UNCOMP 18 +#define MASTER_CAMNOC_HF1_UNCOMP 19 +#define MASTER_CAMNOC_SF_UNCOMP 20 +#define MASTER_SPDM 21 +#define MASTER_TIC 22 +#define MASTER_SNOC_CNOC 23 +#define MASTER_QDSS_DAP 24 +#define MASTER_CNOC_DC_NOC 25 +#define MASTER_APPSS_PROC 26 +#define MASTER_GNOC_CFG 27 +#define MASTER_LLCC 28 +#define MASTER_TCU_0 29 +#define MASTER_MEM_NOC_CFG 30 +#define MASTER_GNOC_MEM_NOC 31 +#define MASTER_MNOC_HF_MEM_NOC 32 +#define MASTER_MNOC_SF_MEM_NOC 33 +#define MASTER_SNOC_GC_MEM_NOC 34 +#define MASTER_SNOC_SF_MEM_NOC 35 +#define MASTER_GFX3D 36 +#define MASTER_CNOC_MNOC_CFG 37 +#define MASTER_CAMNOC_HF0 38 +#define MASTER_CAMNOC_HF1 39 +#define MASTER_CAMNOC_SF 40 +#define MASTER_MDP0 41 +#define MASTER_MDP1 42 +#define MASTER_ROTATOR 43 +#define MASTER_VIDEO_P0 44 +#define MASTER_VIDEO_P1 45 +#define MASTER_VIDEO_PROC 46 +#define MASTER_SNOC_CFG 47 +#define MASTER_A1NOC_SNOC 48 +#define MASTER_A2NOC_SNOC 49 +#define MASTER_GNOC_SNOC 50 +#define MASTER_MEM_NOC_SNOC 51 +#define MASTER_ANOC_PCIE_SNOC 52 +#define MASTER_PIMEM 53 +#define MASTER_GIC 54 +#define SLAVE_A1NOC_SNOC 55 +#define SLAVE_SERVICE_A1NOC 56 +#define SLAVE_ANOC_PCIE_A1NOC_SNOC 57 +#define SLAVE_A2NOC_SNOC 58 +#define SLAVE_ANOC_PCIE_SNOC 59 +#define SLAVE_SERVICE_A2NOC 60 +#define SLAVE_CAMNOC_UNCOMP 61 +#define SLAVE_A1NOC_CFG 62 +#define SLAVE_A2NOC_CFG 63 +#define SLAVE_AOP 64 +#define SLAVE_AOSS 65 +#define SLAVE_CAMERA_CFG 66 +#define SLAVE_CLK_CTL 67 +#define SLAVE_CDSP_CFG 68 +#define SLAVE_RBCPR_CX_CFG 69 +#define SLAVE_CRYPTO_0_CFG 70 +#define SLAVE_DCC_CFG 71 +#define SLAVE_CNOC_DDRSS 72 +#define SLAVE_DISPLAY_CFG 73 +#define SLAVE_GLM 74 +#define SLAVE_GFX3D_CFG 75 +#define SLAVE_IMEM_CFG 76 +#define SLAVE_IPA_CFG 77 +#define SLAVE_CNOC_MNOC_CFG 78 +#define SLAVE_PCIE_0_CFG 79 +#define SLAVE_PCIE_1_CFG 80 +#define SLAVE_PDM 81 +#define SLAVE_SOUTH_PHY_CFG 82 +#define SLAVE_PIMEM_CFG 83 +#define SLAVE_PRNG 84 +#define SLAVE_QDSS_CFG 85 +#define SLAVE_BLSP_2 86 +#define SLAVE_BLSP_1 87 +#define SLAVE_SDCC_2 88 +#define SLAVE_SDCC_4 89 +#define SLAVE_SNOC_CFG 90 +#define SLAVE_SPDM_WRAPPER 91 +#define SLAVE_SPSS_CFG 92 +#define SLAVE_TCSR 93 +#define SLAVE_TLMM_NORTH 94 +#define SLAVE_TLMM_SOUTH 95 +#define SLAVE_TSIF 96 +#define SLAVE_UFS_CARD_CFG 97 +#define SLAVE_UFS_MEM_CFG 98 +#define SLAVE_USB3_0 99 +#define SLAVE_USB3_1 100 +#define SLAVE_VENUS_CFG 101 +#define SLAVE_VSENSE_CTRL_CFG 102 +#define SLAVE_CNOC_A2NOC 103 +#define SLAVE_SERVICE_CNOC 104 +#define SLAVE_LLCC_CFG 105 +#define SLAVE_MEM_NOC_CFG 106 +#define SLAVE_GNOC_SNOC 107 +#define SLAVE_GNOC_MEM_NOC 108 +#define SLAVE_SERVICE_GNOC 109 +#define SLAVE_EBI1 110 +#define SLAVE_MSS_PROC_MS_MPU_CFG 111 +#define SLAVE_MEM_NOC_GNOC 112 +#define SLAVE_LLCC 113 +#define SLAVE_MEM_NOC_SNOC 114 +#define SLAVE_SERVICE_MEM_NOC 115 +#define SLAVE_MNOC_SF_MEM_NOC 116 +#define SLAVE_MNOC_HF_MEM_NOC 117 +#define SLAVE_SERVICE_MNOC 118 +#define SLAVE_APPSS 119 +#define SLAVE_SNOC_CNOC 120 +#define SLAVE_SNOC_MEM_NOC_GC 121 +#define SLAVE_SNOC_MEM_NOC_SF 122 +#define SLAVE_IMEM 123 +#define SLAVE_PCIE_0 124 +#define SLAVE_PCIE_1 125 +#define SLAVE_PIMEM 126 +#define SLAVE_SERVICE_SNOC 127 +#define SLAVE_QDSS_STM 128 +#define SLAVE_TCU 129 + +#endif diff --git a/include/linux/interconnect-provider.h b/include/linux/interconnect-provider.h new file mode 100644 index 000000000000..7ea40e82416b --- /dev/null +++ b/include/linux/interconnect-provider.h @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018, Linaro Ltd. + * Author: Georgi Djakov <georgi.djakov@linaro.org> + */ + +#ifndef __LINUX_INTERCONNECT_PROVIDER_H +#define __LINUX_INTERCONNECT_PROVIDER_H + +#include <linux/interconnect.h> + +#define icc_units_to_bps(bw) ((bw) * 1000ULL) + +struct icc_node; +struct of_phandle_args; + +/** + * struct icc_onecell_data - driver data for onecell interconnect providers + * + * @num_nodes: number of nodes in this device + * @nodes: array of pointers to the nodes in this device + */ +struct icc_onecell_data { + unsigned int num_nodes; + struct icc_node *nodes[]; +}; + +struct icc_node *of_icc_xlate_onecell(struct of_phandle_args *spec, + void *data); + +/** + * struct icc_provider - interconnect provider (controller) entity that might + * provide multiple interconnect controls + * + * @provider_list: list of the registered interconnect providers + * @nodes: internal list of the interconnect provider nodes + * @set: pointer to device specific set operation function + * @aggregate: pointer to device specific aggregate operation function + * @xlate: provider-specific callback for mapping nodes from phandle arguments + * @dev: the device this interconnect provider belongs to + * @users: count of active users + * @data: pointer to private data + */ +struct icc_provider { + struct list_head provider_list; + struct list_head nodes; + int (*set)(struct icc_node *src, struct icc_node *dst); + int (*aggregate)(struct icc_node *node, u8 tag, u32 avg_bw, + u32 peak_bw, u32 *agg_avg, u32 *agg_peak); + struct icc_node* (*xlate)(struct of_phandle_args *spec, void *data); + struct device *dev; + int users; + void *data; +}; + +/** + * struct icc_node - entity that is part of the interconnect topology + * + * @id: platform specific node id + * @name: node name used in debugfs + * @links: a list of targets pointing to where we can go next when traversing + * @num_links: number of links to other interconnect nodes + * @provider: points to the interconnect provider of this node + * @node_list: the list entry in the parent provider's "nodes" list + * @search_list: list used when walking the nodes graph + * @reverse: pointer to previous node when walking the nodes graph + * @is_traversed: flag that is used when walking the nodes graph + * @req_list: a list of QoS constraint requests associated with this node + * @avg_bw: aggregated value of average bandwidth requests from all consumers + * @peak_bw: aggregated value of peak bandwidth requests from all consumers + * @data: pointer to private data + */ +struct icc_node { + int id; + const char *name; + struct icc_node **links; + size_t num_links; + + struct icc_provider *provider; + struct list_head node_list; + struct list_head search_list; + struct icc_node *reverse; + u8 is_traversed:1; + struct hlist_head req_list; + u32 avg_bw; + u32 peak_bw; + void *data; +}; + +#if IS_ENABLED(CONFIG_INTERCONNECT) + +struct icc_node *icc_node_create(int id); +void icc_node_destroy(int id); +int icc_link_create(struct icc_node *node, const int dst_id); +int icc_link_destroy(struct icc_node *src, struct icc_node *dst); +void icc_node_add(struct icc_node *node, struct icc_provider *provider); +void icc_node_del(struct icc_node *node); +int icc_provider_add(struct icc_provider *provider); +int icc_provider_del(struct icc_provider *provider); + +#else + +static inline struct icc_node *icc_node_create(int id) +{ + return ERR_PTR(-ENOTSUPP); +} + +void icc_node_destroy(int id) +{ +} + +static inline int icc_link_create(struct icc_node *node, const int dst_id) +{ + return -ENOTSUPP; +} + +int icc_link_destroy(struct icc_node *src, struct icc_node *dst) +{ + return -ENOTSUPP; +} + +void icc_node_add(struct icc_node *node, struct icc_provider *provider) +{ +} + +void icc_node_del(struct icc_node *node) +{ +} + +static inline int icc_provider_add(struct icc_provider *provider) +{ + return -ENOTSUPP; +} + +static inline int icc_provider_del(struct icc_provider *provider) +{ + return -ENOTSUPP; +} + +#endif /* CONFIG_INTERCONNECT */ + +#endif /* __LINUX_INTERCONNECT_PROVIDER_H */ diff --git a/include/linux/interconnect.h b/include/linux/interconnect.h new file mode 100644 index 000000000000..1ce59a93dbc7 --- /dev/null +++ b/include/linux/interconnect.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018, Linaro Ltd. + * Author: Georgi Djakov <georgi.djakov@linaro.org> + */ + +#ifndef __LINUX_INTERCONNECT_H +#define __LINUX_INTERCONNECT_H + +#include <linux/mutex.h> +#include <linux/types.h> + +/* macros for converting to icc units */ +#define Bps_to_icc(x) ((x) / 1000) +#define kBps_to_icc(x) (x) +#define MBps_to_icc(x) ((x) * 1000) +#define GBps_to_icc(x) ((x) * 1000 * 1000) +#define bps_to_icc(x) (1) +#define kbps_to_icc(x) ((x) / 8 + ((x) % 8 ? 1 : 0)) +#define Mbps_to_icc(x) ((x) * 1000 / 8) +#define Gbps_to_icc(x) ((x) * 1000 * 1000 / 8) + +struct icc_path; +struct device; + +#if IS_ENABLED(CONFIG_INTERCONNECT) + +struct icc_path *icc_get(struct device *dev, const int src_id, + const int dst_id); +struct icc_path *of_icc_get(struct device *dev, const char *name); +void icc_put(struct icc_path *path); +int icc_set(struct icc_path *path, u32 avg_bw, u32 peak_bw); +void icc_set_tag(struct icc_path *path, u8 tag); + +#else + +static inline struct icc_path *icc_get(struct device *dev, const int src_id, + const int dst_id) +{ + return NULL; +} + +static inline struct icc_path *of_icc_get(struct device *dev, + const char *name) +{ + return NULL; +} + +static inline void icc_put(struct icc_path *path) +{ +} + +static inline int icc_set(struct icc_path *path, u32 avg_bw, u32 peak_bw) +{ + return 0; +} + +static inline void icc_set_tag(struct icc_path *path, u8 tag) +{ +} + +#endif /* CONFIG_INTERCONNECT */ + +#endif /* __LINUX_INTERCONNECT_H */ |