summaryrefslogtreecommitdiff
path: root/drivers/pci/controller/dwc/pci-imx6.c
diff options
context:
space:
mode:
authorRichard Zhu <hongxing.zhu@nxp.com>2020-01-06 15:54:12 +0800
committerRichard Zhu <hongxing.zhu@nxp.com>2020-02-05 17:34:18 +0800
commit14290b00bc3fba5086151e7e3f1d25972e1ce578 (patch)
tree7c0ff87a86a1d0b8511e7c562b36ff7e3889bda0 /drivers/pci/controller/dwc/pci-imx6.c
parent00de7142f86d053b325aa5e6fd49df9ce2f0428e (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.c47
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,
},