i3c: renesas: Perform Dynamic Address Assignment on resume

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.

Since renesas_i3c_reset() is not called anymore in atomic context
update it to use read_poll_timeout().

Along with this, struct renesas_i3c::DATBASn and its usage were removed,
as they are no longer needed.

Fixes: e721898631 ("i3c: renesas: Add suspend/resume support")
Cc: stable@vger.kernel.org
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Tested-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Link: https://patch.msgid.link/20260713130545.568657-7-claudiu.beznea+renesas@tuxon.dev
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
This commit is contained in:
Claudiu Beznea 2026-07-13 16:05:34 +03:00 committed by Alexandre Belloni
parent 27cf0ad162
commit fbf26154c4

View File

@ -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;
@ -495,8 +494,8 @@ static int renesas_i3c_reset(struct renesas_i3c *i3c)
renesas_writel(i3c->regs, BCTL, 0);
renesas_set_bit(i3c->regs, RSTCTL, RSTCTL_RI3CRST);
return read_poll_timeout_atomic(renesas_readl, val, !(val & RSTCTL_RI3CRST),
0, 1000, false, i3c->regs, RSTCTL);
return read_poll_timeout(renesas_readl, val, !(val & RSTCTL_RI3CRST),
0, 1000, false, i3c->regs, RSTCTL);
}
static void renesas_i3c_hw_init(struct renesas_i3c *i3c)
@ -1427,12 +1426,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);
}
@ -1443,17 +1436,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;
@ -1474,10 +1463,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)
@ -1503,15 +1492,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);
ret = i3c_master_do_daa_ext(&i3c->base, true);
if (ret)
dev_err(dev, "DAA failed on resume, ret=%d", ret);
i2c_mark_adapter_resumed(&i3c->base.i2c);
/*
* I3C devices may have retained their dynamic address anyway. Do not
* fail the resume because of DAA error.
*/
return 0;
err_clks_disable:
@ -1524,8 +1517,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[] = {