All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/17] i3c: renesas: Suspend to RAM with power loss and runtime PM
@ 2026-05-22 10:17 ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:17 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Hi,

This series adjusts the suspend to RAM code to handle cases where power
to the connected devices is lost during suspend to RAM. The fixes
included in this series are required for that support.

Along with suspend to RAM support, runtime PM support is also added.
Cleanup patches were included to prepare for clean runtime PM support.

Thank you,
Claudiu

Claudiu Beznea (17):
  i3c: renesas: Check that the transfer is valid before accessing it
  i3c: renesas: Use the divider 128
  i3c: renesas: Restore STDBR and EXTBR registers on resume
  i3c: renesas: Follow the reset deassert order used in probe
  i3c: renesas: Fix re-attach
  i3c: renesas: Reset the controller on resume
  i3c: renesas: Perform Dynamic Address Assignment on resume
  i3c: renesas: Clean DATBAS register on detach
  i3c: renesas: Use reset_control_bulk_{assert, deassert}()
  i3c: renesas: Return immediately if there is nothing to transfer
  i3c: renesas: Follow a unified pattern for transfer and command
    initialization
  i3c: renesas: Drop the explicit memset() call
  i3c: renesas: Update HW registers after SW computations are done
  i3c: renesas: Organize structures to avoid unnecessary padding
  i3c: renesas: Use the "dev_name:irq_name" format for the interrupt
    name
  i3c: renesas: Drop unnecessary tab
  i3c: renesas: Add runtime PM support

 drivers/i3c/master/renesas-i3c.c | 378 ++++++++++++++++++++++---------
 1 file changed, 273 insertions(+), 105 deletions(-)

-- 
2.43.0


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 00/17] i3c: renesas: Suspend to RAM with power loss and runtime PM
@ 2026-05-22 10:17 ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:17 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Hi,

This series adjusts the suspend to RAM code to handle cases where power
to the connected devices is lost during suspend to RAM. The fixes
included in this series are required for that support.

Along with suspend to RAM support, runtime PM support is also added.
Cleanup patches were included to prepare for clean runtime PM support.

Thank you,
Claudiu

Claudiu Beznea (17):
  i3c: renesas: Check that the transfer is valid before accessing it
  i3c: renesas: Use the divider 128
  i3c: renesas: Restore STDBR and EXTBR registers on resume
  i3c: renesas: Follow the reset deassert order used in probe
  i3c: renesas: Fix re-attach
  i3c: renesas: Reset the controller on resume
  i3c: renesas: Perform Dynamic Address Assignment on resume
  i3c: renesas: Clean DATBAS register on detach
  i3c: renesas: Use reset_control_bulk_{assert, deassert}()
  i3c: renesas: Return immediately if there is nothing to transfer
  i3c: renesas: Follow a unified pattern for transfer and command
    initialization
  i3c: renesas: Drop the explicit memset() call
  i3c: renesas: Update HW registers after SW computations are done
  i3c: renesas: Organize structures to avoid unnecessary padding
  i3c: renesas: Use the "dev_name:irq_name" format for the interrupt
    name
  i3c: renesas: Drop unnecessary tab
  i3c: renesas: Add runtime PM support

 drivers/i3c/master/renesas-i3c.c | 378 ++++++++++++++++++++++---------
 1 file changed, 273 insertions(+), 105 deletions(-)

-- 
2.43.0


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

* [PATCH 01/17] i3c: renesas: Check that the transfer is valid before accessing it
  2026-05-22 10:17 ` Claudiu Beznea
@ 2026-05-22 10:17   ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:17 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea, stable

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

The Renesas I3C driver uses an asynchronous model to transfer data. It
prepares a struct renesas_i3c_xfer, enqueues it, and waits for completion.
The interrupt handler dequeues the transfer, updates/uses it, and signals
the waiting thread.

If the completion times out, the waiting thread dequeues the transfer and
free it. If an interrupt fires after that, the handler may access freed
memory, leading to crashes.

Check that the transfer is still valid before accessing it in the
interrupt handler.

Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
Cc: stable@vger.kernel.org
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index f39c449922ca..36e3ccbe66b0 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -1014,6 +1014,9 @@ static irqreturn_t renesas_i3c_tx_isr(int irq, void *data)
 
 	scoped_guard(spinlock, &i3c->xferqueue.lock) {
 		xfer = i3c->xferqueue.cur;
+		if (!xfer)
+			return IRQ_HANDLED;
+
 		cmd = xfer->cmds;
 
 		if (xfer->is_i2c_xfer) {
@@ -1054,6 +1057,9 @@ static irqreturn_t renesas_i3c_resp_isr(int irq, void *data)
 
 	scoped_guard(spinlock, &i3c->xferqueue.lock) {
 		xfer = i3c->xferqueue.cur;
+		if (!xfer)
+			return IRQ_HANDLED;
+
 		cmd = xfer->cmds;
 
 		/* Clear the Respone Queue Full status flag*/
@@ -1138,6 +1144,9 @@ static irqreturn_t renesas_i3c_tend_isr(int irq, void *data)
 
 	scoped_guard(spinlock, &i3c->xferqueue.lock) {
 		xfer = i3c->xferqueue.cur;
+		if (!xfer)
+			return IRQ_HANDLED;
+
 		cmd = xfer->cmds;
 
 		if (xfer->is_i2c_xfer) {
@@ -1184,6 +1193,9 @@ static irqreturn_t renesas_i3c_rx_isr(int irq, void *data)
 
 	scoped_guard(spinlock, &i3c->xferqueue.lock) {
 		xfer = i3c->xferqueue.cur;
+		if (!xfer)
+			return IRQ_HANDLED;
+
 		cmd = xfer->cmds;
 
 		if (xfer->is_i2c_xfer) {
@@ -1235,6 +1247,8 @@ static irqreturn_t renesas_i3c_stop_isr(int irq, void *data)
 
 	scoped_guard(spinlock, &i3c->xferqueue.lock) {
 		xfer = i3c->xferqueue.cur;
+		if (!xfer)
+			return IRQ_HANDLED;
 
 		/* read back registers to confirm writes have fully propagated */
 		renesas_writel(i3c->regs, BST, 0);
@@ -1259,6 +1273,9 @@ static irqreturn_t renesas_i3c_start_isr(int irq, void *data)
 
 	scoped_guard(spinlock, &i3c->xferqueue.lock) {
 		xfer = i3c->xferqueue.cur;
+		if (!xfer)
+			return IRQ_HANDLED;
+
 		cmd = xfer->cmds;
 
 		if (xfer->is_i2c_xfer) {
-- 
2.43.0


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 01/17] i3c: renesas: Check that the transfer is valid before accessing it
@ 2026-05-22 10:17   ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:17 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea, stable

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

The Renesas I3C driver uses an asynchronous model to transfer data. It
prepares a struct renesas_i3c_xfer, enqueues it, and waits for completion.
The interrupt handler dequeues the transfer, updates/uses it, and signals
the waiting thread.

If the completion times out, the waiting thread dequeues the transfer and
free it. If an interrupt fires after that, the handler may access freed
memory, leading to crashes.

Check that the transfer is still valid before accessing it in the
interrupt handler.

Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
Cc: stable@vger.kernel.org
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index f39c449922ca..36e3ccbe66b0 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -1014,6 +1014,9 @@ static irqreturn_t renesas_i3c_tx_isr(int irq, void *data)
 
 	scoped_guard(spinlock, &i3c->xferqueue.lock) {
 		xfer = i3c->xferqueue.cur;
+		if (!xfer)
+			return IRQ_HANDLED;
+
 		cmd = xfer->cmds;
 
 		if (xfer->is_i2c_xfer) {
@@ -1054,6 +1057,9 @@ static irqreturn_t renesas_i3c_resp_isr(int irq, void *data)
 
 	scoped_guard(spinlock, &i3c->xferqueue.lock) {
 		xfer = i3c->xferqueue.cur;
+		if (!xfer)
+			return IRQ_HANDLED;
+
 		cmd = xfer->cmds;
 
 		/* Clear the Respone Queue Full status flag*/
@@ -1138,6 +1144,9 @@ static irqreturn_t renesas_i3c_tend_isr(int irq, void *data)
 
 	scoped_guard(spinlock, &i3c->xferqueue.lock) {
 		xfer = i3c->xferqueue.cur;
+		if (!xfer)
+			return IRQ_HANDLED;
+
 		cmd = xfer->cmds;
 
 		if (xfer->is_i2c_xfer) {
@@ -1184,6 +1193,9 @@ static irqreturn_t renesas_i3c_rx_isr(int irq, void *data)
 
 	scoped_guard(spinlock, &i3c->xferqueue.lock) {
 		xfer = i3c->xferqueue.cur;
+		if (!xfer)
+			return IRQ_HANDLED;
+
 		cmd = xfer->cmds;
 
 		if (xfer->is_i2c_xfer) {
@@ -1235,6 +1247,8 @@ static irqreturn_t renesas_i3c_stop_isr(int irq, void *data)
 
 	scoped_guard(spinlock, &i3c->xferqueue.lock) {
 		xfer = i3c->xferqueue.cur;
+		if (!xfer)
+			return IRQ_HANDLED;
 
 		/* read back registers to confirm writes have fully propagated */
 		renesas_writel(i3c->regs, BST, 0);
@@ -1259,6 +1273,9 @@ static irqreturn_t renesas_i3c_start_isr(int irq, void *data)
 
 	scoped_guard(spinlock, &i3c->xferqueue.lock) {
 		xfer = i3c->xferqueue.cur;
+		if (!xfer)
+			return IRQ_HANDLED;
+
 		cmd = xfer->cmds;
 
 		if (xfer->is_i2c_xfer) {
-- 
2.43.0


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

* [PATCH 02/17] i3c: renesas: Use the divider 128
  2026-05-22 10:17 ` Claudiu Beznea
@ 2026-05-22 10:18   ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea, stable

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

The REFCKCTL.IREFCKS field is 3 bits wide, and setting it to 7 selects a
divider of 128 for the internal reference clock. Use this divider value.

Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
Cc: stable@vger.kernel.org
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 36e3ccbe66b0..1917549cf6d5 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -559,7 +559,7 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
 
 	i2c_parse_fw_timings(&m->dev, &t, true);
 
-	for (cks = 0; cks < 7; cks++) {
+	for (cks = 0; cks <= 7; cks++) {
 		/* SCL low-period calculation in Open-drain mode */
 		od_low_ticks = ((i2c_total_ticks * 6) / 10);
 
-- 
2.43.0


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

* [PATCH 02/17] i3c: renesas: Use the divider 128
@ 2026-05-22 10:18   ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea, stable

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

The REFCKCTL.IREFCKS field is 3 bits wide, and setting it to 7 selects a
divider of 128 for the internal reference clock. Use this divider value.

Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
Cc: stable@vger.kernel.org
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 36e3ccbe66b0..1917549cf6d5 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -559,7 +559,7 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
 
 	i2c_parse_fw_timings(&m->dev, &t, true);
 
-	for (cks = 0; cks < 7; cks++) {
+	for (cks = 0; cks <= 7; cks++) {
 		/* SCL low-period calculation in Open-drain mode */
 		od_low_ticks = ((i2c_total_ticks * 6) / 10);
 
-- 
2.43.0


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 03/17] i3c: renesas: Restore STDBR and EXTBR registers on resume
  2026-05-22 10:17 ` Claudiu Beznea
@ 2026-05-22 10:18   ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea, stable

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

The Renesas RZ/G3S supports a power saving state where power to the most
SoC componentes (including I3C) is lost.

The STDBR and EXTBR are configured in initialization phase though the
struct i3c_master_controller_ops::bus_init. Set them on resume function
as well to keep the same state of the controller after a suspend with
power loss and a similar initialization sequence as in bus_init.

Fixes: e7218986319b ("i3c: renesas: Add suspend/resume support")
Cc: stable@vger.kernel.org
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 1917549cf6d5..6c23f956ad2a 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -260,6 +260,7 @@ struct renesas_i3c {
 	u32 dyn_addr;
 	u32 i2c_STDBR;
 	u32 i3c_STDBR;
+	u32 extbr;
 	unsigned long rate;
 	u8 addrs[RENESAS_I3C_MAX_DEVS];
 	struct renesas_i3c_xferqueue xferqueue;
@@ -607,10 +608,9 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
 	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
 
 	/* Extended Bit Rate setting */
-	renesas_writel(i3c->regs, EXTBR, EXTBR_EBRLO(od_low_ticks) |
-					   EXTBR_EBRHO(od_high_ticks) |
-					   EXTBR_EBRLP(pp_low_ticks) |
-					   EXTBR_EBRHP(pp_high_ticks));
+	i3c->extbr = EXTBR_EBRLO(od_low_ticks) | EXTBR_EBRHO(od_high_ticks) |
+		     EXTBR_EBRLP(pp_low_ticks) | EXTBR_EBRHP(pp_high_ticks);
+	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
 
 	renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
 	i3c->refclk_div = cks;
@@ -1447,6 +1447,8 @@ static int renesas_i3c_resume_noirq(struct device *dev)
 		goto err_tresetn;
 
 	/* Re-store I3C registers value. */
+	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
+	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
 	renesas_writel(i3c->regs, REFCKCTL,
 		       REFCKCTL_IREFCKS(i3c->refclk_div));
 	renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYADV |
-- 
2.43.0


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

* [PATCH 03/17] i3c: renesas: Restore STDBR and EXTBR registers on resume
@ 2026-05-22 10:18   ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea, stable

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

The Renesas RZ/G3S supports a power saving state where power to the most
SoC componentes (including I3C) is lost.

The STDBR and EXTBR are configured in initialization phase though the
struct i3c_master_controller_ops::bus_init. Set them on resume function
as well to keep the same state of the controller after a suspend with
power loss and a similar initialization sequence as in bus_init.

Fixes: e7218986319b ("i3c: renesas: Add suspend/resume support")
Cc: stable@vger.kernel.org
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 1917549cf6d5..6c23f956ad2a 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -260,6 +260,7 @@ struct renesas_i3c {
 	u32 dyn_addr;
 	u32 i2c_STDBR;
 	u32 i3c_STDBR;
+	u32 extbr;
 	unsigned long rate;
 	u8 addrs[RENESAS_I3C_MAX_DEVS];
 	struct renesas_i3c_xferqueue xferqueue;
@@ -607,10 +608,9 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
 	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
 
 	/* Extended Bit Rate setting */
-	renesas_writel(i3c->regs, EXTBR, EXTBR_EBRLO(od_low_ticks) |
-					   EXTBR_EBRHO(od_high_ticks) |
-					   EXTBR_EBRLP(pp_low_ticks) |
-					   EXTBR_EBRHP(pp_high_ticks));
+	i3c->extbr = EXTBR_EBRLO(od_low_ticks) | EXTBR_EBRHO(od_high_ticks) |
+		     EXTBR_EBRLP(pp_low_ticks) | EXTBR_EBRHP(pp_high_ticks);
+	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
 
 	renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
 	i3c->refclk_div = cks;
@@ -1447,6 +1447,8 @@ static int renesas_i3c_resume_noirq(struct device *dev)
 		goto err_tresetn;
 
 	/* Re-store I3C registers value. */
+	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
+	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
 	renesas_writel(i3c->regs, REFCKCTL,
 		       REFCKCTL_IREFCKS(i3c->refclk_div));
 	renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYADV |
-- 
2.43.0


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 04/17] i3c: renesas: Follow the reset deassert order used in probe
  2026-05-22 10:17 ` Claudiu Beznea
@ 2026-05-22 10:18   ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea, stable

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Use the same reset deassert order in the resume and probe paths to avoid
potential failures due to ordering differences.

Fixes: e7218986319b ("i3c: renesas: Add suspend/resume support")
Cc: stable@vger.kernel.org
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 6c23f956ad2a..d2f29ed0b6ed 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -1434,17 +1434,17 @@ static int renesas_i3c_resume_noirq(struct device *dev)
 	struct renesas_i3c *i3c = dev_get_drvdata(dev);
 	int i, ret;
 
-	ret = reset_control_deassert(i3c->presetn);
+	ret = reset_control_deassert(i3c->tresetn);
 	if (ret)
 		return ret;
 
-	ret = reset_control_deassert(i3c->tresetn);
+	ret = reset_control_deassert(i3c->presetn);
 	if (ret)
-		goto err_presetn;
+		goto err_tresetn;
 
 	ret = clk_bulk_enable(i3c->num_clks, i3c->clks);
 	if (ret)
-		goto err_tresetn;
+		goto err_presetn;
 
 	/* Re-store I3C registers value. */
 	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
@@ -1465,10 +1465,10 @@ static int renesas_i3c_resume_noirq(struct device *dev)
 
 	return 0;
 
-err_tresetn:
-	reset_control_assert(i3c->tresetn);
 err_presetn:
 	reset_control_assert(i3c->presetn);
+err_tresetn:
+	reset_control_assert(i3c->tresetn);
 	return ret;
 }
 
-- 
2.43.0


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

* [PATCH 04/17] i3c: renesas: Follow the reset deassert order used in probe
@ 2026-05-22 10:18   ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea, stable

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Use the same reset deassert order in the resume and probe paths to avoid
potential failures due to ordering differences.

Fixes: e7218986319b ("i3c: renesas: Add suspend/resume support")
Cc: stable@vger.kernel.org
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 6c23f956ad2a..d2f29ed0b6ed 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -1434,17 +1434,17 @@ static int renesas_i3c_resume_noirq(struct device *dev)
 	struct renesas_i3c *i3c = dev_get_drvdata(dev);
 	int i, ret;
 
-	ret = reset_control_deassert(i3c->presetn);
+	ret = reset_control_deassert(i3c->tresetn);
 	if (ret)
 		return ret;
 
-	ret = reset_control_deassert(i3c->tresetn);
+	ret = reset_control_deassert(i3c->presetn);
 	if (ret)
-		goto err_presetn;
+		goto err_tresetn;
 
 	ret = clk_bulk_enable(i3c->num_clks, i3c->clks);
 	if (ret)
-		goto err_tresetn;
+		goto err_presetn;
 
 	/* Re-store I3C registers value. */
 	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
@@ -1465,10 +1465,10 @@ static int renesas_i3c_resume_noirq(struct device *dev)
 
 	return 0;
 
-err_tresetn:
-	reset_control_assert(i3c->tresetn);
 err_presetn:
 	reset_control_assert(i3c->presetn);
+err_tresetn:
+	reset_control_assert(i3c->tresetn);
 	return ret;
 }
 
-- 
2.43.0


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 05/17] i3c: renesas: Fix re-attach
  2026-05-22 10:17 ` Claudiu Beznea
@ 2026-05-22 10:18   ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea, stable

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

During re-attach, the device may change its position in the i3c->addrs[]
array. As a result, it may use a different Device Address Table Basic
Register (DATBAS), which needs to be reconfigured.

Reconfigure the DATBAS register on re-attach. Along with it update
software caches.

Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
Cc: stable@vger.kernel.org
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index d2f29ed0b6ed..5174a390d668 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -892,10 +892,28 @@ static int renesas_i3c_reattach_i3c_dev(struct i3c_dev_desc *dev,
 	struct i3c_master_controller *m = i3c_dev_get_master(dev);
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
 	struct renesas_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
+	int pos;
+
+	pos = renesas_i3c_get_free_pos(i3c);
+	if (pos < 0)
+		return pos;
+
+	if (data->index != pos) {
+		renesas_writel(i3c->regs, DATBAS(data->index), 0);
+		i3c->addrs[data->index] = 0;
+		i3c->free_pos |= BIT(data->index);
+
+		data->index = pos;
+		i3c->free_pos &= ~BIT(data->index);
+	}
 
 	i3c->addrs[data->index] = dev->info.dyn_addr ? dev->info.dyn_addr :
 							dev->info.static_addr;
 
+	renesas_writel(i3c->regs, DATBAS(data->index),
+		       DATBAS_DVSTAD(dev->info.static_addr) |
+		       datbas_dvdyad_with_parity(i3c->addrs[data->index]));
+
 	return 0;
 }
 
-- 
2.43.0


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

* [PATCH 05/17] i3c: renesas: Fix re-attach
@ 2026-05-22 10:18   ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea, stable

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

During re-attach, the device may change its position in the i3c->addrs[]
array. As a result, it may use a different Device Address Table Basic
Register (DATBAS), which needs to be reconfigured.

Reconfigure the DATBAS register on re-attach. Along with it update
software caches.

Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
Cc: stable@vger.kernel.org
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index d2f29ed0b6ed..5174a390d668 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -892,10 +892,28 @@ static int renesas_i3c_reattach_i3c_dev(struct i3c_dev_desc *dev,
 	struct i3c_master_controller *m = i3c_dev_get_master(dev);
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
 	struct renesas_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
+	int pos;
+
+	pos = renesas_i3c_get_free_pos(i3c);
+	if (pos < 0)
+		return pos;
+
+	if (data->index != pos) {
+		renesas_writel(i3c->regs, DATBAS(data->index), 0);
+		i3c->addrs[data->index] = 0;
+		i3c->free_pos |= BIT(data->index);
+
+		data->index = pos;
+		i3c->free_pos &= ~BIT(data->index);
+	}
 
 	i3c->addrs[data->index] = dev->info.dyn_addr ? dev->info.dyn_addr :
 							dev->info.static_addr;
 
+	renesas_writel(i3c->regs, DATBAS(data->index),
+		       DATBAS_DVSTAD(dev->info.static_addr) |
+		       datbas_dvdyad_with_parity(i3c->addrs[data->index]));
+
 	return 0;
 }
 
-- 
2.43.0


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 06/17] i3c: renesas: Reset the controller on resume
  2026-05-22 10:17 ` Claudiu Beznea
@ 2026-05-22 10:18   ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea, stable

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Reset the controller on resume after enabling the clocks to follow the
same sequence as in probe and avoid potential ordering related failures.

Fixes: e7218986319b ("i3c: renesas: Add suspend/resume support")
Cc: stable@vger.kernel.org
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 5174a390d668..2f3c6ddf75c0 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -1464,6 +1464,10 @@ static int renesas_i3c_resume_noirq(struct device *dev)
 	if (ret)
 		goto err_presetn;
 
+	ret = renesas_i3c_reset(i3c);
+	if (ret)
+		goto err_clks_disable;
+
 	/* Re-store I3C registers value. */
 	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
 	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
@@ -1483,6 +1487,8 @@ static int renesas_i3c_resume_noirq(struct device *dev)
 
 	return 0;
 
+err_clks_disable:
+	clk_bulk_disable(i3c->num_clks, i3c->clks);
 err_presetn:
 	reset_control_assert(i3c->presetn);
 err_tresetn:
-- 
2.43.0


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

* [PATCH 06/17] i3c: renesas: Reset the controller on resume
@ 2026-05-22 10:18   ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea, stable

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Reset the controller on resume after enabling the clocks to follow the
same sequence as in probe and avoid potential ordering related failures.

Fixes: e7218986319b ("i3c: renesas: Add suspend/resume support")
Cc: stable@vger.kernel.org
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 5174a390d668..2f3c6ddf75c0 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -1464,6 +1464,10 @@ static int renesas_i3c_resume_noirq(struct device *dev)
 	if (ret)
 		goto err_presetn;
 
+	ret = renesas_i3c_reset(i3c);
+	if (ret)
+		goto err_clks_disable;
+
 	/* Re-store I3C registers value. */
 	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
 	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
@@ -1483,6 +1487,8 @@ static int renesas_i3c_resume_noirq(struct device *dev)
 
 	return 0;
 
+err_clks_disable:
+	clk_bulk_disable(i3c->num_clks, i3c->clks);
 err_presetn:
 	reset_control_assert(i3c->presetn);
 err_tresetn:
-- 
2.43.0


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 07/17] i3c: renesas: Perform Dynamic Address Assignment on resume
  2026-05-22 10:17 ` Claudiu Beznea
@ 2026-05-22 10:18   ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea, stable

From: Claudiu Beznea <claudiu.beznea.uj@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.

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@vger.kernel.org
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@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


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

* [PATCH 07/17] i3c: renesas: Perform Dynamic Address Assignment on resume
@ 2026-05-22 10:18   ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea, stable

From: Claudiu Beznea <claudiu.beznea.uj@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.

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@vger.kernel.org
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@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


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 08/17] i3c: renesas: Clean DATBAS register on detach
  2026-05-22 10:17 ` Claudiu Beznea
@ 2026-05-22 10:18   ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea, stable

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

The controller uses DATBAS registers on TX/RX logic. Clean the DATBAS
register for the detached I3C device to avoid issues.

Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
Cc: stable@vger.kernel.org
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index c009d0de6a2b..d32646deb69f 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -922,6 +922,8 @@ static void renesas_i3c_detach_i3c_dev(struct i3c_dev_desc *dev)
 	struct i3c_master_controller *m = i3c_dev_get_master(dev);
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
 
+	renesas_writel(i3c->regs, DATBAS(data->index), 0);
+
 	i3c_dev_set_master_data(dev, NULL);
 	i3c->addrs[data->index] = 0;
 	i3c->free_pos |= BIT(data->index);
-- 
2.43.0


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

* [PATCH 08/17] i3c: renesas: Clean DATBAS register on detach
@ 2026-05-22 10:18   ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea, stable

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

The controller uses DATBAS registers on TX/RX logic. Clean the DATBAS
register for the detached I3C device to avoid issues.

Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
Cc: stable@vger.kernel.org
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index c009d0de6a2b..d32646deb69f 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -922,6 +922,8 @@ static void renesas_i3c_detach_i3c_dev(struct i3c_dev_desc *dev)
 	struct i3c_master_controller *m = i3c_dev_get_master(dev);
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
 
+	renesas_writel(i3c->regs, DATBAS(data->index), 0);
+
 	i3c_dev_set_master_data(dev, NULL);
 	i3c->addrs[data->index] = 0;
 	i3c->free_pos |= BIT(data->index);
-- 
2.43.0


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 09/17] i3c: renesas: Use reset_control_bulk_{assert, deassert}()
  2026-05-22 10:17 ` Claudiu Beznea
@ 2026-05-22 10:18   ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Use reset_control_bulk_assert() and reset_control_bulk_deassert() in the
suspend and resume paths to simplify the code.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 30 +++++++++++++-----------------
 1 file changed, 13 insertions(+), 17 deletions(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index d32646deb69f..e5963270d6e5 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -1414,24 +1414,22 @@ static void renesas_i3c_remove(struct platform_device *pdev)
 static int renesas_i3c_suspend(struct device *dev)
 {
 	struct renesas_i3c *i3c = dev_get_drvdata(dev);
+	struct reset_control_bulk_data resets[] = {
+		{ .rstc = i3c->presetn },
+		{ .rstc = i3c->tresetn },
+	};
 	int ret;
 
 	i2c_mark_adapter_suspended(&i3c->base.i2c);
 
-	ret = reset_control_assert(i3c->presetn);
+	ret = reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
 	if (ret)
 		goto err_mark_resumed;
 
-	ret = reset_control_assert(i3c->tresetn);
-	if (ret)
-		goto err_presetn;
-
 	clk_bulk_disable(i3c->num_clks, i3c->clks);
 
 	return 0;
 
-err_presetn:
-	reset_control_deassert(i3c->presetn);
 err_mark_resumed:
 	i2c_mark_adapter_resumed(&i3c->base.i2c);
 
@@ -1441,19 +1439,19 @@ static int renesas_i3c_suspend(struct device *dev)
 static int renesas_i3c_resume(struct device *dev)
 {
 	struct renesas_i3c *i3c = dev_get_drvdata(dev);
+	struct reset_control_bulk_data resets[] = {
+		{ .rstc = i3c->presetn },
+		{ .rstc = i3c->tresetn },
+	};
 	int ret;
 
-	ret = reset_control_deassert(i3c->tresetn);
+	ret = reset_control_bulk_deassert(ARRAY_SIZE(resets), resets);
 	if (ret)
 		return ret;
 
-	ret = reset_control_deassert(i3c->presetn);
-	if (ret)
-		goto err_tresetn;
-
 	ret = clk_bulk_enable(i3c->num_clks, i3c->clks);
 	if (ret)
-		goto err_presetn;
+		goto err_resets_asserted;
 
 	ret = renesas_i3c_reset(i3c);
 	if (ret)
@@ -1484,10 +1482,8 @@ static int renesas_i3c_resume(struct device *dev)
 
 err_clks_disable:
 	clk_bulk_disable(i3c->num_clks, i3c->clks);
-err_presetn:
-	reset_control_assert(i3c->presetn);
-err_tresetn:
-	reset_control_assert(i3c->tresetn);
+err_resets_asserted:
+	reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
 	return ret;
 }
 
-- 
2.43.0


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 09/17] i3c: renesas: Use reset_control_bulk_{assert, deassert}()
@ 2026-05-22 10:18   ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Use reset_control_bulk_assert() and reset_control_bulk_deassert() in the
suspend and resume paths to simplify the code.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 30 +++++++++++++-----------------
 1 file changed, 13 insertions(+), 17 deletions(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index d32646deb69f..e5963270d6e5 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -1414,24 +1414,22 @@ static void renesas_i3c_remove(struct platform_device *pdev)
 static int renesas_i3c_suspend(struct device *dev)
 {
 	struct renesas_i3c *i3c = dev_get_drvdata(dev);
+	struct reset_control_bulk_data resets[] = {
+		{ .rstc = i3c->presetn },
+		{ .rstc = i3c->tresetn },
+	};
 	int ret;
 
 	i2c_mark_adapter_suspended(&i3c->base.i2c);
 
-	ret = reset_control_assert(i3c->presetn);
+	ret = reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
 	if (ret)
 		goto err_mark_resumed;
 
-	ret = reset_control_assert(i3c->tresetn);
-	if (ret)
-		goto err_presetn;
-
 	clk_bulk_disable(i3c->num_clks, i3c->clks);
 
 	return 0;
 
-err_presetn:
-	reset_control_deassert(i3c->presetn);
 err_mark_resumed:
 	i2c_mark_adapter_resumed(&i3c->base.i2c);
 
@@ -1441,19 +1439,19 @@ static int renesas_i3c_suspend(struct device *dev)
 static int renesas_i3c_resume(struct device *dev)
 {
 	struct renesas_i3c *i3c = dev_get_drvdata(dev);
+	struct reset_control_bulk_data resets[] = {
+		{ .rstc = i3c->presetn },
+		{ .rstc = i3c->tresetn },
+	};
 	int ret;
 
-	ret = reset_control_deassert(i3c->tresetn);
+	ret = reset_control_bulk_deassert(ARRAY_SIZE(resets), resets);
 	if (ret)
 		return ret;
 
-	ret = reset_control_deassert(i3c->presetn);
-	if (ret)
-		goto err_tresetn;
-
 	ret = clk_bulk_enable(i3c->num_clks, i3c->clks);
 	if (ret)
-		goto err_presetn;
+		goto err_resets_asserted;
 
 	ret = renesas_i3c_reset(i3c);
 	if (ret)
@@ -1484,10 +1482,8 @@ static int renesas_i3c_resume(struct device *dev)
 
 err_clks_disable:
 	clk_bulk_disable(i3c->num_clks, i3c->clks);
-err_presetn:
-	reset_control_assert(i3c->presetn);
-err_tresetn:
-	reset_control_assert(i3c->tresetn);
+err_resets_asserted:
+	reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
 	return ret;
 }
 
-- 
2.43.0


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

* [PATCH 10/17] i3c: renesas: Return immediately if there is nothing to transfer
  2026-05-22 10:17 ` Claudiu Beznea
@ 2026-05-22 10:18   ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

There is no need to allocate a transfer structure when i2c_nxfers is zero.
Return immediately instead of unnecessarily allocating memory.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index e5963270d6e5..de75125eb013 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -940,13 +940,13 @@ static int renesas_i3c_i2c_xfers(struct i2c_dev_desc *dev,
 	u8 start_bit = CNDCTL_STCND;
 	int i;
 
+	if (!i2c_nxfers)
+		return 0;
+
 	struct renesas_i3c_xfer *xfer __free(kfree) = renesas_i3c_alloc_xfer(i3c, 1);
 	if (!xfer)
 		return -ENOMEM;
 
-	if (!i2c_nxfers)
-		return 0;
-
 	renesas_i3c_bus_enable(m, false);
 
 	init_completion(&xfer->comp);
-- 
2.43.0


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 10/17] i3c: renesas: Return immediately if there is nothing to transfer
@ 2026-05-22 10:18   ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

There is no need to allocate a transfer structure when i2c_nxfers is zero.
Return immediately instead of unnecessarily allocating memory.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index e5963270d6e5..de75125eb013 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -940,13 +940,13 @@ static int renesas_i3c_i2c_xfers(struct i2c_dev_desc *dev,
 	u8 start_bit = CNDCTL_STCND;
 	int i;
 
+	if (!i2c_nxfers)
+		return 0;
+
 	struct renesas_i3c_xfer *xfer __free(kfree) = renesas_i3c_alloc_xfer(i3c, 1);
 	if (!xfer)
 		return -ENOMEM;
 
-	if (!i2c_nxfers)
-		return 0;
-
 	renesas_i3c_bus_enable(m, false);
 
 	init_completion(&xfer->comp);
-- 
2.43.0


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

* [PATCH 11/17] i3c: renesas: Follow a unified pattern for transfer and command initialization
  2026-05-22 10:17 ` Claudiu Beznea
@ 2026-05-22 10:18   ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Follow a unified pattern for transfer and command initialization across
the driver. This keeps the code cleaner and easier to follow. Also, in
some cases the I3C device was enabled before the transfer data structure
was even allocated.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index de75125eb013..12bf4797a70d 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -648,6 +648,10 @@ static int renesas_i3c_daa(struct i3c_master_controller *m)
 	if (!xfer)
 		return -ENOMEM;
 
+	init_completion(&xfer->comp);
+	cmd = xfer->cmds;
+	cmd->rx_count = 0;
+
 	/* Enable I3C bus. */
 	renesas_i3c_bus_enable(m, true);
 
@@ -669,10 +673,6 @@ static int renesas_i3c_daa(struct i3c_master_controller *m)
 		renesas_writel(i3c->regs, DATBAS(pos), datbas_dvdyad_with_parity(ret));
 	}
 
-	init_completion(&xfer->comp);
-	cmd = xfer->cmds;
-	cmd->rx_count = 0;
-
 	ret = renesas_i3c_get_free_pos(i3c);
 	if (ret < 0)
 		return ret;
@@ -760,13 +760,13 @@ static int renesas_i3c_send_ccc_cmd(struct i3c_master_controller *m,
 	if (!xfer)
 		return -ENOMEM;
 
-	renesas_i3c_bus_enable(m, true);
-
 	init_completion(&xfer->comp);
 	cmd = xfer->cmds;
 	cmd->rnw = ccc->rnw;
 	cmd->cmd0 = 0;
 
+	renesas_i3c_bus_enable(m, true);
+
 	/* Calculate the command descriptor. */
 	switch (ccc->id) {
 	case I3C_CCC_SETDASA:
@@ -816,15 +816,15 @@ static int renesas_i3c_i3c_xfers(struct i3c_dev_desc *dev, struct i3c_xfer *i3c_
 	struct renesas_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
 	int i;
 
-	/* Enable I3C bus. */
-	renesas_i3c_bus_enable(m, true);
-
 	struct renesas_i3c_xfer *xfer __free(kfree) = renesas_i3c_alloc_xfer(i3c, 1);
 	if (!xfer)
 		return -ENOMEM;
 
 	init_completion(&xfer->comp);
 
+	/* Enable I3C bus. */
+	renesas_i3c_bus_enable(m, true);
+
 	for (i = 0; i < i3c_nxfers; i++) {
 		struct renesas_i3c_cmd *cmd = xfer->cmds;
 
@@ -947,12 +947,12 @@ static int renesas_i3c_i2c_xfers(struct i2c_dev_desc *dev,
 	if (!xfer)
 		return -ENOMEM;
 
-	renesas_i3c_bus_enable(m, false);
-
 	init_completion(&xfer->comp);
 	xfer->is_i2c_xfer = true;
 	cmd = xfer->cmds;
 
+	renesas_i3c_bus_enable(m, false);
+
 	if (!(renesas_readl(i3c->regs, BCST) & BCST_BFREF)) {
 		cmd->err = -EBUSY;
 		return cmd->err;
-- 
2.43.0


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 11/17] i3c: renesas: Follow a unified pattern for transfer and command initialization
@ 2026-05-22 10:18   ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Follow a unified pattern for transfer and command initialization across
the driver. This keeps the code cleaner and easier to follow. Also, in
some cases the I3C device was enabled before the transfer data structure
was even allocated.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index de75125eb013..12bf4797a70d 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -648,6 +648,10 @@ static int renesas_i3c_daa(struct i3c_master_controller *m)
 	if (!xfer)
 		return -ENOMEM;
 
+	init_completion(&xfer->comp);
+	cmd = xfer->cmds;
+	cmd->rx_count = 0;
+
 	/* Enable I3C bus. */
 	renesas_i3c_bus_enable(m, true);
 
@@ -669,10 +673,6 @@ static int renesas_i3c_daa(struct i3c_master_controller *m)
 		renesas_writel(i3c->regs, DATBAS(pos), datbas_dvdyad_with_parity(ret));
 	}
 
-	init_completion(&xfer->comp);
-	cmd = xfer->cmds;
-	cmd->rx_count = 0;
-
 	ret = renesas_i3c_get_free_pos(i3c);
 	if (ret < 0)
 		return ret;
@@ -760,13 +760,13 @@ static int renesas_i3c_send_ccc_cmd(struct i3c_master_controller *m,
 	if (!xfer)
 		return -ENOMEM;
 
-	renesas_i3c_bus_enable(m, true);
-
 	init_completion(&xfer->comp);
 	cmd = xfer->cmds;
 	cmd->rnw = ccc->rnw;
 	cmd->cmd0 = 0;
 
+	renesas_i3c_bus_enable(m, true);
+
 	/* Calculate the command descriptor. */
 	switch (ccc->id) {
 	case I3C_CCC_SETDASA:
@@ -816,15 +816,15 @@ static int renesas_i3c_i3c_xfers(struct i3c_dev_desc *dev, struct i3c_xfer *i3c_
 	struct renesas_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
 	int i;
 
-	/* Enable I3C bus. */
-	renesas_i3c_bus_enable(m, true);
-
 	struct renesas_i3c_xfer *xfer __free(kfree) = renesas_i3c_alloc_xfer(i3c, 1);
 	if (!xfer)
 		return -ENOMEM;
 
 	init_completion(&xfer->comp);
 
+	/* Enable I3C bus. */
+	renesas_i3c_bus_enable(m, true);
+
 	for (i = 0; i < i3c_nxfers; i++) {
 		struct renesas_i3c_cmd *cmd = xfer->cmds;
 
@@ -947,12 +947,12 @@ static int renesas_i3c_i2c_xfers(struct i2c_dev_desc *dev,
 	if (!xfer)
 		return -ENOMEM;
 
-	renesas_i3c_bus_enable(m, false);
-
 	init_completion(&xfer->comp);
 	xfer->is_i2c_xfer = true;
 	cmd = xfer->cmds;
 
+	renesas_i3c_bus_enable(m, false);
+
 	if (!(renesas_readl(i3c->regs, BCST) & BCST_BFREF)) {
 		cmd->err = -EBUSY;
 		return cmd->err;
-- 
2.43.0


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

* [PATCH 12/17] i3c: renesas: Drop the explicit memset() call
  2026-05-22 10:17 ` Claudiu Beznea
@ 2026-05-22 10:18   ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Drop the explicit memset() call on struct i3c_device_info object, as it is
already initialized at declaration through compiler initialization.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 12bf4797a70d..865e67ac0fd2 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -624,7 +624,6 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
 	i3c->dyn_addr = ret;
 	renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYAD(ret) | MSDVAD_MDYADV);
 
-	memset(&info, 0, sizeof(info));
 	info.dyn_addr = ret;
 	return i3c_master_set_info(&i3c->base, &info);
 }
-- 
2.43.0


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 12/17] i3c: renesas: Drop the explicit memset() call
@ 2026-05-22 10:18   ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Drop the explicit memset() call on struct i3c_device_info object, as it is
already initialized at declaration through compiler initialization.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 12bf4797a70d..865e67ac0fd2 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -624,7 +624,6 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
 	i3c->dyn_addr = ret;
 	renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYAD(ret) | MSDVAD_MDYADV);
 
-	memset(&info, 0, sizeof(info));
 	info.dyn_addr = ret;
 	return i3c_master_set_info(&i3c->base, &info);
 }
-- 
2.43.0


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

* [PATCH 13/17] i3c: renesas: Update HW registers after SW computations are done
  2026-05-22 10:17 ` Claudiu Beznea
@ 2026-05-22 10:18   ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

renesas_i3c_bus_init() performs a number of computations and software
cache updates, interleaving them with hardware register writes. While
this works today, it makes it harder to minimize the time the controller
must remain powered when runtime PM is introduced.

Perform all software computations and cache updates first, then update
the hardware registers. This prepares for future runtime PM support.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 865e67ac0fd2..631c9c5d8038 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -550,10 +550,6 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
 	if (!i3c->rate)
 		return -EINVAL;
 
-	ret = renesas_i3c_reset(i3c);
-	if (ret)
-		return ret;
-
 	i2c_total_ticks = DIV_ROUND_UP(i3c->rate, bus->scl_rate.i2c);
 	i3c_total_ticks = DIV_ROUND_UP(i3c->rate, bus->scl_rate.i3c);
 
@@ -604,27 +600,31 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
 			STDBR_SBRHO(double_SBR, od_high_ticks) |
 			STDBR_SBRLP(pp_low_ticks) |
 			STDBR_SBRHP(pp_high_ticks);
-	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
 
 	/* Extended Bit Rate setting */
 	i3c->extbr = EXTBR_EBRLO(od_low_ticks) | EXTBR_EBRHO(od_high_ticks) |
 		     EXTBR_EBRLP(pp_low_ticks) | EXTBR_EBRHP(pp_high_ticks);
-	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
-
-	renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
-	i3c->refclk_div = cks;
-
-	/* I3C hw init*/
-	renesas_i3c_hw_init(i3c);
 
 	ret = i3c_master_get_free_addr(m, 0);
 	if (ret < 0)
 		return ret;
 
+	info.dyn_addr = ret;
 	i3c->dyn_addr = ret;
-	renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYAD(ret) | MSDVAD_MDYADV);
+	i3c->refclk_div = cks;
+
+	ret = renesas_i3c_reset(i3c);
+	if (ret)
+		return ret;
+
+	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
+	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
+	renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
+	renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYAD(i3c->dyn_addr) | MSDVAD_MDYADV);
+
+	/* I3C hw init*/
+	renesas_i3c_hw_init(i3c);
 
-	info.dyn_addr = ret;
 	return i3c_master_set_info(&i3c->base, &info);
 }
 
-- 
2.43.0


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 13/17] i3c: renesas: Update HW registers after SW computations are done
@ 2026-05-22 10:18   ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

renesas_i3c_bus_init() performs a number of computations and software
cache updates, interleaving them with hardware register writes. While
this works today, it makes it harder to minimize the time the controller
must remain powered when runtime PM is introduced.

Perform all software computations and cache updates first, then update
the hardware registers. This prepares for future runtime PM support.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 865e67ac0fd2..631c9c5d8038 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -550,10 +550,6 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
 	if (!i3c->rate)
 		return -EINVAL;
 
-	ret = renesas_i3c_reset(i3c);
-	if (ret)
-		return ret;
-
 	i2c_total_ticks = DIV_ROUND_UP(i3c->rate, bus->scl_rate.i2c);
 	i3c_total_ticks = DIV_ROUND_UP(i3c->rate, bus->scl_rate.i3c);
 
@@ -604,27 +600,31 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
 			STDBR_SBRHO(double_SBR, od_high_ticks) |
 			STDBR_SBRLP(pp_low_ticks) |
 			STDBR_SBRHP(pp_high_ticks);
-	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
 
 	/* Extended Bit Rate setting */
 	i3c->extbr = EXTBR_EBRLO(od_low_ticks) | EXTBR_EBRHO(od_high_ticks) |
 		     EXTBR_EBRLP(pp_low_ticks) | EXTBR_EBRHP(pp_high_ticks);
-	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
-
-	renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
-	i3c->refclk_div = cks;
-
-	/* I3C hw init*/
-	renesas_i3c_hw_init(i3c);
 
 	ret = i3c_master_get_free_addr(m, 0);
 	if (ret < 0)
 		return ret;
 
+	info.dyn_addr = ret;
 	i3c->dyn_addr = ret;
-	renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYAD(ret) | MSDVAD_MDYADV);
+	i3c->refclk_div = cks;
+
+	ret = renesas_i3c_reset(i3c);
+	if (ret)
+		return ret;
+
+	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
+	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
+	renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
+	renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYAD(i3c->dyn_addr) | MSDVAD_MDYADV);
+
+	/* I3C hw init*/
+	renesas_i3c_hw_init(i3c);
 
-	info.dyn_addr = ret;
 	return i3c_master_set_info(&i3c->base, &info);
 }
 
-- 
2.43.0


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

* [PATCH 14/17] i3c: renesas: Organize structures to avoid unnecessary padding
  2026-05-22 10:17 ` Claudiu Beznea
@ 2026-05-22 10:18   ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Reorder structure members to reduce padding and improve memory layout.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 631c9c5d8038..5614ed99553c 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -221,19 +221,19 @@ enum renesas_i3c_event {
 };
 
 struct renesas_i3c_cmd {
+	const void *tx_buf;
+	void *rx_buf;
+	/* i2c xfer */
+	u8 *i2c_buf;
+	const struct i2c_msg *msg;
+	int i2c_bytes_left;
+	int i2c_is_last;
 	u32 cmd0;
 	u32 len;
-	const void *tx_buf;
 	u32 tx_count;
-	void *rx_buf;
 	u32 rx_count;
 	u32 err;
 	u8 rnw;
-	/* i2c xfer */
-	int i2c_bytes_left;
-	int i2c_is_last;
-	u8 *i2c_buf;
-	const struct i2c_msg *msg;
 };
 
 struct renesas_i3c_xfer {
@@ -253,21 +253,21 @@ struct renesas_i3c_xferqueue {
 };
 
 struct renesas_i3c {
+	void __iomem *regs;
+	struct clk_bulk_data *clks;
+	struct reset_control *presetn;
+	struct reset_control *tresetn;
+	struct renesas_i3c_xferqueue xferqueue;
 	struct i3c_master_controller base;
+	unsigned long rate;
 	enum i3c_internal_state internal_state;
-	u16 maxdevs;
 	u32 free_pos;
 	u32 dyn_addr;
 	u32 i2c_STDBR;
 	u32 i3c_STDBR;
 	u32 extbr;
-	unsigned long rate;
+	u16 maxdevs;
 	u8 addrs[RENESAS_I3C_MAX_DEVS];
-	struct renesas_i3c_xferqueue xferqueue;
-	void __iomem *regs;
-	struct clk_bulk_data *clks;
-	struct reset_control *presetn;
-	struct reset_control *tresetn;
 	u8 num_clks;
 	u8 refclk_div;
 };
-- 
2.43.0


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 14/17] i3c: renesas: Organize structures to avoid unnecessary padding
@ 2026-05-22 10:18   ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Reorder structure members to reduce padding and improve memory layout.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 631c9c5d8038..5614ed99553c 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -221,19 +221,19 @@ enum renesas_i3c_event {
 };
 
 struct renesas_i3c_cmd {
+	const void *tx_buf;
+	void *rx_buf;
+	/* i2c xfer */
+	u8 *i2c_buf;
+	const struct i2c_msg *msg;
+	int i2c_bytes_left;
+	int i2c_is_last;
 	u32 cmd0;
 	u32 len;
-	const void *tx_buf;
 	u32 tx_count;
-	void *rx_buf;
 	u32 rx_count;
 	u32 err;
 	u8 rnw;
-	/* i2c xfer */
-	int i2c_bytes_left;
-	int i2c_is_last;
-	u8 *i2c_buf;
-	const struct i2c_msg *msg;
 };
 
 struct renesas_i3c_xfer {
@@ -253,21 +253,21 @@ struct renesas_i3c_xferqueue {
 };
 
 struct renesas_i3c {
+	void __iomem *regs;
+	struct clk_bulk_data *clks;
+	struct reset_control *presetn;
+	struct reset_control *tresetn;
+	struct renesas_i3c_xferqueue xferqueue;
 	struct i3c_master_controller base;
+	unsigned long rate;
 	enum i3c_internal_state internal_state;
-	u16 maxdevs;
 	u32 free_pos;
 	u32 dyn_addr;
 	u32 i2c_STDBR;
 	u32 i3c_STDBR;
 	u32 extbr;
-	unsigned long rate;
+	u16 maxdevs;
 	u8 addrs[RENESAS_I3C_MAX_DEVS];
-	struct renesas_i3c_xferqueue xferqueue;
-	void __iomem *regs;
-	struct clk_bulk_data *clks;
-	struct reset_control *presetn;
-	struct reset_control *tresetn;
 	u8 num_clks;
 	u8 refclk_div;
 };
-- 
2.43.0


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

* [PATCH 15/17] i3c: renesas: Use the "dev_name:irq_name" format for the interrupt name
  2026-05-22 10:17 ` Claudiu Beznea
@ 2026-05-22 10:18   ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Use the "dev_name:irq_name" format for the interrupt names. This makes it
easier to identify interrupts in systems where multiple devices may request
interrupts with the same name.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 5614ed99553c..e6e05ac03082 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -1385,12 +1385,19 @@ static int renesas_i3c_probe(struct platform_device *pdev)
 		return ret;
 
 	for (i = 0; i < ARRAY_SIZE(renesas_i3c_irqs); i++) {
+		const char *irqname;
+
 		ret = platform_get_irq_byname(pdev, renesas_i3c_irqs[i].name);
 		if (ret < 0)
 			return ret;
 
+		irqname = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s:%s", dev_name(&pdev->dev),
+					 renesas_i3c_irqs[i].desc);
+		if (!irqname)
+			return -ENOMEM;
+
 		ret = devm_request_irq(&pdev->dev, ret, renesas_i3c_irqs[i].isr,
-				       0, renesas_i3c_irqs[i].desc, i3c);
+				       0, irqname, i3c);
 		if (ret)
 			return ret;
 	}
-- 
2.43.0


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 15/17] i3c: renesas: Use the "dev_name:irq_name" format for the interrupt name
@ 2026-05-22 10:18   ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Use the "dev_name:irq_name" format for the interrupt names. This makes it
easier to identify interrupts in systems where multiple devices may request
interrupts with the same name.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 5614ed99553c..e6e05ac03082 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -1385,12 +1385,19 @@ static int renesas_i3c_probe(struct platform_device *pdev)
 		return ret;
 
 	for (i = 0; i < ARRAY_SIZE(renesas_i3c_irqs); i++) {
+		const char *irqname;
+
 		ret = platform_get_irq_byname(pdev, renesas_i3c_irqs[i].name);
 		if (ret < 0)
 			return ret;
 
+		irqname = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s:%s", dev_name(&pdev->dev),
+					 renesas_i3c_irqs[i].desc);
+		if (!irqname)
+			return -ENOMEM;
+
 		ret = devm_request_irq(&pdev->dev, ret, renesas_i3c_irqs[i].isr,
-				       0, renesas_i3c_irqs[i].desc, i3c);
+				       0, irqname, i3c);
 		if (ret)
 			return ret;
 	}
-- 
2.43.0


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

* [PATCH 16/17] i3c: renesas: Drop unnecessary tab
  2026-05-22 10:17 ` Claudiu Beznea
@ 2026-05-22 10:18   ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Remove an unnecessary tab to make the code cleaner.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index e6e05ac03082..a070db4d2440 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -109,7 +109,7 @@
 #define  NCMDQP_DATA_LENGTH(x)	FIELD_PREP(GENMASK(31, 16), x)
 
 #define NRSPQP			0x154 /* Normal Respone Queue */
-#define  NRSPQP_NO_ERROR			0
+#define  NRSPQP_NO_ERROR		0
 #define  NRSPQP_ERROR_CRC		1
 #define  NRSPQP_ERROR_PARITY		2
 #define  NRSPQP_ERROR_FRAME		3
-- 
2.43.0


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 16/17] i3c: renesas: Drop unnecessary tab
@ 2026-05-22 10:18   ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

Remove an unnecessary tab to make the code cleaner.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index e6e05ac03082..a070db4d2440 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -109,7 +109,7 @@
 #define  NCMDQP_DATA_LENGTH(x)	FIELD_PREP(GENMASK(31, 16), x)
 
 #define NRSPQP			0x154 /* Normal Respone Queue */
-#define  NRSPQP_NO_ERROR			0
+#define  NRSPQP_NO_ERROR		0
 #define  NRSPQP_ERROR_CRC		1
 #define  NRSPQP_ERROR_PARITY		2
 #define  NRSPQP_ERROR_FRAME		3
-- 
2.43.0


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

* [PATCH 17/17] i3c: renesas: Add runtime PM support
  2026-05-22 10:17 ` Claudiu Beznea
@ 2026-05-22 10:18   ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

On the SoCs where the Renesas I3C driver is enabled (RZ/G3S and RZ/G3E),
the clocks of the IP are managed through a clock PM domain. To keep the
I3C code simpler, the explicit clock handling was dropped along with the
addition of runtime PM support, in favor of the runtime PM APIs. Only the
code for getting tclk was preserved, as it is necessary to compute the
I3C clock rate.

All the APIs provided to the I3C subsystem through struct
i3c_master_controller_ops are guarded with runtime PM APIs to
enable/disable the controller at runtime.

As the Renesas I3C driver implements an asynchronous transmit model by
preparing a transfer and waiting for its completion through the ISR,
renesas_i3c_abort_xfer() was added to disable interrupts and synchronize
IRQs before runtime suspending the controller. For this, the interrupts
were saved in struct renesas_i3c::irqs. Along with this,
renesas_i3c_wait_xfer() return type was changed to unsigned long.

Along with the clocks, the controller pin configuration is changed
through the provided "sleep" pin configuration.

Add runtime PM support for the Renesas I3C driver.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 183 ++++++++++++++++++++++++++-----
 1 file changed, 156 insertions(+), 27 deletions(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index a070db4d2440..3b9807a89b54 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -21,7 +21,9 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/reset.h>
 #include <linux/slab.h>
 #include "../internals.h"
@@ -199,8 +201,6 @@
 #define RENESAS_I3C_MAX_DEVS	8
 #define I2C_INIT_MSG		-1
 
-#define RENESAS_I3C_TCLK_IDX	1
-
 enum i3c_internal_state {
 	I3C_INTERNAL_STATE_DISABLED,
 	I3C_INTERNAL_STATE_CONTROLLER_IDLE,
@@ -254,12 +254,15 @@ struct renesas_i3c_xferqueue {
 
 struct renesas_i3c {
 	void __iomem *regs;
-	struct clk_bulk_data *clks;
+	struct clk *tclk;
 	struct reset_control *presetn;
 	struct reset_control *tresetn;
+	struct device *dev;
+	int *irqs;
 	struct renesas_i3c_xferqueue xferqueue;
 	struct i3c_master_controller base;
 	unsigned long rate;
+	unsigned int num_irqs;
 	enum i3c_internal_state internal_state;
 	u32 free_pos;
 	u32 dyn_addr;
@@ -268,7 +271,6 @@ struct renesas_i3c {
 	u32 extbr;
 	u16 maxdevs;
 	u8 addrs[RENESAS_I3C_MAX_DEVS];
-	u8 num_clks;
 	u8 refclk_div;
 };
 
@@ -433,7 +435,18 @@ static void renesas_i3c_enqueue_xfer(struct renesas_i3c *i3c, struct renesas_i3c
 	}
 }
 
-static void renesas_i3c_wait_xfer(struct renesas_i3c *i3c, struct renesas_i3c_xfer *xfer)
+static void renesas_i3c_abort_xfer(struct renesas_i3c *i3c)
+{
+	/* Disable all interrupts */
+	renesas_writel(i3c->regs, BIE, 0);
+	renesas_writel(i3c->regs, NTIE, 0);
+
+	/* Synchronize IRQs. */
+	for (unsigned int i = 0; i < i3c->num_irqs; i++)
+		synchronize_irq(i3c->irqs[i]);
+}
+
+static unsigned long renesas_i3c_wait_xfer(struct renesas_i3c *i3c, struct renesas_i3c_xfer *xfer)
 {
 	unsigned long time_left;
 
@@ -442,6 +455,8 @@ static void renesas_i3c_wait_xfer(struct renesas_i3c *i3c, struct renesas_i3c_xf
 	time_left = wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000));
 	if (!time_left)
 		renesas_i3c_dequeue_xfer(i3c, xfer);
+
+	return time_left;
 }
 
 static void renesas_i3c_set_prts(struct renesas_i3c *i3c, u32 val)
@@ -475,6 +490,12 @@ static void renesas_i3c_bus_enable(struct i3c_master_controller *m, bool i3c_mod
 static int renesas_i3c_reset(struct renesas_i3c *i3c)
 {
 	u32 val;
+	int ret;
+
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
 
 	renesas_writel(i3c->regs, BCTL, 0);
 	renesas_set_bit(i3c->regs, RSTCTL, RSTCTL_RI3CRST);
@@ -546,7 +567,7 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
 	int od_high_ticks, od_low_ticks, i2c_total_ticks;
 	int ret;
 
-	i3c->rate = clk_get_rate(i3c->clks[RENESAS_I3C_TCLK_IDX].clk);
+	i3c->rate = clk_get_rate(i3c->tclk);
 	if (!i3c->rate)
 		return -EINVAL;
 
@@ -617,6 +638,11 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
 	if (ret)
 		return ret;
 
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
 	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
 	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
 	renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
@@ -639,6 +665,7 @@ static int renesas_i3c_daa(struct i3c_master_controller *m)
 {
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
 	struct renesas_i3c_cmd *cmd;
+	unsigned long time_left;
 	u32 olddevs, newdevs;
 	u8 last_addr = 0, pos;
 	int ret;
@@ -651,6 +678,11 @@ static int renesas_i3c_daa(struct i3c_master_controller *m)
 	cmd = xfer->cmds;
 	cmd->rx_count = 0;
 
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
 	/* Enable I3C bus. */
 	renesas_i3c_bus_enable(m, true);
 
@@ -685,7 +717,9 @@ static int renesas_i3c_daa(struct i3c_master_controller *m)
 		    NCMDQP_CMD(I3C_CCC_ENTDAA) | NCMDQP_DEV_INDEX(ret) |
 		    NCMDQP_DEV_COUNT(i3c->maxdevs - ret) | NCMDQP_TOC;
 
-	renesas_i3c_wait_xfer(i3c, xfer);
+	time_left = renesas_i3c_wait_xfer(i3c, xfer);
+	if (!time_left)
+		renesas_i3c_abort_xfer(i3c);
 
 	newdevs = GENMASK(i3c->maxdevs - cmd->rx_count - 1, 0);
 	newdevs &= ~olddevs;
@@ -747,6 +781,7 @@ static int renesas_i3c_send_ccc_cmd(struct i3c_master_controller *m,
 {
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
 	struct renesas_i3c_cmd *cmd;
+	unsigned long time_left;
 	int ret, pos = 0;
 
 	if (ccc->id & I3C_CCC_DIRECT) {
@@ -764,6 +799,11 @@ static int renesas_i3c_send_ccc_cmd(struct i3c_master_controller *m,
 	cmd->rnw = ccc->rnw;
 	cmd->cmd0 = 0;
 
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
 	renesas_i3c_bus_enable(m, true);
 
 	/* Calculate the command descriptor. */
@@ -798,7 +838,9 @@ static int renesas_i3c_send_ccc_cmd(struct i3c_master_controller *m,
 		}
 	}
 
-	renesas_i3c_wait_xfer(i3c, xfer);
+	time_left = renesas_i3c_wait_xfer(i3c, xfer);
+	if (!time_left)
+		renesas_i3c_abort_xfer(i3c);
 
 	ret = xfer->ret;
 	if (ret)
@@ -813,7 +855,9 @@ static int renesas_i3c_i3c_xfers(struct i3c_dev_desc *dev, struct i3c_xfer *i3c_
 	struct i3c_master_controller *m = i3c_dev_get_master(dev);
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
 	struct renesas_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
-	int i;
+	unsigned long time_left;
+	bool abort_xfer = false;
+	int i, ret;
 
 	struct renesas_i3c_xfer *xfer __free(kfree) = renesas_i3c_alloc_xfer(i3c, 1);
 	if (!xfer)
@@ -821,6 +865,11 @@ static int renesas_i3c_i3c_xfers(struct i3c_dev_desc *dev, struct i3c_xfer *i3c_
 
 	init_completion(&xfer->comp);
 
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
 	/* Enable I3C bus. */
 	renesas_i3c_bus_enable(m, true);
 
@@ -852,9 +901,14 @@ static int renesas_i3c_i3c_xfers(struct i3c_dev_desc *dev, struct i3c_xfer *i3c_
 				renesas_set_bit(i3c->regs, NTIE, NTIE_TDBEIE0);
 		}
 
-		renesas_i3c_wait_xfer(i3c, xfer);
+		time_left = renesas_i3c_wait_xfer(i3c, xfer);
+		if (!time_left)
+			abort_xfer = true;
 	}
 
+	if (abort_xfer)
+		renesas_i3c_abort_xfer(i3c);
+
 	return 0;
 }
 
@@ -863,12 +917,17 @@ static int renesas_i3c_attach_i3c_dev(struct i3c_dev_desc *dev)
 	struct i3c_master_controller *m = i3c_dev_get_master(dev);
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
 	struct renesas_i3c_i2c_dev_data *data;
-	int pos;
+	int pos, ret;
 
 	pos = renesas_i3c_get_free_pos(i3c);
 	if (pos < 0)
 		return pos;
 
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
 	data = kzalloc_obj(*data);
 	if (!data)
 		return -ENOMEM;
@@ -890,12 +949,17 @@ static int renesas_i3c_reattach_i3c_dev(struct i3c_dev_desc *dev,
 	struct i3c_master_controller *m = i3c_dev_get_master(dev);
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
 	struct renesas_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
-	int pos;
+	int pos, ret;
 
 	pos = renesas_i3c_get_free_pos(i3c);
 	if (pos < 0)
 		return pos;
 
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
 	if (data->index != pos) {
 		renesas_writel(i3c->regs, DATBAS(data->index), 0);
 		i3c->addrs[data->index] = 0;
@@ -920,6 +984,12 @@ static void renesas_i3c_detach_i3c_dev(struct i3c_dev_desc *dev)
 	struct renesas_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
 	struct i3c_master_controller *m = i3c_dev_get_master(dev);
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
+	int ret;
+
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return;
 
 	renesas_writel(i3c->regs, DATBAS(data->index), 0);
 
@@ -937,7 +1007,9 @@ static int renesas_i3c_i2c_xfers(struct i2c_dev_desc *dev,
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
 	struct renesas_i3c_cmd *cmd;
 	u8 start_bit = CNDCTL_STCND;
-	int i;
+	unsigned long time_left;
+	bool abort_xfer = false;
+	int i, ret;
 
 	if (!i2c_nxfers)
 		return 0;
@@ -950,6 +1022,11 @@ static int renesas_i3c_i2c_xfers(struct i2c_dev_desc *dev,
 	xfer->is_i2c_xfer = true;
 	cmd = xfer->cmds;
 
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
 	renesas_i3c_bus_enable(m, false);
 
 	if (!(renesas_readl(i3c->regs, BCST) & BCST_BFREF)) {
@@ -976,7 +1053,9 @@ static int renesas_i3c_i2c_xfers(struct i2c_dev_desc *dev,
 
 		renesas_set_bit(i3c->regs, NTSTE, NTSTE_TDBEE0);
 
-		wait_for_completion_timeout(&xfer->comp, m->i2c.timeout);
+		time_left = wait_for_completion_timeout(&xfer->comp, m->i2c.timeout);
+		if (!time_left)
+			abort_xfer = true;
 
 		if (cmd->err)
 			break;
@@ -985,6 +1064,10 @@ static int renesas_i3c_i2c_xfers(struct i2c_dev_desc *dev,
 	}
 
 	renesas_i3c_dequeue_xfer(i3c, xfer);
+
+	if (abort_xfer)
+		renesas_i3c_abort_xfer(i3c);
+
 	return cmd->err;
 }
 
@@ -1347,6 +1430,11 @@ static const struct renesas_i3c_irq_desc renesas_i3c_irqs[] = {
 	{ .name = "nack", .isr = renesas_i3c_tend_isr, .desc = "i3c-nack" },
 };
 
+static void renesas_i3c_dont_use_autosuspend(void *data)
+{
+	pm_runtime_dont_use_autosuspend(data);
+}
+
 static int renesas_i3c_probe(struct platform_device *pdev)
 {
 	struct renesas_i3c *i3c;
@@ -1360,12 +1448,21 @@ static int renesas_i3c_probe(struct platform_device *pdev)
 	if (IS_ERR(i3c->regs))
 		return PTR_ERR(i3c->regs);
 
-	ret = devm_clk_bulk_get_all_enabled(&pdev->dev, &i3c->clks);
-	if (ret <= RENESAS_I3C_TCLK_IDX)
-		return dev_err_probe(&pdev->dev, ret < 0 ? ret : -EINVAL,
-				     "Failed to get clocks (need > %d, got %d)\n",
-				     RENESAS_I3C_TCLK_IDX, ret);
-	i3c->num_clks = ret;
+	i3c->tclk = devm_clk_get(&pdev->dev, "tclk");
+	if (IS_ERR(i3c->tclk))
+		return dev_err_probe(&pdev->dev, PTR_ERR(i3c->tclk), "Failed to get tclk");
+
+	i3c->dev = &pdev->dev;
+	pm_runtime_set_autosuspend_delay(&pdev->dev, 300);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	ret = devm_add_action_or_reset(&pdev->dev, renesas_i3c_dont_use_autosuspend,
+				       i3c->dev);
+	if (ret)
+		return ret;
+
+	ret = devm_pm_runtime_enable(&pdev->dev);
+	if (ret)
+		return ret;
 
 	i3c->tresetn = devm_reset_control_get_optional_exclusive_deasserted(&pdev->dev, "tresetn");
 	if (IS_ERR(i3c->tresetn))
@@ -1384,19 +1481,25 @@ static int renesas_i3c_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	i3c->num_irqs = ARRAY_SIZE(renesas_i3c_irqs);
+	i3c->irqs = devm_kcalloc(&pdev->dev, i3c->num_irqs, sizeof(*i3c->irqs), GFP_KERNEL);
+	if (!i3c->irqs)
+		return -ENOMEM;
+
 	for (i = 0; i < ARRAY_SIZE(renesas_i3c_irqs); i++) {
 		const char *irqname;
 
 		ret = platform_get_irq_byname(pdev, renesas_i3c_irqs[i].name);
 		if (ret < 0)
 			return ret;
+		i3c->irqs[i] = ret;
 
 		irqname = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s:%s", dev_name(&pdev->dev),
 					 renesas_i3c_irqs[i].desc);
 		if (!irqname)
 			return -ENOMEM;
 
-		ret = devm_request_irq(&pdev->dev, ret, renesas_i3c_irqs[i].isr,
+		ret = devm_request_irq(&pdev->dev, i3c->irqs[i], renesas_i3c_irqs[i].isr,
 				       0, irqname, i3c);
 		if (ret)
 			return ret;
@@ -1432,10 +1535,14 @@ static int renesas_i3c_suspend(struct device *dev)
 	if (ret)
 		goto err_mark_resumed;
 
-	clk_bulk_disable(i3c->num_clks, i3c->clks);
+	ret = pm_runtime_force_suspend(dev);
+	if (ret)
+		goto err_resets_deassert;
 
 	return 0;
 
+err_resets_deassert:
+	reset_control_bulk_deassert(ARRAY_SIZE(resets), resets);
 err_mark_resumed:
 	i2c_mark_adapter_resumed(&i3c->base.i2c);
 
@@ -1451,17 +1558,22 @@ static int renesas_i3c_resume(struct device *dev)
 	};
 	int ret;
 
+	ret = pm_runtime_force_resume(dev);
+	if (ret)
+		return ret;
+
 	ret = reset_control_bulk_deassert(ARRAY_SIZE(resets), resets);
 	if (ret)
 		return ret;
 
-	ret = clk_bulk_enable(i3c->num_clks, i3c->clks);
+	ret = renesas_i3c_reset(i3c);
 	if (ret)
 		goto err_resets_asserted;
 
-	ret = renesas_i3c_reset(i3c);
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
 	if (ret)
-		goto err_clks_disable;
+		goto err_resets_asserted;
 
 	/* Re-store I3C registers value. */
 	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
@@ -1486,14 +1598,31 @@ static int renesas_i3c_resume(struct device *dev)
 	 */
 	return 0;
 
-err_clks_disable:
-	clk_bulk_disable(i3c->num_clks, i3c->clks);
 err_resets_asserted:
+	/*
+	 * If this happens, there is no way to recover from this state without
+	 * reloading the driver. We want to avoid keeping the reset line
+	 * deasserted unnecessarily. The runtime paths will still work correctly
+	 * even if the IP registers are accessed while reset is asserted (e.g.
+	 * if a runtime path is triggered after a failed resume). Checked on
+	 * RZ/G3S.
+	 */
 	reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
 	return ret;
 }
 
+static int renesas_i3c_runtime_suspend(struct device *dev)
+{
+	return pinctrl_pm_select_sleep_state(dev);
+}
+
+static int renesas_i3c_runtime_resume(struct device *dev)
+{
+	return pinctrl_pm_select_default_state(dev);
+}
+
 static const struct dev_pm_ops renesas_i3c_pm_ops = {
+	RUNTIME_PM_OPS(renesas_i3c_runtime_suspend, renesas_i3c_runtime_resume, NULL)
 	SYSTEM_SLEEP_PM_OPS(renesas_i3c_suspend, renesas_i3c_resume)
 };
 
-- 
2.43.0


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* [PATCH 17/17] i3c: renesas: Add runtime PM support
@ 2026-05-22 10:18   ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-22 10:18 UTC (permalink / raw)
  To: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, Frank.Li,
	p.zabel
  Cc: claudiu.beznea, claudiu.beznea, linux-i3c, linux-kernel,
	linux-renesas-soc, Claudiu Beznea

From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

On the SoCs where the Renesas I3C driver is enabled (RZ/G3S and RZ/G3E),
the clocks of the IP are managed through a clock PM domain. To keep the
I3C code simpler, the explicit clock handling was dropped along with the
addition of runtime PM support, in favor of the runtime PM APIs. Only the
code for getting tclk was preserved, as it is necessary to compute the
I3C clock rate.

All the APIs provided to the I3C subsystem through struct
i3c_master_controller_ops are guarded with runtime PM APIs to
enable/disable the controller at runtime.

As the Renesas I3C driver implements an asynchronous transmit model by
preparing a transfer and waiting for its completion through the ISR,
renesas_i3c_abort_xfer() was added to disable interrupts and synchronize
IRQs before runtime suspending the controller. For this, the interrupts
were saved in struct renesas_i3c::irqs. Along with this,
renesas_i3c_wait_xfer() return type was changed to unsigned long.

Along with the clocks, the controller pin configuration is changed
through the provided "sleep" pin configuration.

Add runtime PM support for the Renesas I3C driver.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/i3c/master/renesas-i3c.c | 183 ++++++++++++++++++++++++++-----
 1 file changed, 156 insertions(+), 27 deletions(-)

diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index a070db4d2440..3b9807a89b54 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -21,7 +21,9 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/reset.h>
 #include <linux/slab.h>
 #include "../internals.h"
@@ -199,8 +201,6 @@
 #define RENESAS_I3C_MAX_DEVS	8
 #define I2C_INIT_MSG		-1
 
-#define RENESAS_I3C_TCLK_IDX	1
-
 enum i3c_internal_state {
 	I3C_INTERNAL_STATE_DISABLED,
 	I3C_INTERNAL_STATE_CONTROLLER_IDLE,
@@ -254,12 +254,15 @@ struct renesas_i3c_xferqueue {
 
 struct renesas_i3c {
 	void __iomem *regs;
-	struct clk_bulk_data *clks;
+	struct clk *tclk;
 	struct reset_control *presetn;
 	struct reset_control *tresetn;
+	struct device *dev;
+	int *irqs;
 	struct renesas_i3c_xferqueue xferqueue;
 	struct i3c_master_controller base;
 	unsigned long rate;
+	unsigned int num_irqs;
 	enum i3c_internal_state internal_state;
 	u32 free_pos;
 	u32 dyn_addr;
@@ -268,7 +271,6 @@ struct renesas_i3c {
 	u32 extbr;
 	u16 maxdevs;
 	u8 addrs[RENESAS_I3C_MAX_DEVS];
-	u8 num_clks;
 	u8 refclk_div;
 };
 
@@ -433,7 +435,18 @@ static void renesas_i3c_enqueue_xfer(struct renesas_i3c *i3c, struct renesas_i3c
 	}
 }
 
-static void renesas_i3c_wait_xfer(struct renesas_i3c *i3c, struct renesas_i3c_xfer *xfer)
+static void renesas_i3c_abort_xfer(struct renesas_i3c *i3c)
+{
+	/* Disable all interrupts */
+	renesas_writel(i3c->regs, BIE, 0);
+	renesas_writel(i3c->regs, NTIE, 0);
+
+	/* Synchronize IRQs. */
+	for (unsigned int i = 0; i < i3c->num_irqs; i++)
+		synchronize_irq(i3c->irqs[i]);
+}
+
+static unsigned long renesas_i3c_wait_xfer(struct renesas_i3c *i3c, struct renesas_i3c_xfer *xfer)
 {
 	unsigned long time_left;
 
@@ -442,6 +455,8 @@ static void renesas_i3c_wait_xfer(struct renesas_i3c *i3c, struct renesas_i3c_xf
 	time_left = wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000));
 	if (!time_left)
 		renesas_i3c_dequeue_xfer(i3c, xfer);
+
+	return time_left;
 }
 
 static void renesas_i3c_set_prts(struct renesas_i3c *i3c, u32 val)
@@ -475,6 +490,12 @@ static void renesas_i3c_bus_enable(struct i3c_master_controller *m, bool i3c_mod
 static int renesas_i3c_reset(struct renesas_i3c *i3c)
 {
 	u32 val;
+	int ret;
+
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
 
 	renesas_writel(i3c->regs, BCTL, 0);
 	renesas_set_bit(i3c->regs, RSTCTL, RSTCTL_RI3CRST);
@@ -546,7 +567,7 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
 	int od_high_ticks, od_low_ticks, i2c_total_ticks;
 	int ret;
 
-	i3c->rate = clk_get_rate(i3c->clks[RENESAS_I3C_TCLK_IDX].clk);
+	i3c->rate = clk_get_rate(i3c->tclk);
 	if (!i3c->rate)
 		return -EINVAL;
 
@@ -617,6 +638,11 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
 	if (ret)
 		return ret;
 
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
 	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
 	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
 	renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
@@ -639,6 +665,7 @@ static int renesas_i3c_daa(struct i3c_master_controller *m)
 {
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
 	struct renesas_i3c_cmd *cmd;
+	unsigned long time_left;
 	u32 olddevs, newdevs;
 	u8 last_addr = 0, pos;
 	int ret;
@@ -651,6 +678,11 @@ static int renesas_i3c_daa(struct i3c_master_controller *m)
 	cmd = xfer->cmds;
 	cmd->rx_count = 0;
 
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
 	/* Enable I3C bus. */
 	renesas_i3c_bus_enable(m, true);
 
@@ -685,7 +717,9 @@ static int renesas_i3c_daa(struct i3c_master_controller *m)
 		    NCMDQP_CMD(I3C_CCC_ENTDAA) | NCMDQP_DEV_INDEX(ret) |
 		    NCMDQP_DEV_COUNT(i3c->maxdevs - ret) | NCMDQP_TOC;
 
-	renesas_i3c_wait_xfer(i3c, xfer);
+	time_left = renesas_i3c_wait_xfer(i3c, xfer);
+	if (!time_left)
+		renesas_i3c_abort_xfer(i3c);
 
 	newdevs = GENMASK(i3c->maxdevs - cmd->rx_count - 1, 0);
 	newdevs &= ~olddevs;
@@ -747,6 +781,7 @@ static int renesas_i3c_send_ccc_cmd(struct i3c_master_controller *m,
 {
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
 	struct renesas_i3c_cmd *cmd;
+	unsigned long time_left;
 	int ret, pos = 0;
 
 	if (ccc->id & I3C_CCC_DIRECT) {
@@ -764,6 +799,11 @@ static int renesas_i3c_send_ccc_cmd(struct i3c_master_controller *m,
 	cmd->rnw = ccc->rnw;
 	cmd->cmd0 = 0;
 
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
 	renesas_i3c_bus_enable(m, true);
 
 	/* Calculate the command descriptor. */
@@ -798,7 +838,9 @@ static int renesas_i3c_send_ccc_cmd(struct i3c_master_controller *m,
 		}
 	}
 
-	renesas_i3c_wait_xfer(i3c, xfer);
+	time_left = renesas_i3c_wait_xfer(i3c, xfer);
+	if (!time_left)
+		renesas_i3c_abort_xfer(i3c);
 
 	ret = xfer->ret;
 	if (ret)
@@ -813,7 +855,9 @@ static int renesas_i3c_i3c_xfers(struct i3c_dev_desc *dev, struct i3c_xfer *i3c_
 	struct i3c_master_controller *m = i3c_dev_get_master(dev);
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
 	struct renesas_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
-	int i;
+	unsigned long time_left;
+	bool abort_xfer = false;
+	int i, ret;
 
 	struct renesas_i3c_xfer *xfer __free(kfree) = renesas_i3c_alloc_xfer(i3c, 1);
 	if (!xfer)
@@ -821,6 +865,11 @@ static int renesas_i3c_i3c_xfers(struct i3c_dev_desc *dev, struct i3c_xfer *i3c_
 
 	init_completion(&xfer->comp);
 
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
 	/* Enable I3C bus. */
 	renesas_i3c_bus_enable(m, true);
 
@@ -852,9 +901,14 @@ static int renesas_i3c_i3c_xfers(struct i3c_dev_desc *dev, struct i3c_xfer *i3c_
 				renesas_set_bit(i3c->regs, NTIE, NTIE_TDBEIE0);
 		}
 
-		renesas_i3c_wait_xfer(i3c, xfer);
+		time_left = renesas_i3c_wait_xfer(i3c, xfer);
+		if (!time_left)
+			abort_xfer = true;
 	}
 
+	if (abort_xfer)
+		renesas_i3c_abort_xfer(i3c);
+
 	return 0;
 }
 
@@ -863,12 +917,17 @@ static int renesas_i3c_attach_i3c_dev(struct i3c_dev_desc *dev)
 	struct i3c_master_controller *m = i3c_dev_get_master(dev);
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
 	struct renesas_i3c_i2c_dev_data *data;
-	int pos;
+	int pos, ret;
 
 	pos = renesas_i3c_get_free_pos(i3c);
 	if (pos < 0)
 		return pos;
 
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
 	data = kzalloc_obj(*data);
 	if (!data)
 		return -ENOMEM;
@@ -890,12 +949,17 @@ static int renesas_i3c_reattach_i3c_dev(struct i3c_dev_desc *dev,
 	struct i3c_master_controller *m = i3c_dev_get_master(dev);
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
 	struct renesas_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
-	int pos;
+	int pos, ret;
 
 	pos = renesas_i3c_get_free_pos(i3c);
 	if (pos < 0)
 		return pos;
 
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
 	if (data->index != pos) {
 		renesas_writel(i3c->regs, DATBAS(data->index), 0);
 		i3c->addrs[data->index] = 0;
@@ -920,6 +984,12 @@ static void renesas_i3c_detach_i3c_dev(struct i3c_dev_desc *dev)
 	struct renesas_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
 	struct i3c_master_controller *m = i3c_dev_get_master(dev);
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
+	int ret;
+
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return;
 
 	renesas_writel(i3c->regs, DATBAS(data->index), 0);
 
@@ -937,7 +1007,9 @@ static int renesas_i3c_i2c_xfers(struct i2c_dev_desc *dev,
 	struct renesas_i3c *i3c = to_renesas_i3c(m);
 	struct renesas_i3c_cmd *cmd;
 	u8 start_bit = CNDCTL_STCND;
-	int i;
+	unsigned long time_left;
+	bool abort_xfer = false;
+	int i, ret;
 
 	if (!i2c_nxfers)
 		return 0;
@@ -950,6 +1022,11 @@ static int renesas_i3c_i2c_xfers(struct i2c_dev_desc *dev,
 	xfer->is_i2c_xfer = true;
 	cmd = xfer->cmds;
 
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
 	renesas_i3c_bus_enable(m, false);
 
 	if (!(renesas_readl(i3c->regs, BCST) & BCST_BFREF)) {
@@ -976,7 +1053,9 @@ static int renesas_i3c_i2c_xfers(struct i2c_dev_desc *dev,
 
 		renesas_set_bit(i3c->regs, NTSTE, NTSTE_TDBEE0);
 
-		wait_for_completion_timeout(&xfer->comp, m->i2c.timeout);
+		time_left = wait_for_completion_timeout(&xfer->comp, m->i2c.timeout);
+		if (!time_left)
+			abort_xfer = true;
 
 		if (cmd->err)
 			break;
@@ -985,6 +1064,10 @@ static int renesas_i3c_i2c_xfers(struct i2c_dev_desc *dev,
 	}
 
 	renesas_i3c_dequeue_xfer(i3c, xfer);
+
+	if (abort_xfer)
+		renesas_i3c_abort_xfer(i3c);
+
 	return cmd->err;
 }
 
@@ -1347,6 +1430,11 @@ static const struct renesas_i3c_irq_desc renesas_i3c_irqs[] = {
 	{ .name = "nack", .isr = renesas_i3c_tend_isr, .desc = "i3c-nack" },
 };
 
+static void renesas_i3c_dont_use_autosuspend(void *data)
+{
+	pm_runtime_dont_use_autosuspend(data);
+}
+
 static int renesas_i3c_probe(struct platform_device *pdev)
 {
 	struct renesas_i3c *i3c;
@@ -1360,12 +1448,21 @@ static int renesas_i3c_probe(struct platform_device *pdev)
 	if (IS_ERR(i3c->regs))
 		return PTR_ERR(i3c->regs);
 
-	ret = devm_clk_bulk_get_all_enabled(&pdev->dev, &i3c->clks);
-	if (ret <= RENESAS_I3C_TCLK_IDX)
-		return dev_err_probe(&pdev->dev, ret < 0 ? ret : -EINVAL,
-				     "Failed to get clocks (need > %d, got %d)\n",
-				     RENESAS_I3C_TCLK_IDX, ret);
-	i3c->num_clks = ret;
+	i3c->tclk = devm_clk_get(&pdev->dev, "tclk");
+	if (IS_ERR(i3c->tclk))
+		return dev_err_probe(&pdev->dev, PTR_ERR(i3c->tclk), "Failed to get tclk");
+
+	i3c->dev = &pdev->dev;
+	pm_runtime_set_autosuspend_delay(&pdev->dev, 300);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	ret = devm_add_action_or_reset(&pdev->dev, renesas_i3c_dont_use_autosuspend,
+				       i3c->dev);
+	if (ret)
+		return ret;
+
+	ret = devm_pm_runtime_enable(&pdev->dev);
+	if (ret)
+		return ret;
 
 	i3c->tresetn = devm_reset_control_get_optional_exclusive_deasserted(&pdev->dev, "tresetn");
 	if (IS_ERR(i3c->tresetn))
@@ -1384,19 +1481,25 @@ static int renesas_i3c_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	i3c->num_irqs = ARRAY_SIZE(renesas_i3c_irqs);
+	i3c->irqs = devm_kcalloc(&pdev->dev, i3c->num_irqs, sizeof(*i3c->irqs), GFP_KERNEL);
+	if (!i3c->irqs)
+		return -ENOMEM;
+
 	for (i = 0; i < ARRAY_SIZE(renesas_i3c_irqs); i++) {
 		const char *irqname;
 
 		ret = platform_get_irq_byname(pdev, renesas_i3c_irqs[i].name);
 		if (ret < 0)
 			return ret;
+		i3c->irqs[i] = ret;
 
 		irqname = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s:%s", dev_name(&pdev->dev),
 					 renesas_i3c_irqs[i].desc);
 		if (!irqname)
 			return -ENOMEM;
 
-		ret = devm_request_irq(&pdev->dev, ret, renesas_i3c_irqs[i].isr,
+		ret = devm_request_irq(&pdev->dev, i3c->irqs[i], renesas_i3c_irqs[i].isr,
 				       0, irqname, i3c);
 		if (ret)
 			return ret;
@@ -1432,10 +1535,14 @@ static int renesas_i3c_suspend(struct device *dev)
 	if (ret)
 		goto err_mark_resumed;
 
-	clk_bulk_disable(i3c->num_clks, i3c->clks);
+	ret = pm_runtime_force_suspend(dev);
+	if (ret)
+		goto err_resets_deassert;
 
 	return 0;
 
+err_resets_deassert:
+	reset_control_bulk_deassert(ARRAY_SIZE(resets), resets);
 err_mark_resumed:
 	i2c_mark_adapter_resumed(&i3c->base.i2c);
 
@@ -1451,17 +1558,22 @@ static int renesas_i3c_resume(struct device *dev)
 	};
 	int ret;
 
+	ret = pm_runtime_force_resume(dev);
+	if (ret)
+		return ret;
+
 	ret = reset_control_bulk_deassert(ARRAY_SIZE(resets), resets);
 	if (ret)
 		return ret;
 
-	ret = clk_bulk_enable(i3c->num_clks, i3c->clks);
+	ret = renesas_i3c_reset(i3c);
 	if (ret)
 		goto err_resets_asserted;
 
-	ret = renesas_i3c_reset(i3c);
+	PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
 	if (ret)
-		goto err_clks_disable;
+		goto err_resets_asserted;
 
 	/* Re-store I3C registers value. */
 	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
@@ -1486,14 +1598,31 @@ static int renesas_i3c_resume(struct device *dev)
 	 */
 	return 0;
 
-err_clks_disable:
-	clk_bulk_disable(i3c->num_clks, i3c->clks);
 err_resets_asserted:
+	/*
+	 * If this happens, there is no way to recover from this state without
+	 * reloading the driver. We want to avoid keeping the reset line
+	 * deasserted unnecessarily. The runtime paths will still work correctly
+	 * even if the IP registers are accessed while reset is asserted (e.g.
+	 * if a runtime path is triggered after a failed resume). Checked on
+	 * RZ/G3S.
+	 */
 	reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
 	return ret;
 }
 
+static int renesas_i3c_runtime_suspend(struct device *dev)
+{
+	return pinctrl_pm_select_sleep_state(dev);
+}
+
+static int renesas_i3c_runtime_resume(struct device *dev)
+{
+	return pinctrl_pm_select_default_state(dev);
+}
+
 static const struct dev_pm_ops renesas_i3c_pm_ops = {
+	RUNTIME_PM_OPS(renesas_i3c_runtime_suspend, renesas_i3c_runtime_resume, NULL)
 	SYSTEM_SLEEP_PM_OPS(renesas_i3c_suspend, renesas_i3c_resume)
 };
 
-- 
2.43.0


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

* Re: [PATCH 01/17] i3c: renesas: Check that the transfer is valid before accessing it
  2026-05-22 10:17   ` Claudiu Beznea
@ 2026-05-22 19:02     ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:02 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Fri, May 22, 2026 at 01:17:59PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> The Renesas I3C driver uses an asynchronous model to transfer data. It
> prepares a struct renesas_i3c_xfer, enqueues it, and waits for completion.
> The interrupt handler dequeues the transfer, updates/uses it, and signals
> the waiting thread.
>
> If the completion times out, the waiting thread dequeues the transfer and
> free it. If an interrupt fires after that, the handler may access freed
> memory, leading to crashes.
>
> Check that the transfer is still valid before accessing it in the
> interrupt handler.
>
> Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
> Cc: stable@vger.kernel.org
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/i3c/master/renesas-i3c.c | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index f39c449922ca..36e3ccbe66b0 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -1014,6 +1014,9 @@ static irqreturn_t renesas_i3c_tx_isr(int irq, void *data)
>
>  	scoped_guard(spinlock, &i3c->xferqueue.lock) {
>  		xfer = i3c->xferqueue.cur;
> +		if (!xfer)
> +			return IRQ_HANDLED;
> +
>  		cmd = xfer->cmds;
>
>  		if (xfer->is_i2c_xfer) {
> @@ -1054,6 +1057,9 @@ static irqreturn_t renesas_i3c_resp_isr(int irq, void *data)
>
>  	scoped_guard(spinlock, &i3c->xferqueue.lock) {
>  		xfer = i3c->xferqueue.cur;
> +		if (!xfer)
> +			return IRQ_HANDLED;
> +
>  		cmd = xfer->cmds;
>
>  		/* Clear the Respone Queue Full status flag*/
> @@ -1138,6 +1144,9 @@ static irqreturn_t renesas_i3c_tend_isr(int irq, void *data)
>
>  	scoped_guard(spinlock, &i3c->xferqueue.lock) {
>  		xfer = i3c->xferqueue.cur;
> +		if (!xfer)
> +			return IRQ_HANDLED;
> +
>  		cmd = xfer->cmds;
>
>  		if (xfer->is_i2c_xfer) {
> @@ -1184,6 +1193,9 @@ static irqreturn_t renesas_i3c_rx_isr(int irq, void *data)
>
>  	scoped_guard(spinlock, &i3c->xferqueue.lock) {
>  		xfer = i3c->xferqueue.cur;
> +		if (!xfer)
> +			return IRQ_HANDLED;
> +
>  		cmd = xfer->cmds;
>
>  		if (xfer->is_i2c_xfer) {
> @@ -1235,6 +1247,8 @@ static irqreturn_t renesas_i3c_stop_isr(int irq, void *data)
>
>  	scoped_guard(spinlock, &i3c->xferqueue.lock) {
>  		xfer = i3c->xferqueue.cur;
> +		if (!xfer)
> +			return IRQ_HANDLED;
>
>  		/* read back registers to confirm writes have fully propagated */
>  		renesas_writel(i3c->regs, BST, 0);
> @@ -1259,6 +1273,9 @@ static irqreturn_t renesas_i3c_start_isr(int irq, void *data)
>
>  	scoped_guard(spinlock, &i3c->xferqueue.lock) {
>  		xfer = i3c->xferqueue.cur;
> +		if (!xfer)
> +			return IRQ_HANDLED;
> +
>  		cmd = xfer->cmds;
>
>  		if (xfer->is_i2c_xfer) {
> --
> 2.43.0
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 01/17] i3c: renesas: Check that the transfer is valid before accessing it
@ 2026-05-22 19:02     ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:02 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Fri, May 22, 2026 at 01:17:59PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> The Renesas I3C driver uses an asynchronous model to transfer data. It
> prepares a struct renesas_i3c_xfer, enqueues it, and waits for completion.
> The interrupt handler dequeues the transfer, updates/uses it, and signals
> the waiting thread.
>
> If the completion times out, the waiting thread dequeues the transfer and
> free it. If an interrupt fires after that, the handler may access freed
> memory, leading to crashes.
>
> Check that the transfer is still valid before accessing it in the
> interrupt handler.
>
> Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
> Cc: stable@vger.kernel.org
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/i3c/master/renesas-i3c.c | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index f39c449922ca..36e3ccbe66b0 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -1014,6 +1014,9 @@ static irqreturn_t renesas_i3c_tx_isr(int irq, void *data)
>
>  	scoped_guard(spinlock, &i3c->xferqueue.lock) {
>  		xfer = i3c->xferqueue.cur;
> +		if (!xfer)
> +			return IRQ_HANDLED;
> +
>  		cmd = xfer->cmds;
>
>  		if (xfer->is_i2c_xfer) {
> @@ -1054,6 +1057,9 @@ static irqreturn_t renesas_i3c_resp_isr(int irq, void *data)
>
>  	scoped_guard(spinlock, &i3c->xferqueue.lock) {
>  		xfer = i3c->xferqueue.cur;
> +		if (!xfer)
> +			return IRQ_HANDLED;
> +
>  		cmd = xfer->cmds;
>
>  		/* Clear the Respone Queue Full status flag*/
> @@ -1138,6 +1144,9 @@ static irqreturn_t renesas_i3c_tend_isr(int irq, void *data)
>
>  	scoped_guard(spinlock, &i3c->xferqueue.lock) {
>  		xfer = i3c->xferqueue.cur;
> +		if (!xfer)
> +			return IRQ_HANDLED;
> +
>  		cmd = xfer->cmds;
>
>  		if (xfer->is_i2c_xfer) {
> @@ -1184,6 +1193,9 @@ static irqreturn_t renesas_i3c_rx_isr(int irq, void *data)
>
>  	scoped_guard(spinlock, &i3c->xferqueue.lock) {
>  		xfer = i3c->xferqueue.cur;
> +		if (!xfer)
> +			return IRQ_HANDLED;
> +
>  		cmd = xfer->cmds;
>
>  		if (xfer->is_i2c_xfer) {
> @@ -1235,6 +1247,8 @@ static irqreturn_t renesas_i3c_stop_isr(int irq, void *data)
>
>  	scoped_guard(spinlock, &i3c->xferqueue.lock) {
>  		xfer = i3c->xferqueue.cur;
> +		if (!xfer)
> +			return IRQ_HANDLED;
>
>  		/* read back registers to confirm writes have fully propagated */
>  		renesas_writel(i3c->regs, BST, 0);
> @@ -1259,6 +1273,9 @@ static irqreturn_t renesas_i3c_start_isr(int irq, void *data)
>
>  	scoped_guard(spinlock, &i3c->xferqueue.lock) {
>  		xfer = i3c->xferqueue.cur;
> +		if (!xfer)
> +			return IRQ_HANDLED;
> +
>  		cmd = xfer->cmds;
>
>  		if (xfer->is_i2c_xfer) {
> --
> 2.43.0
>

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

* Re: [PATCH 02/17] i3c: renesas: Use the divider 128
  2026-05-22 10:18   ` Claudiu Beznea
@ 2026-05-22 19:06     ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:06 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Fri, May 22, 2026 at 01:18:00PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> The REFCKCTL.IREFCKS field is 3 bits wide, and setting it to 7 selects a
> divider of 128 for the internal reference clock. Use this divider value.

This doesnot reflect what your change, code add one more search for clks = 7

Frank

>
> Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
> Cc: stable@vger.kernel.org
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
>  drivers/i3c/master/renesas-i3c.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 36e3ccbe66b0..1917549cf6d5 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -559,7 +559,7 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
>
>  	i2c_parse_fw_timings(&m->dev, &t, true);
>
> -	for (cks = 0; cks < 7; cks++) {
> +	for (cks = 0; cks <= 7; cks++) {
>  		/* SCL low-period calculation in Open-drain mode */
>  		od_low_ticks = ((i2c_total_ticks * 6) / 10);
>
> --
> 2.43.0
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 02/17] i3c: renesas: Use the divider 128
@ 2026-05-22 19:06     ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:06 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Fri, May 22, 2026 at 01:18:00PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> The REFCKCTL.IREFCKS field is 3 bits wide, and setting it to 7 selects a
> divider of 128 for the internal reference clock. Use this divider value.

This doesnot reflect what your change, code add one more search for clks = 7

Frank

>
> Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
> Cc: stable@vger.kernel.org
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
>  drivers/i3c/master/renesas-i3c.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 36e3ccbe66b0..1917549cf6d5 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -559,7 +559,7 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
>
>  	i2c_parse_fw_timings(&m->dev, &t, true);
>
> -	for (cks = 0; cks < 7; cks++) {
> +	for (cks = 0; cks <= 7; cks++) {
>  		/* SCL low-period calculation in Open-drain mode */
>  		od_low_ticks = ((i2c_total_ticks * 6) / 10);
>
> --
> 2.43.0
>

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

* Re: [PATCH 03/17] i3c: renesas: Restore STDBR and EXTBR registers on resume
  2026-05-22 10:18   ` Claudiu Beznea
@ 2026-05-22 19:10     ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:10 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Fri, May 22, 2026 at 01:18:01PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> The Renesas RZ/G3S supports a power saving state where power to the most
> SoC componentes (including I3C) is lost.
>
> The STDBR and EXTBR are configured in initialization phase though the
> struct i3c_master_controller_ops::bus_init. Set them on resume function
> as well to keep the same state of the controller after a suspend with
> power loss and a similar initialization sequence as in bus_init.
>
> Fixes: e7218986319b ("i3c: renesas: Add suspend/resume support")
> Cc: stable@vger.kernel.org
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
>  drivers/i3c/master/renesas-i3c.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 1917549cf6d5..6c23f956ad2a 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -260,6 +260,7 @@ struct renesas_i3c {
>  	u32 dyn_addr;
>  	u32 i2c_STDBR;
>  	u32 i3c_STDBR;
> +	u32 extbr;

can you keep consisent with above 2 register, use upcase EXTBR,

Frank
>  	unsigned long rate;
>  	u8 addrs[RENESAS_I3C_MAX_DEVS];
>  	struct renesas_i3c_xferqueue xferqueue;
> @@ -607,10 +608,9 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
>  	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
>
>  	/* Extended Bit Rate setting */
> -	renesas_writel(i3c->regs, EXTBR, EXTBR_EBRLO(od_low_ticks) |
> -					   EXTBR_EBRHO(od_high_ticks) |
> -					   EXTBR_EBRLP(pp_low_ticks) |
> -					   EXTBR_EBRHP(pp_high_ticks));
> +	i3c->extbr = EXTBR_EBRLO(od_low_ticks) | EXTBR_EBRHO(od_high_ticks) |
> +		     EXTBR_EBRLP(pp_low_ticks) | EXTBR_EBRHP(pp_high_ticks);
> +	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
>
>  	renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
>  	i3c->refclk_div = cks;
> @@ -1447,6 +1447,8 @@ static int renesas_i3c_resume_noirq(struct device *dev)
>  		goto err_tresetn;
>
>  	/* Re-store I3C registers value. */
> +	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
> +	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
>  	renesas_writel(i3c->regs, REFCKCTL,
>  		       REFCKCTL_IREFCKS(i3c->refclk_div));
>  	renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYADV |
> --
> 2.43.0
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 03/17] i3c: renesas: Restore STDBR and EXTBR registers on resume
@ 2026-05-22 19:10     ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:10 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Fri, May 22, 2026 at 01:18:01PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> The Renesas RZ/G3S supports a power saving state where power to the most
> SoC componentes (including I3C) is lost.
>
> The STDBR and EXTBR are configured in initialization phase though the
> struct i3c_master_controller_ops::bus_init. Set them on resume function
> as well to keep the same state of the controller after a suspend with
> power loss and a similar initialization sequence as in bus_init.
>
> Fixes: e7218986319b ("i3c: renesas: Add suspend/resume support")
> Cc: stable@vger.kernel.org
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
>  drivers/i3c/master/renesas-i3c.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 1917549cf6d5..6c23f956ad2a 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -260,6 +260,7 @@ struct renesas_i3c {
>  	u32 dyn_addr;
>  	u32 i2c_STDBR;
>  	u32 i3c_STDBR;
> +	u32 extbr;

can you keep consisent with above 2 register, use upcase EXTBR,

Frank
>  	unsigned long rate;
>  	u8 addrs[RENESAS_I3C_MAX_DEVS];
>  	struct renesas_i3c_xferqueue xferqueue;
> @@ -607,10 +608,9 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
>  	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
>
>  	/* Extended Bit Rate setting */
> -	renesas_writel(i3c->regs, EXTBR, EXTBR_EBRLO(od_low_ticks) |
> -					   EXTBR_EBRHO(od_high_ticks) |
> -					   EXTBR_EBRLP(pp_low_ticks) |
> -					   EXTBR_EBRHP(pp_high_ticks));
> +	i3c->extbr = EXTBR_EBRLO(od_low_ticks) | EXTBR_EBRHO(od_high_ticks) |
> +		     EXTBR_EBRLP(pp_low_ticks) | EXTBR_EBRHP(pp_high_ticks);
> +	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
>
>  	renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
>  	i3c->refclk_div = cks;
> @@ -1447,6 +1447,8 @@ static int renesas_i3c_resume_noirq(struct device *dev)
>  		goto err_tresetn;
>
>  	/* Re-store I3C registers value. */
> +	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
> +	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
>  	renesas_writel(i3c->regs, REFCKCTL,
>  		       REFCKCTL_IREFCKS(i3c->refclk_div));
>  	renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYADV |
> --
> 2.43.0
>

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

* Re: [PATCH 04/17] i3c: renesas: Follow the reset deassert order used in probe
  2026-05-22 10:18   ` Claudiu Beznea
@ 2026-05-22 19:11     ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:11 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Fri, May 22, 2026 at 01:18:02PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Use the same reset deassert order in the resume and probe paths to avoid
> potential failures due to ordering differences.
>
> Fixes: e7218986319b ("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>

>  drivers/i3c/master/renesas-i3c.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 6c23f956ad2a..d2f29ed0b6ed 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -1434,17 +1434,17 @@ static int renesas_i3c_resume_noirq(struct device *dev)
>  	struct renesas_i3c *i3c = dev_get_drvdata(dev);
>  	int i, ret;
>
> -	ret = reset_control_deassert(i3c->presetn);
> +	ret = reset_control_deassert(i3c->tresetn);
>  	if (ret)
>  		return ret;
>
> -	ret = reset_control_deassert(i3c->tresetn);
> +	ret = reset_control_deassert(i3c->presetn);
>  	if (ret)
> -		goto err_presetn;
> +		goto err_tresetn;
>
>  	ret = clk_bulk_enable(i3c->num_clks, i3c->clks);
>  	if (ret)
> -		goto err_tresetn;
> +		goto err_presetn;
>
>  	/* Re-store I3C registers value. */
>  	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
> @@ -1465,10 +1465,10 @@ static int renesas_i3c_resume_noirq(struct device *dev)
>
>  	return 0;
>
> -err_tresetn:
> -	reset_control_assert(i3c->tresetn);
>  err_presetn:
>  	reset_control_assert(i3c->presetn);
> +err_tresetn:
> +	reset_control_assert(i3c->tresetn);
>  	return ret;
>  }
>
> --
> 2.43.0
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 04/17] i3c: renesas: Follow the reset deassert order used in probe
@ 2026-05-22 19:11     ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:11 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Fri, May 22, 2026 at 01:18:02PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Use the same reset deassert order in the resume and probe paths to avoid
> potential failures due to ordering differences.
>
> Fixes: e7218986319b ("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>

>  drivers/i3c/master/renesas-i3c.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 6c23f956ad2a..d2f29ed0b6ed 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -1434,17 +1434,17 @@ static int renesas_i3c_resume_noirq(struct device *dev)
>  	struct renesas_i3c *i3c = dev_get_drvdata(dev);
>  	int i, ret;
>
> -	ret = reset_control_deassert(i3c->presetn);
> +	ret = reset_control_deassert(i3c->tresetn);
>  	if (ret)
>  		return ret;
>
> -	ret = reset_control_deassert(i3c->tresetn);
> +	ret = reset_control_deassert(i3c->presetn);
>  	if (ret)
> -		goto err_presetn;
> +		goto err_tresetn;
>
>  	ret = clk_bulk_enable(i3c->num_clks, i3c->clks);
>  	if (ret)
> -		goto err_tresetn;
> +		goto err_presetn;
>
>  	/* Re-store I3C registers value. */
>  	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
> @@ -1465,10 +1465,10 @@ static int renesas_i3c_resume_noirq(struct device *dev)
>
>  	return 0;
>
> -err_tresetn:
> -	reset_control_assert(i3c->tresetn);
>  err_presetn:
>  	reset_control_assert(i3c->presetn);
> +err_tresetn:
> +	reset_control_assert(i3c->tresetn);
>  	return ret;
>  }
>
> --
> 2.43.0
>

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

* Re: [PATCH 05/17] i3c: renesas: Fix re-attach
  2026-05-22 10:18   ` Claudiu Beznea
@ 2026-05-22 19:13     ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:13 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Fri, May 22, 2026 at 01:18:03PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

subject should descript what change

possible candidate si

"Reconfigure the DATBAS register on re-attach"

Frank

>
> During re-attach, the device may change its position in the i3c->addrs[]
> array. As a result, it may use a different Device Address Table Basic
> Register (DATBAS), which needs to be reconfigured.
>
> Reconfigure the DATBAS register on re-attach. Along with it update
> software caches.
>
> Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
> Cc: stable@vger.kernel.org
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
>  drivers/i3c/master/renesas-i3c.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index d2f29ed0b6ed..5174a390d668 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -892,10 +892,28 @@ static int renesas_i3c_reattach_i3c_dev(struct i3c_dev_desc *dev,
>  	struct i3c_master_controller *m = i3c_dev_get_master(dev);
>  	struct renesas_i3c *i3c = to_renesas_i3c(m);
>  	struct renesas_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
> +	int pos;
> +
> +	pos = renesas_i3c_get_free_pos(i3c);
> +	if (pos < 0)
> +		return pos;
> +
> +	if (data->index != pos) {
> +		renesas_writel(i3c->regs, DATBAS(data->index), 0);
> +		i3c->addrs[data->index] = 0;
> +		i3c->free_pos |= BIT(data->index);
> +
> +		data->index = pos;
> +		i3c->free_pos &= ~BIT(data->index);
> +	}
>
>  	i3c->addrs[data->index] = dev->info.dyn_addr ? dev->info.dyn_addr :
>  							dev->info.static_addr;
>
> +	renesas_writel(i3c->regs, DATBAS(data->index),
> +		       DATBAS_DVSTAD(dev->info.static_addr) |
> +		       datbas_dvdyad_with_parity(i3c->addrs[data->index]));
> +
>  	return 0;
>  }
>
> --
> 2.43.0
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 05/17] i3c: renesas: Fix re-attach
@ 2026-05-22 19:13     ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:13 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Fri, May 22, 2026 at 01:18:03PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

subject should descript what change

possible candidate si

"Reconfigure the DATBAS register on re-attach"

Frank

>
> During re-attach, the device may change its position in the i3c->addrs[]
> array. As a result, it may use a different Device Address Table Basic
> Register (DATBAS), which needs to be reconfigured.
>
> Reconfigure the DATBAS register on re-attach. Along with it update
> software caches.
>
> Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
> Cc: stable@vger.kernel.org
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
>  drivers/i3c/master/renesas-i3c.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index d2f29ed0b6ed..5174a390d668 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -892,10 +892,28 @@ static int renesas_i3c_reattach_i3c_dev(struct i3c_dev_desc *dev,
>  	struct i3c_master_controller *m = i3c_dev_get_master(dev);
>  	struct renesas_i3c *i3c = to_renesas_i3c(m);
>  	struct renesas_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
> +	int pos;
> +
> +	pos = renesas_i3c_get_free_pos(i3c);
> +	if (pos < 0)
> +		return pos;
> +
> +	if (data->index != pos) {
> +		renesas_writel(i3c->regs, DATBAS(data->index), 0);
> +		i3c->addrs[data->index] = 0;
> +		i3c->free_pos |= BIT(data->index);
> +
> +		data->index = pos;
> +		i3c->free_pos &= ~BIT(data->index);
> +	}
>
>  	i3c->addrs[data->index] = dev->info.dyn_addr ? dev->info.dyn_addr :
>  							dev->info.static_addr;
>
> +	renesas_writel(i3c->regs, DATBAS(data->index),
> +		       DATBAS_DVSTAD(dev->info.static_addr) |
> +		       datbas_dvdyad_with_parity(i3c->addrs[data->index]));
> +
>  	return 0;
>  }
>
> --
> 2.43.0
>

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

* Re: [PATCH 06/17] i3c: renesas: Reset the controller on resume
  2026-05-22 10:18   ` Claudiu Beznea
@ 2026-05-22 19:15     ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:15 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Fri, May 22, 2026 at 01:18:04PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Reset the controller on resume after enabling the clocks to follow the
> same sequence as in probe and avoid potential ordering related failures.
>
> Fixes: e7218986319b ("i3c: renesas: Add suspend/resume support")
> Cc: stable@vger.kernel.org
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---

Can you move these similar stuff to one helper function to avoid duplicate
efforts later?

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/i3c/master/renesas-i3c.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 5174a390d668..2f3c6ddf75c0 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -1464,6 +1464,10 @@ static int renesas_i3c_resume_noirq(struct device *dev)
>  	if (ret)
>  		goto err_presetn;
>
> +	ret = renesas_i3c_reset(i3c);
> +	if (ret)
> +		goto err_clks_disable;
> +
>  	/* Re-store I3C registers value. */
>  	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
>  	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
> @@ -1483,6 +1487,8 @@ static int renesas_i3c_resume_noirq(struct device *dev)
>
>  	return 0;
>
> +err_clks_disable:
> +	clk_bulk_disable(i3c->num_clks, i3c->clks);
>  err_presetn:
>  	reset_control_assert(i3c->presetn);
>  err_tresetn:
> --
> 2.43.0
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 06/17] i3c: renesas: Reset the controller on resume
@ 2026-05-22 19:15     ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:15 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Fri, May 22, 2026 at 01:18:04PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Reset the controller on resume after enabling the clocks to follow the
> same sequence as in probe and avoid potential ordering related failures.
>
> Fixes: e7218986319b ("i3c: renesas: Add suspend/resume support")
> Cc: stable@vger.kernel.org
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---

Can you move these similar stuff to one helper function to avoid duplicate
efforts later?

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/i3c/master/renesas-i3c.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 5174a390d668..2f3c6ddf75c0 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -1464,6 +1464,10 @@ static int renesas_i3c_resume_noirq(struct device *dev)
>  	if (ret)
>  		goto err_presetn;
>
> +	ret = renesas_i3c_reset(i3c);
> +	if (ret)
> +		goto err_clks_disable;
> +
>  	/* Re-store I3C registers value. */
>  	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
>  	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
> @@ -1483,6 +1487,8 @@ static int renesas_i3c_resume_noirq(struct device *dev)
>
>  	return 0;
>
> +err_clks_disable:
> +	clk_bulk_disable(i3c->num_clks, i3c->clks);
>  err_presetn:
>  	reset_control_assert(i3c->presetn);
>  err_tresetn:
> --
> 2.43.0
>

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

* Re: [PATCH 07/17] i3c: renesas: Perform Dynamic Address Assignment on resume
  2026-05-22 10:18   ` Claudiu Beznea
@ 2026-05-22 19:16     ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:16 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Fri, May 22, 2026 at 01:18:05PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@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@vger.kernel.org
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@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
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 07/17] i3c: renesas: Perform Dynamic Address Assignment on resume
@ 2026-05-22 19:16     ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:16 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Fri, May 22, 2026 at 01:18:05PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@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@vger.kernel.org
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@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
>

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

* Re: [PATCH 08/17] i3c: renesas: Clean DATBAS register on detach
  2026-05-22 10:18   ` Claudiu Beznea
@ 2026-05-22 19:17     ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:17 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Fri, May 22, 2026 at 01:18:06PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> The controller uses DATBAS registers on TX/RX logic. Clean the DATBAS
> register for the detached I3C device to avoid issues.
>
> Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
> Cc: stable@vger.kernel.org
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/i3c/master/renesas-i3c.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index c009d0de6a2b..d32646deb69f 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -922,6 +922,8 @@ static void renesas_i3c_detach_i3c_dev(struct i3c_dev_desc *dev)
>  	struct i3c_master_controller *m = i3c_dev_get_master(dev);
>  	struct renesas_i3c *i3c = to_renesas_i3c(m);
>
> +	renesas_writel(i3c->regs, DATBAS(data->index), 0);
> +
>  	i3c_dev_set_master_data(dev, NULL);
>  	i3c->addrs[data->index] = 0;
>  	i3c->free_pos |= BIT(data->index);
> --
> 2.43.0
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 08/17] i3c: renesas: Clean DATBAS register on detach
@ 2026-05-22 19:17     ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:17 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Fri, May 22, 2026 at 01:18:06PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> The controller uses DATBAS registers on TX/RX logic. Clean the DATBAS
> register for the detached I3C device to avoid issues.
>
> Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
> Cc: stable@vger.kernel.org
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/i3c/master/renesas-i3c.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index c009d0de6a2b..d32646deb69f 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -922,6 +922,8 @@ static void renesas_i3c_detach_i3c_dev(struct i3c_dev_desc *dev)
>  	struct i3c_master_controller *m = i3c_dev_get_master(dev);
>  	struct renesas_i3c *i3c = to_renesas_i3c(m);
>
> +	renesas_writel(i3c->regs, DATBAS(data->index), 0);
> +
>  	i3c_dev_set_master_data(dev, NULL);
>  	i3c->addrs[data->index] = 0;
>  	i3c->free_pos |= BIT(data->index);
> --
> 2.43.0
>

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

* Re: [PATCH 09/17] i3c: renesas: Use reset_control_bulk_{assert, deassert}()
  2026-05-22 10:18   ` Claudiu Beznea
@ 2026-05-22 19:19     ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:19 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

On Fri, May 22, 2026 at 01:18:07PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Use reset_control_bulk_assert() and reset_control_bulk_deassert() in the
> suspend and resume paths to simplify the code.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
>  drivers/i3c/master/renesas-i3c.c | 30 +++++++++++++-----------------
>  1 file changed, 13 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index d32646deb69f..e5963270d6e5 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -1414,24 +1414,22 @@ static void renesas_i3c_remove(struct platform_device *pdev)
>  static int renesas_i3c_suspend(struct device *dev)
>  {
>  	struct renesas_i3c *i3c = dev_get_drvdata(dev);
> +	struct reset_control_bulk_data resets[] = {
> +		{ .rstc = i3c->presetn },
> +		{ .rstc = i3c->tresetn },
> +	};

Suppose it is also used in probe funciton. can move these into renesas_i3c

Frank

>  	int ret;
>
>  	i2c_mark_adapter_suspended(&i3c->base.i2c);
>
> -	ret = reset_control_assert(i3c->presetn);
> +	ret = reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
>  	if (ret)
>  		goto err_mark_resumed;
>
> -	ret = reset_control_assert(i3c->tresetn);
> -	if (ret)
> -		goto err_presetn;
> -
>  	clk_bulk_disable(i3c->num_clks, i3c->clks);
>
>  	return 0;
>
> -err_presetn:
> -	reset_control_deassert(i3c->presetn);
>  err_mark_resumed:
>  	i2c_mark_adapter_resumed(&i3c->base.i2c);
>
> @@ -1441,19 +1439,19 @@ static int renesas_i3c_suspend(struct device *dev)
>  static int renesas_i3c_resume(struct device *dev)
>  {
>  	struct renesas_i3c *i3c = dev_get_drvdata(dev);
> +	struct reset_control_bulk_data resets[] = {
> +		{ .rstc = i3c->presetn },
> +		{ .rstc = i3c->tresetn },
> +	};
>  	int ret;
>
> -	ret = reset_control_deassert(i3c->tresetn);
> +	ret = reset_control_bulk_deassert(ARRAY_SIZE(resets), resets);
>  	if (ret)
>  		return ret;
>
> -	ret = reset_control_deassert(i3c->presetn);
> -	if (ret)
> -		goto err_tresetn;
> -
>  	ret = clk_bulk_enable(i3c->num_clks, i3c->clks);
>  	if (ret)
> -		goto err_presetn;
> +		goto err_resets_asserted;
>
>  	ret = renesas_i3c_reset(i3c);
>  	if (ret)
> @@ -1484,10 +1482,8 @@ static int renesas_i3c_resume(struct device *dev)
>
>  err_clks_disable:
>  	clk_bulk_disable(i3c->num_clks, i3c->clks);
> -err_presetn:
> -	reset_control_assert(i3c->presetn);
> -err_tresetn:
> -	reset_control_assert(i3c->tresetn);
> +err_resets_asserted:
> +	reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
>  	return ret;
>  }
>
> --
> 2.43.0
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 09/17] i3c: renesas: Use reset_control_bulk_{assert, deassert}()
@ 2026-05-22 19:19     ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:19 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

On Fri, May 22, 2026 at 01:18:07PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Use reset_control_bulk_assert() and reset_control_bulk_deassert() in the
> suspend and resume paths to simplify the code.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
>  drivers/i3c/master/renesas-i3c.c | 30 +++++++++++++-----------------
>  1 file changed, 13 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index d32646deb69f..e5963270d6e5 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -1414,24 +1414,22 @@ static void renesas_i3c_remove(struct platform_device *pdev)
>  static int renesas_i3c_suspend(struct device *dev)
>  {
>  	struct renesas_i3c *i3c = dev_get_drvdata(dev);
> +	struct reset_control_bulk_data resets[] = {
> +		{ .rstc = i3c->presetn },
> +		{ .rstc = i3c->tresetn },
> +	};

Suppose it is also used in probe funciton. can move these into renesas_i3c

Frank

>  	int ret;
>
>  	i2c_mark_adapter_suspended(&i3c->base.i2c);
>
> -	ret = reset_control_assert(i3c->presetn);
> +	ret = reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
>  	if (ret)
>  		goto err_mark_resumed;
>
> -	ret = reset_control_assert(i3c->tresetn);
> -	if (ret)
> -		goto err_presetn;
> -
>  	clk_bulk_disable(i3c->num_clks, i3c->clks);
>
>  	return 0;
>
> -err_presetn:
> -	reset_control_deassert(i3c->presetn);
>  err_mark_resumed:
>  	i2c_mark_adapter_resumed(&i3c->base.i2c);
>
> @@ -1441,19 +1439,19 @@ static int renesas_i3c_suspend(struct device *dev)
>  static int renesas_i3c_resume(struct device *dev)
>  {
>  	struct renesas_i3c *i3c = dev_get_drvdata(dev);
> +	struct reset_control_bulk_data resets[] = {
> +		{ .rstc = i3c->presetn },
> +		{ .rstc = i3c->tresetn },
> +	};
>  	int ret;
>
> -	ret = reset_control_deassert(i3c->tresetn);
> +	ret = reset_control_bulk_deassert(ARRAY_SIZE(resets), resets);
>  	if (ret)
>  		return ret;
>
> -	ret = reset_control_deassert(i3c->presetn);
> -	if (ret)
> -		goto err_tresetn;
> -
>  	ret = clk_bulk_enable(i3c->num_clks, i3c->clks);
>  	if (ret)
> -		goto err_presetn;
> +		goto err_resets_asserted;
>
>  	ret = renesas_i3c_reset(i3c);
>  	if (ret)
> @@ -1484,10 +1482,8 @@ static int renesas_i3c_resume(struct device *dev)
>
>  err_clks_disable:
>  	clk_bulk_disable(i3c->num_clks, i3c->clks);
> -err_presetn:
> -	reset_control_assert(i3c->presetn);
> -err_tresetn:
> -	reset_control_assert(i3c->tresetn);
> +err_resets_asserted:
> +	reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
>  	return ret;
>  }
>
> --
> 2.43.0
>

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

* Re: [PATCH 10/17] i3c: renesas: Return immediately if there is nothing to transfer
  2026-05-22 10:18   ` Claudiu Beznea
@ 2026-05-22 19:20     ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:20 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

subject:
	 Return immediately if nothing transfer

Frank

On Fri, May 22, 2026 at 01:18:08PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> There is no need to allocate a transfer structure when i2c_nxfers is zero.
> Return immediately instead of unnecessarily allocating memory.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
>  drivers/i3c/master/renesas-i3c.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index e5963270d6e5..de75125eb013 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -940,13 +940,13 @@ static int renesas_i3c_i2c_xfers(struct i2c_dev_desc *dev,
>  	u8 start_bit = CNDCTL_STCND;
>  	int i;
>
> +	if (!i2c_nxfers)
> +		return 0;
> +
>  	struct renesas_i3c_xfer *xfer __free(kfree) = renesas_i3c_alloc_xfer(i3c, 1);
>  	if (!xfer)
>  		return -ENOMEM;
>
> -	if (!i2c_nxfers)
> -		return 0;
> -
>  	renesas_i3c_bus_enable(m, false);
>
>  	init_completion(&xfer->comp);
> --
> 2.43.0
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 10/17] i3c: renesas: Return immediately if there is nothing to transfer
@ 2026-05-22 19:20     ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:20 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

subject:
	 Return immediately if nothing transfer

Frank

On Fri, May 22, 2026 at 01:18:08PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> There is no need to allocate a transfer structure when i2c_nxfers is zero.
> Return immediately instead of unnecessarily allocating memory.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
>  drivers/i3c/master/renesas-i3c.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index e5963270d6e5..de75125eb013 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -940,13 +940,13 @@ static int renesas_i3c_i2c_xfers(struct i2c_dev_desc *dev,
>  	u8 start_bit = CNDCTL_STCND;
>  	int i;
>
> +	if (!i2c_nxfers)
> +		return 0;
> +
>  	struct renesas_i3c_xfer *xfer __free(kfree) = renesas_i3c_alloc_xfer(i3c, 1);
>  	if (!xfer)
>  		return -ENOMEM;
>
> -	if (!i2c_nxfers)
> -		return 0;
> -
>  	renesas_i3c_bus_enable(m, false);
>
>  	init_completion(&xfer->comp);
> --
> 2.43.0
>

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

* Re: [PATCH 11/17] i3c: renesas: Follow a unified pattern for transfer and command initialization
  2026-05-22 10:18   ` Claudiu Beznea
@ 2026-05-22 19:21     ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:21 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

On Fri, May 22, 2026 at 01:18:09PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Follow a unified pattern for transfer and command initialization across
> the driver. This keeps the code cleaner and easier to follow. Also, in
> some cases the I3C device was enabled before the transfer data structure
> was even allocated.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/i3c/master/renesas-i3c.c | 22 +++++++++++-----------
>  1 file changed, 11 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index de75125eb013..12bf4797a70d 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -648,6 +648,10 @@ static int renesas_i3c_daa(struct i3c_master_controller *m)
>  	if (!xfer)
>  		return -ENOMEM;
>
> +	init_completion(&xfer->comp);
> +	cmd = xfer->cmds;
> +	cmd->rx_count = 0;
> +
>  	/* Enable I3C bus. */
>  	renesas_i3c_bus_enable(m, true);
>
> @@ -669,10 +673,6 @@ static int renesas_i3c_daa(struct i3c_master_controller *m)
>  		renesas_writel(i3c->regs, DATBAS(pos), datbas_dvdyad_with_parity(ret));
>  	}
>
> -	init_completion(&xfer->comp);
> -	cmd = xfer->cmds;
> -	cmd->rx_count = 0;
> -
>  	ret = renesas_i3c_get_free_pos(i3c);
>  	if (ret < 0)
>  		return ret;
> @@ -760,13 +760,13 @@ static int renesas_i3c_send_ccc_cmd(struct i3c_master_controller *m,
>  	if (!xfer)
>  		return -ENOMEM;
>
> -	renesas_i3c_bus_enable(m, true);
> -
>  	init_completion(&xfer->comp);
>  	cmd = xfer->cmds;
>  	cmd->rnw = ccc->rnw;
>  	cmd->cmd0 = 0;
>
> +	renesas_i3c_bus_enable(m, true);
> +
>  	/* Calculate the command descriptor. */
>  	switch (ccc->id) {
>  	case I3C_CCC_SETDASA:
> @@ -816,15 +816,15 @@ static int renesas_i3c_i3c_xfers(struct i3c_dev_desc *dev, struct i3c_xfer *i3c_
>  	struct renesas_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
>  	int i;
>
> -	/* Enable I3C bus. */
> -	renesas_i3c_bus_enable(m, true);
> -
>  	struct renesas_i3c_xfer *xfer __free(kfree) = renesas_i3c_alloc_xfer(i3c, 1);
>  	if (!xfer)
>  		return -ENOMEM;
>
>  	init_completion(&xfer->comp);
>
> +	/* Enable I3C bus. */
> +	renesas_i3c_bus_enable(m, true);
> +
>  	for (i = 0; i < i3c_nxfers; i++) {
>  		struct renesas_i3c_cmd *cmd = xfer->cmds;
>
> @@ -947,12 +947,12 @@ static int renesas_i3c_i2c_xfers(struct i2c_dev_desc *dev,
>  	if (!xfer)
>  		return -ENOMEM;
>
> -	renesas_i3c_bus_enable(m, false);
> -
>  	init_completion(&xfer->comp);
>  	xfer->is_i2c_xfer = true;
>  	cmd = xfer->cmds;
>
> +	renesas_i3c_bus_enable(m, false);
> +
>  	if (!(renesas_readl(i3c->regs, BCST) & BCST_BFREF)) {
>  		cmd->err = -EBUSY;
>  		return cmd->err;
> --
> 2.43.0
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 11/17] i3c: renesas: Follow a unified pattern for transfer and command initialization
@ 2026-05-22 19:21     ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:21 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

On Fri, May 22, 2026 at 01:18:09PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Follow a unified pattern for transfer and command initialization across
> the driver. This keeps the code cleaner and easier to follow. Also, in
> some cases the I3C device was enabled before the transfer data structure
> was even allocated.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/i3c/master/renesas-i3c.c | 22 +++++++++++-----------
>  1 file changed, 11 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index de75125eb013..12bf4797a70d 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -648,6 +648,10 @@ static int renesas_i3c_daa(struct i3c_master_controller *m)
>  	if (!xfer)
>  		return -ENOMEM;
>
> +	init_completion(&xfer->comp);
> +	cmd = xfer->cmds;
> +	cmd->rx_count = 0;
> +
>  	/* Enable I3C bus. */
>  	renesas_i3c_bus_enable(m, true);
>
> @@ -669,10 +673,6 @@ static int renesas_i3c_daa(struct i3c_master_controller *m)
>  		renesas_writel(i3c->regs, DATBAS(pos), datbas_dvdyad_with_parity(ret));
>  	}
>
> -	init_completion(&xfer->comp);
> -	cmd = xfer->cmds;
> -	cmd->rx_count = 0;
> -
>  	ret = renesas_i3c_get_free_pos(i3c);
>  	if (ret < 0)
>  		return ret;
> @@ -760,13 +760,13 @@ static int renesas_i3c_send_ccc_cmd(struct i3c_master_controller *m,
>  	if (!xfer)
>  		return -ENOMEM;
>
> -	renesas_i3c_bus_enable(m, true);
> -
>  	init_completion(&xfer->comp);
>  	cmd = xfer->cmds;
>  	cmd->rnw = ccc->rnw;
>  	cmd->cmd0 = 0;
>
> +	renesas_i3c_bus_enable(m, true);
> +
>  	/* Calculate the command descriptor. */
>  	switch (ccc->id) {
>  	case I3C_CCC_SETDASA:
> @@ -816,15 +816,15 @@ static int renesas_i3c_i3c_xfers(struct i3c_dev_desc *dev, struct i3c_xfer *i3c_
>  	struct renesas_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
>  	int i;
>
> -	/* Enable I3C bus. */
> -	renesas_i3c_bus_enable(m, true);
> -
>  	struct renesas_i3c_xfer *xfer __free(kfree) = renesas_i3c_alloc_xfer(i3c, 1);
>  	if (!xfer)
>  		return -ENOMEM;
>
>  	init_completion(&xfer->comp);
>
> +	/* Enable I3C bus. */
> +	renesas_i3c_bus_enable(m, true);
> +
>  	for (i = 0; i < i3c_nxfers; i++) {
>  		struct renesas_i3c_cmd *cmd = xfer->cmds;
>
> @@ -947,12 +947,12 @@ static int renesas_i3c_i2c_xfers(struct i2c_dev_desc *dev,
>  	if (!xfer)
>  		return -ENOMEM;
>
> -	renesas_i3c_bus_enable(m, false);
> -
>  	init_completion(&xfer->comp);
>  	xfer->is_i2c_xfer = true;
>  	cmd = xfer->cmds;
>
> +	renesas_i3c_bus_enable(m, false);
> +
>  	if (!(renesas_readl(i3c->regs, BCST) & BCST_BFREF)) {
>  		cmd->err = -EBUSY;
>  		return cmd->err;
> --
> 2.43.0
>

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

* Re: [PATCH 12/17] i3c: renesas: Drop the explicit memset() call
  2026-05-22 10:18   ` Claudiu Beznea
@ 2026-05-22 19:43     ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:43 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

On Fri, May 22, 2026 at 01:18:10PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Drop the explicit memset() call on struct i3c_device_info object, as it is
> already initialized at declaration through compiler initialization.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/i3c/master/renesas-i3c.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 12bf4797a70d..865e67ac0fd2 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -624,7 +624,6 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
>  	i3c->dyn_addr = ret;
>  	renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYAD(ret) | MSDVAD_MDYADV);
>
> -	memset(&info, 0, sizeof(info));
>  	info.dyn_addr = ret;
>  	return i3c_master_set_info(&i3c->base, &info);
>  }
> --
> 2.43.0
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 12/17] i3c: renesas: Drop the explicit memset() call
@ 2026-05-22 19:43     ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:43 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

On Fri, May 22, 2026 at 01:18:10PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Drop the explicit memset() call on struct i3c_device_info object, as it is
> already initialized at declaration through compiler initialization.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/i3c/master/renesas-i3c.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 12bf4797a70d..865e67ac0fd2 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -624,7 +624,6 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
>  	i3c->dyn_addr = ret;
>  	renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYAD(ret) | MSDVAD_MDYADV);
>
> -	memset(&info, 0, sizeof(info));
>  	info.dyn_addr = ret;
>  	return i3c_master_set_info(&i3c->base, &info);
>  }
> --
> 2.43.0
>

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

* Re: [PATCH 13/17] i3c: renesas: Update HW registers after SW computations are done
  2026-05-22 10:18   ` Claudiu Beznea
@ 2026-05-22 19:48     ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:48 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

On Fri, May 22, 2026 at 01:18:11PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> renesas_i3c_bus_init() performs a number of computations and software
> cache updates, interleaving them with hardware register writes. While
> this works today, it makes it harder to minimize the time the controller
> must remain powered when runtime PM is introduced.
>
> Perform all software computations and cache updates first, then update
> the hardware registers. This prepares for future runtime PM support.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/i3c/master/renesas-i3c.c | 28 ++++++++++++++--------------
>  1 file changed, 14 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 865e67ac0fd2..631c9c5d8038 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -550,10 +550,6 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
>  	if (!i3c->rate)
>  		return -EINVAL;
>
> -	ret = renesas_i3c_reset(i3c);
> -	if (ret)
> -		return ret;
> -
>  	i2c_total_ticks = DIV_ROUND_UP(i3c->rate, bus->scl_rate.i2c);
>  	i3c_total_ticks = DIV_ROUND_UP(i3c->rate, bus->scl_rate.i3c);
>
> @@ -604,27 +600,31 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
>  			STDBR_SBRHO(double_SBR, od_high_ticks) |
>  			STDBR_SBRLP(pp_low_ticks) |
>  			STDBR_SBRHP(pp_high_ticks);
> -	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
>
>  	/* Extended Bit Rate setting */
>  	i3c->extbr = EXTBR_EBRLO(od_low_ticks) | EXTBR_EBRHO(od_high_ticks) |
>  		     EXTBR_EBRLP(pp_low_ticks) | EXTBR_EBRHP(pp_high_ticks);
> -	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
> -
> -	renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
> -	i3c->refclk_div = cks;
> -
> -	/* I3C hw init*/
> -	renesas_i3c_hw_init(i3c);
>
>  	ret = i3c_master_get_free_addr(m, 0);
>  	if (ret < 0)
>  		return ret;
>
> +	info.dyn_addr = ret;
>  	i3c->dyn_addr = ret;
> -	renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYAD(ret) | MSDVAD_MDYADV);
> +	i3c->refclk_div = cks;
> +
> +	ret = renesas_i3c_reset(i3c);
> +	if (ret)
> +		return ret;
> +
> +	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
> +	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
> +	renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
> +	renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYAD(i3c->dyn_addr) | MSDVAD_MDYADV);
> +
> +	/* I3C hw init*/
> +	renesas_i3c_hw_init(i3c);
>
> -	info.dyn_addr = ret;
>  	return i3c_master_set_info(&i3c->base, &info);
>  }
>
> --
> 2.43.0
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 13/17] i3c: renesas: Update HW registers after SW computations are done
@ 2026-05-22 19:48     ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:48 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

On Fri, May 22, 2026 at 01:18:11PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> renesas_i3c_bus_init() performs a number of computations and software
> cache updates, interleaving them with hardware register writes. While
> this works today, it makes it harder to minimize the time the controller
> must remain powered when runtime PM is introduced.
>
> Perform all software computations and cache updates first, then update
> the hardware registers. This prepares for future runtime PM support.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/i3c/master/renesas-i3c.c | 28 ++++++++++++++--------------
>  1 file changed, 14 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 865e67ac0fd2..631c9c5d8038 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -550,10 +550,6 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
>  	if (!i3c->rate)
>  		return -EINVAL;
>
> -	ret = renesas_i3c_reset(i3c);
> -	if (ret)
> -		return ret;
> -
>  	i2c_total_ticks = DIV_ROUND_UP(i3c->rate, bus->scl_rate.i2c);
>  	i3c_total_ticks = DIV_ROUND_UP(i3c->rate, bus->scl_rate.i3c);
>
> @@ -604,27 +600,31 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
>  			STDBR_SBRHO(double_SBR, od_high_ticks) |
>  			STDBR_SBRLP(pp_low_ticks) |
>  			STDBR_SBRHP(pp_high_ticks);
> -	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
>
>  	/* Extended Bit Rate setting */
>  	i3c->extbr = EXTBR_EBRLO(od_low_ticks) | EXTBR_EBRHO(od_high_ticks) |
>  		     EXTBR_EBRLP(pp_low_ticks) | EXTBR_EBRHP(pp_high_ticks);
> -	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
> -
> -	renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
> -	i3c->refclk_div = cks;
> -
> -	/* I3C hw init*/
> -	renesas_i3c_hw_init(i3c);
>
>  	ret = i3c_master_get_free_addr(m, 0);
>  	if (ret < 0)
>  		return ret;
>
> +	info.dyn_addr = ret;
>  	i3c->dyn_addr = ret;
> -	renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYAD(ret) | MSDVAD_MDYADV);
> +	i3c->refclk_div = cks;
> +
> +	ret = renesas_i3c_reset(i3c);
> +	if (ret)
> +		return ret;
> +
> +	renesas_writel(i3c->regs, STDBR, i3c->i3c_STDBR);
> +	renesas_writel(i3c->regs, EXTBR, i3c->extbr);
> +	renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
> +	renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYAD(i3c->dyn_addr) | MSDVAD_MDYADV);
> +
> +	/* I3C hw init*/
> +	renesas_i3c_hw_init(i3c);
>
> -	info.dyn_addr = ret;
>  	return i3c_master_set_info(&i3c->base, &info);
>  }
>
> --
> 2.43.0
>

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

* Re: [PATCH 14/17] i3c: renesas: Organize structures to avoid unnecessary padding
  2026-05-22 10:18   ` Claudiu Beznea
@ 2026-05-22 19:50     ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:50 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

On Fri, May 22, 2026 at 01:18:12PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Reorder structure members to reduce padding and improve memory layout.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
>  drivers/i3c/master/renesas-i3c.c | 28 ++++++++++++++--------------
>  1 file changed, 14 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 631c9c5d8038..5614ed99553c 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -221,19 +221,19 @@ enum renesas_i3c_event {
>  };
>
>  struct renesas_i3c_cmd {
> +	const void *tx_buf;
> +	void *rx_buf;
> +	/* i2c xfer */
> +	u8 *i2c_buf;
> +	const struct i2c_msg *msg;
> +	int i2c_bytes_left;
> +	int i2c_is_last;
>  	u32 cmd0;
>  	u32 len;
> -	const void *tx_buf;
>  	u32 tx_count;
> -	void *rx_buf;
>  	u32 rx_count;
>  	u32 err;
>  	u8 rnw;
> -	/* i2c xfer */
> -	int i2c_bytes_left;
> -	int i2c_is_last;
> -	u8 *i2c_buf;
> -	const struct i2c_msg *msg;
>  };
>
>  struct renesas_i3c_xfer {
> @@ -253,21 +253,21 @@ struct renesas_i3c_xferqueue {
>  };
>
>  struct renesas_i3c {
> +	void __iomem *regs;
> +	struct clk_bulk_data *clks;
> +	struct reset_control *presetn;
> +	struct reset_control *tresetn;
> +	struct renesas_i3c_xferqueue xferqueue;
>  	struct i3c_master_controller base;
> +	unsigned long rate;
>  	enum i3c_internal_state internal_state;
> -	u16 maxdevs;
>  	u32 free_pos;
>  	u32 dyn_addr;
>  	u32 i2c_STDBR;
>  	u32 i3c_STDBR;
>  	u32 extbr;
> -	unsigned long rate;
> +	u16 maxdevs;
>  	u8 addrs[RENESAS_I3C_MAX_DEVS];
> -	struct renesas_i3c_xferqueue xferqueue;
> -	void __iomem *regs;
> -	struct clk_bulk_data *clks;
> -	struct reset_control *presetn;
> -	struct reset_control *tresetn;
>  	u8 num_clks;
>  	u8 refclk_div;
>  };
> --
> 2.43.0
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 14/17] i3c: renesas: Organize structures to avoid unnecessary padding
@ 2026-05-22 19:50     ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:50 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

On Fri, May 22, 2026 at 01:18:12PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Reorder structure members to reduce padding and improve memory layout.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
>  drivers/i3c/master/renesas-i3c.c | 28 ++++++++++++++--------------
>  1 file changed, 14 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 631c9c5d8038..5614ed99553c 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -221,19 +221,19 @@ enum renesas_i3c_event {
>  };
>
>  struct renesas_i3c_cmd {
> +	const void *tx_buf;
> +	void *rx_buf;
> +	/* i2c xfer */
> +	u8 *i2c_buf;
> +	const struct i2c_msg *msg;
> +	int i2c_bytes_left;
> +	int i2c_is_last;
>  	u32 cmd0;
>  	u32 len;
> -	const void *tx_buf;
>  	u32 tx_count;
> -	void *rx_buf;
>  	u32 rx_count;
>  	u32 err;
>  	u8 rnw;
> -	/* i2c xfer */
> -	int i2c_bytes_left;
> -	int i2c_is_last;
> -	u8 *i2c_buf;
> -	const struct i2c_msg *msg;
>  };
>
>  struct renesas_i3c_xfer {
> @@ -253,21 +253,21 @@ struct renesas_i3c_xferqueue {
>  };
>
>  struct renesas_i3c {
> +	void __iomem *regs;
> +	struct clk_bulk_data *clks;
> +	struct reset_control *presetn;
> +	struct reset_control *tresetn;
> +	struct renesas_i3c_xferqueue xferqueue;
>  	struct i3c_master_controller base;
> +	unsigned long rate;
>  	enum i3c_internal_state internal_state;
> -	u16 maxdevs;
>  	u32 free_pos;
>  	u32 dyn_addr;
>  	u32 i2c_STDBR;
>  	u32 i3c_STDBR;
>  	u32 extbr;
> -	unsigned long rate;
> +	u16 maxdevs;
>  	u8 addrs[RENESAS_I3C_MAX_DEVS];
> -	struct renesas_i3c_xferqueue xferqueue;
> -	void __iomem *regs;
> -	struct clk_bulk_data *clks;
> -	struct reset_control *presetn;
> -	struct reset_control *tresetn;
>  	u8 num_clks;
>  	u8 refclk_div;
>  };
> --
> 2.43.0
>

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

* Re: [PATCH 15/17] i3c: renesas: Use the "dev_name:irq_name" format for the interrupt name
  2026-05-22 10:18   ` Claudiu Beznea
@ 2026-05-22 19:51     ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:51 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

On Fri, May 22, 2026 at 01:18:13PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Use the "dev_name:irq_name" format for the interrupt names. This makes it
> easier to identify interrupts in systems where multiple devices may request
> interrupts with the same name.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/i3c/master/renesas-i3c.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 5614ed99553c..e6e05ac03082 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -1385,12 +1385,19 @@ static int renesas_i3c_probe(struct platform_device *pdev)
>  		return ret;
>
>  	for (i = 0; i < ARRAY_SIZE(renesas_i3c_irqs); i++) {
> +		const char *irqname;
> +
>  		ret = platform_get_irq_byname(pdev, renesas_i3c_irqs[i].name);
>  		if (ret < 0)
>  			return ret;
>
> +		irqname = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s:%s", dev_name(&pdev->dev),
> +					 renesas_i3c_irqs[i].desc);
> +		if (!irqname)
> +			return -ENOMEM;
> +
>  		ret = devm_request_irq(&pdev->dev, ret, renesas_i3c_irqs[i].isr,
> -				       0, renesas_i3c_irqs[i].desc, i3c);
> +				       0, irqname, i3c);
>  		if (ret)
>  			return ret;
>  	}
> --
> 2.43.0
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 15/17] i3c: renesas: Use the "dev_name:irq_name" format for the interrupt name
@ 2026-05-22 19:51     ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:51 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

On Fri, May 22, 2026 at 01:18:13PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Use the "dev_name:irq_name" format for the interrupt names. This makes it
> easier to identify interrupts in systems where multiple devices may request
> interrupts with the same name.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/i3c/master/renesas-i3c.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 5614ed99553c..e6e05ac03082 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -1385,12 +1385,19 @@ static int renesas_i3c_probe(struct platform_device *pdev)
>  		return ret;
>
>  	for (i = 0; i < ARRAY_SIZE(renesas_i3c_irqs); i++) {
> +		const char *irqname;
> +
>  		ret = platform_get_irq_byname(pdev, renesas_i3c_irqs[i].name);
>  		if (ret < 0)
>  			return ret;
>
> +		irqname = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s:%s", dev_name(&pdev->dev),
> +					 renesas_i3c_irqs[i].desc);
> +		if (!irqname)
> +			return -ENOMEM;
> +
>  		ret = devm_request_irq(&pdev->dev, ret, renesas_i3c_irqs[i].isr,
> -				       0, renesas_i3c_irqs[i].desc, i3c);
> +				       0, irqname, i3c);
>  		if (ret)
>  			return ret;
>  	}
> --
> 2.43.0
>

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

* Re: [PATCH 16/17] i3c: renesas: Drop unnecessary tab
  2026-05-22 10:18   ` Claudiu Beznea
@ 2026-05-22 19:52     ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:52 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

On Fri, May 22, 2026 at 01:18:14PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Remove an unnecessary tab to make the code cleaner.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/i3c/master/renesas-i3c.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index e6e05ac03082..a070db4d2440 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -109,7 +109,7 @@
>  #define  NCMDQP_DATA_LENGTH(x)	FIELD_PREP(GENMASK(31, 16), x)
>
>  #define NRSPQP			0x154 /* Normal Respone Queue */
> -#define  NRSPQP_NO_ERROR			0
> +#define  NRSPQP_NO_ERROR		0
>  #define  NRSPQP_ERROR_CRC		1
>  #define  NRSPQP_ERROR_PARITY		2
>  #define  NRSPQP_ERROR_FRAME		3
> --
> 2.43.0
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 16/17] i3c: renesas: Drop unnecessary tab
@ 2026-05-22 19:52     ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 19:52 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

On Fri, May 22, 2026 at 01:18:14PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Remove an unnecessary tab to make the code cleaner.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/i3c/master/renesas-i3c.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index e6e05ac03082..a070db4d2440 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -109,7 +109,7 @@
>  #define  NCMDQP_DATA_LENGTH(x)	FIELD_PREP(GENMASK(31, 16), x)
>
>  #define NRSPQP			0x154 /* Normal Respone Queue */
> -#define  NRSPQP_NO_ERROR			0
> +#define  NRSPQP_NO_ERROR		0
>  #define  NRSPQP_ERROR_CRC		1
>  #define  NRSPQP_ERROR_PARITY		2
>  #define  NRSPQP_ERROR_FRAME		3
> --
> 2.43.0
>

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

* Re: [PATCH 17/17] i3c: renesas: Add runtime PM support
  2026-05-22 10:18   ` Claudiu Beznea
@ 2026-05-22 20:01     ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 20:01 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

On Fri, May 22, 2026 at 01:18:15PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> On the SoCs where the Renesas I3C driver is enabled (RZ/G3S and RZ/G3E),
> the clocks of the IP are managed through a clock PM domain. To keep the
> I3C code simpler, the explicit clock handling was dropped along with the
> addition of runtime PM support, in favor of the runtime PM APIs. Only the
> code for getting tclk was preserved, as it is necessary to compute the
> I3C clock rate.
>
> All the APIs provided to the I3C subsystem through struct
> i3c_master_controller_ops are guarded with runtime PM APIs to
> enable/disable the controller at runtime.
>
> As the Renesas I3C driver implements an asynchronous transmit model by
> preparing a transfer and waiting for its completion through the ISR,
> renesas_i3c_abort_xfer() was added to disable interrupts and synchronize
> IRQs before runtime suspending the controller. For this, the interrupts
> were saved in struct renesas_i3c::irqs. Along with this,
> renesas_i3c_wait_xfer() return type was changed to unsigned long.
>
> Along with the clocks, the controller pin configuration is changed
> through the provided "sleep" pin configuration.
>
> Add runtime PM support for the Renesas I3C driver.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
>  drivers/i3c/master/renesas-i3c.c | 183 ++++++++++++++++++++++++++-----
>  1 file changed, 156 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index a070db4d2440..3b9807a89b54 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -21,7 +21,9 @@
...
>  static int renesas_i3c_probe(struct platform_device *pdev)
>  {
>  	struct renesas_i3c *i3c;
> @@ -1360,12 +1448,21 @@ static int renesas_i3c_probe(struct platform_device *pdev)
>  	if (IS_ERR(i3c->regs))
>  		return PTR_ERR(i3c->regs);
>
> -	ret = devm_clk_bulk_get_all_enabled(&pdev->dev, &i3c->clks);
> -	if (ret <= RENESAS_I3C_TCLK_IDX)
> -		return dev_err_probe(&pdev->dev, ret < 0 ? ret : -EINVAL,
> -				     "Failed to get clocks (need > %d, got %d)\n",
> -				     RENESAS_I3C_TCLK_IDX, ret);
> -	i3c->num_clks = ret;

you can still use devm_clk_bulk_get_all(), if need tclk, you iterate clks
to find 'tclk', in case in future, need more clocks than tcls.

> +	i3c->tclk = devm_clk_get(&pdev->dev, "tclk");
> +	if (IS_ERR(i3c->tclk))
> +		return dev_err_probe(&pdev->dev, PTR_ERR(i3c->tclk), "Failed to get tclk");
> +
> +	i3c->dev = &pdev->dev;
> +	pm_runtime_set_autosuspend_delay(&pdev->dev, 300);
> +	pm_runtime_use_autosuspend(&pdev->dev);
> +	ret = devm_add_action_or_reset(&pdev->dev, renesas_i3c_dont_use_autosuspend,
> +				       i3c->dev);

do you cleanup resource in renesas_i3c_dont_use_autosuspend(), look likes
needn't it.

> +	if (ret)
> +		return ret;
> +
> +	ret = devm_pm_runtime_enable(&pdev->dev);
> +	if (ret)
> +		return ret;
>
...
>
> +static int renesas_i3c_runtime_suspend(struct device *dev)
> +{
> +	return pinctrl_pm_select_sleep_state(dev);

Only change pin state, don't disable clock?

Frank
> +}
> +
> +static int renesas_i3c_runtime_resume(struct device *dev)
> +{
> +	return pinctrl_pm_select_default_state(dev);
> +}
> +
>  static const struct dev_pm_ops renesas_i3c_pm_ops = {
> +	RUNTIME_PM_OPS(renesas_i3c_runtime_suspend, renesas_i3c_runtime_resume, NULL)
>  	SYSTEM_SLEEP_PM_OPS(renesas_i3c_suspend, renesas_i3c_resume)
>  };
>
> --
> 2.43.0
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 17/17] i3c: renesas: Add runtime PM support
@ 2026-05-22 20:01     ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-22 20:01 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea

On Fri, May 22, 2026 at 01:18:15PM +0300, Claudiu Beznea wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> On the SoCs where the Renesas I3C driver is enabled (RZ/G3S and RZ/G3E),
> the clocks of the IP are managed through a clock PM domain. To keep the
> I3C code simpler, the explicit clock handling was dropped along with the
> addition of runtime PM support, in favor of the runtime PM APIs. Only the
> code for getting tclk was preserved, as it is necessary to compute the
> I3C clock rate.
>
> All the APIs provided to the I3C subsystem through struct
> i3c_master_controller_ops are guarded with runtime PM APIs to
> enable/disable the controller at runtime.
>
> As the Renesas I3C driver implements an asynchronous transmit model by
> preparing a transfer and waiting for its completion through the ISR,
> renesas_i3c_abort_xfer() was added to disable interrupts and synchronize
> IRQs before runtime suspending the controller. For this, the interrupts
> were saved in struct renesas_i3c::irqs. Along with this,
> renesas_i3c_wait_xfer() return type was changed to unsigned long.
>
> Along with the clocks, the controller pin configuration is changed
> through the provided "sleep" pin configuration.
>
> Add runtime PM support for the Renesas I3C driver.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
>  drivers/i3c/master/renesas-i3c.c | 183 ++++++++++++++++++++++++++-----
>  1 file changed, 156 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index a070db4d2440..3b9807a89b54 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
> @@ -21,7 +21,9 @@
...
>  static int renesas_i3c_probe(struct platform_device *pdev)
>  {
>  	struct renesas_i3c *i3c;
> @@ -1360,12 +1448,21 @@ static int renesas_i3c_probe(struct platform_device *pdev)
>  	if (IS_ERR(i3c->regs))
>  		return PTR_ERR(i3c->regs);
>
> -	ret = devm_clk_bulk_get_all_enabled(&pdev->dev, &i3c->clks);
> -	if (ret <= RENESAS_I3C_TCLK_IDX)
> -		return dev_err_probe(&pdev->dev, ret < 0 ? ret : -EINVAL,
> -				     "Failed to get clocks (need > %d, got %d)\n",
> -				     RENESAS_I3C_TCLK_IDX, ret);
> -	i3c->num_clks = ret;

you can still use devm_clk_bulk_get_all(), if need tclk, you iterate clks
to find 'tclk', in case in future, need more clocks than tcls.

> +	i3c->tclk = devm_clk_get(&pdev->dev, "tclk");
> +	if (IS_ERR(i3c->tclk))
> +		return dev_err_probe(&pdev->dev, PTR_ERR(i3c->tclk), "Failed to get tclk");
> +
> +	i3c->dev = &pdev->dev;
> +	pm_runtime_set_autosuspend_delay(&pdev->dev, 300);
> +	pm_runtime_use_autosuspend(&pdev->dev);
> +	ret = devm_add_action_or_reset(&pdev->dev, renesas_i3c_dont_use_autosuspend,
> +				       i3c->dev);

do you cleanup resource in renesas_i3c_dont_use_autosuspend(), look likes
needn't it.

> +	if (ret)
> +		return ret;
> +
> +	ret = devm_pm_runtime_enable(&pdev->dev);
> +	if (ret)
> +		return ret;
>
...
>
> +static int renesas_i3c_runtime_suspend(struct device *dev)
> +{
> +	return pinctrl_pm_select_sleep_state(dev);

Only change pin state, don't disable clock?

Frank
> +}
> +
> +static int renesas_i3c_runtime_resume(struct device *dev)
> +{
> +	return pinctrl_pm_select_default_state(dev);
> +}
> +
>  static const struct dev_pm_ops renesas_i3c_pm_ops = {
> +	RUNTIME_PM_OPS(renesas_i3c_runtime_suspend, renesas_i3c_runtime_resume, NULL)
>  	SYSTEM_SLEEP_PM_OPS(renesas_i3c_suspend, renesas_i3c_resume)
>  };
>
> --
> 2.43.0
>

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

* Re: [PATCH 02/17] i3c: renesas: Use the divider 128
  2026-05-22 19:06     ` Frank Li
@ 2026-05-23  8:14       ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-23  8:14 UTC (permalink / raw)
  To: Frank Li
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable



On 5/22/26 22:06, Frank Li wrote:
> On Fri, May 22, 2026 at 01:18:00PM +0300, Claudiu Beznea wrote:
>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>
>> The REFCKCTL.IREFCKS field is 3 bits wide, and setting it to 7 selects a
>> divider of 128 for the internal reference clock. Use this divider value.
> 
> This doesnot reflect what your change, code add one more search for clks = 7

cks is later written in the renesas_i3c_bus_init() to the REFCKCTL.IREFCKS. The 
following lines are from the renesas_i3c_bus_init() function:

	renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
	i3c->refclk_div = cks;

> 
> Frank
> 
>>
>> Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>> ---
>>   drivers/i3c/master/renesas-i3c.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
>> index 36e3ccbe66b0..1917549cf6d5 100644
>> --- a/drivers/i3c/master/renesas-i3c.c
>> +++ b/drivers/i3c/master/renesas-i3c.c
>> @@ -559,7 +559,7 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
>>
>>   	i2c_parse_fw_timings(&m->dev, &t, true);
>>
>> -	for (cks = 0; cks < 7; cks++) {
>> +	for (cks = 0; cks <= 7; cks++) {
>>   		/* SCL low-period calculation in Open-drain mode */
>>   		od_low_ticks = ((i2c_total_ticks * 6) / 10);
>>
>> --
>> 2.43.0
>>

-- 
Thank you,
Claudiu


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 02/17] i3c: renesas: Use the divider 128
@ 2026-05-23  8:14       ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-23  8:14 UTC (permalink / raw)
  To: Frank Li
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable



On 5/22/26 22:06, Frank Li wrote:
> On Fri, May 22, 2026 at 01:18:00PM +0300, Claudiu Beznea wrote:
>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>
>> The REFCKCTL.IREFCKS field is 3 bits wide, and setting it to 7 selects a
>> divider of 128 for the internal reference clock. Use this divider value.
> 
> This doesnot reflect what your change, code add one more search for clks = 7

cks is later written in the renesas_i3c_bus_init() to the REFCKCTL.IREFCKS. The 
following lines are from the renesas_i3c_bus_init() function:

	renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
	i3c->refclk_div = cks;

> 
> Frank
> 
>>
>> Fixes: d028219a9f14 ("i3c: master: Add basic driver for the Renesas I3C controller")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>> ---
>>   drivers/i3c/master/renesas-i3c.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
>> index 36e3ccbe66b0..1917549cf6d5 100644
>> --- a/drivers/i3c/master/renesas-i3c.c
>> +++ b/drivers/i3c/master/renesas-i3c.c
>> @@ -559,7 +559,7 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
>>
>>   	i2c_parse_fw_timings(&m->dev, &t, true);
>>
>> -	for (cks = 0; cks < 7; cks++) {
>> +	for (cks = 0; cks <= 7; cks++) {
>>   		/* SCL low-period calculation in Open-drain mode */
>>   		od_low_ticks = ((i2c_total_ticks * 6) / 10);
>>
>> --
>> 2.43.0
>>

-- 
Thank you,
Claudiu


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

* Re: [PATCH 17/17] i3c: renesas: Add runtime PM support
  2026-05-22 20:01     ` Frank Li
@ 2026-05-23 10:23       ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-23 10:23 UTC (permalink / raw)
  To: Frank Li
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, geert+renesas@glider.be



On 5/22/26 23:01, Frank Li wrote:
> On Fri, May 22, 2026 at 01:18:15PM +0300, Claudiu Beznea wrote:
>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>
>> On the SoCs where the Renesas I3C driver is enabled (RZ/G3S and RZ/G3E),
>> the clocks of the IP are managed through a clock PM domain. To keep the
>> I3C code simpler, the explicit clock handling was dropped along with the
>> addition of runtime PM support, in favor of the runtime PM APIs. Only the
>> code for getting tclk was preserved, as it is necessary to compute the
>> I3C clock rate.
>>
>> All the APIs provided to the I3C subsystem through struct
>> i3c_master_controller_ops are guarded with runtime PM APIs to
>> enable/disable the controller at runtime.
>>
>> As the Renesas I3C driver implements an asynchronous transmit model by
>> preparing a transfer and waiting for its completion through the ISR,
>> renesas_i3c_abort_xfer() was added to disable interrupts and synchronize
>> IRQs before runtime suspending the controller. For this, the interrupts
>> were saved in struct renesas_i3c::irqs. Along with this,
>> renesas_i3c_wait_xfer() return type was changed to unsigned long.
>>
>> Along with the clocks, the controller pin configuration is changed
>> through the provided "sleep" pin configuration.
>>
>> Add runtime PM support for the Renesas I3C driver.
>>
>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>> ---
>>   drivers/i3c/master/renesas-i3c.c | 183 ++++++++++++++++++++++++++-----
>>   1 file changed, 156 insertions(+), 27 deletions(-)
>>
>> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
>> index a070db4d2440..3b9807a89b54 100644
>> --- a/drivers/i3c/master/renesas-i3c.c
>> +++ b/drivers/i3c/master/renesas-i3c.c
>> @@ -21,7 +21,9 @@
> ...
>>   static int renesas_i3c_probe(struct platform_device *pdev)
>>   {
>>   	struct renesas_i3c *i3c;
>> @@ -1360,12 +1448,21 @@ static int renesas_i3c_probe(struct platform_device *pdev)
>>   	if (IS_ERR(i3c->regs))
>>   		return PTR_ERR(i3c->regs);
>>
>> -	ret = devm_clk_bulk_get_all_enabled(&pdev->dev, &i3c->clks);
>> -	if (ret <= RENESAS_I3C_TCLK_IDX)
>> -		return dev_err_probe(&pdev->dev, ret < 0 ? ret : -EINVAL,
>> -				     "Failed to get clocks (need > %d, got %d)\n",
>> -				     RENESAS_I3C_TCLK_IDX, ret);
>> -	i3c->num_clks = ret;
> 
> you can still use devm_clk_bulk_get_all(), if need tclk, you iterate clks
> to find 'tclk', in case in future, need more clocks than tcls.

Indeed, but as they are not needed in the current driver form, I would prefer to 
drop handling both of them as the final code looks simpler. As the clocks are 
enabled/disabled through PM domain, getting rid of 
devm_clk_bulk_get_all_enabled() simplifies the code, FMPOV, it drops 1 pointer 
and 1 int. So, I would like to keep it like this if all OK.

Also, if I'm not wrong, Geert (in cc) prefers having the clock controlled 
directly through power domains if that is possible. I concluded that from:

commit d303ce595cac
Author: Geert Uytterhoeven <geert+renesas@glider.be>
Date:   Wed Mar 20 11:30:03 2019 +0100

     i2c: riic: Add Runtime PM support

     - Replace explicit clock handling by Runtime PM calls,
       - Streamline Runtime PM handling in error paths,
       - Enable Runtime PM in .probe(),
       - Disable Runtime PM in .remove(),
       - Make sure the device is runtime-resumed when disabling interrupts in
         .remove().

     Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
     Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
     Tested-by: Chris Brandt <chris.brandt@renesas.com>
     Signed-off-by: Wolfram Sang <wsa@the-dreams.de>

> 
>> +	i3c->tclk = devm_clk_get(&pdev->dev, "tclk");
>> +	if (IS_ERR(i3c->tclk))
>> +		return dev_err_probe(&pdev->dev, PTR_ERR(i3c->tclk), "Failed to get tclk");
>> +
>> +	i3c->dev = &pdev->dev;
>> +	pm_runtime_set_autosuspend_delay(&pdev->dev, 300);
>> +	pm_runtime_use_autosuspend(&pdev->dev);
>> +	ret = devm_add_action_or_reset(&pdev->dev, renesas_i3c_dont_use_autosuspend,
>> +				       i3c->dev);
> 
> do you cleanup resource in renesas_i3c_dont_use_autosuspend(), look likes
> needn't it.

According to documentation at [1] this is necessary.

[1] 
https://elixir.bootlin.com/linux/v7.1-rc4/source/Documentation/power/runtime_pm.rst#L616

> 
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = devm_pm_runtime_enable(&pdev->dev);
>> +	if (ret)
>> +		return ret;
>>
> ...
>>
>> +static int renesas_i3c_runtime_suspend(struct device *dev)
>> +{
>> +	return pinctrl_pm_select_sleep_state(dev);
> 
> Only change pin state, don't disable clock?

Clocks are handled though the I3C PM domain.

On the Renesas SoCs, where this driver is enabled, clocks are controlled though 
clock PM domains. Every runtime PM suspend/resume will call 
clk_disable()/clk_enable() though the PM domains.

-- 
Thank you,
Claudiu


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 17/17] i3c: renesas: Add runtime PM support
@ 2026-05-23 10:23       ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-23 10:23 UTC (permalink / raw)
  To: Frank Li
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, geert+renesas@glider.be



On 5/22/26 23:01, Frank Li wrote:
> On Fri, May 22, 2026 at 01:18:15PM +0300, Claudiu Beznea wrote:
>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>
>> On the SoCs where the Renesas I3C driver is enabled (RZ/G3S and RZ/G3E),
>> the clocks of the IP are managed through a clock PM domain. To keep the
>> I3C code simpler, the explicit clock handling was dropped along with the
>> addition of runtime PM support, in favor of the runtime PM APIs. Only the
>> code for getting tclk was preserved, as it is necessary to compute the
>> I3C clock rate.
>>
>> All the APIs provided to the I3C subsystem through struct
>> i3c_master_controller_ops are guarded with runtime PM APIs to
>> enable/disable the controller at runtime.
>>
>> As the Renesas I3C driver implements an asynchronous transmit model by
>> preparing a transfer and waiting for its completion through the ISR,
>> renesas_i3c_abort_xfer() was added to disable interrupts and synchronize
>> IRQs before runtime suspending the controller. For this, the interrupts
>> were saved in struct renesas_i3c::irqs. Along with this,
>> renesas_i3c_wait_xfer() return type was changed to unsigned long.
>>
>> Along with the clocks, the controller pin configuration is changed
>> through the provided "sleep" pin configuration.
>>
>> Add runtime PM support for the Renesas I3C driver.
>>
>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>> ---
>>   drivers/i3c/master/renesas-i3c.c | 183 ++++++++++++++++++++++++++-----
>>   1 file changed, 156 insertions(+), 27 deletions(-)
>>
>> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
>> index a070db4d2440..3b9807a89b54 100644
>> --- a/drivers/i3c/master/renesas-i3c.c
>> +++ b/drivers/i3c/master/renesas-i3c.c
>> @@ -21,7 +21,9 @@
> ...
>>   static int renesas_i3c_probe(struct platform_device *pdev)
>>   {
>>   	struct renesas_i3c *i3c;
>> @@ -1360,12 +1448,21 @@ static int renesas_i3c_probe(struct platform_device *pdev)
>>   	if (IS_ERR(i3c->regs))
>>   		return PTR_ERR(i3c->regs);
>>
>> -	ret = devm_clk_bulk_get_all_enabled(&pdev->dev, &i3c->clks);
>> -	if (ret <= RENESAS_I3C_TCLK_IDX)
>> -		return dev_err_probe(&pdev->dev, ret < 0 ? ret : -EINVAL,
>> -				     "Failed to get clocks (need > %d, got %d)\n",
>> -				     RENESAS_I3C_TCLK_IDX, ret);
>> -	i3c->num_clks = ret;
> 
> you can still use devm_clk_bulk_get_all(), if need tclk, you iterate clks
> to find 'tclk', in case in future, need more clocks than tcls.

Indeed, but as they are not needed in the current driver form, I would prefer to 
drop handling both of them as the final code looks simpler. As the clocks are 
enabled/disabled through PM domain, getting rid of 
devm_clk_bulk_get_all_enabled() simplifies the code, FMPOV, it drops 1 pointer 
and 1 int. So, I would like to keep it like this if all OK.

Also, if I'm not wrong, Geert (in cc) prefers having the clock controlled 
directly through power domains if that is possible. I concluded that from:

commit d303ce595cac
Author: Geert Uytterhoeven <geert+renesas@glider.be>
Date:   Wed Mar 20 11:30:03 2019 +0100

     i2c: riic: Add Runtime PM support

     - Replace explicit clock handling by Runtime PM calls,
       - Streamline Runtime PM handling in error paths,
       - Enable Runtime PM in .probe(),
       - Disable Runtime PM in .remove(),
       - Make sure the device is runtime-resumed when disabling interrupts in
         .remove().

     Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
     Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
     Tested-by: Chris Brandt <chris.brandt@renesas.com>
     Signed-off-by: Wolfram Sang <wsa@the-dreams.de>

> 
>> +	i3c->tclk = devm_clk_get(&pdev->dev, "tclk");
>> +	if (IS_ERR(i3c->tclk))
>> +		return dev_err_probe(&pdev->dev, PTR_ERR(i3c->tclk), "Failed to get tclk");
>> +
>> +	i3c->dev = &pdev->dev;
>> +	pm_runtime_set_autosuspend_delay(&pdev->dev, 300);
>> +	pm_runtime_use_autosuspend(&pdev->dev);
>> +	ret = devm_add_action_or_reset(&pdev->dev, renesas_i3c_dont_use_autosuspend,
>> +				       i3c->dev);
> 
> do you cleanup resource in renesas_i3c_dont_use_autosuspend(), look likes
> needn't it.

According to documentation at [1] this is necessary.

[1] 
https://elixir.bootlin.com/linux/v7.1-rc4/source/Documentation/power/runtime_pm.rst#L616

> 
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = devm_pm_runtime_enable(&pdev->dev);
>> +	if (ret)
>> +		return ret;
>>
> ...
>>
>> +static int renesas_i3c_runtime_suspend(struct device *dev)
>> +{
>> +	return pinctrl_pm_select_sleep_state(dev);
> 
> Only change pin state, don't disable clock?

Clocks are handled though the I3C PM domain.

On the Renesas SoCs, where this driver is enabled, clocks are controlled though 
clock PM domains. Every runtime PM suspend/resume will call 
clk_disable()/clk_enable() though the PM domains.

-- 
Thank you,
Claudiu


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

* Re: [PATCH 06/17] i3c: renesas: Reset the controller on resume
  2026-05-22 19:15     ` Frank Li
@ 2026-05-23 10:24       ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-23 10:24 UTC (permalink / raw)
  To: Frank Li
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable



On 5/22/26 22:15, Frank Li wrote:
> On Fri, May 22, 2026 at 01:18:04PM +0300, Claudiu Beznea wrote:
>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>
>> Reset the controller on resume after enabling the clocks to follow the
>> same sequence as in probe and avoid potential ordering related failures.
>>
>> Fixes: e7218986319b ("i3c: renesas: Add suspend/resume support")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>> ---
> 
> Can you move these similar stuff to one helper function to avoid duplicate
> efforts later?

If you are talking about moving also the control of the reset signals in the 
renesas_i3c_reset() I can do that, but, FMPOV, it will complicate the code, 
especially the initialization and failure paths (see the above diff built on top 
of this series).

Moving the reset de-assert in the renesas_i3c_reset() will involve calling 
functions to assert back the resets in case of failure. FMPOV, that is a bit 
unbalanced (wrt the way the code looks) because we are calling deassert in one 
function and assert in another function. It is a bit difficult to follow.

Please see the above diff and let me know your thoughts.


diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 3b9807a89b54..5f45a024aa54 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -255,8 +255,7 @@ struct renesas_i3c_xferqueue {
  struct renesas_i3c {
         void __iomem *regs;
         struct clk *tclk;
-       struct reset_control *presetn;
-       struct reset_control *tresetn;
+       struct reset_control_bulk_data *resets;
         struct device *dev;
         int *irqs;
         struct renesas_i3c_xferqueue xferqueue;
@@ -264,6 +263,7 @@ struct renesas_i3c {
         unsigned long rate;
         unsigned int num_irqs;
         enum i3c_internal_state internal_state;
+       u32 num_resets;
         u32 free_pos;
         u32 dyn_addr;
         u32 i2c_STDBR;
@@ -492,16 +492,28 @@ static int renesas_i3c_reset(struct renesas_i3c *i3c)
         u32 val;
         int ret;

+       ret = reset_control_bulk_deassert(i3c->num_resets, i3c->resets);
+       if (ret)
+               return ret;
+
         PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
         ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
         if (ret)
-               return ret;
+               goto assert;

         renesas_writel(i3c->regs, BCTL, 0);
         renesas_set_bit(i3c->regs, RSTCTL, RSTCTL_RI3CRST);

-       return read_poll_timeout(renesas_readl, val, !(val & RSTCTL_RI3CRST),
-                                0, 1000, false, i3c->regs, RSTCTL);
+       ret = read_poll_timeout(renesas_readl, val, !(val & RSTCTL_RI3CRST),
+                               0, 1000, false, i3c->regs, RSTCTL);
+       if (ret)
+               goto assert;
+
+       return 0;
+
+assert:
+       reset_control_bulk_assert(i3c->num_resets, i3c->resets);
+       return ret;
  }

  static void renesas_i3c_hw_init(struct renesas_i3c *i3c)
@@ -1430,11 +1442,20 @@ static const struct renesas_i3c_irq_desc 
renesas_i3c_irqs[] = {
         { .name = "nack", .isr = renesas_i3c_tend_isr, .desc = "i3c-nack" },
  };

+static const char * const renesas_i3c_resets[] = { "tresetn", "presetn" };
+
  static void renesas_i3c_dont_use_autosuspend(void *data)
  {
         pm_runtime_dont_use_autosuspend(data);
  }

+static void renesas_i3c_resets_assert(void *data)
+{
+       struct renesas_i3c *i3c = data;
+
+       reset_control_bulk_assert(i3c->num_resets, i3c->resets);
+}
+
  static int renesas_i3c_probe(struct platform_device *pdev)
  {
         struct renesas_i3c *i3c;
@@ -1464,15 +1485,20 @@ static int renesas_i3c_probe(struct platform_device *pdev)
         if (ret)
                 return ret;

-       i3c->tresetn = 
devm_reset_control_get_optional_exclusive_deasserted(&pdev->dev, "tresetn");
-       if (IS_ERR(i3c->tresetn))
-               return dev_err_probe(&pdev->dev, PTR_ERR(i3c->tresetn),
-                                    "Error: missing tresetn ctrl\n");
+       i3c->num_resets = ARRAY_SIZE(renesas_i3c_resets);
+       i3c->resets = devm_kmalloc_array(&pdev->dev, i3c->num_resets,
+                                        sizeof(*i3c->resets), GFP_KERNEL);
+       if (!i3c->resets)
+               return -ENOMEM;

-       i3c->presetn = 
devm_reset_control_get_optional_exclusive_deasserted(&pdev->dev, "presetn");
-       if (IS_ERR(i3c->presetn))
-               return dev_err_probe(&pdev->dev, PTR_ERR(i3c->presetn),
-                                    "Error: missing presetn ctrl\n");
+       for (unsigned int i = 0; i < i3c->num_resets; i++)
+               i3c->resets[i].id = renesas_i3c_resets[i];
+
+       ret = devm_reset_control_bulk_get_optional_exclusive(&pdev->dev,
+                                                            i3c->num_resets,
+                                                            i3c->resets);
+       if (ret)
+               return ret;

         spin_lock_init(&i3c->xferqueue.lock);
         INIT_LIST_HEAD(&i3c->xferqueue.list);
@@ -1481,6 +1507,11 @@ static int renesas_i3c_probe(struct platform_device *pdev)
         if (ret)
                 return ret;

+       /* Add devm action for resets deasserted in renesas_i3c_reset(). */
+       ret = devm_add_action_or_reset(&pdev->dev, renesas_i3c_resets_assert, NULL);
+       if (ret)
+               return ret;
+
         i3c->num_irqs = ARRAY_SIZE(renesas_i3c_irqs);
         i3c->irqs = devm_kcalloc(&pdev->dev, i3c->num_irqs, sizeof(*i3c->irqs), 
GFP_KERNEL);
         if (!i3c->irqs)
@@ -1523,15 +1554,11 @@ static void renesas_i3c_remove(struct platform_device *pdev)
  static int renesas_i3c_suspend(struct device *dev)
  {
         struct renesas_i3c *i3c = dev_get_drvdata(dev);
-       struct reset_control_bulk_data resets[] = {
-               { .rstc = i3c->presetn },
-               { .rstc = i3c->tresetn },
-       };
         int ret;

         i2c_mark_adapter_suspended(&i3c->base.i2c);

-       ret = reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
+       ret = reset_control_bulk_assert(i3c->num_resets, i3c->resets);
         if (ret)
                 goto err_mark_resumed;

@@ -1542,7 +1569,7 @@ static int renesas_i3c_suspend(struct device *dev)
         return 0;

  err_resets_deassert:
-       reset_control_bulk_deassert(ARRAY_SIZE(resets), resets);
+       reset_control_bulk_deassert(i3c->num_resets, i3c->resets);
  err_mark_resumed:
         i2c_mark_adapter_resumed(&i3c->base.i2c);

@@ -1552,23 +1579,15 @@ static int renesas_i3c_suspend(struct device *dev)
  static int renesas_i3c_resume(struct device *dev)
  {
         struct renesas_i3c *i3c = dev_get_drvdata(dev);
-       struct reset_control_bulk_data resets[] = {
-               { .rstc = i3c->presetn },
-               { .rstc = i3c->tresetn },
-       };
         int ret;

         ret = pm_runtime_force_resume(dev);
         if (ret)
                 return ret;

-       ret = reset_control_bulk_deassert(ARRAY_SIZE(resets), resets);
-       if (ret)
-               return ret;
-
         ret = renesas_i3c_reset(i3c);
         if (ret)
-               goto err_resets_asserted;
+               return ret;

         PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
         ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
@@ -1607,7 +1626,7 @@ static int renesas_i3c_resume(struct device *dev)
          * if a runtime path is triggered after a failed resume). Checked on
          * RZ/G3S.
          */
-       reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
+       reset_control_bulk_assert(i3c->num_resets, i3c->resets);
         return ret;
  }

-- 
Thank you,
Claudiu


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

* Re: [PATCH 06/17] i3c: renesas: Reset the controller on resume
@ 2026-05-23 10:24       ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-23 10:24 UTC (permalink / raw)
  To: Frank Li
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable



On 5/22/26 22:15, Frank Li wrote:
> On Fri, May 22, 2026 at 01:18:04PM +0300, Claudiu Beznea wrote:
>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>
>> Reset the controller on resume after enabling the clocks to follow the
>> same sequence as in probe and avoid potential ordering related failures.
>>
>> Fixes: e7218986319b ("i3c: renesas: Add suspend/resume support")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>> ---
> 
> Can you move these similar stuff to one helper function to avoid duplicate
> efforts later?

If you are talking about moving also the control of the reset signals in the 
renesas_i3c_reset() I can do that, but, FMPOV, it will complicate the code, 
especially the initialization and failure paths (see the above diff built on top 
of this series).

Moving the reset de-assert in the renesas_i3c_reset() will involve calling 
functions to assert back the resets in case of failure. FMPOV, that is a bit 
unbalanced (wrt the way the code looks) because we are calling deassert in one 
function and assert in another function. It is a bit difficult to follow.

Please see the above diff and let me know your thoughts.


diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 3b9807a89b54..5f45a024aa54 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -255,8 +255,7 @@ struct renesas_i3c_xferqueue {
  struct renesas_i3c {
         void __iomem *regs;
         struct clk *tclk;
-       struct reset_control *presetn;
-       struct reset_control *tresetn;
+       struct reset_control_bulk_data *resets;
         struct device *dev;
         int *irqs;
         struct renesas_i3c_xferqueue xferqueue;
@@ -264,6 +263,7 @@ struct renesas_i3c {
         unsigned long rate;
         unsigned int num_irqs;
         enum i3c_internal_state internal_state;
+       u32 num_resets;
         u32 free_pos;
         u32 dyn_addr;
         u32 i2c_STDBR;
@@ -492,16 +492,28 @@ static int renesas_i3c_reset(struct renesas_i3c *i3c)
         u32 val;
         int ret;

+       ret = reset_control_bulk_deassert(i3c->num_resets, i3c->resets);
+       if (ret)
+               return ret;
+
         PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
         ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
         if (ret)
-               return ret;
+               goto assert;

         renesas_writel(i3c->regs, BCTL, 0);
         renesas_set_bit(i3c->regs, RSTCTL, RSTCTL_RI3CRST);

-       return read_poll_timeout(renesas_readl, val, !(val & RSTCTL_RI3CRST),
-                                0, 1000, false, i3c->regs, RSTCTL);
+       ret = read_poll_timeout(renesas_readl, val, !(val & RSTCTL_RI3CRST),
+                               0, 1000, false, i3c->regs, RSTCTL);
+       if (ret)
+               goto assert;
+
+       return 0;
+
+assert:
+       reset_control_bulk_assert(i3c->num_resets, i3c->resets);
+       return ret;
  }

  static void renesas_i3c_hw_init(struct renesas_i3c *i3c)
@@ -1430,11 +1442,20 @@ static const struct renesas_i3c_irq_desc 
renesas_i3c_irqs[] = {
         { .name = "nack", .isr = renesas_i3c_tend_isr, .desc = "i3c-nack" },
  };

+static const char * const renesas_i3c_resets[] = { "tresetn", "presetn" };
+
  static void renesas_i3c_dont_use_autosuspend(void *data)
  {
         pm_runtime_dont_use_autosuspend(data);
  }

+static void renesas_i3c_resets_assert(void *data)
+{
+       struct renesas_i3c *i3c = data;
+
+       reset_control_bulk_assert(i3c->num_resets, i3c->resets);
+}
+
  static int renesas_i3c_probe(struct platform_device *pdev)
  {
         struct renesas_i3c *i3c;
@@ -1464,15 +1485,20 @@ static int renesas_i3c_probe(struct platform_device *pdev)
         if (ret)
                 return ret;

-       i3c->tresetn = 
devm_reset_control_get_optional_exclusive_deasserted(&pdev->dev, "tresetn");
-       if (IS_ERR(i3c->tresetn))
-               return dev_err_probe(&pdev->dev, PTR_ERR(i3c->tresetn),
-                                    "Error: missing tresetn ctrl\n");
+       i3c->num_resets = ARRAY_SIZE(renesas_i3c_resets);
+       i3c->resets = devm_kmalloc_array(&pdev->dev, i3c->num_resets,
+                                        sizeof(*i3c->resets), GFP_KERNEL);
+       if (!i3c->resets)
+               return -ENOMEM;

-       i3c->presetn = 
devm_reset_control_get_optional_exclusive_deasserted(&pdev->dev, "presetn");
-       if (IS_ERR(i3c->presetn))
-               return dev_err_probe(&pdev->dev, PTR_ERR(i3c->presetn),
-                                    "Error: missing presetn ctrl\n");
+       for (unsigned int i = 0; i < i3c->num_resets; i++)
+               i3c->resets[i].id = renesas_i3c_resets[i];
+
+       ret = devm_reset_control_bulk_get_optional_exclusive(&pdev->dev,
+                                                            i3c->num_resets,
+                                                            i3c->resets);
+       if (ret)
+               return ret;

         spin_lock_init(&i3c->xferqueue.lock);
         INIT_LIST_HEAD(&i3c->xferqueue.list);
@@ -1481,6 +1507,11 @@ static int renesas_i3c_probe(struct platform_device *pdev)
         if (ret)
                 return ret;

+       /* Add devm action for resets deasserted in renesas_i3c_reset(). */
+       ret = devm_add_action_or_reset(&pdev->dev, renesas_i3c_resets_assert, NULL);
+       if (ret)
+               return ret;
+
         i3c->num_irqs = ARRAY_SIZE(renesas_i3c_irqs);
         i3c->irqs = devm_kcalloc(&pdev->dev, i3c->num_irqs, sizeof(*i3c->irqs), 
GFP_KERNEL);
         if (!i3c->irqs)
@@ -1523,15 +1554,11 @@ static void renesas_i3c_remove(struct platform_device *pdev)
  static int renesas_i3c_suspend(struct device *dev)
  {
         struct renesas_i3c *i3c = dev_get_drvdata(dev);
-       struct reset_control_bulk_data resets[] = {
-               { .rstc = i3c->presetn },
-               { .rstc = i3c->tresetn },
-       };
         int ret;

         i2c_mark_adapter_suspended(&i3c->base.i2c);

-       ret = reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
+       ret = reset_control_bulk_assert(i3c->num_resets, i3c->resets);
         if (ret)
                 goto err_mark_resumed;

@@ -1542,7 +1569,7 @@ static int renesas_i3c_suspend(struct device *dev)
         return 0;

  err_resets_deassert:
-       reset_control_bulk_deassert(ARRAY_SIZE(resets), resets);
+       reset_control_bulk_deassert(i3c->num_resets, i3c->resets);
  err_mark_resumed:
         i2c_mark_adapter_resumed(&i3c->base.i2c);

@@ -1552,23 +1579,15 @@ static int renesas_i3c_suspend(struct device *dev)
  static int renesas_i3c_resume(struct device *dev)
  {
         struct renesas_i3c *i3c = dev_get_drvdata(dev);
-       struct reset_control_bulk_data resets[] = {
-               { .rstc = i3c->presetn },
-               { .rstc = i3c->tresetn },
-       };
         int ret;

         ret = pm_runtime_force_resume(dev);
         if (ret)
                 return ret;

-       ret = reset_control_bulk_deassert(ARRAY_SIZE(resets), resets);
-       if (ret)
-               return ret;
-
         ret = renesas_i3c_reset(i3c);
         if (ret)
-               goto err_resets_asserted;
+               return ret;

         PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(i3c->dev, pm);
         ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
@@ -1607,7 +1626,7 @@ static int renesas_i3c_resume(struct device *dev)
          * if a runtime path is triggered after a failed resume). Checked on
          * RZ/G3S.
          */
-       reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
+       reset_control_bulk_assert(i3c->num_resets, i3c->resets);
         return ret;
  }

-- 
Thank you,
Claudiu


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 07/17] i3c: renesas: Perform Dynamic Address Assignment on resume
  2026-05-22 19:16     ` Frank Li
@ 2026-05-23 10:26       ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-23 10:26 UTC (permalink / raw)
  To: Frank Li
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable



On 5/22/26 22:16, Frank Li wrote:
> On Fri, May 22, 2026 at 01:18:05PM +0300, Claudiu Beznea wrote:
>> From: Claudiu Beznea<claudiu.beznea.uj@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 referhttps://lore.kernel.org/linux-i3c/20260512121732.406009-1- 
> adrian.hunter@intel.com/T/#mafdc9631a2a18dfebfa5b5efcb8584d32bceba7f
> 
> which defer DAA to workqueue.
> 

I've reviewed this series and tested it. Tests passed on my side.

According to the following diff from patch 6/8 [1]:

  /**
   * i3c_master_do_daa_ext() - Dynamic Address Assignment (extended version)
   * @master: controller
@@ -1878,9 +1889,7 @@ int i3c_master_do_daa_ext(struct i3c_master_controller 
*master, bool rstdaa)
  	if (ret)
  		goto out;

-	i3c_bus_normaluse_lock(&master->bus);
-	i3c_master_register_new_i3c_devs(master);
-	i3c_bus_normaluse_unlock(&master->bus);
+	queue_work(master->wq, &master->reg_work);
  out:
  	i3c_master_rpm_put(master);

only the registration of the new devices is deferred. The RSTDAA command is 
still sent according to the following code in i3c_master_do_daa_ext():

	// ...

	if (master->shutting_down) {
		ret = -ENODEV;
	} else {
		if (rstdaa)
			rstret = i3c_master_rstdaa_locked(master, I3C_BROADCAST_ADDR);
		ret = master->ops->do_daa(master);
	}

	// ...

which is what fixed the communication with the I3C devices I used in my testing, 
in resume case.

If I remove the i3c_master_do_daa_ext() call from renesas_i3c_resume() then the 
I3C devices are not working anymore after resume on my setup.

Also, the i3c_master_do_daa_ext() call in i3c_hci_resume_common() remains 
unchanged [2] in series [1].

So, could you please let me know if I misunderstood your comment and if there is 
anything that should be done for this patch?

[1] https://lore.kernel.org/all/20260512121732.406009-7-adrian.hunter@intel.com/
[2] 
https://elixir.bootlin.com/linux/v7.1-rc4/source/drivers/i3c/master/mipi-i3c-hci/core.c#L848

-- 
Thank you,
Claudiu


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

* Re: [PATCH 07/17] i3c: renesas: Perform Dynamic Address Assignment on resume
@ 2026-05-23 10:26       ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-23 10:26 UTC (permalink / raw)
  To: Frank Li
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable



On 5/22/26 22:16, Frank Li wrote:
> On Fri, May 22, 2026 at 01:18:05PM +0300, Claudiu Beznea wrote:
>> From: Claudiu Beznea<claudiu.beznea.uj@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 referhttps://lore.kernel.org/linux-i3c/20260512121732.406009-1- 
> adrian.hunter@intel.com/T/#mafdc9631a2a18dfebfa5b5efcb8584d32bceba7f
> 
> which defer DAA to workqueue.
> 

I've reviewed this series and tested it. Tests passed on my side.

According to the following diff from patch 6/8 [1]:

  /**
   * i3c_master_do_daa_ext() - Dynamic Address Assignment (extended version)
   * @master: controller
@@ -1878,9 +1889,7 @@ int i3c_master_do_daa_ext(struct i3c_master_controller 
*master, bool rstdaa)
  	if (ret)
  		goto out;

-	i3c_bus_normaluse_lock(&master->bus);
-	i3c_master_register_new_i3c_devs(master);
-	i3c_bus_normaluse_unlock(&master->bus);
+	queue_work(master->wq, &master->reg_work);
  out:
  	i3c_master_rpm_put(master);

only the registration of the new devices is deferred. The RSTDAA command is 
still sent according to the following code in i3c_master_do_daa_ext():

	// ...

	if (master->shutting_down) {
		ret = -ENODEV;
	} else {
		if (rstdaa)
			rstret = i3c_master_rstdaa_locked(master, I3C_BROADCAST_ADDR);
		ret = master->ops->do_daa(master);
	}

	// ...

which is what fixed the communication with the I3C devices I used in my testing, 
in resume case.

If I remove the i3c_master_do_daa_ext() call from renesas_i3c_resume() then the 
I3C devices are not working anymore after resume on my setup.

Also, the i3c_master_do_daa_ext() call in i3c_hci_resume_common() remains 
unchanged [2] in series [1].

So, could you please let me know if I misunderstood your comment and if there is 
anything that should be done for this patch?

[1] https://lore.kernel.org/all/20260512121732.406009-7-adrian.hunter@intel.com/
[2] 
https://elixir.bootlin.com/linux/v7.1-rc4/source/drivers/i3c/master/mipi-i3c-hci/core.c#L848

-- 
Thank you,
Claudiu


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 09/17] i3c: renesas: Use reset_control_bulk_{assert, deassert}()
  2026-05-22 19:19     ` Frank Li
@ 2026-05-23 10:26       ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-23 10:26 UTC (permalink / raw)
  To: Frank Li
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea



On 5/22/26 22:19, Frank Li wrote:
> On Fri, May 22, 2026 at 01:18:07PM +0300, Claudiu Beznea wrote:
>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>
>> Use reset_control_bulk_assert() and reset_control_bulk_deassert() in the
>> suspend and resume paths to simplify the code.
>>
>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>> ---
>>   drivers/i3c/master/renesas-i3c.c | 30 +++++++++++++-----------------
>>   1 file changed, 13 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
>> index d32646deb69f..e5963270d6e5 100644
>> --- a/drivers/i3c/master/renesas-i3c.c
>> +++ b/drivers/i3c/master/renesas-i3c.c
>> @@ -1414,24 +1414,22 @@ static void renesas_i3c_remove(struct platform_device *pdev)
>>   static int renesas_i3c_suspend(struct device *dev)
>>   {
>>   	struct renesas_i3c *i3c = dev_get_drvdata(dev);
>> +	struct reset_control_bulk_data resets[] = {
>> +		{ .rstc = i3c->presetn },
>> +		{ .rstc = i3c->tresetn },
>> +	};
> 
> Suppose it is also used in probe funciton. can move these into renesas_i3c
As explained in patch 06/07 is either this way or complicate other code paths. 
Please let me know the preferred approach.

-- 
Thank you,
Claudiu


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 09/17] i3c: renesas: Use reset_control_bulk_{assert, deassert}()
@ 2026-05-23 10:26       ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-23 10:26 UTC (permalink / raw)
  To: Frank Li
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea



On 5/22/26 22:19, Frank Li wrote:
> On Fri, May 22, 2026 at 01:18:07PM +0300, Claudiu Beznea wrote:
>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>
>> Use reset_control_bulk_assert() and reset_control_bulk_deassert() in the
>> suspend and resume paths to simplify the code.
>>
>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>> ---
>>   drivers/i3c/master/renesas-i3c.c | 30 +++++++++++++-----------------
>>   1 file changed, 13 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
>> index d32646deb69f..e5963270d6e5 100644
>> --- a/drivers/i3c/master/renesas-i3c.c
>> +++ b/drivers/i3c/master/renesas-i3c.c
>> @@ -1414,24 +1414,22 @@ static void renesas_i3c_remove(struct platform_device *pdev)
>>   static int renesas_i3c_suspend(struct device *dev)
>>   {
>>   	struct renesas_i3c *i3c = dev_get_drvdata(dev);
>> +	struct reset_control_bulk_data resets[] = {
>> +		{ .rstc = i3c->presetn },
>> +		{ .rstc = i3c->tresetn },
>> +	};
> 
> Suppose it is also used in probe funciton. can move these into renesas_i3c
As explained in patch 06/07 is either this way or complicate other code paths. 
Please let me know the preferred approach.

-- 
Thank you,
Claudiu


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

* Re: [PATCH 03/17] i3c: renesas: Restore STDBR and EXTBR registers on resume
  2026-05-22 19:10     ` Frank Li
@ 2026-05-28  8:29       ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-28  8:29 UTC (permalink / raw)
  To: Frank Li
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

Hi, Frank,

On 5/22/26 22:10, Frank Li wrote:
> On Fri, May 22, 2026 at 01:18:01PM +0300, Claudiu Beznea wrote:
>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>
>> The Renesas RZ/G3S supports a power saving state where power to the most
>> SoC componentes (including I3C) is lost.
>>
>> The STDBR and EXTBR are configured in initialization phase though the
>> struct i3c_master_controller_ops::bus_init. Set them on resume function
>> as well to keep the same state of the controller after a suspend with
>> power loss and a similar initialization sequence as in bus_init.
>>
>> Fixes: e7218986319b ("i3c: renesas: Add suspend/resume support")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>> ---
>>   drivers/i3c/master/renesas-i3c.c | 10 ++++++----
>>   1 file changed, 6 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
>> index 1917549cf6d5..6c23f956ad2a 100644
>> --- a/drivers/i3c/master/renesas-i3c.c
>> +++ b/drivers/i3c/master/renesas-i3c.c
>> @@ -260,6 +260,7 @@ struct renesas_i3c {
>>   	u32 dyn_addr;
>>   	u32 i2c_STDBR;
>>   	u32 i3c_STDBR;
>> +	u32 extbr;
> 
> can you keep consisent with above 2 register, use upcase EXTBR,

Using upper case for this will mislead the compiler. There is already a macro 
defined for EXTBR:

#define EXTBR                   0x78

Defining this member as:

u32 EXTBR;

will make the compiler try to replace the EXTBR in "i3c->EXTBR" at preprocessing 
time:

   CC [M]  drivers/i3c/master/renesas-i3c.o
../drivers/i3c/master/renesas-i3c.c:65:17: error: expected identifier or ‘(’ 
before numeric constant
    65 | #define EXTBR   0x78
       |                 ^~~~
../drivers/i3c/master/renesas-i3c.c:263:6: note: in expansion of macro ‘EXTBR’
   263 |  u32 EXTBR;
       |      ^~~~~
../drivers/i3c/master/renesas-i3c.c: In function ‘renesas_i3c_bus_init’:
../drivers/i3c/master/renesas-i3c.c:65:17: error: expected identifier before 
numeric constant
    65 | #define EXTBR   0x78
       |                 ^~~~
../drivers/i3c/master/renesas-i3c.c:611:7: note: in expansion of macro ‘EXTBR’
   611 |  i3c->EXTBR = EXTBR_EBRLO(od_low_ticks) | EXTBR_EBRHO(od_high_ticks) |
       |       ^~~~~
../drivers/i3c/master/renesas-i3c.c:65:17: error: expected identifier before 
numeric constant
    65 | #define EXTBR   0x78
       |                 ^~~~
../drivers/i3c/master/renesas-i3c.c:613:40: note: in expansion of macro ‘EXTBR’
   613 |  renesas_writel(i3c->regs, EXTBR, i3c->EXTBR);
       |                                        ^~~~~
../drivers/i3c/master/renesas-i3c.c: In function ‘renesas_i3c_resume_noirq’:
../drivers/i3c/master/renesas-i3c.c:65:17: error: expected identifier before 
numeric constant
    65 | #define EXTBR   0x78
       |                 ^~~~
../drivers/i3c/master/renesas-i3c.c:1451:40: note: in expansion of macro ‘EXTBR’
  1451 |  renesas_writel(i3c->regs, EXTBR, i3c->EXTBR);
       |                                        ^~~~~

The register contains both i3c and i2c specific fields. I'm not sure using 
i2c_i3c_EXTBR is the best way to go forward for this or just keeping it as is.

-- 
Thank you,
Claudiu


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 03/17] i3c: renesas: Restore STDBR and EXTBR registers on resume
@ 2026-05-28  8:29       ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-05-28  8:29 UTC (permalink / raw)
  To: Frank Li
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

Hi, Frank,

On 5/22/26 22:10, Frank Li wrote:
> On Fri, May 22, 2026 at 01:18:01PM +0300, Claudiu Beznea wrote:
>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>
>> The Renesas RZ/G3S supports a power saving state where power to the most
>> SoC componentes (including I3C) is lost.
>>
>> The STDBR and EXTBR are configured in initialization phase though the
>> struct i3c_master_controller_ops::bus_init. Set them on resume function
>> as well to keep the same state of the controller after a suspend with
>> power loss and a similar initialization sequence as in bus_init.
>>
>> Fixes: e7218986319b ("i3c: renesas: Add suspend/resume support")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>> ---
>>   drivers/i3c/master/renesas-i3c.c | 10 ++++++----
>>   1 file changed, 6 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
>> index 1917549cf6d5..6c23f956ad2a 100644
>> --- a/drivers/i3c/master/renesas-i3c.c
>> +++ b/drivers/i3c/master/renesas-i3c.c
>> @@ -260,6 +260,7 @@ struct renesas_i3c {
>>   	u32 dyn_addr;
>>   	u32 i2c_STDBR;
>>   	u32 i3c_STDBR;
>> +	u32 extbr;
> 
> can you keep consisent with above 2 register, use upcase EXTBR,

Using upper case for this will mislead the compiler. There is already a macro 
defined for EXTBR:

#define EXTBR                   0x78

Defining this member as:

u32 EXTBR;

will make the compiler try to replace the EXTBR in "i3c->EXTBR" at preprocessing 
time:

   CC [M]  drivers/i3c/master/renesas-i3c.o
../drivers/i3c/master/renesas-i3c.c:65:17: error: expected identifier or ‘(’ 
before numeric constant
    65 | #define EXTBR   0x78
       |                 ^~~~
../drivers/i3c/master/renesas-i3c.c:263:6: note: in expansion of macro ‘EXTBR’
   263 |  u32 EXTBR;
       |      ^~~~~
../drivers/i3c/master/renesas-i3c.c: In function ‘renesas_i3c_bus_init’:
../drivers/i3c/master/renesas-i3c.c:65:17: error: expected identifier before 
numeric constant
    65 | #define EXTBR   0x78
       |                 ^~~~
../drivers/i3c/master/renesas-i3c.c:611:7: note: in expansion of macro ‘EXTBR’
   611 |  i3c->EXTBR = EXTBR_EBRLO(od_low_ticks) | EXTBR_EBRHO(od_high_ticks) |
       |       ^~~~~
../drivers/i3c/master/renesas-i3c.c:65:17: error: expected identifier before 
numeric constant
    65 | #define EXTBR   0x78
       |                 ^~~~
../drivers/i3c/master/renesas-i3c.c:613:40: note: in expansion of macro ‘EXTBR’
   613 |  renesas_writel(i3c->regs, EXTBR, i3c->EXTBR);
       |                                        ^~~~~
../drivers/i3c/master/renesas-i3c.c: In function ‘renesas_i3c_resume_noirq’:
../drivers/i3c/master/renesas-i3c.c:65:17: error: expected identifier before 
numeric constant
    65 | #define EXTBR   0x78
       |                 ^~~~
../drivers/i3c/master/renesas-i3c.c:1451:40: note: in expansion of macro ‘EXTBR’
  1451 |  renesas_writel(i3c->regs, EXTBR, i3c->EXTBR);
       |                                        ^~~~~

The register contains both i3c and i2c specific fields. I'm not sure using 
i2c_i3c_EXTBR is the best way to go forward for this or just keeping it as is.

-- 
Thank you,
Claudiu


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

* Re: [PATCH 03/17] i3c: renesas: Restore STDBR and EXTBR registers on resume
  2026-05-28  8:29       ` Claudiu Beznea
@ 2026-05-28 19:13         ` Frank Li
  -1 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-28 19:13 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Thu, May 28, 2026 at 11:29:46AM +0300, Claudiu Beznea wrote:
> Hi, Frank,
>
> On 5/22/26 22:10, Frank Li wrote:
> > On Fri, May 22, 2026 at 01:18:01PM +0300, Claudiu Beznea wrote:
> > > From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> > >
> > > The Renesas RZ/G3S supports a power saving state where power to the most
> > > SoC componentes (including I3C) is lost.
> > >
> > > The STDBR and EXTBR are configured in initialization phase though the
> > > struct i3c_master_controller_ops::bus_init. Set them on resume function
> > > as well to keep the same state of the controller after a suspend with
> > > power loss and a similar initialization sequence as in bus_init.
> > >
> > > Fixes: e7218986319b ("i3c: renesas: Add suspend/resume support")
> > > Cc: stable@vger.kernel.org
> > > Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> > > ---
> > >   drivers/i3c/master/renesas-i3c.c | 10 ++++++----
> > >   1 file changed, 6 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> > > index 1917549cf6d5..6c23f956ad2a 100644
> > > --- a/drivers/i3c/master/renesas-i3c.c
> > > +++ b/drivers/i3c/master/renesas-i3c.c
> > > @@ -260,6 +260,7 @@ struct renesas_i3c {
> > >   	u32 dyn_addr;
> > >   	u32 i2c_STDBR;
> > >   	u32 i3c_STDBR;
> > > +	u32 extbr;
> >
> > can you keep consisent with above 2 register, use upcase EXTBR,
>
> Using upper case for this will mislead the compiler. There is already a
> macro defined for EXTBR:

That's fine.

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>
> #define EXTBR                   0x78
>
> Defining this member as:
>
> u32 EXTBR;
>
> will make the compiler try to replace the EXTBR in "i3c->EXTBR" at
> preprocessing time:
>
>   CC [M]  drivers/i3c/master/renesas-i3c.o
> ../drivers/i3c/master/renesas-i3c.c:65:17: error: expected identifier or ‘(’
> before numeric constant
>    65 | #define EXTBR   0x78
>       |                 ^~~~
> ../drivers/i3c/master/renesas-i3c.c:263:6: note: in expansion of macro ‘EXTBR’
>   263 |  u32 EXTBR;
>       |      ^~~~~
> ../drivers/i3c/master/renesas-i3c.c: In function ‘renesas_i3c_bus_init’:
> ../drivers/i3c/master/renesas-i3c.c:65:17: error: expected identifier before
> numeric constant
>    65 | #define EXTBR   0x78
>       |                 ^~~~
> ../drivers/i3c/master/renesas-i3c.c:611:7: note: in expansion of macro ‘EXTBR’
>   611 |  i3c->EXTBR = EXTBR_EBRLO(od_low_ticks) | EXTBR_EBRHO(od_high_ticks) |
>       |       ^~~~~
> ../drivers/i3c/master/renesas-i3c.c:65:17: error: expected identifier before
> numeric constant
>    65 | #define EXTBR   0x78
>       |                 ^~~~
> ../drivers/i3c/master/renesas-i3c.c:613:40: note: in expansion of macro ‘EXTBR’
>   613 |  renesas_writel(i3c->regs, EXTBR, i3c->EXTBR);
>       |                                        ^~~~~
> ../drivers/i3c/master/renesas-i3c.c: In function ‘renesas_i3c_resume_noirq’:
> ../drivers/i3c/master/renesas-i3c.c:65:17: error: expected identifier before
> numeric constant
>    65 | #define EXTBR   0x78
>       |                 ^~~~
> ../drivers/i3c/master/renesas-i3c.c:1451:40: note: in expansion of macro ‘EXTBR’
>  1451 |  renesas_writel(i3c->regs, EXTBR, i3c->EXTBR);
>       |                                        ^~~~~
>
> The register contains both i3c and i2c specific fields. I'm not sure using
> i2c_i3c_EXTBR is the best way to go forward for this or just keeping it as
> is.
>
> --
> Thank you,
> Claudiu
>

-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 03/17] i3c: renesas: Restore STDBR and EXTBR registers on resume
@ 2026-05-28 19:13         ` Frank Li
  0 siblings, 0 replies; 86+ messages in thread
From: Frank Li @ 2026-05-28 19:13 UTC (permalink / raw)
  To: Claudiu Beznea
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	claudiu.beznea, linux-i3c, linux-kernel, linux-renesas-soc,
	Claudiu Beznea, stable

On Thu, May 28, 2026 at 11:29:46AM +0300, Claudiu Beznea wrote:
> Hi, Frank,
>
> On 5/22/26 22:10, Frank Li wrote:
> > On Fri, May 22, 2026 at 01:18:01PM +0300, Claudiu Beznea wrote:
> > > From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> > >
> > > The Renesas RZ/G3S supports a power saving state where power to the most
> > > SoC componentes (including I3C) is lost.
> > >
> > > The STDBR and EXTBR are configured in initialization phase though the
> > > struct i3c_master_controller_ops::bus_init. Set them on resume function
> > > as well to keep the same state of the controller after a suspend with
> > > power loss and a similar initialization sequence as in bus_init.
> > >
> > > Fixes: e7218986319b ("i3c: renesas: Add suspend/resume support")
> > > Cc: stable@vger.kernel.org
> > > Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> > > ---
> > >   drivers/i3c/master/renesas-i3c.c | 10 ++++++----
> > >   1 file changed, 6 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> > > index 1917549cf6d5..6c23f956ad2a 100644
> > > --- a/drivers/i3c/master/renesas-i3c.c
> > > +++ b/drivers/i3c/master/renesas-i3c.c
> > > @@ -260,6 +260,7 @@ struct renesas_i3c {
> > >   	u32 dyn_addr;
> > >   	u32 i2c_STDBR;
> > >   	u32 i3c_STDBR;
> > > +	u32 extbr;
> >
> > can you keep consisent with above 2 register, use upcase EXTBR,
>
> Using upper case for this will mislead the compiler. There is already a
> macro defined for EXTBR:

That's fine.

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>
> #define EXTBR                   0x78
>
> Defining this member as:
>
> u32 EXTBR;
>
> will make the compiler try to replace the EXTBR in "i3c->EXTBR" at
> preprocessing time:
>
>   CC [M]  drivers/i3c/master/renesas-i3c.o
> ../drivers/i3c/master/renesas-i3c.c:65:17: error: expected identifier or ‘(’
> before numeric constant
>    65 | #define EXTBR   0x78
>       |                 ^~~~
> ../drivers/i3c/master/renesas-i3c.c:263:6: note: in expansion of macro ‘EXTBR’
>   263 |  u32 EXTBR;
>       |      ^~~~~
> ../drivers/i3c/master/renesas-i3c.c: In function ‘renesas_i3c_bus_init’:
> ../drivers/i3c/master/renesas-i3c.c:65:17: error: expected identifier before
> numeric constant
>    65 | #define EXTBR   0x78
>       |                 ^~~~
> ../drivers/i3c/master/renesas-i3c.c:611:7: note: in expansion of macro ‘EXTBR’
>   611 |  i3c->EXTBR = EXTBR_EBRLO(od_low_ticks) | EXTBR_EBRHO(od_high_ticks) |
>       |       ^~~~~
> ../drivers/i3c/master/renesas-i3c.c:65:17: error: expected identifier before
> numeric constant
>    65 | #define EXTBR   0x78
>       |                 ^~~~
> ../drivers/i3c/master/renesas-i3c.c:613:40: note: in expansion of macro ‘EXTBR’
>   613 |  renesas_writel(i3c->regs, EXTBR, i3c->EXTBR);
>       |                                        ^~~~~
> ../drivers/i3c/master/renesas-i3c.c: In function ‘renesas_i3c_resume_noirq’:
> ../drivers/i3c/master/renesas-i3c.c:65:17: error: expected identifier before
> numeric constant
>    65 | #define EXTBR   0x78
>       |                 ^~~~
> ../drivers/i3c/master/renesas-i3c.c:1451:40: note: in expansion of macro ‘EXTBR’
>  1451 |  renesas_writel(i3c->regs, EXTBR, i3c->EXTBR);
>       |                                        ^~~~~
>
> The register contains both i3c and i2c specific fields. I'm not sure using
> i2c_i3c_EXTBR is the best way to go forward for this or just keeping it as
> is.
>
> --
> Thank you,
> Claudiu
>

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

* Re: [PATCH 17/17] i3c: renesas: Add runtime PM support
  2026-05-23 10:23       ` Claudiu Beznea
@ 2026-06-02 11:49         ` Claudiu Beznea
  -1 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-06-02 11:49 UTC (permalink / raw)
  To: Claudiu Beznea, Frank Li
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	linux-i3c, linux-kernel, linux-renesas-soc, Claudiu Beznea,
	geert+renesas@glider.be



On 5/23/26 13:23, Claudiu Beznea wrote:
>>> +    i3c->dev = &pdev->dev;
>>> +    pm_runtime_set_autosuspend_delay(&pdev->dev, 300);
>>> +    pm_runtime_use_autosuspend(&pdev->dev);
>>> +    ret = devm_add_action_or_reset(&pdev->dev, 
>>> renesas_i3c_dont_use_autosuspend,
>>> +                       i3c->dev);
>>
>> do you cleanup resource in renesas_i3c_dont_use_autosuspend(), look likes
>> needn't it.
> 
> According to documentation at [1] this is necessary.
> 
> [1] https://elixir.bootlin.com/linux/v7.1-rc4/source/Documentation/power/ 
> runtime_pm.rst#L616

Actually, the cleanup helper of devm_pm_runtime_enable() takes care of this, 
thus I'll be removing the renesas_i3c_dont_use_autosuspend().

Thank you,
Claudiu


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

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

* Re: [PATCH 17/17] i3c: renesas: Add runtime PM support
@ 2026-06-02 11:49         ` Claudiu Beznea
  0 siblings, 0 replies; 86+ messages in thread
From: Claudiu Beznea @ 2026-06-02 11:49 UTC (permalink / raw)
  To: Claudiu Beznea, Frank Li
  Cc: wsa+renesas, tommaso.merciai.xr, alexandre.belloni, p.zabel,
	linux-i3c, linux-kernel, linux-renesas-soc, Claudiu Beznea,
	geert+renesas@glider.be



On 5/23/26 13:23, Claudiu Beznea wrote:
>>> +    i3c->dev = &pdev->dev;
>>> +    pm_runtime_set_autosuspend_delay(&pdev->dev, 300);
>>> +    pm_runtime_use_autosuspend(&pdev->dev);
>>> +    ret = devm_add_action_or_reset(&pdev->dev, 
>>> renesas_i3c_dont_use_autosuspend,
>>> +                       i3c->dev);
>>
>> do you cleanup resource in renesas_i3c_dont_use_autosuspend(), look likes
>> needn't it.
> 
> According to documentation at [1] this is necessary.
> 
> [1] https://elixir.bootlin.com/linux/v7.1-rc4/source/Documentation/power/ 
> runtime_pm.rst#L616

Actually, the cleanup helper of devm_pm_runtime_enable() takes care of this, 
thus I'll be removing the renesas_i3c_dont_use_autosuspend().

Thank you,
Claudiu


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

end of thread, other threads:[~2026-06-02 11:49 UTC | newest]

Thread overview: 86+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-22 10:17 [PATCH 00/17] i3c: renesas: Suspend to RAM with power loss and runtime PM Claudiu Beznea
2026-05-22 10:17 ` Claudiu Beznea
2026-05-22 10:17 ` [PATCH 01/17] i3c: renesas: Check that the transfer is valid before accessing it Claudiu Beznea
2026-05-22 10:17   ` Claudiu Beznea
2026-05-22 19:02   ` Frank Li
2026-05-22 19:02     ` Frank Li
2026-05-22 10:18 ` [PATCH 02/17] i3c: renesas: Use the divider 128 Claudiu Beznea
2026-05-22 10:18   ` Claudiu Beznea
2026-05-22 19:06   ` Frank Li
2026-05-22 19:06     ` Frank Li
2026-05-23  8:14     ` Claudiu Beznea
2026-05-23  8:14       ` Claudiu Beznea
2026-05-22 10:18 ` [PATCH 03/17] i3c: renesas: Restore STDBR and EXTBR registers on resume Claudiu Beznea
2026-05-22 10:18   ` Claudiu Beznea
2026-05-22 19:10   ` Frank Li
2026-05-22 19:10     ` Frank Li
2026-05-28  8:29     ` Claudiu Beznea
2026-05-28  8:29       ` Claudiu Beznea
2026-05-28 19:13       ` Frank Li
2026-05-28 19:13         ` Frank Li
2026-05-22 10:18 ` [PATCH 04/17] i3c: renesas: Follow the reset deassert order used in probe Claudiu Beznea
2026-05-22 10:18   ` Claudiu Beznea
2026-05-22 19:11   ` Frank Li
2026-05-22 19:11     ` Frank Li
2026-05-22 10:18 ` [PATCH 05/17] i3c: renesas: Fix re-attach Claudiu Beznea
2026-05-22 10:18   ` Claudiu Beznea
2026-05-22 19:13   ` Frank Li
2026-05-22 19:13     ` Frank Li
2026-05-22 10:18 ` [PATCH 06/17] i3c: renesas: Reset the controller on resume Claudiu Beznea
2026-05-22 10:18   ` Claudiu Beznea
2026-05-22 19:15   ` Frank Li
2026-05-22 19:15     ` Frank Li
2026-05-23 10:24     ` Claudiu Beznea
2026-05-23 10:24       ` Claudiu Beznea
2026-05-22 10:18 ` [PATCH 07/17] i3c: renesas: Perform Dynamic Address Assignment " Claudiu Beznea
2026-05-22 10:18   ` Claudiu Beznea
2026-05-22 19:16   ` Frank Li
2026-05-22 19:16     ` Frank Li
2026-05-23 10:26     ` Claudiu Beznea
2026-05-23 10:26       ` Claudiu Beznea
2026-05-22 10:18 ` [PATCH 08/17] i3c: renesas: Clean DATBAS register on detach Claudiu Beznea
2026-05-22 10:18   ` Claudiu Beznea
2026-05-22 19:17   ` Frank Li
2026-05-22 19:17     ` Frank Li
2026-05-22 10:18 ` [PATCH 09/17] i3c: renesas: Use reset_control_bulk_{assert, deassert}() Claudiu Beznea
2026-05-22 10:18   ` Claudiu Beznea
2026-05-22 19:19   ` Frank Li
2026-05-22 19:19     ` Frank Li
2026-05-23 10:26     ` Claudiu Beznea
2026-05-23 10:26       ` Claudiu Beznea
2026-05-22 10:18 ` [PATCH 10/17] i3c: renesas: Return immediately if there is nothing to transfer Claudiu Beznea
2026-05-22 10:18   ` Claudiu Beznea
2026-05-22 19:20   ` Frank Li
2026-05-22 19:20     ` Frank Li
2026-05-22 10:18 ` [PATCH 11/17] i3c: renesas: Follow a unified pattern for transfer and command initialization Claudiu Beznea
2026-05-22 10:18   ` Claudiu Beznea
2026-05-22 19:21   ` Frank Li
2026-05-22 19:21     ` Frank Li
2026-05-22 10:18 ` [PATCH 12/17] i3c: renesas: Drop the explicit memset() call Claudiu Beznea
2026-05-22 10:18   ` Claudiu Beznea
2026-05-22 19:43   ` Frank Li
2026-05-22 19:43     ` Frank Li
2026-05-22 10:18 ` [PATCH 13/17] i3c: renesas: Update HW registers after SW computations are done Claudiu Beznea
2026-05-22 10:18   ` Claudiu Beznea
2026-05-22 19:48   ` Frank Li
2026-05-22 19:48     ` Frank Li
2026-05-22 10:18 ` [PATCH 14/17] i3c: renesas: Organize structures to avoid unnecessary padding Claudiu Beznea
2026-05-22 10:18   ` Claudiu Beznea
2026-05-22 19:50   ` Frank Li
2026-05-22 19:50     ` Frank Li
2026-05-22 10:18 ` [PATCH 15/17] i3c: renesas: Use the "dev_name:irq_name" format for the interrupt name Claudiu Beznea
2026-05-22 10:18   ` Claudiu Beznea
2026-05-22 19:51   ` Frank Li
2026-05-22 19:51     ` Frank Li
2026-05-22 10:18 ` [PATCH 16/17] i3c: renesas: Drop unnecessary tab Claudiu Beznea
2026-05-22 10:18   ` Claudiu Beznea
2026-05-22 19:52   ` Frank Li
2026-05-22 19:52     ` Frank Li
2026-05-22 10:18 ` [PATCH 17/17] i3c: renesas: Add runtime PM support Claudiu Beznea
2026-05-22 10:18   ` Claudiu Beznea
2026-05-22 20:01   ` Frank Li
2026-05-22 20:01     ` Frank Li
2026-05-23 10:23     ` Claudiu Beznea
2026-05-23 10:23       ` Claudiu Beznea
2026-06-02 11:49       ` Claudiu Beznea
2026-06-02 11:49         ` Claudiu Beznea

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.