diff options
Diffstat (limited to 'drivers/pci/host')
-rw-r--r-- | drivers/pci/host/pci-imx6.c | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index c3cc315473ce..24d7ea634453 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -73,6 +73,7 @@ struct imx_pcie { int power_on_gpio; int reset_gpio; bool gpio_active_high; + int reset_ep_gpio; struct clk *pcie_bus; struct clk *pcie_inbound_axi; struct clk *pcie_phy; @@ -95,6 +96,7 @@ struct imx_pcie { struct regulator *pcie_phy_regulator; struct regulator *pcie_bus_regulator; struct regulator *epdev_on; + int force_detect_state; }; /* PCIe Root Complex registers (memory-mapped) */ @@ -495,11 +497,7 @@ static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie) if ((gpr1 & IMX6Q_GPR1_PCIE_REF_CLK_EN) && (gpr12 & IMX6Q_GPR12_PCIE_CTL_2)) { - val = dw_pcie_readl_rc(pp, PCIE_PL_PFLR); - val &= ~PCIE_PL_PFLR_LINK_STATE_MASK; - val |= PCIE_PL_PFLR_FORCE_LINK; - dw_pcie_writel_rc(pp, PCIE_PL_PFLR, val); - + imx_pcie->force_detect_state = 1; regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6Q_GPR12_PCIE_CTL_2, 0 << 10); } @@ -932,13 +930,22 @@ static int imx_pcie_deassert_core_reset(struct imx_pcie *imx_pcie) /* Some boards don't have PCIe reset GPIO. */ if (gpio_is_valid(imx_pcie->reset_gpio)) { + if (gpio_is_valid(imx_pcie->reset_ep_gpio)) + gpio_set_value_cansleep(imx_pcie->reset_ep_gpio, 1); gpio_set_value_cansleep(imx_pcie->reset_gpio, imx_pcie->gpio_active_high); mdelay(20); gpio_set_value_cansleep(imx_pcie->reset_gpio, !imx_pcie->gpio_active_high); - mdelay(20); + mdelay(1); + if (gpio_is_valid(imx_pcie->reset_ep_gpio)) + gpio_set_value_cansleep(imx_pcie->reset_ep_gpio, 0); + } else if (gpio_is_valid(imx_pcie->reset_ep_gpio)) { + gpio_set_value_cansleep(imx_pcie->reset_ep_gpio, 1); + mdelay(100); + gpio_set_value_cansleep(imx_pcie->reset_ep_gpio, 0); } + mdelay(20); if (ret == 0) return ret; @@ -1552,6 +1559,16 @@ static int imx_pcie_establish_link(struct imx_pcie *imx_pcie) goto out; } + if (imx_pcie->force_detect_state) { + u32 val; + + imx_pcie->force_detect_state = 0; + val = dw_pcie_readl_rc(pp, PCIE_PL_PFLR); + val &= ~PCIE_PL_PFLR_LINK_STATE_MASK; + val |= PCIE_PL_PFLR_FORCE_LINK; + dw_pcie_writel_rc(pp, PCIE_PL_PFLR, val); + } + /* * Start Directed Speed Change so the best possible speed both link * partners support can be negotiated. @@ -2330,6 +2347,17 @@ static int imx_pcie_probe(struct platform_device *pdev) } else if (imx_pcie->dis_gpio == -EPROBE_DEFER) { return imx_pcie->dis_gpio; } + imx_pcie->reset_ep_gpio = of_get_named_gpio(node, "reset-ep-gpio", 0); + if (gpio_is_valid(imx_pcie->reset_ep_gpio)) { + ret = devm_gpio_request_one(&pdev->dev, + imx_pcie->reset_ep_gpio, + GPIOF_OUT_INIT_HIGH, + "PCIe EP reset"); + if (ret) { + dev_err(&pdev->dev, "unable to get reset end point gpio\n"); + return ret; + } + } imx_pcie->power_on_gpio = of_get_named_gpio(node, "power-on-gpio", 0); if (gpio_is_valid(imx_pcie->power_on_gpio)) { |