mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user