1b5d2f741SDavid Dai // SPDX-License-Identifier: GPL-2.0
2b5d2f741SDavid Dai /*
3b5d2f741SDavid Dai  * Copyright (c) 2018, The Linux Foundation. All rights reserved.
4b5d2f741SDavid Dai  *
5b5d2f741SDavid Dai  */
6b5d2f741SDavid Dai 
7b5d2f741SDavid Dai #include <asm/div64.h>
8b5d2f741SDavid Dai #include <dt-bindings/interconnect/qcom,sdm845.h>
9b5d2f741SDavid Dai #include <linux/device.h>
10b5d2f741SDavid Dai #include <linux/interconnect.h>
11b5d2f741SDavid Dai #include <linux/interconnect-provider.h>
12b5d2f741SDavid Dai #include <linux/io.h>
13b5d2f741SDavid Dai #include <linux/module.h>
14b5d2f741SDavid Dai #include <linux/of_device.h>
15b5d2f741SDavid Dai #include <linux/of_platform.h>
16b5d2f741SDavid Dai #include <linux/platform_device.h>
17b5d2f741SDavid Dai #include <linux/sort.h>
18b5d2f741SDavid Dai 
19b5d2f741SDavid Dai #include <soc/qcom/cmd-db.h>
20b5d2f741SDavid Dai #include <soc/qcom/rpmh.h>
21b5d2f741SDavid Dai #include <soc/qcom/tcs.h>
22b5d2f741SDavid Dai 
23b5d2f741SDavid Dai #define BCM_TCS_CMD_COMMIT_SHFT		30
24b5d2f741SDavid Dai #define BCM_TCS_CMD_COMMIT_MASK		0x40000000
25b5d2f741SDavid Dai #define BCM_TCS_CMD_VALID_SHFT		29
26b5d2f741SDavid Dai #define BCM_TCS_CMD_VALID_MASK		0x20000000
27b5d2f741SDavid Dai #define BCM_TCS_CMD_VOTE_X_SHFT		14
28b5d2f741SDavid Dai #define BCM_TCS_CMD_VOTE_MASK		0x3fff
29b5d2f741SDavid Dai #define BCM_TCS_CMD_VOTE_Y_SHFT		0
30b5d2f741SDavid Dai #define BCM_TCS_CMD_VOTE_Y_MASK		0xfffc000
31b5d2f741SDavid Dai 
32b5d2f741SDavid Dai #define BCM_TCS_CMD(commit, valid, vote_x, vote_y)		\
33b5d2f741SDavid Dai 	(((commit) << BCM_TCS_CMD_COMMIT_SHFT) |		\
34b5d2f741SDavid Dai 	((valid) << BCM_TCS_CMD_VALID_SHFT) |			\
35b5d2f741SDavid Dai 	((cpu_to_le32(vote_x) &					\
36b5d2f741SDavid Dai 	BCM_TCS_CMD_VOTE_MASK) << BCM_TCS_CMD_VOTE_X_SHFT) |	\
37b5d2f741SDavid Dai 	((cpu_to_le32(vote_y) &					\
38b5d2f741SDavid Dai 	BCM_TCS_CMD_VOTE_MASK) << BCM_TCS_CMD_VOTE_Y_SHFT))
39b5d2f741SDavid Dai 
40b5d2f741SDavid Dai #define to_qcom_provider(_provider) \
41b5d2f741SDavid Dai 	container_of(_provider, struct qcom_icc_provider, provider)
42b5d2f741SDavid Dai 
43b5d2f741SDavid Dai struct qcom_icc_provider {
44b5d2f741SDavid Dai 	struct icc_provider provider;
45b5d2f741SDavid Dai 	struct device *dev;
46b5d2f741SDavid Dai 	struct qcom_icc_bcm **bcms;
47b5d2f741SDavid Dai 	size_t num_bcms;
48b5d2f741SDavid Dai };
49b5d2f741SDavid Dai 
50b5d2f741SDavid Dai /**
51b5d2f741SDavid Dai  * struct bcm_db - Auxiliary data pertaining to each Bus Clock Manager (BCM)
52b5d2f741SDavid Dai  * @unit: divisor used to convert bytes/sec bw value to an RPMh msg
53b5d2f741SDavid Dai  * @width: multiplier used to convert bytes/sec bw value to an RPMh msg
54b5d2f741SDavid Dai  * @vcd: virtual clock domain that this bcm belongs to
55b5d2f741SDavid Dai  * @reserved: reserved field
56b5d2f741SDavid Dai  */
57b5d2f741SDavid Dai struct bcm_db {
58b5d2f741SDavid Dai 	__le32 unit;
59b5d2f741SDavid Dai 	__le16 width;
60b5d2f741SDavid Dai 	u8 vcd;
61b5d2f741SDavid Dai 	u8 reserved;
62b5d2f741SDavid Dai };
63b5d2f741SDavid Dai 
64b5d2f741SDavid Dai #define SDM845_MAX_LINKS	43
65b5d2f741SDavid Dai #define SDM845_MAX_BCMS		30
66b5d2f741SDavid Dai #define SDM845_MAX_BCM_PER_NODE	2
67b5d2f741SDavid Dai #define SDM845_MAX_VCD		10
68b5d2f741SDavid Dai 
699e3ce77cSDavid Dai /*
709e3ce77cSDavid Dai  * The AMC bucket denotes constraints that are applied to hardware when
719e3ce77cSDavid Dai  * icc_set_bw() completes, whereas the WAKE and SLEEP constraints are applied
729e3ce77cSDavid Dai  * when the execution environment transitions between active and low power mode.
739e3ce77cSDavid Dai  */
749e3ce77cSDavid Dai #define QCOM_ICC_BUCKET_AMC		0
759e3ce77cSDavid Dai #define QCOM_ICC_BUCKET_WAKE		1
769e3ce77cSDavid Dai #define QCOM_ICC_BUCKET_SLEEP		2
779e3ce77cSDavid Dai #define QCOM_ICC_NUM_BUCKETS		3
789e3ce77cSDavid Dai #define QCOM_ICC_TAG_AMC		BIT(QCOM_ICC_BUCKET_AMC)
799e3ce77cSDavid Dai #define QCOM_ICC_TAG_WAKE		BIT(QCOM_ICC_BUCKET_WAKE)
809e3ce77cSDavid Dai #define QCOM_ICC_TAG_SLEEP		BIT(QCOM_ICC_BUCKET_SLEEP)
819e3ce77cSDavid Dai #define QCOM_ICC_TAG_ACTIVE_ONLY	(QCOM_ICC_TAG_AMC | QCOM_ICC_TAG_WAKE)
829e3ce77cSDavid Dai #define QCOM_ICC_TAG_ALWAYS		(QCOM_ICC_TAG_AMC | QCOM_ICC_TAG_WAKE |\
839e3ce77cSDavid Dai 					 QCOM_ICC_TAG_SLEEP)
849e3ce77cSDavid Dai 
85b5d2f741SDavid Dai /**
86b5d2f741SDavid Dai  * struct qcom_icc_node - Qualcomm specific interconnect nodes
87b5d2f741SDavid Dai  * @name: the node name used in debugfs
88b5d2f741SDavid Dai  * @links: an array of nodes where we can go next while traversing
89b5d2f741SDavid Dai  * @id: a unique node identifier
90b5d2f741SDavid Dai  * @num_links: the total number of @links
91b5d2f741SDavid Dai  * @channels: num of channels at this node
92b5d2f741SDavid Dai  * @buswidth: width of the interconnect between a node and the bus
93b5d2f741SDavid Dai  * @sum_avg: current sum aggregate value of all avg bw requests
94b5d2f741SDavid Dai  * @max_peak: current max aggregate value of all peak bw requests
95b5d2f741SDavid Dai  * @bcms: list of bcms associated with this logical node
96b5d2f741SDavid Dai  * @num_bcms: num of @bcms
97b5d2f741SDavid Dai  */
98b5d2f741SDavid Dai struct qcom_icc_node {
99b5d2f741SDavid Dai 	const char *name;
100b5d2f741SDavid Dai 	u16 links[SDM845_MAX_LINKS];
101b5d2f741SDavid Dai 	u16 id;
102b5d2f741SDavid Dai 	u16 num_links;
103b5d2f741SDavid Dai 	u16 channels;
104b5d2f741SDavid Dai 	u16 buswidth;
1059e3ce77cSDavid Dai 	u64 sum_avg[QCOM_ICC_NUM_BUCKETS];
1069e3ce77cSDavid Dai 	u64 max_peak[QCOM_ICC_NUM_BUCKETS];
107b5d2f741SDavid Dai 	struct qcom_icc_bcm *bcms[SDM845_MAX_BCM_PER_NODE];
108b5d2f741SDavid Dai 	size_t num_bcms;
109b5d2f741SDavid Dai };
110b5d2f741SDavid Dai 
111b5d2f741SDavid Dai /**
112b5d2f741SDavid Dai  * struct qcom_icc_bcm - Qualcomm specific hardware accelerator nodes
113b5d2f741SDavid Dai  * known as Bus Clock Manager (BCM)
114b5d2f741SDavid Dai  * @name: the bcm node name used to fetch BCM data from command db
115b5d2f741SDavid Dai  * @type: latency or bandwidth bcm
116b5d2f741SDavid Dai  * @addr: address offsets used when voting to RPMH
117b5d2f741SDavid Dai  * @vote_x: aggregated threshold values, represents sum_bw when @type is bw bcm
118b5d2f741SDavid Dai  * @vote_y: aggregated threshold values, represents peak_bw when @type is bw bcm
119b5d2f741SDavid Dai  * @dirty: flag used to indicate whether the bcm needs to be committed
120b5d2f741SDavid Dai  * @keepalive: flag used to indicate whether a keepalive is required
121b5d2f741SDavid Dai  * @aux_data: auxiliary data used when calculating threshold values and
122b5d2f741SDavid Dai  * communicating with RPMh
123b5d2f741SDavid Dai  * @list: used to link to other bcms when compiling lists for commit
124b5d2f741SDavid Dai  * @num_nodes: total number of @num_nodes
125b5d2f741SDavid Dai  * @nodes: list of qcom_icc_nodes that this BCM encapsulates
126b5d2f741SDavid Dai  */
127b5d2f741SDavid Dai struct qcom_icc_bcm {
128b5d2f741SDavid Dai 	const char *name;
129b5d2f741SDavid Dai 	u32 type;
130b5d2f741SDavid Dai 	u32 addr;
1319e3ce77cSDavid Dai 	u64 vote_x[QCOM_ICC_NUM_BUCKETS];
1329e3ce77cSDavid Dai 	u64 vote_y[QCOM_ICC_NUM_BUCKETS];
133b5d2f741SDavid Dai 	bool dirty;
134b5d2f741SDavid Dai 	bool keepalive;
135b5d2f741SDavid Dai 	struct bcm_db aux_data;
136b5d2f741SDavid Dai 	struct list_head list;
137b5d2f741SDavid Dai 	size_t num_nodes;
138b5d2f741SDavid Dai 	struct qcom_icc_node *nodes[];
139b5d2f741SDavid Dai };
140b5d2f741SDavid Dai 
141b5d2f741SDavid Dai struct qcom_icc_fabric {
142b5d2f741SDavid Dai 	struct qcom_icc_node **nodes;
143b5d2f741SDavid Dai 	size_t num_nodes;
144b5d2f741SDavid Dai };
145b5d2f741SDavid Dai 
146b5d2f741SDavid Dai struct qcom_icc_desc {
147b5d2f741SDavid Dai 	struct qcom_icc_node **nodes;
148b5d2f741SDavid Dai 	size_t num_nodes;
149b5d2f741SDavid Dai 	struct qcom_icc_bcm **bcms;
150b5d2f741SDavid Dai 	size_t num_bcms;
151b5d2f741SDavid Dai };
152b5d2f741SDavid Dai 
153b5d2f741SDavid Dai #define DEFINE_QNODE(_name, _id, _channels, _buswidth,			\
154b5d2f741SDavid Dai 			_numlinks, ...)					\
155b5d2f741SDavid Dai 		static struct qcom_icc_node _name = {			\
156b5d2f741SDavid Dai 		.id = _id,						\
157b5d2f741SDavid Dai 		.name = #_name,						\
158b5d2f741SDavid Dai 		.channels = _channels,					\
159b5d2f741SDavid Dai 		.buswidth = _buswidth,					\
160b5d2f741SDavid Dai 		.num_links = _numlinks,					\
161b5d2f741SDavid Dai 		.links = { __VA_ARGS__ },				\
162b5d2f741SDavid Dai 	}
163b5d2f741SDavid Dai 
164b5d2f741SDavid Dai DEFINE_QNODE(qhm_a1noc_cfg, MASTER_A1NOC_CFG, 1, 4, 1, SLAVE_SERVICE_A1NOC);
165b5d2f741SDavid Dai DEFINE_QNODE(qhm_qup1, MASTER_BLSP_1, 1, 4, 1, SLAVE_A1NOC_SNOC);
166b5d2f741SDavid Dai DEFINE_QNODE(qhm_tsif, MASTER_TSIF, 1, 4, 1, SLAVE_A1NOC_SNOC);
167b5d2f741SDavid Dai DEFINE_QNODE(xm_sdc2, MASTER_SDCC_2, 1, 8, 1, SLAVE_A1NOC_SNOC);
168b5d2f741SDavid Dai DEFINE_QNODE(xm_sdc4, MASTER_SDCC_4, 1, 8, 1, SLAVE_A1NOC_SNOC);
169b5d2f741SDavid Dai DEFINE_QNODE(xm_ufs_card, MASTER_UFS_CARD, 1, 8, 1, SLAVE_A1NOC_SNOC);
170b5d2f741SDavid Dai DEFINE_QNODE(xm_ufs_mem, MASTER_UFS_MEM, 1, 8, 1, SLAVE_A1NOC_SNOC);
171b5d2f741SDavid Dai DEFINE_QNODE(xm_pcie_0, MASTER_PCIE_0, 1, 8, 1, SLAVE_ANOC_PCIE_A1NOC_SNOC);
172b5d2f741SDavid Dai DEFINE_QNODE(qhm_a2noc_cfg, MASTER_A2NOC_CFG, 1, 4, 1, SLAVE_SERVICE_A2NOC);
173b5d2f741SDavid Dai DEFINE_QNODE(qhm_qdss_bam, MASTER_QDSS_BAM, 1, 4, 1, SLAVE_A2NOC_SNOC);
174b5d2f741SDavid Dai DEFINE_QNODE(qhm_qup2, MASTER_BLSP_2, 1, 4, 1, SLAVE_A2NOC_SNOC);
175b5d2f741SDavid Dai DEFINE_QNODE(qnm_cnoc, MASTER_CNOC_A2NOC, 1, 8, 1, SLAVE_A2NOC_SNOC);
176b5d2f741SDavid Dai DEFINE_QNODE(qxm_crypto, MASTER_CRYPTO, 1, 8, 1, SLAVE_A2NOC_SNOC);
177b5d2f741SDavid Dai DEFINE_QNODE(qxm_ipa, MASTER_IPA, 1, 8, 1, SLAVE_A2NOC_SNOC);
178b5d2f741SDavid Dai DEFINE_QNODE(xm_pcie3_1, MASTER_PCIE_1, 1, 8, 1, SLAVE_ANOC_PCIE_SNOC);
179b5d2f741SDavid Dai DEFINE_QNODE(xm_qdss_etr, MASTER_QDSS_ETR, 1, 8, 1, SLAVE_A2NOC_SNOC);
180b5d2f741SDavid Dai DEFINE_QNODE(xm_usb3_0, MASTER_USB3_0, 1, 8, 1, SLAVE_A2NOC_SNOC);
181b5d2f741SDavid Dai DEFINE_QNODE(xm_usb3_1, MASTER_USB3_1, 1, 8, 1, SLAVE_A2NOC_SNOC);
182b5d2f741SDavid Dai DEFINE_QNODE(qxm_camnoc_hf0_uncomp, MASTER_CAMNOC_HF0_UNCOMP, 1, 32, 1, SLAVE_CAMNOC_UNCOMP);
183b5d2f741SDavid Dai DEFINE_QNODE(qxm_camnoc_hf1_uncomp, MASTER_CAMNOC_HF1_UNCOMP, 1, 32, 1, SLAVE_CAMNOC_UNCOMP);
184b5d2f741SDavid Dai DEFINE_QNODE(qxm_camnoc_sf_uncomp, MASTER_CAMNOC_SF_UNCOMP, 1, 32, 1, SLAVE_CAMNOC_UNCOMP);
185b5d2f741SDavid Dai DEFINE_QNODE(qhm_spdm, MASTER_SPDM, 1, 4, 1, SLAVE_CNOC_A2NOC);
186b5d2f741SDavid Dai 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);
187b5d2f741SDavid Dai 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);
188b5d2f741SDavid Dai 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);
189b5d2f741SDavid Dai DEFINE_QNODE(qhm_cnoc, MASTER_CNOC_DC_NOC, 1, 4, 2, SLAVE_LLCC_CFG, SLAVE_MEM_NOC_CFG);
190b5d2f741SDavid Dai DEFINE_QNODE(acm_l3, MASTER_APPSS_PROC, 1, 16, 3, SLAVE_GNOC_SNOC, SLAVE_GNOC_MEM_NOC, SLAVE_SERVICE_GNOC);
191b5d2f741SDavid Dai DEFINE_QNODE(pm_gnoc_cfg, MASTER_GNOC_CFG, 1, 4, 1, SLAVE_SERVICE_GNOC);
192b5d2f741SDavid Dai DEFINE_QNODE(llcc_mc, MASTER_LLCC, 4, 4, 1, SLAVE_EBI1);
193b5d2f741SDavid Dai DEFINE_QNODE(acm_tcu, MASTER_TCU_0, 1, 8, 3, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC, SLAVE_MEM_NOC_SNOC);
194b5d2f741SDavid Dai DEFINE_QNODE(qhm_memnoc_cfg, MASTER_MEM_NOC_CFG, 1, 4, 2, SLAVE_MSS_PROC_MS_MPU_CFG, SLAVE_SERVICE_MEM_NOC);
195b5d2f741SDavid Dai DEFINE_QNODE(qnm_apps, MASTER_GNOC_MEM_NOC, 2, 32, 1, SLAVE_LLCC);
196b5d2f741SDavid Dai DEFINE_QNODE(qnm_mnoc_hf, MASTER_MNOC_HF_MEM_NOC, 2, 32, 2, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC);
197b5d2f741SDavid Dai DEFINE_QNODE(qnm_mnoc_sf, MASTER_MNOC_SF_MEM_NOC, 1, 32, 3, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC, SLAVE_MEM_NOC_SNOC);
198b5d2f741SDavid Dai DEFINE_QNODE(qnm_snoc_gc, MASTER_SNOC_GC_MEM_NOC, 1, 8, 1, SLAVE_LLCC);
199b5d2f741SDavid Dai DEFINE_QNODE(qnm_snoc_sf, MASTER_SNOC_SF_MEM_NOC, 1, 16, 2, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC);
200b5d2f741SDavid Dai DEFINE_QNODE(qxm_gpu, MASTER_GFX3D, 2, 32, 3, SLAVE_MEM_NOC_GNOC, SLAVE_LLCC, SLAVE_MEM_NOC_SNOC);
201b5d2f741SDavid Dai DEFINE_QNODE(qhm_mnoc_cfg, MASTER_CNOC_MNOC_CFG, 1, 4, 1, SLAVE_SERVICE_MNOC);
202b5d2f741SDavid Dai DEFINE_QNODE(qxm_camnoc_hf0, MASTER_CAMNOC_HF0, 1, 32, 1, SLAVE_MNOC_HF_MEM_NOC);
203b5d2f741SDavid Dai DEFINE_QNODE(qxm_camnoc_hf1, MASTER_CAMNOC_HF1, 1, 32, 1, SLAVE_MNOC_HF_MEM_NOC);
204b5d2f741SDavid Dai DEFINE_QNODE(qxm_camnoc_sf, MASTER_CAMNOC_SF, 1, 32, 1, SLAVE_MNOC_SF_MEM_NOC);
205b5d2f741SDavid Dai DEFINE_QNODE(qxm_mdp0, MASTER_MDP0, 1, 32, 1, SLAVE_MNOC_HF_MEM_NOC);
206b5d2f741SDavid Dai DEFINE_QNODE(qxm_mdp1, MASTER_MDP1, 1, 32, 1, SLAVE_MNOC_HF_MEM_NOC);
207b5d2f741SDavid Dai DEFINE_QNODE(qxm_rot, MASTER_ROTATOR, 1, 32, 1, SLAVE_MNOC_SF_MEM_NOC);
208b5d2f741SDavid Dai DEFINE_QNODE(qxm_venus0, MASTER_VIDEO_P0, 1, 32, 1, SLAVE_MNOC_SF_MEM_NOC);
209b5d2f741SDavid Dai DEFINE_QNODE(qxm_venus1, MASTER_VIDEO_P1, 1, 32, 1, SLAVE_MNOC_SF_MEM_NOC);
210b5d2f741SDavid Dai DEFINE_QNODE(qxm_venus_arm9, MASTER_VIDEO_PROC, 1, 8, 1, SLAVE_MNOC_SF_MEM_NOC);
211b5d2f741SDavid Dai DEFINE_QNODE(qhm_snoc_cfg, MASTER_SNOC_CFG, 1, 4, 1, SLAVE_SERVICE_SNOC);
212b5d2f741SDavid Dai 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);
213b5d2f741SDavid Dai 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);
214b5d2f741SDavid Dai 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);
215b5d2f741SDavid Dai DEFINE_QNODE(qnm_memnoc, MASTER_MEM_NOC_SNOC, 1, 8, 5, SLAVE_APPSS, SLAVE_SNOC_CNOC, SLAVE_IMEM, SLAVE_PIMEM, SLAVE_QDSS_STM);
216b5d2f741SDavid Dai 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);
217b5d2f741SDavid Dai DEFINE_QNODE(qxm_pimem, MASTER_PIMEM, 1, 8, 2, SLAVE_SNOC_MEM_NOC_GC, SLAVE_IMEM);
218b5d2f741SDavid Dai DEFINE_QNODE(xm_gic, MASTER_GIC, 1, 8, 2, SLAVE_SNOC_MEM_NOC_GC, SLAVE_IMEM);
219b5d2f741SDavid Dai DEFINE_QNODE(qns_a1noc_snoc, SLAVE_A1NOC_SNOC, 1, 16, 1, MASTER_A1NOC_SNOC);
220b5d2f741SDavid Dai DEFINE_QNODE(srvc_aggre1_noc, SLAVE_SERVICE_A1NOC, 1, 4, 0);
221b5d2f741SDavid Dai DEFINE_QNODE(qns_pcie_a1noc_snoc, SLAVE_ANOC_PCIE_A1NOC_SNOC, 1, 16, 1, MASTER_ANOC_PCIE_SNOC);
222b5d2f741SDavid Dai DEFINE_QNODE(qns_a2noc_snoc, SLAVE_A2NOC_SNOC, 1, 16, 1, MASTER_A2NOC_SNOC);
223b5d2f741SDavid Dai DEFINE_QNODE(qns_pcie_snoc, SLAVE_ANOC_PCIE_SNOC, 1, 16, 1, MASTER_ANOC_PCIE_SNOC);
224b5d2f741SDavid Dai DEFINE_QNODE(srvc_aggre2_noc, SLAVE_SERVICE_A2NOC, 1, 4, 0);
225b5d2f741SDavid Dai DEFINE_QNODE(qns_camnoc_uncomp, SLAVE_CAMNOC_UNCOMP, 1, 32, 0);
226b5d2f741SDavid Dai DEFINE_QNODE(qhs_a1_noc_cfg, SLAVE_A1NOC_CFG, 1, 4, 1, MASTER_A1NOC_CFG);
227b5d2f741SDavid Dai DEFINE_QNODE(qhs_a2_noc_cfg, SLAVE_A2NOC_CFG, 1, 4, 1, MASTER_A2NOC_CFG);
228b5d2f741SDavid Dai DEFINE_QNODE(qhs_aop, SLAVE_AOP, 1, 4, 0);
229b5d2f741SDavid Dai DEFINE_QNODE(qhs_aoss, SLAVE_AOSS, 1, 4, 0);
230b5d2f741SDavid Dai DEFINE_QNODE(qhs_camera_cfg, SLAVE_CAMERA_CFG, 1, 4, 0);
231b5d2f741SDavid Dai DEFINE_QNODE(qhs_clk_ctl, SLAVE_CLK_CTL, 1, 4, 0);
232b5d2f741SDavid Dai DEFINE_QNODE(qhs_compute_dsp_cfg, SLAVE_CDSP_CFG, 1, 4, 0);
233b5d2f741SDavid Dai DEFINE_QNODE(qhs_cpr_cx, SLAVE_RBCPR_CX_CFG, 1, 4, 0);
234b5d2f741SDavid Dai DEFINE_QNODE(qhs_crypto0_cfg, SLAVE_CRYPTO_0_CFG, 1, 4, 0);
235b5d2f741SDavid Dai DEFINE_QNODE(qhs_dcc_cfg, SLAVE_DCC_CFG, 1, 4, 1, MASTER_CNOC_DC_NOC);
236b5d2f741SDavid Dai DEFINE_QNODE(qhs_ddrss_cfg, SLAVE_CNOC_DDRSS, 1, 4, 0);
237b5d2f741SDavid Dai DEFINE_QNODE(qhs_display_cfg, SLAVE_DISPLAY_CFG, 1, 4, 0);
238b5d2f741SDavid Dai DEFINE_QNODE(qhs_glm, SLAVE_GLM, 1, 4, 0);
239b5d2f741SDavid Dai DEFINE_QNODE(qhs_gpuss_cfg, SLAVE_GFX3D_CFG, 1, 8, 0);
240b5d2f741SDavid Dai DEFINE_QNODE(qhs_imem_cfg, SLAVE_IMEM_CFG, 1, 4, 0);
241b5d2f741SDavid Dai DEFINE_QNODE(qhs_ipa, SLAVE_IPA_CFG, 1, 4, 0);
242b5d2f741SDavid Dai DEFINE_QNODE(qhs_mnoc_cfg, SLAVE_CNOC_MNOC_CFG, 1, 4, 1, MASTER_CNOC_MNOC_CFG);
243b5d2f741SDavid Dai DEFINE_QNODE(qhs_pcie0_cfg, SLAVE_PCIE_0_CFG, 1, 4, 0);
244b5d2f741SDavid Dai DEFINE_QNODE(qhs_pcie_gen3_cfg, SLAVE_PCIE_1_CFG, 1, 4, 0);
245b5d2f741SDavid Dai DEFINE_QNODE(qhs_pdm, SLAVE_PDM, 1, 4, 0);
246b5d2f741SDavid Dai DEFINE_QNODE(qhs_phy_refgen_south, SLAVE_SOUTH_PHY_CFG, 1, 4, 0);
247b5d2f741SDavid Dai DEFINE_QNODE(qhs_pimem_cfg, SLAVE_PIMEM_CFG, 1, 4, 0);
248b5d2f741SDavid Dai DEFINE_QNODE(qhs_prng, SLAVE_PRNG, 1, 4, 0);
249b5d2f741SDavid Dai DEFINE_QNODE(qhs_qdss_cfg, SLAVE_QDSS_CFG, 1, 4, 0);
250b5d2f741SDavid Dai DEFINE_QNODE(qhs_qupv3_north, SLAVE_BLSP_2, 1, 4, 0);
251b5d2f741SDavid Dai DEFINE_QNODE(qhs_qupv3_south, SLAVE_BLSP_1, 1, 4, 0);
252b5d2f741SDavid Dai DEFINE_QNODE(qhs_sdc2, SLAVE_SDCC_2, 1, 4, 0);
253b5d2f741SDavid Dai DEFINE_QNODE(qhs_sdc4, SLAVE_SDCC_4, 1, 4, 0);
254b5d2f741SDavid Dai DEFINE_QNODE(qhs_snoc_cfg, SLAVE_SNOC_CFG, 1, 4, 1, MASTER_SNOC_CFG);
255b5d2f741SDavid Dai DEFINE_QNODE(qhs_spdm, SLAVE_SPDM_WRAPPER, 1, 4, 0);
256b5d2f741SDavid Dai DEFINE_QNODE(qhs_spss_cfg, SLAVE_SPSS_CFG, 1, 4, 0);
257b5d2f741SDavid Dai DEFINE_QNODE(qhs_tcsr, SLAVE_TCSR, 1, 4, 0);
258b5d2f741SDavid Dai DEFINE_QNODE(qhs_tlmm_north, SLAVE_TLMM_NORTH, 1, 4, 0);
259b5d2f741SDavid Dai DEFINE_QNODE(qhs_tlmm_south, SLAVE_TLMM_SOUTH, 1, 4, 0);
260b5d2f741SDavid Dai DEFINE_QNODE(qhs_tsif, SLAVE_TSIF, 1, 4, 0);
261b5d2f741SDavid Dai DEFINE_QNODE(qhs_ufs_card_cfg, SLAVE_UFS_CARD_CFG, 1, 4, 0);
262b5d2f741SDavid Dai DEFINE_QNODE(qhs_ufs_mem_cfg, SLAVE_UFS_MEM_CFG, 1, 4, 0);
263b5d2f741SDavid Dai DEFINE_QNODE(qhs_usb3_0, SLAVE_USB3_0, 1, 4, 0);
264b5d2f741SDavid Dai DEFINE_QNODE(qhs_usb3_1, SLAVE_USB3_1, 1, 4, 0);
265b5d2f741SDavid Dai DEFINE_QNODE(qhs_venus_cfg, SLAVE_VENUS_CFG, 1, 4, 0);
266b5d2f741SDavid Dai DEFINE_QNODE(qhs_vsense_ctrl_cfg, SLAVE_VSENSE_CTRL_CFG, 1, 4, 0);
267b5d2f741SDavid Dai DEFINE_QNODE(qns_cnoc_a2noc, SLAVE_CNOC_A2NOC, 1, 8, 1, MASTER_CNOC_A2NOC);
268b5d2f741SDavid Dai DEFINE_QNODE(srvc_cnoc, SLAVE_SERVICE_CNOC, 1, 4, 0);
269b5d2f741SDavid Dai DEFINE_QNODE(qhs_llcc, SLAVE_LLCC_CFG, 1, 4, 0);
270b5d2f741SDavid Dai DEFINE_QNODE(qhs_memnoc, SLAVE_MEM_NOC_CFG, 1, 4, 1, MASTER_MEM_NOC_CFG);
271b5d2f741SDavid Dai DEFINE_QNODE(qns_gladiator_sodv, SLAVE_GNOC_SNOC, 1, 8, 1, MASTER_GNOC_SNOC);
272b5d2f741SDavid Dai DEFINE_QNODE(qns_gnoc_memnoc, SLAVE_GNOC_MEM_NOC, 2, 32, 1, MASTER_GNOC_MEM_NOC);
273b5d2f741SDavid Dai DEFINE_QNODE(srvc_gnoc, SLAVE_SERVICE_GNOC, 1, 4, 0);
274b5d2f741SDavid Dai DEFINE_QNODE(ebi, SLAVE_EBI1, 4, 4, 0);
275b5d2f741SDavid Dai DEFINE_QNODE(qhs_mdsp_ms_mpu_cfg, SLAVE_MSS_PROC_MS_MPU_CFG, 1, 4, 0);
276b5d2f741SDavid Dai DEFINE_QNODE(qns_apps_io, SLAVE_MEM_NOC_GNOC, 1, 32, 0);
277b5d2f741SDavid Dai DEFINE_QNODE(qns_llcc, SLAVE_LLCC, 4, 16, 1, MASTER_LLCC);
278b5d2f741SDavid Dai DEFINE_QNODE(qns_memnoc_snoc, SLAVE_MEM_NOC_SNOC, 1, 8, 1, MASTER_MEM_NOC_SNOC);
279b5d2f741SDavid Dai DEFINE_QNODE(srvc_memnoc, SLAVE_SERVICE_MEM_NOC, 1, 4, 0);
280b5d2f741SDavid Dai DEFINE_QNODE(qns2_mem_noc, SLAVE_MNOC_SF_MEM_NOC, 1, 32, 1, MASTER_MNOC_SF_MEM_NOC);
281b5d2f741SDavid Dai DEFINE_QNODE(qns_mem_noc_hf, SLAVE_MNOC_HF_MEM_NOC, 2, 32, 1, MASTER_MNOC_HF_MEM_NOC);
282b5d2f741SDavid Dai DEFINE_QNODE(srvc_mnoc, SLAVE_SERVICE_MNOC, 1, 4, 0);
283b5d2f741SDavid Dai DEFINE_QNODE(qhs_apss, SLAVE_APPSS, 1, 8, 0);
284b5d2f741SDavid Dai DEFINE_QNODE(qns_cnoc, SLAVE_SNOC_CNOC, 1, 8, 1, MASTER_SNOC_CNOC);
285b5d2f741SDavid Dai DEFINE_QNODE(qns_memnoc_gc, SLAVE_SNOC_MEM_NOC_GC, 1, 8, 1, MASTER_SNOC_GC_MEM_NOC);
286b5d2f741SDavid Dai DEFINE_QNODE(qns_memnoc_sf, SLAVE_SNOC_MEM_NOC_SF, 1, 16, 1, MASTER_SNOC_SF_MEM_NOC);
287b5d2f741SDavid Dai DEFINE_QNODE(qxs_imem, SLAVE_IMEM, 1, 8, 0);
288b5d2f741SDavid Dai DEFINE_QNODE(qxs_pcie, SLAVE_PCIE_0, 1, 8, 0);
289b5d2f741SDavid Dai DEFINE_QNODE(qxs_pcie_gen3, SLAVE_PCIE_1, 1, 8, 0);
290b5d2f741SDavid Dai DEFINE_QNODE(qxs_pimem, SLAVE_PIMEM, 1, 8, 0);
291b5d2f741SDavid Dai DEFINE_QNODE(srvc_snoc, SLAVE_SERVICE_SNOC, 1, 4, 0);
292b5d2f741SDavid Dai DEFINE_QNODE(xs_qdss_stm, SLAVE_QDSS_STM, 1, 4, 0);
293b5d2f741SDavid Dai DEFINE_QNODE(xs_sys_tcu_cfg, SLAVE_TCU, 1, 8, 0);
294b5d2f741SDavid Dai 
295b5d2f741SDavid Dai #define DEFINE_QBCM(_name, _bcmname, _keepalive, _numnodes, ...)	\
296b5d2f741SDavid Dai 		static struct qcom_icc_bcm _name = {			\
297b5d2f741SDavid Dai 		.name = _bcmname,					\
298b5d2f741SDavid Dai 		.keepalive = _keepalive,				\
299b5d2f741SDavid Dai 		.num_nodes = _numnodes,					\
300b5d2f741SDavid Dai 		.nodes = { __VA_ARGS__ },				\
301b5d2f741SDavid Dai 	}
302b5d2f741SDavid Dai 
303b5d2f741SDavid Dai DEFINE_QBCM(bcm_acv, "ACV", false, 1, &ebi);
304b5d2f741SDavid Dai DEFINE_QBCM(bcm_mc0, "MC0", true, 1, &ebi);
305b5d2f741SDavid Dai DEFINE_QBCM(bcm_sh0, "SH0", true, 1, &qns_llcc);
306b5d2f741SDavid Dai DEFINE_QBCM(bcm_mm0, "MM0", false, 1, &qns_mem_noc_hf);
307b5d2f741SDavid Dai DEFINE_QBCM(bcm_sh1, "SH1", false, 1, &qns_apps_io);
308b5d2f741SDavid Dai 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);
309b5d2f741SDavid Dai DEFINE_QBCM(bcm_sh2, "SH2", false, 1, &qns_memnoc_snoc);
310b5d2f741SDavid Dai DEFINE_QBCM(bcm_mm2, "MM2", false, 1, &qns2_mem_noc);
311b5d2f741SDavid Dai DEFINE_QBCM(bcm_sh3, "SH3", false, 1, &acm_tcu);
312b5d2f741SDavid Dai DEFINE_QBCM(bcm_mm3, "MM3", false, 5, &qxm_camnoc_sf, &qxm_rot, &qxm_venus0, &qxm_venus1, &qxm_venus_arm9);
313b5d2f741SDavid Dai DEFINE_QBCM(bcm_sh5, "SH5", false, 1, &qnm_apps);
314b5d2f741SDavid Dai DEFINE_QBCM(bcm_sn0, "SN0", true, 1, &qns_memnoc_sf);
315b5d2f741SDavid Dai DEFINE_QBCM(bcm_ce0, "CE0", false, 1, &qxm_crypto);
316b5d2f741SDavid Dai 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);
317b5d2f741SDavid Dai DEFINE_QBCM(bcm_qup0, "QUP0", false, 2, &qhm_qup1, &qhm_qup2);
318b5d2f741SDavid Dai DEFINE_QBCM(bcm_sn1, "SN1", false, 1, &qxs_imem);
319b5d2f741SDavid Dai DEFINE_QBCM(bcm_sn2, "SN2", false, 1, &qns_memnoc_gc);
320b5d2f741SDavid Dai DEFINE_QBCM(bcm_sn3, "SN3", false, 1, &qns_cnoc);
321b5d2f741SDavid Dai DEFINE_QBCM(bcm_sn4, "SN4", false, 1, &qxm_pimem);
322b5d2f741SDavid Dai DEFINE_QBCM(bcm_sn5, "SN5", false, 1, &xs_qdss_stm);
323b5d2f741SDavid Dai DEFINE_QBCM(bcm_sn6, "SN6", false, 3, &qhs_apss, &srvc_snoc, &xs_sys_tcu_cfg);
324b5d2f741SDavid Dai DEFINE_QBCM(bcm_sn7, "SN7", false, 1, &qxs_pcie);
325b5d2f741SDavid Dai DEFINE_QBCM(bcm_sn8, "SN8", false, 1, &qxs_pcie_gen3);
326b5d2f741SDavid Dai DEFINE_QBCM(bcm_sn9, "SN9", false, 2, &srvc_aggre1_noc, &qnm_aggre1_noc);
327b5d2f741SDavid Dai DEFINE_QBCM(bcm_sn11, "SN11", false, 2, &srvc_aggre2_noc, &qnm_aggre2_noc);
328b5d2f741SDavid Dai DEFINE_QBCM(bcm_sn12, "SN12", false, 2, &qnm_gladiator_sodv, &xm_gic);
329b5d2f741SDavid Dai DEFINE_QBCM(bcm_sn14, "SN14", false, 1, &qnm_pcie_anoc);
330b5d2f741SDavid Dai DEFINE_QBCM(bcm_sn15, "SN15", false, 1, &qnm_memnoc);
331b5d2f741SDavid Dai 
332b5d2f741SDavid Dai static struct qcom_icc_node *rsc_hlos_nodes[] = {
333b5d2f741SDavid Dai 	[MASTER_APPSS_PROC] = &acm_l3,
334b5d2f741SDavid Dai 	[MASTER_TCU_0] = &acm_tcu,
335b5d2f741SDavid Dai 	[MASTER_LLCC] = &llcc_mc,
336b5d2f741SDavid Dai 	[MASTER_GNOC_CFG] = &pm_gnoc_cfg,
337b5d2f741SDavid Dai 	[MASTER_A1NOC_CFG] = &qhm_a1noc_cfg,
338b5d2f741SDavid Dai 	[MASTER_A2NOC_CFG] = &qhm_a2noc_cfg,
339b5d2f741SDavid Dai 	[MASTER_CNOC_DC_NOC] = &qhm_cnoc,
340b5d2f741SDavid Dai 	[MASTER_MEM_NOC_CFG] = &qhm_memnoc_cfg,
341b5d2f741SDavid Dai 	[MASTER_CNOC_MNOC_CFG] = &qhm_mnoc_cfg,
342b5d2f741SDavid Dai 	[MASTER_QDSS_BAM] = &qhm_qdss_bam,
343b5d2f741SDavid Dai 	[MASTER_BLSP_1] = &qhm_qup1,
344b5d2f741SDavid Dai 	[MASTER_BLSP_2] = &qhm_qup2,
345b5d2f741SDavid Dai 	[MASTER_SNOC_CFG] = &qhm_snoc_cfg,
346b5d2f741SDavid Dai 	[MASTER_SPDM] = &qhm_spdm,
347b5d2f741SDavid Dai 	[MASTER_TIC] = &qhm_tic,
348b5d2f741SDavid Dai 	[MASTER_TSIF] = &qhm_tsif,
349b5d2f741SDavid Dai 	[MASTER_A1NOC_SNOC] = &qnm_aggre1_noc,
350b5d2f741SDavid Dai 	[MASTER_A2NOC_SNOC] = &qnm_aggre2_noc,
351b5d2f741SDavid Dai 	[MASTER_GNOC_MEM_NOC] = &qnm_apps,
352b5d2f741SDavid Dai 	[MASTER_CNOC_A2NOC] = &qnm_cnoc,
353b5d2f741SDavid Dai 	[MASTER_GNOC_SNOC] = &qnm_gladiator_sodv,
354b5d2f741SDavid Dai 	[MASTER_MEM_NOC_SNOC] = &qnm_memnoc,
355b5d2f741SDavid Dai 	[MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf,
356b5d2f741SDavid Dai 	[MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf,
357b5d2f741SDavid Dai 	[MASTER_ANOC_PCIE_SNOC] = &qnm_pcie_anoc,
358b5d2f741SDavid Dai 	[MASTER_SNOC_CNOC] = &qnm_snoc,
359b5d2f741SDavid Dai 	[MASTER_SNOC_GC_MEM_NOC] = &qnm_snoc_gc,
360b5d2f741SDavid Dai 	[MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf,
361b5d2f741SDavid Dai 	[MASTER_CAMNOC_HF0] = &qxm_camnoc_hf0,
362b5d2f741SDavid Dai 	[MASTER_CAMNOC_HF0_UNCOMP] = &qxm_camnoc_hf0_uncomp,
363b5d2f741SDavid Dai 	[MASTER_CAMNOC_HF1] = &qxm_camnoc_hf1,
364b5d2f741SDavid Dai 	[MASTER_CAMNOC_HF1_UNCOMP] = &qxm_camnoc_hf1_uncomp,
365b5d2f741SDavid Dai 	[MASTER_CAMNOC_SF] = &qxm_camnoc_sf,
366b5d2f741SDavid Dai 	[MASTER_CAMNOC_SF_UNCOMP] = &qxm_camnoc_sf_uncomp,
367b5d2f741SDavid Dai 	[MASTER_CRYPTO] = &qxm_crypto,
368b5d2f741SDavid Dai 	[MASTER_GFX3D] = &qxm_gpu,
369b5d2f741SDavid Dai 	[MASTER_IPA] = &qxm_ipa,
370b5d2f741SDavid Dai 	[MASTER_MDP0] = &qxm_mdp0,
371b5d2f741SDavid Dai 	[MASTER_MDP1] = &qxm_mdp1,
372b5d2f741SDavid Dai 	[MASTER_PIMEM] = &qxm_pimem,
373b5d2f741SDavid Dai 	[MASTER_ROTATOR] = &qxm_rot,
374b5d2f741SDavid Dai 	[MASTER_VIDEO_P0] = &qxm_venus0,
375b5d2f741SDavid Dai 	[MASTER_VIDEO_P1] = &qxm_venus1,
376b5d2f741SDavid Dai 	[MASTER_VIDEO_PROC] = &qxm_venus_arm9,
377b5d2f741SDavid Dai 	[MASTER_GIC] = &xm_gic,
378b5d2f741SDavid Dai 	[MASTER_PCIE_1] = &xm_pcie3_1,
379b5d2f741SDavid Dai 	[MASTER_PCIE_0] = &xm_pcie_0,
380b5d2f741SDavid Dai 	[MASTER_QDSS_DAP] = &xm_qdss_dap,
381b5d2f741SDavid Dai 	[MASTER_QDSS_ETR] = &xm_qdss_etr,
382b5d2f741SDavid Dai 	[MASTER_SDCC_2] = &xm_sdc2,
383b5d2f741SDavid Dai 	[MASTER_SDCC_4] = &xm_sdc4,
384b5d2f741SDavid Dai 	[MASTER_UFS_CARD] = &xm_ufs_card,
385b5d2f741SDavid Dai 	[MASTER_UFS_MEM] = &xm_ufs_mem,
386b5d2f741SDavid Dai 	[MASTER_USB3_0] = &xm_usb3_0,
387b5d2f741SDavid Dai 	[MASTER_USB3_1] = &xm_usb3_1,
388b5d2f741SDavid Dai 	[SLAVE_EBI1] = &ebi,
389b5d2f741SDavid Dai 	[SLAVE_A1NOC_CFG] = &qhs_a1_noc_cfg,
390b5d2f741SDavid Dai 	[SLAVE_A2NOC_CFG] = &qhs_a2_noc_cfg,
391b5d2f741SDavid Dai 	[SLAVE_AOP] = &qhs_aop,
392b5d2f741SDavid Dai 	[SLAVE_AOSS] = &qhs_aoss,
393b5d2f741SDavid Dai 	[SLAVE_APPSS] = &qhs_apss,
394b5d2f741SDavid Dai 	[SLAVE_CAMERA_CFG] = &qhs_camera_cfg,
395b5d2f741SDavid Dai 	[SLAVE_CLK_CTL] = &qhs_clk_ctl,
396b5d2f741SDavid Dai 	[SLAVE_CDSP_CFG] = &qhs_compute_dsp_cfg,
397b5d2f741SDavid Dai 	[SLAVE_RBCPR_CX_CFG] = &qhs_cpr_cx,
398b5d2f741SDavid Dai 	[SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg,
399b5d2f741SDavid Dai 	[SLAVE_DCC_CFG] = &qhs_dcc_cfg,
400b5d2f741SDavid Dai 	[SLAVE_CNOC_DDRSS] = &qhs_ddrss_cfg,
401b5d2f741SDavid Dai 	[SLAVE_DISPLAY_CFG] = &qhs_display_cfg,
402b5d2f741SDavid Dai 	[SLAVE_GLM] = &qhs_glm,
403b5d2f741SDavid Dai 	[SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg,
404b5d2f741SDavid Dai 	[SLAVE_IMEM_CFG] = &qhs_imem_cfg,
405b5d2f741SDavid Dai 	[SLAVE_IPA_CFG] = &qhs_ipa,
406b5d2f741SDavid Dai 	[SLAVE_LLCC_CFG] = &qhs_llcc,
407b5d2f741SDavid Dai 	[SLAVE_MSS_PROC_MS_MPU_CFG] = &qhs_mdsp_ms_mpu_cfg,
408b5d2f741SDavid Dai 	[SLAVE_MEM_NOC_CFG] = &qhs_memnoc,
409b5d2f741SDavid Dai 	[SLAVE_CNOC_MNOC_CFG] = &qhs_mnoc_cfg,
410b5d2f741SDavid Dai 	[SLAVE_PCIE_0_CFG] = &qhs_pcie0_cfg,
411b5d2f741SDavid Dai 	[SLAVE_PCIE_1_CFG] = &qhs_pcie_gen3_cfg,
412b5d2f741SDavid Dai 	[SLAVE_PDM] = &qhs_pdm,
413b5d2f741SDavid Dai 	[SLAVE_SOUTH_PHY_CFG] = &qhs_phy_refgen_south,
414b5d2f741SDavid Dai 	[SLAVE_PIMEM_CFG] = &qhs_pimem_cfg,
415b5d2f741SDavid Dai 	[SLAVE_PRNG] = &qhs_prng,
416b5d2f741SDavid Dai 	[SLAVE_QDSS_CFG] = &qhs_qdss_cfg,
417b5d2f741SDavid Dai 	[SLAVE_BLSP_2] = &qhs_qupv3_north,
418b5d2f741SDavid Dai 	[SLAVE_BLSP_1] = &qhs_qupv3_south,
419b5d2f741SDavid Dai 	[SLAVE_SDCC_2] = &qhs_sdc2,
420b5d2f741SDavid Dai 	[SLAVE_SDCC_4] = &qhs_sdc4,
421b5d2f741SDavid Dai 	[SLAVE_SNOC_CFG] = &qhs_snoc_cfg,
422b5d2f741SDavid Dai 	[SLAVE_SPDM_WRAPPER] = &qhs_spdm,
423b5d2f741SDavid Dai 	[SLAVE_SPSS_CFG] = &qhs_spss_cfg,
424b5d2f741SDavid Dai 	[SLAVE_TCSR] = &qhs_tcsr,
425b5d2f741SDavid Dai 	[SLAVE_TLMM_NORTH] = &qhs_tlmm_north,
426b5d2f741SDavid Dai 	[SLAVE_TLMM_SOUTH] = &qhs_tlmm_south,
427b5d2f741SDavid Dai 	[SLAVE_TSIF] = &qhs_tsif,
428b5d2f741SDavid Dai 	[SLAVE_UFS_CARD_CFG] = &qhs_ufs_card_cfg,
429b5d2f741SDavid Dai 	[SLAVE_UFS_MEM_CFG] = &qhs_ufs_mem_cfg,
430b5d2f741SDavid Dai 	[SLAVE_USB3_0] = &qhs_usb3_0,
431b5d2f741SDavid Dai 	[SLAVE_USB3_1] = &qhs_usb3_1,
432b5d2f741SDavid Dai 	[SLAVE_VENUS_CFG] = &qhs_venus_cfg,
433b5d2f741SDavid Dai 	[SLAVE_VSENSE_CTRL_CFG] = &qhs_vsense_ctrl_cfg,
434b5d2f741SDavid Dai 	[SLAVE_MNOC_SF_MEM_NOC] = &qns2_mem_noc,
435b5d2f741SDavid Dai 	[SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc,
436b5d2f741SDavid Dai 	[SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc,
437b5d2f741SDavid Dai 	[SLAVE_MEM_NOC_GNOC] = &qns_apps_io,
438b5d2f741SDavid Dai 	[SLAVE_CAMNOC_UNCOMP] = &qns_camnoc_uncomp,
439b5d2f741SDavid Dai 	[SLAVE_SNOC_CNOC] = &qns_cnoc,
440b5d2f741SDavid Dai 	[SLAVE_CNOC_A2NOC] = &qns_cnoc_a2noc,
441b5d2f741SDavid Dai 	[SLAVE_GNOC_SNOC] = &qns_gladiator_sodv,
442b5d2f741SDavid Dai 	[SLAVE_GNOC_MEM_NOC] = &qns_gnoc_memnoc,
443b5d2f741SDavid Dai 	[SLAVE_LLCC] = &qns_llcc,
444b5d2f741SDavid Dai 	[SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf,
445b5d2f741SDavid Dai 	[SLAVE_SNOC_MEM_NOC_GC] = &qns_memnoc_gc,
446b5d2f741SDavid Dai 	[SLAVE_SNOC_MEM_NOC_SF] = &qns_memnoc_sf,
447b5d2f741SDavid Dai 	[SLAVE_MEM_NOC_SNOC] = &qns_memnoc_snoc,
448b5d2f741SDavid Dai 	[SLAVE_ANOC_PCIE_A1NOC_SNOC] = &qns_pcie_a1noc_snoc,
449b5d2f741SDavid Dai 	[SLAVE_ANOC_PCIE_SNOC] = &qns_pcie_snoc,
450b5d2f741SDavid Dai 	[SLAVE_IMEM] = &qxs_imem,
451b5d2f741SDavid Dai 	[SLAVE_PCIE_0] = &qxs_pcie,
452b5d2f741SDavid Dai 	[SLAVE_PCIE_1] = &qxs_pcie_gen3,
453b5d2f741SDavid Dai 	[SLAVE_PIMEM] = &qxs_pimem,
454b5d2f741SDavid Dai 	[SLAVE_SERVICE_A1NOC] = &srvc_aggre1_noc,
455b5d2f741SDavid Dai 	[SLAVE_SERVICE_A2NOC] = &srvc_aggre2_noc,
456b5d2f741SDavid Dai 	[SLAVE_SERVICE_CNOC] = &srvc_cnoc,
457b5d2f741SDavid Dai 	[SLAVE_SERVICE_GNOC] = &srvc_gnoc,
458b5d2f741SDavid Dai 	[SLAVE_SERVICE_MEM_NOC] = &srvc_memnoc,
459b5d2f741SDavid Dai 	[SLAVE_SERVICE_MNOC] = &srvc_mnoc,
460b5d2f741SDavid Dai 	[SLAVE_SERVICE_SNOC] = &srvc_snoc,
461b5d2f741SDavid Dai 	[SLAVE_QDSS_STM] = &xs_qdss_stm,
462b5d2f741SDavid Dai 	[SLAVE_TCU] = &xs_sys_tcu_cfg,
463b5d2f741SDavid Dai };
464b5d2f741SDavid Dai 
465b5d2f741SDavid Dai static struct qcom_icc_bcm *rsc_hlos_bcms[] = {
466b5d2f741SDavid Dai 	&bcm_acv,
467b5d2f741SDavid Dai 	&bcm_mc0,
468b5d2f741SDavid Dai 	&bcm_sh0,
469b5d2f741SDavid Dai 	&bcm_mm0,
470b5d2f741SDavid Dai 	&bcm_sh1,
471b5d2f741SDavid Dai 	&bcm_mm1,
472b5d2f741SDavid Dai 	&bcm_sh2,
473b5d2f741SDavid Dai 	&bcm_mm2,
474b5d2f741SDavid Dai 	&bcm_sh3,
475b5d2f741SDavid Dai 	&bcm_mm3,
476b5d2f741SDavid Dai 	&bcm_sh5,
477b5d2f741SDavid Dai 	&bcm_sn0,
478b5d2f741SDavid Dai 	&bcm_ce0,
479b5d2f741SDavid Dai 	&bcm_cn0,
480b5d2f741SDavid Dai 	&bcm_qup0,
481b5d2f741SDavid Dai 	&bcm_sn1,
482b5d2f741SDavid Dai 	&bcm_sn2,
483b5d2f741SDavid Dai 	&bcm_sn3,
484b5d2f741SDavid Dai 	&bcm_sn4,
485b5d2f741SDavid Dai 	&bcm_sn5,
486b5d2f741SDavid Dai 	&bcm_sn6,
487b5d2f741SDavid Dai 	&bcm_sn7,
488b5d2f741SDavid Dai 	&bcm_sn8,
489b5d2f741SDavid Dai 	&bcm_sn9,
490b5d2f741SDavid Dai 	&bcm_sn11,
491b5d2f741SDavid Dai 	&bcm_sn12,
492b5d2f741SDavid Dai 	&bcm_sn14,
493b5d2f741SDavid Dai 	&bcm_sn15,
494b5d2f741SDavid Dai };
495b5d2f741SDavid Dai 
496b5d2f741SDavid Dai static struct qcom_icc_desc sdm845_rsc_hlos = {
497b5d2f741SDavid Dai 	.nodes = rsc_hlos_nodes,
498b5d2f741SDavid Dai 	.num_nodes = ARRAY_SIZE(rsc_hlos_nodes),
499b5d2f741SDavid Dai 	.bcms = rsc_hlos_bcms,
500b5d2f741SDavid Dai 	.num_bcms = ARRAY_SIZE(rsc_hlos_bcms),
501b5d2f741SDavid Dai };
502b5d2f741SDavid Dai 
503b5d2f741SDavid Dai static int qcom_icc_bcm_init(struct qcom_icc_bcm *bcm, struct device *dev)
504b5d2f741SDavid Dai {
505b5d2f741SDavid Dai 	struct qcom_icc_node *qn;
506b5d2f741SDavid Dai 	const struct bcm_db *data;
507b5d2f741SDavid Dai 	size_t data_count;
508b5d2f741SDavid Dai 	int i;
509b5d2f741SDavid Dai 
510b5d2f741SDavid Dai 	bcm->addr = cmd_db_read_addr(bcm->name);
511b5d2f741SDavid Dai 	if (!bcm->addr) {
512b5d2f741SDavid Dai 		dev_err(dev, "%s could not find RPMh address\n",
513b5d2f741SDavid Dai 			bcm->name);
514b5d2f741SDavid Dai 		return -EINVAL;
515b5d2f741SDavid Dai 	}
516b5d2f741SDavid Dai 
517b5d2f741SDavid Dai 	data = cmd_db_read_aux_data(bcm->name, &data_count);
518b5d2f741SDavid Dai 	if (IS_ERR(data)) {
519b5d2f741SDavid Dai 		dev_err(dev, "%s command db read error (%ld)\n",
520b5d2f741SDavid Dai 			bcm->name, PTR_ERR(data));
521b5d2f741SDavid Dai 		return PTR_ERR(data);
522b5d2f741SDavid Dai 	}
523b5d2f741SDavid Dai 	if (!data_count) {
524b5d2f741SDavid Dai 		dev_err(dev, "%s command db missing or partial aux data\n",
525b5d2f741SDavid Dai 			bcm->name);
526b5d2f741SDavid Dai 		return -EINVAL;
527b5d2f741SDavid Dai 	}
528b5d2f741SDavid Dai 
529b5d2f741SDavid Dai 	bcm->aux_data.unit = le32_to_cpu(data->unit);
530b5d2f741SDavid Dai 	bcm->aux_data.width = le16_to_cpu(data->width);
531b5d2f741SDavid Dai 	bcm->aux_data.vcd = data->vcd;
532b5d2f741SDavid Dai 	bcm->aux_data.reserved = data->reserved;
533b5d2f741SDavid Dai 
534b5d2f741SDavid Dai 	/*
535b5d2f741SDavid Dai 	 * Link Qnodes to their respective BCMs
536b5d2f741SDavid Dai 	 */
537b5d2f741SDavid Dai 	for (i = 0; i < bcm->num_nodes; i++) {
538b5d2f741SDavid Dai 		qn = bcm->nodes[i];
539b5d2f741SDavid Dai 		qn->bcms[qn->num_bcms] = bcm;
540b5d2f741SDavid Dai 		qn->num_bcms++;
541b5d2f741SDavid Dai 	}
542b5d2f741SDavid Dai 
543b5d2f741SDavid Dai 	return 0;
544b5d2f741SDavid Dai }
545b5d2f741SDavid Dai 
546b5d2f741SDavid Dai inline void tcs_cmd_gen(struct tcs_cmd *cmd, u64 vote_x, u64 vote_y,
547b5d2f741SDavid Dai 			u32 addr, bool commit)
548b5d2f741SDavid Dai {
549b5d2f741SDavid Dai 	bool valid = true;
550b5d2f741SDavid Dai 
551b5d2f741SDavid Dai 	if (!cmd)
552b5d2f741SDavid Dai 		return;
553b5d2f741SDavid Dai 
554b5d2f741SDavid Dai 	if (vote_x == 0 && vote_y == 0)
555b5d2f741SDavid Dai 		valid = false;
556b5d2f741SDavid Dai 
557b5d2f741SDavid Dai 	if (vote_x > BCM_TCS_CMD_VOTE_MASK)
558b5d2f741SDavid Dai 		vote_x = BCM_TCS_CMD_VOTE_MASK;
559b5d2f741SDavid Dai 
560b5d2f741SDavid Dai 	if (vote_y > BCM_TCS_CMD_VOTE_MASK)
561b5d2f741SDavid Dai 		vote_y = BCM_TCS_CMD_VOTE_MASK;
562b5d2f741SDavid Dai 
563b5d2f741SDavid Dai 	cmd->addr = addr;
564b5d2f741SDavid Dai 	cmd->data = BCM_TCS_CMD(commit, valid, vote_x, vote_y);
565b5d2f741SDavid Dai 
566b5d2f741SDavid Dai 	/*
567b5d2f741SDavid Dai 	 * Set the wait for completion flag on command that need to be completed
568b5d2f741SDavid Dai 	 * before the next command.
569b5d2f741SDavid Dai 	 */
570b5d2f741SDavid Dai 	if (commit)
571b5d2f741SDavid Dai 		cmd->wait = true;
572b5d2f741SDavid Dai }
573b5d2f741SDavid Dai 
5749e3ce77cSDavid Dai static void tcs_list_gen(struct list_head *bcm_list, int bucket,
575b5d2f741SDavid Dai 			 struct tcs_cmd tcs_list[SDM845_MAX_VCD],
576b5d2f741SDavid Dai 			 int n[SDM845_MAX_VCD])
577b5d2f741SDavid Dai {
578b5d2f741SDavid Dai 	struct qcom_icc_bcm *bcm;
579b5d2f741SDavid Dai 	bool commit;
580b5d2f741SDavid Dai 	size_t idx = 0, batch = 0, cur_vcd_size = 0;
581b5d2f741SDavid Dai 
582b5d2f741SDavid Dai 	memset(n, 0, sizeof(int) * SDM845_MAX_VCD);
583b5d2f741SDavid Dai 
584b5d2f741SDavid Dai 	list_for_each_entry(bcm, bcm_list, list) {
585b5d2f741SDavid Dai 		commit = false;
586b5d2f741SDavid Dai 		cur_vcd_size++;
587b5d2f741SDavid Dai 		if ((list_is_last(&bcm->list, bcm_list)) ||
588b5d2f741SDavid Dai 		    bcm->aux_data.vcd != list_next_entry(bcm, list)->aux_data.vcd) {
589b5d2f741SDavid Dai 			commit = true;
590b5d2f741SDavid Dai 			cur_vcd_size = 0;
591b5d2f741SDavid Dai 		}
5929e3ce77cSDavid Dai 		tcs_cmd_gen(&tcs_list[idx], bcm->vote_x[bucket],
5939e3ce77cSDavid Dai 			    bcm->vote_y[bucket], bcm->addr, commit);
594b5d2f741SDavid Dai 		idx++;
595b5d2f741SDavid Dai 		n[batch]++;
596b5d2f741SDavid Dai 		/*
597b5d2f741SDavid Dai 		 * Batch the BCMs in such a way that we do not split them in
598b5d2f741SDavid Dai 		 * multiple payloads when they are under the same VCD. This is
599b5d2f741SDavid Dai 		 * to ensure that every BCM is committed since we only set the
600b5d2f741SDavid Dai 		 * commit bit on the last BCM request of every VCD.
601b5d2f741SDavid Dai 		 */
602b5d2f741SDavid Dai 		if (n[batch] >= MAX_RPMH_PAYLOAD) {
603b5d2f741SDavid Dai 			if (!commit) {
604b5d2f741SDavid Dai 				n[batch] -= cur_vcd_size;
605b5d2f741SDavid Dai 				n[batch + 1] = cur_vcd_size;
606b5d2f741SDavid Dai 			}
607b5d2f741SDavid Dai 			batch++;
608b5d2f741SDavid Dai 		}
609b5d2f741SDavid Dai 	}
610b5d2f741SDavid Dai }
611b5d2f741SDavid Dai 
612b5d2f741SDavid Dai static void bcm_aggregate(struct qcom_icc_bcm *bcm)
613b5d2f741SDavid Dai {
6149e3ce77cSDavid Dai 	size_t i, bucket;
6159e3ce77cSDavid Dai 	u64 agg_avg[QCOM_ICC_NUM_BUCKETS] = {0};
6169e3ce77cSDavid Dai 	u64 agg_peak[QCOM_ICC_NUM_BUCKETS] = {0};
617b5d2f741SDavid Dai 	u64 temp;
618b5d2f741SDavid Dai 
6199e3ce77cSDavid Dai 	for (bucket = 0; bucket < QCOM_ICC_NUM_BUCKETS; bucket++) {
620b5d2f741SDavid Dai 		for (i = 0; i < bcm->num_nodes; i++) {
6219e3ce77cSDavid Dai 			temp = bcm->nodes[i]->sum_avg[bucket] * bcm->aux_data.width;
622b5d2f741SDavid Dai 			do_div(temp, bcm->nodes[i]->buswidth * bcm->nodes[i]->channels);
6239e3ce77cSDavid Dai 			agg_avg[bucket] = max(agg_avg[bucket], temp);
624b5d2f741SDavid Dai 
6259e3ce77cSDavid Dai 			temp = bcm->nodes[i]->max_peak[bucket] * bcm->aux_data.width;
626b5d2f741SDavid Dai 			do_div(temp, bcm->nodes[i]->buswidth);
6279e3ce77cSDavid Dai 			agg_peak[bucket] = max(agg_peak[bucket], temp);
628b5d2f741SDavid Dai 		}
629b5d2f741SDavid Dai 
6309e3ce77cSDavid Dai 		temp = agg_avg[bucket] * 1000ULL;
631b5d2f741SDavid Dai 		do_div(temp, bcm->aux_data.unit);
6329e3ce77cSDavid Dai 		bcm->vote_x[bucket] = temp;
633b5d2f741SDavid Dai 
6349e3ce77cSDavid Dai 		temp = agg_peak[bucket] * 1000ULL;
635b5d2f741SDavid Dai 		do_div(temp, bcm->aux_data.unit);
6369e3ce77cSDavid Dai 		bcm->vote_y[bucket] = temp;
6379e3ce77cSDavid Dai 	}
638b5d2f741SDavid Dai 
6399e3ce77cSDavid Dai 	if (bcm->keepalive && bcm->vote_x[QCOM_ICC_BUCKET_AMC] == 0 &&
6409e3ce77cSDavid Dai 	    bcm->vote_y[QCOM_ICC_BUCKET_AMC] == 0) {
6419e3ce77cSDavid Dai 		bcm->vote_x[QCOM_ICC_BUCKET_AMC] = 1;
6429e3ce77cSDavid Dai 		bcm->vote_x[QCOM_ICC_BUCKET_WAKE] = 1;
6439e3ce77cSDavid Dai 		bcm->vote_y[QCOM_ICC_BUCKET_AMC] = 1;
6449e3ce77cSDavid Dai 		bcm->vote_y[QCOM_ICC_BUCKET_WAKE] = 1;
645b5d2f741SDavid Dai 	}
646b5d2f741SDavid Dai 
647b5d2f741SDavid Dai 	bcm->dirty = false;
648b5d2f741SDavid Dai }
649b5d2f741SDavid Dai 
6509e3ce77cSDavid Dai static void qcom_icc_pre_aggregate(struct icc_node *node)
6519e3ce77cSDavid Dai {
6529e3ce77cSDavid Dai 	size_t i;
6539e3ce77cSDavid Dai 	struct qcom_icc_node *qn;
6549e3ce77cSDavid Dai 
6559e3ce77cSDavid Dai 	qn = node->data;
6569e3ce77cSDavid Dai 
6579e3ce77cSDavid Dai 	for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) {
6589e3ce77cSDavid Dai 		qn->sum_avg[i] = 0;
6599e3ce77cSDavid Dai 		qn->max_peak[i] = 0;
6609e3ce77cSDavid Dai 	}
6619e3ce77cSDavid Dai }
6629e3ce77cSDavid Dai 
663127ab2ccSGeorgi Djakov static int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
664b5d2f741SDavid Dai 			      u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
665b5d2f741SDavid Dai {
666b5d2f741SDavid Dai 	size_t i;
667b5d2f741SDavid Dai 	struct qcom_icc_node *qn;
668b5d2f741SDavid Dai 
669b5d2f741SDavid Dai 	qn = node->data;
670b5d2f741SDavid Dai 
6719e3ce77cSDavid Dai 	if (!tag)
6729e3ce77cSDavid Dai 		tag = QCOM_ICC_TAG_ALWAYS;
6739e3ce77cSDavid Dai 
6749e3ce77cSDavid Dai 	for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) {
6759e3ce77cSDavid Dai 		if (tag & BIT(i)) {
6769e3ce77cSDavid Dai 			qn->sum_avg[i] += avg_bw;
6779e3ce77cSDavid Dai 			qn->max_peak[i] = max_t(u32, qn->max_peak[i], peak_bw);
6789e3ce77cSDavid Dai 		}
6799e3ce77cSDavid Dai 	}
6809e3ce77cSDavid Dai 
681b5d2f741SDavid Dai 	*agg_avg += avg_bw;
682b5d2f741SDavid Dai 	*agg_peak = max_t(u32, *agg_peak, peak_bw);
683b5d2f741SDavid Dai 
684b5d2f741SDavid Dai 	for (i = 0; i < qn->num_bcms; i++)
685b5d2f741SDavid Dai 		qn->bcms[i]->dirty = true;
686b5d2f741SDavid Dai 
687b5d2f741SDavid Dai 	return 0;
688b5d2f741SDavid Dai }
689b5d2f741SDavid Dai 
690b5d2f741SDavid Dai static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
691b5d2f741SDavid Dai {
692b5d2f741SDavid Dai 	struct qcom_icc_provider *qp;
693b5d2f741SDavid Dai 	struct icc_node *node;
694b5d2f741SDavid Dai 	struct tcs_cmd cmds[SDM845_MAX_BCMS];
695b5d2f741SDavid Dai 	struct list_head commit_list;
696b5d2f741SDavid Dai 	int commit_idx[SDM845_MAX_VCD];
697b5d2f741SDavid Dai 	int ret = 0, i;
698b5d2f741SDavid Dai 
699b5d2f741SDavid Dai 	if (!src)
700b5d2f741SDavid Dai 		node = dst;
701b5d2f741SDavid Dai 	else
702b5d2f741SDavid Dai 		node = src;
703b5d2f741SDavid Dai 
704b5d2f741SDavid Dai 	qp = to_qcom_provider(node->provider);
705b5d2f741SDavid Dai 
706b5d2f741SDavid Dai 	INIT_LIST_HEAD(&commit_list);
707b5d2f741SDavid Dai 
708b5d2f741SDavid Dai 	for (i = 0; i < qp->num_bcms; i++) {
709b5d2f741SDavid Dai 		if (qp->bcms[i]->dirty) {
710b5d2f741SDavid Dai 			bcm_aggregate(qp->bcms[i]);
711b5d2f741SDavid Dai 			list_add_tail(&qp->bcms[i]->list, &commit_list);
712b5d2f741SDavid Dai 		}
713b5d2f741SDavid Dai 	}
714b5d2f741SDavid Dai 
715b5d2f741SDavid Dai 	/*
716b5d2f741SDavid Dai 	 * Construct the command list based on a pre ordered list of BCMs
717b5d2f741SDavid Dai 	 * based on VCD.
718b5d2f741SDavid Dai 	 */
7199e3ce77cSDavid Dai 	tcs_list_gen(&commit_list, QCOM_ICC_BUCKET_AMC, cmds, commit_idx);
720b5d2f741SDavid Dai 
721b5d2f741SDavid Dai 	if (!commit_idx[0])
722b5d2f741SDavid Dai 		return ret;
723b5d2f741SDavid Dai 
724b5d2f741SDavid Dai 	ret = rpmh_invalidate(qp->dev);
725b5d2f741SDavid Dai 	if (ret) {
726b5d2f741SDavid Dai 		pr_err("Error invalidating RPMH client (%d)\n", ret);
727b5d2f741SDavid Dai 		return ret;
728b5d2f741SDavid Dai 	}
729b5d2f741SDavid Dai 
730b5d2f741SDavid Dai 	ret = rpmh_write_batch(qp->dev, RPMH_ACTIVE_ONLY_STATE,
731b5d2f741SDavid Dai 			       cmds, commit_idx);
732b5d2f741SDavid Dai 	if (ret) {
733b5d2f741SDavid Dai 		pr_err("Error sending AMC RPMH requests (%d)\n", ret);
734b5d2f741SDavid Dai 		return ret;
735b5d2f741SDavid Dai 	}
736b5d2f741SDavid Dai 
7379e3ce77cSDavid Dai 	INIT_LIST_HEAD(&commit_list);
7389e3ce77cSDavid Dai 
7399e3ce77cSDavid Dai 	for (i = 0; i < qp->num_bcms; i++) {
7409e3ce77cSDavid Dai 		/*
7419e3ce77cSDavid Dai 		 * Only generate WAKE and SLEEP commands if a resource's
7429e3ce77cSDavid Dai 		 * requirements change as the execution environment transitions
7439e3ce77cSDavid Dai 		 * between different power states.
7449e3ce77cSDavid Dai 		 */
7459e3ce77cSDavid Dai 		if (qp->bcms[i]->vote_x[QCOM_ICC_BUCKET_WAKE] !=
7469e3ce77cSDavid Dai 		    qp->bcms[i]->vote_x[QCOM_ICC_BUCKET_SLEEP] ||
7479e3ce77cSDavid Dai 		    qp->bcms[i]->vote_y[QCOM_ICC_BUCKET_WAKE] !=
7489e3ce77cSDavid Dai 		    qp->bcms[i]->vote_y[QCOM_ICC_BUCKET_SLEEP]) {
7499e3ce77cSDavid Dai 			list_add_tail(&qp->bcms[i]->list, &commit_list);
7509e3ce77cSDavid Dai 		}
7519e3ce77cSDavid Dai 	}
7529e3ce77cSDavid Dai 
7539e3ce77cSDavid Dai 	if (list_empty(&commit_list))
7549e3ce77cSDavid Dai 		return ret;
7559e3ce77cSDavid Dai 
7569e3ce77cSDavid Dai 	tcs_list_gen(&commit_list, QCOM_ICC_BUCKET_WAKE, cmds, commit_idx);
7579e3ce77cSDavid Dai 
7589e3ce77cSDavid Dai 	ret = rpmh_write_batch(qp->dev, RPMH_WAKE_ONLY_STATE, cmds, commit_idx);
7599e3ce77cSDavid Dai 	if (ret) {
7609e3ce77cSDavid Dai 		pr_err("Error sending WAKE RPMH requests (%d)\n", ret);
7619e3ce77cSDavid Dai 		return ret;
7629e3ce77cSDavid Dai 	}
7639e3ce77cSDavid Dai 
7649e3ce77cSDavid Dai 	tcs_list_gen(&commit_list, QCOM_ICC_BUCKET_SLEEP, cmds, commit_idx);
7659e3ce77cSDavid Dai 
7669e3ce77cSDavid Dai 	ret = rpmh_write_batch(qp->dev, RPMH_SLEEP_STATE, cmds, commit_idx);
7679e3ce77cSDavid Dai 	if (ret) {
7689e3ce77cSDavid Dai 		pr_err("Error sending SLEEP RPMH requests (%d)\n", ret);
7699e3ce77cSDavid Dai 		return ret;
7709e3ce77cSDavid Dai 	}
7719e3ce77cSDavid Dai 
772b5d2f741SDavid Dai 	return ret;
773b5d2f741SDavid Dai }
774b5d2f741SDavid Dai 
775b5d2f741SDavid Dai static int cmp_vcd(const void *_l, const void *_r)
776b5d2f741SDavid Dai {
777b5d2f741SDavid Dai 	const struct qcom_icc_bcm **l = (const struct qcom_icc_bcm **)_l;
778b5d2f741SDavid Dai 	const struct qcom_icc_bcm **r = (const struct qcom_icc_bcm **)_r;
779b5d2f741SDavid Dai 
780b5d2f741SDavid Dai 	if (l[0]->aux_data.vcd < r[0]->aux_data.vcd)
781b5d2f741SDavid Dai 		return -1;
782b5d2f741SDavid Dai 	else if (l[0]->aux_data.vcd == r[0]->aux_data.vcd)
783b5d2f741SDavid Dai 		return 0;
784b5d2f741SDavid Dai 	else
785b5d2f741SDavid Dai 		return 1;
786b5d2f741SDavid Dai }
787b5d2f741SDavid Dai 
788b5d2f741SDavid Dai static int qnoc_probe(struct platform_device *pdev)
789b5d2f741SDavid Dai {
790b5d2f741SDavid Dai 	const struct qcom_icc_desc *desc;
791b5d2f741SDavid Dai 	struct icc_onecell_data *data;
792b5d2f741SDavid Dai 	struct icc_provider *provider;
793b5d2f741SDavid Dai 	struct qcom_icc_node **qnodes;
794b5d2f741SDavid Dai 	struct qcom_icc_provider *qp;
795b5d2f741SDavid Dai 	struct icc_node *node;
796b5d2f741SDavid Dai 	size_t num_nodes, i;
797b5d2f741SDavid Dai 	int ret;
798b5d2f741SDavid Dai 
799b5d2f741SDavid Dai 	desc = of_device_get_match_data(&pdev->dev);
800b5d2f741SDavid Dai 	if (!desc)
801b5d2f741SDavid Dai 		return -EINVAL;
802b5d2f741SDavid Dai 
803b5d2f741SDavid Dai 	qnodes = desc->nodes;
804b5d2f741SDavid Dai 	num_nodes = desc->num_nodes;
805b5d2f741SDavid Dai 
806b5d2f741SDavid Dai 	qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL);
807b5d2f741SDavid Dai 	if (!qp)
808b5d2f741SDavid Dai 		return -ENOMEM;
809b5d2f741SDavid Dai 
810b5d2f741SDavid Dai 	data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
811b5d2f741SDavid Dai 	if (!data)
812b5d2f741SDavid Dai 		return -ENOMEM;
813b5d2f741SDavid Dai 
814b5d2f741SDavid Dai 	provider = &qp->provider;
815b5d2f741SDavid Dai 	provider->dev = &pdev->dev;
816b5d2f741SDavid Dai 	provider->set = qcom_icc_set;
8179e3ce77cSDavid Dai 	provider->pre_aggregate = qcom_icc_pre_aggregate;
818b5d2f741SDavid Dai 	provider->aggregate = qcom_icc_aggregate;
819b5d2f741SDavid Dai 	provider->xlate = of_icc_xlate_onecell;
820b5d2f741SDavid Dai 	INIT_LIST_HEAD(&provider->nodes);
821b5d2f741SDavid Dai 	provider->data = data;
822b5d2f741SDavid Dai 
823b5d2f741SDavid Dai 	qp->dev = &pdev->dev;
824b5d2f741SDavid Dai 	qp->bcms = desc->bcms;
825b5d2f741SDavid Dai 	qp->num_bcms = desc->num_bcms;
826b5d2f741SDavid Dai 
827b5d2f741SDavid Dai 	ret = icc_provider_add(provider);
828b5d2f741SDavid Dai 	if (ret) {
829b5d2f741SDavid Dai 		dev_err(&pdev->dev, "error adding interconnect provider\n");
830b5d2f741SDavid Dai 		return ret;
831b5d2f741SDavid Dai 	}
832b5d2f741SDavid Dai 
833b5d2f741SDavid Dai 	for (i = 0; i < num_nodes; i++) {
834b5d2f741SDavid Dai 		size_t j;
835b5d2f741SDavid Dai 
836b5d2f741SDavid Dai 		node = icc_node_create(qnodes[i]->id);
837b5d2f741SDavid Dai 		if (IS_ERR(node)) {
838b5d2f741SDavid Dai 			ret = PTR_ERR(node);
839b5d2f741SDavid Dai 			goto err;
840b5d2f741SDavid Dai 		}
841b5d2f741SDavid Dai 
842b5d2f741SDavid Dai 		node->name = qnodes[i]->name;
843b5d2f741SDavid Dai 		node->data = qnodes[i];
844b5d2f741SDavid Dai 		icc_node_add(node, provider);
845b5d2f741SDavid Dai 
846b5d2f741SDavid Dai 		dev_dbg(&pdev->dev, "registered node %p %s %d\n", node,
847b5d2f741SDavid Dai 			qnodes[i]->name, node->id);
848b5d2f741SDavid Dai 
849b5d2f741SDavid Dai 		/* populate links */
850b5d2f741SDavid Dai 		for (j = 0; j < qnodes[i]->num_links; j++)
851b5d2f741SDavid Dai 			icc_link_create(node, qnodes[i]->links[j]);
852b5d2f741SDavid Dai 
853b5d2f741SDavid Dai 		data->nodes[i] = node;
854b5d2f741SDavid Dai 	}
855b5d2f741SDavid Dai 	data->num_nodes = num_nodes;
856b5d2f741SDavid Dai 
857b5d2f741SDavid Dai 	for (i = 0; i < qp->num_bcms; i++)
858b5d2f741SDavid Dai 		qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
859b5d2f741SDavid Dai 
860b5d2f741SDavid Dai 	/*
861b5d2f741SDavid Dai 	 * Pre sort the BCMs based on VCD for ease of generating a command list
862b5d2f741SDavid Dai 	 * that groups the BCMs with the same VCD together. VCDs are numbered
863b5d2f741SDavid Dai 	 * with lowest being the most expensive time wise, ensuring that
864b5d2f741SDavid Dai 	 * those commands are being sent the earliest in the queue.
865b5d2f741SDavid Dai 	 */
866b5d2f741SDavid Dai 	sort(qp->bcms, qp->num_bcms, sizeof(*qp->bcms), cmp_vcd, NULL);
867b5d2f741SDavid Dai 
868b5d2f741SDavid Dai 	platform_set_drvdata(pdev, qp);
869b5d2f741SDavid Dai 
870b5d2f741SDavid Dai 	dev_dbg(&pdev->dev, "Registered SDM845 ICC\n");
871b5d2f741SDavid Dai 
872b5d2f741SDavid Dai 	return ret;
873b5d2f741SDavid Dai err:
874b5d2f741SDavid Dai 	list_for_each_entry(node, &provider->nodes, node_list) {
875b5d2f741SDavid Dai 		icc_node_del(node);
876b5d2f741SDavid Dai 		icc_node_destroy(node->id);
877b5d2f741SDavid Dai 	}
878b5d2f741SDavid Dai 
879b5d2f741SDavid Dai 	icc_provider_del(provider);
880b5d2f741SDavid Dai 	return ret;
881b5d2f741SDavid Dai }
882b5d2f741SDavid Dai 
883b5d2f741SDavid Dai static int qnoc_remove(struct platform_device *pdev)
884b5d2f741SDavid Dai {
885b5d2f741SDavid Dai 	struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
886b5d2f741SDavid Dai 	struct icc_provider *provider = &qp->provider;
887b5d2f741SDavid Dai 	struct icc_node *n;
888b5d2f741SDavid Dai 
889b5d2f741SDavid Dai 	list_for_each_entry(n, &provider->nodes, node_list) {
890b5d2f741SDavid Dai 		icc_node_del(n);
891b5d2f741SDavid Dai 		icc_node_destroy(n->id);
892b5d2f741SDavid Dai 	}
893b5d2f741SDavid Dai 
894b5d2f741SDavid Dai 	return icc_provider_del(provider);
895b5d2f741SDavid Dai }
896b5d2f741SDavid Dai 
897b5d2f741SDavid Dai static const struct of_device_id qnoc_of_match[] = {
898b5d2f741SDavid Dai 	{ .compatible = "qcom,sdm845-rsc-hlos", .data = &sdm845_rsc_hlos },
899b5d2f741SDavid Dai 	{ },
900b5d2f741SDavid Dai };
901b5d2f741SDavid Dai MODULE_DEVICE_TABLE(of, qnoc_of_match);
902b5d2f741SDavid Dai 
903b5d2f741SDavid Dai static struct platform_driver qnoc_driver = {
904b5d2f741SDavid Dai 	.probe = qnoc_probe,
905b5d2f741SDavid Dai 	.remove = qnoc_remove,
906b5d2f741SDavid Dai 	.driver = {
907b5d2f741SDavid Dai 		.name = "qnoc-sdm845",
908b5d2f741SDavid Dai 		.of_match_table = qnoc_of_match,
909b5d2f741SDavid Dai 	},
910b5d2f741SDavid Dai };
911b5d2f741SDavid Dai module_platform_driver(qnoc_driver);
912b5d2f741SDavid Dai 
913b5d2f741SDavid Dai MODULE_AUTHOR("David Dai <daidavid1@codeaurora.org>");
914b5d2f741SDavid Dai MODULE_DESCRIPTION("Qualcomm sdm845 NoC driver");
915b5d2f741SDavid Dai MODULE_LICENSE("GPL v2");
916