13
13
#include <linux/debugfs.h>
14
14
#include <linux/delay.h>
15
15
#include <linux/gpio/consumer.h>
16
+ #include <linux/interconnect.h>
16
17
#include <linux/mfd/syscon.h>
17
18
#include <linux/phy/pcie.h>
18
19
#include <linux/phy/phy.h>
134
135
#define CORE_RESET_TIME_US_MAX 1005
135
136
#define WAKE_DELAY_US 2000 /* 2 ms */
136
137
138
+ #define PCIE_GEN1_BW_MBPS 250
139
+ #define PCIE_GEN2_BW_MBPS 500
140
+ #define PCIE_GEN3_BW_MBPS 985
141
+ #define PCIE_GEN4_BW_MBPS 1969
142
+
137
143
#define to_pcie_ep (x ) dev_get_drvdata((x)->dev)
138
144
139
145
enum qcom_pcie_ep_link_status {
@@ -156,6 +162,7 @@ enum qcom_pcie_ep_link_status {
156
162
* @wake: WAKE# GPIO
157
163
* @phy: PHY controller block
158
164
* @debugfs: PCIe Endpoint Debugfs directory
165
+ * @icc_mem: Handle to an interconnect path between PCIe and MEM
159
166
* @clks: PCIe clocks
160
167
* @num_clks: PCIe clocks count
161
168
* @perst_en: Flag for PERST enable
@@ -179,6 +186,8 @@ struct qcom_pcie_ep {
179
186
struct phy * phy ;
180
187
struct dentry * debugfs ;
181
188
189
+ struct icc_path * icc_mem ;
190
+
182
191
struct clk_bulk_data * clks ;
183
192
int num_clks ;
184
193
@@ -254,8 +263,49 @@ static void qcom_pcie_dw_stop_link(struct dw_pcie *pci)
254
263
disable_irq (pcie_ep -> perst_irq );
255
264
}
256
265
266
+ static void qcom_pcie_ep_icc_update (struct qcom_pcie_ep * pcie_ep )
267
+ {
268
+ struct dw_pcie * pci = & pcie_ep -> pci ;
269
+ u32 offset , status , bw ;
270
+ int speed , width ;
271
+ int ret ;
272
+
273
+ if (!pcie_ep -> icc_mem )
274
+ return ;
275
+
276
+ offset = dw_pcie_find_capability (pci , PCI_CAP_ID_EXP );
277
+ status = readw (pci -> dbi_base + offset + PCI_EXP_LNKSTA );
278
+
279
+ speed = FIELD_GET (PCI_EXP_LNKSTA_CLS , status );
280
+ width = FIELD_GET (PCI_EXP_LNKSTA_NLW , status );
281
+
282
+ switch (speed ) {
283
+ case 1 :
284
+ bw = MBps_to_icc (PCIE_GEN1_BW_MBPS );
285
+ break ;
286
+ case 2 :
287
+ bw = MBps_to_icc (PCIE_GEN2_BW_MBPS );
288
+ break ;
289
+ case 3 :
290
+ bw = MBps_to_icc (PCIE_GEN3_BW_MBPS );
291
+ break ;
292
+ default :
293
+ dev_warn (pci -> dev , "using default GEN4 bandwidth\n" );
294
+ fallthrough ;
295
+ case 4 :
296
+ bw = MBps_to_icc (PCIE_GEN4_BW_MBPS );
297
+ break ;
298
+ }
299
+
300
+ ret = icc_set_bw (pcie_ep -> icc_mem , 0 , width * bw );
301
+ if (ret )
302
+ dev_err (pci -> dev , "failed to set interconnect bandwidth: %d\n" ,
303
+ ret );
304
+ }
305
+
257
306
static int qcom_pcie_enable_resources (struct qcom_pcie_ep * pcie_ep )
258
307
{
308
+ struct dw_pcie * pci = & pcie_ep -> pci ;
259
309
int ret ;
260
310
261
311
ret = clk_bulk_prepare_enable (pcie_ep -> num_clks , pcie_ep -> clks );
@@ -278,8 +328,24 @@ static int qcom_pcie_enable_resources(struct qcom_pcie_ep *pcie_ep)
278
328
if (ret )
279
329
goto err_phy_exit ;
280
330
331
+ /*
332
+ * Some Qualcomm platforms require interconnect bandwidth constraints
333
+ * to be set before enabling interconnect clocks.
334
+ *
335
+ * Set an initial peak bandwidth corresponding to single-lane Gen 1
336
+ * for the pcie-mem path.
337
+ */
338
+ ret = icc_set_bw (pcie_ep -> icc_mem , 0 , MBps_to_icc (PCIE_GEN1_BW_MBPS ));
339
+ if (ret ) {
340
+ dev_err (pci -> dev , "failed to set interconnect bandwidth: %d\n" ,
341
+ ret );
342
+ goto err_phy_off ;
343
+ }
344
+
281
345
return 0 ;
282
346
347
+ err_phy_off :
348
+ phy_power_off (pcie_ep -> phy );
283
349
err_phy_exit :
284
350
phy_exit (pcie_ep -> phy );
285
351
err_disable_clk :
@@ -290,6 +356,7 @@ static int qcom_pcie_enable_resources(struct qcom_pcie_ep *pcie_ep)
290
356
291
357
static void qcom_pcie_disable_resources (struct qcom_pcie_ep * pcie_ep )
292
358
{
359
+ icc_set_bw (pcie_ep -> icc_mem , 0 , 0 );
293
360
phy_power_off (pcie_ep -> phy );
294
361
phy_exit (pcie_ep -> phy );
295
362
clk_bulk_disable_unprepare (pcie_ep -> num_clks , pcie_ep -> clks );
@@ -551,6 +618,10 @@ static int qcom_pcie_ep_get_resources(struct platform_device *pdev,
551
618
if (IS_ERR (pcie_ep -> phy ))
552
619
ret = PTR_ERR (pcie_ep -> phy );
553
620
621
+ pcie_ep -> icc_mem = devm_of_icc_get (dev , "pcie-mem" );
622
+ if (IS_ERR (pcie_ep -> icc_mem ))
623
+ ret = PTR_ERR (pcie_ep -> icc_mem );
624
+
554
625
return ret ;
555
626
}
556
627
@@ -574,6 +645,7 @@ static irqreturn_t qcom_pcie_ep_global_irq_thread(int irq, void *data)
574
645
} else if (FIELD_GET (PARF_INT_ALL_BME , status )) {
575
646
dev_dbg (dev , "Received BME event. Link is enabled!\n" );
576
647
pcie_ep -> link_status = QCOM_PCIE_EP_LINK_ENABLED ;
648
+ qcom_pcie_ep_icc_update (pcie_ep );
577
649
pci_epc_bme_notify (pci -> ep .epc );
578
650
} else if (FIELD_GET (PARF_INT_ALL_PM_TURNOFF , status )) {
579
651
dev_dbg (dev , "Received PM Turn-off event! Entering L23\n" );
@@ -594,7 +666,7 @@ static irqreturn_t qcom_pcie_ep_global_irq_thread(int irq, void *data)
594
666
dw_pcie_ep_linkup (& pci -> ep );
595
667
pcie_ep -> link_status = QCOM_PCIE_EP_LINK_UP ;
596
668
} else {
597
- dev_dbg (dev , "Received unknown event: %d\n" , status );
669
+ dev_err (dev , "Received unknown event: %d\n" , status );
598
670
}
599
671
600
672
return IRQ_HANDLED ;
0 commit comments