difos/target/linux/imx/patches-6.6/600-PCI-imx6-Start-link-at-max-gen-first-for-IMX8MM-and-IMX8MP.patch
Tim Harvey a8feb51e71 kernel/imx: Restore kernel files for v6.6
This is an automatically generated commit which aids following Kernel patch
history, as git will see the move and copy as a rename thus defeating the
purpose.

For the original discussion see:
https://lists.openwrt.org/pipermail/openwrt-devel/2023-October/041673.html

Signed-off-by: Tim Harvey <tharvey@gateworks.com>
Link: https://github.com/openwrt/openwrt/pull/19029
Signed-off-by: Nick Hainke <vincent@systemli.org>
2025-06-07 08:38:06 +02:00

121 lines
4 KiB
Diff

From cf983e4a04eecb5be93af7b53cb10805ee448998 Mon Sep 17 00:00:00 2001
From: Tim Harvey <tharvey@gateworks.com>
Date: Mon, 21 Aug 2023 09:20:17 -0700
Subject: [PATCH] PCI: imx6: Start link at max gen first for IMX8MM and IMX8MP
commit fa33a6d87eac ("PCI: imx6: Start link in Gen1 before negotiating
for Gen2 mode") started link negotiation at Gen1 before attempting
faster speeds in order to work around an issue with a particular switch
on an IMX6Q SoC.
This behavior is not the norm for PCI link negotiation and it has been
found to cause issues in other cases:
- IMX8MM with PI7C9X2G608GP switch: various endpoints (such as qca988x)
will fail to link more than 50% of the time
- IMX8MP with PI7C9X2G608GP switch: occasionally will fail to link with
switch and cause a CPU hang about 30% of the time
Disable this behavior for IMX8MM and IMX8MP.
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
drivers/pci/controller/dwc/pci-imx6.c | 53 ++++++++++++++-------------
1 file changed, 27 insertions(+), 26 deletions(-)
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -60,6 +60,7 @@ enum imx6_pcie_variants {
#define IMX6_PCIE_FLAG_IMX6_PHY BIT(0)
#define IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE BIT(1)
#define IMX6_PCIE_FLAG_SUPPORTS_SUSPEND BIT(2)
+#define IMX6_PCIE_FLAG_GEN1_LAST BIT(3)
#define IMX6_PCIE_MAX_CLKS 6
@@ -836,26 +837,28 @@ static int imx6_pcie_start_link(struct d
u32 tmp;
int ret;
- /*
- * Force Gen1 operation when starting the link. In case the link is
- * started in Gen2 mode, there is a possibility the devices on the
- * bus will not be detected at all. This happens with PCIe switches.
- */
- dw_pcie_dbi_ro_wr_en(pci);
- tmp = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP);
- tmp &= ~PCI_EXP_LNKCAP_SLS;
- tmp |= PCI_EXP_LNKCAP_SLS_2_5GB;
- dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCAP, tmp);
- dw_pcie_dbi_ro_wr_dis(pci);
+ if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_GEN1_LAST)) {
+ /*
+ * Force Gen1 operation when starting the link. In case the link is
+ * started in Gen2 mode, there is a possibility the devices on the
+ * bus will not be detected at all. This happens with PCIe switches.
+ */
+ dw_pcie_dbi_ro_wr_en(pci);
+ tmp = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP);
+ tmp &= ~PCI_EXP_LNKCAP_SLS;
+ tmp |= PCI_EXP_LNKCAP_SLS_2_5GB;
+ dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCAP, tmp);
+ dw_pcie_dbi_ro_wr_dis(pci);
+ }
/* Start LTSSM. */
imx6_pcie_ltssm_enable(dev);
- ret = dw_pcie_wait_for_link(pci);
- if (ret)
- goto err_reset_phy;
+ if ((pci->link_gen > 1) && !(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_GEN1_LAST)) {
+ ret = dw_pcie_wait_for_link(pci);
+ if (ret)
+ goto err_reset_phy;
- if (pci->link_gen > 1) {
/* Allow faster modes after the link is up */
dw_pcie_dbi_ro_wr_en(pci);
tmp = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP);
@@ -889,18 +892,14 @@ static int imx6_pcie_start_link(struct d
goto err_reset_phy;
}
}
-
- /* Make sure link training is finished as well! */
- ret = dw_pcie_wait_for_link(pci);
- if (ret)
- goto err_reset_phy;
- } else {
- dev_info(dev, "Link: Only Gen1 is enabled\n");
}
+ ret = dw_pcie_wait_for_link(pci);
+ if (ret)
+ goto err_reset_phy;
+
imx6_pcie->link_is_up = true;
- tmp = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
- dev_info(dev, "Link up, Gen%i\n", tmp & PCI_EXP_LNKSTA_CLS);
+
return 0;
err_reset_phy:
@@ -1457,14 +1456,16 @@ static const struct imx6_pcie_drvdata dr
},
[IMX8MM] = {
.variant = IMX8MM,
- .flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,
+ .flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND |
+ IMX6_PCIE_FLAG_GEN1_LAST,
.gpr = "fsl,imx8mm-iomuxc-gpr",
.clk_names = imx8mm_clks,
.clks_cnt = ARRAY_SIZE(imx8mm_clks),
},
[IMX8MP] = {
.variant = IMX8MP,
- .flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,
+ .flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND |
+ IMX6_PCIE_FLAG_GEN1_LAST,
.gpr = "fsl,imx8mp-iomuxc-gpr",
.clk_names = imx8mm_clks,
.clks_cnt = ARRAY_SIZE(imx8mm_clks),