[PATCH 07/17] i3c: renesas: Perform Dynamic Address Assignment on resume

Frank Li Frank.li at nxp.com
Fri May 22 12:16:55 PDT 2026


On Fri, May 22, 2026 at 01:18:05PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj at bp.renesas.com>
>
> The Renesas RZ/G3S SoC supports a power saving mode where power to most
> SoC components, including I3C, is turned off.
>
> On systems where the I3C devices also loses power during suspend (e.g. NXP
> P3T1085UK-ARD connected to the PMOD1_6A connector of the RZ SMARC Carrier
> 2 + Renesas RZ/G3S SMARC SOM), the devices becomes unreachable after
> resume.
>
> Running DAA in the controller resume path restores communication. However,
> DAA relies on interrupts for TX/RX, which are not available in the noirq
> suspend/resume phase (unless they are wakeup interrupts). For this, the
> suspend/resume callbacks were moved out of the noirq phase. Currently,
> there is no identified use case on either the Renesas RZ/G3S or Renesas
> RZ/G3E SoCs that requires the controller suspend/resume hooks to be part of
> the noirq suspend/resume phase.

Can you refer https://lore.kernel.org/linux-i3c/20260512121732.406009-1-adrian.hunter@intel.com/T/#mafdc9631a2a18dfebfa5b5efcb8584d32bceba7f

which defer DAA to workqueue.

Frank

>
> Along with this, struct renesas_i3c::DATBASn and its usage were removed,
> as they are no longer needed.
>
> Fixes: e7218986319b ("i3c: renesas: Add suspend/resume support")
> Cc: stable at vger.kernel.org
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj at bp.renesas.com>
> ---
>  drivers/i3c/master/renesas-i3c.c | 34 ++++++++++++--------------------
>  1 file changed, 13 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 2f3c6ddf75c0..c009d0de6a2b 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -265,7 +265,6 @@ struct renesas_i3c {
>  	u8 addrs[RENESAS_I3C_MAX_DEVS];
>  	struct renesas_i3c_xferqueue xferqueue;
>  	void __iomem *regs;
> -	u32 *DATBASn;
>  	struct clk_bulk_data *clks;
>  	struct reset_control *presetn;
>  	struct reset_control *tresetn;
> @@ -1400,12 +1399,6 @@ static int renesas_i3c_probe(struct platform_device *pdev)
>  	i3c->maxdevs = RENESAS_I3C_MAX_DEVS;
>  	i3c->free_pos = GENMASK(i3c->maxdevs - 1, 0);
>
> -	/* Allocate dynamic Device Address Table backup. */
> -	i3c->DATBASn = devm_kzalloc(&pdev->dev, sizeof(u32) * i3c->maxdevs,
> -				    GFP_KERNEL);
> -	if (!i3c->DATBASn)
> -		return -ENOMEM;
> -
>  	return i3c_master_register(&i3c->base, &pdev->dev, &renesas_i3c_ops, false);
>  }
>
> @@ -1416,17 +1409,13 @@ static void renesas_i3c_remove(struct platform_device *pdev)
>  	i3c_master_unregister(&i3c->base);
>  }
>
> -static int renesas_i3c_suspend_noirq(struct device *dev)
> +static int renesas_i3c_suspend(struct device *dev)
>  {
>  	struct renesas_i3c *i3c = dev_get_drvdata(dev);
> -	int i, ret;
> +	int ret;
>
>  	i2c_mark_adapter_suspended(&i3c->base.i2c);
>
> -	/* Store Device Address Table values. */
> -	for (i = 0; i < i3c->maxdevs; i++)
> -		i3c->DATBASn[i] = renesas_readl(i3c->regs, DATBAS(i));
> -
>  	ret = reset_control_assert(i3c->presetn);
>  	if (ret)
>  		goto err_mark_resumed;
> @@ -1447,10 +1436,10 @@ static int renesas_i3c_suspend_noirq(struct device *dev)
>  	return ret;
>  }
>
> -static int renesas_i3c_resume_noirq(struct device *dev)
> +static int renesas_i3c_resume(struct device *dev)
>  {
>  	struct renesas_i3c *i3c = dev_get_drvdata(dev);
> -	int i, ret;
> +	int ret;
>
>  	ret = reset_control_deassert(i3c->tresetn);
>  	if (ret)
> @@ -1476,15 +1465,19 @@ static int renesas_i3c_resume_noirq(struct device *dev)
>  	renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYADV |
>  		       MSDVAD_MDYAD(i3c->dyn_addr));
>
> -	/* Restore Device Address Table values. */
> -	for (i = 0; i < i3c->maxdevs; i++)
> -		renesas_writel(i3c->regs, DATBAS(i), i3c->DATBASn[i]);
> -
>  	/* I3C hw init. */
>  	renesas_i3c_hw_init(i3c);
>
>  	i2c_mark_adapter_resumed(&i3c->base.i2c);
>
> +	ret = i3c_master_do_daa_ext(&i3c->base, true);
> +	if (ret)
> +		dev_err(dev, "DAA failed on resume, ret=%d", ret);
> +
> +	/*
> +	 * I3C devices may have retained their dynamic address anyway. Do not
> +	 * fail the resume because of DAA error.
> +	 */
>  	return 0;
>
>  err_clks_disable:
> @@ -1497,8 +1490,7 @@ static int renesas_i3c_resume_noirq(struct device *dev)
>  }
>
>  static const struct dev_pm_ops renesas_i3c_pm_ops = {
> -	NOIRQ_SYSTEM_SLEEP_PM_OPS(renesas_i3c_suspend_noirq,
> -				  renesas_i3c_resume_noirq)
> +	SYSTEM_SLEEP_PM_OPS(renesas_i3c_suspend, renesas_i3c_resume)
>  };
>
>  static const struct of_device_id renesas_i3c_of_ids[] = {
> --
> 2.43.0
>



More information about the linux-i3c mailing list