diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c index a9eb55386cd2..537e69dfb894 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -1451,6 +1451,129 @@ static void rk_pcie_set_power_limit(struct rk_pcie *rk_pcie) dw_pcie_writew_dbi(rk_pcie->pci, reg + PCI_EXP_SLTCAP, val); } +static int rk_pcie_hardware_io_config(struct rk_pcie *rk_pcie) +{ + struct dw_pcie *pci = rk_pcie->pci; + struct device *dev = pci->dev; + int ret; + + if (!IS_ERR_OR_NULL(rk_pcie->prsnt_gpio)) { + if (!gpiod_get_value(rk_pcie->prsnt_gpio)) { + dev_info(dev, "device isn't present\n"); + return -ENODEV; + } + } + + ret = rk_pcie_enable_power(rk_pcie); + if (ret) + return ret; + + reset_control_assert(rk_pcie->rsts); + udelay(10); + + ret = clk_bulk_prepare_enable(rk_pcie->clk_cnt, rk_pcie->clks); + if (ret) { + dev_err(dev, "clock init failed\n"); + goto disable_vpcie3v3; + } + + ret = phy_set_mode_ext(rk_pcie->phy, PHY_MODE_PCIE, PHY_MODE_PCIE_RC); + if (ret) { + dev_err(dev, "fail to set phy to rc mode\n"); + goto disable_clk; + } + + if (rk_pcie->bifurcation) + phy_set_mode_ext(rk_pcie->phy, PHY_MODE_PCIE, PHY_MODE_PCIE_BIFURCATION); + + ret = phy_init(rk_pcie->phy); + if (ret < 0) { + dev_err(dev, "fail to init phy\n"); + goto disable_clk; + } + + phy_power_on(rk_pcie->phy); + + reset_control_deassert(rk_pcie->rsts); + + ret = phy_calibrate(rk_pcie->phy); + if (ret) { + dev_err(dev, "phy lock failed\n"); + goto disable_phy; + } + + return 0; + +disable_phy: + phy_power_off(rk_pcie->phy); + phy_exit(rk_pcie->phy); +disable_clk: + clk_bulk_disable_unprepare(rk_pcie->clk_cnt, rk_pcie->clks); +disable_vpcie3v3: + reset_control_assert(rk_pcie->rsts); + rk_pcie_disable_power(rk_pcie); + + return ret; +} + +static int rk_pcie_hardware_io_unconfig(struct rk_pcie *rk_pcie) +{ + phy_power_off(rk_pcie->phy); + phy_exit(rk_pcie->phy); + clk_bulk_disable_unprepare(rk_pcie->clk_cnt, rk_pcie->clks); + reset_control_assert(rk_pcie->rsts); + rk_pcie_disable_power(rk_pcie); + gpiod_set_value_cansleep(rk_pcie->rst_gpio, 0); + + return 0; +} + +static int rk_pcie_host_config(struct rk_pcie *rk_pcie) +{ + struct dw_pcie *pci = rk_pcie->pci; + u32 val; + + if (rk_pcie->is_lpbk) { + val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL); + val |= PORT_LINK_LPBK_ENABLE; + dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val); + } + + if (rk_pcie->is_comp && rk_pcie->comp_prst[0]) { + val = dw_pcie_readl_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS); + val |= BIT(4) | rk_pcie->comp_prst[0] | (rk_pcie->comp_prst[1] << 12); + dw_pcie_writel_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS, val); + } + + /* Enable RASDES Error event by default */ + val = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_VNDR); + if (!val) { + dev_err(pci->dev, "Unable to find RASDES CAP!\n"); + } else { + dw_pcie_writel_dbi(pci, val + 8, 0x1c); + dw_pcie_writel_dbi(pci, val + 8, 0x3); + rk_pcie->have_rasdes = true; + } + + dw_pcie_dbi_ro_wr_en(pci); + + rk_pcie_fast_link_setup(rk_pcie); + + rk_pcie_set_power_limit(rk_pcie); + + rk_pcie_set_rc_mode(rk_pcie); + + rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK_LEGACY, + rk_pcie->intx | 0xffff0000); + + return 0; +} + +static int rk_pcie_host_unconfig(struct rk_pcie *rk_pcie) +{ + return 0; +} + static int rk_pcie_really_probe(void *p) { struct platform_device *pdev = p; @@ -1460,7 +1583,6 @@ static int rk_pcie_really_probe(void *p) int ret; const struct of_device_id *match; const struct rk_pcie_of_data *data; - u32 val; /* 1. resource initialization */ match = of_match_device(rk_pcie_of_match, dev); @@ -1499,93 +1621,26 @@ static int rk_pcie_really_probe(void *p) } /* 4. hardware io settings */ - if (!IS_ERR_OR_NULL(rk_pcie->prsnt_gpio)) { - if (!gpiod_get_value(rk_pcie->prsnt_gpio)) { - dev_info(dev, "device isn't present\n"); - ret = -ENODEV; - goto release_driver; - } - } - - ret = rk_pcie_enable_power(rk_pcie); - if (ret) + ret = rk_pcie_hardware_io_config(rk_pcie); + if (ret) { + dev_err_probe(dev, ret, "setting hardware io failed\n"); goto release_driver; + } pm_runtime_enable(dev); pm_runtime_get_sync(pci->dev); - reset_control_assert(rk_pcie->rsts); - udelay(10); - - ret = clk_bulk_prepare_enable(rk_pcie->clk_cnt, rk_pcie->clks); - if (ret) { - dev_err_probe(dev, ret, "clock init failed\n"); - goto disable_vpcie3v3; - } - - ret = phy_set_mode_ext(rk_pcie->phy, PHY_MODE_PCIE, PHY_MODE_PCIE_RC); - if (ret) { - dev_err_probe(dev, ret, "fail to set phy to rc mode\n"); - goto disable_clk; - } - - if (rk_pcie->bifurcation) - phy_set_mode_ext(rk_pcie->phy, PHY_MODE_PCIE, PHY_MODE_PCIE_BIFURCATION); - - ret = phy_init(rk_pcie->phy); - if (ret < 0) { - dev_err_probe(dev, ret, "fail to init phy\n"); - goto disable_clk; - } - - phy_power_on(rk_pcie->phy); - - reset_control_deassert(rk_pcie->rsts); - - ret = phy_calibrate(rk_pcie->phy); - if (ret) { - dev_err(dev, "phy lock failed\n"); - goto disable_phy; - } - /* 5. host registers manipulation */ - if (rk_pcie->is_lpbk) { - val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL); - val |= PORT_LINK_LPBK_ENABLE; - dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val); + ret = rk_pcie_host_config(rk_pcie); + if (ret) { + dev_err_probe(dev, ret, "host registers manipulation failed\n"); + goto unconfig_hardware_io; } - if (rk_pcie->is_comp && rk_pcie->comp_prst[0]) { - val = dw_pcie_readl_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS); - val |= BIT(4) | rk_pcie->comp_prst[0] | (rk_pcie->comp_prst[1] << 12); - dw_pcie_writel_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS, val); - } - - /* Enable RASDES Error event by default */ - val = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_VNDR); - if (!val) { - dev_err(pci->dev, "Unable to find RASDES CAP!\n"); - } else { - dw_pcie_writel_dbi(pci, val + 8, 0x1c); - dw_pcie_writel_dbi(pci, val + 8, 0x3); - rk_pcie->have_rasdes = true; - } - - dw_pcie_dbi_ro_wr_en(pci); - - rk_pcie_fast_link_setup(rk_pcie); - - rk_pcie_set_power_limit(rk_pcie); - - rk_pcie_set_rc_mode(rk_pcie); - - rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK_LEGACY, - rk_pcie->intx | 0xffff0000); - /* 6. software process */ ret = rk_pcie_init_irq_and_wq(rk_pcie, pdev); if (ret) - goto disable_phy; + goto unconfig_host; ret = rk_add_pcie_port(rk_pcie, pdev); @@ -1633,15 +1688,12 @@ deinit_irq_and_wq: destroy_workqueue(rk_pcie->hot_rst_wq); if (rk_pcie->irq_domain) irq_domain_remove(rk_pcie->irq_domain); -disable_phy: - phy_power_off(rk_pcie->phy); - phy_exit(rk_pcie->phy); -disable_clk: - clk_bulk_disable_unprepare(rk_pcie->clk_cnt, rk_pcie->clks); -disable_vpcie3v3: +unconfig_host: + rk_pcie_host_unconfig(rk_pcie); +unconfig_hardware_io: pm_runtime_put(dev); pm_runtime_disable(dev); - rk_pcie_disable_power(rk_pcie); + rk_pcie_hardware_io_unconfig(rk_pcie); release_driver: if (rk_pcie) rk_pcie->finish_probe = true; @@ -1715,14 +1767,12 @@ static int rk_pcie_remove(struct platform_device *pdev) } device_init_wakeup(dev, false); + + rk_pcie_host_unconfig(rk_pcie); + pm_runtime_put(dev); pm_runtime_disable(dev); - phy_power_off(rk_pcie->phy); - phy_exit(rk_pcie->phy); - clk_bulk_disable_unprepare(rk_pcie->clk_cnt, rk_pcie->clks); - reset_control_assert(rk_pcie->rsts); - rk_pcie_disable_power(rk_pcie); - gpiod_set_value_cansleep(rk_pcie->rst_gpio, 0); + rk_pcie_hardware_io_unconfig(rk_pcie); return 0; } @@ -1904,18 +1954,13 @@ no_l2: /* make sure assert phy success */ usleep_range(200, 300); - phy_power_off(rk_pcie->phy); - phy_exit(rk_pcie->phy); - rk_pcie->intx = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_INTR_MASK_LEGACY); - clk_bulk_disable_unprepare(rk_pcie->clk_cnt, rk_pcie->clks); + rk_pcie_host_unconfig(rk_pcie); + rk_pcie_hardware_io_unconfig(rk_pcie); rk_pcie->in_suspend = true; - gpiod_set_value_cansleep(rk_pcie->rst_gpio, 0); - ret = rk_pcie_disable_power(rk_pcie); - return ret; } @@ -1923,77 +1968,29 @@ static int __maybe_unused rockchip_dw_pcie_resume(struct device *dev) { struct rk_pcie *rk_pcie = dev_get_drvdata(dev); struct dw_pcie *pci = rk_pcie->pci; - u32 val; int ret; - ret = rk_pcie_enable_power(rk_pcie); - if (ret) + /* 4. hardware io settings */ + ret = rk_pcie_hardware_io_config(rk_pcie); + if (ret) { + dev_err(dev, "setting hardware io failed, ret=%d\n", ret); return ret; + } - pm_runtime_enable(dev); - pm_runtime_get_sync(pci->dev); - - reset_control_assert(rk_pcie->rsts); - udelay(10); - - ret = clk_bulk_prepare_enable(rk_pcie->clk_cnt, rk_pcie->clks); + /* 5. host registers manipulation */ + ret = rk_pcie_host_config(rk_pcie); if (ret) { - dev_err(dev, "failed to prepare enable pcie bulk clks: %d\n", ret); - goto disable_vpcie3v3; + dev_err(dev, "host registers manipulation failed, ret=%d\n", ret); + goto unconfig_hardware_io; } - ret = phy_set_mode_ext(rk_pcie->phy, PHY_MODE_PCIE, PHY_MODE_PCIE_RC); - if (ret) { - dev_err(dev, "fail to set phy to rc mode, err %d\n", ret); - goto disable_clk; - } - - if (rk_pcie->bifurcation) - phy_set_mode_ext(rk_pcie->phy, PHY_MODE_PCIE, PHY_MODE_PCIE_BIFURCATION); - - ret = phy_init(rk_pcie->phy); - if (ret < 0) { - dev_err(dev, "fail to init phy, err %d\n", ret); - goto disable_clk; - } - - phy_power_on(rk_pcie->phy); - - reset_control_deassert(rk_pcie->rsts); - - ret = phy_calibrate(rk_pcie->phy); - if (ret) { - dev_err(dev, "phy lock failed\n"); - goto disable_phy; - } - - /* Enable RASDES Error event by default */ - val = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_VNDR); - if (!val) { - dev_err(pci->dev, "Unable to find RASDES CAP!\n"); - } else { - dw_pcie_writel_dbi(pci, val + 8, 0x1c); - dw_pcie_writel_dbi(pci, val + 8, 0x3); - rk_pcie->have_rasdes = true; - } - - dw_pcie_dbi_ro_wr_en(pci); - - rk_pcie_fast_link_setup(rk_pcie); - - rk_pcie_set_power_limit(rk_pcie); - - rk_pcie_set_rc_mode(rk_pcie); - - rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK_LEGACY, - rk_pcie->intx | 0xffff0000); - + /* 6. software process */ dw_pcie_setup_rc(&pci->pp); ret = rk_pcie_establish_link(pci); if (ret) { - dev_err(dev, "failed to establish pcie link\n"); - goto disable_phy; + dev_err(dev, "failed to establish pcie link, ret=%d\n", ret); + goto unconfig_host; } /* Disable BAR0 BAR1 */ @@ -2006,15 +2003,11 @@ static int __maybe_unused rockchip_dw_pcie_resume(struct device *dev) device_init_wakeup(dev, true); return 0; -disable_phy: - phy_power_off(rk_pcie->phy); - phy_exit(rk_pcie->phy); -disable_clk: - clk_bulk_disable_unprepare(rk_pcie->clk_cnt, rk_pcie->clks); -disable_vpcie3v3: - pm_runtime_put(dev); - pm_runtime_disable(dev); - rk_pcie_disable_power(rk_pcie); + +unconfig_host: + rk_pcie_host_unconfig(rk_pcie); +unconfig_hardware_io: + rk_pcie_hardware_io_unconfig(rk_pcie); return ret; }