summaryrefslogtreecommitdiff
path: root/drivers/pci/host/pci-imx6.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/host/pci-imx6.c')
-rw-r--r--drivers/pci/host/pci-imx6.c40
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)) {