1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2019 Linaro Ltd
6 #include <dt-bindings/interconnect/qcom,qcs404.h>
8 #include <linux/device.h>
9 #include <linux/interconnect-provider.h>
11 #include <linux/module.h>
12 #include <linux/of_device.h>
13 #include <linux/of_platform.h>
14 #include <linux/platform_device.h>
15 #include <linux/slab.h>
19 #define RPM_BUS_MASTER_REQ 0x73616d62
20 #define RPM_BUS_SLAVE_REQ 0x766c7362
23 QCS404_MASTER_AMPSS_M0
= 1,
24 QCS404_MASTER_GRAPHICS_3D
,
25 QCS404_MASTER_MDP_PORT0
,
26 QCS404_SNOC_BIMC_1_MAS
,
31 QCS404_MASTER_XM_USB_HS1
,
32 QCS404_MASTER_CRYPTO_CORE0
,
37 QCS404_MASTER_QDSS_BAM
,
40 QCS404_MASTER_QDSS_ETR
,
64 QCS404_SLAVE_SPDM_WRAPPER
,
68 QCS404_SLAVE_SNOC_CFG
,
69 QCS404_SLAVE_MESSAGE_RAM
,
70 QCS404_SLAVE_DISPLAY_CFG
,
71 QCS404_SLAVE_GRAPHICS_3D_CFG
,
73 QCS404_SLAVE_TLMM_NORTH
,
75 QCS404_SLAVE_EMAC_CFG
,
77 QCS404_SLAVE_TLMM_EAST
,
79 QCS404_SLAVE_PMIC_ARB
,
82 QCS404_SLAVE_TLMM_SOUTH
,
85 QCS404_SLAVE_CRYPTO_0_CFG
,
89 QCS404_SNOC_BIMC_1_SLV
,
92 QCS404_SLAVE_QDSS_STM
,
93 QCS404_SLAVE_CATS_128
,
94 QCS404_SLAVE_OCMEM_64
,
98 #define to_qcom_provider(_provider) \
99 container_of(_provider, struct qcom_icc_provider, provider)
101 static const struct clk_bulk_data bus_clocks
[] = {
107 * struct qcom_icc_provider - Qualcomm specific interconnect provider
108 * @provider: generic interconnect provider
109 * @bus_clks: the clk_bulk_data table of bus clocks
110 * @num_clks: the total number of clk_bulk_data entries
112 struct qcom_icc_provider
{
113 struct icc_provider provider
;
114 struct clk_bulk_data
*bus_clks
;
118 #define QCS404_MAX_LINKS 12
121 * struct qcom_icc_node - Qualcomm specific interconnect nodes
122 * @name: the node name used in debugfs
123 * @id: a unique node identifier
124 * @links: an array of nodes where we can go next while traversing
125 * @num_links: the total number of @links
126 * @buswidth: width of the interconnect between a node and the bus (bytes)
127 * @mas_rpm_id: RPM id for devices that are bus masters
128 * @slv_rpm_id: RPM id for devices that are bus slaves
129 * @rate: current bus clock rate in Hz
131 struct qcom_icc_node
{
134 u16 links
[QCS404_MAX_LINKS
];
142 struct qcom_icc_desc
{
143 struct qcom_icc_node
**nodes
;
147 #define DEFINE_QNODE(_name, _id, _buswidth, _mas_rpm_id, _slv_rpm_id, \
149 static struct qcom_icc_node _name = { \
152 .buswidth = _buswidth, \
153 .mas_rpm_id = _mas_rpm_id, \
154 .slv_rpm_id = _slv_rpm_id, \
155 .num_links = ARRAY_SIZE(((int[]){ __VA_ARGS__ })), \
156 .links = { __VA_ARGS__ }, \
159 DEFINE_QNODE(mas_apps_proc
, QCS404_MASTER_AMPSS_M0
, 8, 0, -1, QCS404_SLAVE_EBI_CH0
, QCS404_BIMC_SNOC_SLV
);
160 DEFINE_QNODE(mas_oxili
, QCS404_MASTER_GRAPHICS_3D
, 8, 6, -1, QCS404_SLAVE_EBI_CH0
, QCS404_BIMC_SNOC_SLV
);
161 DEFINE_QNODE(mas_mdp
, QCS404_MASTER_MDP_PORT0
, 8, 8, -1, QCS404_SLAVE_EBI_CH0
, QCS404_BIMC_SNOC_SLV
);
162 DEFINE_QNODE(mas_snoc_bimc_1
, QCS404_SNOC_BIMC_1_MAS
, 8, 76, -1, QCS404_SLAVE_EBI_CH0
);
163 DEFINE_QNODE(mas_tcu_0
, QCS404_MASTER_TCU_0
, 8, -1, -1, QCS404_SLAVE_EBI_CH0
, QCS404_BIMC_SNOC_SLV
);
164 DEFINE_QNODE(mas_spdm
, QCS404_MASTER_SPDM
, 4, -1, -1, QCS404_PNOC_INT_3
);
165 DEFINE_QNODE(mas_blsp_1
, QCS404_MASTER_BLSP_1
, 4, 41, -1, QCS404_PNOC_INT_3
);
166 DEFINE_QNODE(mas_blsp_2
, QCS404_MASTER_BLSP_2
, 4, 39, -1, QCS404_PNOC_INT_3
);
167 DEFINE_QNODE(mas_xi_usb_hs1
, QCS404_MASTER_XM_USB_HS1
, 8, 138, -1, QCS404_PNOC_INT_0
);
168 DEFINE_QNODE(mas_crypto
, QCS404_MASTER_CRYPTO_CORE0
, 8, 23, -1, QCS404_PNOC_SNOC_SLV
, QCS404_PNOC_INT_2
);
169 DEFINE_QNODE(mas_sdcc_1
, QCS404_MASTER_SDCC_1
, 8, 33, -1, QCS404_PNOC_INT_0
);
170 DEFINE_QNODE(mas_sdcc_2
, QCS404_MASTER_SDCC_2
, 8, 35, -1, QCS404_PNOC_INT_0
);
171 DEFINE_QNODE(mas_snoc_pcnoc
, QCS404_SNOC_PNOC_MAS
, 8, 77, -1, QCS404_PNOC_INT_2
);
172 DEFINE_QNODE(mas_qpic
, QCS404_MASTER_QPIC
, 4, -1, -1, QCS404_PNOC_INT_0
);
173 DEFINE_QNODE(mas_qdss_bam
, QCS404_MASTER_QDSS_BAM
, 4, -1, -1, QCS404_SNOC_QDSS_INT
);
174 DEFINE_QNODE(mas_bimc_snoc
, QCS404_BIMC_SNOC_MAS
, 8, 21, -1, QCS404_SLAVE_OCMEM_64
, QCS404_SLAVE_CATS_128
, QCS404_SNOC_INT_0
, QCS404_SNOC_INT_1
);
175 DEFINE_QNODE(mas_pcnoc_snoc
, QCS404_PNOC_SNOC_MAS
, 8, 29, -1, QCS404_SNOC_BIMC_1_SLV
, QCS404_SNOC_INT_2
, QCS404_SNOC_INT_0
);
176 DEFINE_QNODE(mas_qdss_etr
, QCS404_MASTER_QDSS_ETR
, 8, -1, -1, QCS404_SNOC_QDSS_INT
);
177 DEFINE_QNODE(mas_emac
, QCS404_MASTER_EMAC
, 8, -1, -1, QCS404_SNOC_BIMC_1_SLV
, QCS404_SNOC_INT_1
);
178 DEFINE_QNODE(mas_pcie
, QCS404_MASTER_PCIE
, 8, -1, -1, QCS404_SNOC_BIMC_1_SLV
, QCS404_SNOC_INT_1
);
179 DEFINE_QNODE(mas_usb3
, QCS404_MASTER_USB3
, 8, -1, -1, QCS404_SNOC_BIMC_1_SLV
, QCS404_SNOC_INT_1
);
180 DEFINE_QNODE(pcnoc_int_0
, QCS404_PNOC_INT_0
, 8, 85, 114, QCS404_PNOC_SNOC_SLV
, QCS404_PNOC_INT_2
);
181 DEFINE_QNODE(pcnoc_int_2
, QCS404_PNOC_INT_2
, 8, 124, 184, QCS404_PNOC_SLV_10
, QCS404_SLAVE_TCU
, QCS404_PNOC_SLV_11
, QCS404_PNOC_SLV_2
, QCS404_PNOC_SLV_3
, QCS404_PNOC_SLV_0
, QCS404_PNOC_SLV_1
, QCS404_PNOC_SLV_6
, QCS404_PNOC_SLV_7
, QCS404_PNOC_SLV_4
, QCS404_PNOC_SLV_8
, QCS404_PNOC_SLV_9
);
182 DEFINE_QNODE(pcnoc_int_3
, QCS404_PNOC_INT_3
, 8, 125, 185, QCS404_PNOC_SNOC_SLV
);
183 DEFINE_QNODE(pcnoc_s_0
, QCS404_PNOC_SLV_0
, 4, 89, 118, QCS404_SLAVE_PRNG
, QCS404_SLAVE_SPDM_WRAPPER
, QCS404_SLAVE_PDM
);
184 DEFINE_QNODE(pcnoc_s_1
, QCS404_PNOC_SLV_1
, 4, 90, 119, QCS404_SLAVE_TCSR
);
185 DEFINE_QNODE(pcnoc_s_2
, QCS404_PNOC_SLV_2
, 4, -1, -1, QCS404_SLAVE_GRAPHICS_3D_CFG
);
186 DEFINE_QNODE(pcnoc_s_3
, QCS404_PNOC_SLV_3
, 4, 92, 121, QCS404_SLAVE_MESSAGE_RAM
);
187 DEFINE_QNODE(pcnoc_s_4
, QCS404_PNOC_SLV_4
, 4, 93, 122, QCS404_SLAVE_SNOC_CFG
);
188 DEFINE_QNODE(pcnoc_s_6
, QCS404_PNOC_SLV_6
, 4, 94, 123, QCS404_SLAVE_BLSP_1
, QCS404_SLAVE_TLMM_NORTH
, QCS404_SLAVE_EMAC_CFG
);
189 DEFINE_QNODE(pcnoc_s_7
, QCS404_PNOC_SLV_7
, 4, 95, 124, QCS404_SLAVE_TLMM_SOUTH
, QCS404_SLAVE_DISPLAY_CFG
, QCS404_SLAVE_SDCC_1
, QCS404_SLAVE_PCIE_1
, QCS404_SLAVE_SDCC_2
);
190 DEFINE_QNODE(pcnoc_s_8
, QCS404_PNOC_SLV_8
, 4, 96, 125, QCS404_SLAVE_CRYPTO_0_CFG
);
191 DEFINE_QNODE(pcnoc_s_9
, QCS404_PNOC_SLV_9
, 4, 97, 126, QCS404_SLAVE_BLSP_2
, QCS404_SLAVE_TLMM_EAST
, QCS404_SLAVE_PMIC_ARB
);
192 DEFINE_QNODE(pcnoc_s_10
, QCS404_PNOC_SLV_10
, 4, 157, -1, QCS404_SLAVE_USB_HS
);
193 DEFINE_QNODE(pcnoc_s_11
, QCS404_PNOC_SLV_11
, 4, 158, 246, QCS404_SLAVE_USB3
);
194 DEFINE_QNODE(qdss_int
, QCS404_SNOC_QDSS_INT
, 8, -1, -1, QCS404_SNOC_BIMC_1_SLV
, QCS404_SNOC_INT_1
);
195 DEFINE_QNODE(snoc_int_0
, QCS404_SNOC_INT_0
, 8, 99, 130, QCS404_SLAVE_LPASS
, QCS404_SLAVE_APPSS
, QCS404_SLAVE_WCSS
);
196 DEFINE_QNODE(snoc_int_1
, QCS404_SNOC_INT_1
, 8, 100, 131, QCS404_SNOC_PNOC_SLV
, QCS404_SNOC_INT_2
);
197 DEFINE_QNODE(snoc_int_2
, QCS404_SNOC_INT_2
, 8, 134, 197, QCS404_SLAVE_QDSS_STM
, QCS404_SLAVE_OCIMEM
);
198 DEFINE_QNODE(slv_ebi
, QCS404_SLAVE_EBI_CH0
, 8, -1, 0, 0);
199 DEFINE_QNODE(slv_bimc_snoc
, QCS404_BIMC_SNOC_SLV
, 8, -1, 2, QCS404_BIMC_SNOC_MAS
);
200 DEFINE_QNODE(slv_spdm
, QCS404_SLAVE_SPDM_WRAPPER
, 4, -1, -1, 0);
201 DEFINE_QNODE(slv_pdm
, QCS404_SLAVE_PDM
, 4, -1, 41, 0);
202 DEFINE_QNODE(slv_prng
, QCS404_SLAVE_PRNG
, 4, -1, 44, 0);
203 DEFINE_QNODE(slv_tcsr
, QCS404_SLAVE_TCSR
, 4, -1, 50, 0);
204 DEFINE_QNODE(slv_snoc_cfg
, QCS404_SLAVE_SNOC_CFG
, 4, -1, 70, 0);
205 DEFINE_QNODE(slv_message_ram
, QCS404_SLAVE_MESSAGE_RAM
, 4, -1, 55, 0);
206 DEFINE_QNODE(slv_disp_ss_cfg
, QCS404_SLAVE_DISPLAY_CFG
, 4, -1, -1, 0);
207 DEFINE_QNODE(slv_gpu_cfg
, QCS404_SLAVE_GRAPHICS_3D_CFG
, 4, -1, -1, 0);
208 DEFINE_QNODE(slv_blsp_1
, QCS404_SLAVE_BLSP_1
, 4, -1, 39, 0);
209 DEFINE_QNODE(slv_tlmm_north
, QCS404_SLAVE_TLMM_NORTH
, 4, -1, 214, 0);
210 DEFINE_QNODE(slv_pcie
, QCS404_SLAVE_PCIE_1
, 4, -1, -1, 0);
211 DEFINE_QNODE(slv_ethernet
, QCS404_SLAVE_EMAC_CFG
, 4, -1, -1, 0);
212 DEFINE_QNODE(slv_blsp_2
, QCS404_SLAVE_BLSP_2
, 4, -1, 37, 0);
213 DEFINE_QNODE(slv_tlmm_east
, QCS404_SLAVE_TLMM_EAST
, 4, -1, 213, 0);
214 DEFINE_QNODE(slv_tcu
, QCS404_SLAVE_TCU
, 8, -1, -1, 0);
215 DEFINE_QNODE(slv_pmic_arb
, QCS404_SLAVE_PMIC_ARB
, 4, -1, 59, 0);
216 DEFINE_QNODE(slv_sdcc_1
, QCS404_SLAVE_SDCC_1
, 4, -1, 31, 0);
217 DEFINE_QNODE(slv_sdcc_2
, QCS404_SLAVE_SDCC_2
, 4, -1, 33, 0);
218 DEFINE_QNODE(slv_tlmm_south
, QCS404_SLAVE_TLMM_SOUTH
, 4, -1, -1, 0);
219 DEFINE_QNODE(slv_usb_hs
, QCS404_SLAVE_USB_HS
, 4, -1, 40, 0);
220 DEFINE_QNODE(slv_usb3
, QCS404_SLAVE_USB3
, 4, -1, 22, 0);
221 DEFINE_QNODE(slv_crypto_0_cfg
, QCS404_SLAVE_CRYPTO_0_CFG
, 4, -1, 52, 0);
222 DEFINE_QNODE(slv_pcnoc_snoc
, QCS404_PNOC_SNOC_SLV
, 8, -1, 45, QCS404_PNOC_SNOC_MAS
);
223 DEFINE_QNODE(slv_kpss_ahb
, QCS404_SLAVE_APPSS
, 4, -1, -1, 0);
224 DEFINE_QNODE(slv_wcss
, QCS404_SLAVE_WCSS
, 4, -1, 23, 0);
225 DEFINE_QNODE(slv_snoc_bimc_1
, QCS404_SNOC_BIMC_1_SLV
, 8, -1, 104, QCS404_SNOC_BIMC_1_MAS
);
226 DEFINE_QNODE(slv_imem
, QCS404_SLAVE_OCIMEM
, 8, -1, 26, 0);
227 DEFINE_QNODE(slv_snoc_pcnoc
, QCS404_SNOC_PNOC_SLV
, 8, -1, 28, QCS404_SNOC_PNOC_MAS
);
228 DEFINE_QNODE(slv_qdss_stm
, QCS404_SLAVE_QDSS_STM
, 4, -1, 30, 0);
229 DEFINE_QNODE(slv_cats_0
, QCS404_SLAVE_CATS_128
, 16, -1, -1, 0);
230 DEFINE_QNODE(slv_cats_1
, QCS404_SLAVE_OCMEM_64
, 8, -1, -1, 0);
231 DEFINE_QNODE(slv_lpass
, QCS404_SLAVE_LPASS
, 4, -1, -1, 0);
233 static struct qcom_icc_node
*qcs404_bimc_nodes
[] = {
234 [MASTER_AMPSS_M0
] = &mas_apps_proc
,
235 [MASTER_OXILI
] = &mas_oxili
,
236 [MASTER_MDP_PORT0
] = &mas_mdp
,
237 [MASTER_SNOC_BIMC_1
] = &mas_snoc_bimc_1
,
238 [MASTER_TCU_0
] = &mas_tcu_0
,
239 [SLAVE_EBI_CH0
] = &slv_ebi
,
240 [SLAVE_BIMC_SNOC
] = &slv_bimc_snoc
,
243 static struct qcom_icc_desc qcs404_bimc
= {
244 .nodes
= qcs404_bimc_nodes
,
245 .num_nodes
= ARRAY_SIZE(qcs404_bimc_nodes
),
248 static struct qcom_icc_node
*qcs404_pcnoc_nodes
[] = {
249 [MASTER_SPDM
] = &mas_spdm
,
250 [MASTER_BLSP_1
] = &mas_blsp_1
,
251 [MASTER_BLSP_2
] = &mas_blsp_2
,
252 [MASTER_XI_USB_HS1
] = &mas_xi_usb_hs1
,
253 [MASTER_CRYPT0
] = &mas_crypto
,
254 [MASTER_SDCC_1
] = &mas_sdcc_1
,
255 [MASTER_SDCC_2
] = &mas_sdcc_2
,
256 [MASTER_SNOC_PCNOC
] = &mas_snoc_pcnoc
,
257 [MASTER_QPIC
] = &mas_qpic
,
258 [PCNOC_INT_0
] = &pcnoc_int_0
,
259 [PCNOC_INT_2
] = &pcnoc_int_2
,
260 [PCNOC_INT_3
] = &pcnoc_int_3
,
261 [PCNOC_S_0
] = &pcnoc_s_0
,
262 [PCNOC_S_1
] = &pcnoc_s_1
,
263 [PCNOC_S_2
] = &pcnoc_s_2
,
264 [PCNOC_S_3
] = &pcnoc_s_3
,
265 [PCNOC_S_4
] = &pcnoc_s_4
,
266 [PCNOC_S_6
] = &pcnoc_s_6
,
267 [PCNOC_S_7
] = &pcnoc_s_7
,
268 [PCNOC_S_8
] = &pcnoc_s_8
,
269 [PCNOC_S_9
] = &pcnoc_s_9
,
270 [PCNOC_S_10
] = &pcnoc_s_10
,
271 [PCNOC_S_11
] = &pcnoc_s_11
,
272 [SLAVE_SPDM
] = &slv_spdm
,
273 [SLAVE_PDM
] = &slv_pdm
,
274 [SLAVE_PRNG
] = &slv_prng
,
275 [SLAVE_TCSR
] = &slv_tcsr
,
276 [SLAVE_SNOC_CFG
] = &slv_snoc_cfg
,
277 [SLAVE_MESSAGE_RAM
] = &slv_message_ram
,
278 [SLAVE_DISP_SS_CFG
] = &slv_disp_ss_cfg
,
279 [SLAVE_GPU_CFG
] = &slv_gpu_cfg
,
280 [SLAVE_BLSP_1
] = &slv_blsp_1
,
281 [SLAVE_BLSP_2
] = &slv_blsp_2
,
282 [SLAVE_TLMM_NORTH
] = &slv_tlmm_north
,
283 [SLAVE_PCIE
] = &slv_pcie
,
284 [SLAVE_ETHERNET
] = &slv_ethernet
,
285 [SLAVE_TLMM_EAST
] = &slv_tlmm_east
,
286 [SLAVE_TCU
] = &slv_tcu
,
287 [SLAVE_PMIC_ARB
] = &slv_pmic_arb
,
288 [SLAVE_SDCC_1
] = &slv_sdcc_1
,
289 [SLAVE_SDCC_2
] = &slv_sdcc_2
,
290 [SLAVE_TLMM_SOUTH
] = &slv_tlmm_south
,
291 [SLAVE_USB_HS
] = &slv_usb_hs
,
292 [SLAVE_USB3
] = &slv_usb3
,
293 [SLAVE_CRYPTO_0_CFG
] = &slv_crypto_0_cfg
,
294 [SLAVE_PCNOC_SNOC
] = &slv_pcnoc_snoc
,
297 static struct qcom_icc_desc qcs404_pcnoc
= {
298 .nodes
= qcs404_pcnoc_nodes
,
299 .num_nodes
= ARRAY_SIZE(qcs404_pcnoc_nodes
),
302 static struct qcom_icc_node
*qcs404_snoc_nodes
[] = {
303 [MASTER_QDSS_BAM
] = &mas_qdss_bam
,
304 [MASTER_BIMC_SNOC
] = &mas_bimc_snoc
,
305 [MASTER_PCNOC_SNOC
] = &mas_pcnoc_snoc
,
306 [MASTER_QDSS_ETR
] = &mas_qdss_etr
,
307 [MASTER_EMAC
] = &mas_emac
,
308 [MASTER_PCIE
] = &mas_pcie
,
309 [MASTER_USB3
] = &mas_usb3
,
310 [QDSS_INT
] = &qdss_int
,
311 [SNOC_INT_0
] = &snoc_int_0
,
312 [SNOC_INT_1
] = &snoc_int_1
,
313 [SNOC_INT_2
] = &snoc_int_2
,
314 [SLAVE_KPSS_AHB
] = &slv_kpss_ahb
,
315 [SLAVE_WCSS
] = &slv_wcss
,
316 [SLAVE_SNOC_BIMC_1
] = &slv_snoc_bimc_1
,
317 [SLAVE_IMEM
] = &slv_imem
,
318 [SLAVE_SNOC_PCNOC
] = &slv_snoc_pcnoc
,
319 [SLAVE_QDSS_STM
] = &slv_qdss_stm
,
320 [SLAVE_CATS_0
] = &slv_cats_0
,
321 [SLAVE_CATS_1
] = &slv_cats_1
,
322 [SLAVE_LPASS
] = &slv_lpass
,
325 static struct qcom_icc_desc qcs404_snoc
= {
326 .nodes
= qcs404_snoc_nodes
,
327 .num_nodes
= ARRAY_SIZE(qcs404_snoc_nodes
),
330 static int qcom_icc_set(struct icc_node
*src
, struct icc_node
*dst
)
332 struct qcom_icc_provider
*qp
;
333 struct qcom_icc_node
*qn
;
334 struct icc_provider
*provider
;
344 provider
= src
->provider
;
345 qp
= to_qcom_provider(provider
);
347 list_for_each_entry(n
, &provider
->nodes
, node_list
)
348 provider
->aggregate(n
, 0, n
->avg_bw
, n
->peak_bw
,
349 &agg_avg
, &agg_peak
);
351 sum_bw
= icc_units_to_bps(agg_avg
);
352 max_peak_bw
= icc_units_to_bps(agg_peak
);
354 /* send bandwidth request message to the RPM processor */
355 if (qn
->mas_rpm_id
!= -1) {
356 ret
= qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE
,
361 pr_err("qcom_icc_rpm_smd_send mas %d error %d\n",
362 qn
->mas_rpm_id
, ret
);
367 if (qn
->slv_rpm_id
!= -1) {
368 ret
= qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE
,
373 pr_err("qcom_icc_rpm_smd_send slv error %d\n",
379 rate
= max(sum_bw
, max_peak_bw
);
381 do_div(rate
, qn
->buswidth
);
383 if (qn
->rate
== rate
)
386 for (i
= 0; i
< qp
->num_clks
; i
++) {
387 ret
= clk_set_rate(qp
->bus_clks
[i
].clk
, rate
);
389 pr_err("%s clk_set_rate error: %d\n",
390 qp
->bus_clks
[i
].id
, ret
);
400 static int qnoc_probe(struct platform_device
*pdev
)
402 struct device
*dev
= &pdev
->dev
;
403 const struct qcom_icc_desc
*desc
;
404 struct icc_onecell_data
*data
;
405 struct icc_provider
*provider
;
406 struct qcom_icc_node
**qnodes
;
407 struct qcom_icc_provider
*qp
;
408 struct icc_node
*node
;
412 /* wait for the RPM proxy */
413 if (!qcom_icc_rpm_smd_available())
414 return -EPROBE_DEFER
;
416 desc
= of_device_get_match_data(dev
);
420 qnodes
= desc
->nodes
;
421 num_nodes
= desc
->num_nodes
;
423 qp
= devm_kzalloc(dev
, sizeof(*qp
), GFP_KERNEL
);
427 data
= devm_kzalloc(dev
, struct_size(data
, nodes
, num_nodes
),
432 qp
->bus_clks
= devm_kmemdup(dev
, bus_clocks
, sizeof(bus_clocks
),
437 qp
->num_clks
= ARRAY_SIZE(bus_clocks
);
438 ret
= devm_clk_bulk_get(dev
, qp
->num_clks
, qp
->bus_clks
);
442 ret
= clk_bulk_prepare_enable(qp
->num_clks
, qp
->bus_clks
);
446 provider
= &qp
->provider
;
447 INIT_LIST_HEAD(&provider
->nodes
);
449 provider
->set
= qcom_icc_set
;
450 provider
->aggregate
= icc_std_aggregate
;
451 provider
->xlate
= of_icc_xlate_onecell
;
452 provider
->data
= data
;
454 ret
= icc_provider_add(provider
);
456 dev_err(dev
, "error adding interconnect provider: %d\n", ret
);
457 clk_bulk_disable_unprepare(qp
->num_clks
, qp
->bus_clks
);
461 for (i
= 0; i
< num_nodes
; i
++) {
464 node
= icc_node_create(qnodes
[i
]->id
);
470 node
->name
= qnodes
[i
]->name
;
471 node
->data
= qnodes
[i
];
472 icc_node_add(node
, provider
);
474 dev_dbg(dev
, "registered node %s\n", node
->name
);
477 for (j
= 0; j
< qnodes
[i
]->num_links
; j
++)
478 icc_link_create(node
, qnodes
[i
]->links
[j
]);
480 data
->nodes
[i
] = node
;
482 data
->num_nodes
= num_nodes
;
484 platform_set_drvdata(pdev
, qp
);
488 icc_nodes_remove(provider
);
489 clk_bulk_disable_unprepare(qp
->num_clks
, qp
->bus_clks
);
490 icc_provider_del(provider
);
495 static int qnoc_remove(struct platform_device
*pdev
)
497 struct qcom_icc_provider
*qp
= platform_get_drvdata(pdev
);
499 icc_nodes_remove(&qp
->provider
);
500 clk_bulk_disable_unprepare(qp
->num_clks
, qp
->bus_clks
);
501 return icc_provider_del(&qp
->provider
);
504 static const struct of_device_id qcs404_noc_of_match
[] = {
505 { .compatible
= "qcom,qcs404-bimc", .data
= &qcs404_bimc
},
506 { .compatible
= "qcom,qcs404-pcnoc", .data
= &qcs404_pcnoc
},
507 { .compatible
= "qcom,qcs404-snoc", .data
= &qcs404_snoc
},
510 MODULE_DEVICE_TABLE(of
, qcs404_noc_of_match
);
512 static struct platform_driver qcs404_noc_driver
= {
514 .remove
= qnoc_remove
,
516 .name
= "qnoc-qcs404",
517 .of_match_table
= qcs404_noc_of_match
,
520 module_platform_driver(qcs404_noc_driver
);
521 MODULE_DESCRIPTION("Qualcomm QCS404 NoC driver");
522 MODULE_LICENSE("GPL v2");