From 75d336c1651af429f12f2a89fb030a209a994946 Mon Sep 17 00:00:00 2001 From: Andrejs Cainikovs Date: Sat, 5 Feb 2022 14:56:28 +0100 Subject: pci: pci-imx6: fix PERST# start-up sequence According to the PCI-E standard the PERST# signal (reset-gpio in fsl,imx6* compatible dts) should be kept asserted for at least 100 usec before the PCI-E refclock is stable, should be kept asserted for at least 100ms after the power rails are stable and the host should wait at least 100 msec after it is de-asserted before accessing the configuration space of any attached device. From PCI Express Card Electromechanical Specification T-PVPERL: Power stable to PERST# inactive - 100 msec T-PERST-CLK: REFCLK stable before PERST# inactive 100 usec. From PCI Express Base Specification: To allow components to perform internal initialization, system software must wait for at least 100 ms from the end of a Conventional Reset of one or more devices before it is permitted to issue Configuration Requests to those devices Failure to do so could prevent PCI-E devices to be working correctly, and this was experienced with real devices. Signed-off-by: Andrejs Cainikovs --- drivers/pci/controller/dwc/pci-imx6.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 663f41df33ab..b130a9282101 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -1148,6 +1148,12 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) dev_err(dev, "failed to disable vpcie regulator: %d\n", ret); } + + /* Some boards don't have PCIe reset GPIO. */ + if (imx6_pcie->reset_gpiod) { + gpiod_set_value_cansleep(imx6_pcie->reset_gpiod, + !imx6_pcie->gpio_active_high); + } } static void imx6_pcie_set_l1_latency(struct imx6_pcie *imx6_pcie) @@ -1223,16 +1229,6 @@ static int imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) break; } - /* Some boards don't have PCIe reset GPIO. */ - if (imx6_pcie->reset_gpiod) { - gpiod_set_value_cansleep(imx6_pcie->reset_gpiod, - !imx6_pcie->gpio_active_high); - msleep(100); - gpiod_set_value_cansleep(imx6_pcie->reset_gpiod, - imx6_pcie->gpio_active_high); - msleep(20); - } - switch (imx6_pcie->drvdata->variant) { case IMX8QM: case IMX8QM_EP: @@ -1403,6 +1399,19 @@ static int imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) break; } + /* Some boards don't have PCIe reset GPIO. */ + if (imx6_pcie->reset_gpiod) { + msleep(100); + gpiod_set_value_cansleep(imx6_pcie->reset_gpiod, + imx6_pcie->gpio_active_high); + /* + * PCI Express Base Specification: + * A delay of at least 100ms is required after PERST# is + * de-asserted before issuing any Configuration Requests + */ + msleep(100); + } + return 0; err_pll: -- cgit v1.2.3