diff options
author | Richard Zhu <hongxing.zhu@nxp.com> | 2020-01-06 15:54:12 +0800 |
---|---|---|
committer | Richard Zhu <hongxing.zhu@nxp.com> | 2020-02-05 17:34:18 +0800 |
commit | 14290b00bc3fba5086151e7e3f1d25972e1ce578 (patch) | |
tree | 7c0ff87a86a1d0b8511e7c562b36ff7e3889bda0 /drivers/pci/controller/dwc/pci-imx6.c | |
parent | 00de7142f86d053b325aa5e6fd49df9ce2f0428e (diff) |
LF-290 PCI: imx: add the pcie pm workaround for imx6qdl
Add the PCIe PM workaround for iMX6QDL.
------
L2 can exit by 'reset' or inband beacon (from remote EP)
toggling phy_powerdown has same effect as 'inband beacon'
So, toggle bit18 of GPR1, used as a workaround of errata
ERR005723 "PCIe PCIe does not support L2 Power Down"
WARNING: This is not official workaround for ERR005723.
Fortunately, we don't encounter issue with this workaround.
User should take own risk to use it.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
Diffstat (limited to 'drivers/pci/controller/dwc/pci-imx6.c')
-rw-r--r-- | drivers/pci/controller/dwc/pci-imx6.c | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index a4ab38398449..9742fa780efe 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -1952,9 +1952,21 @@ static int imx6_pcie_suspend_noirq(struct device *dev) if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_SUPPORTS_SUSPEND)) return 0; - imx6_pcie_pm_turnoff(imx6_pcie); - imx6_pcie_ltssm_disable(dev); - imx6_pcie_clk_disable(imx6_pcie); + if (unlikely(imx6_pcie->drvdata->variant == IMX6Q)) { + /* + * L2 can exit by 'reset' or Inband beacon (from remote EP) + * toggling phy_powerdown has same effect as 'inband beacon' + * So, toggle bit18 of GPR1, used as a workaround of errata + * ERR005723 "PCIe PCIe does not support L2 Power Down" + */ + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, + IMX6Q_GPR1_PCIE_TEST_PD, + IMX6Q_GPR1_PCIE_TEST_PD); + } else { + imx6_pcie_pm_turnoff(imx6_pcie); + imx6_pcie_ltssm_disable(dev); + imx6_pcie_clk_disable(imx6_pcie); + } return 0; } @@ -1967,16 +1979,26 @@ static int imx6_pcie_resume_noirq(struct device *dev) if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_SUPPORTS_SUSPEND)) return 0; + if (unlikely(imx6_pcie->drvdata->variant == IMX6Q)) { + /* + * L2 can exit by 'reset' or Inband beacon (from remote EP) + * toggling phy_powerdown has same effect as 'inband beacon' + * So, toggle bit18 of GPR1, used as a workaround of errata + * ERR005723 "PCIe PCIe does not support L2 Power Down" + */ + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, + IMX6Q_GPR1_PCIE_TEST_PD, 0); + } else { + imx6_pcie_assert_core_reset(imx6_pcie); + imx6_pcie_init_phy(imx6_pcie); + imx6_pcie_deassert_core_reset(imx6_pcie); + dw_pcie_setup_rc(pp); + pci_imx_set_msi_en(pp); - imx6_pcie_assert_core_reset(imx6_pcie); - imx6_pcie_init_phy(imx6_pcie); - imx6_pcie_deassert_core_reset(imx6_pcie); - dw_pcie_setup_rc(pp); - pci_imx_set_msi_en(pp); - - ret = imx6_pcie_establish_link(imx6_pcie); - if (ret < 0) - dev_info(dev, "pcie link is down after resume.\n"); + ret = imx6_pcie_establish_link(imx6_pcie); + if (ret < 0) + dev_info(dev, "pcie link is down after resume.\n"); + } return 0; } @@ -2539,6 +2561,7 @@ static const struct imx6_pcie_drvdata drvdata[] = { [IMX6Q] = { .variant = IMX6Q, .flags = IMX6_PCIE_FLAG_IMX6_PHY | + IMX6_PCIE_FLAG_SUPPORTS_SUSPEND | IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE, .dbi_length = 0x200, }, |