diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 60620cc0dedc..6bad30e330d4 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -1157,6 +1157,8 @@ int dw_pcie_suspend_noirq(struct dw_pcie *pci) if (!pci_host_common_can_enter_d3cold(pci->pp.bridge)) return 0; + pci->pp.skip_pwrctrl_off = true; + if (pci->pp.ops->pme_turn_off) { pci->pp.ops->pme_turn_off(&pci->pp); } else { @@ -1212,6 +1214,7 @@ int dw_pcie_resume_noirq(struct dw_pcie *pci) return 0; pci->suspended = false; + pci->pp.skip_pwrctrl_off = false; if (pci->pp.ops->init) { ret = pci->pp.ops->init(&pci->pp); diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 57ca6b8de55b..bc34858c0851 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -436,6 +436,7 @@ struct dw_pcie_rp { bool ecam_enabled; bool native_ecam; bool skip_l23_ready; + bool skip_pwrctrl_off; }; struct dw_pcie_ep_ops { diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 83e973623f55..143c280c5fc0 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -1308,13 +1308,17 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp) if (ret) goto err_deinit; - ret = pci_pwrctrl_create_devices(pci->dev); - if (ret) - goto err_disable_phy; + if (!pci->suspended) { + ret = pci_pwrctrl_create_devices(pci->dev); + if (ret) + goto err_disable_phy; + } - ret = pci_pwrctrl_power_on_devices(pci->dev); - if (ret) - goto err_pwrctrl_destroy; + if (!pp->skip_pwrctrl_off) { + ret = pci_pwrctrl_power_on_devices(pci->dev); + if (ret) + goto err_pwrctrl_destroy; + } if (pcie->cfg->ops->post_init) { ret = pcie->cfg->ops->post_init(pcie); @@ -1356,11 +1360,14 @@ static void qcom_pcie_host_deinit(struct dw_pcie_rp *pp) qcom_pcie_perst_assert(pcie); - /* - * No need to destroy pwrctrl devices as this function only gets called - * during system suspend as of now. - */ - pci_pwrctrl_power_off_devices(pci->dev); + if (!pci->pp.skip_pwrctrl_off) { + /* + * No need to destroy pwrctrl devices as this function only gets called + * during system suspend as of now. + */ + pci_pwrctrl_power_off_devices(pci->dev); + } + qcom_pcie_phy_power_off(pcie); pcie->cfg->ops->deinit(pcie); } @@ -2050,11 +2057,16 @@ static int qcom_pcie_resume_noirq(struct device *dev) ret = icc_enable(pcie->icc_mem); if (ret) { dev_err(dev, "Failed to enable PCIe-MEM interconnect path: %d\n", ret); - return ret; + goto disable_icc_cpu; } + + /* + * Ignore -ENODEV & -EIO here since it is expected when no endpoint is + * connected to the PCIe link. + */ ret = dw_pcie_resume_noirq(pcie->pci); - if (ret && (ret != -ETIMEDOUT)) - return ret; + if (ret && ret != -ENODEV && ret != -EIO) + goto disable_icc_mem; } else { if (pm_suspend_target_state != PM_SUSPEND_MEM) { ret = icc_enable(pcie->icc_cpu); @@ -2069,6 +2081,12 @@ static int qcom_pcie_resume_noirq(struct device *dev) qcom_pcie_icc_opp_update(pcie); return 0; +disable_icc_mem: + icc_disable(pcie->icc_mem); +disable_icc_cpu: + icc_disable(pcie->icc_cpu); + + return ret; } static const struct of_device_id qcom_pcie_match[] = {