diff --git a/target/linux/imx/patches-6.6/600-PCI-imx6-Start-link-at-max-gen-first-for-IMX8MM-and-IMX8MP.patch b/target/linux/imx/patches-6.6/600-PCI-imx6-Start-link-at-max-gen-first-for-IMX8MM-and-IMX8MP.patch new file mode 100644 index 00000000000..002c2044622 --- /dev/null +++ b/target/linux/imx/patches-6.6/600-PCI-imx6-Start-link-at-max-gen-first-for-IMX8MM-and-IMX8MP.patch @@ -0,0 +1,119 @@ +From cf983e4a04eecb5be93af7b53cb10805ee448998 Mon Sep 17 00:00:00 2001 +From: Tim Harvey +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 +--- + 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) + + struct imx6_pcie_drvdata { + enum imx6_pcie_variants variant; +@@ -876,26 +877,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); +@@ -929,18 +932,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: +@@ -1505,12 +1504,14 @@ 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", + }, + [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", + }, + [IMX8MQ_EP] = {