diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index 345365ea97c7..55c1c60f7f8f 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -692,9 +692,16 @@ void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index) dw_pcie_writel_atu(pci, dir, index, PCIE_ATU_REGION_CTRL2, 0); } +/** + * dw_pcie_wait_for_link - Wait for the PCIe link to be up + * @pci: DWC instance + * + * Returns: 0 if link is up, -ENODEV if device is not found, -ETIMEDOUT if the + * link fails to come up for other reasons. + */ int dw_pcie_wait_for_link(struct dw_pcie *pci) { - u32 offset, val; + u32 offset, val, ltssm; int retries; /* Check if the link is up or not */ @@ -706,6 +713,17 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci) } if (retries >= PCIE_LINK_WAIT_MAX_RETRIES) { + /* + * If the link is in Detect.Quiet or Detect.Active state, it + * indicates that no device is detected. + */ + ltssm = dw_pcie_get_ltssm(pci); + if (ltssm == DW_PCIE_LTSSM_DETECT_QUIET || + ltssm == DW_PCIE_LTSSM_DETECT_ACT) { + dev_info(pci->dev, "Device not found\n"); + return -ENODEV; + } + dev_info(pci->dev, "Phy link never came up\n"); return -ETIMEDOUT; }