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>
133134#define CORE_RESET_TIME_US_MAX 1005
134135#define WAKE_DELAY_US 2000 /* 2 ms */
135136
137+ #define PCIE_GEN1_BW_MBPS 250
138+ #define PCIE_GEN2_BW_MBPS 500
139+ #define PCIE_GEN3_BW_MBPS 985
140+ #define PCIE_GEN4_BW_MBPS 1969
141+
136142#define to_pcie_ep (x ) dev_get_drvdata((x)->dev)
137143
138144enum qcom_pcie_ep_link_status {
@@ -155,6 +161,7 @@ enum qcom_pcie_ep_link_status {
155161 * @wake: WAKE# GPIO
156162 * @phy: PHY controller block
157163 * @debugfs: PCIe Endpoint Debugfs directory
164+ * @icc_mem: Handle to an interconnect path between PCIe and MEM
158165 * @clks: PCIe clocks
159166 * @num_clks: PCIe clocks count
160167 * @perst_en: Flag for PERST enable
@@ -178,6 +185,8 @@ struct qcom_pcie_ep {
178185 struct phy * phy ;
179186 struct dentry * debugfs ;
180187
188+ struct icc_path * icc_mem ;
189+
181190 struct clk_bulk_data * clks ;
182191 int num_clks ;
183192
@@ -253,8 +262,49 @@ static void qcom_pcie_dw_stop_link(struct dw_pcie *pci)
253262 disable_irq (pcie_ep -> perst_irq );
254263}
255264
265+ static void qcom_pcie_ep_icc_update (struct qcom_pcie_ep * pcie_ep )
266+ {
267+ struct dw_pcie * pci = & pcie_ep -> pci ;
268+ u32 offset , status , bw ;
269+ int speed , width ;
270+ int ret ;
271+
272+ if (!pcie_ep -> icc_mem )
273+ return ;
274+
275+ offset = dw_pcie_find_capability (pci , PCI_CAP_ID_EXP );
276+ status = readw (pci -> dbi_base + offset + PCI_EXP_LNKSTA );
277+
278+ speed = FIELD_GET (PCI_EXP_LNKSTA_CLS , status );
279+ width = FIELD_GET (PCI_EXP_LNKSTA_NLW , status );
280+
281+ switch (speed ) {
282+ case 1 :
283+ bw = MBps_to_icc (PCIE_GEN1_BW_MBPS );
284+ break ;
285+ case 2 :
286+ bw = MBps_to_icc (PCIE_GEN2_BW_MBPS );
287+ break ;
288+ case 3 :
289+ bw = MBps_to_icc (PCIE_GEN3_BW_MBPS );
290+ break ;
291+ default :
292+ dev_warn (pci -> dev , "using default GEN4 bandwidth\n" );
293+ fallthrough ;
294+ case 4 :
295+ bw = MBps_to_icc (PCIE_GEN4_BW_MBPS );
296+ break ;
297+ }
298+
299+ ret = icc_set_bw (pcie_ep -> icc_mem , 0 , width * bw );
300+ if (ret )
301+ dev_err (pci -> dev , "failed to set interconnect bandwidth: %d\n" ,
302+ ret );
303+ }
304+
256305static int qcom_pcie_enable_resources (struct qcom_pcie_ep * pcie_ep )
257306{
307+ struct dw_pcie * pci = & pcie_ep -> pci ;
258308 int ret ;
259309
260310 ret = clk_bulk_prepare_enable (pcie_ep -> num_clks , pcie_ep -> clks );
@@ -277,8 +327,24 @@ static int qcom_pcie_enable_resources(struct qcom_pcie_ep *pcie_ep)
277327 if (ret )
278328 goto err_phy_exit ;
279329
330+ /*
331+ * Some Qualcomm platforms require interconnect bandwidth constraints
332+ * to be set before enabling interconnect clocks.
333+ *
334+ * Set an initial peak bandwidth corresponding to single-lane Gen 1
335+ * for the pcie-mem path.
336+ */
337+ ret = icc_set_bw (pcie_ep -> icc_mem , 0 , MBps_to_icc (PCIE_GEN1_BW_MBPS ));
338+ if (ret ) {
339+ dev_err (pci -> dev , "failed to set interconnect bandwidth: %d\n" ,
340+ ret );
341+ goto err_phy_off ;
342+ }
343+
280344 return 0 ;
281345
346+ err_phy_off :
347+ phy_power_off (pcie_ep -> phy );
282348err_phy_exit :
283349 phy_exit (pcie_ep -> phy );
284350err_disable_clk :
@@ -289,6 +355,7 @@ static int qcom_pcie_enable_resources(struct qcom_pcie_ep *pcie_ep)
289355
290356static void qcom_pcie_disable_resources (struct qcom_pcie_ep * pcie_ep )
291357{
358+ icc_set_bw (pcie_ep -> icc_mem , 0 , 0 );
292359 phy_power_off (pcie_ep -> phy );
293360 phy_exit (pcie_ep -> phy );
294361 clk_bulk_disable_unprepare (pcie_ep -> num_clks , pcie_ep -> clks );
@@ -550,6 +617,10 @@ static int qcom_pcie_ep_get_resources(struct platform_device *pdev,
550617 if (IS_ERR (pcie_ep -> phy ))
551618 ret = PTR_ERR (pcie_ep -> phy );
552619
620+ pcie_ep -> icc_mem = devm_of_icc_get (dev , "pcie-mem" );
621+ if (IS_ERR (pcie_ep -> icc_mem ))
622+ ret = PTR_ERR (pcie_ep -> icc_mem );
623+
553624 return ret ;
554625}
555626
@@ -573,6 +644,7 @@ static irqreturn_t qcom_pcie_ep_global_irq_thread(int irq, void *data)
573644 } else if (FIELD_GET (PARF_INT_ALL_BME , status )) {
574645 dev_dbg (dev , "Received BME event. Link is enabled!\n" );
575646 pcie_ep -> link_status = QCOM_PCIE_EP_LINK_ENABLED ;
647+ qcom_pcie_ep_icc_update (pcie_ep );
576648 pci_epc_bme_notify (pci -> ep .epc );
577649 } else if (FIELD_GET (PARF_INT_ALL_PM_TURNOFF , status )) {
578650 dev_dbg (dev , "Received PM Turn-off event! Entering L23\n" );
0 commit comments