The driver decides the link is up when the LTSSM state in the DesignWare PORT_DEBUG0 register reads L0. L0 is a physical layer state; the data link layer may not be up yet, and config requests sent before it is are lost.
Linux's pcie-spacemit-k1 driver reads the link status register in the "link" window instead, and needs both SMLH_LINK_UP (physical layer) and RDLH_LINK_UP (data link layer); FreeBSD's spacemit_pcie driver does the same. The window is already mapped (as phy_ahb) and the bits already defined, but nothing read them. Use them, and drop the now unused PORT_DEBUG0 definitions. Signed-off-by: Dave Klotz <[email protected]> --- drivers/pci/pcie_dw_spacemit.c | 9 ++++++--- drivers/pci/pcie_dw_spacemit.h | 5 ----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/pci/pcie_dw_spacemit.c b/drivers/pci/pcie_dw_spacemit.c index 5e0871986b..3394ddbd18 100644 --- a/drivers/pci/pcie_dw_spacemit.c +++ b/drivers/pci/pcie_dw_spacemit.c @@ -81,10 +81,13 @@ static int is_link_up(struct pcie_dw_spacemit *pci) { u32 val; - val = readl(pci->dw.dbi_base + PCIE_PORT_DEBUG0); - val &= PORT_LOGIC_LTSSM_STATE_MASK; + /* + * As in Linux, the link is up once both the physical layer (SMLH) + * and the data link layer (RDLH) report it. + */ + val = spacemit_pcie_phy_ahb_readl(pci, K1X_PHY_AHB_LINK_STS); - return (val == PORT_LOGIC_LTSSM_STATE_L0); + return (val & SMLH_LINK_UP) && (val & RDLH_LINK_UP); } static int wait_link_up(struct pcie_dw_spacemit *pci) diff --git a/drivers/pci/pcie_dw_spacemit.h b/drivers/pci/pcie_dw_spacemit.h index 2c17f113b7..6f198f7d58 100644 --- a/drivers/pci/pcie_dw_spacemit.h +++ b/drivers/pci/pcie_dw_spacemit.h @@ -22,11 +22,6 @@ #define PCIE_MISC_CONTROL_1_OFF 0x8bc #define PCIE_DBI_RO_WR_EN BIT(0) -#define PLR_OFFSET 0x700 -#define PCIE_PORT_DEBUG0 (PLR_OFFSET + 0x28) -#define PORT_LOGIC_LTSSM_STATE_MASK 0x1f -#define PORT_LOGIC_LTSSM_STATE_L0 0x11 - #define PCIE_LINK_UP_TIMEOUT_MS 1000 /* Vendor and device IDs */ -- 2.55.0
