From 7fc31365404331fd43c3839a0acb09ca9b0ee57c Mon Sep 17 00:00:00 2001 From: Yue Wang Date: Wed, 29 Jul 2020 13:38:30 +0800 Subject: [PATCH] pcie: fix pcie resume link timeout [1/1] PD#SWPL-30613 Problem: fix pcie resume link timeout Solution: fix pcie resume link timeout Verify: S905D3 Change-Id: I6a4a9870b365c193e7c8cfc963d01cbed86956b3 Signed-off-by: Yue Wang --- drivers/amlogic/pci/pcie-amlogic-v2.c | 57 ++++++++++++++++++--------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/drivers/amlogic/pci/pcie-amlogic-v2.c b/drivers/amlogic/pci/pcie-amlogic-v2.c index 006624d68a9d..5559f9755ad0 100644 --- a/drivers/amlogic/pci/pcie-amlogic-v2.c +++ b/drivers/amlogic/pci/pcie-amlogic-v2.c @@ -574,13 +574,17 @@ static int amlogic_pcie_link_up(struct pcie_port *pp) int cnt = 0; u32 val = 0; u32 linkup = 0; + int i = 0; struct amlogic_pcie *amlogic_pcie = to_amlogic_pcie(pp); - val = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1); - linkup = ((val & PCIE_PHY_DEBUG_R1_LINK_UP) && - (!(val & PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING))); - if (linkup) - return linkup; + for (i = 0; i < 1000; i++) { + val = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1); + linkup = ((val & PCIE_PHY_DEBUG_R1_LINK_UP) && + (!(val & PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING))); + if (linkup) + return linkup; + usleep_range(100, 110); + } while (smlh_up == 0 || rdlh_up == 0 || ltssm_up == 0 || speed_okay == 0) { @@ -1035,6 +1039,7 @@ static int amlogic_pcie_suspend_noirq(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct amlogic_pcie *amlogic_pcie = platform_get_drvdata(pdev); + u32 val; if (!amlogic_pcie->pm_enable) { dev_info(dev, "don't noirq suspend amlogic pcie\n"); @@ -1058,16 +1063,24 @@ static int amlogic_pcie_suspend_noirq(struct device *dev) dev_info(dev, "amlogic_pcie_suspend_noirq\n"); - clk_disable_unprepare(amlogic_pcie->clk); - clk_disable_unprepare(amlogic_pcie->bus_clk); - clk_disable_unprepare(amlogic_pcie->phy_clk); - amlogic_pcie->phy->reset_state = 0; + val = amlogic_cfg_readl(amlogic_pcie, PCIE_CFG0); + val &= (~APP_LTSSM_ENABLE); + amlogic_cfg_writel(amlogic_pcie, val, PCIE_CFG0); + usleep_range(500, 510); if (amlogic_pcie->pcie_num == 1) { writel(0x1d, amlogic_pcie->pcie_aml_regs_v2.pcie_phy_r[0]); amlogic_pcie->phy->power_state = 0; } + usleep_range(500, 510); + + clk_disable_unprepare(amlogic_pcie->clk); + clk_disable_unprepare(amlogic_pcie->phy_clk); + usleep_range(500, 510); + clk_disable_unprepare(amlogic_pcie->bus_clk); + amlogic_pcie->phy->reset_state = 0; + return 0; } @@ -1076,6 +1089,7 @@ static int amlogic_pcie_resume_noirq(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct amlogic_pcie *amlogic_pcie = platform_get_drvdata(pdev); unsigned long rate = 100000000; + u32 val; if (!amlogic_pcie->pm_enable) { dev_info(dev, "don't noirq resume amlogic pcie\n"); @@ -1087,12 +1101,6 @@ static int amlogic_pcie_resume_noirq(struct device *dev) return 0; } - if (amlogic_pcie->pcie_num == 1) { - writel(0x1c, amlogic_pcie->pcie_aml_regs_v2.pcie_phy_r[0]); - amlogic_pcie->phy->power_state = 1; - udelay(500); - } - if (amlogic_pcie->device_attch == 0) { dev_info(dev, "controller power off, no resume noirq\n"); return 0; @@ -1104,10 +1112,23 @@ static int amlogic_pcie_resume_noirq(struct device *dev) amlogic_pcie->phy->reset_state = 1; - clk_prepare_enable(amlogic_pcie->phy_clk); clk_prepare_enable(amlogic_pcie->bus_clk); + usleep_range(500, 510); + + clk_prepare_enable(amlogic_pcie->phy_clk); clk_prepare_enable(amlogic_pcie->clk); - udelay(500); + usleep_range(500, 510); + + if (amlogic_pcie->pcie_num == 1) { + writel(0x1c, amlogic_pcie->pcie_aml_regs_v2.pcie_phy_r[0]); + amlogic_pcie->phy->power_state = 1; + usleep_range(500, 510); + } + + val = amlogic_cfg_readl(amlogic_pcie, PCIE_CFG0); + val |= (APP_LTSSM_ENABLE); + amlogic_cfg_writel(amlogic_pcie, val, PCIE_CFG0); + usleep_range(500, 510); return 0; } @@ -1146,4 +1167,4 @@ static int __init amlogic_pcie_init(void) { return platform_driver_probe(&amlogic_pcie_driver, amlogic_pcie_probe); } -subsys_initcall(amlogic_pcie_init); +device_initcall(amlogic_pcie_init);