2018-08-24 01:58:34

by David Dai

[permalink] [raw]
Subject: [PATCH v3 0/2] Add sdm845 interconnect provider driver

Hi,

This patch series adds a driver and DT binding using the interconnect (ICC)
framework [1] to describe the Qualcomm SDM845 platform's topology of its
interconnected buses and internal aggregation nodes known as
Bus Clock Managers(BCM). The SDM845 ICC provider driver would aggregate and
satisfy consumer requests across the SoC by generating commands that
communicate with the BCM through the Resource Power Manager (RPMh) driver [2]
interface. The SDM845 ICC driver also configures QoS settings specific to each
node to ensure clients have proper priority.

The SDM845 interconnect provider has dependencies on the RPMh driver
and Command DB driver [3].

Changes in v3 [6]:
- Updated provider set prototype to be compatible with v8 of ICC framework
- Added additional comments and fixed format (Evan G.)
- Fixed endianess issues (Evan G.)
- Added clean up of nodes in probe failure and qnoc_remove (Evan G.)
- Merged sdm845 local node IDs with qcom dt-binding IDs
- Removed IPA CORE nodes and BCMs.

Changes in v2 [5]:
- Updated to use the latest RPMH and CommandDB patches
- Fixed bug in bcm aggregation
- Updated sdm845 provider dt entry

Changes in v1 [4]:
- Addressed review feedback from Georgi D. and Evan G.
- Removed proposal to modify ICC aggregate callback interface
- Moved BCM aggregation into provider set function
- Added devicetree binding documentation
- Fixed logic in generating TCS command list
- Added keepalive flags for resources that are critical to platform operation
- Added various comments to clarify intent
- Removed unused types and struct definitions

[1]: https://lkml.org/lkml/2018/8/10/387
[2]: https://lkml.org/lkml/2018/6/20/519
[3]: https://lkml.org/lkml/2018/4/10/714
[4]: https://patchwork.kernel.org/patch/10428167/
[5]: https://lkml.org/lkml/2018/6/29/743
[6]: https://lkml.org/lkml/2018/7/18/1109

Summary of the patches:
Patch 1 creates the Qualcomm SDM845 Specific provider driver.
Patch 2 Adds dt binding for SDM845 provider

TODO:
* Add Network-on-Chip (NoC) objects to encapsulate logical nodes for QoS.
* Add QoS configuration specific to each NoC.

David Dai (2):
interconnect: qcom: Add sdm845 interconnect provider driver
arm64: dts: sdm845: Add interconnect provider DT nodes

.../bindings/interconnect/qcom-sdm845.txt | 22 +
arch/arm64/boot/dts/qcom/sdm845.dtsi | 5 +
drivers/interconnect/qcom/Kconfig | 8 +
drivers/interconnect/qcom/Makefile | 1 +
drivers/interconnect/qcom/sdm845.c | 844 +++++++++++++++++++++
include/dt-bindings/interconnect/qcom.h | 110 ++-
6 files changed, 989 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/interconnect/qcom-sdm845.txt
create mode 100644 drivers/interconnect/qcom/sdm845.c

--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



2018-08-24 01:58:35

by David Dai

[permalink] [raw]
Subject: [PATCH v3 2/2] arm64: dts: sdm845: Add interconnect provider DT nodes

Add RSC(Resource State Coordinator) provider
dictating network-on-chip interconnect bus performance
found on SDM845-based platforms.

Change-Id: I58f0bfc3ed484d7b45064dceb94dcfda507e9333
Signed-off-by: David Dai <[email protected]>
---
arch/arm64/boot/dts/qcom/sdm845.dtsi | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 1097c7e..4d15784 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -1651,6 +1651,11 @@
compatible = "qcom,sdm845-rpmh-clk";
#clock-cells = <1>;
};
+
+ qnoc: qnoc{
+ compatible = "qcom,sdm845-rsc-hlos";
+ #interconnect-cells = <1>;
+ };
};

ufsphy: phy@1d87000 {
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


2018-08-24 01:58:40

by David Dai

[permalink] [raw]
Subject: [PATCH v3 1/2] interconnect: qcom: Add sdm845 interconnect provider driver

Introduce Qualcomm SDM845 specific provider driver using the
interconnect framework.

Change-Id: I716b39068b4a211b8203b2a52d3037a5b84594ea
Signed-off-by: David Dai <[email protected]>
---
.../bindings/interconnect/qcom-sdm845.txt | 22 +
drivers/interconnect/qcom/Kconfig | 8 +
drivers/interconnect/qcom/Makefile | 1 +
drivers/interconnect/qcom/sdm845.c | 844 +++++++++++++++++++++
include/dt-bindings/interconnect/qcom.h | 110 ++-
5 files changed, 984 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/interconnect/qcom-sdm845.txt
create mode 100644 drivers/interconnect/qcom/sdm845.c

diff --git a/Documentation/devicetree/bindings/interconnect/qcom-sdm845.txt b/Documentation/devicetree/bindings/interconnect/qcom-sdm845.txt
new file mode 100644
index 0000000..6248523
--- /dev/null
+++ b/Documentation/devicetree/bindings/interconnect/qcom-sdm845.txt
@@ -0,0 +1,22 @@
+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"
+
+Examples:
+
+apps_rsc: rsc {
+ qnoc: qnoc-rsc-hlos {
+ compatible = "qcom,sdm845-rsc-hlos";
+ };
+};
+
diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig
index add6d7e..170ef3d 100644
--- a/drivers/interconnect/qcom/Kconfig
+++ b/drivers/interconnect/qcom/Kconfig
@@ -21,3 +21,11 @@ config INTERCONNECT_QCOM_MSM8916
help
This is a driver for the Qualcomm Network-on-Chip on msm8916-based
platforms.
+
+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.
diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile
index 53f3380..a0a5056 100644
--- a/drivers/interconnect/qcom/Makefile
+++ b/drivers/interconnect/qcom/Makefile
@@ -2,3 +2,4 @@
obj-$(CONFIG_INTERCONNECT_QCOM_SMD_RPM) += smd-rpm.o

obj-$(CONFIG_INTERCONNECT_QCOM_MSM8916) += msm8916.o
+obj-$(CONFIG_INTERCONNECT_QCOM_SDM845) += sdm845.o
diff --git a/drivers/interconnect/qcom/sdm845.c b/drivers/interconnect/qcom/sdm845.c
new file mode 100644
index 0000000..57aba8a
--- /dev/null
+++ b/drivers/interconnect/qcom/sdm845.c
@@ -0,0 +1,844 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/interconnect.h>
+#include <linux/interconnect-provider.h>
+#include <dt-bindings/interconnect/qcom.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 <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 0x200010000
+#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)
+
+#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 DEFINE_QBCM(_name, _bcmname, _keepalive, _numnodes, ...) \
+ static struct qcom_icc_bcm _name = { \
+ .name = _bcmname, \
+ .keepalive = _keepalive, \
+ .num_nodes = _numnodes, \
+ .nodes = { __VA_ARGS__ }, \
+ }
+
+struct qcom_icc_provider {
+ struct icc_provider provider;
+ void __iomem *base;
+ 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: bcm threshold values are in magnitudes of this
+ * @width: prototype width
+ * @vcd: virtual clock domain that this bcm belongs to
+ */
+
+struct bcm_db {
+ u32 unit;
+ u16 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
+
+/**
+ * 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_bcm: 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;
+ u64 max_peak;
+ 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 or bcm needs to be committed
+ * @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;
+ u64 vote_y;
+ 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;
+ u32 base_offset;
+ u32 qos_offset;
+};
+
+struct qcom_icc_desc {
+ struct qcom_icc_node **nodes;
+ size_t num_nodes;
+ struct qcom_icc_bcm **bcms;
+ size_t num_bcms;
+};
+
+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_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[] = {
+ &acm_l3,
+ &acm_tcu,
+ &llcc_mc,
+ &pm_gnoc_cfg,
+ &qhm_a1noc_cfg,
+ &qhm_a2noc_cfg,
+ &qhm_cnoc,
+ &qhm_memnoc_cfg,
+ &qhm_mnoc_cfg,
+ &qhm_qdss_bam,
+ &qhm_qup1,
+ &qhm_qup2,
+ &qhm_snoc_cfg,
+ &qhm_spdm,
+ &qhm_tic,
+ &qhm_tsif,
+ &qnm_aggre1_noc,
+ &qnm_aggre2_noc,
+ &qnm_apps,
+ &qnm_cnoc,
+ &qnm_gladiator_sodv,
+ &qnm_memnoc,
+ &qnm_mnoc_hf,
+ &qnm_mnoc_sf,
+ &qnm_pcie_anoc,
+ &qnm_snoc,
+ &qnm_snoc_gc,
+ &qnm_snoc_sf,
+ &qxm_camnoc_hf0,
+ &qxm_camnoc_hf0_uncomp,
+ &qxm_camnoc_hf1,
+ &qxm_camnoc_hf1_uncomp,
+ &qxm_camnoc_sf,
+ &qxm_camnoc_sf_uncomp,
+ &qxm_crypto,
+ &qxm_gpu,
+ &qxm_ipa,
+ &qxm_mdp0,
+ &qxm_mdp1,
+ &qxm_pimem,
+ &qxm_rot,
+ &qxm_venus0,
+ &qxm_venus1,
+ &qxm_venus_arm9,
+ &xm_gic,
+ &xm_pcie3_1,
+ &xm_pcie_0,
+ &xm_qdss_dap,
+ &xm_qdss_etr,
+ &xm_sdc2,
+ &xm_sdc4,
+ &xm_ufs_card,
+ &xm_ufs_mem,
+ &xm_usb3_0,
+ &xm_usb3_1,
+ &ebi,
+ &qhs_a1_noc_cfg,
+ &qhs_a2_noc_cfg,
+ &qhs_aop,
+ &qhs_aoss,
+ &qhs_apss,
+ &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_llcc,
+ &qhs_mdsp_ms_mpu_cfg,
+ &qhs_memnoc,
+ &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,
+ &qns2_mem_noc,
+ &qns_a1noc_snoc,
+ &qns_a2noc_snoc,
+ &qns_apps_io,
+ &qns_camnoc_uncomp,
+ &qns_cnoc,
+ &qns_cnoc_a2noc,
+ &qns_gladiator_sodv,
+ &qns_gnoc_memnoc,
+ &qns_llcc,
+ &qns_mem_noc_hf,
+ &qns_memnoc_gc,
+ &qns_memnoc_sf,
+ &qns_memnoc_snoc,
+ &qns_pcie_a1noc_snoc,
+ &qns_pcie_snoc,
+ &qxs_imem,
+ &qxs_pcie,
+ &qxs_pcie_gen3,
+ &qxs_pimem,
+ &srvc_aggre1_noc,
+ &srvc_aggre2_noc,
+ &srvc_cnoc,
+ &srvc_gnoc,
+ &srvc_memnoc,
+ &srvc_mnoc,
+ &srvc_snoc,
+ &xs_qdss_stm,
+ &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_init(struct icc_node *node)
+{
+ /* TODO: init qos and priority */
+
+ return 0;
+}
+
+static int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev)
+{
+ struct qcom_icc_node *qn;
+ int ret, 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;
+ }
+
+ if (cmd_db_read_aux_data_len(bcm->name) < sizeof(struct bcm_db)) {
+ dev_err(dev, "%s command db missing or partial aux data\n",
+ bcm->name);
+ return -EINVAL;
+ }
+
+ ret = cmd_db_read_aux_data(bcm->name, (u8 *)&bcm->aux_data,
+ sizeof(struct bcm_db));
+ if (ret < 0) {
+ dev_err(dev, "%s command db read error (%d)\n",
+ bcm->name, ret);
+ return ret;
+ }
+
+ bcm->aux_data.unit = le32_to_cpu(bcm->aux_data.unit);
+ bcm->aux_data.width = le16_to_cpu(bcm->aux_data.width);
+
+ /*
+ * 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;
+}
+
+static int qcom_tcs_cmd_gen(struct tcs_cmd *cmd, u64 vote_x,
+ u64 vote_y, u32 addr, bool commit)
+{
+ int ret = 0;
+ bool valid = true;
+
+ if (!cmd)
+ return ret;
+
+ 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 commands that have the commit
+ * set, in order to indicate to the RSC to not release the TCS slot
+ * until hardware has acknowledged that this transaction has completed.
+ */
+ if (commit)
+ cmd->wait = true;
+
+ return ret;
+}
+
+static void qcom_tcs_list_gen(struct list_head *bcm_list,
+ struct tcs_cmd *tcs_list, int *n)
+{
+ 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_is_last(&bcm->list, bcm_list)) {
+ commit = true;
+ cur_vcd_size = 0;
+ }
+ qcom_tcs_cmd_gen(&tcs_list[idx], bcm->vote_x, bcm->vote_y,
+ 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 qcom_icc_bcm_aggregate(struct qcom_icc_bcm *bcm)
+{
+ size_t i;
+ u64 agg_avg = 0;
+ u64 agg_peak = 0;
+
+ for (i = 0; i < bcm->num_nodes; i++) {
+ agg_avg = max(agg_avg,
+ bcm->nodes[i]->sum_avg * bcm->aux_data.width /
+ (bcm->nodes[i]->buswidth * bcm->nodes[i]->channels));
+ agg_peak = max(agg_peak,
+ bcm->nodes[i]->max_peak * bcm->aux_data.width /
+ bcm->nodes[i]->buswidth);
+ }
+
+ bcm->vote_x = (u64)(agg_avg * 1000ULL / bcm->aux_data.unit);
+ bcm->vote_y = (u64)(agg_peak * 1000ULL / bcm->aux_data.unit);
+
+ if (bcm->keepalive && bcm->vote_x == 0 && bcm->vote_y == 0) {
+ bcm->vote_x = 1;
+ bcm->vote_y = 1;
+ }
+
+ bcm->dirty = false;
+}
+
+static int qcom_icc_aggregate(struct icc_node *node, u32 avg_bw,
+ u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
+{
+ size_t i;
+ struct qcom_icc_node *qn;
+
+ qn = node->data;
+
+ *agg_avg += avg_bw;
+ *agg_peak = max_t(u64, agg_peak, peak_bw);
+
+ qn->sum_avg = *agg_avg;
+ qn->max_peak = *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 qcom_icc_node *qn;
+ struct icc_node *node;
+ struct icc_provider *provider;
+ 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;
+
+ qn = node->data;
+ provider = node->provider;
+ qp = to_qcom_provider(node->provider);
+
+ INIT_LIST_HEAD(&commit_list);
+
+ for (i = 0; i < qp->num_bcms; i++) {
+ if (qp->bcms[i]->dirty) {
+ qcom_icc_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.
+ */
+ qcom_tcs_list_gen(&commit_list, 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;
+ }
+
+ 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 qcom_icc_node **qnodes;
+ struct icc_node *node;
+ struct qcom_icc_provider *qp;
+ struct icc_provider *provider;
+ 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;
+
+ provider = &qp->provider;
+ provider->dev = &pdev->dev;
+ provider->set = &qcom_icc_set;
+ provider->aggregate = &qcom_icc_aggregate;
+ INIT_LIST_HEAD(&provider->nodes);
+ provider->data = qp;
+
+ 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++) {
+ int ret;
+ 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);
+
+ ret = qcom_icc_init(node);
+ if (ret)
+ dev_err(&pdev->dev, "%s init error (%d)\n", node->name,
+ ret);
+
+ /* populate links */
+ for (j = 0; j < qnodes[i]->num_links; j++)
+ if (qnodes[i]->links[j])
+ icc_link_create(node, qnodes[i]->links[j]);
+ }
+
+ 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, provider);
+ dev_info(&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 icc_provider *provider = platform_get_drvdata(pdev);
+ 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 <[email protected]>");
+MODULE_DESCRIPTION("Qualcomm sdm845 NoC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/dt-bindings/interconnect/qcom.h b/include/dt-bindings/interconnect/qcom.h
index 1a1421a..79d8935 100644
--- a/include/dt-bindings/interconnect/qcom.h
+++ b/include/dt-bindings/interconnect/qcom.h
@@ -94,5 +94,113 @@
#define SNOC_PNOC_SLV 82
#define SNOC_QDSS_INT 83
#define SYSTEM_SLAVE_FAB_APPS 84
-
+#define MASTER_APPSS_PROC 85
+#define MASTER_PCIE_0 86
+#define MASTER_QDSS_DAP 87
+#define MASTER_LLCC 88
+#define MASTER_GNOC_CFG 89
+#define MASTER_A1NOC_CFG 90
+#define MASTER_A2NOC_CFG 91
+#define MASTER_CNOC_DC_NOC 92
+#define MASTER_MEM_NOC_CFG 93
+#define MASTER_CNOC_MNOC_CFG 94
+#define MASTER_UFS_MEM 95
+#define MASTER_USB3_0 96
+#define MASTER_USB3_1 97
+#define MASTER_BLSP_2 98
+#define MASTER_UFS_CARD 99
+#define MASTER_TIC 100
+#define MASTER_TSIF 101
+#define MASTER_A1NOC_SNOC 102
+#define MASTER_A2NOC_SNOC 103
+#define MASTER_GNOC_MEM_NOC 104
+#define MASTER_CNOC_A2NOC 105
+#define MASTER_GNOC_SNOC 106
+#define MASTER_MEM_NOC_SNOC 107
+#define MASTER_MNOC_HF_MEM_NOC 108
+#define MASTER_MNOC_SF_MEM_NOC 109
+#define MASTER_ANOC_PCIE_SNOC 110
+#define MASTER_SNOC_CNOC 111
+#define MASTER_SNOC_GC_MEM_NOC 112
+#define MASTER_SNOC_SF_MEM_NOC 113
+#define MASTER_CAMNOC_HF0 114
+#define MASTER_CAMNOC_HF0_UNCOMP 115
+#define MASTER_CAMNOC_HF1 116
+#define MASTER_CAMNOC_HF1_UNCOMP 117
+#define MASTER_CAMNOC_SF 118
+#define MASTER_CAMNOC_SF_UNCOMP 119
+#define MASTER_CRYPTO 120
+#define MASTER_GFX3D 121
+#define MASTER_IPA 122
+#define MASTER_MDP0 123
+#define MASTER_MDP1 124
+#define MASTER_PIMEM 125
+#define MASTER_ROTATOR 126
+#define MASTER_SDCC_4 127
+#define MASTER_VIDEO_P1 128
+#define MASTER_VIDEO_PROC 129
+#define MASTER_GIC 130
+#define MASTER_PCIE_1 131
+#define SLAVE_IMEM 134
+#define SLAVE_PCIE_0 135
+#define SLAVE_PCIE_1 136
+#define SLAVE_PIMEM 137
+#define SLAVE_SERVICE_A1NOC 138
+#define SLAVE_SERVICE_A2NOC 139
+#define SLAVE_SERVICE_CNOC 140
+#define SLAVE_EBI1 141
+#define SLAVE_TCU 142
+#define SLAVE_A1NOC_CFG 143
+#define SLAVE_A2NOC_CFG 144
+#define SLAVE_AOP 145
+#define SLAVE_AOSS 146
+#define SLAVE_APPSS 147
+#define SLAVE_SERVICE_GNOC 148
+#define SLAVE_SERVICE_MEM_NOC 149
+#define SLAVE_CDSP_CFG 150
+#define SLAVE_RBCPR_CX_CFG 151
+#define SLAVE_SERVICE_MNOC 152
+#define SLAVE_DCC_CFG 153
+#define SLAVE_CNOC_DDRSS 154
+#define SLAVE_GLM 156
+#define SLAVE_GFX3D_CFG 157
+#define SLAVE_MEM_NOC_SNOC 158
+#define SLAVE_IPA_CFG 159
+#define SLAVE_LLCC_CFG 160
+#define SLAVE_MSS_PROC_MS_MPU_CFG 161
+#define SLAVE_MEM_NOC_CFG 162
+#define SLAVE_CNOC_MNOC_CFG 163
+#define SLAVE_PCIE_0_CFG 164
+#define SLAVE_PCIE_1_CFG 165
+#define SLAVE_PDM 166
+#define SLAVE_SOUTH_PHY_CFG 167
+#define SLAVE_PIMEM_CFG 168
+#define SLAVE_ANOC_PCIE_SNOC 169
+#define SLAVE_MNOC_HF_MEM_NOC 170
+#define SLAVE_BLSP_2 171
+#define SLAVE_ANOC_PCIE_A1NOC_SNOC 172
+#define SLAVE_SDCC_2 173
+#define SLAVE_SNOC_MEM_NOC_SF 174
+#define SLAVE_LLCC 175
+#define SLAVE_SPDM_WRAPPER 176
+#define SLAVE_SPSS_CFG 177
+#define SLAVE_TCSR 178
+#define SLAVE_TLMM_NORTH 179
+#define SLAVE_TLMM_SOUTH 180
+#define SLAVE_TSIF 181
+#define SLAVE_UFS_CARD_CFG 182
+#define SLAVE_UFS_MEM_CFG 183
+#define SLAVE_USB3_0 184
+#define SLAVE_USB3_1 185
+#define SLAVE_SNOC_MEM_NOC_GC 186
+#define SLAVE_VSENSE_CTRL_CFG 187
+#define SLAVE_MNOC_SF_MEM_NOC 188
+#define SLAVE_A1NOC_SNOC 189
+#define SLAVE_A2NOC_SNOC 190
+#define SLAVE_MEM_NOC_GNOC 191
+#define SLAVE_CAMNOC_UNCOMP 192
+#define SLAVE_SNOC_CNOC 193
+#define SLAVE_CNOC_A2NOC 194
+#define SLAVE_GNOC_SNOC 195
+#define SLAVE_GNOC_MEM_NOC 196
#endif
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


2018-08-24 15:00:33

by Lina Iyer

[permalink] [raw]
Subject: Re: [PATCH v3 2/2] arm64: dts: sdm845: Add interconnect provider DT nodes

On Thu, Aug 23 2018 at 19:57 -0600, David Dai wrote:
>Add RSC(Resource State Coordinator) provider
>dictating network-on-chip interconnect bus performance
>found on SDM845-based platforms.
>
>Change-Id: I58f0bfc3ed484d7b45064dceb94dcfda507e9333
Remove this pls.

-- Lina

>Signed-off-by: David Dai <[email protected]>
>---
> arch/arm64/boot/dts/qcom/sdm845.dtsi | 5 +++++
> 1 file changed, 5 insertions(+)
>
>diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
>index 1097c7e..4d15784 100644
>--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
>+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
>@@ -1651,6 +1651,11 @@
> compatible = "qcom,sdm845-rpmh-clk";
> #clock-cells = <1>;
> };
>+
>+ qnoc: qnoc{
>+ compatible = "qcom,sdm845-rsc-hlos";
>+ #interconnect-cells = <1>;
>+ };
> };
>
> ufsphy: phy@1d87000 {
>--
>The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
>a Linux Foundation Collaborative Project
>

2018-08-24 15:36:50

by Lina Iyer

[permalink] [raw]
Subject: Re: [PATCH v3 1/2] interconnect: qcom: Add sdm845 interconnect provider driver

On Thu, Aug 23 2018 at 19:57 -0600, David Dai wrote:
>Introduce Qualcomm SDM845 specific provider driver using the
>interconnect framework.
>
SDM845 specific, can't be reused?

Please describe why we need this driver and how this driver solves the
problem.

>Change-Id: I716b39068b4a211b8203b2a52d3037a5b84594ea
Remove this pls.

>Signed-off-by: David Dai <[email protected]>
>---
> .../bindings/interconnect/qcom-sdm845.txt | 22 +
> drivers/interconnect/qcom/Kconfig | 8 +
> drivers/interconnect/qcom/Makefile | 1 +
> drivers/interconnect/qcom/sdm845.c | 844 +++++++++++++++++++++
> include/dt-bindings/interconnect/qcom.h | 110 ++-
> 5 files changed, 984 insertions(+), 1 deletion(-)
> create mode 100644 Documentation/devicetree/bindings/interconnect/qcom-sdm845.txt
> create mode 100644 drivers/interconnect/qcom/sdm845.c
>
>diff --git a/Documentation/devicetree/bindings/interconnect/qcom-sdm845.txt b/Documentation/devicetree/bindings/interconnect/qcom-sdm845.txt
>new file mode 100644
>index 0000000..6248523
>--- /dev/null
>+++ b/Documentation/devicetree/bindings/interconnect/qcom-sdm845.txt
Device tree bindings are best reviewed by the fine folks on
[email protected]. Please include them in your mails.

>@@ -0,0 +1,22 @@
>+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"
Is this driver ever going to be reusable for other SoCs?
If so, a generic compatible name should be preferred, and if you have
SoC specific data, then provide that compatible separately.
>+
>+Examples:
>+
>+apps_rsc: rsc {
>+ qnoc: qnoc-rsc-hlos {
>+ compatible = "qcom,sdm845-rsc-hlos";
>+ };
>+};
>+
>diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig
>index add6d7e..170ef3d 100644
>--- a/drivers/interconnect/qcom/Kconfig
>+++ b/drivers/interconnect/qcom/Kconfig
>@@ -21,3 +21,11 @@ config INTERCONNECT_QCOM_MSM8916
> help
> This is a driver for the Qualcomm Network-on-Chip on msm8916-based
> platforms.
>+
>+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.
>diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile
>index 53f3380..a0a5056 100644
>--- a/drivers/interconnect/qcom/Makefile
>+++ b/drivers/interconnect/qcom/Makefile
>@@ -2,3 +2,4 @@
> obj-$(CONFIG_INTERCONNECT_QCOM_SMD_RPM) += smd-rpm.o
>
> obj-$(CONFIG_INTERCONNECT_QCOM_MSM8916) += msm8916.o
>+obj-$(CONFIG_INTERCONNECT_QCOM_SDM845) += sdm845.o
>diff --git a/drivers/interconnect/qcom/sdm845.c b/drivers/interconnect/qcom/sdm845.c
>new file mode 100644
>index 0000000..57aba8a
>--- /dev/null
>+++ b/drivers/interconnect/qcom/sdm845.c
>@@ -0,0 +1,844 @@
>+/* SPDX-License-Identifier: GPL-2.0 */
>+/*
>+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
>+ *
>+ */
>+
>+#include <linux/device.h>
>+#include <linux/io.h>
>+#include <linux/interconnect.h>
>+#include <linux/interconnect-provider.h>
>+#include <dt-bindings/interconnect/qcom.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 <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 0x200010000
>+#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)
>+
>+#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 DEFINE_QBCM(_name, _bcmname, _keepalive, _numnodes, ...) \
>+ static struct qcom_icc_bcm _name = { \
>+ .name = _bcmname, \
>+ .keepalive = _keepalive, \
>+ .num_nodes = _numnodes, \
>+ .nodes = { __VA_ARGS__ }, \
>+ }
>+
>+struct qcom_icc_provider {
>+ struct icc_provider provider;
>+ void __iomem *base;
>+ 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: bcm threshold values are in magnitudes of this
>+ * @width: prototype width
>+ * @vcd: virtual clock domain that this bcm belongs to
>+ */
>+
>+struct bcm_db {
>+ u32 unit;
>+ u16 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
>+
>+/**
>+ * 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_bcm: 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;
>+ u64 max_peak;
>+ 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 or bcm needs to be committed
>+ * @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;
>+ u64 vote_y;
>+ 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;
>+ u32 base_offset;
>+ u32 qos_offset;
>+};
>+
>+struct qcom_icc_desc {
>+ struct qcom_icc_node **nodes;
>+ size_t num_nodes;
>+ struct qcom_icc_bcm **bcms;
>+ size_t num_bcms;
>+};
>+
>+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_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[] = {
>+ &acm_l3,
>+ &acm_tcu,
>+ &llcc_mc,
>+ &pm_gnoc_cfg,
>+ &qhm_a1noc_cfg,
>+ &qhm_a2noc_cfg,
>+ &qhm_cnoc,
>+ &qhm_memnoc_cfg,
>+ &qhm_mnoc_cfg,
>+ &qhm_qdss_bam,
>+ &qhm_qup1,
>+ &qhm_qup2,
>+ &qhm_snoc_cfg,
>+ &qhm_spdm,
>+ &qhm_tic,
>+ &qhm_tsif,
>+ &qnm_aggre1_noc,
>+ &qnm_aggre2_noc,
>+ &qnm_apps,
>+ &qnm_cnoc,
>+ &qnm_gladiator_sodv,
>+ &qnm_memnoc,
>+ &qnm_mnoc_hf,
>+ &qnm_mnoc_sf,
>+ &qnm_pcie_anoc,
>+ &qnm_snoc,
>+ &qnm_snoc_gc,
>+ &qnm_snoc_sf,
>+ &qxm_camnoc_hf0,
>+ &qxm_camnoc_hf0_uncomp,
>+ &qxm_camnoc_hf1,
>+ &qxm_camnoc_hf1_uncomp,
>+ &qxm_camnoc_sf,
>+ &qxm_camnoc_sf_uncomp,
>+ &qxm_crypto,
>+ &qxm_gpu,
>+ &qxm_ipa,
>+ &qxm_mdp0,
>+ &qxm_mdp1,
>+ &qxm_pimem,
>+ &qxm_rot,
>+ &qxm_venus0,
>+ &qxm_venus1,
>+ &qxm_venus_arm9,
>+ &xm_gic,
>+ &xm_pcie3_1,
>+ &xm_pcie_0,
>+ &xm_qdss_dap,
>+ &xm_qdss_etr,
>+ &xm_sdc2,
>+ &xm_sdc4,
>+ &xm_ufs_card,
>+ &xm_ufs_mem,
>+ &xm_usb3_0,
>+ &xm_usb3_1,
>+ &ebi,
>+ &qhs_a1_noc_cfg,
>+ &qhs_a2_noc_cfg,
>+ &qhs_aop,
>+ &qhs_aoss,
>+ &qhs_apss,
>+ &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_llcc,
>+ &qhs_mdsp_ms_mpu_cfg,
>+ &qhs_memnoc,
>+ &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,
>+ &qns2_mem_noc,
>+ &qns_a1noc_snoc,
>+ &qns_a2noc_snoc,
>+ &qns_apps_io,
>+ &qns_camnoc_uncomp,
>+ &qns_cnoc,
>+ &qns_cnoc_a2noc,
>+ &qns_gladiator_sodv,
>+ &qns_gnoc_memnoc,
>+ &qns_llcc,
>+ &qns_mem_noc_hf,
>+ &qns_memnoc_gc,
>+ &qns_memnoc_sf,
>+ &qns_memnoc_snoc,
>+ &qns_pcie_a1noc_snoc,
>+ &qns_pcie_snoc,
>+ &qxs_imem,
>+ &qxs_pcie,
>+ &qxs_pcie_gen3,
>+ &qxs_pimem,
>+ &srvc_aggre1_noc,
>+ &srvc_aggre2_noc,
>+ &srvc_cnoc,
>+ &srvc_gnoc,
>+ &srvc_memnoc,
>+ &srvc_mnoc,
>+ &srvc_snoc,
>+ &xs_qdss_stm,
>+ &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_init(struct icc_node *node)
>+{
>+ /* TODO: init qos and priority */
>+
>+ return 0;
>+}
>+
>+static int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev)
>+{
>+ struct qcom_icc_node *qn;
>+ int ret, 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;
>+ }
>+
>+ if (cmd_db_read_aux_data_len(bcm->name) < sizeof(struct bcm_db)) {
>+ dev_err(dev, "%s command db missing or partial aux data\n",
>+ bcm->name);
>+ return -EINVAL;
>+ }
>+
>+ ret = cmd_db_read_aux_data(bcm->name, (u8 *)&bcm->aux_data,
>+ sizeof(struct bcm_db));
>+ if (ret < 0) {
>+ dev_err(dev, "%s command db read error (%d)\n",
>+ bcm->name, ret);
>+ return ret;
>+ }
>+
>+ bcm->aux_data.unit = le32_to_cpu(bcm->aux_data.unit);
>+ bcm->aux_data.width = le16_to_cpu(bcm->aux_data.width);
>+
>+ /*
>+ * 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;
>+}
>+
>+static int qcom_tcs_cmd_gen(struct tcs_cmd *cmd, u64 vote_x,
>+ u64 vote_y, u32 addr, bool commit)
Apparently, a lot of people like if you align the next line under the (,
in general for every wrap, not just for functions. I have come to
appreciate it myself :).

static int qcom_tcs_cmd_gen(struct tcs_cmd *cmd, u64 vote_x,
u64 vote_y, u32 addr, bool commit)

>+{
>+ int ret = 0;
>+ bool valid = true;
>+
>+ if (!cmd)
>+ return ret;
>+
>+ 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 commands that have the commit
>+ * set, in order to indicate to the RSC to not release the TCS slot
>+ * until hardware has acknowledged that this transaction has completed.
The TCS is not released until all the commands in the TCS are
transmitted (and completed for response required cases). It is not
relevant here. A better comment would be:
Set the wait for completion flag on command that need to be completed
before the next command.
>+ */
>+ if (commit)
>+ cmd->wait = true;
>+
>+ return ret;
>+}
>+
>+static void qcom_tcs_list_gen(struct list_head *bcm_list,
Drop the 'qcom_' prefix to the local static functions.
>+ struct tcs_cmd *tcs_list, int *n)
>+{
>+ 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_is_last(&bcm->list, bcm_list)) {
>+ commit = true;
>+ cur_vcd_size = 0;
>+ }
>+ qcom_tcs_cmd_gen(&tcs_list[idx], bcm->vote_x, bcm->vote_y,
>+ 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 qcom_icc_bcm_aggregate(struct qcom_icc_bcm *bcm)
>+{
>+ size_t i;
>+ u64 agg_avg = 0;
>+ u64 agg_peak = 0;
>+
>+ for (i = 0; i < bcm->num_nodes; i++) {
>+ agg_avg = max(agg_avg,
>+ bcm->nodes[i]->sum_avg * bcm->aux_data.width /
>+ (bcm->nodes[i]->buswidth * bcm->nodes[i]->channels));
>+ agg_peak = max(agg_peak,
>+ bcm->nodes[i]->max_peak * bcm->aux_data.width /
>+ bcm->nodes[i]->buswidth);
>+ }
>+
>+ bcm->vote_x = (u64)(agg_avg * 1000ULL / bcm->aux_data.unit);
>+ bcm->vote_y = (u64)(agg_peak * 1000ULL / bcm->aux_data.unit);
>+
>+ if (bcm->keepalive && bcm->vote_x == 0 && bcm->vote_y == 0) {
>+ bcm->vote_x = 1;
>+ bcm->vote_y = 1;
>+ }
>+
>+ bcm->dirty = false;
>+}
>+
>+static int qcom_icc_aggregate(struct icc_node *node, u32 avg_bw,
>+ u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
>+{
>+ size_t i;
>+ struct qcom_icc_node *qn;
>+
>+ qn = node->data;
>+
>+ *agg_avg += avg_bw;
>+ *agg_peak = max_t(u64, agg_peak, peak_bw);
>+
>+ qn->sum_avg = *agg_avg;
>+ qn->max_peak = *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 qcom_icc_node *qn;
>+ struct icc_node *node;
>+ struct icc_provider *provider;
>+ struct tcs_cmd cmds[SDM845_MAX_BCMS];
Is there a chance we could move it out of the stack?
>+ struct list_head commit_list;
>+ int commit_idx[SDM845_MAX_VCD];
>+ int ret = 0, i;
>+
>+ if (!src)
>+ node = dst;
>+ else
>+ node = src;
>+
>+ qn = node->data;
>+ provider = node->provider;
>+ qp = to_qcom_provider(node->provider);
>+
>+ INIT_LIST_HEAD(&commit_list);
>+
>+ for (i = 0; i < qp->num_bcms; i++) {
>+ if (qp->bcms[i]->dirty) {
>+ qcom_icc_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.
>+ */
>+ qcom_tcs_list_gen(&commit_list, 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;
>+ }
We are not tackling the sleep and wake states at this time?
>+
>+ 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 qcom_icc_node **qnodes;
>+ struct icc_node *node;
>+ struct qcom_icc_provider *qp;
>+ struct icc_provider *provider;
>+ 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;
>+
>+ provider = &qp->provider;
>+ provider->dev = &pdev->dev;
>+ provider->set = &qcom_icc_set;
>+ provider->aggregate = &qcom_icc_aggregate;
>+ INIT_LIST_HEAD(&provider->nodes);
>+ provider->data = qp;
>+
>+ 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++) {
>+ int ret;
>+ 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);
>+
>+ ret = qcom_icc_init(node);
>+ if (ret)
>+ dev_err(&pdev->dev, "%s init error (%d)\n", node->name,
>+ ret);
>+
>+ /* populate links */
>+ for (j = 0; j < qnodes[i]->num_links; j++)
>+ if (qnodes[i]->links[j])
>+ icc_link_create(node, qnodes[i]->links[j]);
>+ }
>+
>+ 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, provider);
>+ dev_info(&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 icc_provider *provider = platform_get_drvdata(pdev);
>+ 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 },
To me this indicates that this driver could possibly support more than
one SoC.

>+ { },
>+};
>+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 <[email protected]>");
>+MODULE_DESCRIPTION("Qualcomm sdm845 NoC driver");
>+MODULE_LICENSE("GPL v2");
Do we need this?

Thanks,
Lina

>diff --git a/include/dt-bindings/interconnect/qcom.h b/include/dt-bindings/interconnect/qcom.h
>index 1a1421a..79d8935 100644
>--- a/include/dt-bindings/interconnect/qcom.h
>+++ b/include/dt-bindings/interconnect/qcom.h
>@@ -94,5 +94,113 @@
> #define SNOC_PNOC_SLV 82
> #define SNOC_QDSS_INT 83
> #define SYSTEM_SLAVE_FAB_APPS 84
>-
>+#define MASTER_APPSS_PROC 85
>+#define MASTER_PCIE_0 86
>+#define MASTER_QDSS_DAP 87
>+#define MASTER_LLCC 88
>+#define MASTER_GNOC_CFG 89
>+#define MASTER_A1NOC_CFG 90
>+#define MASTER_A2NOC_CFG 91
>+#define MASTER_CNOC_DC_NOC 92
>+#define MASTER_MEM_NOC_CFG 93
>+#define MASTER_CNOC_MNOC_CFG 94
>+#define MASTER_UFS_MEM 95
>+#define MASTER_USB3_0 96
>+#define MASTER_USB3_1 97
>+#define MASTER_BLSP_2 98
>+#define MASTER_UFS_CARD 99
>+#define MASTER_TIC 100
>+#define MASTER_TSIF 101
>+#define MASTER_A1NOC_SNOC 102
>+#define MASTER_A2NOC_SNOC 103
>+#define MASTER_GNOC_MEM_NOC 104
>+#define MASTER_CNOC_A2NOC 105
>+#define MASTER_GNOC_SNOC 106
>+#define MASTER_MEM_NOC_SNOC 107
>+#define MASTER_MNOC_HF_MEM_NOC 108
>+#define MASTER_MNOC_SF_MEM_NOC 109
>+#define MASTER_ANOC_PCIE_SNOC 110
>+#define MASTER_SNOC_CNOC 111
>+#define MASTER_SNOC_GC_MEM_NOC 112
>+#define MASTER_SNOC_SF_MEM_NOC 113
>+#define MASTER_CAMNOC_HF0 114
>+#define MASTER_CAMNOC_HF0_UNCOMP 115
>+#define MASTER_CAMNOC_HF1 116
>+#define MASTER_CAMNOC_HF1_UNCOMP 117
>+#define MASTER_CAMNOC_SF 118
>+#define MASTER_CAMNOC_SF_UNCOMP 119
>+#define MASTER_CRYPTO 120
>+#define MASTER_GFX3D 121
>+#define MASTER_IPA 122
>+#define MASTER_MDP0 123
>+#define MASTER_MDP1 124
>+#define MASTER_PIMEM 125
>+#define MASTER_ROTATOR 126
>+#define MASTER_SDCC_4 127
>+#define MASTER_VIDEO_P1 128
>+#define MASTER_VIDEO_PROC 129
>+#define MASTER_GIC 130
>+#define MASTER_PCIE_1 131
>+#define SLAVE_IMEM 134
>+#define SLAVE_PCIE_0 135
>+#define SLAVE_PCIE_1 136
>+#define SLAVE_PIMEM 137
>+#define SLAVE_SERVICE_A1NOC 138
>+#define SLAVE_SERVICE_A2NOC 139
>+#define SLAVE_SERVICE_CNOC 140
>+#define SLAVE_EBI1 141
>+#define SLAVE_TCU 142
>+#define SLAVE_A1NOC_CFG 143
>+#define SLAVE_A2NOC_CFG 144
>+#define SLAVE_AOP 145
>+#define SLAVE_AOSS 146
>+#define SLAVE_APPSS 147
>+#define SLAVE_SERVICE_GNOC 148
>+#define SLAVE_SERVICE_MEM_NOC 149
>+#define SLAVE_CDSP_CFG 150
>+#define SLAVE_RBCPR_CX_CFG 151
>+#define SLAVE_SERVICE_MNOC 152
>+#define SLAVE_DCC_CFG 153
>+#define SLAVE_CNOC_DDRSS 154
>+#define SLAVE_GLM 156
>+#define SLAVE_GFX3D_CFG 157
>+#define SLAVE_MEM_NOC_SNOC 158
>+#define SLAVE_IPA_CFG 159
>+#define SLAVE_LLCC_CFG 160
>+#define SLAVE_MSS_PROC_MS_MPU_CFG 161
>+#define SLAVE_MEM_NOC_CFG 162
>+#define SLAVE_CNOC_MNOC_CFG 163
>+#define SLAVE_PCIE_0_CFG 164
>+#define SLAVE_PCIE_1_CFG 165
>+#define SLAVE_PDM 166
>+#define SLAVE_SOUTH_PHY_CFG 167
>+#define SLAVE_PIMEM_CFG 168
>+#define SLAVE_ANOC_PCIE_SNOC 169
>+#define SLAVE_MNOC_HF_MEM_NOC 170
>+#define SLAVE_BLSP_2 171
>+#define SLAVE_ANOC_PCIE_A1NOC_SNOC 172
>+#define SLAVE_SDCC_2 173
>+#define SLAVE_SNOC_MEM_NOC_SF 174
>+#define SLAVE_LLCC 175
>+#define SLAVE_SPDM_WRAPPER 176
>+#define SLAVE_SPSS_CFG 177
>+#define SLAVE_TCSR 178
>+#define SLAVE_TLMM_NORTH 179
>+#define SLAVE_TLMM_SOUTH 180
>+#define SLAVE_TSIF 181
>+#define SLAVE_UFS_CARD_CFG 182
>+#define SLAVE_UFS_MEM_CFG 183
>+#define SLAVE_USB3_0 184
>+#define SLAVE_USB3_1 185
>+#define SLAVE_SNOC_MEM_NOC_GC 186
>+#define SLAVE_VSENSE_CTRL_CFG 187
>+#define SLAVE_MNOC_SF_MEM_NOC 188
>+#define SLAVE_A1NOC_SNOC 189
>+#define SLAVE_A2NOC_SNOC 190
>+#define SLAVE_MEM_NOC_GNOC 191
>+#define SLAVE_CAMNOC_UNCOMP 192
>+#define SLAVE_SNOC_CNOC 193
>+#define SLAVE_CNOC_A2NOC 194
>+#define SLAVE_GNOC_SNOC 195
>+#define SLAVE_GNOC_MEM_NOC 196
> #endif
>--
>The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
>a Linux Foundation Collaborative Project
>

2018-10-01 18:46:46

by Evan Green

[permalink] [raw]
Subject: Re: [PATCH v3 1/2] interconnect: qcom: Add sdm845 interconnect provider driver

Hi David. Apologies for my late review, this fell under the rug for a
little while.

On Thu, Aug 23, 2018 at 6:57 PM David Dai <[email protected]> wrote:
>
> Introduce Qualcomm SDM845 specific provider driver using the
> interconnect framework.
>
> Change-Id: I716b39068b4a211b8203b2a52d3037a5b84594ea
> Signed-off-by: David Dai <[email protected]>
> ---
> .../bindings/interconnect/qcom-sdm845.txt | 22 +
> drivers/interconnect/qcom/Kconfig | 8 +
> drivers/interconnect/qcom/Makefile | 1 +
> drivers/interconnect/qcom/sdm845.c | 844 +++++++++++++++++++++
> include/dt-bindings/interconnect/qcom.h | 110 ++-
> 5 files changed, 984 insertions(+), 1 deletion(-)
> create mode 100644 Documentation/devicetree/bindings/interconnect/qcom-sdm845.txt
> create mode 100644 drivers/interconnect/qcom/sdm845.c
>
...
> diff --git a/drivers/interconnect/qcom/sdm845.c b/drivers/interconnect/qcom/sdm845.c
> new file mode 100644
> index 0000000..57aba8a
> --- /dev/null
> +++ b/drivers/interconnect/qcom/sdm845.c
> @@ -0,0 +1,844 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2018, The Linux Foundation. All rights reserved.
> + *
> + */
> +
> +#include <linux/device.h>
> +#include <linux/io.h>
> +#include <linux/interconnect.h>

Nit: alphabetization here (io > in)

> +#include <linux/interconnect-provider.h>
> +#include <dt-bindings/interconnect/qcom.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>

slab.h is not needed is it?

> +#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 0x200010000

Did you mean to have that 0x10000 in there? In BCM_TCS_CMD you just
shift by 29, which would make that 0x10000 always zero.

> +#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

This VOTE_Y_MASK isn't used. Also, given that the shift is 0, it
doesn't look right.

> +
> +#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)
> +
> +#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 DEFINE_QBCM(_name, _bcmname, _keepalive, _numnodes, ...) \
> + static struct qcom_icc_bcm _name = { \
> + .name = _bcmname, \
> + .keepalive = _keepalive, \
> + .num_nodes = _numnodes, \
> + .nodes = { __VA_ARGS__ }, \
> + }
> +
> +struct qcom_icc_provider {
> + struct icc_provider provider;
> + void __iomem *base;
> + 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: bcm threshold values are in magnitudes of this

I'm having a little trouble understanding this comment, I think it
could be crispened up. So this is a divisor that applies when
converting a bytes/second bandwidth value to an RPMh message. Yes?

> + * @width: prototype width

So this is a multiplier that's applied when converting a bytes/second
bandwidth into an RPMh message?

> + * @vcd: virtual clock domain that this bcm belongs to
> + */
> +
> +struct bcm_db {
> + u32 unit;
> + u16 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
> +
> +/**
> + * 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_bcm: 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;
> + u64 max_peak;
> + 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 or bcm needs to be committed
> + * @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;
> + u64 vote_y;
> + 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;
> + u32 base_offset;
> + u32 qos_offset;
> +};
> +
> +struct qcom_icc_desc {
> + struct qcom_icc_node **nodes;
> + size_t num_nodes;
> + struct qcom_icc_bcm **bcms;
> + size_t num_bcms;
> +};
> +
...
> +
> +static int qcom_tcs_cmd_gen(struct tcs_cmd *cmd, u64 vote_x,
> + u64 vote_y, u32 addr, bool commit)
> +{
> + int ret = 0;
> + bool valid = true;
> +
> + if (!cmd)
> + return ret;
> +
> + 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 commands that have the commit
> + * set, in order to indicate to the RSC to not release the TCS slot
> + * until hardware has acknowledged that this transaction has completed.
> + */
> + if (commit)
> + cmd->wait = true;
> +
> + return ret;

This function appears never to be able to fail. Perhaps remove ret and
change return type to void.

> +}
> +
> +static void qcom_tcs_list_gen(struct list_head *bcm_list,
> + struct tcs_cmd *tcs_list, int *n)
> +{
> + 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_is_last(&bcm->list, bcm_list)) {

Whoa, I think this fixup got scrozzed. The old logic was...
+ if ((bcm->aux_data.vcd !=
+ list_next_entry(bcm, list)->aux_data.vcd) ||
+ list_is_last(&bcm->list, bcm_list)) {
...and I think all you were trying to do was reverse the order of the
two conditionals so list_is_last happened first. Something happened
along the way.

> + commit = true;
> + cur_vcd_size = 0;
> + }
> + qcom_tcs_cmd_gen(&tcs_list[idx], bcm->vote_x, bcm->vote_y,
> + 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 qcom_icc_bcm_aggregate(struct qcom_icc_bcm *bcm)
> +{
> + size_t i;
> + u64 agg_avg = 0;
> + u64 agg_peak = 0;
> +
> + for (i = 0; i < bcm->num_nodes; i++) {
> + agg_avg = max(agg_avg,
> + bcm->nodes[i]->sum_avg * bcm->aux_data.width /
> + (bcm->nodes[i]->buswidth * bcm->nodes[i]->channels));
> + agg_peak = max(agg_peak,
> + bcm->nodes[i]->max_peak * bcm->aux_data.width /
> + bcm->nodes[i]->buswidth);
> + }
> +
> + bcm->vote_x = (u64)(agg_avg * 1000ULL / bcm->aux_data.unit);
> + bcm->vote_y = (u64)(agg_peak * 1000ULL / bcm->aux_data.unit);
> +
> + if (bcm->keepalive && bcm->vote_x == 0 && bcm->vote_y == 0) {
> + bcm->vote_x = 1;
> + bcm->vote_y = 1;
> + }
> +
> + bcm->dirty = false;
> +}
> +
> +static int qcom_icc_aggregate(struct icc_node *node, u32 avg_bw,
> + u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
> +{
> + size_t i;
> + struct qcom_icc_node *qn;
> +
> + qn = node->data;
> +
> + *agg_avg += avg_bw;
> + *agg_peak = max_t(u64, agg_peak, peak_bw);

This should be u32 instead of u64. My compiler complains about this.

> +
> + qn->sum_avg = *agg_avg;
> + qn->max_peak = *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)
...