summaryrefslogtreecommitdiff
path: root/drivers/pci/controller
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-07-31 10:11:52 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-07-31 10:11:52 -0700
commit596254ecc5b7502915feaa737f62b636b77d669a (patch)
treed78ad9c5cc7c7707b466aaec814201b777c464e8 /drivers/pci/controller
parent5f5d80d3b7536b11ddf64be1a80b5500b70afa0c (diff)
parent7678e81498e20e78d7d5f64e552cd153117c1d66 (diff)
downloadlinux-next-596254ecc5b7502915feaa737f62b636b77d669a.tar.gz
linux-next-596254ecc5b7502915feaa737f62b636b77d669a.zip
Merge tag 'pci-v7.2-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci
Pull pci fixes from Bjorn Helgaas: - Remove Karthikeyan Mitran from Mobiveil MAINTAINERS PCIe entry since email bounces (Manivannan Sadhasivam) - Preserve i.MX6Q, i.MX6QP, and i.MX6SX Root Port MSI/MSI-X Capabilities when using iMSI-RX to work around hardware defect (Soeren Moch) - Reorder i.MX6Q/DL PHY power up to fix boot hang regression (Richard Zhu) * tag 'pci-v7.2-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci: PCI: imx6: Fix i.MX6Q/DL boot hang caused by improper PHY power sequencing PCI: imx6: Keep i.MX6 Root Port MSI/MSI-X Capabilities with iMSI-RX to work around hardware bug MAINTAINERS: Drop Karthikeyan Mitran from Mobiveil PCIe entry
Diffstat (limited to 'drivers/pci/controller')
-rw-r--r--drivers/pci/controller/dwc/pci-imx6.c52
1 files changed, 30 insertions, 22 deletions
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 98e1db751132..f7389b5437df 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -680,21 +680,12 @@ static int imx_pcie_attach_pd(struct device *dev)
static int imx6q_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
{
- if (enable) {
- /* power up core phy and enable ref clock */
- regmap_clear_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_TEST_PD);
- /*
- * The async reset input need ref clock to sync internally,
- * when the ref clock comes after reset, internal synced
- * reset time is too short, cannot meet the requirement.
- * Add a ~10us delay here.
- */
- usleep_range(10, 100);
- regmap_set_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_REF_CLK_EN);
- } else {
- regmap_clear_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_REF_CLK_EN);
- regmap_set_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_TEST_PD);
- }
+ if (enable)
+ regmap_set_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1,
+ IMX6Q_GPR1_PCIE_REF_CLK_EN);
+ else
+ regmap_clear_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1,
+ IMX6Q_GPR1_PCIE_REF_CLK_EN);
return 0;
}
@@ -825,8 +816,16 @@ static int imx6sx_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
static int imx6qp_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
{
+ if (assert)
+ regmap_set_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1,
+ IMX6Q_GPR1_PCIE_TEST_PD);
+ else
+ regmap_clear_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1,
+ IMX6Q_GPR1_PCIE_TEST_PD);
+
regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_SW_RST,
assert ? IMX6Q_GPR1_PCIE_SW_RST : 0);
+
if (!assert)
usleep_range(200, 500);
@@ -835,11 +834,15 @@ static int imx6qp_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
static int imx6q_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
{
- if (!assert)
- return 0;
+ if (assert)
+ regmap_set_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1,
+ IMX6Q_GPR1_PCIE_TEST_PD);
+ else
+ regmap_clear_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1,
+ IMX6Q_GPR1_PCIE_TEST_PD);
- regmap_set_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_TEST_PD);
- regmap_set_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_REF_CLK_EN);
+ if (!assert)
+ usleep_range(200, 500);
return 0;
}
@@ -1445,6 +1448,7 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp)
return 0;
err_phy_off:
+ imx_pcie_assert_core_reset(imx_pcie);
phy_power_off(imx_pcie->phy);
err_phy_exit:
phy_exit(imx_pcie->phy);
@@ -1466,6 +1470,7 @@ static void imx_pcie_host_exit(struct dw_pcie_rp *pp)
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct imx_pcie *imx_pcie = to_imx_pcie(pci);
+ imx_pcie_assert_core_reset(imx_pcie);
if (imx_pcie->phy) {
if (phy_power_off(imx_pcie->phy))
dev_err(pci->dev, "unable to power off PHY\n");
@@ -1995,7 +2000,8 @@ static const struct imx_pcie_drvdata drvdata[] = {
.flags = IMX_PCIE_FLAG_IMX_PHY |
IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND |
IMX_PCIE_FLAG_BROKEN_SUSPEND |
- IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
+ IMX_PCIE_FLAG_SUPPORTS_SUSPEND |
+ IMX_PCIE_FLAG_KEEP_MSI_CAP,
.dbi_length = 0x200,
.gpr = "fsl,imx6q-iomuxc-gpr",
.ltssm_off = IOMUXC_GPR12,
@@ -2011,7 +2017,8 @@ static const struct imx_pcie_drvdata drvdata[] = {
.flags = IMX_PCIE_FLAG_IMX_PHY |
IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND |
IMX_PCIE_FLAG_SKIP_L23_READY |
- IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
+ IMX_PCIE_FLAG_SUPPORTS_SUSPEND |
+ IMX_PCIE_FLAG_KEEP_MSI_CAP,
.gpr = "fsl,imx6q-iomuxc-gpr",
.ltssm_off = IOMUXC_GPR12,
.ltssm_mask = IMX6Q_GPR12_PCIE_CTL_2,
@@ -2026,7 +2033,8 @@ static const struct imx_pcie_drvdata drvdata[] = {
.flags = IMX_PCIE_FLAG_IMX_PHY |
IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND |
IMX_PCIE_FLAG_SKIP_L23_READY |
- IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
+ IMX_PCIE_FLAG_SUPPORTS_SUSPEND |
+ IMX_PCIE_FLAG_KEEP_MSI_CAP,
.dbi_length = 0x200,
.gpr = "fsl,imx6q-iomuxc-gpr",
.ltssm_off = IOMUXC_GPR12,