From 29613a7fe779ac0477ab00cb2b7490dfd0d58891 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Thu, 15 Aug 2024 09:29:19 +0800 Subject: [PATCH] Revert "PCI: rockchip: dw: remove .link_up() hook from struct dw_pcie_ops" Revert this commit as it wasn't reliably work as expected by massive test. The problem is clear now that cxpl_debug_info from DWC core is missing rdlh_link_up. So reading PCIE_PORT_DEBUG1 and check smlh_link_up isn't enough. Quoted from DWC databook, section 8.2.3 AXI Bridge Initialization, Clocking and Reset: "In RC Mode, your AXI application must not generate any MEM or I/O requests, until the host software has enabled the Memory Space Enable (MSE), and IO Space Enable (ISE) bits respectively. Your RC application should not generate CFG requests until it has confirmed that the link is up by sampling the smlh_link_up and rdlh_link_up outputs." The problem was introduced by commit 1 and fixed by commit 2 but not to the end. And finally commit 3 rename the register but not fix anything. It was broken from the first time. ANY dwc controller should be use the buggy default method to check link up state. So revert this commit to use our own link_up hook, and check PCIE_PORT_DEBUG1_LINK_IN_TRAINING as well to fix what we were actually trying to fix. This process is confirmed from ASIC simulation. [1]. commit dac29e6c5460 ("PCI: designware: Add default link up check if sub-driver doesn't override") [2]. commit 01c076732e82 ("PCI: designware: Check LTSSM training bit before deciding link is up") [3]. commit 60ef4b072ba0 ("PCI: dwc: imx6: Share PHY debug register definitions") This reverts commit a095b986015598f2aa1ef1e424f766a8bb65f4a3. Change-Id: I2104e5fe00ac3be921f6dc1185ad3ce34e01d1bc Signed-off-by: Shawn Lin Signed-off-by: Stephen Chen --- drivers/pci/controller/dwc/pcie-dw-rockchip.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c index ba462061f6a0c..94b221b5b6148 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -274,6 +274,18 @@ static inline void rk_pcie_enable_ltssm(struct rk_pcie *rk_pcie) rk_pcie_writel_apb(rk_pcie, 0x0, 0xC000C); } +static int rk_pcie_link_up(struct dw_pcie *pci) +{ + struct rk_pcie *rk_pcie = to_rk_pcie(pci); + u32 val; + + val = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS); + if ((val & (RDLH_LINKUP | SMLH_LINKUP)) == 0x30000) + return 1; + + return 0; +} + static void rk_pcie_enable_debug(struct rk_pcie *rk_pcie) { if (!IS_ENABLED(CONFIG_DEBUG_FS)) @@ -814,6 +826,7 @@ MODULE_DEVICE_TABLE(of, rk_pcie_of_match); static const struct dw_pcie_ops dw_pcie_ops = { .start_link = rk_pcie_establish_link, + .link_up = rk_pcie_link_up, }; static void rk_pcie_fast_link_setup(struct rk_pcie *rk_pcie)