]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
PCI: iproc: Fix PCIe reset logic
authorRay Jui <rjui@broadcom.com>
Wed, 16 Sep 2015 00:39:18 +0000 (17:39 -0700)
committerBjorn Helgaas <bhelgaas@google.com>
Fri, 25 Sep 2015 23:13:04 +0000 (18:13 -0500)
The current reset logic does not always properly reset the device.  For
example, in the case when the perst_b signal is already de-asserted in the
bootloader, the current reset logic fails to trigger a proper assert ->
de-assert reset sequence.

Fix the issue by always triggering the proper reset sequence.

Also explicitly select the desired reset source, i.e., perst_b, and reduce
the wait time after the device comes out of reset from 250 ms to 100 ms,
based on recommendation from the ASIC team.

Tested-by: Vladimir Dreizin <vdreizin@broadcom.com>
Tested-by: Darren Edamura <dedamura@broadcom.com>
Signed-off-by: Ray Jui <rjui@broadcom.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Vladimir Dreizin <vdreizin@broadcom.com>
Reviewed-by: Trac Hoang <trhoang@broadcom.com>
Reviewed-by: Scott Branden <sbranden@broadcom.com>
drivers/pci/host/pcie-iproc.c

index 52e7ff22d7eafb2037f9c3a04380d6f98b63f8b1..80e0541548a15a47afb98aa5732504f878416845 100644 (file)
@@ -31,6 +31,8 @@
 #include "pcie-iproc.h"
 
 #define CLK_CONTROL_OFFSET           0x000
+#define EP_PERST_SOURCE_SELECT_SHIFT 2
+#define EP_PERST_SOURCE_SELECT       BIT(EP_PERST_SOURCE_SELECT_SHIFT)
 #define EP_MODE_SURVIVE_PERST_SHIFT  1
 #define EP_MODE_SURVIVE_PERST        BIT(EP_MODE_SURVIVE_PERST_SHIFT)
 #define RC_PCIE_RST_OUTPUT_SHIFT     0
@@ -119,15 +121,18 @@ static void iproc_pcie_reset(struct iproc_pcie *pcie)
        u32 val;
 
        /*
-        * Configure the PCIe controller as root complex and send a downstream
-        * reset
+        * Select perst_b signal as reset source. Put the device into reset,
+        * and then bring it out of reset
         */
-       val = EP_MODE_SURVIVE_PERST | RC_PCIE_RST_OUTPUT;
+       val = readl(pcie->base + CLK_CONTROL_OFFSET);
+       val &= ~EP_PERST_SOURCE_SELECT & ~EP_MODE_SURVIVE_PERST &
+               ~RC_PCIE_RST_OUTPUT;
        writel(val, pcie->base + CLK_CONTROL_OFFSET);
        udelay(250);
-       val &= ~EP_MODE_SURVIVE_PERST;
+
+       val |= RC_PCIE_RST_OUTPUT;
        writel(val, pcie->base + CLK_CONTROL_OFFSET);
-       msleep(250);
+       msleep(100);
 }
 
 static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)