RE: [PATCH] can: rcar_canfd: Change the initializing flow for clocks and resets

Biju Das <[email protected]> Thu, 23 Jul 2026 08:02:08 +0000
Newsgroups org.kernel.vger.linux-can,org.kernel.vger.linux-kernel,org.kernel.vger.linux-renesas-soc
Message-ID <TY3PR01MB113465FDE69A565A731E9238586C02@TY3PR01MB11346.jpnprd01.prod.outlook.com>
Hi All,

> -----Original Message-----
> From: Biju <[email protected]>
> Sent: 25 June 2026 14:52
> Subject: [PATCH] can: rcar_canfd: Change the initializing flow for clocks and resets
> 
> From: Tu Nguyen <[email protected]>
> 
> Testing CANFD on RZ/G3E shows that many registers do not reset to their initial values with the current
> flow of deasserting resets first and then enabling clocks.
> 
> Based on the HW manual, clocks should be supplied first and the resets deasserted afterward.
> 
>  section 7.4.3 Procedure for Activating Modules: RZ/G2L  section 4.4.9.3 Procedure for Starting up Units:
> RZ/G3E
> 
> So, update the order of the initializing flow for resets and clocks to match the hardware manual,
> resetting all CANFD registers to their initial values. Also update rcar_canfd_global_deinit() to assert
> resets before disabling clocks, so the teardown path mirrors the new init ordering.
> 
> Fixes: 76e9353a80e9 ("can: rcar_canfd: Add support for RZ/G2L family")
> Signed-off-by: Tu Nguyen <[email protected]>
> Signed-off-by: Biju Das <[email protected]>
> ---
>  drivers/net/can/rcar/rcar_canfd.c | 32 +++++++++++++++----------------
>  1 file changed, 16 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
> index eaf8cac78038..fcc37b73ed43 100644
> --- a/drivers/net/can/rcar/rcar_canfd.c
> +++ b/drivers/net/can/rcar/rcar_canfd.c
> @@ -2003,20 +2003,12 @@ static int rcar_canfd_global_init(struct rcar_canfd_global *gpriv)
>  	u32 ch, sts;
>  	int err;
> 
> -	err = reset_control_reset(gpriv->rstc1);
> -	if (err)
> -		return err;
> -
> -	err = reset_control_reset(gpriv->rstc2);
> -	if (err)
> -		goto fail_reset1;
> -
>  	/* Enable peripheral clock for register access */
>  	err = clk_prepare_enable(gpriv->clkp);
>  	if (err) {
>  		dev_err(dev, "failed to enable peripheral clock: %pe\n",
>  			ERR_PTR(err));
> -		goto fail_reset2;
> +		return err;
>  	}
> 
>  	/* Enable RAM clock */
> @@ -2027,10 +2019,18 @@ static int rcar_canfd_global_init(struct rcar_canfd_global *gpriv)
>  		goto fail_clk;
>  	}
> 
> +	err = reset_control_reset(gpriv->rstc1);
> +	if (err)
> +		goto fail_ram_clk;
> +
> +	err = reset_control_reset(gpriv->rstc2);
> +	if (err)
> +		goto fail_reset1;
> +
>  	err = rcar_canfd_reset_controller(gpriv);
>  	if (err) {
>  		dev_err(dev, "reset controller failed: %pe\n", ERR_PTR(err));
> -		goto fail_ram_clk;
> +		goto fail_reset2;
>  	}
> 
>  	/* Controller in Global reset & Channel reset mode */ @@ -2068,14 +2068,14 @@ static int
> rcar_canfd_global_init(struct rcar_canfd_global *gpriv)
> 
>  fail_mode:
>  	rcar_canfd_disable_global_interrupts(gpriv);
> -fail_ram_clk:
> -	clk_disable_unprepare(gpriv->clk_ram);
> -fail_clk:
> -	clk_disable_unprepare(gpriv->clkp);
>  fail_reset2:
>  	reset_control_assert(gpriv->rstc2);
>  fail_reset1:
>  	reset_control_assert(gpriv->rstc1);
> +fail_ram_clk:
> +	clk_disable_unprepare(gpriv->clk_ram);
> +fail_clk:
> +	clk_disable_unprepare(gpriv->clkp);
>  	return err;
>  }
> 
> @@ -2090,10 +2090,10 @@ static void rcar_canfd_global_deinit(struct rcar_canfd_global *gpriv, bool full)
>  		rcar_canfd_set_bit(gpriv->base, RCANFD_GCTR, RCANFD_GCTR_GSLPR);
>  	}
> 
> -	clk_disable_unprepare(gpriv->clk_ram);
> -	clk_disable_unprepare(gpriv->clkp);
>  	reset_control_assert(gpriv->rstc2);
>  	reset_control_assert(gpriv->rstc1);
> +	clk_disable_unprepare(gpriv->clk_ram);
> +	clk_disable_unprepare(gpriv->clkp);
>  }
> 
>  static int rcar_canfd_probe(struct platform_device *pdev)
> --
> 2.43.0

Gentle ping.

Cheers,
Biju