]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
PCI: dwc: Skip waiting for L2/L3 Ready if dw_pcie_rp::skip_l23_wait is true
authorRichard Zhu <hongxing.zhu@nxp.com>
Wed, 14 Jan 2026 08:33:00 +0000 (16:33 +0800)
committerManivannan Sadhasivam <mani@kernel.org>
Wed, 21 Jan 2026 09:37:39 +0000 (15:07 +0530)
In NXP i.MX6QP and i.MX7D SoCs, LTSSM registers are not accessible once
PME_Turn_Off message is broadcasted to the link. So there is no way to
verify whether the link has entered L2/L3 Ready state or not.

Hence, add a new flag 'dw_pcie_rp::skip_l23_ready' and set it to 'true' for
the above mentioned SoCs. This flag when set, will allow the DWC core to
skip polling for L2/L3 Ready state and just wait for 10ms as recommended in
the PCIe spec r6.0, sec 5.3.3.2.1.

Fixes: a528d1a72597 ("PCI: imx6: Use DWC common suspend resume method")
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
[mani: renamed flag to skip_l23_ready and reworded description]
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260114083300.3689672-2-hongxing.zhu@nxp.com
drivers/pci/controller/dwc/pci-imx6.c
drivers/pci/controller/dwc/pcie-designware-host.c
drivers/pci/controller/dwc/pcie-designware.h

index 4668fc9648bff637c779e2f4d5f182671348258c..dfe814469993134b2f6de5fa2586e4e8ff84ebff 100644 (file)
@@ -114,6 +114,7 @@ enum imx_pcie_variants {
 #define IMX_PCIE_FLAG_BROKEN_SUSPEND           BIT(9)
 #define IMX_PCIE_FLAG_HAS_LUT                  BIT(10)
 #define IMX_PCIE_FLAG_8GT_ECN_ERR051586                BIT(11)
+#define IMX_PCIE_FLAG_SKIP_L23_READY           BIT(12)
 
 #define imx_check_flag(pci, val)       (pci->drvdata->flags & val)
 
@@ -1777,6 +1778,8 @@ static int imx_pcie_probe(struct platform_device *pdev)
                 */
                imx_pcie_add_lut_by_rid(imx_pcie, 0);
        } else {
+               if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_SKIP_L23_READY))
+                       pci->pp.skip_l23_ready = true;
                pci->pp.use_atu_msg = true;
                ret = dw_pcie_host_init(&pci->pp);
                if (ret < 0)
@@ -1838,6 +1841,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
                .variant = IMX6QP,
                .flags = IMX_PCIE_FLAG_IMX_PHY |
                         IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND |
+                        IMX_PCIE_FLAG_SKIP_L23_READY |
                         IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
                .dbi_length = 0x200,
                .gpr = "fsl,imx6q-iomuxc-gpr",
@@ -1854,6 +1858,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
                .variant = IMX7D,
                .flags = IMX_PCIE_FLAG_SUPPORTS_SUSPEND |
                         IMX_PCIE_FLAG_HAS_APP_RESET |
+                        IMX_PCIE_FLAG_SKIP_L23_READY |
                         IMX_PCIE_FLAG_HAS_PHY_RESET,
                .gpr = "fsl,imx7d-iomuxc-gpr",
                .mode_off[0] = IOMUXC_GPR12,
index a72406ef7e26e029054edba5a8559497541c19e5..a17833dd6f9d4b4aa06dc1fe09ffed5e2c28a82f 100644 (file)
@@ -1199,6 +1199,16 @@ int dw_pcie_suspend_noirq(struct dw_pcie *pci)
                        return ret;
        }
 
+       /*
+        * Some SoCs do not support reading the LTSSM register after
+        * PME_Turn_Off broadcast. For those SoCs, skip waiting for L2/L3 Ready
+        * state and wait 10ms as recommended in PCIe spec r6.0, sec 5.3.3.2.1.
+        */
+       if (pci->pp.skip_l23_ready) {
+               mdelay(PCIE_PME_TO_L2_TIMEOUT_US/1000);
+               goto stop_link;
+       }
+
        ret = read_poll_timeout(dw_pcie_get_ltssm, val,
                                val == DW_PCIE_LTSSM_L2_IDLE ||
                                val <= DW_PCIE_LTSSM_DETECT_WAIT,
index c1def4d9cf62cda5a7b35d94ffed5700d489250f..ec4b7a689f59168dd92772e86c3ac92f501fcbff 100644 (file)
@@ -442,6 +442,7 @@ struct dw_pcie_rp {
        struct pci_config_window *cfg;
        bool                    ecam_enabled;
        bool                    native_ecam;
+       bool                    skip_l23_ready;
 };
 
 struct dw_pcie_ep_ops {