From bb01956344da904463870104d3a66ecfffea7c7a Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 3 Feb 2014 21:46:22 +0100 Subject: pci: mx6: Implement reset callback Add a callback so that a board can implement it's own specific routine to toggle the port's #PERST line or #define a GPIO to do so. Signed-off-by: Marek Vasut --- drivers/pci/pcie_imx.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/drivers/pci/pcie_imx.c b/drivers/pci/pcie_imx.c index 0a74867b12..34377e90bd 100644 --- a/drivers/pci/pcie_imx.c +++ b/drivers/pci/pcie_imx.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -450,6 +451,47 @@ static int imx6_pcie_init_phy(void) return 0; } +__weak int imx6_pcie_toggle_reset(void) +{ + /* + * See 'PCI EXPRESS BASE SPECIFICATION, REV 3.0, SECTION 6.6.1' + * for detailed understanding of the PCIe CR reset logic. + * + * The PCIe #PERST reset line _MUST_ be connected, otherwise your + * design does not conform to the specification. You must wait at + * least 20 mS after de-asserting the #PERST so the EP device can + * do self-initialisation. + * + * In case your #PERST pin is connected to a plain GPIO pin of the + * CPU, you can define CONFIG_PCIE_IMX_PERST_GPIO in your board's + * configuration file and the condition below will handle the rest + * of the reset toggling. + * + * In case your #PERST toggling logic is more complex, for example + * connected via CPLD or somesuch, you can override this function + * in your board file and implement reset logic as needed. You must + * not forget to wait at least 20 mS after de-asserting #PERST in + * this case either though. + * + * In case your #PERST line of the PCIe EP device is not connected + * at all, your design is broken and you should fix your design, + * otherwise you will observe problems like for example the link + * not coming up after rebooting the system back from running Linux + * that uses the PCIe as well OR the PCIe link might not come up in + * Linux at all in the first place since it's in some non-reset + * state due to being previously used in U-Boot. + */ +#ifdef CONFIG_PCIE_IMX_PERST_GPIO + gpio_direction_output(CONFIG_PCIE_IMX_PERST_GPIO, 0); + mdelay(20); + gpio_set_value(CONFIG_PCIE_IMX_PERST_GPIO, 1); + mdelay(20); +#else + puts("WARNING: Make sure the PCIe #PERST line is connected!\n"); +#endif + return 0; +} + static int imx6_pcie_deassert_core_reset(void) { struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; @@ -466,10 +508,9 @@ static int imx6_pcie_deassert_core_reset(void) * Wait for the clock to settle a bit, when the clock are sourced * from the CPU, we need about 30mS to settle. */ - mdelay(30); + mdelay(50); - /* FIXME: GPIO reset goes here */ - mdelay(100); + imx6_pcie_toggle_reset(); return 0; } -- cgit