1313#include <linux/debugfs.h>
1414#include <linux/delay.h>
1515#include <linux/gpio/consumer.h>
16+ #include <linux/interconnect.h>
1617#include <linux/mfd/syscon.h>
1718#include <linux/phy/pcie.h>
1819#include <linux/phy/phy.h>
134135#define CORE_RESET_TIME_US_MAX 1005
135136#define WAKE_DELAY_US 2000 /* 2 ms */
136137
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+
137143#define to_pcie_ep (x ) dev_get_drvdata((x)->dev)
138144
139145enum qcom_pcie_ep_link_status {
@@ -156,6 +162,7 @@ enum qcom_pcie_ep_link_status {
156162 * @wake: WAKE# GPIO
157163 * @phy: PHY controller block
158164 * @debugfs: PCIe Endpoint Debugfs directory
165+ * @icc_mem: Handle to an interconnect path between PCIe and MEM
159166 * @clks: PCIe clocks
160167 * @num_clks: PCIe clocks count
161168 * @perst_en: Flag for PERST enable
@@ -179,6 +186,8 @@ struct qcom_pcie_ep {
179186 struct phy * phy ;
180187 struct dentry * debugfs ;
181188
189+ struct icc_path * icc_mem ;
190+
182191 struct clk_bulk_data * clks ;
183192 int num_clks ;
184193
@@ -254,8 +263,49 @@ static void qcom_pcie_dw_stop_link(struct dw_pcie *pci)
254263 disable_irq (pcie_ep -> perst_irq );
255264}
256265
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+
257306static int qcom_pcie_enable_resources (struct qcom_pcie_ep * pcie_ep )
258307{
308+ struct dw_pcie * pci = & pcie_ep -> pci ;
259309 int ret ;
260310
261311 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)
278328 if (ret )
279329 goto err_phy_exit ;
280330
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+
281345 return 0 ;
282346
347+ err_phy_off :
348+ phy_power_off (pcie_ep -> phy );
283349err_phy_exit :
284350 phy_exit (pcie_ep -> phy );
285351err_disable_clk :
@@ -290,6 +356,7 @@ static int qcom_pcie_enable_resources(struct qcom_pcie_ep *pcie_ep)
290356
291357static void qcom_pcie_disable_resources (struct qcom_pcie_ep * pcie_ep )
292358{
359+ icc_set_bw (pcie_ep -> icc_mem , 0 , 0 );
293360 phy_power_off (pcie_ep -> phy );
294361 phy_exit (pcie_ep -> phy );
295362 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,
551618 if (IS_ERR (pcie_ep -> phy ))
552619 ret = PTR_ERR (pcie_ep -> phy );
553620
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+
554625 return ret ;
555626}
556627
@@ -574,6 +645,7 @@ static irqreturn_t qcom_pcie_ep_global_irq_thread(int irq, void *data)
574645 } else if (FIELD_GET (PARF_INT_ALL_BME , status )) {
575646 dev_dbg (dev , "Received BME event. Link is enabled!\n" );
576647 pcie_ep -> link_status = QCOM_PCIE_EP_LINK_ENABLED ;
648+ qcom_pcie_ep_icc_update (pcie_ep );
577649 pci_epc_bme_notify (pci -> ep .epc );
578650 } else if (FIELD_GET (PARF_INT_ALL_PM_TURNOFF , status )) {
579651 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)
594666 dw_pcie_ep_linkup (& pci -> ep );
595667 pcie_ep -> link_status = QCOM_PCIE_EP_LINK_UP ;
596668 } else {
597- dev_dbg (dev , "Received unknown event: %d\n" , status );
669+ dev_err (dev , "Received unknown event: %d\n" , status );
598670 }
599671
600672 return IRQ_HANDLED ;
0 commit comments