From: Richard Zhu <hongxing.zhu@xxxxxxx> - Move the phy_power_on() to host_init and resume functions from imx6_pcie_clk_enable(). - Move the phy_init() to host_init and resume functions from imx6_pcie_deassert_core_reset(). Refine the error handling in imx6_pcie_host_init() and imx6_pcie_resume_noirq() functions accordingly. [bhelgaas: add "ret" back since it's used again] Link: https://lore.kernel.org/r/1655189942-12678-9-git-send-email-hongxing.zhu@xxxxxxx Signed-off-by: Richard Zhu <hongxing.zhu@xxxxxxx> Signed-off-by: Bjorn Helgaas <bhelgaas@xxxxxxxxxx> --- drivers/pci/controller/dwc/pci-imx6.c | 70 +++++++++++++++++++++------ 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index b6e5420d67b6..bd736aff94a3 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -639,14 +639,6 @@ static int imx6_pcie_clk_enable(struct imx6_pcie *imx6_pcie) goto err_ref_clk; } - switch (imx6_pcie->drvdata->variant) { - case IMX8MM: - if (phy_power_on(imx6_pcie->phy)) - dev_err(dev, "unable to power on PHY\n"); - break; - default: - break; - } /* allow the clocks to stabilize */ usleep_range(200, 500); return 0; @@ -733,10 +725,6 @@ static int imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) case IMX8MQ: reset_control_deassert(imx6_pcie->pciephy_reset); break; - case IMX8MM: - if (phy_init(imx6_pcie->phy)) - dev_err(dev, "waiting for phy ready timeout!\n"); - break; case IMX7D: reset_control_deassert(imx6_pcie->pciephy_reset); @@ -772,6 +760,7 @@ static int imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) usleep_range(200, 500); break; case IMX6Q: /* Nothing to do */ + case IMX8MM: break; } @@ -923,15 +912,39 @@ static int imx6_pcie_host_init(struct pcie_port *pp) imx6_pcie_assert_core_reset(imx6_pcie); imx6_pcie_init_phy(imx6_pcie); + if (imx6_pcie->phy) { + ret = phy_power_on(imx6_pcie->phy); + if (ret) { + dev_err(dev, "pcie phy power up failed.\n"); + return ret; + } + } + ret = imx6_pcie_deassert_core_reset(imx6_pcie); if (ret < 0) { dev_err(dev, "pcie host init failed: %d\n", ret); - return ret; + goto err_phy_off; + } + if (imx6_pcie->phy) { + ret = phy_init(imx6_pcie->phy); + if (ret) { + dev_err(dev, "waiting for phy ready timeout!\n"); + goto err_phy_init; + } } imx6_setup_phy_mpll(imx6_pcie); return 0; + +err_phy_init: + imx6_pcie_clk_disable(imx6_pcie); + if (imx6_pcie->vpcie) + regulator_disable(imx6_pcie->vpcie); +err_phy_off: + if (imx6_pcie->phy) + phy_power_off(imx6_pcie->phy); + return ret; } static const struct dw_pcie_host_ops imx6_pcie_host_ops = { @@ -1029,18 +1042,47 @@ static int imx6_pcie_resume_noirq(struct device *dev) { struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev); struct pcie_port *pp = &imx6_pcie->pci->pp; + int ret; if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_SUPPORTS_SUSPEND)) return 0; imx6_pcie_assert_core_reset(imx6_pcie); imx6_pcie_init_phy(imx6_pcie); - imx6_pcie_deassert_core_reset(imx6_pcie); + if (imx6_pcie->phy) { + ret = phy_power_on(imx6_pcie->phy); + if (ret) { + dev_err(dev, "pcie phy power up failed.\n"); + return ret; + } + } + + ret = imx6_pcie_deassert_core_reset(imx6_pcie); + if (ret < 0) { + dev_err(dev, "pcie deassert core reset failed: %d.\n", ret); + goto err_phy_off; + } else if (imx6_pcie->phy) { + ret = phy_init(imx6_pcie->phy); + if (ret) { + dev_err(dev, "pcie phy init failed.\n"); + goto err_phy_init; + } + } + dw_pcie_setup_rc(pp); if (imx6_pcie->link_is_up) imx6_pcie_start_link(imx6_pcie->pci); return 0; + +err_phy_init: + imx6_pcie_clk_disable(imx6_pcie); + if (imx6_pcie->vpcie) + regulator_disable(imx6_pcie->vpcie); +err_phy_off: + if (imx6_pcie->phy) + phy_power_off(imx6_pcie->phy); + return ret; } #endif -- 2.25.1