Эх сурвалжийг харах

Merge branch 'lorenzo/pci/rcar'

  - clean up clocks, MSI, IRQ mappings in R-Car probe failure paths (Marek
    Vasut)

  - poll more frequently (5us vs 5ms) while waiting for R-Car data link
    active (Marek Vasut)

  - use generic OF parsing interface in R-Car (Vladimir Zapolskiy)

  - add R-Car V3H (R8A77980) "compatible" string (Sergei Shtylyov)

  - add R-Car gen3 PHY support (Sergei Shtylyov)

  - improve R-Car PHYRDY polling (Sergei Shtylyov)

  - clean up R-Car macros (Marek Vasut)

  - use runtime PM for R-Car controller clock (Dien Pham)

* lorenzo/pci/rcar:
  PCI: rcar: Remove IRQ mappings in rcar_pcie_enable_msi() failpath
  PCI: rcar: Teardown MSI setup if rcar_pcie_enable() fails
  PCI: rcar: Add missing irq_dispose_mapping() into failpath
  PCI: rcar: Pull bus clock enable/disable from rcar_pcie_get_resources()
  PCI: rcar: Poll more often in rcar_pcie_wait_for_dl()
  PCI: rcar: Reuse generic pci_parse_request_of_pci_ranges() function
  DT: pci: rcar-pci: document R8A77980 bindings
  PCI: rcar: Factor out rcar_pcie_hw_init() call
  PCI: rcar: Add R-Car gen3 PHY support
  PCI: rcar: Remove PHYRDY polling from rcar_pcie_hw_init_h1()
  PCI: rcar: Poll PHYRDY in rcar_pcie_hw_init()
  PCI: rcar: Clean up the macros
  PCI: rcar: Use runtime PM to control controller clock

# Conflicts:
#	drivers/pci/host/pcie-rcar.c
Bjorn Helgaas 7 жил өмнө
parent
commit
1c2bef0a3f

+ 6 - 0
Documentation/devicetree/bindings/pci/rcar-pci.txt

@@ -8,6 +8,7 @@ compatible: "renesas,pcie-r8a7743" for the R8A7743 SoC;
 	    "renesas,pcie-r8a7793" for the R8A7793 SoC;
 	    "renesas,pcie-r8a7793" for the R8A7793 SoC;
 	    "renesas,pcie-r8a7795" for the R8A7795 SoC;
 	    "renesas,pcie-r8a7795" for the R8A7795 SoC;
 	    "renesas,pcie-r8a7796" for the R8A7796 SoC;
 	    "renesas,pcie-r8a7796" for the R8A7796 SoC;
+	    "renesas,pcie-r8a77980" for the R8A77980 SoC;
 	    "renesas,pcie-rcar-gen2" for a generic R-Car Gen2 or
 	    "renesas,pcie-rcar-gen2" for a generic R-Car Gen2 or
 				     RZ/G1 compatible device.
 				     RZ/G1 compatible device.
 	    "renesas,pcie-rcar-gen3" for a generic R-Car Gen3 compatible device.
 	    "renesas,pcie-rcar-gen3" for a generic R-Car Gen3 compatible device.
@@ -32,6 +33,11 @@ compatible: "renesas,pcie-r8a7743" for the R8A7743 SoC;
 	and PCIe bus clocks.
 	and PCIe bus clocks.
 - clock-names: from common clock binding: should be "pcie" and "pcie_bus".
 - clock-names: from common clock binding: should be "pcie" and "pcie_bus".
 
 
+Optional properties:
+- phys: from common PHY binding: PHY phandle and specifier (only make sense
+	for R-Car gen3 SoCs where the PCIe PHYs have their own register blocks).
+- phy-names: from common PHY binding: should be "pcie".
+
 Example:
 Example:
 
 
 SoC-specific DT Entry:
 SoC-specific DT Entry:

+ 154 - 127
drivers/pci/host/pcie-rcar.c

@@ -11,6 +11,7 @@
  * Author: Phil Edworthy <phil.edworthy@renesas.com>
  * Author: Phil Edworthy <phil.edworthy@renesas.com>
  */
  */
 
 
+#include <linux/bitops.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
@@ -24,6 +25,7 @@
 #include <linux/of_pci.h>
 #include <linux/of_pci.h>
 #include <linux/of_platform.h>
 #include <linux/of_platform.h>
 #include <linux/pci.h>
 #include <linux/pci.h>
+#include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
@@ -32,12 +34,14 @@
 
 
 #define PCIECAR			0x000010
 #define PCIECAR			0x000010
 #define PCIECCTLR		0x000018
 #define PCIECCTLR		0x000018
-#define  CONFIG_SEND_ENABLE	(1 << 31)
+#define  CONFIG_SEND_ENABLE	BIT(31)
 #define  TYPE0			(0 << 8)
 #define  TYPE0			(0 << 8)
-#define  TYPE1			(1 << 8)
+#define  TYPE1			BIT(8)
 #define PCIECDR			0x000020
 #define PCIECDR			0x000020
 #define PCIEMSR			0x000028
 #define PCIEMSR			0x000028
 #define PCIEINTXR		0x000400
 #define PCIEINTXR		0x000400
+#define PCIEPHYSR		0x0007f0
+#define  PHYRDY			BIT(0)
 #define PCIEMSITXR		0x000840
 #define PCIEMSITXR		0x000840
 
 
 /* Transfer control */
 /* Transfer control */
@@ -46,7 +50,7 @@
 #define PCIETSTR		0x02004
 #define PCIETSTR		0x02004
 #define  DATA_LINK_ACTIVE	1
 #define  DATA_LINK_ACTIVE	1
 #define PCIEERRFR		0x02020
 #define PCIEERRFR		0x02020
-#define  UNSUPPORTED_REQUEST	(1 << 4)
+#define  UNSUPPORTED_REQUEST	BIT(4)
 #define PCIEMSIFR		0x02044
 #define PCIEMSIFR		0x02044
 #define PCIEMSIALR		0x02048
 #define PCIEMSIALR		0x02048
 #define  MSIFE			1
 #define  MSIFE			1
@@ -59,17 +63,17 @@
 /* local address reg & mask */
 /* local address reg & mask */
 #define PCIELAR(x)		(0x02200 + ((x) * 0x20))
 #define PCIELAR(x)		(0x02200 + ((x) * 0x20))
 #define PCIELAMR(x)		(0x02208 + ((x) * 0x20))
 #define PCIELAMR(x)		(0x02208 + ((x) * 0x20))
-#define  LAM_PREFETCH		(1 << 3)
-#define  LAM_64BIT		(1 << 2)
-#define  LAR_ENABLE		(1 << 1)
+#define  LAM_PREFETCH		BIT(3)
+#define  LAM_64BIT		BIT(2)
+#define  LAR_ENABLE		BIT(1)
 
 
 /* PCIe address reg & mask */
 /* PCIe address reg & mask */
 #define PCIEPALR(x)		(0x03400 + ((x) * 0x20))
 #define PCIEPALR(x)		(0x03400 + ((x) * 0x20))
 #define PCIEPAUR(x)		(0x03404 + ((x) * 0x20))
 #define PCIEPAUR(x)		(0x03404 + ((x) * 0x20))
 #define PCIEPAMR(x)		(0x03408 + ((x) * 0x20))
 #define PCIEPAMR(x)		(0x03408 + ((x) * 0x20))
 #define PCIEPTCTLR(x)		(0x0340c + ((x) * 0x20))
 #define PCIEPTCTLR(x)		(0x0340c + ((x) * 0x20))
-#define  PAR_ENABLE		(1 << 31)
-#define  IO_SPACE		(1 << 8)
+#define  PAR_ENABLE		BIT(31)
+#define  IO_SPACE		BIT(8)
 
 
 /* Configuration */
 /* Configuration */
 #define PCICONF(x)		(0x010000 + ((x) * 0x4))
 #define PCICONF(x)		(0x010000 + ((x) * 0x4))
@@ -81,47 +85,46 @@
 #define IDSETR1			0x011004
 #define IDSETR1			0x011004
 #define TLCTLR			0x011048
 #define TLCTLR			0x011048
 #define MACSR			0x011054
 #define MACSR			0x011054
-#define  SPCHGFIN		(1 << 4)
-#define  SPCHGFAIL		(1 << 6)
-#define  SPCHGSUC		(1 << 7)
+#define  SPCHGFIN		BIT(4)
+#define  SPCHGFAIL		BIT(6)
+#define  SPCHGSUC		BIT(7)
 #define  LINK_SPEED		(0xf << 16)
 #define  LINK_SPEED		(0xf << 16)
 #define  LINK_SPEED_2_5GTS	(1 << 16)
 #define  LINK_SPEED_2_5GTS	(1 << 16)
 #define  LINK_SPEED_5_0GTS	(2 << 16)
 #define  LINK_SPEED_5_0GTS	(2 << 16)
 #define MACCTLR			0x011058
 #define MACCTLR			0x011058
-#define  SPEED_CHANGE		(1 << 24)
-#define  SCRAMBLE_DISABLE	(1 << 27)
+#define  SPEED_CHANGE		BIT(24)
+#define  SCRAMBLE_DISABLE	BIT(27)
 #define MACS2R			0x011078
 #define MACS2R			0x011078
 #define MACCGSPSETR		0x011084
 #define MACCGSPSETR		0x011084
-#define  SPCNGRSN		(1 << 31)
+#define  SPCNGRSN		BIT(31)
 
 
 /* R-Car H1 PHY */
 /* R-Car H1 PHY */
 #define H1_PCIEPHYADRR		0x04000c
 #define H1_PCIEPHYADRR		0x04000c
-#define  WRITE_CMD		(1 << 16)
-#define  PHY_ACK		(1 << 24)
+#define  WRITE_CMD		BIT(16)
+#define  PHY_ACK		BIT(24)
 #define  RATE_POS		12
 #define  RATE_POS		12
 #define  LANE_POS		8
 #define  LANE_POS		8
 #define  ADR_POS		0
 #define  ADR_POS		0
 #define H1_PCIEPHYDOUTR		0x040014
 #define H1_PCIEPHYDOUTR		0x040014
-#define H1_PCIEPHYSR		0x040018
 
 
 /* R-Car Gen2 PHY */
 /* R-Car Gen2 PHY */
 #define GEN2_PCIEPHYADDR	0x780
 #define GEN2_PCIEPHYADDR	0x780
 #define GEN2_PCIEPHYDATA	0x784
 #define GEN2_PCIEPHYDATA	0x784
 #define GEN2_PCIEPHYCTRL	0x78c
 #define GEN2_PCIEPHYCTRL	0x78c
 
 
-#define INT_PCI_MSI_NR	32
+#define INT_PCI_MSI_NR		32
 
 
-#define RCONF(x)	(PCICONF(0)+(x))
-#define RPMCAP(x)	(PMCAP(0)+(x))
-#define REXPCAP(x)	(EXPCAP(0)+(x))
-#define RVCCAP(x)	(VCCAP(0)+(x))
+#define RCONF(x)		(PCICONF(0) + (x))
+#define RPMCAP(x)		(PMCAP(0) + (x))
+#define REXPCAP(x)		(EXPCAP(0) + (x))
+#define RVCCAP(x)		(VCCAP(0) + (x))
 
 
-#define  PCIE_CONF_BUS(b)	(((b) & 0xff) << 24)
-#define  PCIE_CONF_DEV(d)	(((d) & 0x1f) << 19)
-#define  PCIE_CONF_FUNC(f)	(((f) & 0x7) << 16)
+#define PCIE_CONF_BUS(b)	(((b) & 0xff) << 24)
+#define PCIE_CONF_DEV(d)	(((d) & 0x1f) << 19)
+#define PCIE_CONF_FUNC(f)	(((f) & 0x7) << 16)
 
 
-#define RCAR_PCI_MAX_RESOURCES 4
-#define MAX_NR_INBOUND_MAPS 6
+#define RCAR_PCI_MAX_RESOURCES	4
+#define MAX_NR_INBOUND_MAPS	6
 
 
 struct rcar_msi {
 struct rcar_msi {
 	DECLARE_BITMAP(used, INT_PCI_MSI_NR);
 	DECLARE_BITMAP(used, INT_PCI_MSI_NR);
@@ -141,10 +144,10 @@ static inline struct rcar_msi *to_rcar_msi(struct msi_controller *chip)
 /* Structure representing the PCIe interface */
 /* Structure representing the PCIe interface */
 struct rcar_pcie {
 struct rcar_pcie {
 	struct device		*dev;
 	struct device		*dev;
+	struct phy		*phy;
 	void __iomem		*base;
 	void __iomem		*base;
 	struct list_head	resources;
 	struct list_head	resources;
 	int			root_bus_nr;
 	int			root_bus_nr;
-	struct clk		*clk;
 	struct clk		*bus_clk;
 	struct clk		*bus_clk;
 	struct			rcar_msi msi;
 	struct			rcar_msi msi;
 };
 };
@@ -529,12 +532,12 @@ static void phy_write_reg(struct rcar_pcie *pcie,
 	phy_wait_for_ack(pcie);
 	phy_wait_for_ack(pcie);
 }
 }
 
 
-static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
+static int rcar_pcie_wait_for_phyrdy(struct rcar_pcie *pcie)
 {
 {
 	unsigned int timeout = 10;
 	unsigned int timeout = 10;
 
 
 	while (timeout--) {
 	while (timeout--) {
-		if ((rcar_pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
+		if (rcar_pci_read_reg(pcie, PCIEPHYSR) & PHYRDY)
 			return 0;
 			return 0;
 
 
 		msleep(5);
 		msleep(5);
@@ -543,6 +546,21 @@ static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
 	return -ETIMEDOUT;
 	return -ETIMEDOUT;
 }
 }
 
 
+static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
+{
+	unsigned int timeout = 10000;
+
+	while (timeout--) {
+		if ((rcar_pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
+			return 0;
+
+		udelay(5);
+		cpu_relax();
+	}
+
+	return -ETIMEDOUT;
+}
+
 static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
 static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
 {
 {
 	int err;
 	int err;
@@ -553,6 +571,10 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
 	/* Set mode */
 	/* Set mode */
 	rcar_pci_write_reg(pcie, 1, PCIEMSR);
 	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
 	 * Initial header for port config space is type 1, set the device
 	 * class to match. Hardware takes care of propagating the IDSETR
 	 * class to match. Hardware takes care of propagating the IDSETR
@@ -607,10 +629,8 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
 	return 0;
 	return 0;
 }
 }
 
 
-static int rcar_pcie_hw_init_h1(struct rcar_pcie *pcie)
+static int rcar_pcie_phy_init_h1(struct rcar_pcie *pcie)
 {
 {
-	unsigned int timeout = 10;
-
 	/* Initialize the phy */
 	/* Initialize the phy */
 	phy_write_reg(pcie, 0, 0x42, 0x1, 0x0EC34191);
 	phy_write_reg(pcie, 0, 0x42, 0x1, 0x0EC34191);
 	phy_write_reg(pcie, 1, 0x42, 0x1, 0x0EC34180);
 	phy_write_reg(pcie, 1, 0x42, 0x1, 0x0EC34180);
@@ -629,17 +649,10 @@ static int rcar_pcie_hw_init_h1(struct rcar_pcie *pcie)
 	phy_write_reg(pcie, 0, 0x64, 0x1, 0x3F0F1F0F);
 	phy_write_reg(pcie, 0, 0x64, 0x1, 0x3F0F1F0F);
 	phy_write_reg(pcie, 0, 0x66, 0x1, 0x00008000);
 	phy_write_reg(pcie, 0, 0x66, 0x1, 0x00008000);
 
 
-	while (timeout--) {
-		if (rcar_pci_read_reg(pcie, H1_PCIEPHYSR))
-			return rcar_pcie_hw_init(pcie);
-
-		msleep(5);
-	}
-
-	return -ETIMEDOUT;
+	return 0;
 }
 }
 
 
-static int rcar_pcie_hw_init_gen2(struct rcar_pcie *pcie)
+static int rcar_pcie_phy_init_gen2(struct rcar_pcie *pcie)
 {
 {
 	/*
 	/*
 	 * These settings come from the R-Car Series, 2nd Generation User's
 	 * These settings come from the R-Car Series, 2nd Generation User's
@@ -656,7 +669,18 @@ static int rcar_pcie_hw_init_gen2(struct rcar_pcie *pcie)
 	rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL);
 	rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL);
 	rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL);
 	rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL);
 
 
-	return rcar_pcie_hw_init(pcie);
+	return 0;
+}
+
+static int rcar_pcie_phy_init_gen3(struct rcar_pcie *pcie)
+{
+	int err;
+
+	err = phy_init(pcie->phy);
+	if (err)
+		return err;
+
+	return phy_power_on(pcie->phy);
 }
 }
 
 
 static int rcar_msi_alloc(struct rcar_msi *chip)
 static int rcar_msi_alloc(struct rcar_msi *chip)
@@ -844,6 +868,20 @@ static const struct irq_domain_ops msi_domain_ops = {
 	.map = rcar_msi_map,
 	.map = rcar_msi_map,
 };
 };
 
 
+static void rcar_pcie_unmap_msi(struct rcar_pcie *pcie)
+{
+	struct rcar_msi *msi = &pcie->msi;
+	int i, irq;
+
+	for (i = 0; i < INT_PCI_MSI_NR; i++) {
+		irq = irq_find_mapping(msi->domain, i);
+		if (irq > 0)
+			irq_dispose_mapping(irq);
+	}
+
+	irq_domain_remove(msi->domain);
+}
+
 static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
 static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
 {
 {
 	struct device *dev = pcie->dev;
 	struct device *dev = pcie->dev;
@@ -898,16 +936,35 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
 	return 0;
 	return 0;
 
 
 err:
 err:
-	irq_domain_remove(msi->domain);
+	rcar_pcie_unmap_msi(pcie);
 	return err;
 	return err;
 }
 }
 
 
+static void rcar_pcie_teardown_msi(struct rcar_pcie *pcie)
+{
+	struct rcar_msi *msi = &pcie->msi;
+
+	/* Disable all MSI interrupts */
+	rcar_pci_write_reg(pcie, 0, PCIEMSIIER);
+
+	/* Disable address decoding of the MSI interrupt, MSIFE */
+	rcar_pci_write_reg(pcie, 0, PCIEMSIALR);
+
+	free_pages(msi->pages, 0);
+
+	rcar_pcie_unmap_msi(pcie);
+}
+
 static int rcar_pcie_get_resources(struct rcar_pcie *pcie)
 static int rcar_pcie_get_resources(struct rcar_pcie *pcie)
 {
 {
 	struct device *dev = pcie->dev;
 	struct device *dev = pcie->dev;
 	struct resource res;
 	struct resource res;
 	int err, i;
 	int err, i;
 
 
+	pcie->phy = devm_phy_optional_get(dev, "pcie");
+	if (IS_ERR(pcie->phy))
+		return PTR_ERR(pcie->phy);
+
 	err = of_address_to_resource(dev->of_node, 0, &res);
 	err = of_address_to_resource(dev->of_node, 0, &res);
 	if (err)
 	if (err)
 		return err;
 		return err;
@@ -916,30 +973,17 @@ static int rcar_pcie_get_resources(struct rcar_pcie *pcie)
 	if (IS_ERR(pcie->base))
 	if (IS_ERR(pcie->base))
 		return PTR_ERR(pcie->base);
 		return PTR_ERR(pcie->base);
 
 
-	pcie->clk = devm_clk_get(dev, "pcie");
-	if (IS_ERR(pcie->clk)) {
-		dev_err(dev, "cannot get platform clock\n");
-		return PTR_ERR(pcie->clk);
-	}
-	err = clk_prepare_enable(pcie->clk);
-	if (err)
-		return err;
-
 	pcie->bus_clk = devm_clk_get(dev, "pcie_bus");
 	pcie->bus_clk = devm_clk_get(dev, "pcie_bus");
 	if (IS_ERR(pcie->bus_clk)) {
 	if (IS_ERR(pcie->bus_clk)) {
 		dev_err(dev, "cannot get pcie bus clock\n");
 		dev_err(dev, "cannot get pcie bus clock\n");
-		err = PTR_ERR(pcie->bus_clk);
-		goto fail_clk;
+		return PTR_ERR(pcie->bus_clk);
 	}
 	}
-	err = clk_prepare_enable(pcie->bus_clk);
-	if (err)
-		goto fail_clk;
 
 
 	i = irq_of_parse_and_map(dev->of_node, 0);
 	i = irq_of_parse_and_map(dev->of_node, 0);
 	if (!i) {
 	if (!i) {
 		dev_err(dev, "cannot get platform resources for msi interrupt\n");
 		dev_err(dev, "cannot get platform resources for msi interrupt\n");
 		err = -ENOENT;
 		err = -ENOENT;
-		goto err_map_reg;
+		goto err_irq1;
 	}
 	}
 	pcie->msi.irq1 = i;
 	pcie->msi.irq1 = i;
 
 
@@ -947,17 +991,15 @@ static int rcar_pcie_get_resources(struct rcar_pcie *pcie)
 	if (!i) {
 	if (!i) {
 		dev_err(dev, "cannot get platform resources for msi interrupt\n");
 		dev_err(dev, "cannot get platform resources for msi interrupt\n");
 		err = -ENOENT;
 		err = -ENOENT;
-		goto err_map_reg;
+		goto err_irq2;
 	}
 	}
 	pcie->msi.irq2 = i;
 	pcie->msi.irq2 = i;
 
 
 	return 0;
 	return 0;
 
 
-err_map_reg:
-	clk_disable_unprepare(pcie->bus_clk);
-fail_clk:
-	clk_disable_unprepare(pcie->clk);
-
+err_irq2:
+	irq_dispose_mapping(pcie->msi.irq1);
+err_irq1:
 	return err;
 	return err;
 }
 }
 
 
@@ -1053,62 +1095,28 @@ static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie *pcie,
 }
 }
 
 
 static const struct of_device_id rcar_pcie_of_match[] = {
 static const struct of_device_id rcar_pcie_of_match[] = {
-	{ .compatible = "renesas,pcie-r8a7779", .data = rcar_pcie_hw_init_h1 },
+	{ .compatible = "renesas,pcie-r8a7779",
+	  .data = rcar_pcie_phy_init_h1 },
 	{ .compatible = "renesas,pcie-r8a7790",
 	{ .compatible = "renesas,pcie-r8a7790",
-	  .data = rcar_pcie_hw_init_gen2 },
+	  .data = rcar_pcie_phy_init_gen2 },
 	{ .compatible = "renesas,pcie-r8a7791",
 	{ .compatible = "renesas,pcie-r8a7791",
-	  .data = rcar_pcie_hw_init_gen2 },
+	  .data = rcar_pcie_phy_init_gen2 },
 	{ .compatible = "renesas,pcie-rcar-gen2",
 	{ .compatible = "renesas,pcie-rcar-gen2",
-	  .data = rcar_pcie_hw_init_gen2 },
-	{ .compatible = "renesas,pcie-r8a7795", .data = rcar_pcie_hw_init },
-	{ .compatible = "renesas,pcie-rcar-gen3", .data = rcar_pcie_hw_init },
+	  .data = rcar_pcie_phy_init_gen2 },
+	{ .compatible = "renesas,pcie-r8a7795",
+	  .data = rcar_pcie_phy_init_gen3 },
+	{ .compatible = "renesas,pcie-rcar-gen3",
+	  .data = rcar_pcie_phy_init_gen3 },
 	{},
 	{},
 };
 };
 
 
-static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci)
-{
-	int err;
-	struct device *dev = pci->dev;
-	resource_size_t iobase;
-	struct resource_entry *win, *tmp;
-
-	err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff,
-						    &pci->resources, &iobase);
-	if (err)
-		return err;
-
-	err = devm_request_pci_bus_resources(dev, &pci->resources);
-	if (err)
-		goto out_release_res;
-
-	resource_list_for_each_entry_safe(win, tmp, &pci->resources) {
-		struct resource *res = win->res;
-
-		if (resource_type(res) == IORESOURCE_IO) {
-			err = pci_remap_iospace(res, iobase);
-			if (err) {
-				dev_warn(dev, "error %d: failed to map resource %pR\n",
-					 err, res);
-
-				resource_list_destroy_entry(win);
-			}
-		}
-	}
-
-	return 0;
-
-out_release_res:
-	pci_free_resource_list(&pci->resources);
-	return err;
-}
-
 static int rcar_pcie_probe(struct platform_device *pdev)
 static int rcar_pcie_probe(struct platform_device *pdev)
 {
 {
 	struct device *dev = &pdev->dev;
 	struct device *dev = &pdev->dev;
 	struct rcar_pcie *pcie;
 	struct rcar_pcie *pcie;
 	unsigned int data;
 	unsigned int data;
 	int err;
 	int err;
-	int (*hw_init_fn)(struct rcar_pcie *);
+	int (*phy_init_fn)(struct rcar_pcie *);
 	struct pci_host_bridge *bridge;
 	struct pci_host_bridge *bridge;
 
 
 	bridge = pci_alloc_host_bridge(sizeof(*pcie));
 	bridge = pci_alloc_host_bridge(sizeof(*pcie));
@@ -1119,36 +1127,45 @@ static int rcar_pcie_probe(struct platform_device *pdev)
 
 
 	pcie->dev = dev;
 	pcie->dev = dev;
 
 
-	INIT_LIST_HEAD(&pcie->resources);
-
-	err = rcar_pcie_parse_request_of_pci_ranges(pcie);
+	err = pci_parse_request_of_pci_ranges(dev, &pcie->resources, NULL);
 	if (err)
 	if (err)
 		goto err_free_bridge;
 		goto err_free_bridge;
 
 
+	pm_runtime_enable(pcie->dev);
+	err = pm_runtime_get_sync(pcie->dev);
+	if (err < 0) {
+		dev_err(pcie->dev, "pm_runtime_get_sync failed\n");
+		goto err_pm_disable;
+	}
+
 	err = rcar_pcie_get_resources(pcie);
 	err = rcar_pcie_get_resources(pcie);
 	if (err < 0) {
 	if (err < 0) {
 		dev_err(dev, "failed to request resources: %d\n", err);
 		dev_err(dev, "failed to request resources: %d\n", err);
-		goto err_free_resource_list;
+		goto err_pm_put;
+	}
+
+	err = clk_prepare_enable(pcie->bus_clk);
+	if (err) {
+		dev_err(dev, "failed to enable bus clock: %d\n", err);
+		goto err_unmap_msi_irqs;
 	}
 	}
 
 
 	err = rcar_pcie_parse_map_dma_ranges(pcie, dev->of_node);
 	err = rcar_pcie_parse_map_dma_ranges(pcie, dev->of_node);
 	if (err)
 	if (err)
-		goto err_free_resource_list;
+		goto err_clk_disable;
 
 
-	pm_runtime_enable(dev);
-	err = pm_runtime_get_sync(dev);
-	if (err < 0) {
-		dev_err(dev, "pm_runtime_get_sync failed\n");
-		goto err_pm_disable;
+	phy_init_fn = of_device_get_match_data(dev);
+	err = phy_init_fn(pcie);
+	if (err) {
+		dev_err(dev, "failed to init PCIe PHY\n");
+		goto err_clk_disable;
 	}
 	}
 
 
 	/* Failure to get a link might just be that no cards are inserted */
 	/* Failure to get a link might just be that no cards are inserted */
-	hw_init_fn = of_device_get_match_data(dev);
-	err = hw_init_fn(pcie);
-	if (err) {
+	if (rcar_pcie_hw_init(pcie)) {
 		dev_info(dev, "PCIe link down\n");
 		dev_info(dev, "PCIe link down\n");
 		err = -ENODEV;
 		err = -ENODEV;
-		goto err_pm_put;
+		goto err_clk_disable;
 	}
 	}
 
 
 	data = rcar_pci_read_reg(pcie, MACSR);
 	data = rcar_pci_read_reg(pcie, MACSR);
@@ -1160,24 +1177,34 @@ static int rcar_pcie_probe(struct platform_device *pdev)
 			dev_err(dev,
 			dev_err(dev,
 				"failed to enable MSI support: %d\n",
 				"failed to enable MSI support: %d\n",
 				err);
 				err);
-			goto err_pm_put;
+			goto err_clk_disable;
 		}
 		}
 	}
 	}
 
 
 	err = rcar_pcie_enable(pcie);
 	err = rcar_pcie_enable(pcie);
 	if (err)
 	if (err)
-		goto err_pm_put;
+		goto err_msi_teardown;
 
 
 	return 0;
 	return 0;
 
 
+err_msi_teardown:
+	if (IS_ENABLED(CONFIG_PCI_MSI))
+		rcar_pcie_teardown_msi(pcie);
+
+err_clk_disable:
+	clk_disable_unprepare(pcie->bus_clk);
+
+err_unmap_msi_irqs:
+	irq_dispose_mapping(pcie->msi.irq2);
+	irq_dispose_mapping(pcie->msi.irq1);
+
 err_pm_put:
 err_pm_put:
 	pm_runtime_put(dev);
 	pm_runtime_put(dev);
 
 
 err_pm_disable:
 err_pm_disable:
 	pm_runtime_disable(dev);
 	pm_runtime_disable(dev);
-
-err_free_resource_list:
 	pci_free_resource_list(&pcie->resources);
 	pci_free_resource_list(&pcie->resources);
+
 err_free_bridge:
 err_free_bridge:
 	pci_free_host_bridge(bridge);
 	pci_free_host_bridge(bridge);