Re: [PATCH 4/5] PCI: dwc: rcar-gen4: Handle PERST via reset subsystem

Manivannan Sadhasivam <[email protected]>
Newsgroups org.kernel.vger.linux-renesas-soc,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci
Message-ID <ceimnmpsyfmrkuvrrsgkjg3fk2yf7fj7z5ie3cj6vfyighatag@hyb3vr2nclpm>
On Sat, Jul 04, 2026 at 10:25:03PM +0200, Marek Vasut wrote:
> Handle PERST via both GPIO and reset subsystem. On R-Car Gen4, the
> PERST signal is operated as a GPIO, on R-Car Gen5 it might only be
> accessible via SCMI reset via reset subsystem. Support both options.
> This is a preparatory patch for R-Car Gen5 support.
> 
> Signed-off-by: Marek Vasut <[email protected]>
> ---
> Cc: "Krzysztof Wilczyński" <[email protected]>
> Cc: Bjorn Helgaas <[email protected]>
> Cc: Conor Dooley <[email protected]>
> Cc: Geert Uytterhoeven <[email protected]>
> Cc: Krzysztof Kozlowski <[email protected]>
> Cc: Lorenzo Pieralisi <[email protected]>
> Cc: Manivannan Sadhasivam <[email protected]>
> Cc: Rob Herring <[email protected]>
> Cc: Yoshihiro Shimoda <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> Cc: [email protected]
> Cc: [email protected]
> ---
>  drivers/pci/controller/dwc/pcie-rcar-gen4.c | 42 +++++++++++++++++++--
>  1 file changed, 39 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> index 05c22cc648135..186eedb33c27d 100644
> --- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> +++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> @@ -98,6 +98,7 @@ struct rcar_gen4_pcie {
>  	void __iomem *base;
>  	void __iomem *phy_base;
>  	struct platform_device *pdev;
> +	struct reset_control *perst;
>  	const struct rcar_gen4_pcie_drvdata *drvdata;
>  };
>  #define to_rcar_gen4_pcie(_dw)	container_of(_dw, struct rcar_gen4_pcie, dw)
> @@ -299,10 +300,27 @@ 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 reset_control *perst;
> +
>  	rcar->phy_base = devm_platform_ioremap_resource_byname(rcar->pdev, "phy");
>  	if (IS_ERR(rcar->phy_base))
>  		return PTR_ERR(rcar->phy_base);
>  
> +	rcar->perst = NULL;
> +	for_each_available_child_of_node_scoped(dev->of_node, of_port) {
> +		perst = of_reset_control_get(of_port, "perst");
> +		if (IS_ERR(perst)) {
> +			if (PTR_ERR(perst) != -EPROBE_DEFER)
> +				dev_err(dev, "Failed to get PERST#\n");
> +			return PTR_ERR(perst);

return dev_err_probe(dev, PTR_ERR(perst), "Failed to get PERST#\n")?

> +		}
> +
> +		/* There is only one root port. */
> +		rcar->perst = perst;
> +		break;

It feels weird to see for_each_available_child_of_node_scoped() and then
breaking with first node. Maybe you can just use of_get_next_available_child().

> +	}
> +
>  	/* Renesas-specific registers */
>  	rcar->base = devm_platform_ioremap_resource_byname(rcar->pdev, "app");
>  
> @@ -425,6 +443,22 @@ static int rcar_gen4_pcie_host_msi_init(struct dw_pcie_rp *pp)
>  	return ret;
>  }
>  
> +static void rcar_gen4_pcie_host_perst(struct dw_pcie_rp *pp, int enable)
> +{

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);
> +
> +	gpiod_set_value_cansleep(dw->pe_rst, enable);
> +
> +	if (!rcar->perst)
> +		return;
> +
> +	if (enable)
> +		reset_control_assert(rcar->perst);
> +	else
> +		reset_control_deassert(rcar->perst);
> +}
> +
>  /* Host mode */
>  static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
>  {
> @@ -432,7 +466,7 @@ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
>  	struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
>  	int ret;
>  
> -	gpiod_set_value_cansleep(dw->pe_rst, 1);
> +	rcar_gen4_pcie_host_perst(pp, 1);
>  
>  	ret = rcar_gen4_pcie_common_init(rcar);
>  	if (ret)
> @@ -453,7 +487,7 @@ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp)
>  
>  	msleep(PCIE_T_PVPERL_MS);	/* pe_rst requires 100msec delay */
>  
> -	gpiod_set_value_cansleep(dw->pe_rst, 0);
> +	rcar_gen4_pcie_host_perst(pp, 0);

rcar_gen4_pcie_host_perst_assert(pp, false)

>  
>  	return 0;
>  
> @@ -467,7 +501,7 @@ static void rcar_gen4_pcie_host_deinit(struct dw_pcie_rp *pp)
>  	struct dw_pcie *dw = to_dw_pcie_from_pp(pp);
>  	struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);
>  
> -	gpiod_set_value_cansleep(dw->pe_rst, 1);
> +	rcar_gen4_pcie_host_perst(pp, 1);

rcar_gen4_pcie_host_perst_assert(pp, true)

>  	rcar_gen4_pcie_common_deinit(rcar);
>  }
>  
> @@ -671,6 +705,8 @@ static void rcar_gen4_pcie_remove(struct platform_device *pdev)
>  
>  	rcar_gen4_remove_dw_pcie(rcar);
>  	rcar_gen4_pcie_unprepare(rcar);
> +	if (rcar->perst)
> +		reset_control_put(rcar->perst);

I don't see reset_control_put() in any error paths of probe().

- Mani

-- 
மணிவண்ணன் சதாசிவம்
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.