Message ID | 20240402-pci2_upstream-v3-7-803414bdb430@nxp.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | PCI: imx6: Fix\rename\clean up and add lut information for imx95 | expand |
On Tue, Apr 02, 2024 at 10:33:43AM -0400, Frank Li wrote: > Instead of using the switch case statement to assert/dassert the core reset > handled by this driver itself, let's introduce a new callback core_reset() > and define it for platforms that require it. This simplifies the code. > > Signed-off-by: Frank Li <Frank.Li@nxp.com> > --- > drivers/pci/controller/dwc/pcie-imx.c | 131 ++++++++++++++++++---------------- > 1 file changed, 68 insertions(+), 63 deletions(-) > > diff --git a/drivers/pci/controller/dwc/pcie-imx.c b/drivers/pci/controller/dwc/pcie-imx.c > index 77dae5c3f7057..af0f960f28757 100644 > --- a/drivers/pci/controller/dwc/pcie-imx.c > +++ b/drivers/pci/controller/dwc/pcie-imx.c > @@ -104,6 +104,7 @@ struct imx_pcie_drvdata { > const struct pci_epc_features *epc_features; > int (*init_phy)(struct imx_pcie *pcie); > int (*set_ref_clk)(struct imx_pcie *pcie, bool enable); > + int (*core_reset)(struct imx_pcie *pcie, bool assert); > }; > > struct imx_pcie { > @@ -671,35 +672,72 @@ static void imx_pcie_clk_disable(struct imx_pcie *imx_pcie) > clk_bulk_disable_unprepare(imx_pcie->drvdata->clks_cnt, imx_pcie->clks); > } > > +static int imx6sx_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert) > +{ > + regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6SX_GPR12_PCIE_TEST_POWERDOWN, > + assert ? IMX6SX_GPR12_PCIE_TEST_POWERDOWN : 0); Earlier, this register was not cleared during deassert. Is if fine? > + /* Force PCIe PHY reset */ > + regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR5, IMX6SX_GPR5_PCIE_BTNRST_RESET, > + assert ? IMX6SX_GPR5_PCIE_BTNRST_RESET : 0); > + return 0; > +} > + > +static int imx6qp_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert) > +{ > + 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); > + > + return 0; > +} > + > +static int imx6q_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert) > +{ > + regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_TEST_PD, > + assert ? IMX6Q_GPR1_PCIE_TEST_PD : 0); > + > + regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_REF_CLK_EN, > + assert ? 0 : IMX6Q_GPR1_PCIE_REF_CLK_EN); > + Same comment as above. > + return 0; > +} > + > +static int imx7d_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert) > +{ > + struct dw_pcie *pci = imx_pcie->pci; > + struct device *dev = pci->dev; > + > + if (assert) > + return 0; > + > + /* > + * Workaround for ERR010728, failure of PCI-e PLL VCO to oscillate, especially when cold. What does 'especially when cold' means? I know it is an old comment, but still it is not very clear. > + * This turns off "Duty-cycle Corrector" and other mysterious undocumented things. Same comment as previous patch. > + */ > + > + if (likely(imx_pcie->phy_base)) { > + /* De-assert DCC_FB_EN */ > + writel(PCIE_PHY_CMN_REG4_DCC_FB_EN, imx_pcie->phy_base + PCIE_PHY_CMN_REG4); > + /* Assert RX_EQS and RX_EQS_SEL */ > + writel(PCIE_PHY_CMN_REG24_RX_EQ_SEL | PCIE_PHY_CMN_REG24_RX_EQ, > + imx_pcie->phy_base + PCIE_PHY_CMN_REG24); > + /* Assert ATT_MODE */ > + writel(PCIE_PHY_CMN_REG26_ATT_MODE, imx_pcie->phy_base + PCIE_PHY_CMN_REG26); Why does this workaround a part of core_reset handling? This function doesn't look like performing reset at all. - Mani > + } else { > + dev_warn(dev, "Unable to apply ERR010728 workaround. DT missing fsl,imx7d-pcie-phy phandle ?\n"); > + } > + imx7d_pcie_wait_for_phy_pll_lock(imx_pcie); > + return 0; > +} > + > static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie) > { > reset_control_assert(imx_pcie->pciephy_reset); > reset_control_assert(imx_pcie->apps_reset); > > - switch (imx_pcie->drvdata->variant) { > - case IMX6SX: > - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12, > - IMX6SX_GPR12_PCIE_TEST_POWERDOWN, > - IMX6SX_GPR12_PCIE_TEST_POWERDOWN); > - /* Force PCIe PHY reset */ > - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR5, > - IMX6SX_GPR5_PCIE_BTNRST_RESET, > - IMX6SX_GPR5_PCIE_BTNRST_RESET); > - break; > - case IMX6QP: > - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, > - IMX6Q_GPR1_PCIE_SW_RST, > - IMX6Q_GPR1_PCIE_SW_RST); > - break; > - case IMX6Q: > - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, > - IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18); > - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, > - IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16); > - break; > - default: > - break; > - } > + if (imx_pcie->drvdata->core_reset) > + imx_pcie->drvdata->core_reset(imx_pcie, true); > > /* Some boards don't have PCIe reset GPIO. */ > if (gpio_is_valid(imx_pcie->reset_gpio)) > @@ -709,47 +747,10 @@ static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie) > > static int imx_pcie_deassert_core_reset(struct imx_pcie *imx_pcie) > { > - struct dw_pcie *pci = imx_pcie->pci; > - struct device *dev = pci->dev; > - > reset_control_deassert(imx_pcie->pciephy_reset); > > - switch (imx_pcie->drvdata->variant) { > - case IMX7D: > - /* Workaround for ERR010728, failure of PCI-e PLL VCO to > - * oscillate, especially when cold. This turns off "Duty-cycle > - * Corrector" and other mysterious undocumented things. > - */ > - if (likely(imx_pcie->phy_base)) { > - /* De-assert DCC_FB_EN */ > - writel(PCIE_PHY_CMN_REG4_DCC_FB_EN, > - imx_pcie->phy_base + PCIE_PHY_CMN_REG4); > - /* Assert RX_EQS and RX_EQS_SEL */ > - writel(PCIE_PHY_CMN_REG24_RX_EQ_SEL > - | PCIE_PHY_CMN_REG24_RX_EQ, > - imx_pcie->phy_base + PCIE_PHY_CMN_REG24); > - /* Assert ATT_MODE */ > - writel(PCIE_PHY_CMN_REG26_ATT_MODE, > - imx_pcie->phy_base + PCIE_PHY_CMN_REG26); > - } else { > - dev_warn(dev, "Unable to apply ERR010728 workaround. DT missing fsl,imx7d-pcie-phy phandle ?\n"); > - } > - > - imx7d_pcie_wait_for_phy_pll_lock(imx_pcie); > - break; > - case IMX6SX: > - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR5, > - IMX6SX_GPR5_PCIE_BTNRST_RESET, 0); > - break; > - case IMX6QP: > - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, > - IMX6Q_GPR1_PCIE_SW_RST, 0); > - > - usleep_range(200, 500); > - break; > - default: > - break; > - } > + if (imx_pcie->drvdata->core_reset) > + imx_pcie->drvdata->core_reset(imx_pcie, false); > > /* Some boards don't have PCIe reset GPIO. */ > if (gpio_is_valid(imx_pcie->reset_gpio)) { > @@ -1447,6 +1448,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > .init_phy = imx_pcie_init_phy, > .set_ref_clk = imx6q_pcie_set_ref_clk, > + .core_reset = imx6q_pcie_core_reset, > }, > [IMX6SX] = { > .variant = IMX6SX, > @@ -1462,6 +1464,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > .init_phy = imx6sx_pcie_init_phy, > .set_ref_clk = imx6sx_pcie_set_ref_clk, > + .core_reset = imx6sx_pcie_core_reset, > }, > [IMX6QP] = { > .variant = IMX6QP, > @@ -1478,6 +1481,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > .init_phy = imx_pcie_init_phy, > .set_ref_clk = imx6q_pcie_set_ref_clk, > + .core_reset = imx6qp_pcie_core_reset, > }, > [IMX7D] = { > .variant = IMX7D, > @@ -1491,6 +1495,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > .init_phy = imx7d_pcie_init_phy, > .set_ref_clk = imx7d_pcie_set_ref_clk, > + .core_reset = imx7d_pcie_core_reset, > }, > [IMX8MQ] = { > .variant = IMX8MQ, > > -- > 2.34.1 >
On Sat, Apr 27, 2024 at 03:49:50PM +0530, Manivannan Sadhasivam wrote: > On Tue, Apr 02, 2024 at 10:33:43AM -0400, Frank Li wrote: > > Instead of using the switch case statement to assert/dassert the core reset > > handled by this driver itself, let's introduce a new callback core_reset() > > and define it for platforms that require it. This simplifies the code. > > > > Signed-off-by: Frank Li <Frank.Li@nxp.com> > > --- > > drivers/pci/controller/dwc/pcie-imx.c | 131 ++++++++++++++++++---------------- > > 1 file changed, 68 insertions(+), 63 deletions(-) > > > > diff --git a/drivers/pci/controller/dwc/pcie-imx.c b/drivers/pci/controller/dwc/pcie-imx.c > > index 77dae5c3f7057..af0f960f28757 100644 > > --- a/drivers/pci/controller/dwc/pcie-imx.c > > +++ b/drivers/pci/controller/dwc/pcie-imx.c > > @@ -104,6 +104,7 @@ struct imx_pcie_drvdata { > > const struct pci_epc_features *epc_features; > > int (*init_phy)(struct imx_pcie *pcie); > > int (*set_ref_clk)(struct imx_pcie *pcie, bool enable); > > + int (*core_reset)(struct imx_pcie *pcie, bool assert); > > }; > > > > struct imx_pcie { > > @@ -671,35 +672,72 @@ static void imx_pcie_clk_disable(struct imx_pcie *imx_pcie) > > clk_bulk_disable_unprepare(imx_pcie->drvdata->clks_cnt, imx_pcie->clks); > > } > > > > +static int imx6sx_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert) > > +{ > > + regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6SX_GPR12_PCIE_TEST_POWERDOWN, > > + assert ? IMX6SX_GPR12_PCIE_TEST_POWERDOWN : 0); > > Earlier, this register was not cleared during deassert. Is if fine? Just missed power off cycle, it is functional. But I think it's better to match old logic to let review easily. > > > + /* Force PCIe PHY reset */ > > + regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR5, IMX6SX_GPR5_PCIE_BTNRST_RESET, > > + assert ? IMX6SX_GPR5_PCIE_BTNRST_RESET : 0); > > + return 0; > > +} > > + > > +static int imx6qp_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert) > > +{ > > + 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); > > + > > + return 0; > > +} > > + > > +static int imx6q_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert) > > +{ > > + regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_TEST_PD, > > + assert ? IMX6Q_GPR1_PCIE_TEST_PD : 0); > > + > > + regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_REF_CLK_EN, > > + assert ? 0 : IMX6Q_GPR1_PCIE_REF_CLK_EN); > > + > > Same comment as above. > > > + return 0; > > +} > > + > > +static int imx7d_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert) > > +{ > > + struct dw_pcie *pci = imx_pcie->pci; > > + struct device *dev = pci->dev; > > + > > + if (assert) > > + return 0; > > + > > + /* > > + * Workaround for ERR010728, failure of PCI-e PLL VCO to oscillate, especially when cold. > > What does 'especially when cold' means? I know it is an old comment, but still > it is not very clear. > > > + * This turns off "Duty-cycle Corrector" and other mysterious undocumented things. > > Same comment as previous patch. It is copy from old comments. How about keep the same here. And improve at difference patch? I copied key content from formal errata. /* Workaround for ERR010728 (IMX7DS_2N09P, Rev. 1.1, 4/2023): PCIe: PLL may fail to lock under corner conditions Initial VCO oscillation may fail under corner conditions such as cold temperature which will cause the PCIe PLL fail to lock in the initialization phase. The Duty-cycle Corrector calibration must be disabled 1. De-assert the G_RST signal by clearing SRC_PCIEPHY_RCR[PCIEPHY_G_RST]. 2. De-assert DCC_FB_EN by writing data “0x29” to the register address 0x306d0014. 3. Assert RX_EQS, RX_EQ_SEL by writing data “0x48” to the register address 0x306d0090. 4. Assert ATT_MODE by writing data “0xbc” to the register address 0x306d0098. 5. De-assert the CMN_RST signal by clearing register bit SRC_PCIEPHY_RCR[PCIEPHY_BTN] */ > > > + */ > > + > > + if (likely(imx_pcie->phy_base)) { > > + /* De-assert DCC_FB_EN */ > > + writel(PCIE_PHY_CMN_REG4_DCC_FB_EN, imx_pcie->phy_base + PCIE_PHY_CMN_REG4); > > + /* Assert RX_EQS and RX_EQS_SEL */ > > + writel(PCIE_PHY_CMN_REG24_RX_EQ_SEL | PCIE_PHY_CMN_REG24_RX_EQ, > > + imx_pcie->phy_base + PCIE_PHY_CMN_REG24); > > + /* Assert ATT_MODE */ > > + writel(PCIE_PHY_CMN_REG26_ATT_MODE, imx_pcie->phy_base + PCIE_PHY_CMN_REG26); > > Why does this workaround a part of core_reset handling? This function doesn't > look like performing reset at all. According to errata document, it should be step 2,3,4. > > - Mani > > > + } else { > > + dev_warn(dev, "Unable to apply ERR010728 workaround. DT missing fsl,imx7d-pcie-phy phandle ?\n"); > > + } > > + imx7d_pcie_wait_for_phy_pll_lock(imx_pcie); > > + return 0; > > +} > > + > > static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie) > > { > > reset_control_assert(imx_pcie->pciephy_reset); > > reset_control_assert(imx_pcie->apps_reset); > > > > - switch (imx_pcie->drvdata->variant) { > > - case IMX6SX: > > - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12, > > - IMX6SX_GPR12_PCIE_TEST_POWERDOWN, > > - IMX6SX_GPR12_PCIE_TEST_POWERDOWN); > > - /* Force PCIe PHY reset */ > > - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR5, > > - IMX6SX_GPR5_PCIE_BTNRST_RESET, > > - IMX6SX_GPR5_PCIE_BTNRST_RESET); > > - break; > > - case IMX6QP: > > - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, > > - IMX6Q_GPR1_PCIE_SW_RST, > > - IMX6Q_GPR1_PCIE_SW_RST); > > - break; > > - case IMX6Q: > > - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, > > - IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18); > > - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, > > - IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16); > > - break; > > - default: > > - break; > > - } > > + if (imx_pcie->drvdata->core_reset) > > + imx_pcie->drvdata->core_reset(imx_pcie, true); > > > > /* Some boards don't have PCIe reset GPIO. */ > > if (gpio_is_valid(imx_pcie->reset_gpio)) > > @@ -709,47 +747,10 @@ static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie) > > > > static int imx_pcie_deassert_core_reset(struct imx_pcie *imx_pcie) > > { > > - struct dw_pcie *pci = imx_pcie->pci; > > - struct device *dev = pci->dev; > > - > > reset_control_deassert(imx_pcie->pciephy_reset); > > > > - switch (imx_pcie->drvdata->variant) { > > - case IMX7D: > > - /* Workaround for ERR010728, failure of PCI-e PLL VCO to > > - * oscillate, especially when cold. This turns off "Duty-cycle > > - * Corrector" and other mysterious undocumented things. > > - */ > > - if (likely(imx_pcie->phy_base)) { > > - /* De-assert DCC_FB_EN */ > > - writel(PCIE_PHY_CMN_REG4_DCC_FB_EN, > > - imx_pcie->phy_base + PCIE_PHY_CMN_REG4); > > - /* Assert RX_EQS and RX_EQS_SEL */ > > - writel(PCIE_PHY_CMN_REG24_RX_EQ_SEL > > - | PCIE_PHY_CMN_REG24_RX_EQ, > > - imx_pcie->phy_base + PCIE_PHY_CMN_REG24); > > - /* Assert ATT_MODE */ > > - writel(PCIE_PHY_CMN_REG26_ATT_MODE, > > - imx_pcie->phy_base + PCIE_PHY_CMN_REG26); > > - } else { > > - dev_warn(dev, "Unable to apply ERR010728 workaround. DT missing fsl,imx7d-pcie-phy phandle ?\n"); > > - } > > - > > - imx7d_pcie_wait_for_phy_pll_lock(imx_pcie); > > - break; > > - case IMX6SX: > > - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR5, > > - IMX6SX_GPR5_PCIE_BTNRST_RESET, 0); > > - break; > > - case IMX6QP: > > - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, > > - IMX6Q_GPR1_PCIE_SW_RST, 0); > > - > > - usleep_range(200, 500); > > - break; > > - default: > > - break; > > - } > > + if (imx_pcie->drvdata->core_reset) > > + imx_pcie->drvdata->core_reset(imx_pcie, false); > > > > /* Some boards don't have PCIe reset GPIO. */ > > if (gpio_is_valid(imx_pcie->reset_gpio)) { > > @@ -1447,6 +1448,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > > .init_phy = imx_pcie_init_phy, > > .set_ref_clk = imx6q_pcie_set_ref_clk, > > + .core_reset = imx6q_pcie_core_reset, > > }, > > [IMX6SX] = { > > .variant = IMX6SX, > > @@ -1462,6 +1464,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > > .init_phy = imx6sx_pcie_init_phy, > > .set_ref_clk = imx6sx_pcie_set_ref_clk, > > + .core_reset = imx6sx_pcie_core_reset, > > }, > > [IMX6QP] = { > > .variant = IMX6QP, > > @@ -1478,6 +1481,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > > .init_phy = imx_pcie_init_phy, > > .set_ref_clk = imx6q_pcie_set_ref_clk, > > + .core_reset = imx6qp_pcie_core_reset, > > }, > > [IMX7D] = { > > .variant = IMX7D, > > @@ -1491,6 +1495,7 @@ static const struct imx_pcie_drvdata drvdata[] = { > > .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, > > .init_phy = imx7d_pcie_init_phy, > > .set_ref_clk = imx7d_pcie_set_ref_clk, > > + .core_reset = imx7d_pcie_core_reset, > > }, > > [IMX8MQ] = { > > .variant = IMX8MQ, > > > > -- > > 2.34.1 > > > > -- > மணிவண்ணன் சதாசிவம்
diff --git a/drivers/pci/controller/dwc/pcie-imx.c b/drivers/pci/controller/dwc/pcie-imx.c index 77dae5c3f7057..af0f960f28757 100644 --- a/drivers/pci/controller/dwc/pcie-imx.c +++ b/drivers/pci/controller/dwc/pcie-imx.c @@ -104,6 +104,7 @@ struct imx_pcie_drvdata { const struct pci_epc_features *epc_features; int (*init_phy)(struct imx_pcie *pcie); int (*set_ref_clk)(struct imx_pcie *pcie, bool enable); + int (*core_reset)(struct imx_pcie *pcie, bool assert); }; struct imx_pcie { @@ -671,35 +672,72 @@ static void imx_pcie_clk_disable(struct imx_pcie *imx_pcie) clk_bulk_disable_unprepare(imx_pcie->drvdata->clks_cnt, imx_pcie->clks); } +static int imx6sx_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert) +{ + regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6SX_GPR12_PCIE_TEST_POWERDOWN, + assert ? IMX6SX_GPR12_PCIE_TEST_POWERDOWN : 0); + /* Force PCIe PHY reset */ + regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR5, IMX6SX_GPR5_PCIE_BTNRST_RESET, + assert ? IMX6SX_GPR5_PCIE_BTNRST_RESET : 0); + return 0; +} + +static int imx6qp_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert) +{ + 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); + + return 0; +} + +static int imx6q_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert) +{ + regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_TEST_PD, + assert ? IMX6Q_GPR1_PCIE_TEST_PD : 0); + + regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_REF_CLK_EN, + assert ? 0 : IMX6Q_GPR1_PCIE_REF_CLK_EN); + + return 0; +} + +static int imx7d_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert) +{ + struct dw_pcie *pci = imx_pcie->pci; + struct device *dev = pci->dev; + + if (assert) + return 0; + + /* + * Workaround for ERR010728, failure of PCI-e PLL VCO to oscillate, especially when cold. + * This turns off "Duty-cycle Corrector" and other mysterious undocumented things. + */ + + if (likely(imx_pcie->phy_base)) { + /* De-assert DCC_FB_EN */ + writel(PCIE_PHY_CMN_REG4_DCC_FB_EN, imx_pcie->phy_base + PCIE_PHY_CMN_REG4); + /* Assert RX_EQS and RX_EQS_SEL */ + writel(PCIE_PHY_CMN_REG24_RX_EQ_SEL | PCIE_PHY_CMN_REG24_RX_EQ, + imx_pcie->phy_base + PCIE_PHY_CMN_REG24); + /* Assert ATT_MODE */ + writel(PCIE_PHY_CMN_REG26_ATT_MODE, imx_pcie->phy_base + PCIE_PHY_CMN_REG26); + } else { + dev_warn(dev, "Unable to apply ERR010728 workaround. DT missing fsl,imx7d-pcie-phy phandle ?\n"); + } + imx7d_pcie_wait_for_phy_pll_lock(imx_pcie); + return 0; +} + static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie) { reset_control_assert(imx_pcie->pciephy_reset); reset_control_assert(imx_pcie->apps_reset); - switch (imx_pcie->drvdata->variant) { - case IMX6SX: - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12, - IMX6SX_GPR12_PCIE_TEST_POWERDOWN, - IMX6SX_GPR12_PCIE_TEST_POWERDOWN); - /* Force PCIe PHY reset */ - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR5, - IMX6SX_GPR5_PCIE_BTNRST_RESET, - IMX6SX_GPR5_PCIE_BTNRST_RESET); - break; - case IMX6QP: - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, - IMX6Q_GPR1_PCIE_SW_RST, - IMX6Q_GPR1_PCIE_SW_RST); - break; - case IMX6Q: - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, - IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18); - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, - IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16); - break; - default: - break; - } + if (imx_pcie->drvdata->core_reset) + imx_pcie->drvdata->core_reset(imx_pcie, true); /* Some boards don't have PCIe reset GPIO. */ if (gpio_is_valid(imx_pcie->reset_gpio)) @@ -709,47 +747,10 @@ static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie) static int imx_pcie_deassert_core_reset(struct imx_pcie *imx_pcie) { - struct dw_pcie *pci = imx_pcie->pci; - struct device *dev = pci->dev; - reset_control_deassert(imx_pcie->pciephy_reset); - switch (imx_pcie->drvdata->variant) { - case IMX7D: - /* Workaround for ERR010728, failure of PCI-e PLL VCO to - * oscillate, especially when cold. This turns off "Duty-cycle - * Corrector" and other mysterious undocumented things. - */ - if (likely(imx_pcie->phy_base)) { - /* De-assert DCC_FB_EN */ - writel(PCIE_PHY_CMN_REG4_DCC_FB_EN, - imx_pcie->phy_base + PCIE_PHY_CMN_REG4); - /* Assert RX_EQS and RX_EQS_SEL */ - writel(PCIE_PHY_CMN_REG24_RX_EQ_SEL - | PCIE_PHY_CMN_REG24_RX_EQ, - imx_pcie->phy_base + PCIE_PHY_CMN_REG24); - /* Assert ATT_MODE */ - writel(PCIE_PHY_CMN_REG26_ATT_MODE, - imx_pcie->phy_base + PCIE_PHY_CMN_REG26); - } else { - dev_warn(dev, "Unable to apply ERR010728 workaround. DT missing fsl,imx7d-pcie-phy phandle ?\n"); - } - - imx7d_pcie_wait_for_phy_pll_lock(imx_pcie); - break; - case IMX6SX: - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR5, - IMX6SX_GPR5_PCIE_BTNRST_RESET, 0); - break; - case IMX6QP: - regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, - IMX6Q_GPR1_PCIE_SW_RST, 0); - - usleep_range(200, 500); - break; - default: - break; - } + if (imx_pcie->drvdata->core_reset) + imx_pcie->drvdata->core_reset(imx_pcie, false); /* Some boards don't have PCIe reset GPIO. */ if (gpio_is_valid(imx_pcie->reset_gpio)) { @@ -1447,6 +1448,7 @@ static const struct imx_pcie_drvdata drvdata[] = { .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, .init_phy = imx_pcie_init_phy, .set_ref_clk = imx6q_pcie_set_ref_clk, + .core_reset = imx6q_pcie_core_reset, }, [IMX6SX] = { .variant = IMX6SX, @@ -1462,6 +1464,7 @@ static const struct imx_pcie_drvdata drvdata[] = { .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, .init_phy = imx6sx_pcie_init_phy, .set_ref_clk = imx6sx_pcie_set_ref_clk, + .core_reset = imx6sx_pcie_core_reset, }, [IMX6QP] = { .variant = IMX6QP, @@ -1478,6 +1481,7 @@ static const struct imx_pcie_drvdata drvdata[] = { .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, .init_phy = imx_pcie_init_phy, .set_ref_clk = imx6q_pcie_set_ref_clk, + .core_reset = imx6qp_pcie_core_reset, }, [IMX7D] = { .variant = IMX7D, @@ -1491,6 +1495,7 @@ static const struct imx_pcie_drvdata drvdata[] = { .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, .init_phy = imx7d_pcie_init_phy, .set_ref_clk = imx7d_pcie_set_ref_clk, + .core_reset = imx7d_pcie_core_reset, }, [IMX8MQ] = { .variant = IMX8MQ,
Instead of using the switch case statement to assert/dassert the core reset handled by this driver itself, let's introduce a new callback core_reset() and define it for platforms that require it. This simplifies the code. Signed-off-by: Frank Li <Frank.Li@nxp.com> --- drivers/pci/controller/dwc/pcie-imx.c | 131 ++++++++++++++++++---------------- 1 file changed, 68 insertions(+), 63 deletions(-)