diff mbox series

[v3,1/5] pcie-rcar: poll PHYRDY in rcar_pcie_hw_init()

Message ID 89f4bb11-918a-397d-0dd8-5a6e630504f7@cogentembedded.com
State Accepted
Headers show
Series Add R8A77980 PCIe support & some driver cleanups | expand

Commit Message

Sergei Shtylyov May 3, 2018, 7:36 p.m. UTC
In  all the R-Car gen1/2/3 manuals, we are instructed to poll PCIEPHYSR
for PHYRDY=1  at  an early stage of the PCIEC initialization -- while
the driver only does this on R-Car H1 (polling a PHY specific register).
Add the PHYRDY polling to rcar_pcie_hw_init(). Note that without the
special PHY driver on the R-Car V3H (R8A77980) the PCIEC initialization
just freezes the kernel -- adding the PHYRDY polling allows the init code
to exit gracefully on timeout (PHY starts powered down after reset on this
SoC).

Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Reviewed-by: Simon Horman <horms+renesas@verge.net.au>

---
Changes in version 3:
- used the BIT() macro in #define PHYRDY;
- added the SoC model # to the patch description;
- added Rob's and Simon's tags;
- refreshed atop of Marek's patch.

 drivers/pci/host/pcie-rcar.c |   20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
diff mbox series

Patch

Index: pci/drivers/pci/host/pcie-rcar.c
===================================================================
--- pci.orig/drivers/pci/host/pcie-rcar.c
+++ pci/drivers/pci/host/pcie-rcar.c
@@ -37,6 +37,8 @@ 
 #define PCIECDR			0x000020
 #define PCIEMSR			0x000028
 #define PCIEINTXR		0x000400
+#define PCIEPHYSR		0x0007f0
+#define  PHYRDY			BIT(0)
 #define PCIEMSITXR		0x000840
 
 /* Transfer control */
@@ -527,6 +529,20 @@  static void phy_write_reg(struct rcar_pc
 	phy_wait_for_ack(pcie);
 }
 
+static int rcar_pcie_wait_for_phyrdy(struct rcar_pcie *pcie)
+{
+	unsigned int timeout = 10;
+
+	while (timeout--) {
+		if (rcar_pci_read_reg(pcie, PCIEPHYSR) & PHYRDY)
+			return 0;
+
+		msleep(5);
+	}
+
+	return -ETIMEDOUT;
+}
+
 static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
 {
 	unsigned int timeout = 10;
@@ -551,6 +567,10 @@  static int rcar_pcie_hw_init(struct rcar
 	/* Set mode */
 	rcar_pci_write_reg(pcie, 1, PCIEMSR);
 
+	err = rcar_pcie_wait_for_phyrdy(pcie);
+	if (err)
+		return err;
+
 	/*
 	 * Initial header for port config space is type 1, set the device
 	 * class to match. Hardware takes care of propagating the IDSETR