> -----Original Message----- > From: Francesco Dolcini <francesco.dolcini@xxxxxxxxxxx> > Sent: 2022年2月15日 0:15 > To: Hongxing Zhu <hongxing.zhu@xxxxxxx>; Lucas Stach > <l.stach@xxxxxxxxxxxxxx>; Lorenzo Pieralisi <lorenzo.pieralisi@xxxxxxx>; Rob > Herring <robh@xxxxxxxxxx>; Krzysztof Wilczy?ski <kw@xxxxxxxxx>; > Pengutronix Kernel Team <kernel@xxxxxxxxxxxxxx>; Fabio Estevam > <festevam@xxxxxxxxx>; dl-linux-imx <linux-imx@xxxxxxx>; Bjorn Helgaas > <helgaas@xxxxxxxxxx> > Cc: Francesco Dolcini <francesco.dolcini@xxxxxxxxxxx>; Shawn Guo > <shawnguo@xxxxxxxxxx>; Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>; > linux-pci@xxxxxxxxxxxxxxx; linux-arm-kernel@xxxxxxxxxxxxxxxxxxx > Subject: [PATCH v2] PCI: imx6: Fix PERST# start-up sequence > > According to the PCIe standard the PERST# signal (reset-gpio in > fsl,imx* compatible dts) should be kept asserted for at least 100 usec before > the PCIe refclock is stable, should be kept asserted for at least 100 msec 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 PCIe CEM r2.0, sec 2.6.2 > > T-PVPERL: Power stable to PERST# inactive - 100 msec > T-PERST-CLK: REFCLK stable before PERST# inactive - 100 usec. > > From PCIe r5.0, sec 6.6.1 > > With a Downstream Port that does not support Link speeds greater than > 5.0 GT/s, software must wait a minimum of 100 ms before sending a > Configuration Request to the device immediately below that Port. > > Failure to do so could prevent PCIe devices to be working correctly, and this > was experienced with real devices. > > Move reset assert to imx6_pcie_assert_core_reset(), this way we ensure that > PERST# is asserted before enabling any clock, move de-assert to the end of > imx6_pcie_deassert_core_reset() after the clock is enabled and deemed stable > and add a new delay of 100 msec just afterward. > > Link: > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore.ker > nel.org%2Fall%2F20220211152550.286821-1-francesco.dolcini%40toradex.co > m&data=04%7C01%7Chongxing.zhu%40nxp.com%7C28939dcb78a8460f > c3db08d9efd538cb%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C > 637804521335664249%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAw > MDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&sda > ta=l7vjiJ3KuERmaWYMy09svELcUcI1ekLJPVKpt0AViTo%3D&reserved=0 > Fixes: bb38919ec56e ("PCI: imx6: Add support for i.MX6 PCIe controller") > Signed-off-by: Francesco Dolcini <francesco.dolcini@xxxxxxxxxxx> Thanks. Acked-by: Richard Zhu <hongxing.zhu@xxxxxxx> Best Regards Richard Zhu > --- > v2: Add complete reference to the PCIe standards, s/PCI-E/PCIe/g > --- > drivers/pci/controller/dwc/pci-imx6.c | 23 ++++++++++++++--------- > 1 file changed, 14 insertions(+), 9 deletions(-) > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c > b/drivers/pci/controller/dwc/pci-imx6.c > index 7b200b66114a..73baa2044ccf 100644 > --- a/drivers/pci/controller/dwc/pci-imx6.c > +++ b/drivers/pci/controller/dwc/pci-imx6.c > @@ -408,6 +408,11 @@ 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 (gpio_is_valid(imx6_pcie->reset_gpio)) > + gpio_set_value_cansleep(imx6_pcie->reset_gpio, > + imx6_pcie->gpio_active_high); > } > > static unsigned int imx6_pcie_grp_offset(const struct imx6_pcie *imx6_pcie) > @@ -544,15 +549,6 @@ static void imx6_pcie_deassert_core_reset(struct > imx6_pcie *imx6_pcie) > /* allow the clocks to stabilize */ > usleep_range(200, 500); > > - /* Some boards don't have PCIe reset GPIO. */ > - if (gpio_is_valid(imx6_pcie->reset_gpio)) { > - gpio_set_value_cansleep(imx6_pcie->reset_gpio, > - imx6_pcie->gpio_active_high); > - msleep(100); > - gpio_set_value_cansleep(imx6_pcie->reset_gpio, > - !imx6_pcie->gpio_active_high); > - } > - > switch (imx6_pcie->drvdata->variant) { > case IMX8MQ: > reset_control_deassert(imx6_pcie->pciephy_reset); > @@ -599,6 +595,15 @@ static void imx6_pcie_deassert_core_reset(struct > imx6_pcie *imx6_pcie) > break; > } > > + /* Some boards don't have PCIe reset GPIO. */ > + if (gpio_is_valid(imx6_pcie->reset_gpio)) { > + msleep(100); > + gpio_set_value_cansleep(imx6_pcie->reset_gpio, > + !imx6_pcie->gpio_active_high); > + /* Wait for 100ms after PERST# deassertion (PCIe r5.0, 6.6.1) */ > + msleep(100); > + } > + > return; > > err_ref_clk: > -- > 2.25.1