@@ -183,8 +183,6 @@ static int dra7xx_pcie_host_init(struct pcie_port *pp)
dw_pcie_setup_rc(pp);
- dra7xx_pcie_establish_link(pci);
- dw_pcie_wait_for_link(pci);
dw_pcie_msi_init(pp);
dra7xx_pcie_enable_interrupts(dra7xx);
@@ -229,30 +229,9 @@ static void exynos_pcie_assert_reset(struct exynos_pcie *ep)
GPIOF_OUT_INIT_HIGH, "RESET");
}
-static int exynos_pcie_establish_link(struct exynos_pcie *ep)
+static int exynos_pcie_start_link(struct dw_pcie *pci)
{
- struct dw_pcie *pci = ep->pci;
- struct pcie_port *pp = &pci->pp;
- struct device *dev = pci->dev;
-
- if (dw_pcie_link_up(pci)) {
- dev_err(dev, "Link already up\n");
- return 0;
- }
-
- exynos_pcie_assert_core_reset(ep);
-
- phy_reset(ep->phy);
-
- exynos_pcie_writel(ep->mem_res->elbi_base, 1,
- PCIE_PWR_RESET);
-
- phy_power_on(ep->phy);
- phy_init(ep->phy);
-
- exynos_pcie_deassert_core_reset(ep);
- dw_pcie_setup_rc(pp);
- exynos_pcie_assert_reset(ep);
+ struct exynos_pcie *ep = to_exynos_pcie(pci);
/* assert LTSSM enable */
exynos_pcie_writel(ep->mem_res->elbi_base, PCIE_ELBI_LTSSM_ENABLE,
@@ -386,7 +365,20 @@ static int exynos_pcie_host_init(struct pcie_port *pp)
pp->bridge->ops = &exynos_pci_ops;
- exynos_pcie_establish_link(ep);
+ exynos_pcie_assert_core_reset(ep);
+
+ phy_reset(ep->phy);
+
+ exynos_pcie_writel(ep->mem_res->elbi_base, 1,
+ PCIE_PWR_RESET);
+
+ phy_power_on(ep->phy);
+ phy_init(ep->phy);
+
+ exynos_pcie_deassert_core_reset(ep);
+ dw_pcie_setup_rc(pp);
+ exynos_pcie_assert_reset(ep);
+
exynos_pcie_enable_interrupts(ep);
return 0;
@@ -430,6 +422,7 @@ static const struct dw_pcie_ops dw_pcie_ops = {
.read_dbi = exynos_pcie_read_dbi,
.write_dbi = exynos_pcie_write_dbi,
.link_up = exynos_pcie_link_up,
+ .start_link = exynos_pcie_start_link,
};
static int __init exynos_pcie_probe(struct platform_device *pdev)
@@ -745,9 +745,9 @@ static void imx6_pcie_ltssm_enable(struct device *dev)
}
}
-static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
+static int imx6_pcie_start_link(struct dw_pcie *pci)
{
- struct dw_pcie *pci = imx6_pcie->pci;
+ struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
struct device *dev = pci->dev;
u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
u32 tmp;
@@ -835,7 +835,6 @@ static int imx6_pcie_host_init(struct pcie_port *pp)
imx6_pcie_deassert_core_reset(imx6_pcie);
imx6_setup_phy_mpll(imx6_pcie);
dw_pcie_setup_rc(pp);
- imx6_pcie_establish_link(imx6_pcie);
dw_pcie_msi_init(pp);
return 0;
@@ -865,7 +864,7 @@ static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,
}
static const struct dw_pcie_ops dw_pcie_ops = {
- /* No special ops needed, but pcie-designware still expects this struct */
+ .start_link = imx6_pcie_start_link,
};
#ifdef CONFIG_PM_SLEEP
@@ -974,7 +973,7 @@ static int imx6_pcie_resume_noirq(struct device *dev)
imx6_pcie_deassert_core_reset(imx6_pcie);
dw_pcie_setup_rc(pp);
- ret = imx6_pcie_establish_link(imx6_pcie);
+ ret = imx6_pcie_start_link(imx6_pcie->pci);
if (ret < 0)
dev_info(dev, "pcie link is down after resume.\n");
@@ -511,14 +511,8 @@ static void ks_pcie_stop_link(struct dw_pcie *pci)
static int ks_pcie_start_link(struct dw_pcie *pci)
{
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
- struct device *dev = pci->dev;
u32 val;
- if (dw_pcie_link_up(pci)) {
- dev_dbg(dev, "link is already up\n");
- return 0;
- }
-
/* Initiate Link Training */
val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
ks_pcie_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);
@@ -833,9 +827,6 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)
"Asynchronous external abort");
#endif
- ks_pcie_start_link(pci);
- dw_pcie_wait_for_link(pci);
-
return 0;
}
@@ -231,7 +231,7 @@ static void meson_pcie_assert_reset(struct meson_pcie *mp)
gpiod_set_value_cansleep(mp->reset_gpio, 0);
}
-static void meson_pcie_init_dw(struct meson_pcie *mp)
+static void meson_pcie_ltssm_enable(struct meson_pcie *mp)
{
u32 val;
@@ -289,20 +289,14 @@ static void meson_set_max_rd_req_size(struct meson_pcie *mp, int size)
dw_pcie_writel_dbi(pci, offset + PCI_EXP_DEVCTL, val);
}
-static int meson_pcie_establish_link(struct meson_pcie *mp)
+static int meson_pcie_start_link(struct dw_pcie *pci)
{
- struct dw_pcie *pci = &mp->pci;
- struct pcie_port *pp = &pci->pp;
-
- meson_pcie_init_dw(mp);
- meson_set_max_payload(mp, MAX_PAYLOAD_SIZE);
- meson_set_max_rd_req_size(mp, MAX_READ_REQ_SIZE);
-
- dw_pcie_setup_rc(pp);
+ struct meson_pcie *mp = to_meson_pcie(pci);
+ meson_pcie_ltssm_enable(mp);
meson_pcie_assert_reset(mp);
- return dw_pcie_wait_for_link(pci);
+ return 0;
}
static int meson_pcie_rd_own_conf(struct pci_bus *bus, u32 devfn,
@@ -380,14 +374,13 @@ static int meson_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct meson_pcie *mp = to_meson_pcie(pci);
- int ret;
pp->bridge->ops = &meson_pci_ops;
- ret = meson_pcie_establish_link(mp);
- if (ret)
- return ret;
+ meson_set_max_payload(mp, MAX_PAYLOAD_SIZE);
+ meson_set_max_rd_req_size(mp, MAX_READ_REQ_SIZE);
+ dw_pcie_setup_rc(pp);
dw_pcie_msi_init(pp);
return 0;
@@ -418,6 +411,7 @@ static int meson_add_pcie_port(struct meson_pcie *mp,
static const struct dw_pcie_ops dw_pcie_ops = {
.link_up = meson_pcie_link_up,
+ .start_link = meson_pcie_start_link,
};
static int meson_pcie_probe(struct platform_device *pdev)
@@ -154,10 +154,24 @@ static int armada8k_pcie_link_up(struct dw_pcie *pci)
return 0;
}
-static void armada8k_pcie_establish_link(struct armada8k_pcie *pcie)
+static int armada8k_pcie_start_link(struct dw_pcie *pci)
+{
+ u32 reg;
+
+ /* Start LTSSM */
+ reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG);
+ reg |= PCIE_APP_LTSSM_EN;
+ dw_pcie_writel_dbi(pci, PCIE_GLOBAL_CONTROL_REG, reg);
+
+ return 0;
+}
+
+static int armada8k_pcie_host_init(struct pcie_port *pp)
{
- struct dw_pcie *pci = pcie->pci;
u32 reg;
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+
+ dw_pcie_setup_rc(pp);
if (!dw_pcie_link_up(pci)) {
/* Disable LTSSM state machine to enable configuration */
@@ -193,26 +207,6 @@ static void armada8k_pcie_establish_link(struct armada8k_pcie *pcie)
PCIE_INT_C_ASSERT_MASK | PCIE_INT_D_ASSERT_MASK;
dw_pcie_writel_dbi(pci, PCIE_GLOBAL_INT_MASK1_REG, reg);
- if (!dw_pcie_link_up(pci)) {
- /* Configuration done. Start LTSSM */
- reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG);
- reg |= PCIE_APP_LTSSM_EN;
- dw_pcie_writel_dbi(pci, PCIE_GLOBAL_CONTROL_REG, reg);
- }
-
- /* Wait until the link becomes active again */
- if (dw_pcie_wait_for_link(pci))
- dev_err(pci->dev, "Link not up after reconfiguration\n");
-}
-
-static int armada8k_pcie_host_init(struct pcie_port *pp)
-{
- struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
- struct armada8k_pcie *pcie = to_armada8k_pcie(pci);
-
- dw_pcie_setup_rc(pp);
- armada8k_pcie_establish_link(pcie);
-
return 0;
}
@@ -269,6 +263,7 @@ static int armada8k_add_pcie_port(struct armada8k_pcie *pcie,
static const struct dw_pcie_ops dw_pcie_ops = {
.link_up = armada8k_pcie_link_up,
+ .start_link = armada8k_pcie_start_link,
};
static int armada8k_pcie_probe(struct platform_device *pdev)
@@ -329,8 +329,6 @@ static int artpec6_pcie_host_init(struct pcie_port *pp)
artpec6_pcie_deassert_core_reset(artpec6_pcie);
artpec6_pcie_wait_for_phy(artpec6_pcie);
dw_pcie_setup_rc(pp);
- artpec6_pcie_establish_link(pci);
- dw_pcie_wait_for_link(pci);
dw_pcie_msi_init(pp);
return 0;
@@ -423,6 +423,15 @@ int dw_pcie_host_init(struct pcie_port *pp)
goto err_free_msi;
}
+ if (!dw_pcie_link_up(pci) && pci->ops->start_link) {
+ ret = pci->ops->start_link(pci);
+ if (ret)
+ goto err_free_msi;
+ }
+
+ /* Ignore errors, the link may come up later */
+ dw_pcie_wait_for_link(pci);
+
bridge->sysdata = pp;
ret = pci_host_probe(bridge);
@@ -35,10 +35,7 @@ static const struct of_device_id dw_plat_pcie_of_match[];
static int dw_plat_pcie_host_init(struct pcie_port *pp)
{
- struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-
dw_pcie_setup_rc(pp);
- dw_pcie_wait_for_link(pci);
dw_pcie_msi_init(pp);
return 0;
@@ -169,39 +169,36 @@ static int histb_pcie_link_up(struct dw_pcie *pci)
return 0;
}
-static int histb_pcie_establish_link(struct pcie_port *pp)
+static int histb_pcie_start_link(struct dw_pcie *pci)
{
- struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct histb_pcie *hipcie = to_histb_pcie(pci);
u32 regval;
- if (dw_pcie_link_up(pci)) {
- dev_info(pci->dev, "Link already up\n");
- return 0;
- }
-
- /* PCIe RC work mode */
- regval = histb_pcie_readl(hipcie, PCIE_SYS_CTRL0);
- regval &= ~PCIE_DEVICE_TYPE_MASK;
- regval |= PCIE_WM_RC;
- histb_pcie_writel(hipcie, PCIE_SYS_CTRL0, regval);
-
- /* setup root complex */
- dw_pcie_setup_rc(pp);
-
/* assert LTSSM enable */
regval = histb_pcie_readl(hipcie, PCIE_SYS_CTRL7);
regval |= PCIE_APP_LTSSM_ENABLE;
histb_pcie_writel(hipcie, PCIE_SYS_CTRL7, regval);
- return dw_pcie_wait_for_link(pci);
+ return 0;
}
static int histb_pcie_host_init(struct pcie_port *pp)
{
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct histb_pcie *hipcie = to_histb_pcie(pci);
+ u32 regval;
+
pp->bridge->ops = &histb_pci_ops;
- histb_pcie_establish_link(pp);
+ /* PCIe RC work mode */
+ regval = histb_pcie_readl(hipcie, PCIE_SYS_CTRL0);
+ regval &= ~PCIE_DEVICE_TYPE_MASK;
+ regval |= PCIE_WM_RC;
+ histb_pcie_writel(hipcie, PCIE_SYS_CTRL0, regval);
+
+ /* setup root complex */
+ dw_pcie_setup_rc(pp);
+
dw_pcie_msi_init(pp);
return 0;
@@ -300,6 +297,7 @@ static const struct dw_pcie_ops dw_pcie_ops = {
.read_dbi = histb_pcie_read_dbi,
.write_dbi = histb_pcie_write_dbi,
.link_up = histb_pcie_link_up,
+ .start_link = histb_pcie_start_link,
};
static int histb_pcie_probe(struct platform_device *pdev)
@@ -390,32 +390,14 @@ static int kirin_pcie_link_up(struct dw_pcie *pci)
return 0;
}
-static int kirin_pcie_establish_link(struct pcie_port *pp)
+static int kirin_pcie_start_link(struct dw_pcie *pci)
{
- struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct kirin_pcie *kirin_pcie = to_kirin_pcie(pci);
- struct device *dev = kirin_pcie->pci->dev;
- int count = 0;
-
- if (kirin_pcie_link_up(pci))
- return 0;
-
- dw_pcie_setup_rc(pp);
/* assert LTSSM enable */
kirin_apb_ctrl_writel(kirin_pcie, PCIE_LTSSM_ENABLE_BIT,
PCIE_APP_LTSSM_ENABLE);
- /* check if the link is up or not */
- while (!kirin_pcie_link_up(pci)) {
- usleep_range(LINK_WAIT_MIN, LINK_WAIT_MAX);
- count++;
- if (count == 1000) {
- dev_err(dev, "Link Fail\n");
- return -EINVAL;
- }
- }
-
return 0;
}
@@ -423,7 +405,7 @@ static int kirin_pcie_host_init(struct pcie_port *pp)
{
pp->bridge->ops = &kirin_pci_ops;
- kirin_pcie_establish_link(pp);
+ dw_pcie_setup_rc(pp);
dw_pcie_msi_init(pp);
return 0;
@@ -433,6 +415,7 @@ static const struct dw_pcie_ops kirin_dw_pcie_ops = {
.read_dbi = kirin_pcie_read_dbi,
.write_dbi = kirin_pcie_write_dbi,
.link_up = kirin_pcie_link_up,
+ .start_link = kirin_pcie_start_link,
};
static const struct dw_pcie_host_ops kirin_pcie_host_ops = {
@@ -207,18 +207,15 @@ static void qcom_ep_reset_deassert(struct qcom_pcie *pcie)
usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500);
}
-static int qcom_pcie_establish_link(struct qcom_pcie *pcie)
+static int qcom_pcie_start_link(struct dw_pcie *pci)
{
- struct dw_pcie *pci = pcie->pci;
-
- if (dw_pcie_link_up(pci))
- return 0;
+ struct qcom_pcie *pcie = to_qcom_pcie(pci);
/* Enable Link Training state machine */
if (pcie->ops->ltssm_enable)
pcie->ops->ltssm_enable(pcie);
- return dw_pcie_wait_for_link(pci);
+ return 0;
}
static void qcom_pcie_2_1_0_ltssm_enable(struct qcom_pcie *pcie)
@@ -1288,15 +1285,8 @@ static int qcom_pcie_host_init(struct pcie_port *pp)
qcom_ep_reset_deassert(pcie);
- ret = qcom_pcie_establish_link(pcie);
- if (ret)
- goto err;
-
return 0;
-err:
- qcom_ep_reset_assert(pcie);
- if (pcie->ops->post_deinit)
- pcie->ops->post_deinit(pcie);
+
err_disable_phy:
phy_power_off(pcie->phy);
err_deinit:
@@ -1363,6 +1353,7 @@ static const struct qcom_pcie_ops ops_2_7_0 = {
static const struct dw_pcie_ops dw_pcie_ops = {
.link_up = qcom_pcie_link_up,
+ .start_link = qcom_pcie_start_link,
};
static int qcom_pcie_probe(struct platform_device *pdev)
@@ -66,32 +66,10 @@ struct pcie_app_reg {
#define to_spear13xx_pcie(x) dev_get_drvdata((x)->dev)
-static int spear13xx_pcie_establish_link(struct spear13xx_pcie *spear13xx_pcie)
+static int spear13xx_pcie_start_link(struct dw_pcie *pci)
{
- struct dw_pcie *pci = spear13xx_pcie->pci;
- struct pcie_port *pp = &pci->pp;
+ struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci);
struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
- u32 val;
- u32 exp_cap_off = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
-
- if (dw_pcie_link_up(pci)) {
- dev_err(pci->dev, "link already up\n");
- return 0;
- }
-
- dw_pcie_setup_rc(pp);
-
- /*
- * this controller support only 128 bytes read size, however its
- * default value in capability register is 512 bytes. So force
- * it to 128 here.
- */
- val = dw_pcie_readw_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL);
- val &= ~PCI_EXP_DEVCTL_READRQ;
- dw_pcie_writew_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL, val);
-
- dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, 0x104A);
- dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, 0xCD80);
/* enable ltssm */
writel(DEVICE_TYPE_RC | (1 << MISCTRL_EN_ID)
@@ -99,7 +77,7 @@ static int spear13xx_pcie_establish_link(struct spear13xx_pcie *spear13xx_pcie)
| ((u32)1 << REG_TRANSLATION_ENABLE),
&app_reg->app_ctrl_0);
- return dw_pcie_wait_for_link(pci);
+ return 0;
}
static irqreturn_t spear13xx_pcie_irq_handler(int irq, void *arg)
@@ -151,10 +129,25 @@ static int spear13xx_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci);
+ u32 exp_cap_off = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+ u32 val;
spear13xx_pcie->app_base = pci->dbi_base + 0x2000;
- spear13xx_pcie_establish_link(spear13xx_pcie);
+ dw_pcie_setup_rc(pp);
+
+ /*
+ * this controller support only 128 bytes read size, however its
+ * default value in capability register is 512 bytes. So force
+ * it to 128 here.
+ */
+ val = dw_pcie_readw_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL);
+ val &= ~PCI_EXP_DEVCTL_READRQ;
+ dw_pcie_writew_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL, val);
+
+ dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, 0x104A);
+ dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, 0xCD80);
+
spear13xx_pcie_enable_interrupts(spear13xx_pcie);
return 0;
@@ -198,6 +191,7 @@ static int spear13xx_add_pcie_port(struct spear13xx_pcie *spear13xx_pcie,
static const struct dw_pcie_ops dw_pcie_ops = {
.link_up = spear13xx_pcie_link_up,
+ .start_link = spear13xx_pcie_start_link,
};
static int spear13xx_pcie_probe(struct platform_device *pdev)
@@ -1549,7 +1549,6 @@ static int tegra_pcie_deinit_controller(struct tegra_pcie_dw *pcie)
static int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie)
{
- struct pcie_port *pp = &pcie->pci.pp;
struct device *dev = pcie->dev;
char *name;
int ret;
@@ -146,16 +146,13 @@ static int uniphier_pcie_link_up(struct dw_pcie *pci)
return (val & mask) == mask;
}
-static int uniphier_pcie_establish_link(struct dw_pcie *pci)
+static int uniphier_pcie_start_link(struct dw_pcie *pci)
{
struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci);
- if (dw_pcie_link_up(pci))
- return 0;
-
uniphier_pcie_ltssm_enable(priv, true);
- return dw_pcie_wait_for_link(pci);
+ return 0;
}
static void uniphier_pcie_stop_link(struct dw_pcie *pci)
@@ -318,10 +315,6 @@ static int uniphier_pcie_host_init(struct pcie_port *pp)
uniphier_pcie_irq_enable(priv);
dw_pcie_setup_rc(pp);
- ret = uniphier_pcie_establish_link(pci);
- if (ret)
- return ret;
-
dw_pcie_msi_init(pp);
return 0;
@@ -385,7 +378,7 @@ static int uniphier_pcie_host_enable(struct uniphier_pcie_priv *priv)
}
static const struct dw_pcie_ops dw_pcie_ops = {
- .start_link = uniphier_pcie_establish_link,
+ .start_link = uniphier_pcie_start_link,
.stop_link = uniphier_pcie_stop_link,
.link_up = uniphier_pcie_link_up,
};