PCI: dw: rockchip: Define IO and Host initialization interfaces

Change-Id: I3491ee22e216d009aee2613de4b6f276c2154a72
Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
This commit is contained in:
Jon Lin
2024-10-28 10:36:44 +08:00
committed by Tao Huang
parent c37dff4abe
commit 7f84caccd0

View File

@@ -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;
}