All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] PCI: dwc: rcar-gen4: Replace pe_rst GPIO PERST with GPIO reset aux driver
@ 2026-10-28 17:21 Marek Vasut
  2026-10-28 17:21 ` [PATCH 2/2] PCI: rcar-gen4: Inline rcar_gen4_pcie_host_perst_assert() again Marek Vasut
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Marek Vasut @ 2026-10-28 17:21 UTC (permalink / raw)
  To: linux-pci
  Cc: Marek Vasut, Krzysztof Wilczyński, Alex Elder,
	Andy Shevchenko, Arnd Bergmann, Bartosz Golaszewski,
	Bjorn Helgaas, Frank Li, Geert Uytterhoeven, Jingoo Han,
	Koichiro Den, Lorenzo Pieralisi, Magnus Damm,
	Manivannan Sadhasivam, Neil Armstrong, Randolph Lin, Rob Herring,
	Sherry Sun, Siddharth Vadapalli, Vidya Sagar, Vincent Guittot,
	Wilfred Mallawa, Xincheng Zhang, Yoshihiro Shimoda, linux-kernel,
	linux-renesas-soc

There is currently one user of core DWC PCIe struct gpio_desc *pe_rst
field, which is R-Car Gen4 driver. This driver already does convoluted
handling of both GPIO controlled PERST# and reset controller controlled
PERST#. Simplify the situation using reset GPIO aux driver.

First, eliminate the pe_rst GPIO from DWC core, so it is not in the
way, this is the easy top half of this patch.

Second, deal with the resets using reset GPIO aux driver in the R-Car
Gen4 PCIe driver. The R-Car Gen4 PCIe driver currently handles two
variants of DT description which can be passed to it:

1) Combined mandatory PCIe core resets and optional GPIO PERST#:
   pciec@nnn {
       compatible = "renesas,r8a779g0-pcie", "renesas,rcar-gen4-pcie";
       ...
       resets = <&reset 624>, <&reset 1121>;
       reset-names = "pwr", "core";
       reset-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>; // This is GPIO PERST#
       ...
   };
   The PCIe core resets are requested already in pcie-designware.c
   dw_pcie_get_resets(), but the reset-gpios GPIO PERST# has to be
   handled later, in R-Car Gen4 PCIe driver host .init callback,
   to avoid interference with the core dw_pcie_get_resets(). The
   GPIO PERST# has to be requested by index since there is no
   reset-names entry for it, using the first unused reset index.

2) Separate mandatory PCIe core resets and optional reset controller PERST#:
   pciec@nnn {
       compatible = "renesas,r8a78000-pcie4", "renesas,rcar-gen5-pcie4";
       ...
       resets = <&reset 345>;
       reset-names = "pwr";
       ...
       pciec40_rp: pci@0,0 {
           compatible = "pciclass,0604";
           ...
           resets = <&reset 815>; // This is reset controller PERST#
           reset-names = "perst";
       };
   };
   The PCIe core resets are requested already in pcie-designware.c
   dw_pcie_get_resets(), and root port reset controller PERST# used
   to be handled in rcar_gen4_pcie_get_resources(), but now the root
   port reset controller PERST# has to be handled later, in R-Car Gen4
   PCIe driver host .init callback, to avoid interference with the core
   dw_pcie_get_resets().

Ultimately, this simplifies both the core and the R-Car Gen4 PCIe driver.

Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: "Krzysztof Wilczyński" <kwilczynski@kernel.org>
Cc: Alex Elder <elder@riscstar.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Bartosz Golaszewski <brgl@kernel.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Frank Li <Frank.Li@nxp.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Jingoo Han <jingoohan1@gmail.com>
Cc: Koichiro Den <den@valinux.co.jp>
Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Manivannan Sadhasivam <mani@kernel.org>
Cc: Neil Armstrong <neil.armstrong@linaro.org>
Cc: Randolph Lin <randolph@andestech.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Sherry Sun <sherry.sun@nxp.com>
Cc: Siddharth Vadapalli <s-vadapalli@ti.com>
Cc: Vidya Sagar <vidyas@nvidia.com>
Cc: Vincent Guittot <vincent.guittot@linaro.org>
Cc: Wilfred Mallawa <wilfred.mallawa@wdc.com>
Cc: Xincheng Zhang <zhangxincheng@ultrarisc.com>
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Cc: linux-kernel@vger.kernel.org
Cc: linux-pci@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
NOTE: Thanks Bartosz for helping me figure the GPIO reset aux driver out
---
 drivers/pci/controller/dwc/Kconfig           |   1 +
 drivers/pci/controller/dwc/pcie-designware.c |   4 -
 drivers/pci/controller/dwc/pcie-designware.h |   1 -
 drivers/pci/controller/dwc/pcie-rcar-gen4.c  | 107 ++++++++++++++-----
 4 files changed, 83 insertions(+), 30 deletions(-)

diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
index 0a0d56fcf0ac9..d65cf1e9d842b 100644
--- a/drivers/pci/controller/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
@@ -350,6 +350,7 @@ config PCIE_RCAR_GEN4_HOST
 	depends on PCI_MSI
 	select PCIE_DW_HOST
 	select PCIE_RCAR_GEN4
+	select RESET_GPIO
 	help
 	  Say Y here if you want PCIe controller (host mode) on R-Car Gen4 SoCs.
 	  To compile this driver as a module, choose M here: the module will be
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 12f102f48d5d5..b09c01853d807 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -104,10 +104,6 @@ static int dw_pcie_get_resets(struct dw_pcie *pci)
 	if (ret)
 		return ret;
 
-	pci->pe_rst = devm_gpiod_get_optional(pci->dev, "reset", GPIOD_OUT_HIGH);
-	if (IS_ERR(pci->pe_rst))
-		return PTR_ERR(pci->pe_rst);
-
 	return 0;
 }
 
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 6d788aa000117..9dc86b66e415d 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -575,7 +575,6 @@ struct dw_pcie {
 	struct clk_bulk_data	core_clks[DW_PCIE_NUM_CORE_CLKS];
 	struct reset_control_bulk_data	app_rsts[DW_PCIE_NUM_APP_RSTS];
 	struct reset_control_bulk_data	core_rsts[DW_PCIE_NUM_CORE_RSTS];
-	struct gpio_desc		*pe_rst;
 	bool			suspended;
 	struct debugfs_info	*debugfs;
 	enum			dw_pcie_device_mode mode;
diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
index fceecbd16355c..d3bf01485e11d 100644
--- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
+++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
@@ -401,7 +401,6 @@ static void rcar_gen4_pcie_unprepare(struct rcar_gen4_pcie *rcar)
 static int rcar_gen4_pcie_get_resources(struct rcar_gen4_pcie *rcar)
 {
 	struct device *dev = rcar->dw.dev;
-	struct device_node *root_port;
 
 	rcar->phy_base = devm_platform_ioremap_resource_byname(rcar->pdev, "phy");
 	if (IS_ERR(rcar->phy_base)) {
@@ -411,18 +410,8 @@ static int rcar_gen4_pcie_get_resources(struct rcar_gen4_pcie *rcar)
 			return PTR_ERR(rcar->phy);
 	}
 
-	root_port = of_get_next_available_child(dev->of_node, NULL);
-	if (root_port) {
-		rcar->perst = of_reset_control_get_optional_exclusive(root_port, "perst");
-		of_node_put(root_port);
-		if (IS_ERR(rcar->perst))
-			return dev_err_probe(dev, PTR_ERR(rcar->perst), "Failed to get PERST#\n");
-	}
-
 	/* Renesas-specific registers */
 	rcar->base = devm_platform_ioremap_resource_byname(rcar->pdev, "app");
-	if (IS_ERR(rcar->base))
-		reset_control_put(rcar->perst);
 
 	return PTR_ERR_OR_ZERO(rcar->base);
 }
@@ -594,19 +583,84 @@ static int rcar_gen4_pcie_enable_device(struct pci_host_bridge *bridge,
 	return 0;
 }
 
+static int rcar_gen4_pcie_host_perst_get(struct dw_pcie *dw)
+{
+	struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
+	struct device_node *root_port;
+	struct device *dev = dw->dev;
+	struct reset_control *perst;
+	int index;
+
+	/*
+	 * Handle two forms of DT which can be passed to this driver:
+	 *
+	 * 1) Combined mandatory PCIe core resets and optional GPIO PERST#:
+	 *    pciec@nnn {
+	 *        compatible = "renesas,r8a779g0-pcie", "renesas,rcar-gen4-pcie";
+	 *        ...
+	 *        resets = <&reset 624>, <&reset 1121>;
+	 *        reset-names = "pwr", "core";
+	 *        reset-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>; // This is GPIO PERST#
+	 *        ...
+	 *    };
+	 *    The PCIe core resets are requested already in pcie-designware.c
+	 *    dw_pcie_get_resets(), but the reset-gpios GPIO PERST# has to be
+	 *    handled at this point here. The GPIO PERST# has to be requested
+	 *    by index since there is no reset-names entry for it, using the
+	 *    first unused reset index.
+	 *
+	 * 2) Separate mandatory PCIe core resets and optional reset controller PERST#:
+	 *    pciec@nnn {
+	 *        compatible = "renesas,r8a78000-pcie4", "renesas,rcar-gen5-pcie4";
+	 *        ...
+	 *        resets = <&reset 345>;
+	 *        reset-names = "pwr";
+	 *        ...
+	 *        pciec40_rp: pci@0,0 {
+	 *            compatible = "pciclass,0604";
+	 *            ...
+	 *            resets = <&reset 815>; // This is reset controller PERST#
+	 *            reset-names = "perst";
+	 *        };
+	 *    };
+	 *    The PCIe core resets are requested already in pcie-designware.c
+	 *    dw_pcie_get_resets(), but the root port reset controller PERST#
+	 *    has to be handled at this point here using subnode request.
+	 */
+	index = reset_control_get_count(dev);
+	if (index < 0)
+		return index;
+
+	/* Attempt to request GPIO PERST# in PCIe controller node. */
+	perst = of_reset_control_get_exclusive_by_index(dev->of_node, index);
+	if (!IS_ERR(perst))
+		goto exit;
+
+	/* No GPIO reset, test for root port subnode. */
+	root_port = of_get_next_available_child(dev->of_node, NULL);
+	if (!root_port)
+		return dev_err_probe(dev, -EINVAL, "Failed to get PERST# in root port\n");
+
+	/* Attempt to request reset controller PERST# in root port subnode. */
+	perst = of_reset_control_get_optional_exclusive(root_port, "perst");
+	of_node_put(root_port);
+	if (IS_ERR(perst))
+		return dev_err_probe(dev, PTR_ERR(perst), "Failed to get PERST#\n");
+
+exit:
+	rcar->perst = perst;
+	return 0;
+}
+
 static void rcar_gen4_pcie_host_perst_assert(struct dw_pcie_rp *pp, bool assert)
 {
 	struct dw_pcie *dw = to_dw_pcie_from_pp(pp);
 	struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
 
-	if (dw->pe_rst) {
-		gpiod_set_value_cansleep(dw->pe_rst, assert);
-	} else {
-		if (assert)
-			reset_control_assert(rcar->perst);
-		else
-			reset_control_deassert(rcar->perst);
-	}
+	if (assert)
+		reset_control_assert(rcar->perst);
+	else
+		reset_control_deassert(rcar->perst);
 }
 
 /* Host mode */
@@ -616,6 +670,10 @@ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
 	struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
 	int ret;
 
+	ret = rcar_gen4_pcie_host_perst_get(dw);
+	if (ret)
+		return ret;
+
 	if (pp->bridge)
 		pp->bridge->enable_device = rcar_gen4_pcie_enable_device;
 
@@ -623,7 +681,7 @@ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
 
 	ret = rcar->drvdata->init(rcar);
 	if (ret)
-		return ret;
+		goto err_init;
 
 	/*
 	 * According to the section 3.5.7.2 "RC Mode" in DWC PCIe Dual Mode
@@ -646,6 +704,8 @@ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
 
 err:
 	rcar->drvdata->deinit(rcar);
+err_init:
+	reset_control_put(rcar->perst);
 	return ret;
 }
 
@@ -656,6 +716,7 @@ static void rcar_gen4_pcie_host_deinit(struct dw_pcie_rp *pp)
 
 	rcar_gen4_pcie_host_perst_assert(pp, true);
 	rcar->drvdata->deinit(rcar);
+	reset_control_put(rcar->perst);
 }
 
 static const struct dw_pcie_host_ops rcar_gen4_pcie_host_ops = {
@@ -830,7 +891,7 @@ static int rcar_gen4_pcie_probe(struct platform_device *pdev)
 
 	err = rcar_gen4_pcie_prepare(rcar);
 	if (err)
-		goto err_prepare;
+		return err;
 
 	err = rcar_gen4_add_dw_pcie(rcar);
 	if (err)
@@ -841,9 +902,6 @@ static int rcar_gen4_pcie_probe(struct platform_device *pdev)
 err_unprepare:
 	rcar_gen4_pcie_unprepare(rcar);
 
-err_prepare:
-	reset_control_put(rcar->perst);
-
 	return err;
 }
 
@@ -867,7 +925,6 @@ static void rcar_gen4_pcie_remove(struct platform_device *pdev)
 
 	rcar_gen4_remove_dw_pcie(rcar);
 	rcar_gen4_pcie_unprepare(rcar);
-	reset_control_put(rcar->perst);
 }
 
 static int r8a779f0_pcie_ltssm_control(struct rcar_gen4_pcie *rcar, bool enable)
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-10-29 16:19 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-28 17:21 [PATCH 1/2] PCI: dwc: rcar-gen4: Replace pe_rst GPIO PERST with GPIO reset aux driver Marek Vasut
2026-10-28 17:21 ` [PATCH 2/2] PCI: rcar-gen4: Inline rcar_gen4_pcie_host_perst_assert() again Marek Vasut
2026-10-28 17:32   ` sashiko-bot
2026-10-28 17:27 ` [PATCH 1/2] PCI: dwc: rcar-gen4: Replace pe_rst GPIO PERST with GPIO reset aux driver Marek Vasut
2026-10-29 13:52   ` Andy Shevchenko
2026-10-29 16:19     ` Marek Vasut
2026-10-28 17:35 ` sashiko-bot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.