* [PATCH 0/7] Renesas: dmaengine and ASoC fixes
@ 2026-01-26 10:31 Claudiu
2026-01-26 10:31 ` [PATCH 1/7] dmaengine: sh: rz-dmac: Add enable status bit Claudiu
` (6 more replies)
0 siblings, 7 replies; 31+ messages in thread
From: Claudiu @ 2026-01-26 10:31 UTC (permalink / raw)
To: vkoul, biju.das.jz, prabhakar.mahadev-lad.rj, lgirdwood, broonie,
perex, tiwai, p.zabel, geert+renesas, fabrizio.castro.jz
Cc: claudiu.beznea, dmaengine, linux-kernel, linux-sound,
linux-renesas-soc, Claudiu Beznea
From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Hi,
This series addresses issues identified in the DMA engine and RZ SSI
drivers.
As described in the patch "dmaengine: sh: rz-dmac: Set the Link End (LE)
bit on the last descriptor", stress testing on the Renesas RZ/G2L SoC
showed that starting all available DMA channels could cause the system
to stall after several hours of operation. This issue was resolved by
setting the Link End bit on the last descriptor of a DMA transfer.
However, after applying that fix, the SSI audio driver began to suffer
from frequent overruns and underruns. This was caused by the way the SSI
driver emulated cyclic DMA transfers: at the start of playback/capture
it initially enqueued 4 DMA descriptors as single SG transfers, and upon
completion of each descriptor, a new one was enqueued. Since there was
no indication to the DMA hardware where the descriptor list ended
(though the LE bit), the DMA engine continued transferring until the
audio stream was stopped. From time to time, audio signal spikes were
observed in the recorded file with this approach.
To address these issue, cyclic DMA support was added to the DMA engine
driver, and the SSI audio driver was reworked to use this support via
the generic PCM dmaengine APIs.
Due to the behavior described above, no Fixes tags were added to the
patches in this series, and all patches should be merged through the
same tree.
Please note that the dmaengine patches were based on top of the
following series:
- Add DMA support for RZ/T2H and RZ/N2H (https://lore.kernel.org/all/20260105114445.878262-1-cosmin-gabriel.tanislav.xa@renesas.com/)
- Add tx_status and pause/resume support (https://lore.kernel.org/all/20260120133330.3738850-1-claudiu.beznea.uj@bp.renesas.com/)
Please note that the ASoC patch is based on series:
- ASoC: renesas: rz-ssi: Cleanups (https://lore.kernel.org/all/20260119195252.3362486-1-claudiu.beznea.uj@bp.renesas.com/)
Thank you,
Claudiu
Claudiu Beznea (7):
dmaengine: sh: rz-dmac: Add enable status bit
dmaengine: sh: rz-dmac: Add pause status bit
dmaengine: sh: rz-dmac: Drop the update of CHCTRL_SETEN in
channel->chctrl APIs
dmaengine: sh: rz-dmac: Add cyclic DMA support
dmaengine: sh: rz-dmac: Add suspend to RAM support
ASoC: renesas: rz-ssi: Use generic PCM dmaengine APIs
dmaengine: sh: rz-dmac: Set the Link End (LE) bit on the last
descriptor
drivers/dma/sh/rz-dmac.c | 401 ++++++++++++++++++++++++++++++++++---
sound/soc/renesas/rz-ssi.c | 355 +++++++-------------------------
2 files changed, 452 insertions(+), 304 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 1/7] dmaengine: sh: rz-dmac: Add enable status bit
2026-01-26 10:31 [PATCH 0/7] Renesas: dmaengine and ASoC fixes Claudiu
@ 2026-01-26 10:31 ` Claudiu
2026-01-26 10:31 ` [PATCH 2/7] dmaengine: sh: rz-dmac: Add pause " Claudiu
` (5 subsequent siblings)
6 siblings, 0 replies; 31+ messages in thread
From: Claudiu @ 2026-01-26 10:31 UTC (permalink / raw)
To: vkoul, biju.das.jz, prabhakar.mahadev-lad.rj, lgirdwood, broonie,
perex, tiwai, p.zabel, geert+renesas, fabrizio.castro.jz
Cc: claudiu.beznea, dmaengine, linux-kernel, linux-sound,
linux-renesas-soc, Claudiu Beznea
From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Add a status bitmask to struct rz_dmac_chan. This is currently stores only
the enable status of the DMA channel and it is a preparatory commit for
adding cyclic DMA support.
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
drivers/dma/sh/rz-dmac.c | 24 +++++++++++++++++++++---
1 file changed, 21 insertions(+), 3 deletions(-)
diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
index 35124043ae02..95ed357f2b74 100644
--- a/drivers/dma/sh/rz-dmac.c
+++ b/drivers/dma/sh/rz-dmac.c
@@ -62,6 +62,14 @@ struct rz_dmac_desc {
#define to_rz_dmac_desc(d) container_of(d, struct rz_dmac_desc, vd)
+/**
+ * enum rz_dmac_chan_status: RZ DMAC channel status
+ * @RZ_DMAC_CHAN_STATUS_ENABLED: Channel is enabled
+ */
+enum rz_dmac_chan_status {
+ RZ_DMAC_CHAN_STATUS_ENABLED,
+};
+
struct rz_dmac_chan {
struct virt_dma_chan vc;
void __iomem *ch_base;
@@ -73,6 +81,8 @@ struct rz_dmac_chan {
dma_addr_t src_per_address;
dma_addr_t dst_per_address;
+ unsigned long status;
+
u32 chcfg;
u32 chctrl;
int mid_rid;
@@ -302,6 +312,8 @@ static void rz_dmac_enable_hw(struct rz_dmac_chan *channel)
rz_dmac_ch_writel(channel, channel->chcfg, CHCFG, 1);
rz_dmac_ch_writel(channel, CHCTRL_SWRST, CHCTRL, 1);
rz_dmac_ch_writel(channel, chctrl, CHCTRL, 1);
+
+ channel->status |= BIT(RZ_DMAC_CHAN_STATUS_ENABLED);
}
}
@@ -313,6 +325,8 @@ static void rz_dmac_disable_hw(struct rz_dmac_chan *channel)
dev_dbg(dmac->dev, "%s channel %d\n", __func__, channel->index);
rz_dmac_ch_writel(channel, CHCTRL_DEFAULT, CHCTRL, 1);
+
+ channel->status &= ~BIT(RZ_DMAC_CHAN_STATUS_ENABLED);
}
static void rz_dmac_set_dmars_register(struct rz_dmac *dmac, int nr, u32 dmars)
@@ -578,6 +592,9 @@ static int rz_dmac_terminate_all(struct dma_chan *chan)
list_splice_tail_init(&channel->ld_active, &channel->ld_free);
list_splice_tail_init(&channel->ld_queue, &channel->ld_free);
vchan_get_all_descriptors(&channel->vc, &head);
+
+ channel->status = 0;
+
spin_unlock_irqrestore(&channel->vc.lock, flags);
vchan_dma_desc_free_list(&channel->vc, &head);
@@ -841,8 +858,7 @@ static int rz_dmac_device_pause(struct dma_chan *chan)
guard(spinlock_irqsave)(&channel->vc.lock);
- val = rz_dmac_ch_readl(channel, CHSTAT, 1);
- if (!(val & CHSTAT_EN))
+ if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_ENABLED)))
return 0;
rz_dmac_ch_writel(channel, CHCTRL_SETSUS, CHCTRL, 1);
@@ -882,8 +898,10 @@ static void rz_dmac_irq_handle_channel(struct rz_dmac_chan *channel)
dev_err(dmac->dev, "DMAC err CHSTAT_%d = %08X\n",
channel->index, chstat);
- scoped_guard(spinlock_irqsave, &channel->vc.lock)
+ scoped_guard(spinlock_irqsave, &channel->vc.lock) {
rz_dmac_ch_writel(channel, CHCTRL_DEFAULT, CHCTRL, 1);
+ channel->status &= ~BIT(RZ_DMAC_CHAN_STATUS_ENABLED);
+ }
return;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 2/7] dmaengine: sh: rz-dmac: Add pause status bit
2026-01-26 10:31 [PATCH 0/7] Renesas: dmaengine and ASoC fixes Claudiu
2026-01-26 10:31 ` [PATCH 1/7] dmaengine: sh: rz-dmac: Add enable status bit Claudiu
@ 2026-01-26 10:31 ` Claudiu
2026-01-26 10:31 ` [PATCH 3/7] dmaengine: sh: rz-dmac: Drop the update of CHCTRL_SETEN in channel->chctrl APIs Claudiu
` (4 subsequent siblings)
6 siblings, 0 replies; 31+ messages in thread
From: Claudiu @ 2026-01-26 10:31 UTC (permalink / raw)
To: vkoul, biju.das.jz, prabhakar.mahadev-lad.rj, lgirdwood, broonie,
perex, tiwai, p.zabel, geert+renesas, fabrizio.castro.jz
Cc: claudiu.beznea, dmaengine, linux-kernel, linux-sound,
linux-renesas-soc, Claudiu Beznea
From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Add the RZ_DMAC_CHAN_STATUS_PAUSED status bit index. This is needed to
implement suspend to RAM support for cyclic DMA channels, which will be
added in subsequent commits.
The pause and resume implementations are updated to reuse the code added
for suspend to RAM handling. Since the pause state is now stored in a
per-channel software cache, there is no longer a need to interrogate the
hardware registers in the pause path. Using the software status cache
simplifies the implementation. The resume code was updated to use the
software status cache as well.
This is a preparatory commit for cyclic DMA suspend to RAM support.
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
drivers/dma/sh/rz-dmac.c | 68 ++++++++++++++++++++++++++++++----------
1 file changed, 52 insertions(+), 16 deletions(-)
diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
index 95ed357f2b74..8d8391a5b3a7 100644
--- a/drivers/dma/sh/rz-dmac.c
+++ b/drivers/dma/sh/rz-dmac.c
@@ -18,6 +18,7 @@
#include <linux/irqchip/irq-renesas-rzv2h.h>
#include <linux/irqchip/irq-renesas-rzt2h.h>
#include <linux/list.h>
+#include <linux/lockdep.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_dma.h>
@@ -65,9 +66,11 @@ struct rz_dmac_desc {
/**
* enum rz_dmac_chan_status: RZ DMAC channel status
* @RZ_DMAC_CHAN_STATUS_ENABLED: Channel is enabled
+ * @RZ_DMAC_CHAN_STATUS_PAUSED: Channel is paused though DMA engine callbacks
*/
enum rz_dmac_chan_status {
RZ_DMAC_CHAN_STATUS_ENABLED,
+ RZ_DMAC_CHAN_STATUS_PAUSED,
};
struct rz_dmac_chan {
@@ -833,12 +836,9 @@ static enum dma_status rz_dmac_tx_status(struct dma_chan *chan,
return status;
scoped_guard(spinlock_irqsave, &channel->vc.lock) {
- u32 val;
-
residue = rz_dmac_chan_get_residue(channel, cookie);
- val = rz_dmac_ch_readl(channel, CHSTAT, 1);
- if (val & CHSTAT_SUS)
+ if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED))
status = DMA_PAUSED;
}
@@ -851,35 +851,71 @@ static enum dma_status rz_dmac_tx_status(struct dma_chan *chan,
return status;
}
-static int rz_dmac_device_pause(struct dma_chan *chan)
+static int rz_dmac_device_pause_set(struct rz_dmac_chan *channel,
+ enum rz_dmac_chan_status status)
{
- struct rz_dmac_chan *channel = to_rz_dmac_chan(chan);
u32 val;
+ int ret;
- guard(spinlock_irqsave)(&channel->vc.lock);
+ lockdep_assert_held(&channel->vc.lock);
if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_ENABLED)))
return 0;
rz_dmac_ch_writel(channel, CHCTRL_SETSUS, CHCTRL, 1);
- return read_poll_timeout_atomic(rz_dmac_ch_readl, val,
- (val & CHSTAT_SUS), 1, 1024,
- false, channel, CHSTAT, 1);
+ ret = read_poll_timeout_atomic(rz_dmac_ch_readl, val,
+ (val & CHSTAT_SUS), 1, 1024, false,
+ channel, CHSTAT, 1);
+ if (ret)
+ return ret;
+
+ channel->status |= BIT(status);
+
+ return 0;
}
-static int rz_dmac_device_resume(struct dma_chan *chan)
+static int rz_dmac_device_pause(struct dma_chan *chan)
{
struct rz_dmac_chan *channel = to_rz_dmac_chan(chan);
- u32 val;
guard(spinlock_irqsave)(&channel->vc.lock);
- /* Do not check CHSTAT_SUS but rely on HW capabilities. */
+ if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED))
+ return 0;
+
+ return rz_dmac_device_pause_set(channel, RZ_DMAC_CHAN_STATUS_PAUSED);
+}
+
+static int rz_dmac_device_resume_set(struct rz_dmac_chan *channel,
+ enum rz_dmac_chan_status status)
+{
+ u32 val;
+ int ret;
+
+ lockdep_assert_held(&channel->vc.lock);
+
+ if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED)))
+ return 0;
rz_dmac_ch_writel(channel, CHCTRL_CLRSUS, CHCTRL, 1);
- return read_poll_timeout_atomic(rz_dmac_ch_readl, val,
- !(val & CHSTAT_SUS), 1, 1024,
- false, channel, CHSTAT, 1);
+ ret = read_poll_timeout_atomic(rz_dmac_ch_readl, val,
+ !(val & CHSTAT_SUS), 1, 1024, false,
+ channel, CHSTAT, 1);
+ if (ret)
+ return ret;
+
+ channel->status &= ~BIT(status);
+
+ return 0;
+}
+
+static int rz_dmac_device_resume(struct dma_chan *chan)
+{
+ struct rz_dmac_chan *channel = to_rz_dmac_chan(chan);
+
+ guard(spinlock_irqsave)(&channel->vc.lock);
+
+ return rz_dmac_device_resume_set(channel, RZ_DMAC_CHAN_STATUS_PAUSED);
}
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 3/7] dmaengine: sh: rz-dmac: Drop the update of CHCTRL_SETEN in channel->chctrl APIs
2026-01-26 10:31 [PATCH 0/7] Renesas: dmaengine and ASoC fixes Claudiu
2026-01-26 10:31 ` [PATCH 1/7] dmaengine: sh: rz-dmac: Add enable status bit Claudiu
2026-01-26 10:31 ` [PATCH 2/7] dmaengine: sh: rz-dmac: Add pause " Claudiu
@ 2026-01-26 10:31 ` Claudiu
2026-01-26 10:31 ` [PATCH 4/7] dmaengine: sh: rz-dmac: Add cyclic DMA support Claudiu
` (3 subsequent siblings)
6 siblings, 0 replies; 31+ messages in thread
From: Claudiu @ 2026-01-26 10:31 UTC (permalink / raw)
To: vkoul, biju.das.jz, prabhakar.mahadev-lad.rj, lgirdwood, broonie,
perex, tiwai, p.zabel, geert+renesas, fabrizio.castro.jz
Cc: claudiu.beznea, dmaengine, linux-kernel, linux-sound,
linux-renesas-soc, Claudiu Beznea
From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
The CHCTRL_SETEN bit is explicitly set in rz_dmac_enable_hw(). Updating
struct rz_dmac_chan::chctrl with this bit is unnecessary in the current
code base. Moreover, it conflicts with the configuration sequence used for
cyclic DMA channels during suspend to RAM, which will be introduced in
subsequent commits.
This is a preparatory commit for cyclic DMA suspend to RAM support.
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
drivers/dma/sh/rz-dmac.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
index 8d8391a5b3a7..4bc7ea9566fd 100644
--- a/drivers/dma/sh/rz-dmac.c
+++ b/drivers/dma/sh/rz-dmac.c
@@ -375,7 +375,7 @@ static void rz_dmac_prepare_desc_for_memcpy(struct rz_dmac_chan *channel)
rz_dmac_set_dma_req_no(dmac, channel->index, dmac->info->default_dma_req_no);
channel->chcfg = chcfg;
- channel->chctrl = CHCTRL_STG | CHCTRL_SETEN;
+ channel->chctrl = CHCTRL_STG;
}
static void rz_dmac_prepare_descs_for_slave_sg(struct rz_dmac_chan *channel)
@@ -424,8 +424,6 @@ static void rz_dmac_prepare_descs_for_slave_sg(struct rz_dmac_chan *channel)
channel->lmdesc.tail = lmdesc;
rz_dmac_set_dma_req_no(dmac, channel->index, channel->mid_rid);
-
- channel->chctrl = CHCTRL_SETEN;
}
static int rz_dmac_xfer_desc(struct rz_dmac_chan *chan)
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 4/7] dmaengine: sh: rz-dmac: Add cyclic DMA support
2026-01-26 10:31 [PATCH 0/7] Renesas: dmaengine and ASoC fixes Claudiu
` (2 preceding siblings ...)
2026-01-26 10:31 ` [PATCH 3/7] dmaengine: sh: rz-dmac: Drop the update of CHCTRL_SETEN in channel->chctrl APIs Claudiu
@ 2026-01-26 10:31 ` Claudiu
2026-01-26 10:31 ` [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support Claudiu
` (2 subsequent siblings)
6 siblings, 0 replies; 31+ messages in thread
From: Claudiu @ 2026-01-26 10:31 UTC (permalink / raw)
To: vkoul, biju.das.jz, prabhakar.mahadev-lad.rj, lgirdwood, broonie,
perex, tiwai, p.zabel, geert+renesas, fabrizio.castro.jz
Cc: claudiu.beznea, dmaengine, linux-kernel, linux-sound,
linux-renesas-soc, Claudiu Beznea
From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Add cyclic DMA support to the RZ DMAC driver. A per-channel status bit is
introduced to mark cyclic channels and is set during the DMA prepare
callback. The IRQ handler checks this status bit and calls
vchan_cyclic_callback() accordingly.
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
drivers/dma/sh/rz-dmac.c | 137 +++++++++++++++++++++++++++++++++++++--
1 file changed, 133 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
index 4bc7ea9566fd..ab5f49a0b9f2 100644
--- a/drivers/dma/sh/rz-dmac.c
+++ b/drivers/dma/sh/rz-dmac.c
@@ -35,6 +35,7 @@
enum rz_dmac_prep_type {
RZ_DMAC_DESC_MEMCPY,
RZ_DMAC_DESC_SLAVE_SG,
+ RZ_DMAC_DESC_CYCLIC,
};
struct rz_lmdesc {
@@ -59,6 +60,7 @@ struct rz_dmac_desc {
/* For slave sg */
struct scatterlist *sg;
unsigned int sgcount;
+ u32 start_lmdesc;
};
#define to_rz_dmac_desc(d) container_of(d, struct rz_dmac_desc, vd)
@@ -67,10 +69,12 @@ struct rz_dmac_desc {
* enum rz_dmac_chan_status: RZ DMAC channel status
* @RZ_DMAC_CHAN_STATUS_ENABLED: Channel is enabled
* @RZ_DMAC_CHAN_STATUS_PAUSED: Channel is paused though DMA engine callbacks
+ * @RZ_DMAC_CHAN_STATUS_CYCLIC: Channel is cyclic
*/
enum rz_dmac_chan_status {
RZ_DMAC_CHAN_STATUS_ENABLED,
RZ_DMAC_CHAN_STATUS_PAUSED,
+ RZ_DMAC_CHAN_STATUS_CYCLIC,
};
struct rz_dmac_chan {
@@ -194,6 +198,7 @@ struct rz_dmac {
/* LINK MODE DESCRIPTOR */
#define HEADER_LV BIT(0)
+#define HEADER_WBD BIT(2)
#define RZ_DMAC_MAX_CHAN_DESCRIPTORS 16
#define RZ_DMAC_MAX_CHANNELS 16
@@ -426,6 +431,60 @@ static void rz_dmac_prepare_descs_for_slave_sg(struct rz_dmac_chan *channel)
rz_dmac_set_dma_req_no(dmac, channel->index, channel->mid_rid);
}
+static void rz_dmac_prepare_descs_for_cyclic(struct rz_dmac_chan *channel)
+{
+ struct dma_chan *chan = &channel->vc.chan;
+ struct rz_dmac *dmac = to_rz_dmac(chan->device);
+ struct rz_dmac_desc *d = channel->desc;
+ size_t period_len = d->sgcount;
+ struct rz_lmdesc *lmdesc;
+ size_t buf_len = d->len;
+ size_t periods = buf_len / period_len;
+ u32 start_lmdesc;
+
+ lockdep_assert_held(&channel->vc.lock);
+
+ channel->chcfg |= CHCFG_SEL(channel->index) | CHCFG_DMS;
+
+ if (d->direction == DMA_DEV_TO_MEM) {
+ channel->chcfg |= CHCFG_SAD;
+ channel->chcfg &= ~CHCFG_REQD;
+ } else {
+ channel->chcfg |= CHCFG_DAD | CHCFG_REQD;
+ }
+
+ lmdesc = channel->lmdesc.tail;
+ start_lmdesc = channel->lmdesc.base_dma +
+ (sizeof(struct rz_lmdesc) * (lmdesc - channel->lmdesc.base));
+ d->start_lmdesc = start_lmdesc;
+
+ for (size_t i = 0; i < periods; i++) {
+ if (d->direction == DMA_DEV_TO_MEM) {
+ lmdesc->sa = d->src;
+ lmdesc->da = d->dest + (i * period_len);
+ } else {
+ lmdesc->sa = d->src + (i * period_len);
+ lmdesc->da = d->dest;
+ }
+
+ lmdesc->tb = period_len;
+ lmdesc->chitvl = 0;
+ lmdesc->chext = 0;
+ lmdesc->chcfg = channel->chcfg;
+ lmdesc->header = HEADER_LV | HEADER_WBD;
+
+ if (i == periods - 1)
+ lmdesc->nxla = start_lmdesc;
+
+ if (++lmdesc >= (channel->lmdesc.base + DMAC_NR_LMDESC))
+ lmdesc = channel->lmdesc.base;
+ }
+
+ channel->lmdesc.tail = lmdesc;
+
+ rz_dmac_set_dma_req_no(dmac, channel->index, channel->mid_rid);
+}
+
static int rz_dmac_xfer_desc(struct rz_dmac_chan *chan)
{
struct rz_dmac_desc *d = chan->desc;
@@ -446,6 +505,10 @@ static int rz_dmac_xfer_desc(struct rz_dmac_chan *chan)
rz_dmac_prepare_descs_for_slave_sg(chan);
break;
+ case RZ_DMAC_DESC_CYCLIC:
+ rz_dmac_prepare_descs_for_cyclic(chan);
+ break;
+
default:
return -EINVAL;
}
@@ -580,6 +643,52 @@ rz_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
return vchan_tx_prep(&channel->vc, &desc->vd, flags);
}
+static struct dma_async_tx_descriptor *
+rz_dmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
+ size_t buf_len, size_t period_len,
+ enum dma_transfer_direction direction,
+ unsigned long flags)
+{
+ struct rz_dmac_chan *channel = to_rz_dmac_chan(chan);
+ size_t periods = buf_len / period_len;
+ struct rz_dmac_desc *desc;
+
+ if (!is_slave_direction(direction))
+ return NULL;
+
+ if (periods > DMAC_NR_LMDESC)
+ return NULL;
+
+ scoped_guard(spinlock_irqsave, &channel->vc.lock) {
+ if (list_empty(&channel->ld_free))
+ return NULL;
+
+ if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC))
+ return NULL;
+
+ channel->status |= BIT(RZ_DMAC_CHAN_STATUS_CYCLIC);
+
+ desc = list_first_entry(&channel->ld_free, struct rz_dmac_desc, node);
+
+ desc->type = RZ_DMAC_DESC_CYCLIC;
+ desc->sgcount = period_len;
+ desc->len = buf_len;
+ desc->direction = direction;
+
+ if (direction == DMA_DEV_TO_MEM) {
+ desc->src = channel->src_per_address;
+ desc->dest = buf_addr;
+ } else {
+ desc->src = buf_addr;
+ desc->dest = channel->dst_per_address;
+ }
+
+ list_move_tail(channel->ld_free.next, &channel->ld_queue);
+ }
+
+ return vchan_tx_prep(&channel->vc, &desc->vd, flags);
+}
+
static int rz_dmac_terminate_all(struct dma_chan *chan)
{
struct rz_dmac_chan *channel = to_rz_dmac_chan(chan);
@@ -731,9 +840,18 @@ static u32 rz_dmac_calculate_residue_bytes_in_vd(struct rz_dmac_chan *channel)
}
/* Calculate residue from next lmdesc to end of virtual desc */
- while (lmdesc->chcfg & CHCFG_DEM) {
- residue += lmdesc->tb;
- lmdesc = rz_dmac_get_next_lmdesc(channel->lmdesc.base, lmdesc);
+ if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)) {
+ struct rz_dmac_desc *desc = channel->desc;
+
+ while (lmdesc->nxla != desc->start_lmdesc) {
+ residue += lmdesc->tb;
+ lmdesc = rz_dmac_get_next_lmdesc(channel->lmdesc.base, lmdesc);
+ }
+ } else {
+ while (lmdesc->chcfg & CHCFG_DEM) {
+ residue += lmdesc->tb;
+ lmdesc = rz_dmac_get_next_lmdesc(channel->lmdesc.base, lmdesc);
+ }
}
dev_dbg(dmac->dev, "%s: VD residue is %u\n", __func__, residue);
@@ -972,7 +1090,15 @@ static irqreturn_t rz_dmac_irq_handler_thread(int irq, void *dev_id)
}
desc = list_first_entry(&channel->ld_active, struct rz_dmac_desc, node);
- vchan_cookie_complete(&desc->vd);
+
+ if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)) {
+ desc = channel->desc;
+ vchan_cyclic_callback(&desc->vd);
+ goto out;
+ } else {
+ vchan_cookie_complete(&desc->vd);
+ }
+
list_move_tail(channel->ld_active.next, &channel->ld_free);
if (!list_empty(&channel->ld_queue)) {
desc = list_first_entry(&channel->ld_queue, struct rz_dmac_desc,
@@ -1239,6 +1365,8 @@ static int rz_dmac_probe(struct platform_device *pdev)
engine = &dmac->engine;
dma_cap_set(DMA_SLAVE, engine->cap_mask);
dma_cap_set(DMA_MEMCPY, engine->cap_mask);
+ dma_cap_set(DMA_CYCLIC, engine->cap_mask);
+ engine->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
engine->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_0_7_COMMON_BASE + DCTRL);
rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_8_15_COMMON_BASE + DCTRL);
@@ -1250,6 +1378,7 @@ static int rz_dmac_probe(struct platform_device *pdev)
engine->device_tx_status = rz_dmac_tx_status;
engine->device_prep_slave_sg = rz_dmac_prep_slave_sg;
engine->device_prep_dma_memcpy = rz_dmac_prep_dma_memcpy;
+ engine->device_prep_dma_cyclic = rz_dmac_prep_dma_cyclic;
engine->device_config = rz_dmac_config;
engine->device_terminate_all = rz_dmac_terminate_all;
engine->device_issue_pending = rz_dmac_issue_pending;
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-01-26 10:31 [PATCH 0/7] Renesas: dmaengine and ASoC fixes Claudiu
` (3 preceding siblings ...)
2026-01-26 10:31 ` [PATCH 4/7] dmaengine: sh: rz-dmac: Add cyclic DMA support Claudiu
@ 2026-01-26 10:31 ` Claudiu
2026-01-26 11:03 ` Biju Das
2026-03-12 12:26 ` Tommaso Merciai
2026-01-26 10:31 ` [PATCH 6/7] ASoC: renesas: rz-ssi: Use generic PCM dmaengine APIs Claudiu
2026-01-26 10:31 ` [PATCH 7/7] dmaengine: sh: rz-dmac: Set the Link End (LE) bit on the last descriptor Claudiu
6 siblings, 2 replies; 31+ messages in thread
From: Claudiu @ 2026-01-26 10:31 UTC (permalink / raw)
To: vkoul, biju.das.jz, prabhakar.mahadev-lad.rj, lgirdwood, broonie,
perex, tiwai, p.zabel, geert+renesas, fabrizio.castro.jz
Cc: claudiu.beznea, dmaengine, linux-kernel, linux-sound,
linux-renesas-soc, Claudiu Beznea
From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
The Renesas RZ/G3S SoC supports a power saving mode in which power to most
SoC components is turned off, including the DMA IP. Add suspend to RAM
support to save and restore the DMA IP registers.
Cyclic DMA channels require special handling. Since they can be paused and
resumed during system suspend and resume, the driver restores additional
registers for these channels during the resume phase. If a channel was not
explicitly paused during suspend, the driver ensures that it is paused and
resumed as part of the system suspend/resume flow. This might be the
case of a serial device being used with no_console_suspend.
For non-cyclic channels, the dev_pm_ops::prepare callback waits for all
ongoing transfers to complete before allowing suspend-to-RAM to proceed.
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
drivers/dma/sh/rz-dmac.c | 183 +++++++++++++++++++++++++++++++++++++--
1 file changed, 175 insertions(+), 8 deletions(-)
diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
index ab5f49a0b9f2..8f3e2719e639 100644
--- a/drivers/dma/sh/rz-dmac.c
+++ b/drivers/dma/sh/rz-dmac.c
@@ -69,11 +69,15 @@ struct rz_dmac_desc {
* enum rz_dmac_chan_status: RZ DMAC channel status
* @RZ_DMAC_CHAN_STATUS_ENABLED: Channel is enabled
* @RZ_DMAC_CHAN_STATUS_PAUSED: Channel is paused though DMA engine callbacks
+ * @RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL: Channel is paused through driver internal logic
+ * @RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED: Channel was prepared for system suspend
* @RZ_DMAC_CHAN_STATUS_CYCLIC: Channel is cyclic
*/
enum rz_dmac_chan_status {
RZ_DMAC_CHAN_STATUS_ENABLED,
RZ_DMAC_CHAN_STATUS_PAUSED,
+ RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL,
+ RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED,
RZ_DMAC_CHAN_STATUS_CYCLIC,
};
@@ -94,6 +98,10 @@ struct rz_dmac_chan {
u32 chctrl;
int mid_rid;
+ struct {
+ u32 nxla;
+ } pm_state;
+
struct list_head ld_free;
struct list_head ld_queue;
struct list_head ld_active;
@@ -1002,10 +1010,17 @@ static int rz_dmac_device_pause(struct dma_chan *chan)
return rz_dmac_device_pause_set(channel, RZ_DMAC_CHAN_STATUS_PAUSED);
}
+static int rz_dmac_device_pause_internal(struct rz_dmac_chan *channel)
+{
+ lockdep_assert_held(&channel->vc.lock);
+
+ return rz_dmac_device_pause_set(channel, RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL);
+}
+
static int rz_dmac_device_resume_set(struct rz_dmac_chan *channel,
enum rz_dmac_chan_status status)
{
- u32 val;
+ u32 val, chctrl;
int ret;
lockdep_assert_held(&channel->vc.lock);
@@ -1013,14 +1028,33 @@ static int rz_dmac_device_resume_set(struct rz_dmac_chan *channel,
if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED)))
return 0;
- rz_dmac_ch_writel(channel, CHCTRL_CLRSUS, CHCTRL, 1);
- ret = read_poll_timeout_atomic(rz_dmac_ch_readl, val,
- !(val & CHSTAT_SUS), 1, 1024, false,
- channel, CHSTAT, 1);
- if (ret)
- return ret;
+ if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED)) {
+ /*
+ * We can be after a sleep state with power loss. If power was
+ * lost, the CHSTAT_SUS bit is zero. In this case, we need to
+ * enable the channel directly. Otherwise, just set the CLRSUS
+ * bit.
+ */
+ val = rz_dmac_ch_readl(channel, CHSTAT, 1);
+ if (val & CHSTAT_SUS)
+ chctrl = CHCTRL_CLRSUS;
+ else
+ chctrl = CHCTRL_SETEN;
+ } else {
+ chctrl = CHCTRL_CLRSUS;
+ }
+
+ rz_dmac_ch_writel(channel, chctrl, CHCTRL, 1);
- channel->status &= ~BIT(status);
+ if (chctrl & CHCTRL_CLRSUS) {
+ ret = read_poll_timeout_atomic(rz_dmac_ch_readl, val,
+ !(val & CHSTAT_SUS), 1, 1024, false,
+ channel, CHSTAT, 1);
+ if (ret)
+ return ret;
+ }
+
+ channel->status &= ~(BIT(status) | BIT(RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED));
return 0;
}
@@ -1034,6 +1068,13 @@ static int rz_dmac_device_resume(struct dma_chan *chan)
return rz_dmac_device_resume_set(channel, RZ_DMAC_CHAN_STATUS_PAUSED);
}
+static int rz_dmac_device_resume_internal(struct rz_dmac_chan *channel)
+{
+ lockdep_assert_held(&channel->vc.lock);
+
+ return rz_dmac_device_resume_set(channel, RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL);
+}
+
/*
* -----------------------------------------------------------------------------
* IRQ handling
@@ -1438,6 +1479,131 @@ static void rz_dmac_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
}
+static int rz_dmac_suspend_prepare(struct device *dev)
+{
+ struct rz_dmac *dmac = dev_get_drvdata(dev);
+
+ for (unsigned int i = 0; i < dmac->n_channels; i++) {
+ struct rz_dmac_chan *channel = &dmac->channels[i];
+
+ guard(spinlock_irqsave)(&channel->vc.lock);
+
+ /* Wait for transfer completion, except in cyclic case. */
+ if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_ENABLED) &&
+ !(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)))
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+static void rz_dmac_suspend_recover(struct rz_dmac *dmac)
+{
+ for (unsigned int i = 0; i < dmac->n_channels; i++) {
+ struct rz_dmac_chan *channel = &dmac->channels[i];
+
+ guard(spinlock_irqsave)(&channel->vc.lock);
+
+ if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)))
+ continue;
+
+ if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL)))
+ continue;
+
+ rz_dmac_device_resume_internal(channel);
+ }
+}
+
+static int rz_dmac_suspend(struct device *dev)
+{
+ struct rz_dmac *dmac = dev_get_drvdata(dev);
+ int ret;
+
+ for (unsigned int i = 0; i < dmac->n_channels; i++) {
+ struct rz_dmac_chan *channel = &dmac->channels[i];
+
+ guard(spinlock_irqsave)(&channel->vc.lock);
+
+ if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)))
+ continue;
+
+ if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED))) {
+ ret = rz_dmac_device_pause_internal(channel);
+ if (ret) {
+ dev_err(dev, "Failed to suspend channel %s\n",
+ dma_chan_name(&channel->vc.chan));
+ continue;
+ }
+ }
+
+ channel->pm_state.nxla = rz_dmac_ch_readl(channel, NXLA, 1);
+ channel->status |= BIT(RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED);
+ }
+
+ pm_runtime_put_sync(dmac->dev);
+
+ ret = reset_control_assert(dmac->rstc);
+ if (ret) {
+ pm_runtime_resume_and_get(dmac->dev);
+ rz_dmac_suspend_recover(dmac);
+ }
+
+ return ret;
+}
+
+static int rz_dmac_resume(struct device *dev)
+{
+ struct rz_dmac *dmac = dev_get_drvdata(dev);
+ int ret;
+
+ ret = reset_control_deassert(dmac->rstc);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_resume_and_get(dmac->dev);
+ if (ret) {
+ reset_control_assert(dmac->rstc);
+ return ret;
+ }
+
+ rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_0_7_COMMON_BASE + DCTRL);
+ rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_8_15_COMMON_BASE + DCTRL);
+
+ for (unsigned int i = 0; i < dmac->n_channels; i++) {
+ struct rz_dmac_chan *channel = &dmac->channels[i];
+
+ guard(spinlock_irqsave)(&channel->vc.lock);
+
+ rz_dmac_set_dma_req_no(dmac, channel->index, channel->mid_rid);
+
+ if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC))) {
+ rz_dmac_ch_writel(&dmac->channels[i], CHCTRL_DEFAULT, CHCTRL, 1);
+ continue;
+ }
+
+ rz_dmac_ch_writel(channel, channel->pm_state.nxla, NXLA, 1);
+ rz_dmac_ch_writel(channel, channel->chcfg, CHCFG, 1);
+ rz_dmac_ch_writel(channel, CHCTRL_SWRST, CHCTRL, 1);
+ rz_dmac_ch_writel(channel, channel->chctrl, CHCTRL, 1);
+
+ if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL)) {
+ ret = rz_dmac_device_resume_internal(channel);
+ if (ret) {
+ dev_err(dev, "Failed to resume channel %s\n",
+ dma_chan_name(&channel->vc.chan));
+ continue;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops rz_dmac_pm_ops = {
+ .prepare = rz_dmac_suspend_prepare,
+ SYSTEM_SLEEP_PM_OPS(rz_dmac_suspend, rz_dmac_resume)
+};
+
static const struct rz_dmac_info rz_dmac_v2h_info = {
.icu_register_dma_req = rzv2h_icu_register_dma_req,
.default_dma_req_no = RZV2H_ICU_DMAC_REQ_NO_DEFAULT,
@@ -1464,6 +1630,7 @@ static struct platform_driver rz_dmac_driver = {
.driver = {
.name = "rz-dmac",
.of_match_table = of_rz_dmac_match,
+ .pm = pm_sleep_ptr(&rz_dmac_pm_ops),
},
.probe = rz_dmac_probe,
.remove = rz_dmac_remove,
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 6/7] ASoC: renesas: rz-ssi: Use generic PCM dmaengine APIs
2026-01-26 10:31 [PATCH 0/7] Renesas: dmaengine and ASoC fixes Claudiu
` (4 preceding siblings ...)
2026-01-26 10:31 ` [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support Claudiu
@ 2026-01-26 10:31 ` Claudiu
2026-01-26 14:26 ` Geert Uytterhoeven
2026-01-26 10:31 ` [PATCH 7/7] dmaengine: sh: rz-dmac: Set the Link End (LE) bit on the last descriptor Claudiu
6 siblings, 1 reply; 31+ messages in thread
From: Claudiu @ 2026-01-26 10:31 UTC (permalink / raw)
To: vkoul, biju.das.jz, prabhakar.mahadev-lad.rj, lgirdwood, broonie,
perex, tiwai, p.zabel, geert+renesas, fabrizio.castro.jz
Cc: claudiu.beznea, dmaengine, linux-kernel, linux-sound,
linux-renesas-soc, Claudiu Beznea
From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
On Renesas RZ/G2L and RZ/G3S SoCs (where this was tested), captured audio
files occasionally contained random spikes when viewed with a profiling
tool such as Audacity. These spikes were also audible as popping noises.
Using cyclic DMA resolves this issue. The driver was reworked to use the
existing support provided by the generic PCM dmaengine APIs. In addition
to eliminating the random spikes, the following issues were addressed:
- blank periods at the beginning of recorded files, which occurred
intermittently, are no longer present
- no overruns or underruns were observed when continuously recording
short audio files (e.g. 5 seconds) in a loop
- concurrency issues in the SSI driver when enqueuing DMA requests were
eliminated; previously, DMA requests could be prepared and submitted
both from the DMA completion callback and the interrupt handler, which
led to crashes after several hours of testing
- the SSI driver logic is simplified
- the number of generated interrupts is reduced by approximately 250%
In the SSI platform driver probe function, the following changes were
made:
- the driver-specific DMA configuration was removed in favor of the
generic PCM dmaengine APIs. As a result, explicit cleanup goto labels
are no longer required and the driver remove callback was dropped,
since resource management is now handled via devres helpers
- special handling was added for IP variants operating in half-duplex
mode, where the DMA channel name in the device tree is "rt"; this DMA
channel name is taken into account and passed to the generic PCM
dmaengine configuration data
All code previously responsible for preparing and completing DMA
transfers was removed, as this functionality is now handled entirely by
the generic PCM dmaengine APIs.
Since DMA channels must be paused and resumed during recovery paths
(overruns and underruns), the DMA channel references are stored in
rz_ssi_hw_params().
The logic in rz_ssi_is_dma_enabled() was updated to reflect that the
driver no longer manages DMA transfers directly.
Finally, rz_ssi_stream_is_play() was removed, as it had only a single
remaining user after this rework, and its logic was inlined at the call
site.
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
sound/soc/renesas/rz-ssi.c | 355 ++++++++-----------------------------
1 file changed, 77 insertions(+), 278 deletions(-)
diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c
index 39aa865bdca3..d9c88a1975b8 100644
--- a/sound/soc/renesas/rz-ssi.c
+++ b/sound/soc/renesas/rz-ssi.c
@@ -13,6 +13,8 @@
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -87,8 +89,6 @@ struct rz_ssi_stream {
struct rz_ssi_priv *priv;
struct snd_pcm_substream *substream;
int fifo_sample_size; /* sample capacity of SSI FIFO */
- int dma_buffer_pos; /* The address for the next DMA descriptor */
- int completed_dma_buf_pos; /* The address of the last completed DMA descriptor. */
int period_counter; /* for keeping track of periods transferred */
int buffer_pos; /* current frame position in the buffer */
int running; /* 0=stopped, 1=running */
@@ -96,8 +96,6 @@ struct rz_ssi_stream {
int uerr_num;
int oerr_num;
- struct dma_chan *dma_ch;
-
int (*transfer)(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm);
};
@@ -108,7 +106,6 @@ struct rz_ssi_priv {
struct clk *sfr_clk;
struct clk *clk;
- phys_addr_t phys;
int irq_int;
int irq_tx;
int irq_rx;
@@ -148,9 +145,10 @@ struct rz_ssi_priv {
unsigned int sample_width;
unsigned int sample_bits;
} hw_params_cache;
-};
-static void rz_ssi_dma_complete(void *data);
+ struct snd_dmaengine_dai_dma_data dma_dais[SNDRV_PCM_STREAM_LAST + 1];
+ struct dma_chan *dmas[SNDRV_PCM_STREAM_LAST + 1];
+};
static void rz_ssi_reg_writel(struct rz_ssi_priv *priv, uint reg, u32 data)
{
@@ -172,11 +170,6 @@ static void rz_ssi_reg_mask_setl(struct rz_ssi_priv *priv, uint reg,
writel(val, (priv->base + reg));
}
-static inline bool rz_ssi_stream_is_play(struct snd_pcm_substream *substream)
-{
- return substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-}
-
static inline struct rz_ssi_stream *
rz_ssi_stream_get(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream)
{
@@ -185,7 +178,7 @@ rz_ssi_stream_get(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream)
static inline bool rz_ssi_is_dma_enabled(struct rz_ssi_priv *ssi)
{
- return (ssi->playback.dma_ch && (ssi->dma_rt || ssi->capture.dma_ch));
+ return !ssi->playback.transfer && !ssi->capture.transfer;
}
static void rz_ssi_set_substream(struct rz_ssi_stream *strm,
@@ -215,8 +208,6 @@ static void rz_ssi_stream_init(struct rz_ssi_stream *strm,
struct snd_pcm_substream *substream)
{
rz_ssi_set_substream(strm, substream);
- strm->dma_buffer_pos = 0;
- strm->completed_dma_buf_pos = 0;
strm->period_counter = 0;
strm->buffer_pos = 0;
@@ -242,12 +233,13 @@ static void rz_ssi_stream_quit(struct rz_ssi_priv *ssi,
dev_info(dev, "underrun = %d\n", strm->uerr_num);
}
-static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate,
- unsigned int channels)
+static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream,
+ unsigned int rate, unsigned int channels)
{
static u8 ckdv[] = { 1, 2, 4, 8, 16, 32, 64, 128, 6, 12, 24, 48, 96 };
unsigned int channel_bits = 32; /* System Word Length */
unsigned long bclk_rate = rate * channels * channel_bits;
+ struct snd_dmaengine_dai_dma_data *dma_dai;
unsigned int div;
unsigned int i;
u32 ssicr = 0;
@@ -290,6 +282,8 @@ static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate,
return -EINVAL;
}
+ dma_dai = &ssi->dma_dais[substream->stream];
+
/*
* DWL: Data Word Length = {16, 24, 32} bits
* SWL: System Word Length = 32 bits
@@ -298,12 +292,18 @@ static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate,
switch (ssi->hw_params_cache.sample_width) {
case 16:
ssicr |= SSICR_DWL(1);
+ dma_dai->maxburst = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ dma_dai->addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
break;
case 24:
ssicr |= SSICR_DWL(5) | SSICR_PDTA;
+ dma_dai->maxburst = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ dma_dai->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
case 32:
ssicr |= SSICR_DWL(6);
+ dma_dai->maxburst = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ dma_dai->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
default:
dev_err(ssi->dev, "Not support %u data width",
@@ -344,7 +344,7 @@ static void rz_ssi_set_idle(struct rz_ssi_priv *ssi)
static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
{
- bool is_play = rz_ssi_stream_is_play(strm->substream);
+ bool is_play = strm->substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
bool is_full_duplex;
u32 ssicr, ssifcr;
@@ -423,14 +423,6 @@ static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
/* Disable TX/RX */
rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0);
- /* Cancel all remaining DMA transactions */
- if (rz_ssi_is_dma_enabled(ssi)) {
- if (ssi->playback.dma_ch)
- dmaengine_terminate_async(ssi->playback.dma_ch);
- if (ssi->capture.dma_ch)
- dmaengine_terminate_async(ssi->capture.dma_ch);
- }
-
rz_ssi_set_idle(ssi);
return 0;
@@ -458,10 +450,6 @@ static void rz_ssi_pointer_update(struct rz_ssi_stream *strm, int frames)
snd_pcm_period_elapsed(strm->substream);
strm->period_counter = current_period;
}
-
- strm->completed_dma_buf_pos += runtime->period_size;
- if (strm->completed_dma_buf_pos >= runtime->buffer_size)
- strm->completed_dma_buf_pos = 0;
}
static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
@@ -606,12 +594,6 @@ static irqreturn_t rz_ssi_interrupt(int irq, void *data)
if (irq == ssi->irq_int) { /* error or idle */
bool is_stopped = !!(ssisr & (SSISR_RUIRQ | SSISR_ROIRQ |
SSISR_TUIRQ | SSISR_TOIRQ));
- int i, count;
-
- if (rz_ssi_is_dma_enabled(ssi))
- count = 4;
- else
- count = 1;
if (ssi->capture.substream && is_stopped) {
if (ssisr & SSISR_RUIRQ)
@@ -619,7 +601,8 @@ static irqreturn_t rz_ssi_interrupt(int irq, void *data)
if (ssisr & SSISR_ROIRQ)
strm_capture->oerr_num++;
- rz_ssi_stop(ssi, strm_capture);
+ if (rz_ssi_is_dma_enabled(ssi))
+ dmaengine_pause(ssi->dmas[SNDRV_PCM_STREAM_CAPTURE]);
}
if (ssi->playback.substream && is_stopped) {
@@ -628,7 +611,8 @@ static irqreturn_t rz_ssi_interrupt(int irq, void *data)
if (ssisr & SSISR_TOIRQ)
strm_playback->oerr_num++;
- rz_ssi_stop(ssi, strm_playback);
+ if (rz_ssi_is_dma_enabled(ssi))
+ dmaengine_pause(ssi->dmas[SNDRV_PCM_STREAM_PLAYBACK]);
}
/* Clear all flags */
@@ -637,12 +621,16 @@ static irqreturn_t rz_ssi_interrupt(int irq, void *data)
/* Add/remove more data */
if (ssi->capture.substream && is_stopped) {
- for (i = 0; i < count; i++)
+ if (rz_ssi_is_dma_enabled(ssi))
+ dmaengine_resume(ssi->dmas[SNDRV_PCM_STREAM_CAPTURE]);
+ else
strm_capture->transfer(ssi, strm_capture);
}
if (ssi->playback.substream && is_stopped) {
- for (i = 0; i < count; i++)
+ if (rz_ssi_is_dma_enabled(ssi))
+ dmaengine_resume(ssi->dmas[SNDRV_PCM_STREAM_PLAYBACK]);
+ else
strm_playback->transfer(ssi, strm_playback);
}
@@ -679,153 +667,11 @@ static irqreturn_t rz_ssi_interrupt(int irq, void *data)
return IRQ_HANDLED;
}
-static int rz_ssi_dma_slave_config(struct rz_ssi_priv *ssi,
- struct dma_chan *dma_ch, bool is_play)
-{
- struct dma_slave_config cfg;
-
- memset(&cfg, 0, sizeof(cfg));
-
- cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
- cfg.dst_addr = ssi->phys + SSIFTDR;
- cfg.src_addr = ssi->phys + SSIFRDR;
- if (ssi->hw_params_cache.sample_width == 16) {
- cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
- cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
- } else {
- cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- }
-
- return dmaengine_slave_config(dma_ch, &cfg);
-}
-
-static int rz_ssi_dma_transfer(struct rz_ssi_priv *ssi,
- struct rz_ssi_stream *strm)
-{
- struct snd_pcm_substream *substream = strm->substream;
- struct dma_async_tx_descriptor *desc;
- struct snd_pcm_runtime *runtime;
- enum dma_transfer_direction dir;
- u32 dma_paddr, dma_size;
- int amount;
-
- if (!rz_ssi_stream_is_valid(ssi, strm))
- return -EINVAL;
-
- runtime = substream->runtime;
- if (runtime->state == SNDRV_PCM_STATE_DRAINING)
- /*
- * Stream is ending, so do not queue up any more DMA
- * transfers otherwise we play partial sound clips
- * because we can't shut off the DMA quick enough.
- */
- return 0;
-
- dir = rz_ssi_stream_is_play(substream) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
-
- /* Always transfer 1 period */
- amount = runtime->period_size;
-
- /* DMA physical address and size */
- dma_paddr = runtime->dma_addr + frames_to_bytes(runtime,
- strm->dma_buffer_pos);
- dma_size = frames_to_bytes(runtime, amount);
- desc = dmaengine_prep_slave_single(strm->dma_ch, dma_paddr, dma_size,
- dir,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc) {
- dev_err(ssi->dev, "dmaengine_prep_slave_single() fail\n");
- return -ENOMEM;
- }
-
- desc->callback = rz_ssi_dma_complete;
- desc->callback_param = strm;
-
- if (dmaengine_submit(desc) < 0) {
- dev_err(ssi->dev, "dmaengine_submit() fail\n");
- return -EIO;
- }
-
- /* Update DMA pointer */
- strm->dma_buffer_pos += amount;
- if (strm->dma_buffer_pos >= runtime->buffer_size)
- strm->dma_buffer_pos = 0;
-
- /* Start DMA */
- dma_async_issue_pending(strm->dma_ch);
-
- return 0;
-}
-
-static void rz_ssi_dma_complete(void *data)
-{
- struct rz_ssi_stream *strm = (struct rz_ssi_stream *)data;
-
- if (!strm->running || !strm->substream || !strm->substream->runtime)
- return;
-
- /* Note that next DMA transaction has probably already started */
- rz_ssi_pointer_update(strm, strm->substream->runtime->period_size);
-
- /* Queue up another DMA transaction */
- rz_ssi_dma_transfer(strm->priv, strm);
-}
-
-static void rz_ssi_release_dma_channels(struct rz_ssi_priv *ssi)
-{
- if (ssi->playback.dma_ch) {
- dma_release_channel(ssi->playback.dma_ch);
- ssi->playback.dma_ch = NULL;
- if (ssi->dma_rt)
- ssi->dma_rt = false;
- }
-
- if (ssi->capture.dma_ch) {
- dma_release_channel(ssi->capture.dma_ch);
- ssi->capture.dma_ch = NULL;
- }
-}
-
-static int rz_ssi_dma_request(struct rz_ssi_priv *ssi, struct device *dev)
-{
- ssi->playback.dma_ch = dma_request_chan(dev, "tx");
- if (IS_ERR(ssi->playback.dma_ch))
- ssi->playback.dma_ch = NULL;
-
- ssi->capture.dma_ch = dma_request_chan(dev, "rx");
- if (IS_ERR(ssi->capture.dma_ch))
- ssi->capture.dma_ch = NULL;
-
- if (!ssi->playback.dma_ch && !ssi->capture.dma_ch) {
- ssi->playback.dma_ch = dma_request_chan(dev, "rt");
- if (IS_ERR(ssi->playback.dma_ch)) {
- ssi->playback.dma_ch = NULL;
- goto no_dma;
- }
-
- ssi->dma_rt = true;
- }
-
- if (!rz_ssi_is_dma_enabled(ssi))
- goto no_dma;
-
- return 0;
-
-no_dma:
- rz_ssi_release_dma_channels(ssi);
-
- return -ENODEV;
-}
-
static int rz_ssi_trigger_resume(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
{
struct snd_pcm_substream *substream = strm->substream;
- struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
- strm->dma_buffer_pos = strm->completed_dma_buf_pos + runtime->period_size;
-
if (rz_ssi_is_stream_running(&ssi->playback) ||
rz_ssi_is_stream_running(&ssi->capture))
return 0;
@@ -834,7 +680,7 @@ static int rz_ssi_trigger_resume(struct rz_ssi_priv *ssi, struct rz_ssi_stream *
if (ret)
return ret;
- return rz_ssi_clk_setup(ssi, ssi->hw_params_cache.rate,
+ return rz_ssi_clk_setup(ssi, substream, ssi->hw_params_cache.rate,
ssi->hw_params_cache.channels);
}
@@ -843,7 +689,7 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
{
struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
- int ret = 0, i, num_transfer = 1;
+ int ret = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_RESUME:
@@ -857,28 +703,7 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
if (cmd == SNDRV_PCM_TRIGGER_START)
rz_ssi_stream_init(strm, substream);
- if (rz_ssi_is_dma_enabled(ssi)) {
- bool is_playback = rz_ssi_stream_is_play(substream);
-
- if (ssi->dma_rt)
- ret = rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch,
- is_playback);
- else
- ret = rz_ssi_dma_slave_config(ssi, strm->dma_ch,
- is_playback);
-
- /* Fallback to pio */
- if (ret < 0) {
- ssi->playback.transfer = rz_ssi_pio_send;
- ssi->capture.transfer = rz_ssi_pio_recv;
- rz_ssi_release_dma_channels(ssi);
- } else {
- /* For DMA, queue up multiple DMA descriptors */
- num_transfer = 4;
- }
- }
-
- for (i = 0; i < num_transfer; i++) {
+ if (!rz_ssi_is_dma_enabled(ssi)) {
ret = strm->transfer(ssi, strm);
if (ret)
return ret;
@@ -1024,6 +849,9 @@ static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
+ /* Save the DMA channels for recovery. */
+ ssi->dmas[substream->stream] = snd_dmaengine_pcm_get_chan(substream);
+
if (rz_ssi_is_stream_running(&ssi->playback) ||
rz_ssi_is_stream_running(&ssi->capture)) {
if (rz_ssi_is_valid_hw_params(ssi, rate, channels, sample_width, sample_bits))
@@ -1039,10 +867,21 @@ static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream,
if (ret)
return ret;
- return rz_ssi_clk_setup(ssi, rate, channels);
+ return rz_ssi_clk_setup(ssi, substream, rate, channels);
+}
+
+static int rz_ssi_dai_probe(struct snd_soc_dai *dai)
+{
+ struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
+
+ snd_soc_dai_init_dma_data(dai, &ssi->dma_dais[SNDRV_PCM_STREAM_PLAYBACK],
+ &ssi->dma_dais[SNDRV_PCM_STREAM_CAPTURE]);
+
+ return 0;
}
static const struct snd_soc_dai_ops rz_ssi_dai_ops = {
+ .probe = rz_ssi_dai_probe,
.startup = rz_ssi_startup,
.shutdown = rz_ssi_shutdown,
.trigger = rz_ssi_dai_trigger,
@@ -1054,7 +893,8 @@ static const struct snd_pcm_hardware rz_ssi_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_RESUME,
+ SNDRV_PCM_INFO_RESUME |
+ SNDRV_PCM_INFO_PAUSE,
.buffer_bytes_max = PREALLOC_BUFFER,
.period_bytes_min = 32,
.period_bytes_max = 8192,
@@ -1074,26 +914,6 @@ static int rz_ssi_pcm_open(struct snd_soc_component *component,
SNDRV_PCM_HW_PARAM_PERIODS);
}
-static snd_pcm_uframes_t rz_ssi_pcm_pointer(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
- struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
-
- return strm->buffer_pos;
-}
-
-static int rz_ssi_pcm_new(struct snd_soc_component *component,
- struct snd_soc_pcm_runtime *rtd)
-{
- snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
- rtd->card->snd_card->dev,
- PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
- return 0;
-}
-
static struct snd_soc_dai_driver rz_ssi_soc_dai[] = {
{
.name = "rz-ssi-dai",
@@ -1116,15 +936,19 @@ static struct snd_soc_dai_driver rz_ssi_soc_dai[] = {
static const struct snd_soc_component_driver rz_ssi_soc_component = {
.name = "rz-ssi",
.open = rz_ssi_pcm_open,
- .pointer = rz_ssi_pcm_pointer,
- .pcm_construct = rz_ssi_pcm_new,
.legacy_dai_naming = 1,
};
+static struct snd_dmaengine_pcm_config rz_ssi_dmaegine_pcm_conf = {
+ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
+};
+
static int rz_ssi_probe(struct platform_device *pdev)
{
+ struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
struct rz_ssi_priv *ssi;
+ unsigned int flags = 0;
struct clk *audio_clk;
struct resource *res;
int ret;
@@ -1138,7 +962,6 @@ static int rz_ssi_probe(struct platform_device *pdev)
if (IS_ERR(ssi->base))
return PTR_ERR(ssi->base);
- ssi->phys = res->start;
ssi->clk = devm_clk_get(dev, "ssi");
if (IS_ERR(ssi->clk))
return PTR_ERR(ssi->clk);
@@ -1162,16 +985,21 @@ static int rz_ssi_probe(struct platform_device *pdev)
ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 : ssi->audio_clk_2;
- /* Detect DMA support */
- ret = rz_ssi_dma_request(ssi, dev);
- if (ret < 0) {
- dev_warn(dev, "DMA not available, using PIO\n");
+ ssi->dma_dais[SNDRV_PCM_STREAM_PLAYBACK].addr = (dma_addr_t)res->start + SSIFTDR;
+ ssi->dma_dais[SNDRV_PCM_STREAM_CAPTURE].addr = (dma_addr_t)res->start + SSIFRDR;
+
+ if (of_property_match_string(np, "dma-names", "rt") == 0) {
+ flags = SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX;
+ rz_ssi_dmaegine_pcm_conf.chan_names[SNDRV_PCM_STREAM_PLAYBACK] = "rt";
+ }
+
+ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, &rz_ssi_dmaegine_pcm_conf, flags);
+ if (ret) {
+ dev_warn(dev, "DMA not available, using PIO!\n");
ssi->playback.transfer = rz_ssi_pio_send;
ssi->capture.transfer = rz_ssi_pio_recv;
} else {
- dev_info(dev, "DMA enabled");
- ssi->playback.transfer = rz_ssi_dma_transfer;
- ssi->capture.transfer = rz_ssi_dma_transfer;
+ dev_info(dev, "DMA enabled\n");
}
ssi->playback.priv = ssi;
@@ -1182,17 +1010,13 @@ static int rz_ssi_probe(struct platform_device *pdev)
/* Error Interrupt */
ssi->irq_int = platform_get_irq_byname(pdev, "int_req");
- if (ssi->irq_int < 0) {
- ret = ssi->irq_int;
- goto err_release_dma_chs;
- }
+ if (ssi->irq_int < 0)
+ return ssi->irq_int;
ret = devm_request_irq(dev, ssi->irq_int, rz_ssi_interrupt,
0, dev_name(dev), ssi);
- if (ret < 0) {
- dev_err_probe(dev, ret, "irq request error (int_req)\n");
- goto err_release_dma_chs;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "irq request error (int_req)\n");
if (!rz_ssi_is_dma_enabled(ssi)) {
/* Tx and Rx interrupts (pio only) */
@@ -1233,43 +1057,19 @@ static int rz_ssi_probe(struct platform_device *pdev)
}
ssi->rstc = devm_reset_control_get_exclusive(dev, NULL);
- if (IS_ERR(ssi->rstc)) {
- ret = PTR_ERR(ssi->rstc);
- goto err_release_dma_chs;
- }
+ if (IS_ERR(ssi->rstc))
+ return dev_err_probe(dev, PTR_ERR(ssi->rstc), "Failed to get reset\n");
/* Default 0 for power saving. Can be overridden via sysfs. */
pm_runtime_set_autosuspend_delay(dev, 0);
pm_runtime_use_autosuspend(dev);
ret = devm_pm_runtime_enable(dev);
- if (ret < 0) {
- dev_err(dev, "Failed to enable runtime PM!\n");
- goto err_release_dma_chs;
- }
-
- ret = devm_snd_soc_register_component(dev, &rz_ssi_soc_component,
- rz_ssi_soc_dai,
- ARRAY_SIZE(rz_ssi_soc_dai));
- if (ret < 0) {
- dev_err(dev, "failed to register snd component\n");
- goto err_release_dma_chs;
- }
-
- return 0;
-
-err_release_dma_chs:
- rz_ssi_release_dma_channels(ssi);
-
- return ret;
-}
-
-static void rz_ssi_remove(struct platform_device *pdev)
-{
- struct rz_ssi_priv *ssi = dev_get_drvdata(&pdev->dev);
-
- rz_ssi_release_dma_channels(ssi);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to enable runtime PM!\n");
- reset_control_assert(ssi->rstc);
+ return devm_snd_soc_register_component(dev, &rz_ssi_soc_component,
+ rz_ssi_soc_dai,
+ ARRAY_SIZE(rz_ssi_soc_dai));
}
static const struct of_device_id rz_ssi_of_match[] = {
@@ -1304,7 +1104,6 @@ static struct platform_driver rz_ssi_driver = {
.pm = pm_ptr(&rz_ssi_pm_ops),
},
.probe = rz_ssi_probe,
- .remove = rz_ssi_remove,
};
module_platform_driver(rz_ssi_driver);
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 7/7] dmaengine: sh: rz-dmac: Set the Link End (LE) bit on the last descriptor
2026-01-26 10:31 [PATCH 0/7] Renesas: dmaengine and ASoC fixes Claudiu
` (5 preceding siblings ...)
2026-01-26 10:31 ` [PATCH 6/7] ASoC: renesas: rz-ssi: Use generic PCM dmaengine APIs Claudiu
@ 2026-01-26 10:31 ` Claudiu
6 siblings, 0 replies; 31+ messages in thread
From: Claudiu @ 2026-01-26 10:31 UTC (permalink / raw)
To: vkoul, biju.das.jz, prabhakar.mahadev-lad.rj, lgirdwood, broonie,
perex, tiwai, p.zabel, geert+renesas, fabrizio.castro.jz
Cc: claudiu.beznea, dmaengine, linux-kernel, linux-sound,
linux-renesas-soc, Claudiu Beznea
From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
On an RZ/G2L-based system, it has been observed that when the DMA channels
for all enabled IPs are active (TX and RX for one serial IP, TX and RX for
one audio IP, and TX and RX for one SPI IP), shortly after all of them are
started, the system can become irrecoverably blocked. In one debug session
the system did not block, and the DMA HW registers were inspected. It was
found that the DER (Descriptor Error) bit in the CHSTAT register for one of
the SPI DMA channels was set.
According to the RZ/G2L HW Manual, Rev. 1.30, chapter 14.4.7 Channel
Status Register n/nS (CHSTAT_n/nS), description of the DER bit, the DER
bit is set when the LV (Link Valid) value loaded with a descriptor in link
mode is 0. This means that the DMA engine has loaded an invalid
descriptor (as defined in Table 14.14, Header Area, of the same manual).
The same chapter states that when a descriptor error occurs, the transfer
is stopped, but no DMA error interrupt is generated.
Set the LE bit on the last descriptor of a transfer. This informs the DMA
engine that this is the final descriptor for the transfer.
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
drivers/dma/sh/rz-dmac.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
index 8f3e2719e639..3a77a560fcd5 100644
--- a/drivers/dma/sh/rz-dmac.c
+++ b/drivers/dma/sh/rz-dmac.c
@@ -206,6 +206,7 @@ struct rz_dmac {
/* LINK MODE DESCRIPTOR */
#define HEADER_LV BIT(0)
+#define HEADER_LE BIT(1)
#define HEADER_WBD BIT(2)
#define RZ_DMAC_MAX_CHAN_DESCRIPTORS 16
@@ -383,7 +384,7 @@ static void rz_dmac_prepare_desc_for_memcpy(struct rz_dmac_chan *channel)
lmdesc->chcfg = chcfg;
lmdesc->chitvl = 0;
lmdesc->chext = 0;
- lmdesc->header = HEADER_LV;
+ lmdesc->header = HEADER_LV | HEADER_LE;
rz_dmac_set_dma_req_no(dmac, channel->index, dmac->info->default_dma_req_no);
@@ -425,7 +426,7 @@ static void rz_dmac_prepare_descs_for_slave_sg(struct rz_dmac_chan *channel)
lmdesc->chext = 0;
if (i == (sg_len - 1)) {
lmdesc->chcfg = (channel->chcfg & ~CHCFG_DEM);
- lmdesc->header = HEADER_LV;
+ lmdesc->header = HEADER_LV | HEADER_LE;
} else {
lmdesc->chcfg = channel->chcfg;
lmdesc->header = HEADER_LV;
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* RE: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-01-26 10:31 ` [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support Claudiu
@ 2026-01-26 11:03 ` Biju Das
2026-01-26 12:04 ` Claudiu Beznea
2026-03-12 12:26 ` Tommaso Merciai
1 sibling, 1 reply; 31+ messages in thread
From: Biju Das @ 2026-01-26 11:03 UTC (permalink / raw)
To: Claudiu.Beznea, vkoul@kernel.org, Prabhakar Mahadev Lad,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, p.zabel@pengutronix.de, geert+renesas@glider.be,
Fabrizio Castro
Cc: Claudiu.Beznea, dmaengine@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-sound@vger.kernel.org,
linux-renesas-soc@vger.kernel.org, Claudiu Beznea
Hi Claudiu,
Thanks for the patch.
> -----Original Message-----
> From: Claudiu <claudiu.beznea@tuxon.dev>
> Sent: 26 January 2026 10:32
> Subject: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> The Renesas RZ/G3S SoC supports a power saving mode in which power to most SoC components is turned
> off, including the DMA IP. Add suspend to RAM support to save and restore the DMA IP registers.
>
> Cyclic DMA channels require special handling. Since they can be paused and resumed during system
> suspend and resume, the driver restores additional registers for these channels during the resume
> phase. If a channel was not explicitly paused during suspend, the driver ensures that it is paused and
> resumed as part of the system suspend/resume flow. This might be the case of a serial device being
> used with no_console_suspend.
>
> For non-cyclic channels, the dev_pm_ops::prepare callback waits for all ongoing transfers to complete
> before allowing suspend-to-RAM to proceed.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
> drivers/dma/sh/rz-dmac.c | 183 +++++++++++++++++++++++++++++++++++++--
> 1 file changed, 175 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c index ab5f49a0b9f2..8f3e2719e639
> 100644
> --- a/drivers/dma/sh/rz-dmac.c
> +++ b/drivers/dma/sh/rz-dmac.c
> @@ -69,11 +69,15 @@ struct rz_dmac_desc {
> * enum rz_dmac_chan_status: RZ DMAC channel status
> * @RZ_DMAC_CHAN_STATUS_ENABLED: Channel is enabled
> * @RZ_DMAC_CHAN_STATUS_PAUSED: Channel is paused though DMA engine callbacks
> + * @RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL: Channel is paused through
> + driver internal logic
> + * @RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED: Channel was prepared for system
> + suspend
> * @RZ_DMAC_CHAN_STATUS_CYCLIC: Channel is cyclic
> */
> enum rz_dmac_chan_status {
> RZ_DMAC_CHAN_STATUS_ENABLED,
> RZ_DMAC_CHAN_STATUS_PAUSED,
> + RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL,
> + RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED,
> RZ_DMAC_CHAN_STATUS_CYCLIC,
> };
>
> @@ -94,6 +98,10 @@ struct rz_dmac_chan {
> u32 chctrl;
> int mid_rid;
>
> + struct {
> + u32 nxla;
> + } pm_state;
> +
> struct list_head ld_free;
> struct list_head ld_queue;
> struct list_head ld_active;
> @@ -1002,10 +1010,17 @@ static int rz_dmac_device_pause(struct dma_chan *chan)
> return rz_dmac_device_pause_set(channel, RZ_DMAC_CHAN_STATUS_PAUSED); }
>
> +static int rz_dmac_device_pause_internal(struct rz_dmac_chan *channel)
> +{
> + lockdep_assert_held(&channel->vc.lock);
> +
> + return rz_dmac_device_pause_set(channel,
> +RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL);
> +}
> +
> static int rz_dmac_device_resume_set(struct rz_dmac_chan *channel,
> enum rz_dmac_chan_status status) {
> - u32 val;
> + u32 val, chctrl;
> int ret;
>
> lockdep_assert_held(&channel->vc.lock);
> @@ -1013,14 +1028,33 @@ static int rz_dmac_device_resume_set(struct rz_dmac_chan *channel,
> if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED)))
> return 0;
>
> - rz_dmac_ch_writel(channel, CHCTRL_CLRSUS, CHCTRL, 1);
> - ret = read_poll_timeout_atomic(rz_dmac_ch_readl, val,
> - !(val & CHSTAT_SUS), 1, 1024, false,
> - channel, CHSTAT, 1);
> - if (ret)
> - return ret;
> + if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED)) {
> + /*
> + * We can be after a sleep state with power loss. If power was
> + * lost, the CHSTAT_SUS bit is zero. In this case, we need to
> + * enable the channel directly. Otherwise, just set the CLRSUS
> + * bit.
> + */
> + val = rz_dmac_ch_readl(channel, CHSTAT, 1);
> + if (val & CHSTAT_SUS)
> + chctrl = CHCTRL_CLRSUS;
> + else
> + chctrl = CHCTRL_SETEN;
> + } else {
> + chctrl = CHCTRL_CLRSUS;
> + }
> +
> + rz_dmac_ch_writel(channel, chctrl, CHCTRL, 1);
>
> - channel->status &= ~BIT(status);
> + if (chctrl & CHCTRL_CLRSUS) {
> + ret = read_poll_timeout_atomic(rz_dmac_ch_readl, val,
> + !(val & CHSTAT_SUS), 1, 1024, false,
> + channel, CHSTAT, 1);
> + if (ret)
> + return ret;
> + }
> +
> + channel->status &= ~(BIT(status) |
> +BIT(RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED));
>
> return 0;
> }
> @@ -1034,6 +1068,13 @@ static int rz_dmac_device_resume(struct dma_chan *chan)
> return rz_dmac_device_resume_set(channel, RZ_DMAC_CHAN_STATUS_PAUSED); }
>
> +static int rz_dmac_device_resume_internal(struct rz_dmac_chan *channel)
> +{
> + lockdep_assert_held(&channel->vc.lock);
> +
> + return rz_dmac_device_resume_set(channel,
> +RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL);
> +}
> +
> /*
> * -----------------------------------------------------------------------------
> * IRQ handling
> @@ -1438,6 +1479,131 @@ static void rz_dmac_remove(struct platform_device *pdev)
> pm_runtime_disable(&pdev->dev);
> }
>
> +static int rz_dmac_suspend_prepare(struct device *dev) {
> + struct rz_dmac *dmac = dev_get_drvdata(dev);
> +
> + for (unsigned int i = 0; i < dmac->n_channels; i++) {
> + struct rz_dmac_chan *channel = &dmac->channels[i];
> +
> + guard(spinlock_irqsave)(&channel->vc.lock);
> +
> + /* Wait for transfer completion, except in cyclic case. */
> + if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_ENABLED) &&
> + !(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)))
> + return -EAGAIN;
> + }
> +
> + return 0;
> +}
> +
> +static void rz_dmac_suspend_recover(struct rz_dmac *dmac) {
> + for (unsigned int i = 0; i < dmac->n_channels; i++) {
> + struct rz_dmac_chan *channel = &dmac->channels[i];
> +
> + guard(spinlock_irqsave)(&channel->vc.lock);
> +
> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)))
> + continue;
> +
> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL)))
> + continue;
> +
> + rz_dmac_device_resume_internal(channel);
> + }
> +}
> +
> +static int rz_dmac_suspend(struct device *dev) {
> + struct rz_dmac *dmac = dev_get_drvdata(dev);
> + int ret;
> +
> + for (unsigned int i = 0; i < dmac->n_channels; i++) {
> + struct rz_dmac_chan *channel = &dmac->channels[i];
> +
> + guard(spinlock_irqsave)(&channel->vc.lock);
> +
> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)))
> + continue;
> +
> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED))) {
> + ret = rz_dmac_device_pause_internal(channel);
> + if (ret) {
> + dev_err(dev, "Failed to suspend channel %s\n",
> + dma_chan_name(&channel->vc.chan));
> + continue;
> + }
> + }
> +
> + channel->pm_state.nxla = rz_dmac_ch_readl(channel, NXLA, 1);
> + channel->status |= BIT(RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED);
> + }
> +
> + pm_runtime_put_sync(dmac->dev);
> +
> + ret = reset_control_assert(dmac->rstc);
> + if (ret) {
> + pm_runtime_resume_and_get(dmac->dev);
> + rz_dmac_suspend_recover(dmac);
> + }
> +
This patch breaks, s2idle in RZ/G3L as it turns off DMA ACLK and IRQ's
are not routed to CPU for wakeup.
DMA ACLK is required for routing IRQ to CPU, without this CPU won't get any interrupts.
If we make this CLK as critical clock, s2idle fails, as the DMA ALCK turned off during suspend
and there is no IRQ to wake up the system.
LOGS:
root@smarc-rzg3l:~# echo enabled > /sys/class/tty/ttySC3/power/wakeup
echo N > /sys/module/printk/parameters/console_suspend
root@smarc-rzg3l:~# echo N > /sys/module/printk/parameters/console_suspend
root@smarc-rzg3l:~# echo 7 > /proc/sys/kernel/printk
root@smarc-rzg3l:~# echo freeze > /sys/power/state
[ 41.601992] PM: suspend entry (s2idle)
[ 41.605979] Filesystems sync: 0.000 seconds
[ 41.611261] Freezing user space processes
[ 41.614848] Freezing user space processes completed (elapsed 0.003 seconds)
[ 41.622676] OOM killer disabled.
[ 41.625908] Freezing remaining freezable tasks
[ 41.631642] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
[ 41.640137] renesas-gbeth 11c30000.ethernet end0: Link is Down
On my testing shows on RZ/G3L, we need to make DMA ACLK as non-PM clk for
Making both s2idle and str to work on RZ/G3L.
if (pm_suspend_target_state == PM_SUSPEND_TO_IDLE)
you need this check in suspend/resume not to turn off DMAACLK during s2idle.
Also, the callback has to be in non_irq phase so that CPU start getting IRQ's
During sleep phase.
Cheers,
Biju
> + return ret;
> +}
> +
> +static int rz_dmac_resume(struct device *dev) {
> + struct rz_dmac *dmac = dev_get_drvdata(dev);
> + int ret;
> +
> + ret = reset_control_deassert(dmac->rstc);
> + if (ret)
> + return ret;
> +
> + ret = pm_runtime_resume_and_get(dmac->dev);
> + if (ret) {
> + reset_control_assert(dmac->rstc);
> + return ret;
> + }
> +
> + rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_0_7_COMMON_BASE + DCTRL);
> + rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_8_15_COMMON_BASE + DCTRL);
> +
> + for (unsigned int i = 0; i < dmac->n_channels; i++) {
> + struct rz_dmac_chan *channel = &dmac->channels[i];
> +
> + guard(spinlock_irqsave)(&channel->vc.lock);
> +
> + rz_dmac_set_dma_req_no(dmac, channel->index, channel->mid_rid);
> +
> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC))) {
> + rz_dmac_ch_writel(&dmac->channels[i], CHCTRL_DEFAULT, CHCTRL, 1);
> + continue;
> + }
> +
> + rz_dmac_ch_writel(channel, channel->pm_state.nxla, NXLA, 1);
> + rz_dmac_ch_writel(channel, channel->chcfg, CHCFG, 1);
> + rz_dmac_ch_writel(channel, CHCTRL_SWRST, CHCTRL, 1);
> + rz_dmac_ch_writel(channel, channel->chctrl, CHCTRL, 1);
> +
> + if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL)) {
> + ret = rz_dmac_device_resume_internal(channel);
> + if (ret) {
> + dev_err(dev, "Failed to resume channel %s\n",
> + dma_chan_name(&channel->vc.chan));
> + continue;
> + }
> + }
> + }
> +
> + return 0;
> +}
> +
> +static const struct dev_pm_ops rz_dmac_pm_ops = {
> + .prepare = rz_dmac_suspend_prepare,
> + SYSTEM_SLEEP_PM_OPS(rz_dmac_suspend, rz_dmac_resume) };
> +
> static const struct rz_dmac_info rz_dmac_v2h_info = {
> .icu_register_dma_req = rzv2h_icu_register_dma_req,
> .default_dma_req_no = RZV2H_ICU_DMAC_REQ_NO_DEFAULT, @@ -1464,6 +1630,7 @@ static struct
> platform_driver rz_dmac_driver = {
> .driver = {
> .name = "rz-dmac",
> .of_match_table = of_rz_dmac_match,
> + .pm = pm_sleep_ptr(&rz_dmac_pm_ops),
> },
> .probe = rz_dmac_probe,
> .remove = rz_dmac_remove,
> --
> 2.43.0
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-01-26 11:03 ` Biju Das
@ 2026-01-26 12:04 ` Claudiu Beznea
2026-01-26 12:10 ` Biju Das
0 siblings, 1 reply; 31+ messages in thread
From: Claudiu Beznea @ 2026-01-26 12:04 UTC (permalink / raw)
To: Biju Das, vkoul@kernel.org, Prabhakar Mahadev Lad,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, p.zabel@pengutronix.de, geert+renesas@glider.be,
Fabrizio Castro
Cc: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-sound@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Claudiu Beznea
Hi,
On 1/26/26 13:03, Biju Das wrote:
> Hi Claudiu,
>
> Thanks for the patch.
>
>> -----Original Message-----
>> From: Claudiu <claudiu.beznea@tuxon.dev>
>> Sent: 26 January 2026 10:32
>> Subject: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>>
>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>
>> The Renesas RZ/G3S SoC supports a power saving mode in which power to most SoC components is turned
>> off, including the DMA IP. Add suspend to RAM support to save and restore the DMA IP registers.
>>
>> Cyclic DMA channels require special handling. Since they can be paused and resumed during system
>> suspend and resume, the driver restores additional registers for these channels during the resume
>> phase. If a channel was not explicitly paused during suspend, the driver ensures that it is paused and
>> resumed as part of the system suspend/resume flow. This might be the case of a serial device being
>> used with no_console_suspend.
>>
>> For non-cyclic channels, the dev_pm_ops::prepare callback waits for all ongoing transfers to complete
>> before allowing suspend-to-RAM to proceed.
>>
>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>> ---
>> drivers/dma/sh/rz-dmac.c | 183 +++++++++++++++++++++++++++++++++++++--
>> 1 file changed, 175 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c index ab5f49a0b9f2..8f3e2719e639
>> 100644
>> --- a/drivers/dma/sh/rz-dmac.c
>> +++ b/drivers/dma/sh/rz-dmac.c
>> @@ -69,11 +69,15 @@ struct rz_dmac_desc {
>> * enum rz_dmac_chan_status: RZ DMAC channel status
>> * @RZ_DMAC_CHAN_STATUS_ENABLED: Channel is enabled
>> * @RZ_DMAC_CHAN_STATUS_PAUSED: Channel is paused though DMA engine callbacks
>> + * @RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL: Channel is paused through
>> + driver internal logic
>> + * @RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED: Channel was prepared for system
>> + suspend
>> * @RZ_DMAC_CHAN_STATUS_CYCLIC: Channel is cyclic
>> */
>> enum rz_dmac_chan_status {
>> RZ_DMAC_CHAN_STATUS_ENABLED,
>> RZ_DMAC_CHAN_STATUS_PAUSED,
>> + RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL,
>> + RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED,
>> RZ_DMAC_CHAN_STATUS_CYCLIC,
>> };
>>
>> @@ -94,6 +98,10 @@ struct rz_dmac_chan {
>> u32 chctrl;
>> int mid_rid;
>>
>> + struct {
>> + u32 nxla;
>> + } pm_state;
>> +
>> struct list_head ld_free;
>> struct list_head ld_queue;
>> struct list_head ld_active;
>> @@ -1002,10 +1010,17 @@ static int rz_dmac_device_pause(struct dma_chan *chan)
>> return rz_dmac_device_pause_set(channel, RZ_DMAC_CHAN_STATUS_PAUSED); }
>>
>> +static int rz_dmac_device_pause_internal(struct rz_dmac_chan *channel)
>> +{
>> + lockdep_assert_held(&channel->vc.lock);
>> +
>> + return rz_dmac_device_pause_set(channel,
>> +RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL);
>> +}
>> +
>> static int rz_dmac_device_resume_set(struct rz_dmac_chan *channel,
>> enum rz_dmac_chan_status status) {
>> - u32 val;
>> + u32 val, chctrl;
>> int ret;
>>
>> lockdep_assert_held(&channel->vc.lock);
>> @@ -1013,14 +1028,33 @@ static int rz_dmac_device_resume_set(struct rz_dmac_chan *channel,
>> if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED)))
>> return 0;
>>
>> - rz_dmac_ch_writel(channel, CHCTRL_CLRSUS, CHCTRL, 1);
>> - ret = read_poll_timeout_atomic(rz_dmac_ch_readl, val,
>> - !(val & CHSTAT_SUS), 1, 1024, false,
>> - channel, CHSTAT, 1);
>> - if (ret)
>> - return ret;
>> + if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED)) {
>> + /*
>> + * We can be after a sleep state with power loss. If power was
>> + * lost, the CHSTAT_SUS bit is zero. In this case, we need to
>> + * enable the channel directly. Otherwise, just set the CLRSUS
>> + * bit.
>> + */
>> + val = rz_dmac_ch_readl(channel, CHSTAT, 1);
>> + if (val & CHSTAT_SUS)
>> + chctrl = CHCTRL_CLRSUS;
>> + else
>> + chctrl = CHCTRL_SETEN;
>> + } else {
>> + chctrl = CHCTRL_CLRSUS;
>> + }
>> +
>> + rz_dmac_ch_writel(channel, chctrl, CHCTRL, 1);
>>
>> - channel->status &= ~BIT(status);
>> + if (chctrl & CHCTRL_CLRSUS) {
>> + ret = read_poll_timeout_atomic(rz_dmac_ch_readl, val,
>> + !(val & CHSTAT_SUS), 1, 1024, false,
>> + channel, CHSTAT, 1);
>> + if (ret)
>> + return ret;
>> + }
>> +
>> + channel->status &= ~(BIT(status) |
>> +BIT(RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED));
>>
>> return 0;
>> }
>> @@ -1034,6 +1068,13 @@ static int rz_dmac_device_resume(struct dma_chan *chan)
>> return rz_dmac_device_resume_set(channel, RZ_DMAC_CHAN_STATUS_PAUSED); }
>>
>> +static int rz_dmac_device_resume_internal(struct rz_dmac_chan *channel)
>> +{
>> + lockdep_assert_held(&channel->vc.lock);
>> +
>> + return rz_dmac_device_resume_set(channel,
>> +RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL);
>> +}
>> +
>> /*
>> * -----------------------------------------------------------------------------
>> * IRQ handling
>> @@ -1438,6 +1479,131 @@ static void rz_dmac_remove(struct platform_device *pdev)
>> pm_runtime_disable(&pdev->dev);
>> }
>>
>> +static int rz_dmac_suspend_prepare(struct device *dev) {
>> + struct rz_dmac *dmac = dev_get_drvdata(dev);
>> +
>> + for (unsigned int i = 0; i < dmac->n_channels; i++) {
>> + struct rz_dmac_chan *channel = &dmac->channels[i];
>> +
>> + guard(spinlock_irqsave)(&channel->vc.lock);
>> +
>> + /* Wait for transfer completion, except in cyclic case. */
>> + if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_ENABLED) &&
>> + !(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)))
>> + return -EAGAIN;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static void rz_dmac_suspend_recover(struct rz_dmac *dmac) {
>> + for (unsigned int i = 0; i < dmac->n_channels; i++) {
>> + struct rz_dmac_chan *channel = &dmac->channels[i];
>> +
>> + guard(spinlock_irqsave)(&channel->vc.lock);
>> +
>> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)))
>> + continue;
>> +
>> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL)))
>> + continue;
>> +
>> + rz_dmac_device_resume_internal(channel);
>> + }
>> +}
>> +
>> +static int rz_dmac_suspend(struct device *dev) {
>> + struct rz_dmac *dmac = dev_get_drvdata(dev);
>> + int ret;
>> +
>> + for (unsigned int i = 0; i < dmac->n_channels; i++) {
>> + struct rz_dmac_chan *channel = &dmac->channels[i];
>> +
>> + guard(spinlock_irqsave)(&channel->vc.lock);
>> +
>> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)))
>> + continue;
>> +
>> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED))) {
>> + ret = rz_dmac_device_pause_internal(channel);
>> + if (ret) {
>> + dev_err(dev, "Failed to suspend channel %s\n",
>> + dma_chan_name(&channel->vc.chan));
>> + continue;
>> + }
>> + }
>> +
>> + channel->pm_state.nxla = rz_dmac_ch_readl(channel, NXLA, 1);
>> + channel->status |= BIT(RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED);
>> + }
>> +
>> + pm_runtime_put_sync(dmac->dev);
>> +
>> + ret = reset_control_assert(dmac->rstc);
>> + if (ret) {
>> + pm_runtime_resume_and_get(dmac->dev);
>> + rz_dmac_suspend_recover(dmac);
>> + }
>> +
>
>
> This patch breaks, s2idle in RZ/G3L as it turns off DMA ACLK and IRQ's
> are not routed to CPU for wakeup.
Is this particular patch the one that explicitly breaks it? Is there any
mainline PM support available for RZ/G3L? Can it be fixed along with the RZ/G3L
support, if any, as I don't have the board to test it?
Currently, this has been tested with RZ/G2L (no suspend to RAM support) and
RZ/G3S (that has suspend to RAM support).
>
> DMA ACLK is required for routing IRQ to CPU, without this CPU won't get any interrupts.
>
> If we make this CLK as critical clock, s2idle fails, as the DMA ALCK turned off during suspend
> and there is no IRQ to wake up the system.
How a critical clock is turned off durring suspend? Check clk core APIs to
disable clocks:
https://elixir.bootlin.com/linux/v6.19-rc5/source/drivers/clk/clk.c#L1051
https://elixir.bootlin.com/linux/v6.19-rc5/source/drivers/clk/clk.c#L1191
Can you please check the clocks HW bits on suspend/resume? I have prepared a
patch for you to check this:
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index c0584bab58a3..6da4a31ddb67 100644
--- a/drivers/clk/renesas/rzg2l-cpg.c
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -1603,6 +1603,14 @@ static void rzg2l_mod_clock_init_mstop(struct
rzg2l_cpg_priv *priv)
scoped_guard(spinlock_irqsave, &priv->rmw_lock) {
if (!rzg2l_mod_clock_is_enabled(&clk->hw))
rzg2l_mod_clock_module_set_state(clk, true);
+ else {
+
+ struct mod_clock *clock = to_mod_clock(hw);
+ struct rzg2l_cpg_priv *priv = clock->priv;
+ unsigned int reg = clock->off;
+
+ pr_err("%s(): CLK_ON 0x%x/%pC %x\n", __func__,
CLK_ON_R(reg), hw->clk, readl(priv->base + CLK_MON_R(reg)));
+ }
}
}
}
@@ -2055,6 +2063,27 @@ static int __init rzg2l_cpg_probe(struct platform_device
*pdev)
return 0;
}
+static int rzg2l_cpg_suspend(struct device *dev)
+{
+ struct rzg2l_cpg_priv *priv = dev_get_drvdata(dev);
+ struct mod_clock *clk;
+ struct clk_hw *hw;
+
+ for_each_mod_clock(clk, hw, priv) {
+ scoped_guard(spinlock_irqsave, &priv->rmw_lock) {
+ if (rzg2l_mod_clock_is_enabled(&clk->hw)) {
+ struct mod_clock *clock = to_mod_clock(hw);
+ struct rzg2l_cpg_priv *priv = clock->priv;
+ unsigned int reg = clock->off;
+
+ pr_err("%s(): CLK_ON 0x%x/%pC %x\n", __func__,
CLK_ON_R(reg), hw->clk, readl(priv->base + CLK_MON_R(reg)));
+ }
+ }
+ }
+
+ return 0;
+}
+
static int rzg2l_cpg_resume(struct device *dev)
{
struct rzg2l_cpg_priv *priv = dev_get_drvdata(dev);
@@ -2065,7 +2094,7 @@ static int rzg2l_cpg_resume(struct device *dev)
}
static const struct dev_pm_ops rzg2l_cpg_pm_ops = {
- NOIRQ_SYSTEM_SLEEP_PM_OPS(NULL, rzg2l_cpg_resume)
+ NOIRQ_SYSTEM_SLEEP_PM_OPS(rzg2l_cpg_suspend, rzg2l_cpg_resume)
};
static const struct of_device_id rzg2l_cpg_match[] = {
And this is what I'm getting when executing on my side:
root@smarc-rzg3s:~# echo enabled > /sys/class/tty/ttySC3/power/wakeup
root@smarc-rzg3s:~# echo N > /sys/module/printk/parameters/console_suspend
root@smarc-rzg3s:~# echo 7 > /proc/sys/kernel/printk
root@smarc-rzg3s:~# echo freeze > /sys/power/state
[ 80.019374] PM: suspend entry (s2idle)
[ 80.024173] Filesystems sync: 0.000 seconds
[ 80.040934] Freezing user space processes
[ 80.048238] Freezing user space processes completed (elapsed 0.007 seconds)
[ 80.055260] OOM killer disabled.
[ 80.058476] Freezing remaining freezable tasks
[ 80.064400] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
[ 80.137919] ravb 11c30000.ethernet end0: Link is Down
[ 80.170875] rzg2l_cpg_suspend(): CLK_ON 0x514/gic_gicclk 1
[ 80.176435] rzg2l_cpg_suspend(): CLK_ON 0x518/ia55_clk 3
[ 80.181744] rzg2l_cpg_suspend(): CLK_ON 0x518/ia55_pclk 3
[ 80.187137] rzg2l_cpg_suspend(): CLK_ON 0x52c/dmac_aclk 3
[ 80.192528] rzg2l_cpg_suspend(): CLK_ON 0x52c/dmac_pclk 3
[ 80.197971] rzg2l_cpg_suspend(): CLK_ON 0x584/scif0_clk_pck 1
[ 80.203728] rzg2l_cpg_suspend(): CLK_ON 0x598/gpio_hclk 1
[ 80.209136] rzg2l_cpg_suspend(): CLK_ON 0x614/vbat_bclk 1
[ 83.307594] rzg2l_mod_clock_init_mstop(): CLK_ON 0x514/gic_gicclk 1
[ 83.313889] rzg2l_mod_clock_init_mstop(): CLK_ON 0x518/ia55_clk 3
[ 83.319975] rzg2l_mod_clock_init_mstop(): CLK_ON 0x518/ia55_pclk 3
[ 83.326146] rzg2l_mod_clock_init_mstop(): CLK_ON 0x52c/dmac_aclk 3
[ 83.332315] rzg2l_mod_clock_init_mstop(): CLK_ON 0x52c/dmac_pclk 3
[ 83.338572] rzg2l_mod_clock_init_mstop(): CLK_ON 0x584/scif0_clk_pck 1
[ 83.345102] rzg2l_mod_clock_init_mstop(): CLK_ON 0x598/gpio_hclk 1
[ 83.351291] rzg2l_mod_clock_init_mstop(): CLK_ON 0x614/vbat_bclk 1
[ 83.455408] rzg3s-pcie-host 11e40000.pcie: PCIe link status [0x100014e]
[ 83.667239] nvme nvme0: 1/0/0 default/read/poll queues
[ 83.730087] Microchip KSZ9131 Gigabit PHY 11c30000.ethernet-ffffffff:07:
attached PHY driver (mii_bus:phy_addr=11c30000.ethernet-ffffffff:07, irq=59)
[ 83.814109] Microchip KSZ9131 Gigabit PHY 11c40000.ethernet-ffffffff:07:
attached PHY driver (mii_bus:phy_addr=11c40000.ethernet-ffffffff:07, irq=61)
[ 83.917155] usb usb2: root hub lost power or was reset
[ 83.922361] usb usb1: root hub lost power or was reset
[ 84.013163] usb usb4: root hub lost power or was reset
[ 84.018358] usb usb3: root hub lost power or was reset
[ 84.199309] usb 1-1: reset high-speed USB device number 2 using ehci-platform
[ 84.457446] OOM killer enabled.
[ 84.460679] Restarting tasks: Starting
[ 84.477407] Restarting tasks: Done
[ 84.487390] random: crng reseeded on system resumption
[ 84.499640] PM: suspend exit
[ 86.609639] ravb 11c30000.ethernet end0: Link is Up - 1Gbps/Full - flow
control off
root@smarc-rzg3s:~#
root@smarc-rzg3s:~#
root@smarc-rzg3s:~# uname -r
6.19.0-rc6-next-20260123-00021-g1e76e85a016d-dirty
root@smarc-rzg3s:~#
Note that I'm waking up from an wakeup button.
If you are trying to resume from serial wake interrupts, have you checked the
serial driver is prepard to handle this? Please check this driver on how the
resume is handled for wakup from serial device:
https://elixir.bootlin.com/linux/v6.19-rc5/source/drivers/tty/serial/atmel_serial.c#L1414
>
> LOGS:
> root@smarc-rzg3l:~# echo enabled > /sys/class/tty/ttySC3/power/wakeup
> echo N > /sys/module/printk/parameters/console_suspend
> root@smarc-rzg3l:~# echo N > /sys/module/printk/parameters/console_suspend
> root@smarc-rzg3l:~# echo 7 > /proc/sys/kernel/printk
> root@smarc-rzg3l:~# echo freeze > /sys/power/state
> [ 41.601992] PM: suspend entry (s2idle)
> [ 41.605979] Filesystems sync: 0.000 seconds
> [ 41.611261] Freezing user space processes
> [ 41.614848] Freezing user space processes completed (elapsed 0.003 seconds)
> [ 41.622676] OOM killer disabled.
> [ 41.625908] Freezing remaining freezable tasks
> [ 41.631642] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
> [ 41.640137] renesas-gbeth 11c30000.ethernet end0: Link is Down
>
>
> On my testing shows on RZ/G3L, we need to make DMA ACLK as non-PM clk for
> Making both s2idle and str to work on RZ/G3L.
Is there any RZ/G3L suspend to RAM support available on upstream kernel? On my
side, I'm doing the same set of steps on RZ/G3S. This is the output:
root@smarc-rzg3s:~# echo freeze > /sys/power/state
[ 299.431018] PM: suspend entry (s2idle)
[ 299.436111] Filesystems sync: 0.000 seconds
[ 299.452540] Freezing user space processes
[ 299.459432] Freezing user space processes completed (elapsed 0.006 seconds)
[ 299.466422] OOM killer disabled.
[ 299.469656] Freezing remaining freezable tasks
[ 299.475469] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
[ 299.550263] ravb 11c30000.ethernet end0: Link is Down
[ 302.112742] rzg3s-pcie-host 11e40000.pcie: PCIe link status [0x100014e]
[ 302.323225] nvme nvme0: 1/0/0 default/read/poll queues
[ 302.386270] Microchip KSZ9131 Gigabit PHY 11c30000.ethernet-ffffffff:07:
attached PHY driver (mii_bus:phy_addr=11c30000.ethernet-ffffffff:07, irq=59)
[ 302.470286] Microchip KSZ9131 Gigabit PHY 11c40000.ethernet-ffffffff:07:
attached PHY driver (mii_bus:phy_addr=11c40000.ethernet-ffffffff:07, irq=61)
[ 302.573319] usb usb2: root hub lost power or was reset
[ 302.578520] usb usb3: root hub lost power or was reset
[ 302.669350] usb usb4: root hub lost power or was reset
[ 302.674583] usb usb1: root hub lost power or was reset
[ 302.951468] usb 1-1: reset high-speed USB device number 2 using ehci-platform
[ 303.206055] OOM killer enabled.
[ 303.209315] Restarting tasks: Starting
[ 303.228380] Restarting tasks: Done
[ 303.236159] random: crng reseeded on system resumption
[ 303.247796] PM: suspend exit
[ 305.205604] ravb 11c30000.ethernet end0: Link is Up - 1Gbps/Full - flow
control off
root@smarc-rzg3s:~#
root@smarc-rzg3s:~# uname -r
6.19.0-rc6-next-20260123-00021-g1e76e85a016d
root@smarc-rzg3s:~#
And the patches I have on my tree:
1e76e85a016d (HEAD ->
claudiu/SSGRLPCSRC-1478/linux-next/dma-cyclic+ssi-using-it-prepare-for-upstream-v1)
arm64: dts: renesas: r9a07g044: Add dma properties for serial nodes
1a70b2015703 spi flash
d09caee93d5a dmaengine: sh: rz-dmac: Set the Link End (LE) bit on the last
descriptor
65073447cc2b ASoC: renesas: rz-ssi: Use generic PCM dmaengine APIs
8a3e41ac5a15 dmaengine: sh: rz-dmac: Add suspend to RAM support
63d57ebe24c9 dmaengine: sh: rz-dmac: Add cyclic DMA support
fc77f2366208 dmaengine: sh: rz-dmac: Drop the update of CHCTRL_SETEN in
channel->chctrl APIs
>
> if (pm_suspend_target_state == PM_SUSPEND_TO_IDLE)
> you need this check in suspend/resume not to turn off DMAACLK during s2idle.
Again, how is this turned off on suspend/resume if it's critical?
>
> Also, the callback has to be in non_irq phase so that CPU start getting IRQ's
> During sleep phase.
That could be moved there, if there are users of it.
Thank you,
Claudiu
^ permalink raw reply related [flat|nested] 31+ messages in thread
* RE: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-01-26 12:04 ` Claudiu Beznea
@ 2026-01-26 12:10 ` Biju Das
2026-01-26 12:39 ` Claudiu Beznea
0 siblings, 1 reply; 31+ messages in thread
From: Biju Das @ 2026-01-26 12:10 UTC (permalink / raw)
To: Claudiu.Beznea, vkoul@kernel.org, Prabhakar Mahadev Lad,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, p.zabel@pengutronix.de, geert+renesas@glider.be,
Fabrizio Castro
Cc: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-sound@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Claudiu Beznea
> -----Original Message-----
> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> Sent: 26 January 2026 12:05
> To: Biju Das <biju.das.jz@bp.renesas.com>; vkoul@kernel.org; Prabhakar Mahadev Lad <prabhakar.mahadev-
> lad.rj@bp.renesas.com>; lgirdwood@gmail.com; broonie@kernel.org; perex@perex.cz; tiwai@suse.com;
> p.zabel@pengutronix.de; geert+renesas@glider.be; Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> Cc: dmaengine@vger.kernel.org; linux-kernel@vger.kernel.org; linux-sound@vger.kernel.org; linux-
> renesas-soc@vger.kernel.org; Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>
> Hi,
>
> On 1/26/26 13:03, Biju Das wrote:
> > Hi Claudiu,
> >
> > Thanks for the patch.
> >
> >> -----Original Message-----
> >> From: Claudiu <claudiu.beznea@tuxon.dev>
> >> Sent: 26 January 2026 10:32
> >> Subject: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> >> support
> >>
> >> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> >>
> >> The Renesas RZ/G3S SoC supports a power saving mode in which power to
> >> most SoC components is turned off, including the DMA IP. Add suspend to RAM support to save and
> restore the DMA IP registers.
> >>
> >> Cyclic DMA channels require special handling. Since they can be
> >> paused and resumed during system suspend and resume, the driver
> >> restores additional registers for these channels during the resume
> >> phase. If a channel was not explicitly paused during suspend, the
> >> driver ensures that it is paused and resumed as part of the system suspend/resume flow. This might
> be the case of a serial device being used with no_console_suspend.
> >>
> >> For non-cyclic channels, the dev_pm_ops::prepare callback waits for
> >> all ongoing transfers to complete before allowing suspend-to-RAM to proceed.
> >>
> >> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> >> ---
> >> drivers/dma/sh/rz-dmac.c | 183 +++++++++++++++++++++++++++++++++++++--
> >> 1 file changed, 175 insertions(+), 8 deletions(-)
> >>
> >> diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
> >> index ab5f49a0b9f2..8f3e2719e639
> >> 100644
> >> --- a/drivers/dma/sh/rz-dmac.c
> >> +++ b/drivers/dma/sh/rz-dmac.c
> >> @@ -69,11 +69,15 @@ struct rz_dmac_desc {
> >> * enum rz_dmac_chan_status: RZ DMAC channel status
> >> * @RZ_DMAC_CHAN_STATUS_ENABLED: Channel is enabled
> >> * @RZ_DMAC_CHAN_STATUS_PAUSED: Channel is paused though DMA engine
> >> callbacks
> >> + * @RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL: Channel is paused through
> >> + driver internal logic
> >> + * @RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED: Channel was prepared for
> >> + system suspend
> >> * @RZ_DMAC_CHAN_STATUS_CYCLIC: Channel is cyclic
> >> */
> >> enum rz_dmac_chan_status {
> >> RZ_DMAC_CHAN_STATUS_ENABLED,
> >> RZ_DMAC_CHAN_STATUS_PAUSED,
> >> + RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL,
> >> + RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED,
> >> RZ_DMAC_CHAN_STATUS_CYCLIC,
> >> };
> >>
> >> @@ -94,6 +98,10 @@ struct rz_dmac_chan {
> >> u32 chctrl;
> >> int mid_rid;
> >>
> >> + struct {
> >> + u32 nxla;
> >> + } pm_state;
> >> +
> >> struct list_head ld_free;
> >> struct list_head ld_queue;
> >> struct list_head ld_active;
> >> @@ -1002,10 +1010,17 @@ static int rz_dmac_device_pause(struct dma_chan *chan)
> >> return rz_dmac_device_pause_set(channel,
> >> RZ_DMAC_CHAN_STATUS_PAUSED); }
> >>
> >> +static int rz_dmac_device_pause_internal(struct rz_dmac_chan
> >> +*channel) {
> >> + lockdep_assert_held(&channel->vc.lock);
> >> +
> >> + return rz_dmac_device_pause_set(channel,
> >> +RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL);
> >> +}
> >> +
> >> static int rz_dmac_device_resume_set(struct rz_dmac_chan *channel,
> >> enum rz_dmac_chan_status status) {
> >> - u32 val;
> >> + u32 val, chctrl;
> >> int ret;
> >>
> >> lockdep_assert_held(&channel->vc.lock);
> >> @@ -1013,14 +1028,33 @@ static int rz_dmac_device_resume_set(struct rz_dmac_chan *channel,
> >> if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED)))
> >> return 0;
> >>
> >> - rz_dmac_ch_writel(channel, CHCTRL_CLRSUS, CHCTRL, 1);
> >> - ret = read_poll_timeout_atomic(rz_dmac_ch_readl, val,
> >> - !(val & CHSTAT_SUS), 1, 1024, false,
> >> - channel, CHSTAT, 1);
> >> - if (ret)
> >> - return ret;
> >> + if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED)) {
> >> + /*
> >> + * We can be after a sleep state with power loss. If power was
> >> + * lost, the CHSTAT_SUS bit is zero. In this case, we need to
> >> + * enable the channel directly. Otherwise, just set the CLRSUS
> >> + * bit.
> >> + */
> >> + val = rz_dmac_ch_readl(channel, CHSTAT, 1);
> >> + if (val & CHSTAT_SUS)
> >> + chctrl = CHCTRL_CLRSUS;
> >> + else
> >> + chctrl = CHCTRL_SETEN;
> >> + } else {
> >> + chctrl = CHCTRL_CLRSUS;
> >> + }
> >> +
> >> + rz_dmac_ch_writel(channel, chctrl, CHCTRL, 1);
> >>
> >> - channel->status &= ~BIT(status);
> >> + if (chctrl & CHCTRL_CLRSUS) {
> >> + ret = read_poll_timeout_atomic(rz_dmac_ch_readl, val,
> >> + !(val & CHSTAT_SUS), 1, 1024, false,
> >> + channel, CHSTAT, 1);
> >> + if (ret)
> >> + return ret;
> >> + }
> >> +
> >> + channel->status &= ~(BIT(status) |
> >> +BIT(RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED));
> >>
> >> return 0;
> >> }
> >> @@ -1034,6 +1068,13 @@ static int rz_dmac_device_resume(struct dma_chan *chan)
> >> return rz_dmac_device_resume_set(channel,
> >> RZ_DMAC_CHAN_STATUS_PAUSED); }
> >>
> >> +static int rz_dmac_device_resume_internal(struct rz_dmac_chan
> >> +*channel) {
> >> + lockdep_assert_held(&channel->vc.lock);
> >> +
> >> + return rz_dmac_device_resume_set(channel,
> >> +RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL);
> >> +}
> >> +
> >> /*
> >> * -----------------------------------------------------------------------------
> >> * IRQ handling
> >> @@ -1438,6 +1479,131 @@ static void rz_dmac_remove(struct platform_device *pdev)
> >> pm_runtime_disable(&pdev->dev);
> >> }
> >>
> >> +static int rz_dmac_suspend_prepare(struct device *dev) {
> >> + struct rz_dmac *dmac = dev_get_drvdata(dev);
> >> +
> >> + for (unsigned int i = 0; i < dmac->n_channels; i++) {
> >> + struct rz_dmac_chan *channel = &dmac->channels[i];
> >> +
> >> + guard(spinlock_irqsave)(&channel->vc.lock);
> >> +
> >> + /* Wait for transfer completion, except in cyclic case. */
> >> + if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_ENABLED) &&
> >> + !(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)))
> >> + return -EAGAIN;
> >> + }
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +static void rz_dmac_suspend_recover(struct rz_dmac *dmac) {
> >> + for (unsigned int i = 0; i < dmac->n_channels; i++) {
> >> + struct rz_dmac_chan *channel = &dmac->channels[i];
> >> +
> >> + guard(spinlock_irqsave)(&channel->vc.lock);
> >> +
> >> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)))
> >> + continue;
> >> +
> >> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL)))
> >> + continue;
> >> +
> >> + rz_dmac_device_resume_internal(channel);
> >> + }
> >> +}
> >> +
> >> +static int rz_dmac_suspend(struct device *dev) {
> >> + struct rz_dmac *dmac = dev_get_drvdata(dev);
> >> + int ret;
> >> +
> >> + for (unsigned int i = 0; i < dmac->n_channels; i++) {
> >> + struct rz_dmac_chan *channel = &dmac->channels[i];
> >> +
> >> + guard(spinlock_irqsave)(&channel->vc.lock);
> >> +
> >> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)))
> >> + continue;
> >> +
> >> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED))) {
> >> + ret = rz_dmac_device_pause_internal(channel);
> >> + if (ret) {
> >> + dev_err(dev, "Failed to suspend channel %s\n",
> >> + dma_chan_name(&channel->vc.chan));
> >> + continue;
> >> + }
> >> + }
> >> +
> >> + channel->pm_state.nxla = rz_dmac_ch_readl(channel, NXLA, 1);
> >> + channel->status |= BIT(RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED);
> >> + }
> >> +
> >> + pm_runtime_put_sync(dmac->dev);
> >> +
> >> + ret = reset_control_assert(dmac->rstc);
> >> + if (ret) {
> >> + pm_runtime_resume_and_get(dmac->dev);
> >> + rz_dmac_suspend_recover(dmac);
> >> + }
> >> +
> >
> >
> > This patch breaks, s2idle in RZ/G3L as it turns off DMA ACLK and IRQ's
> > are not routed to CPU for wakeup.
>
> Is this particular patch the one that explicitly breaks it? Is there any mainline PM support available
> for RZ/G3L? Can it be fixed along with the RZ/G3L support, if any, as I don't have the board to test
> it?
Maybe your TF-A is enabling DMAACLK during resume. Can you check that mean time, I will check what you have mentioned
Here?
Cheers,
Biju
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-01-26 12:10 ` Biju Das
@ 2026-01-26 12:39 ` Claudiu Beznea
2026-01-26 12:51 ` Biju Das
0 siblings, 1 reply; 31+ messages in thread
From: Claudiu Beznea @ 2026-01-26 12:39 UTC (permalink / raw)
To: Biju Das, vkoul@kernel.org, Prabhakar Mahadev Lad,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, p.zabel@pengutronix.de, geert+renesas@glider.be,
Fabrizio Castro
Cc: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-sound@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Claudiu Beznea
On 1/26/26 14:10, Biju Das wrote:
>
>
>> -----Original Message-----
>> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
>> Sent: 26 January 2026 12:05
>> To: Biju Das <biju.das.jz@bp.renesas.com>; vkoul@kernel.org; Prabhakar Mahadev Lad <prabhakar.mahadev-
>> lad.rj@bp.renesas.com>; lgirdwood@gmail.com; broonie@kernel.org; perex@perex.cz; tiwai@suse.com;
>> p.zabel@pengutronix.de; geert+renesas@glider.be; Fabrizio Castro <fabrizio.castro.jz@renesas.com>
>> Cc: dmaengine@vger.kernel.org; linux-kernel@vger.kernel.org; linux-sound@vger.kernel.org; linux-
>> renesas-soc@vger.kernel.org; Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>>
>> Hi,
>>
>> On 1/26/26 13:03, Biju Das wrote:
>>> Hi Claudiu,
>>>
>>> Thanks for the patch.
>>>
>>>> -----Original Message-----
>>>> From: Claudiu <claudiu.beznea@tuxon.dev>
>>>> Sent: 26 January 2026 10:32
>>>> Subject: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
>>>> support
>>>>
>>>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>>>
>>>> The Renesas RZ/G3S SoC supports a power saving mode in which power to
>>>> most SoC components is turned off, including the DMA IP. Add suspend to RAM support to save and
>> restore the DMA IP registers.
>>>>
>>>> Cyclic DMA channels require special handling. Since they can be
>>>> paused and resumed during system suspend and resume, the driver
>>>> restores additional registers for these channels during the resume
>>>> phase. If a channel was not explicitly paused during suspend, the
>>>> driver ensures that it is paused and resumed as part of the system suspend/resume flow. This might
>> be the case of a serial device being used with no_console_suspend.
>>>>
>>>> For non-cyclic channels, the dev_pm_ops::prepare callback waits for
>>>> all ongoing transfers to complete before allowing suspend-to-RAM to proceed.
>>>>
>>>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>>> ---
>>>> drivers/dma/sh/rz-dmac.c | 183 +++++++++++++++++++++++++++++++++++++--
>>>> 1 file changed, 175 insertions(+), 8 deletions(-)
>>>>
>>>> diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
>>>> index ab5f49a0b9f2..8f3e2719e639
>>>> +
>>>> + pm_runtime_put_sync(dmac->dev);
>>>> +
>>>> + ret = reset_control_assert(dmac->rstc);
>>>> + if (ret) {
>>>> + pm_runtime_resume_and_get(dmac->dev);
>>>> + rz_dmac_suspend_recover(dmac);
>>>> + }
>>>> +
>>>
>>>
>>> This patch breaks, s2idle in RZ/G3L as it turns off DMA ACLK and IRQ's
>>> are not routed to CPU for wakeup.
>>
>> Is this particular patch the one that explicitly breaks it? Is there any mainline PM support available
>> for RZ/G3L? Can it be fixed along with the RZ/G3L support, if any, as I don't have the board to test
>> it?
>
> Maybe your TF-A is enabling DMAACLK during resume. Can you check that mean time, I will check what you have mentioned
> Here?
>
You used "freeze" in your example. Same did I to check your usecase. That
suspend type don't involve TF-A (unless something changes and I'm not aware of).
Thank you,
Claudiu
^ permalink raw reply [flat|nested] 31+ messages in thread
* RE: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-01-26 12:39 ` Claudiu Beznea
@ 2026-01-26 12:51 ` Biju Das
2026-01-26 13:06 ` Biju Das
2026-01-26 13:07 ` Claudiu Beznea
0 siblings, 2 replies; 31+ messages in thread
From: Biju Das @ 2026-01-26 12:51 UTC (permalink / raw)
To: Claudiu.Beznea, vkoul@kernel.org, Prabhakar Mahadev Lad,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, p.zabel@pengutronix.de, geert+renesas@glider.be,
Fabrizio Castro
Cc: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-sound@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Claudiu Beznea
Hi Claudiu,
> -----Original Message-----
> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> Sent: 26 January 2026 12:39
> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>
>
>
> On 1/26/26 14:10, Biju Das wrote:
> >
> >
> >> -----Original Message-----
> >> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> >> Sent: 26 January 2026 12:05
> >> To: Biju Das <biju.das.jz@bp.renesas.com>; vkoul@kernel.org;
> >> Prabhakar Mahadev Lad <prabhakar.mahadev- lad.rj@bp.renesas.com>;
> >> lgirdwood@gmail.com; broonie@kernel.org; perex@perex.cz;
> >> tiwai@suse.com; p.zabel@pengutronix.de; geert+renesas@glider.be;
> >> Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> >> Cc: dmaengine@vger.kernel.org; linux-kernel@vger.kernel.org;
> >> linux-sound@vger.kernel.org; linux- renesas-soc@vger.kernel.org;
> >> Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> >> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> >> support
> >>
> >> Hi,
> >>
> >> On 1/26/26 13:03, Biju Das wrote:
> >>> Hi Claudiu,
> >>>
> >>> Thanks for the patch.
> >>>
> >>>> -----Original Message-----
> >>>> From: Claudiu <claudiu.beznea@tuxon.dev>
> >>>> Sent: 26 January 2026 10:32
> >>>> Subject: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> >>>> support
> >>>>
> >>>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> >>>>
> >>>> The Renesas RZ/G3S SoC supports a power saving mode in which power
> >>>> to most SoC components is turned off, including the DMA IP. Add
> >>>> suspend to RAM support to save and
> >> restore the DMA IP registers.
> >>>>
> >>>> Cyclic DMA channels require special handling. Since they can be
> >>>> paused and resumed during system suspend and resume, the driver
> >>>> restores additional registers for these channels during the resume
> >>>> phase. If a channel was not explicitly paused during suspend, the
> >>>> driver ensures that it is paused and resumed as part of the system
> >>>> suspend/resume flow. This might
> >> be the case of a serial device being used with no_console_suspend.
> >>>>
> >>>> For non-cyclic channels, the dev_pm_ops::prepare callback waits for
> >>>> all ongoing transfers to complete before allowing suspend-to-RAM to proceed.
> >>>>
> >>>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> >>>> ---
> >>>> drivers/dma/sh/rz-dmac.c | 183 +++++++++++++++++++++++++++++++++++++--
> >>>> 1 file changed, 175 insertions(+), 8 deletions(-)
> >>>>
> >>>> diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
> >>>> index ab5f49a0b9f2..8f3e2719e639
> >>>> +
> >>>> + pm_runtime_put_sync(dmac->dev);
> >>>> +
> >>>> + ret = reset_control_assert(dmac->rstc);
> >>>> + if (ret) {
> >>>> + pm_runtime_resume_and_get(dmac->dev);
> >>>> + rz_dmac_suspend_recover(dmac);
> >>>> + }
> >>>> +
> >>>
> >>>
> >>> This patch breaks, s2idle in RZ/G3L as it turns off DMA ACLK and
> >>> IRQ's are not routed to CPU for wakeup.
> >>
> >> Is this particular patch the one that explicitly breaks it? Is there
> >> any mainline PM support available for RZ/G3L? Can it be fixed along
> >> with the RZ/G3L support, if any, as I don't have the board to test it?
> >
> > Maybe your TF-A is enabling DMAACLK during resume. Can you check that
> > mean time, I will check what you have mentioned Here?
> >
>
> You used "freeze" in your example. Same did I to check your usecase. That suspend type don't involve
> TF-A (unless something changes and I'm not aware of).
>
Looks like reset assert in suspend() is the issue, not the clk.
echo N > /sys/module/printk/parameters/console_suspend
root@smarc-rzg3l:~# echo 7 > /proc/sys/kernel/printk
root@smarc-rzg3l:~#
root@smarc-rzg3l:~#
root@smarc-rzg3l:~# echo mem > /sys/power/state
[ 57.103165] PM: suspend entry (deep)
[ 57.106929] Filesystems sync: 0.000 seconds
[ 57.112372] Freezing user space processes
[ 57.114782] Freezing user space processes completed (elapsed 0.002 seconds)
[ 57.123730] OOM killer disabled.
[ 57.126964] Freezing remaining freezable tasks
[ 57.132691] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
[ 57.141140] renesas-gbeth 11c30000.ethernet end0: Link is Down
[ 57.148638] rzg2l_cpg_pm_suspend(): CLK_ON 0x514/gic_gicclk 1
[ 57.154428] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_clk 2
[ 57.160032] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_pclk 2
[ 57.165687] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_aclk 1
[ 57.171339] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_pclk 1
[ 57.177000] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_axi 30c0
[ 57.183174] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_chi 30c0
[ 57.189347] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_i 30c0
[ 57.195258] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_i 30c0
[ 57.201169] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_180_i 30c0
[ 57.207426] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_180_i 30c0
[ 57.213684] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rmii_i 30c0
[ 57.219774] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_ptp_ref_i 30c0
[ 57.226120] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_axi 30c0
[ 57.232290] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_chi 30c0
[ 57.238459] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_i 30c0
[ 57.244369] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_i 30c0
[ 57.250279] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_180_i 30c0
[ 57.256540] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_180_i 30c0
[ 57.262798] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rmii_i 30c0
[ 57.268884] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_ptp_ref_i 30c0
[ 57.275229] rzg2l_cpg_pm_suspend(): CLK_ON 0x584/scif0_clk_pck 1
[ 57.281228] rzg2l_cpg_pm_suspend(): CLK_ON 0x598/gpio_hclk 1
[ 57.286997] Disabling non-boot CPUs ...
[ 57.292890] psci: CPU3 killed (polled 0 ms)
[ 57.300567] psci: CPU2 killed (polled 0 ms)
[ 57.308116] psci: CPU1 killed (polled 0 ms)
NOTICE: BL2: v2.10.5(release):2.10.5/rzg3l_1.0.0
NOTICE: BL2: Built : 08:36:10, Jan 20 2026
INFO: BL2: Doing platform setup
INFO: Configuring TrustZone Controller
INFO: Total 3 regions set.
INFO: Configuring TrustZone Controller
INFO: Total 1 regions set.
INFO: Configuring TrustZone Controller
INFO: Total 1 regions set.
INFO: eMMC boot from partition 1
INFO: Loading image id=39 at address 0x44428
INFO: emmcdrv_block_len: len: 0x00001000
INFO: Load dst=0x44428 src=(p:1)0x260000(4864) len=0x1000(8)
INFO: Image id=39 loaded: 0x44428 - 0x45428
INFO: DDR: Retention Exit (Rev. 02.05)
NOTICE: BL2: SYS_LSI_MODE: 0x12051
NOTICE: BL2: SYS_LSI_DEVID: 0x87d9447
INFO: BL2: Skip loading image id 3
INFO: BL2: Skip loading image id 5
NOTICE: BL2: Booting BL31
INFO: Entry point address = 0x44000000
INFO: SPSR = 0x3cd
INFO: GICv3 without legacy support detected.
INFO: ARM GICv3 driver initialized in EL3
[ 57.313836] Enabling non-boot CPUs ...
[ 57.319883] Detected VIPT I-cache on CPU1
[ 57.319942] GICv3: CPU1: found redistributor 100 region 0:0x0000000012460000
[ 57.319992] CPU1: Booted secondary processor 0x0000000100 [0x412fd050]
[ 57.320755] CPU1 is up
[ 57.341066] Detected VIPT I-cache on CPU2
[ 57.341112] GICv3: CPU2: found redistributor 200 region 0:0x0000000012480000
[ 57.341151] CPU2: Booted secondary processor 0x0000000200 [0x412fd050]
[ 57.341886] CPU2 is up
[ 57.362133] Detected VIPT I-cache on CPU3
[ 57.362177] GICv3: CPU3: found redistributor 300 region 0:0x00000000124a0000
[ 57.362213] CPU3: Booted secondary processor 0x0000000300 [0x412fd050]
[ 57.362975] CPU3 is up
[ 57.383339] rzg2l_mod_clock_init_mstop(): CLK_ON 0x514/gic_gicclk 1
[ 57.389666] rzg2l_mod_clock_init_mstop(): CLK_ON 0x518/ia55_clk 3
[ 57.395803] rzg2l_mod_clock_init_mstop(): CLK_ON 0x518/ia55_pclk 3
[ 57.402038] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_clk_axi 3fff
[ 57.408784] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_clk_chi 3fff
[ 57.415544] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_rmii_i 3fff
[ 57.422217] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_ptp_ref_i 3fff
[ 57.429143] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_clk_axi 3fff
[ 57.435895] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_clk_chi 3fff
[ 57.442656] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_rmii_i 3fff
[ 57.449314] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_ptp_ref_i 3fff
[ 57.456240] rzg2l_mod_clock_init_mstop(): CLK_ON 0x584/scif0_clk_pck 1
[ 57.462818] rzg2l_mod_clock_init_mstop(): CLK_ON 0x598/gpio_hclk 1
[ 57.469039] ###########rzg2l_cpg_resume ########0/0
[ 57.474068] dwmac4: Master AXI performs fixed burst length
[ 57.484472] renesas-gbeth 11c30000.ethernet end0: No Safety Features support found
[ 57.492079] renesas-gbeth 11c30000.ethernet end0: IEEE 1588-2008 Advanced Timestamp supported
[ 57.500658] renesas-gbeth 11c30000.ethernet end0: configuring for phy/rgmii-id link mode
[ 57.525097] dwmac4: Master AXI performs fixed burst length
[ 57.530615] renesas-gbeth 11c40000.ethernet end1: No Safety Features support found
[ 57.538201] renesas-gbeth 11c40000.ethernet end1: IEEE 1588-2008 Advanced Timestamp supported
[ 57.546764] renesas-gbeth 11c40000.ethernet end1: configuring for phy/rgmii-id link mode
[ 57.557533] OOM killer enabled.
[ 57.560668] Restarting tasks: Starting
[ 57.565020] Restarting tasks: Done
[ 57.568586] random: crng reseeded on system resumption
[ 57.573929] PM: suspend exit
root@smarc-rzg3l:~# [ 60.574926] renesas-gbeth 11c30000.ethernet end0: Link is Up - 1Gbps/Full - flow control rx/tx
root@smarc-rzg3l:~#
root@smarc-rzg3l:~# echo enabled > /sys/class/tty/ttySC3/power/wakeup
root@smarc-rzg3l:~# echo freeze > /sys/power/state
[ 86.957826] PM: suspend entry (s2idle)
[ 86.961742] Filesystems sync: 0.000 seconds
[ 86.966381] Freezing user space processes
[ 86.972014] Freezing user space processes completed (elapsed 0.001 seconds)
[ 86.979011] OOM killer disabled.
[ 86.982248] Freezing remaining freezable tasks
[ 86.987966] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
[ 86.996469] renesas-gbeth 11c30000.ethernet end0: Link is Down
[ 87.004128] rzg2l_cpg_pm_suspend(): CLK_ON 0x514/gic_gicclk 1
[ 87.009913] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_clk 3
[ 87.015484] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_pclk 3
[ 87.021140] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_aclk 1
[ 87.026795] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_pclk 1
[ 87.032448] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_axi 30c0
[ 87.038620] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_chi 30c0
[ 87.044792] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_i 30c0
[ 87.050704] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_i 30c0
[ 87.056616] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_180_i 30c0
[ 87.062873] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_180_i 30c0
[ 87.069130] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rmii_i 30c0
[ 87.075218] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_ptp_ref_i 30c0
[ 87.081562] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_axi 30c0
[ 87.087733] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_chi 30c0
[ 87.093917] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_i 30c0
[ 87.099829] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_i 30c0
[ 87.105741] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_180_i 30c0
[ 87.111999] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_180_i 30c0
[ 87.118258] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rmii_i 30c0
[ 87.124342] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_ptp_ref_i 30c0
[ 87.130688] rzg2l_cpg_pm_suspend(): CLK_ON 0x584/scif0_clk_pck 1
[ 87.136687] rzg2l_cpg_pm_suspend(): CLK_ON 0x598/gpio_hclk 1
No IRQ's in s2idle.
Cheers,
Biju
^ permalink raw reply [flat|nested] 31+ messages in thread
* RE: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-01-26 12:51 ` Biju Das
@ 2026-01-26 13:06 ` Biju Das
2026-01-26 13:07 ` Claudiu Beznea
1 sibling, 0 replies; 31+ messages in thread
From: Biju Das @ 2026-01-26 13:06 UTC (permalink / raw)
To: Biju Das, Claudiu.Beznea, vkoul@kernel.org, Prabhakar Mahadev Lad,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, p.zabel@pengutronix.de, geert+renesas@glider.be,
Fabrizio Castro
Cc: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-sound@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Claudiu Beznea
> -----Original Message-----
> From: Biju Das <biju.das.jz@bp.renesas.com>
> Sent: 26 January 2026 12:51
> To: Claudiu.Beznea <claudiu.beznea@tuxon.dev>; vkoul@kernel.org; Prabhakar Mahadev Lad
> <prabhakar.mahadev-lad.rj@bp.renesas.com>; lgirdwood@gmail.com; broonie@kernel.org; perex@perex.cz;
> tiwai@suse.com; p.zabel@pengutronix.de; geert+renesas@glider.be; Fabrizio Castro
> <fabrizio.castro.jz@renesas.com>
> Cc: dmaengine@vger.kernel.org; linux-kernel@vger.kernel.org; linux-sound@vger.kernel.org; linux-
> renesas-soc@vger.kernel.org; Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> Subject: RE: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>
> Hi Claudiu,
>
>
> > -----Original Message-----
> > From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> > Sent: 26 January 2026 12:39
> > Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> > support
> >
> >
> >
> > On 1/26/26 14:10, Biju Das wrote:
> > >
> > >
> > >> -----Original Message-----
> > >> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> > >> Sent: 26 January 2026 12:05
> > >> To: Biju Das <biju.das.jz@bp.renesas.com>; vkoul@kernel.org;
> > >> Prabhakar Mahadev Lad <prabhakar.mahadev- lad.rj@bp.renesas.com>;
> > >> lgirdwood@gmail.com; broonie@kernel.org; perex@perex.cz;
> > >> tiwai@suse.com; p.zabel@pengutronix.de; geert+renesas@glider.be;
> > >> Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > >> Cc: dmaengine@vger.kernel.org; linux-kernel@vger.kernel.org;
> > >> linux-sound@vger.kernel.org; linux- renesas-soc@vger.kernel.org;
> > >> Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> > >> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> > >> support
> > >>
> > >> Hi,
> > >>
> > >> On 1/26/26 13:03, Biju Das wrote:
> > >>> Hi Claudiu,
> > >>>
> > >>> Thanks for the patch.
> > >>>
> > >>>> -----Original Message-----
> > >>>> From: Claudiu <claudiu.beznea@tuxon.dev>
> > >>>> Sent: 26 January 2026 10:32
> > >>>> Subject: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> > >>>> support
> > >>>>
> > >>>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> > >>>>
> > >>>> The Renesas RZ/G3S SoC supports a power saving mode in which
> > >>>> power to most SoC components is turned off, including the DMA IP.
> > >>>> Add suspend to RAM support to save and
> > >> restore the DMA IP registers.
> > >>>>
> > >>>> Cyclic DMA channels require special handling. Since they can be
> > >>>> paused and resumed during system suspend and resume, the driver
> > >>>> restores additional registers for these channels during the
> > >>>> resume phase. If a channel was not explicitly paused during
> > >>>> suspend, the driver ensures that it is paused and resumed as part
> > >>>> of the system suspend/resume flow. This might
> > >> be the case of a serial device being used with no_console_suspend.
> > >>>>
> > >>>> For non-cyclic channels, the dev_pm_ops::prepare callback waits
> > >>>> for all ongoing transfers to complete before allowing suspend-to-RAM to proceed.
> > >>>>
> > >>>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> > >>>> ---
> > >>>> drivers/dma/sh/rz-dmac.c | 183 +++++++++++++++++++++++++++++++++++++--
> > >>>> 1 file changed, 175 insertions(+), 8 deletions(-)
> > >>>>
> > >>>> diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
> > >>>> index ab5f49a0b9f2..8f3e2719e639
> > >>>> +
> > >>>> + pm_runtime_put_sync(dmac->dev);
> > >>>> +
> > >>>> + ret = reset_control_assert(dmac->rstc);
> > >>>> + if (ret) {
> > >>>> + pm_runtime_resume_and_get(dmac->dev);
> > >>>> + rz_dmac_suspend_recover(dmac);
> > >>>> + }
> > >>>> +
> > >>>
> > >>>
> > >>> This patch breaks, s2idle in RZ/G3L as it turns off DMA ACLK and
> > >>> IRQ's are not routed to CPU for wakeup.
> > >>
> > >> Is this particular patch the one that explicitly breaks it? Is
> > >> there any mainline PM support available for RZ/G3L? Can it be fixed
> > >> along with the RZ/G3L support, if any, as I don't have the board to test it?
> > >
> > > Maybe your TF-A is enabling DMAACLK during resume. Can you check
> > > that mean time, I will check what you have mentioned Here?
> > >
> >
> > You used "freeze" in your example. Same did I to check your usecase.
> > That suspend type don't involve TF-A (unless something changes and I'm not aware of).
> >
>
> Looks like reset assert in suspend() is the issue, not the clk.
>
> echo N > /sys/module/printk/parameters/console_suspend
> root@smarc-rzg3l:~# echo 7 > /proc/sys/kernel/printk root@smarc-rzg3l:~# root@smarc-rzg3l:~#
> root@smarc-rzg3l:~# echo mem > /sys/power/state
> [ 57.103165] PM: suspend entry (deep)
> [ 57.106929] Filesystems sync: 0.000 seconds
> [ 57.112372] Freezing user space processes
> [ 57.114782] Freezing user space processes completed (elapsed 0.002 seconds)
> [ 57.123730] OOM killer disabled.
> [ 57.126964] Freezing remaining freezable tasks
> [ 57.132691] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
> [ 57.141140] renesas-gbeth 11c30000.ethernet end0: Link is Down
> [ 57.148638] rzg2l_cpg_pm_suspend(): CLK_ON 0x514/gic_gicclk 1
> [ 57.154428] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_clk 2
> [ 57.160032] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_pclk 2
> [ 57.165687] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_aclk 1
> [ 57.171339] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_pclk 1
> [ 57.177000] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_axi 30c0
> [ 57.183174] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_chi 30c0
> [ 57.189347] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_i 30c0
> [ 57.195258] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_i 30c0
> [ 57.201169] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_180_i 30c0
> [ 57.207426] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_180_i 30c0
> [ 57.213684] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rmii_i 30c0
> [ 57.219774] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_ptp_ref_i 30c0
> [ 57.226120] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_axi 30c0
> [ 57.232290] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_chi 30c0
> [ 57.238459] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_i 30c0
> [ 57.244369] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_i 30c0
> [ 57.250279] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_180_i 30c0
> [ 57.256540] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_180_i 30c0
> [ 57.262798] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rmii_i 30c0
> [ 57.268884] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_ptp_ref_i 30c0
> [ 57.275229] rzg2l_cpg_pm_suspend(): CLK_ON 0x584/scif0_clk_pck 1
> [ 57.281228] rzg2l_cpg_pm_suspend(): CLK_ON 0x598/gpio_hclk 1
> [ 57.286997] Disabling non-boot CPUs ...
> [ 57.292890] psci: CPU3 killed (polled 0 ms)
> [ 57.300567] psci: CPU2 killed (polled 0 ms)
> [ 57.308116] psci: CPU1 killed (polled 0 ms)
> NOTICE: BL2: v2.10.5(release):2.10.5/rzg3l_1.0.0
> NOTICE: BL2: Built : 08:36:10, Jan 20 2026
> INFO: BL2: Doing platform setup
> INFO: Configuring TrustZone Controller
> INFO: Total 3 regions set.
> INFO: Configuring TrustZone Controller
> INFO: Total 1 regions set.
> INFO: Configuring TrustZone Controller
> INFO: Total 1 regions set.
> INFO: eMMC boot from partition 1
> INFO: Loading image id=39 at address 0x44428
> INFO: emmcdrv_block_len: len: 0x00001000
> INFO: Load dst=0x44428 src=(p:1)0x260000(4864) len=0x1000(8)
> INFO: Image id=39 loaded: 0x44428 - 0x45428
> INFO: DDR: Retention Exit (Rev. 02.05)
> NOTICE: BL2: SYS_LSI_MODE: 0x12051
> NOTICE: BL2: SYS_LSI_DEVID: 0x87d9447
> INFO: BL2: Skip loading image id 3
> INFO: BL2: Skip loading image id 5
> NOTICE: BL2: Booting BL31
> INFO: Entry point address = 0x44000000
> INFO: SPSR = 0x3cd
> INFO: GICv3 without legacy support detected.
> INFO: ARM GICv3 driver initialized in EL3
> [ 57.313836] Enabling non-boot CPUs ...
> [ 57.319883] Detected VIPT I-cache on CPU1
> [ 57.319942] GICv3: CPU1: found redistributor 100 region 0:0x0000000012460000
> [ 57.319992] CPU1: Booted secondary processor 0x0000000100 [0x412fd050]
> [ 57.320755] CPU1 is up
> [ 57.341066] Detected VIPT I-cache on CPU2
> [ 57.341112] GICv3: CPU2: found redistributor 200 region 0:0x0000000012480000
> [ 57.341151] CPU2: Booted secondary processor 0x0000000200 [0x412fd050]
> [ 57.341886] CPU2 is up
> [ 57.362133] Detected VIPT I-cache on CPU3
> [ 57.362177] GICv3: CPU3: found redistributor 300 region 0:0x00000000124a0000
> [ 57.362213] CPU3: Booted secondary processor 0x0000000300 [0x412fd050]
> [ 57.362975] CPU3 is up
> [ 57.383339] rzg2l_mod_clock_init_mstop(): CLK_ON 0x514/gic_gicclk 1
> [ 57.389666] rzg2l_mod_clock_init_mstop(): CLK_ON 0x518/ia55_clk 3
> [ 57.395803] rzg2l_mod_clock_init_mstop(): CLK_ON 0x518/ia55_pclk 3
> [ 57.402038] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_clk_axi 3fff
> [ 57.408784] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_clk_chi 3fff
> [ 57.415544] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_rmii_i 3fff
> [ 57.422217] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_ptp_ref_i 3fff
> [ 57.429143] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_clk_axi 3fff
> [ 57.435895] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_clk_chi 3fff
> [ 57.442656] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_rmii_i 3fff
> [ 57.449314] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_ptp_ref_i 3fff
> [ 57.456240] rzg2l_mod_clock_init_mstop(): CLK_ON 0x584/scif0_clk_pck 1
> [ 57.462818] rzg2l_mod_clock_init_mstop(): CLK_ON 0x598/gpio_hclk 1
> [ 57.469039] ###########rzg2l_cpg_resume ########0/0
> [ 57.474068] dwmac4: Master AXI performs fixed burst length
> [ 57.484472] renesas-gbeth 11c30000.ethernet end0: No Safety Features support found
> [ 57.492079] renesas-gbeth 11c30000.ethernet end0: IEEE 1588-2008 Advanced Timestamp supported
> [ 57.500658] renesas-gbeth 11c30000.ethernet end0: configuring for phy/rgmii-id link mode
> [ 57.525097] dwmac4: Master AXI performs fixed burst length
> [ 57.530615] renesas-gbeth 11c40000.ethernet end1: No Safety Features support found
> [ 57.538201] renesas-gbeth 11c40000.ethernet end1: IEEE 1588-2008 Advanced Timestamp supported
> [ 57.546764] renesas-gbeth 11c40000.ethernet end1: configuring for phy/rgmii-id link mode
> [ 57.557533] OOM killer enabled.
> [ 57.560668] Restarting tasks: Starting
> [ 57.565020] Restarting tasks: Done
> [ 57.568586] random: crng reseeded on system resumption
> [ 57.573929] PM: suspend exit
> root@smarc-rzg3l:~# [ 60.574926] renesas-gbeth 11c30000.ethernet end0: Link is Up - 1Gbps/Full -
> flow control rx/tx
>
> root@smarc-rzg3l:~#
> root@smarc-rzg3l:~# echo enabled > /sys/class/tty/ttySC3/power/wakeup
> root@smarc-rzg3l:~# echo freeze > /sys/power/state
> [ 86.957826] PM: suspend entry (s2idle)
> [ 86.961742] Filesystems sync: 0.000 seconds
> [ 86.966381] Freezing user space processes
> [ 86.972014] Freezing user space processes completed (elapsed 0.001 seconds)
> [ 86.979011] OOM killer disabled.
> [ 86.982248] Freezing remaining freezable tasks
> [ 86.987966] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
> [ 86.996469] renesas-gbeth 11c30000.ethernet end0: Link is Down
> [ 87.004128] rzg2l_cpg_pm_suspend(): CLK_ON 0x514/gic_gicclk 1
> [ 87.009913] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_clk 3
> [ 87.015484] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_pclk 3
> [ 87.021140] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_aclk 1
> [ 87.026795] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_pclk 1
> [ 87.032448] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_axi 30c0
> [ 87.038620] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_chi 30c0
> [ 87.044792] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_i 30c0
> [ 87.050704] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_i 30c0
> [ 87.056616] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_180_i 30c0
> [ 87.062873] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_180_i 30c0
> [ 87.069130] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rmii_i 30c0
> [ 87.075218] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_ptp_ref_i 30c0
> [ 87.081562] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_axi 30c0
> [ 87.087733] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_chi 30c0
> [ 87.093917] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_i 30c0
> [ 87.099829] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_i 30c0
> [ 87.105741] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_180_i 30c0
> [ 87.111999] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_180_i 30c0
> [ 87.118258] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rmii_i 30c0
> [ 87.124342] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_ptp_ref_i 30c0
> [ 87.130688] rzg2l_cpg_pm_suspend(): CLK_ON 0x584/scif0_clk_pck 1
> [ 87.136687] rzg2l_cpg_pm_suspend(): CLK_ON 0x598/gpio_hclk 1
>
> No IRQ's in s2idle.
Also STR does not work with critical clk as it is not turning on DMAAclk during resume.
Cheers,
Biju
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-01-26 12:51 ` Biju Das
2026-01-26 13:06 ` Biju Das
@ 2026-01-26 13:07 ` Claudiu Beznea
2026-01-26 13:12 ` Biju Das
1 sibling, 1 reply; 31+ messages in thread
From: Claudiu Beznea @ 2026-01-26 13:07 UTC (permalink / raw)
To: Biju Das, vkoul@kernel.org, Prabhakar Mahadev Lad,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, p.zabel@pengutronix.de, geert+renesas@glider.be,
Fabrizio Castro
Cc: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-sound@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Claudiu Beznea
On 1/26/26 14:51, Biju Das wrote:
> Hi Claudiu,
>
>
>> -----Original Message-----
>> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
>> Sent: 26 January 2026 12:39
>> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>>
>>
>>
>> On 1/26/26 14:10, Biju Das wrote:
>>>
>>>
>>>> -----Original Message-----
>>>> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
>>>> Sent: 26 January 2026 12:05
>>>> To: Biju Das <biju.das.jz@bp.renesas.com>; vkoul@kernel.org;
>>>> Prabhakar Mahadev Lad <prabhakar.mahadev- lad.rj@bp.renesas.com>;
>>>> lgirdwood@gmail.com; broonie@kernel.org; perex@perex.cz;
>>>> tiwai@suse.com; p.zabel@pengutronix.de; geert+renesas@glider.be;
>>>> Fabrizio Castro <fabrizio.castro.jz@renesas.com>
>>>> Cc: dmaengine@vger.kernel.org; linux-kernel@vger.kernel.org;
>>>> linux-sound@vger.kernel.org; linux- renesas-soc@vger.kernel.org;
>>>> Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>>> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
>>>> support
>>>>
>>>> Hi,
>>>>
>>>> On 1/26/26 13:03, Biju Das wrote:
>>>>> Hi Claudiu,
>>>>>
>>>>> Thanks for the patch.
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: Claudiu <claudiu.beznea@tuxon.dev>
>>>>>> Sent: 26 January 2026 10:32
>>>>>> Subject: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
>>>>>> support
>>>>>>
>>>>>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>>>>>
>>>>>> The Renesas RZ/G3S SoC supports a power saving mode in which power
>>>>>> to most SoC components is turned off, including the DMA IP. Add
>>>>>> suspend to RAM support to save and
>>>> restore the DMA IP registers.
>>>>>>
>>>>>> Cyclic DMA channels require special handling. Since they can be
>>>>>> paused and resumed during system suspend and resume, the driver
>>>>>> restores additional registers for these channels during the resume
>>>>>> phase. If a channel was not explicitly paused during suspend, the
>>>>>> driver ensures that it is paused and resumed as part of the system
>>>>>> suspend/resume flow. This might
>>>> be the case of a serial device being used with no_console_suspend.
>>>>>>
>>>>>> For non-cyclic channels, the dev_pm_ops::prepare callback waits for
>>>>>> all ongoing transfers to complete before allowing suspend-to-RAM to proceed.
>>>>>>
>>>>>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>>>>> ---
>>>>>> drivers/dma/sh/rz-dmac.c | 183 +++++++++++++++++++++++++++++++++++++--
>>>>>> 1 file changed, 175 insertions(+), 8 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
>>>>>> index ab5f49a0b9f2..8f3e2719e639
>>>>>> +
>>>>>> + pm_runtime_put_sync(dmac->dev);
>>>>>> +
>>>>>> + ret = reset_control_assert(dmac->rstc);
>>>>>> + if (ret) {
>>>>>> + pm_runtime_resume_and_get(dmac->dev);
>>>>>> + rz_dmac_suspend_recover(dmac);
>>>>>> + }
>>>>>> +
>>>>>
>>>>>
>>>>> This patch breaks, s2idle in RZ/G3L as it turns off DMA ACLK and
>>>>> IRQ's are not routed to CPU for wakeup.
>>>>
>>>> Is this particular patch the one that explicitly breaks it? Is there
>>>> any mainline PM support available for RZ/G3L? Can it be fixed along
>>>> with the RZ/G3L support, if any, as I don't have the board to test it?
>>>
>>> Maybe your TF-A is enabling DMAACLK during resume. Can you check that
>>> mean time, I will check what you have mentioned Here?
>>>
>>
>> You used "freeze" in your example. Same did I to check your usecase. That suspend type don't involve
>> TF-A (unless something changes and I'm not aware of).
>>
>
> Looks like reset assert in suspend() is the issue, not the clk.
How did you concluded this? Do we know if the wakeup interrupt is
configured properly? Could you point to the code configuring the wakeup
interrupt?
Also, could you please respond to the questions on the previous emails I
addressed? It helps understanding the problem.
>
> echo N > /sys/module/printk/parameters/console_suspend
> root@smarc-rzg3l:~# echo 7 > /proc/sys/kernel/printk
> root@smarc-rzg3l:~#
> root@smarc-rzg3l:~#
> root@smarc-rzg3l:~# echo mem > /sys/power/state
> [ 57.103165] PM: suspend entry (deep)
> [ 57.106929] Filesystems sync: 0.000 seconds
> [ 57.112372] Freezing user space processes
> [ 57.114782] Freezing user space processes completed (elapsed 0.002 seconds)
> [ 57.123730] OOM killer disabled.
> [ 57.126964] Freezing remaining freezable tasks
> [ 57.132691] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
> [ 57.141140] renesas-gbeth 11c30000.ethernet end0: Link is Down
> [ 57.148638] rzg2l_cpg_pm_suspend(): CLK_ON 0x514/gic_gicclk 1
> [ 57.154428] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_clk 2
> [ 57.160032] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_pclk 2
> [ 57.165687] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_aclk 1
> [ 57.171339] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_pclk 1
> [ 57.177000] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_axi 30c0
> [ 57.183174] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_chi 30c0
> [ 57.189347] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_i 30c0
> [ 57.195258] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_i 30c0
> [ 57.201169] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_180_i 30c0
> [ 57.207426] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_180_i 30c0
> [ 57.213684] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rmii_i 30c0
> [ 57.219774] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_ptp_ref_i 30c0
> [ 57.226120] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_axi 30c0
> [ 57.232290] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_chi 30c0
> [ 57.238459] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_i 30c0
> [ 57.244369] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_i 30c0
> [ 57.250279] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_180_i 30c0
> [ 57.256540] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_180_i 30c0
> [ 57.262798] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rmii_i 30c0
> [ 57.268884] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_ptp_ref_i 30c0
> [ 57.275229] rzg2l_cpg_pm_suspend(): CLK_ON 0x584/scif0_clk_pck 1
> [ 57.281228] rzg2l_cpg_pm_suspend(): CLK_ON 0x598/gpio_hclk 1
> [ 57.286997] Disabling non-boot CPUs ...
> [ 57.292890] psci: CPU3 killed (polled 0 ms)
> [ 57.300567] psci: CPU2 killed (polled 0 ms)
> [ 57.308116] psci: CPU1 killed (polled 0 ms)
> NOTICE: BL2: v2.10.5(release):2.10.5/rzg3l_1.0.0
> NOTICE: BL2: Built : 08:36:10, Jan 20 2026
> INFO: BL2: Doing platform setup
> INFO: Configuring TrustZone Controller
> INFO: Total 3 regions set.
> INFO: Configuring TrustZone Controller
> INFO: Total 1 regions set.
> INFO: Configuring TrustZone Controller
> INFO: Total 1 regions set.
> INFO: eMMC boot from partition 1
> INFO: Loading image id=39 at address 0x44428
> INFO: emmcdrv_block_len: len: 0x00001000
> INFO: Load dst=0x44428 src=(p:1)0x260000(4864) len=0x1000(8)
> INFO: Image id=39 loaded: 0x44428 - 0x45428
> INFO: DDR: Retention Exit (Rev. 02.05)
> NOTICE: BL2: SYS_LSI_MODE: 0x12051
> NOTICE: BL2: SYS_LSI_DEVID: 0x87d9447
> INFO: BL2: Skip loading image id 3
> INFO: BL2: Skip loading image id 5
> NOTICE: BL2: Booting BL31
> INFO: Entry point address = 0x44000000
> INFO: SPSR = 0x3cd
> INFO: GICv3 without legacy support detected.
> INFO: ARM GICv3 driver initialized in EL3
> [ 57.313836] Enabling non-boot CPUs ...
> [ 57.319883] Detected VIPT I-cache on CPU1
> [ 57.319942] GICv3: CPU1: found redistributor 100 region 0:0x0000000012460000
> [ 57.319992] CPU1: Booted secondary processor 0x0000000100 [0x412fd050]
> [ 57.320755] CPU1 is up
> [ 57.341066] Detected VIPT I-cache on CPU2
> [ 57.341112] GICv3: CPU2: found redistributor 200 region 0:0x0000000012480000
> [ 57.341151] CPU2: Booted secondary processor 0x0000000200 [0x412fd050]
> [ 57.341886] CPU2 is up
> [ 57.362133] Detected VIPT I-cache on CPU3
> [ 57.362177] GICv3: CPU3: found redistributor 300 region 0:0x00000000124a0000
> [ 57.362213] CPU3: Booted secondary processor 0x0000000300 [0x412fd050]
> [ 57.362975] CPU3 is up
> [ 57.383339] rzg2l_mod_clock_init_mstop(): CLK_ON 0x514/gic_gicclk 1
> [ 57.389666] rzg2l_mod_clock_init_mstop(): CLK_ON 0x518/ia55_clk 3
> [ 57.395803] rzg2l_mod_clock_init_mstop(): CLK_ON 0x518/ia55_pclk 3
> [ 57.402038] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_clk_axi 3fff
> [ 57.408784] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_clk_chi 3fff
> [ 57.415544] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_rmii_i 3fff
> [ 57.422217] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_ptp_ref_i 3fff
> [ 57.429143] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_clk_axi 3fff
> [ 57.435895] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_clk_chi 3fff
> [ 57.442656] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_rmii_i 3fff
> [ 57.449314] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_ptp_ref_i 3fff
> [ 57.456240] rzg2l_mod_clock_init_mstop(): CLK_ON 0x584/scif0_clk_pck 1
> [ 57.462818] rzg2l_mod_clock_init_mstop(): CLK_ON 0x598/gpio_hclk 1
> [ 57.469039] ###########rzg2l_cpg_resume ########0/0
> [ 57.474068] dwmac4: Master AXI performs fixed burst length
> [ 57.484472] renesas-gbeth 11c30000.ethernet end0: No Safety Features support found
> [ 57.492079] renesas-gbeth 11c30000.ethernet end0: IEEE 1588-2008 Advanced Timestamp supported
> [ 57.500658] renesas-gbeth 11c30000.ethernet end0: configuring for phy/rgmii-id link mode
> [ 57.525097] dwmac4: Master AXI performs fixed burst length
> [ 57.530615] renesas-gbeth 11c40000.ethernet end1: No Safety Features support found
> [ 57.538201] renesas-gbeth 11c40000.ethernet end1: IEEE 1588-2008 Advanced Timestamp supported
> [ 57.546764] renesas-gbeth 11c40000.ethernet end1: configuring for phy/rgmii-id link mode
> [ 57.557533] OOM killer enabled.
> [ 57.560668] Restarting tasks: Starting
> [ 57.565020] Restarting tasks: Done
> [ 57.568586] random: crng reseeded on system resumption
> [ 57.573929] PM: suspend exit
> root@smarc-rzg3l:~# [ 60.574926] renesas-gbeth 11c30000.ethernet end0: Link is Up - 1Gbps/Full - flow control rx/tx
>
> root@smarc-rzg3l:~#
> root@smarc-rzg3l:~# echo enabled > /sys/class/tty/ttySC3/power/wakeup
> root@smarc-rzg3l:~# echo freeze > /sys/power/state
> [ 86.957826] PM: suspend entry (s2idle)
> [ 86.961742] Filesystems sync: 0.000 seconds
> [ 86.966381] Freezing user space processes
> [ 86.972014] Freezing user space processes completed (elapsed 0.001 seconds)
> [ 86.979011] OOM killer disabled.
> [ 86.982248] Freezing remaining freezable tasks
> [ 86.987966] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
> [ 86.996469] renesas-gbeth 11c30000.ethernet end0: Link is Down
> [ 87.004128] rzg2l_cpg_pm_suspend(): CLK_ON 0x514/gic_gicclk 1
> [ 87.009913] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_clk 3
> [ 87.015484] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_pclk 3
> [ 87.021140] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_aclk 1
> [ 87.026795] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_pclk 1
> [ 87.032448] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_axi 30c0
> [ 87.038620] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_chi 30c0
> [ 87.044792] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_i 30c0
> [ 87.050704] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_i 30c0
> [ 87.056616] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_180_i 30c0
> [ 87.062873] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_180_i 30c0
> [ 87.069130] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rmii_i 30c0
> [ 87.075218] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_ptp_ref_i 30c0
> [ 87.081562] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_axi 30c0
> [ 87.087733] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_chi 30c0
> [ 87.093917] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_i 30c0
> [ 87.099829] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_i 30c0
> [ 87.105741] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_180_i 30c0
> [ 87.111999] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_180_i 30c0
> [ 87.118258] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rmii_i 30c0
> [ 87.124342] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_ptp_ref_i 30c0
> [ 87.130688] rzg2l_cpg_pm_suspend(): CLK_ON 0x584/scif0_clk_pck 1
> [ 87.136687] rzg2l_cpg_pm_suspend(): CLK_ON 0x598/gpio_hclk 1
>
> No IRQ's in s2idle.
You tested mem before freeze while previously you only pointed to the
freeze. Could you please follow the same configuration sequence to isolate
the problem?
Thank you,
Claudiu
^ permalink raw reply [flat|nested] 31+ messages in thread
* RE: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-01-26 13:07 ` Claudiu Beznea
@ 2026-01-26 13:12 ` Biju Das
2026-01-26 15:28 ` Biju Das
0 siblings, 1 reply; 31+ messages in thread
From: Biju Das @ 2026-01-26 13:12 UTC (permalink / raw)
To: Claudiu.Beznea, vkoul@kernel.org, Prabhakar Mahadev Lad,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, p.zabel@pengutronix.de, geert+renesas@glider.be,
Fabrizio Castro
Cc: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-sound@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Claudiu Beznea
Hi Claudiu,
> -----Original Message-----
> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> Sent: 26 January 2026 13:07
> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>
>
>
> On 1/26/26 14:51, Biju Das wrote:
> > Hi Claudiu,
> >
> >
> >> -----Original Message-----
> >> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> >> Sent: 26 January 2026 12:39
> >> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> >> support
> >>
> >>
> >>
> >> On 1/26/26 14:10, Biju Das wrote:
> >>>
> >>>
> >>>> -----Original Message-----
> >>>> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> >>>> Sent: 26 January 2026 12:05
> >>>> To: Biju Das <biju.das.jz@bp.renesas.com>; vkoul@kernel.org;
> >>>> Prabhakar Mahadev Lad <prabhakar.mahadev- lad.rj@bp.renesas.com>;
> >>>> lgirdwood@gmail.com; broonie@kernel.org; perex@perex.cz;
> >>>> tiwai@suse.com; p.zabel@pengutronix.de; geert+renesas@glider.be;
> >>>> Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> >>>> Cc: dmaengine@vger.kernel.org; linux-kernel@vger.kernel.org;
> >>>> linux-sound@vger.kernel.org; linux- renesas-soc@vger.kernel.org;
> >>>> Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> >>>> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> >>>> support
> >>>>
> >>>> Hi,
> >>>>
> >>>> On 1/26/26 13:03, Biju Das wrote:
> >>>>> Hi Claudiu,
> >>>>>
> >>>>> Thanks for the patch.
> >>>>>
> >>>>>> -----Original Message-----
> >>>>>> From: Claudiu <claudiu.beznea@tuxon.dev>
> >>>>>> Sent: 26 January 2026 10:32
> >>>>>> Subject: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> >>>>>> support
> >>>>>>
> >>>>>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> >>>>>>
> >>>>>> The Renesas RZ/G3S SoC supports a power saving mode in which
> >>>>>> power to most SoC components is turned off, including the DMA IP.
> >>>>>> Add suspend to RAM support to save and
> >>>> restore the DMA IP registers.
> >>>>>>
> >>>>>> Cyclic DMA channels require special handling. Since they can be
> >>>>>> paused and resumed during system suspend and resume, the driver
> >>>>>> restores additional registers for these channels during the
> >>>>>> resume phase. If a channel was not explicitly paused during
> >>>>>> suspend, the driver ensures that it is paused and resumed as part
> >>>>>> of the system suspend/resume flow. This might
> >>>> be the case of a serial device being used with no_console_suspend.
> >>>>>>
> >>>>>> For non-cyclic channels, the dev_pm_ops::prepare callback waits
> >>>>>> for all ongoing transfers to complete before allowing suspend-to-RAM to proceed.
> >>>>>>
> >>>>>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> >>>>>> ---
> >>>>>> drivers/dma/sh/rz-dmac.c | 183 +++++++++++++++++++++++++++++++++++++--
> >>>>>> 1 file changed, 175 insertions(+), 8 deletions(-)
> >>>>>>
> >>>>>> diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
> >>>>>> index ab5f49a0b9f2..8f3e2719e639
> >>>>>> +
> >>>>>> + pm_runtime_put_sync(dmac->dev);
> >>>>>> +
> >>>>>> + ret = reset_control_assert(dmac->rstc);
> >>>>>> + if (ret) {
> >>>>>> + pm_runtime_resume_and_get(dmac->dev);
> >>>>>> + rz_dmac_suspend_recover(dmac);
> >>>>>> + }
> >>>>>> +
> >>>>>
> >>>>>
> >>>>> This patch breaks, s2idle in RZ/G3L as it turns off DMA ACLK and
> >>>>> IRQ's are not routed to CPU for wakeup.
> >>>>
> >>>> Is this particular patch the one that explicitly breaks it? Is
> >>>> there any mainline PM support available for RZ/G3L? Can it be fixed
> >>>> along with the RZ/G3L support, if any, as I don't have the board to test it?
> >>>
> >>> Maybe your TF-A is enabling DMAACLK during resume. Can you check
> >>> that mean time, I will check what you have mentioned Here?
> >>>
> >>
> >> You used "freeze" in your example. Same did I to check your usecase.
> >> That suspend type don't involve TF-A (unless something changes and I'm not aware of).
> >>
> >
> > Looks like reset assert in suspend() is the issue, not the clk.
>
> How did you concluded this? Do we know if the wakeup interrupt is configured properly? Could you point
> to the code configuring the wakeup interrupt?
>
> Also, could you please respond to the questions on the previous emails I addressed? It helps
> understanding the problem.
>
> >
> > echo N > /sys/module/printk/parameters/console_suspend
> > root@smarc-rzg3l:~# echo 7 > /proc/sys/kernel/printk
> > root@smarc-rzg3l:~# root@smarc-rzg3l:~# root@smarc-rzg3l:~# echo mem >
> > /sys/power/state
> > [ 57.103165] PM: suspend entry (deep)
> > [ 57.106929] Filesystems sync: 0.000 seconds
> > [ 57.112372] Freezing user space processes
> > [ 57.114782] Freezing user space processes completed (elapsed 0.002 seconds)
> > [ 57.123730] OOM killer disabled.
> > [ 57.126964] Freezing remaining freezable tasks
> > [ 57.132691] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
> > [ 57.141140] renesas-gbeth 11c30000.ethernet end0: Link is Down
> > [ 57.148638] rzg2l_cpg_pm_suspend(): CLK_ON 0x514/gic_gicclk 1
> > [ 57.154428] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_clk 2
> > [ 57.160032] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_pclk 2
> > [ 57.165687] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_aclk 1
> > [ 57.171339] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_pclk 1
> > [ 57.177000] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_axi 30c0
> > [ 57.183174] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_chi 30c0
> > [ 57.189347] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_i 30c0
> > [ 57.195258] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_i 30c0
> > [ 57.201169] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_180_i 30c0
> > [ 57.207426] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_180_i 30c0
> > [ 57.213684] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rmii_i 30c0
> > [ 57.219774] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_ptp_ref_i 30c0
> > [ 57.226120] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_axi 30c0
> > [ 57.232290] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_chi 30c0
> > [ 57.238459] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_i 30c0
> > [ 57.244369] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_i 30c0
> > [ 57.250279] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_180_i 30c0
> > [ 57.256540] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_180_i 30c0
> > [ 57.262798] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rmii_i 30c0
> > [ 57.268884] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_ptp_ref_i 30c0
> > [ 57.275229] rzg2l_cpg_pm_suspend(): CLK_ON 0x584/scif0_clk_pck 1
> > [ 57.281228] rzg2l_cpg_pm_suspend(): CLK_ON 0x598/gpio_hclk 1
> > [ 57.286997] Disabling non-boot CPUs ...
> > [ 57.292890] psci: CPU3 killed (polled 0 ms)
> > [ 57.300567] psci: CPU2 killed (polled 0 ms)
> > [ 57.308116] psci: CPU1 killed (polled 0 ms)
> > NOTICE: BL2: v2.10.5(release):2.10.5/rzg3l_1.0.0
> > NOTICE: BL2: Built : 08:36:10, Jan 20 2026
> > INFO: BL2: Doing platform setup
> > INFO: Configuring TrustZone Controller
> > INFO: Total 3 regions set.
> > INFO: Configuring TrustZone Controller
> > INFO: Total 1 regions set.
> > INFO: Configuring TrustZone Controller
> > INFO: Total 1 regions set.
> > INFO: eMMC boot from partition 1
> > INFO: Loading image id=39 at address 0x44428
> > INFO: emmcdrv_block_len: len: 0x00001000
> > INFO: Load dst=0x44428 src=(p:1)0x260000(4864) len=0x1000(8)
> > INFO: Image id=39 loaded: 0x44428 - 0x45428
> > INFO: DDR: Retention Exit (Rev. 02.05)
> > NOTICE: BL2: SYS_LSI_MODE: 0x12051
> > NOTICE: BL2: SYS_LSI_DEVID: 0x87d9447
> > INFO: BL2: Skip loading image id 3
> > INFO: BL2: Skip loading image id 5
> > NOTICE: BL2: Booting BL31
> > INFO: Entry point address = 0x44000000
> > INFO: SPSR = 0x3cd
> > INFO: GICv3 without legacy support detected.
> > INFO: ARM GICv3 driver initialized in EL3
> > [ 57.313836] Enabling non-boot CPUs ...
> > [ 57.319883] Detected VIPT I-cache on CPU1
> > [ 57.319942] GICv3: CPU1: found redistributor 100 region 0:0x0000000012460000
> > [ 57.319992] CPU1: Booted secondary processor 0x0000000100 [0x412fd050]
> > [ 57.320755] CPU1 is up
> > [ 57.341066] Detected VIPT I-cache on CPU2
> > [ 57.341112] GICv3: CPU2: found redistributor 200 region 0:0x0000000012480000
> > [ 57.341151] CPU2: Booted secondary processor 0x0000000200 [0x412fd050]
> > [ 57.341886] CPU2 is up
> > [ 57.362133] Detected VIPT I-cache on CPU3
> > [ 57.362177] GICv3: CPU3: found redistributor 300 region 0:0x00000000124a0000
> > [ 57.362213] CPU3: Booted secondary processor 0x0000000300 [0x412fd050]
> > [ 57.362975] CPU3 is up
> > [ 57.383339] rzg2l_mod_clock_init_mstop(): CLK_ON 0x514/gic_gicclk 1
> > [ 57.389666] rzg2l_mod_clock_init_mstop(): CLK_ON 0x518/ia55_clk 3
> > [ 57.395803] rzg2l_mod_clock_init_mstop(): CLK_ON 0x518/ia55_pclk 3
> > [ 57.402038] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_clk_axi 3fff
> > [ 57.408784] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_clk_chi 3fff
> > [ 57.415544] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_rmii_i 3fff
> > [ 57.422217] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_ptp_ref_i 3fff
> > [ 57.429143] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_clk_axi 3fff
> > [ 57.435895] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_clk_chi 3fff
> > [ 57.442656] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_rmii_i 3fff
> > [ 57.449314] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_ptp_ref_i 3fff
> > [ 57.456240] rzg2l_mod_clock_init_mstop(): CLK_ON 0x584/scif0_clk_pck 1
> > [ 57.462818] rzg2l_mod_clock_init_mstop(): CLK_ON 0x598/gpio_hclk 1
> > [ 57.469039] ###########rzg2l_cpg_resume ########0/0
> > [ 57.474068] dwmac4: Master AXI performs fixed burst length
> > [ 57.484472] renesas-gbeth 11c30000.ethernet end0: No Safety Features support found
> > [ 57.492079] renesas-gbeth 11c30000.ethernet end0: IEEE 1588-2008 Advanced Timestamp supported
> > [ 57.500658] renesas-gbeth 11c30000.ethernet end0: configuring for phy/rgmii-id link mode
> > [ 57.525097] dwmac4: Master AXI performs fixed burst length
> > [ 57.530615] renesas-gbeth 11c40000.ethernet end1: No Safety Features support found
> > [ 57.538201] renesas-gbeth 11c40000.ethernet end1: IEEE 1588-2008 Advanced Timestamp supported
> > [ 57.546764] renesas-gbeth 11c40000.ethernet end1: configuring for phy/rgmii-id link mode
> > [ 57.557533] OOM killer enabled.
> > [ 57.560668] Restarting tasks: Starting
> > [ 57.565020] Restarting tasks: Done
> > [ 57.568586] random: crng reseeded on system resumption
> > [ 57.573929] PM: suspend exit
> > root@smarc-rzg3l:~# [ 60.574926] renesas-gbeth 11c30000.ethernet end0: Link is Up - 1Gbps/Full -
> flow control rx/tx
> >
> > root@smarc-rzg3l:~#
> > root@smarc-rzg3l:~# echo enabled > /sys/class/tty/ttySC3/power/wakeup
> > root@smarc-rzg3l:~# echo freeze > /sys/power/state
> > [ 86.957826] PM: suspend entry (s2idle)
> > [ 86.961742] Filesystems sync: 0.000 seconds
> > [ 86.966381] Freezing user space processes
> > [ 86.972014] Freezing user space processes completed (elapsed 0.001 seconds)
> > [ 86.979011] OOM killer disabled.
> > [ 86.982248] Freezing remaining freezable tasks
> > [ 86.987966] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
> > [ 86.996469] renesas-gbeth 11c30000.ethernet end0: Link is Down
> > [ 87.004128] rzg2l_cpg_pm_suspend(): CLK_ON 0x514/gic_gicclk 1
> > [ 87.009913] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_clk 3
> > [ 87.015484] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_pclk 3
> > [ 87.021140] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_aclk 1
> > [ 87.026795] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_pclk 1
> > [ 87.032448] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_axi 30c0
> > [ 87.038620] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_chi 30c0
> > [ 87.044792] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_i 30c0
> > [ 87.050704] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_i 30c0
> > [ 87.056616] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_180_i 30c0
> > [ 87.062873] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_180_i 30c0
> > [ 87.069130] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rmii_i 30c0
> > [ 87.075218] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_ptp_ref_i 30c0
> > [ 87.081562] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_axi 30c0
> > [ 87.087733] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_chi 30c0
> > [ 87.093917] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_i 30c0
> > [ 87.099829] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_i 30c0
> > [ 87.105741] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_180_i 30c0
> > [ 87.111999] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_180_i 30c0
> > [ 87.118258] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rmii_i 30c0
> > [ 87.124342] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_ptp_ref_i 30c0
> > [ 87.130688] rzg2l_cpg_pm_suspend(): CLK_ON 0x584/scif0_clk_pck 1
> > [ 87.136687] rzg2l_cpg_pm_suspend(): CLK_ON 0x598/gpio_hclk 1
> >
> > No IRQ's in s2idle.
>
> You tested mem before freeze while previously you only pointed to the freeze. Could you please follow
> the same configuration sequence to isolate the problem?
For s2idle issue on RZ/G3L is DMA device is in asserted state, not forwarding any IRQ to cpu for wakeup.
For S2RAM issue on RZ/G3L is during suspend hardware turns DMAACLK off/ Asserted state. Clock framwork is not turning
On DMAACLK as it critical clk.
Can you please check your TF-A for the second case? First case, RZ/G3S may ok for reset assert state, it can forward IRQs to CPU.
Cheers,
Biju
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 6/7] ASoC: renesas: rz-ssi: Use generic PCM dmaengine APIs
2026-01-26 10:31 ` [PATCH 6/7] ASoC: renesas: rz-ssi: Use generic PCM dmaengine APIs Claudiu
@ 2026-01-26 14:26 ` Geert Uytterhoeven
2026-01-26 14:46 ` Claudiu Beznea
0 siblings, 1 reply; 31+ messages in thread
From: Geert Uytterhoeven @ 2026-01-26 14:26 UTC (permalink / raw)
To: Claudiu
Cc: vkoul, biju.das.jz, prabhakar.mahadev-lad.rj, lgirdwood, broonie,
perex, tiwai, p.zabel, fabrizio.castro.jz, dmaengine,
linux-kernel, linux-sound, linux-renesas-soc, Claudiu Beznea
Hi Claudiu,
On Mon, 26 Jan 2026 at 11:32, Claudiu <claudiu.beznea@tuxon.dev> wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> On Renesas RZ/G2L and RZ/G3S SoCs (where this was tested), captured audio
> files occasionally contained random spikes when viewed with a profiling
> tool such as Audacity. These spikes were also audible as popping noises.
>
> Using cyclic DMA resolves this issue. The driver was reworked to use the
> existing support provided by the generic PCM dmaengine APIs. In addition
> to eliminating the random spikes, the following issues were addressed:
> - blank periods at the beginning of recorded files, which occurred
> intermittently, are no longer present
> - no overruns or underruns were observed when continuously recording
> short audio files (e.g. 5 seconds) in a loop
> - concurrency issues in the SSI driver when enqueuing DMA requests were
> eliminated; previously, DMA requests could be prepared and submitted
> both from the DMA completion callback and the interrupt handler, which
> led to crashes after several hours of testing
> - the SSI driver logic is simplified
> - the number of generated interrupts is reduced by approximately 250%
>
> In the SSI platform driver probe function, the following changes were
> made:
> - the driver-specific DMA configuration was removed in favor of the
> generic PCM dmaengine APIs. As a result, explicit cleanup goto labels
> are no longer required and the driver remove callback was dropped,
> since resource management is now handled via devres helpers
> - special handling was added for IP variants operating in half-duplex
> mode, where the DMA channel name in the device tree is "rt"; this DMA
> channel name is taken into account and passed to the generic PCM
> dmaengine configuration data
>
> All code previously responsible for preparing and completing DMA
> transfers was removed, as this functionality is now handled entirely by
> the generic PCM dmaengine APIs.
>
> Since DMA channels must be paused and resumed during recovery paths
> (overruns and underruns), the DMA channel references are stored in
> rz_ssi_hw_params().
>
> The logic in rz_ssi_is_dma_enabled() was updated to reflect that the
> driver no longer manages DMA transfers directly.
>
> Finally, rz_ssi_stream_is_play() was removed, as it had only a single
> remaining user after this rework, and its logic was inlined at the call
> site.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Thanks for your patch!
> --- a/sound/soc/renesas/rz-ssi.c
> +++ b/sound/soc/renesas/rz-ssi.c
> @@ -1116,15 +936,19 @@ static struct snd_soc_dai_driver rz_ssi_soc_dai[] = {
> static const struct snd_soc_component_driver rz_ssi_soc_component = {
> .name = "rz-ssi",
> .open = rz_ssi_pcm_open,
> - .pointer = rz_ssi_pcm_pointer,
> - .pcm_construct = rz_ssi_pcm_new,
> .legacy_dai_naming = 1,
> };
>
> +static struct snd_dmaengine_pcm_config rz_ssi_dmaegine_pcm_conf = {
> + .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
This fails to link if CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM is not
enabled (e.g. renesas_defconfig):
aarch64-linux-gnu-ld: sound/soc/renesas/rz-ssi.o: in function
`rz_ssi_probe':
rz-ssi.c:(.text+0x538): undefined reference to
`devm_snd_dmaengine_pcm_register'
aarch64-linux-gnu-ld: sound/soc/renesas/rz-ssi.o:(.data+0xc8):
undefined reference to `snd_dmaengine_pcm_prepare_slave_config'
Adding a select like this white-space damaged snippet:
--- a/sound/soc/renesas/Kconfig
+++ b/sound/soc/renesas/Kconfig
@@ -56,6 +56,7 @@ config SND_SOC_MSIOF
config SND_SOC_RZ
tristate "RZ/G2L series SSIF-2 support"
depends on ARCH_RZG2L || COMPILE_TEST
+ select SND_SOC_GENERIC_DMAENGINE_PCM
help
This option enables RZ/G2L SSIF-2 sound support.
would fix the build.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 6/7] ASoC: renesas: rz-ssi: Use generic PCM dmaengine APIs
2026-01-26 14:26 ` Geert Uytterhoeven
@ 2026-01-26 14:46 ` Claudiu Beznea
0 siblings, 0 replies; 31+ messages in thread
From: Claudiu Beznea @ 2026-01-26 14:46 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: vkoul, biju.das.jz, prabhakar.mahadev-lad.rj, lgirdwood, broonie,
perex, tiwai, p.zabel, fabrizio.castro.jz, dmaengine,
linux-kernel, linux-sound, linux-renesas-soc, Claudiu Beznea
Hi, Geert,
On 1/26/26 16:26, Geert Uytterhoeven wrote:
> Hi Claudiu,
>
> On Mon, 26 Jan 2026 at 11:32, Claudiu <claudiu.beznea@tuxon.dev> wrote:
>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>
>> On Renesas RZ/G2L and RZ/G3S SoCs (where this was tested), captured audio
>> files occasionally contained random spikes when viewed with a profiling
>> tool such as Audacity. These spikes were also audible as popping noises.
>>
>> Using cyclic DMA resolves this issue. The driver was reworked to use the
>> existing support provided by the generic PCM dmaengine APIs. In addition
>> to eliminating the random spikes, the following issues were addressed:
>> - blank periods at the beginning of recorded files, which occurred
>> intermittently, are no longer present
>> - no overruns or underruns were observed when continuously recording
>> short audio files (e.g. 5 seconds) in a loop
>> - concurrency issues in the SSI driver when enqueuing DMA requests were
>> eliminated; previously, DMA requests could be prepared and submitted
>> both from the DMA completion callback and the interrupt handler, which
>> led to crashes after several hours of testing
>> - the SSI driver logic is simplified
>> - the number of generated interrupts is reduced by approximately 250%
>>
>> In the SSI platform driver probe function, the following changes were
>> made:
>> - the driver-specific DMA configuration was removed in favor of the
>> generic PCM dmaengine APIs. As a result, explicit cleanup goto labels
>> are no longer required and the driver remove callback was dropped,
>> since resource management is now handled via devres helpers
>> - special handling was added for IP variants operating in half-duplex
>> mode, where the DMA channel name in the device tree is "rt"; this DMA
>> channel name is taken into account and passed to the generic PCM
>> dmaengine configuration data
>>
>> All code previously responsible for preparing and completing DMA
>> transfers was removed, as this functionality is now handled entirely by
>> the generic PCM dmaengine APIs.
>>
>> Since DMA channels must be paused and resumed during recovery paths
>> (overruns and underruns), the DMA channel references are stored in
>> rz_ssi_hw_params().
>>
>> The logic in rz_ssi_is_dma_enabled() was updated to reflect that the
>> driver no longer manages DMA transfers directly.
>>
>> Finally, rz_ssi_stream_is_play() was removed, as it had only a single
>> remaining user after this rework, and its logic was inlined at the call
>> site.
>>
>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> Thanks for your patch!
>
>> --- a/sound/soc/renesas/rz-ssi.c
>> +++ b/sound/soc/renesas/rz-ssi.c
>
>> @@ -1116,15 +936,19 @@ static struct snd_soc_dai_driver rz_ssi_soc_dai[] = {
>> static const struct snd_soc_component_driver rz_ssi_soc_component = {
>> .name = "rz-ssi",
>> .open = rz_ssi_pcm_open,
>> - .pointer = rz_ssi_pcm_pointer,
>> - .pcm_construct = rz_ssi_pcm_new,
>> .legacy_dai_naming = 1,
>> };
>>
>> +static struct snd_dmaengine_pcm_config rz_ssi_dmaegine_pcm_conf = {
>> + .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
>
> This fails to link if CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM is not
> enabled (e.g. renesas_defconfig):
>
> aarch64-linux-gnu-ld: sound/soc/renesas/rz-ssi.o: in function
> `rz_ssi_probe':
> rz-ssi.c:(.text+0x538): undefined reference to
> `devm_snd_dmaengine_pcm_register'
> aarch64-linux-gnu-ld: sound/soc/renesas/rz-ssi.o:(.data+0xc8):
> undefined reference to `snd_dmaengine_pcm_prepare_slave_config'
>
> Adding a select like this white-space damaged snippet:
>
> --- a/sound/soc/renesas/Kconfig
> +++ b/sound/soc/renesas/Kconfig
> @@ -56,6 +56,7 @@ config SND_SOC_MSIOF
> config SND_SOC_RZ
> tristate "RZ/G2L series SSIF-2 support"
> depends on ARCH_RZG2L || COMPILE_TEST
> + select SND_SOC_GENERIC_DMAENGINE_PCM
> help
> This option enables RZ/G2L SSIF-2 sound support.
>
> would fix the build.
Thank you for reporting and proposing a fix. I'll take care of it in v2.
Claudiu
^ permalink raw reply [flat|nested] 31+ messages in thread
* RE: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-01-26 13:12 ` Biju Das
@ 2026-01-26 15:28 ` Biju Das
2026-02-05 13:00 ` Claudiu Beznea
0 siblings, 1 reply; 31+ messages in thread
From: Biju Das @ 2026-01-26 15:28 UTC (permalink / raw)
To: Claudiu.Beznea, vkoul@kernel.org, Prabhakar Mahadev Lad,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, p.zabel@pengutronix.de, geert+renesas@glider.be,
Fabrizio Castro
Cc: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-sound@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Claudiu Beznea
Hi All,
> -----Original Message-----
> From: Biju Das
> Sent: 26 January 2026 13:12
> Subject: RE: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>
> Hi Claudiu,
>
> > -----Original Message-----
> > From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> > Sent: 26 January 2026 13:07
> > Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> > support
> >
> >
> >
> > On 1/26/26 14:51, Biju Das wrote:
> > > Hi Claudiu,
> > >
> > >
> > >> -----Original Message-----
> > >> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> > >> Sent: 26 January 2026 12:39
> > >> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> > >> support
> > >>
> > >>
> > >>
> > >> On 1/26/26 14:10, Biju Das wrote:
> > >>>
> > >>>
> > >>>> -----Original Message-----
> > >>>> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> > >>>> Sent: 26 January 2026 12:05
> > >>>> To: Biju Das <biju.das.jz@bp.renesas.com>; vkoul@kernel.org;
> > >>>> Prabhakar Mahadev Lad <prabhakar.mahadev- lad.rj@bp.renesas.com>;
> > >>>> lgirdwood@gmail.com; broonie@kernel.org; perex@perex.cz;
> > >>>> tiwai@suse.com; p.zabel@pengutronix.de; geert+renesas@glider.be;
> > >>>> Fabrizio Castro <fabrizio.castro.jz@renesas.com>
> > >>>> Cc: dmaengine@vger.kernel.org; linux-kernel@vger.kernel.org;
> > >>>> linux-sound@vger.kernel.org; linux- renesas-soc@vger.kernel.org;
> > >>>> Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> > >>>> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to
> > >>>> RAM support
> > >>>>
> > >>>> Hi,
> > >>>>
> > >>>> On 1/26/26 13:03, Biju Das wrote:
> > >>>>> Hi Claudiu,
> > >>>>>
> > >>>>> Thanks for the patch.
> > >>>>>
> > >>>>>> -----Original Message-----
> > >>>>>> From: Claudiu <claudiu.beznea@tuxon.dev>
> > >>>>>> Sent: 26 January 2026 10:32
> > >>>>>> Subject: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> > >>>>>> support
> > >>>>>>
> > >>>>>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> > >>>>>>
> > >>>>>> The Renesas RZ/G3S SoC supports a power saving mode in which
> > >>>>>> power to most SoC components is turned off, including the DMA IP.
> > >>>>>> Add suspend to RAM support to save and
> > >>>> restore the DMA IP registers.
> > >>>>>>
> > >>>>>> Cyclic DMA channels require special handling. Since they can be
> > >>>>>> paused and resumed during system suspend and resume, the driver
> > >>>>>> restores additional registers for these channels during the
> > >>>>>> resume phase. If a channel was not explicitly paused during
> > >>>>>> suspend, the driver ensures that it is paused and resumed as
> > >>>>>> part of the system suspend/resume flow. This might
> > >>>> be the case of a serial device being used with no_console_suspend.
> > >>>>>>
> > >>>>>> For non-cyclic channels, the dev_pm_ops::prepare callback waits
> > >>>>>> for all ongoing transfers to complete before allowing suspend-to-RAM to proceed.
> > >>>>>>
> > >>>>>> Signed-off-by: Claudiu Beznea
> > >>>>>> <claudiu.beznea.uj@bp.renesas.com>
> > >>>>>> ---
> > >>>>>> drivers/dma/sh/rz-dmac.c | 183 +++++++++++++++++++++++++++++++++++++--
> > >>>>>> 1 file changed, 175 insertions(+), 8 deletions(-)
> > >>>>>>
> > >>>>>> diff --git a/drivers/dma/sh/rz-dmac.c
> > >>>>>> b/drivers/dma/sh/rz-dmac.c index ab5f49a0b9f2..8f3e2719e639
> > >>>>>> +
> > >>>>>> + pm_runtime_put_sync(dmac->dev);
> > >>>>>> +
> > >>>>>> + ret = reset_control_assert(dmac->rstc);
> > >>>>>> + if (ret) {
> > >>>>>> + pm_runtime_resume_and_get(dmac->dev);
> > >>>>>> + rz_dmac_suspend_recover(dmac);
> > >>>>>> + }
> > >>>>>> +
> > >>>>>
> > >>>>>
> > >>>>> This patch breaks, s2idle in RZ/G3L as it turns off DMA ACLK and
> > >>>>> IRQ's are not routed to CPU for wakeup.
> > >>>>
> > >>>> Is this particular patch the one that explicitly breaks it? Is
> > >>>> there any mainline PM support available for RZ/G3L? Can it be
> > >>>> fixed along with the RZ/G3L support, if any, as I don't have the board to test it?
> > >>>
> > >>> Maybe your TF-A is enabling DMAACLK during resume. Can you check
> > >>> that mean time, I will check what you have mentioned Here?
> > >>>
> > >>
> > >> You used "freeze" in your example. Same did I to check your usecase.
> > >> That suspend type don't involve TF-A (unless something changes and I'm not aware of).
> > >>
> > >
> > > Looks like reset assert in suspend() is the issue, not the clk.
> >
> > How did you concluded this? Do we know if the wakeup interrupt is
> > configured properly? Could you point to the code configuring the wakeup interrupt?
> >
> > Also, could you please respond to the questions on the previous emails
> > I addressed? It helps understanding the problem.
> >
> > >
> > > echo N > /sys/module/printk/parameters/console_suspend
> > > root@smarc-rzg3l:~# echo 7 > /proc/sys/kernel/printk
> > > root@smarc-rzg3l:~# root@smarc-rzg3l:~# root@smarc-rzg3l:~# echo mem
> > > > /sys/power/state
> > > [ 57.103165] PM: suspend entry (deep)
> > > [ 57.106929] Filesystems sync: 0.000 seconds
> > > [ 57.112372] Freezing user space processes
> > > [ 57.114782] Freezing user space processes completed (elapsed 0.002 seconds)
> > > [ 57.123730] OOM killer disabled.
> > > [ 57.126964] Freezing remaining freezable tasks
> > > [ 57.132691] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
> > > [ 57.141140] renesas-gbeth 11c30000.ethernet end0: Link is Down
> > > [ 57.148638] rzg2l_cpg_pm_suspend(): CLK_ON 0x514/gic_gicclk 1
> > > [ 57.154428] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_clk 2
> > > [ 57.160032] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_pclk 2
> > > [ 57.165687] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_aclk 1
> > > [ 57.171339] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_pclk 1
> > > [ 57.177000] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_axi 30c0
> > > [ 57.183174] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_chi 30c0
> > > [ 57.189347] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_i 30c0
> > > [ 57.195258] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_i 30c0
> > > [ 57.201169] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_180_i 30c0
> > > [ 57.207426] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_180_i 30c0
> > > [ 57.213684] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rmii_i 30c0
> > > [ 57.219774] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_ptp_ref_i 30c0
> > > [ 57.226120] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_axi 30c0
> > > [ 57.232290] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_chi 30c0
> > > [ 57.238459] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_i 30c0
> > > [ 57.244369] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_i 30c0
> > > [ 57.250279] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_180_i 30c0
> > > [ 57.256540] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_180_i 30c0
> > > [ 57.262798] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rmii_i 30c0
> > > [ 57.268884] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_ptp_ref_i 30c0
> > > [ 57.275229] rzg2l_cpg_pm_suspend(): CLK_ON 0x584/scif0_clk_pck 1
> > > [ 57.281228] rzg2l_cpg_pm_suspend(): CLK_ON 0x598/gpio_hclk 1
> > > [ 57.286997] Disabling non-boot CPUs ...
> > > [ 57.292890] psci: CPU3 killed (polled 0 ms)
> > > [ 57.300567] psci: CPU2 killed (polled 0 ms)
> > > [ 57.308116] psci: CPU1 killed (polled 0 ms)
> > > NOTICE: BL2: v2.10.5(release):2.10.5/rzg3l_1.0.0
> > > NOTICE: BL2: Built : 08:36:10, Jan 20 2026
> > > INFO: BL2: Doing platform setup
> > > INFO: Configuring TrustZone Controller
> > > INFO: Total 3 regions set.
> > > INFO: Configuring TrustZone Controller
> > > INFO: Total 1 regions set.
> > > INFO: Configuring TrustZone Controller
> > > INFO: Total 1 regions set.
> > > INFO: eMMC boot from partition 1
> > > INFO: Loading image id=39 at address 0x44428
> > > INFO: emmcdrv_block_len: len: 0x00001000
> > > INFO: Load dst=0x44428 src=(p:1)0x260000(4864) len=0x1000(8)
> > > INFO: Image id=39 loaded: 0x44428 - 0x45428
> > > INFO: DDR: Retention Exit (Rev. 02.05)
> > > NOTICE: BL2: SYS_LSI_MODE: 0x12051
> > > NOTICE: BL2: SYS_LSI_DEVID: 0x87d9447
> > > INFO: BL2: Skip loading image id 3
> > > INFO: BL2: Skip loading image id 5
> > > NOTICE: BL2: Booting BL31
> > > INFO: Entry point address = 0x44000000
> > > INFO: SPSR = 0x3cd
> > > INFO: GICv3 without legacy support detected.
> > > INFO: ARM GICv3 driver initialized in EL3
> > > [ 57.313836] Enabling non-boot CPUs ...
> > > [ 57.319883] Detected VIPT I-cache on CPU1
> > > [ 57.319942] GICv3: CPU1: found redistributor 100 region 0:0x0000000012460000
> > > [ 57.319992] CPU1: Booted secondary processor 0x0000000100 [0x412fd050]
> > > [ 57.320755] CPU1 is up
> > > [ 57.341066] Detected VIPT I-cache on CPU2
> > > [ 57.341112] GICv3: CPU2: found redistributor 200 region 0:0x0000000012480000
> > > [ 57.341151] CPU2: Booted secondary processor 0x0000000200 [0x412fd050]
> > > [ 57.341886] CPU2 is up
> > > [ 57.362133] Detected VIPT I-cache on CPU3
> > > [ 57.362177] GICv3: CPU3: found redistributor 300 region 0:0x00000000124a0000
> > > [ 57.362213] CPU3: Booted secondary processor 0x0000000300 [0x412fd050]
> > > [ 57.362975] CPU3 is up
> > > [ 57.383339] rzg2l_mod_clock_init_mstop(): CLK_ON 0x514/gic_gicclk 1
> > > [ 57.389666] rzg2l_mod_clock_init_mstop(): CLK_ON 0x518/ia55_clk 3
> > > [ 57.395803] rzg2l_mod_clock_init_mstop(): CLK_ON 0x518/ia55_pclk 3
> > > [ 57.402038] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_clk_axi 3fff
> > > [ 57.408784] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_clk_chi 3fff
> > > [ 57.415544] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_rmii_i 3fff
> > > [ 57.422217] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth0_ptp_ref_i 3fff
> > > [ 57.429143] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_clk_axi 3fff
> > > [ 57.435895] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_clk_chi 3fff
> > > [ 57.442656] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_rmii_i 3fff
> > > [ 57.449314] rzg2l_mod_clock_init_mstop(): CLK_ON 0x57c/eth1_ptp_ref_i 3fff
> > > [ 57.456240] rzg2l_mod_clock_init_mstop(): CLK_ON 0x584/scif0_clk_pck 1
> > > [ 57.462818] rzg2l_mod_clock_init_mstop(): CLK_ON 0x598/gpio_hclk 1
> > > [ 57.469039] ###########rzg2l_cpg_resume ########0/0
> > > [ 57.474068] dwmac4: Master AXI performs fixed burst length
> > > [ 57.484472] renesas-gbeth 11c30000.ethernet end0: No Safety Features support found
> > > [ 57.492079] renesas-gbeth 11c30000.ethernet end0: IEEE 1588-2008 Advanced Timestamp supported
> > > [ 57.500658] renesas-gbeth 11c30000.ethernet end0: configuring for phy/rgmii-id link mode
> > > [ 57.525097] dwmac4: Master AXI performs fixed burst length
> > > [ 57.530615] renesas-gbeth 11c40000.ethernet end1: No Safety Features support found
> > > [ 57.538201] renesas-gbeth 11c40000.ethernet end1: IEEE 1588-2008 Advanced Timestamp supported
> > > [ 57.546764] renesas-gbeth 11c40000.ethernet end1: configuring for phy/rgmii-id link mode
> > > [ 57.557533] OOM killer enabled.
> > > [ 57.560668] Restarting tasks: Starting
> > > [ 57.565020] Restarting tasks: Done
> > > [ 57.568586] random: crng reseeded on system resumption
> > > [ 57.573929] PM: suspend exit
> > > root@smarc-rzg3l:~# [ 60.574926] renesas-gbeth 11c30000.ethernet end0: Link is Up - 1Gbps/Full -
> > flow control rx/tx
> > >
> > > root@smarc-rzg3l:~#
> > > root@smarc-rzg3l:~# echo enabled >
> > > /sys/class/tty/ttySC3/power/wakeup
> > > root@smarc-rzg3l:~# echo freeze > /sys/power/state
> > > [ 86.957826] PM: suspend entry (s2idle)
> > > [ 86.961742] Filesystems sync: 0.000 seconds
> > > [ 86.966381] Freezing user space processes
> > > [ 86.972014] Freezing user space processes completed (elapsed 0.001 seconds)
> > > [ 86.979011] OOM killer disabled.
> > > [ 86.982248] Freezing remaining freezable tasks
> > > [ 86.987966] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
> > > [ 86.996469] renesas-gbeth 11c30000.ethernet end0: Link is Down
> > > [ 87.004128] rzg2l_cpg_pm_suspend(): CLK_ON 0x514/gic_gicclk 1
> > > [ 87.009913] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_clk 3
> > > [ 87.015484] rzg2l_cpg_pm_suspend(): CLK_ON 0x518/ia55_pclk 3
> > > [ 87.021140] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_aclk 1
> > > [ 87.026795] rzg2l_cpg_pm_suspend(): CLK_ON 0x52c/dmac_pclk 1
> > > [ 87.032448] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_axi 30c0
> > > [ 87.038620] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_clk_chi 30c0
> > > [ 87.044792] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_i 30c0
> > > [ 87.050704] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_i 30c0
> > > [ 87.056616] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_tx_180_i 30c0
> > > [ 87.062873] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rx_180_i 30c0
> > > [ 87.069130] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_rmii_i 30c0
> > > [ 87.075218] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth0_ptp_ref_i 30c0
> > > [ 87.081562] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_axi 30c0
> > > [ 87.087733] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_clk_chi 30c0
> > > [ 87.093917] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_i 30c0
> > > [ 87.099829] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_i 30c0
> > > [ 87.105741] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_tx_180_i 30c0
> > > [ 87.111999] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rx_180_i 30c0
> > > [ 87.118258] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_rmii_i 30c0
> > > [ 87.124342] rzg2l_cpg_pm_suspend(): CLK_ON 0x57c/eth1_ptp_ref_i 30c0
> > > [ 87.130688] rzg2l_cpg_pm_suspend(): CLK_ON 0x584/scif0_clk_pck 1
> > > [ 87.136687] rzg2l_cpg_pm_suspend(): CLK_ON 0x598/gpio_hclk 1
> > >
> > > No IRQ's in s2idle.
> >
> > You tested mem before freeze while previously you only pointed to the
> > freeze. Could you please follow the same configuration sequence to isolate the problem?
>
> For s2idle issue on RZ/G3L is DMA device is in asserted state, not forwarding any IRQ to cpu for
> wakeup.
>
> For S2RAM issue on RZ/G3L is during suspend hardware turns DMAACLK off/ Asserted state. Clock framwork
> is not turning On DMAACLK as it critical clk.
>
> Can you please check your TF-A for the second case? First case, RZ/G3S may ok for reset assert state,
> it can forward IRQs to CPU.
Just to summarize, currently there are 2 differences identified between RZ/G3S and RZ/G3L:
SoC differences for s2idle:
RZ/G3S: Can wake the system if the DMA device is in the assert state
RZ/G3L: Cannot wake the system if the DMA device is in the assert state.
TF-A differences for s2ram:
RZ/G3S: TF_A turns on DMA_ACLK during boot/resume.
RZ/G3L: TF_A does not handle DMA_ACLK during boot/resume.
Cheers,
Biju
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-01-26 15:28 ` Biju Das
@ 2026-02-05 13:00 ` Claudiu Beznea
2026-02-05 13:30 ` Biju Das
0 siblings, 1 reply; 31+ messages in thread
From: Claudiu Beznea @ 2026-02-05 13:00 UTC (permalink / raw)
To: Biju Das, vkoul@kernel.org, Prabhakar Mahadev Lad,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, p.zabel@pengutronix.de, geert+renesas@glider.be,
Fabrizio Castro
Cc: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-sound@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Claudiu Beznea
Hi, Biju,
On 1/26/26 17:28, Biju Das wrote:
> Hi All,
>
>> -----Original Message-----
>> From: Biju Das
>> Sent: 26 January 2026 13:12
>> Subject: RE: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>>
[ ... ]
>>
>> For s2idle issue on RZ/G3L is DMA device is in asserted state, not forwarding any IRQ to cpu for
>> wakeup.
>>
>> For S2RAM issue on RZ/G3L is during suspend hardware turns DMAACLK off/ Asserted state. Clock framwork
>> is not turning On DMAACLK as it critical clk.
>>
>> Can you please check your TF-A for the second case? First case, RZ/G3S may ok for reset assert state,
>> it can forward IRQs to CPU.
>
> Just to summarize, currently there are 2 differences identified between RZ/G3S and RZ/G3L:
>
> SoC differences for s2idle:
>
> RZ/G3S: Can wake the system if the DMA device is in the assert state
>
> RZ/G3L: Cannot wake the system if the DMA device is in the assert state.
>
>
> TF-A differences for s2ram:
>
> RZ/G3S: TF_A turns on DMA_ACLK during boot/resume.
>
> RZ/G3L: TF_A does not handle DMA_ACLK during boot/resume.
I'm seeing at [1] you are addressing these differences in the clock/reset
drivers. With that, are you still considering this patch is breaking your system?
Thank you,
Claudiu
[1] https://lore.kernel.org/all/20260130143456.256813-1-biju.das.jz@bp.renesas.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* RE: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-02-05 13:00 ` Claudiu Beznea
@ 2026-02-05 13:30 ` Biju Das
2026-02-05 13:33 ` Geert Uytterhoeven
0 siblings, 1 reply; 31+ messages in thread
From: Biju Das @ 2026-02-05 13:30 UTC (permalink / raw)
To: Claudiu.Beznea, vkoul@kernel.org, Prabhakar Mahadev Lad,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, p.zabel@pengutronix.de, geert+renesas@glider.be,
Fabrizio Castro
Cc: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-sound@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Claudiu Beznea
Hi Claudiu Beznea,
> -----Original Message-----
> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> Sent: 05 February 2026 13:00
> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>
> Hi, Biju,
>
> On 1/26/26 17:28, Biju Das wrote:
> > Hi All,
> >
> >> -----Original Message-----
> >> From: Biju Das
> >> Sent: 26 January 2026 13:12
> >> Subject: RE: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> >> support
> >>
>
> [ ... ]
>
> >>
> >> For s2idle issue on RZ/G3L is DMA device is in asserted state, not
> >> forwarding any IRQ to cpu for wakeup.
> >>
> >> For S2RAM issue on RZ/G3L is during suspend hardware turns DMAACLK
> >> off/ Asserted state. Clock framwork is not turning On DMAACLK as it critical clk.
> >>
> >> Can you please check your TF-A for the second case? First case,
> >> RZ/G3S may ok for reset assert state, it can forward IRQs to CPU.
> >
> > Just to summarize, currently there are 2 differences identified between RZ/G3S and RZ/G3L:
> >
> > SoC differences for s2idle:
> >
> > RZ/G3S: Can wake the system if the DMA device is in the assert state
> >
> > RZ/G3L: Cannot wake the system if the DMA device is in the assert state.
> >
> >
> > TF-A differences for s2ram:
> >
> > RZ/G3S: TF_A turns on DMA_ACLK during boot/resume.
> >
> > RZ/G3L: TF_A does not handle DMA_ACLK during boot/resume.
>
> I'm seeing at [1] you are addressing these differences in the clock/reset drivers. With that, are you
> still considering this patch is breaking your system?
>
Still, thinking whether to add critical reset or go with SoC quirk in DMA driver.
Some SoCs need DMA should be deasserted like critical clock
that can be handled either
1) Add a simple SoC quirk in DMA driver
Or
2) Implement critical reset in SoC specific clock driver and check for all resets.
Is simple SoC quirk in DMA driver, something can be done for RZ/G2L family SoCs?
Cheers,
Biju
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-02-05 13:30 ` Biju Das
@ 2026-02-05 13:33 ` Geert Uytterhoeven
2026-02-05 14:06 ` Biju Das
0 siblings, 1 reply; 31+ messages in thread
From: Geert Uytterhoeven @ 2026-02-05 13:33 UTC (permalink / raw)
To: Biju Das
Cc: Claudiu.Beznea, vkoul@kernel.org, Prabhakar Mahadev Lad,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, p.zabel@pengutronix.de, geert+renesas@glider.be,
Fabrizio Castro, dmaengine@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-sound@vger.kernel.org,
linux-renesas-soc@vger.kernel.org, Claudiu Beznea
Hi Biju,
On Thu, 5 Feb 2026 at 14:30, Biju Das <biju.das.jz@bp.renesas.com> wrote:
> > From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> > On 1/26/26 17:28, Biju Das wrote:
> > >> For s2idle issue on RZ/G3L is DMA device is in asserted state, not
> > >> forwarding any IRQ to cpu for wakeup.
> > >>
> > >> For S2RAM issue on RZ/G3L is during suspend hardware turns DMAACLK
> > >> off/ Asserted state. Clock framwork is not turning On DMAACLK as it critical clk.
> > >>
> > >> Can you please check your TF-A for the second case? First case,
> > >> RZ/G3S may ok for reset assert state, it can forward IRQs to CPU.
> > >
> > > Just to summarize, currently there are 2 differences identified between RZ/G3S and RZ/G3L:
> > >
> > > SoC differences for s2idle:
> > >
> > > RZ/G3S: Can wake the system if the DMA device is in the assert state
> > >
> > > RZ/G3L: Cannot wake the system if the DMA device is in the assert state.
> > >
> > >
> > > TF-A differences for s2ram:
> > >
> > > RZ/G3S: TF_A turns on DMA_ACLK during boot/resume.
> > >
> > > RZ/G3L: TF_A does not handle DMA_ACLK during boot/resume.
> >
> > I'm seeing at [1] you are addressing these differences in the clock/reset drivers. With that, are you
> > still considering this patch is breaking your system?
>
> Still, thinking whether to add critical reset or go with SoC quirk in DMA driver.
> Some SoCs need DMA should be deasserted like critical clock
> that can be handled either
>
> 1) Add a simple SoC quirk in DMA driver
>
> Or
>
> 2) Implement critical reset in SoC specific clock driver and check for all resets.
>
> Is simple SoC quirk in DMA driver, something can be done for RZ/G2L family SoCs?
What if the DMA driver is not enabled?
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 31+ messages in thread
* RE: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-02-05 13:33 ` Geert Uytterhoeven
@ 2026-02-05 14:06 ` Biju Das
2026-02-05 17:20 ` Claudiu Beznea
0 siblings, 1 reply; 31+ messages in thread
From: Biju Das @ 2026-02-05 14:06 UTC (permalink / raw)
To: geert
Cc: Claudiu.Beznea, vkoul@kernel.org, Prabhakar Mahadev Lad,
lgirdwood@gmail.com, broonie@kernel.org, perex@perex.cz,
tiwai@suse.com, p.zabel@pengutronix.de, geert+renesas@glider.be,
Fabrizio Castro, dmaengine@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-sound@vger.kernel.org,
linux-renesas-soc@vger.kernel.org, Claudiu Beznea
Hi Geert,
> -----Original Message-----
> From: Geert Uytterhoeven <geert@linux-m68k.org>
> Sent: 05 February 2026 13:34
> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>
> Hi Biju,
>
> On Thu, 5 Feb 2026 at 14:30, Biju Das <biju.das.jz@bp.renesas.com> wrote:
> > > From: Claudiu Beznea <claudiu.beznea@tuxon.dev> On 1/26/26 17:28,
> > > Biju Das wrote:
> > > >> For s2idle issue on RZ/G3L is DMA device is in asserted state,
> > > >> not forwarding any IRQ to cpu for wakeup.
> > > >>
> > > >> For S2RAM issue on RZ/G3L is during suspend hardware turns
> > > >> DMAACLK off/ Asserted state. Clock framwork is not turning On DMAACLK as it critical clk.
> > > >>
> > > >> Can you please check your TF-A for the second case? First case,
> > > >> RZ/G3S may ok for reset assert state, it can forward IRQs to CPU.
> > > >
> > > > Just to summarize, currently there are 2 differences identified between RZ/G3S and RZ/G3L:
> > > >
> > > > SoC differences for s2idle:
> > > >
> > > > RZ/G3S: Can wake the system if the DMA device is in the assert
> > > > state
> > > >
> > > > RZ/G3L: Cannot wake the system if the DMA device is in the assert state.
> > > >
> > > >
> > > > TF-A differences for s2ram:
> > > >
> > > > RZ/G3S: TF_A turns on DMA_ACLK during boot/resume.
> > > >
> > > > RZ/G3L: TF_A does not handle DMA_ACLK during boot/resume.
> > >
> > > I'm seeing at [1] you are addressing these differences in the
> > > clock/reset drivers. With that, are you still considering this patch is breaking your system?
> >
> > Still, thinking whether to add critical reset or go with SoC quirk in DMA driver.
> > Some SoCs need DMA should be deasserted like critical clock that can
> > be handled either
> >
> > 1) Add a simple SoC quirk in DMA driver
> >
> > Or
> >
> > 2) Implement critical reset in SoC specific clock driver and check for all resets.
> >
> > Is simple SoC quirk in DMA driver, something can be done for RZ/G2L family SoCs?
>
> What if the DMA driver is not enabled?
The below use cases will work (patch[1] - removing the code for deassert in cpg_resume)
as there is no DMA driver to assert the reset.
1) system will boot without DMA driver
2) s2idle will work as there is no DMA driver to assert the reset.
3) s2ram will work without DMA driver.
If DMA driver is enabled, then there is an issue with s2idle
as DMA driver assert the reset and we cannot use serial console
as wakeup source
One solution is SoC quirk will prevent assert/deassert of the DMA reset during
suspend/resume() for affected SoCs.
Other solution is implement the critical reset and check for all assert calls to skip
the DMA resets.
Cheers,
Biju
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-02-05 14:06 ` Biju Das
@ 2026-02-05 17:20 ` Claudiu Beznea
2026-02-05 17:41 ` Biju Das
0 siblings, 1 reply; 31+ messages in thread
From: Claudiu Beznea @ 2026-02-05 17:20 UTC (permalink / raw)
To: Biju Das, geert
Cc: vkoul@kernel.org, Prabhakar Mahadev Lad, lgirdwood@gmail.com,
broonie@kernel.org, perex@perex.cz, tiwai@suse.com,
p.zabel@pengutronix.de, geert+renesas@glider.be, Fabrizio Castro,
dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-sound@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Claudiu Beznea
Hi, Biju,
On 2/5/26 16:06, Biju Das wrote:
> Hi Geert,
>
>> -----Original Message-----
>> From: Geert Uytterhoeven <geert@linux-m68k.org>
>> Sent: 05 February 2026 13:34
>> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>>
>> Hi Biju,
>>
>> On Thu, 5 Feb 2026 at 14:30, Biju Das <biju.das.jz@bp.renesas.com> wrote:
>>>> From: Claudiu Beznea <claudiu.beznea@tuxon.dev> On 1/26/26 17:28,
>>>> Biju Das wrote:
>>>>>> For s2idle issue on RZ/G3L is DMA device is in asserted state,
>>>>>> not forwarding any IRQ to cpu for wakeup.
>>>>>>
>>>>>> For S2RAM issue on RZ/G3L is during suspend hardware turns
>>>>>> DMAACLK off/ Asserted state. Clock framwork is not turning On DMAACLK as it critical clk.
>>>>>>
>>>>>> Can you please check your TF-A for the second case? First case,
>>>>>> RZ/G3S may ok for reset assert state, it can forward IRQs to CPU.
>>>>>
>>>>> Just to summarize, currently there are 2 differences identified between RZ/G3S and RZ/G3L:
>>>>>
>>>>> SoC differences for s2idle:
>>>>>
>>>>> RZ/G3S: Can wake the system if the DMA device is in the assert
>>>>> state
>>>>>
>>>>> RZ/G3L: Cannot wake the system if the DMA device is in the assert state.
>>>>>
>>>>>
>>>>> TF-A differences for s2ram:
>>>>>
>>>>> RZ/G3S: TF_A turns on DMA_ACLK during boot/resume.
>>>>>
>>>>> RZ/G3L: TF_A does not handle DMA_ACLK during boot/resume.
>>>>
>>>> I'm seeing at [1] you are addressing these differences in the
>>>> clock/reset drivers. With that, are you still considering this patch is breaking your system?
>>>
>>> Still, thinking whether to add critical reset or go with SoC quirk in DMA driver.
>>> Some SoCs need DMA should be deasserted like critical clock that can
>>> be handled either
>>>
>>> 1) Add a simple SoC quirk in DMA driver
>>>
>>> Or
>>>
>>> 2) Implement critical reset in SoC specific clock driver and check for all resets.
>>>
>>> Is simple SoC quirk in DMA driver, something can be done for RZ/G2L family SoCs?
>>
>> What if the DMA driver is not enabled?
>
> The below use cases will work (patch[1] - removing the code for deassert in cpg_resume)
> as there is no DMA driver to assert the reset.
>
> 1) system will boot without DMA driver
> 2) s2idle will work as there is no DMA driver to assert the reset.
> 3) s2ram will work without DMA driver.
>
> If DMA driver is enabled, then there is an issue with s2idle
> as DMA driver assert the reset and we cannot use serial console
> as wakeup source
I think we're taking here about both DMA clocks and resets.
What if the DMA clocks are declared critical in Linux and clocks and resets are
not handled by bootloader in probe or resume? Who will restore critical clocks?
clk_prepare_enable() skips applying the setting to hardware as the critical
clock refcount cannot reach zero.
>
> One solution is SoC quirk will prevent assert/deassert of the DMA reset during
> suspend/resume() for affected SoCs.
This can't work w/o taking care of the DMA clocks in the clock driver resume
function (in case DMA clocks are critical). If so, why handling DMA clocks and
resets differently?
>
> Other solution is implement the critical reset and check for all assert calls to skip
> the DMA resets.
I prefer this solution + restore the DMA critical clocks on clock driver
suspend/resume.
Thank you,
Claudiu
^ permalink raw reply [flat|nested] 31+ messages in thread
* RE: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-02-05 17:20 ` Claudiu Beznea
@ 2026-02-05 17:41 ` Biju Das
2026-02-06 7:25 ` Biju Das
2026-02-06 9:58 ` Claudiu Beznea
0 siblings, 2 replies; 31+ messages in thread
From: Biju Das @ 2026-02-05 17:41 UTC (permalink / raw)
To: Claudiu.Beznea, geert
Cc: vkoul@kernel.org, Prabhakar Mahadev Lad, lgirdwood@gmail.com,
broonie@kernel.org, perex@perex.cz, tiwai@suse.com,
p.zabel@pengutronix.de, geert+renesas@glider.be, Fabrizio Castro,
dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-sound@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Claudiu Beznea
Hi Claudiu,
> -----Original Message-----
> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> Sent: 05 February 2026 17:21
> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>
> Hi, Biju,
>
> On 2/5/26 16:06, Biju Das wrote:
> > Hi Geert,
> >
> >> -----Original Message-----
> >> From: Geert Uytterhoeven <geert@linux-m68k.org>
> >> Sent: 05 February 2026 13:34
> >> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> >> support
> >>
> >> Hi Biju,
> >>
> >> On Thu, 5 Feb 2026 at 14:30, Biju Das <biju.das.jz@bp.renesas.com> wrote:
> >>>> From: Claudiu Beznea <claudiu.beznea@tuxon.dev> On 1/26/26 17:28,
> >>>> Biju Das wrote:
> >>>>>> For s2idle issue on RZ/G3L is DMA device is in asserted state,
> >>>>>> not forwarding any IRQ to cpu for wakeup.
> >>>>>>
> >>>>>> For S2RAM issue on RZ/G3L is during suspend hardware turns
> >>>>>> DMAACLK off/ Asserted state. Clock framwork is not turning On DMAACLK as it critical clk.
> >>>>>>
> >>>>>> Can you please check your TF-A for the second case? First case,
> >>>>>> RZ/G3S may ok for reset assert state, it can forward IRQs to CPU.
> >>>>>
> >>>>> Just to summarize, currently there are 2 differences identified between RZ/G3S and RZ/G3L:
> >>>>>
> >>>>> SoC differences for s2idle:
> >>>>>
> >>>>> RZ/G3S: Can wake the system if the DMA device is in the assert
> >>>>> state
> >>>>>
> >>>>> RZ/G3L: Cannot wake the system if the DMA device is in the assert state.
> >>>>>
> >>>>>
> >>>>> TF-A differences for s2ram:
> >>>>>
> >>>>> RZ/G3S: TF_A turns on DMA_ACLK during boot/resume.
> >>>>>
> >>>>> RZ/G3L: TF_A does not handle DMA_ACLK during boot/resume.
> >>>>
> >>>> I'm seeing at [1] you are addressing these differences in the
> >>>> clock/reset drivers. With that, are you still considering this patch is breaking your system?
> >>>
> >>> Still, thinking whether to add critical reset or go with SoC quirk in DMA driver.
> >>> Some SoCs need DMA should be deasserted like critical clock that can
> >>> be handled either
> >>>
> >>> 1) Add a simple SoC quirk in DMA driver
> >>>
> >>> Or
> >>>
> >>> 2) Implement critical reset in SoC specific clock driver and check for all resets.
> >>>
> >>> Is simple SoC quirk in DMA driver, something can be done for RZ/G2L family SoCs?
> >>
> >> What if the DMA driver is not enabled?
> >
> > The below use cases will work (patch[1] - removing the code for
> > deassert in cpg_resume) as there is no DMA driver to assert the reset.
> >
> > 1) system will boot without DMA driver
> > 2) s2idle will work as there is no DMA driver to assert the reset.
> > 3) s2ram will work without DMA driver.
> >
> > If DMA driver is enabled, then there is an issue with s2idle as DMA
> > driver assert the reset and we cannot use serial console as wakeup
> > source
>
> I think we're taking here about both DMA clocks and resets.
>
> What if the DMA clocks are declared critical in Linux and clocks and resets are not handled by
> bootloader in probe or resume? Who will restore critical clocks?
Patch [1] will restore critical clocks.
>
> >
> > One solution is SoC quirk will prevent assert/deassert of the DMA
> > reset during
> > suspend/resume() for affected SoCs.
>
> This can't work w/o taking care of the DMA clocks in the clock driver resume function (in case DMA
> clocks are critical). If so, why handling DMA clocks and resets differently?
What will you prefer
a single check in suspend/resume of DMA driver?
Or
Around 100 checks in suspend/resume in clock driver for checking critical resets for skipping DMA reset?
Cheers,
Biju
^ permalink raw reply [flat|nested] 31+ messages in thread
* RE: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-02-05 17:41 ` Biju Das
@ 2026-02-06 7:25 ` Biju Das
2026-02-06 9:58 ` Claudiu Beznea
1 sibling, 0 replies; 31+ messages in thread
From: Biju Das @ 2026-02-06 7:25 UTC (permalink / raw)
To: Claudiu.Beznea, geert
Cc: vkoul@kernel.org, Prabhakar Mahadev Lad, lgirdwood@gmail.com,
broonie@kernel.org, perex@perex.cz, tiwai@suse.com,
p.zabel@pengutronix.de, geert+renesas@glider.be, Fabrizio Castro,
dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-sound@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Claudiu Beznea
Hi All,
> -----Original Message-----
> From: Biju Das
> Sent: 05 February 2026 17:42
> Subject: RE: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>
> Hi Claudiu,
>
> > -----Original Message-----
> > From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> > Sent: 05 February 2026 17:21
> > Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> > support
> >
> > Hi, Biju,
> >
> > On 2/5/26 16:06, Biju Das wrote:
> > > Hi Geert,
> > >
> > >> -----Original Message-----
> > >> From: Geert Uytterhoeven <geert@linux-m68k.org>
> > >> Sent: 05 February 2026 13:34
> > >> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> > >> support
> > >>
> > >> Hi Biju,
> > >>
> > >> On Thu, 5 Feb 2026 at 14:30, Biju Das <biju.das.jz@bp.renesas.com> wrote:
> > >>>> From: Claudiu Beznea <claudiu.beznea@tuxon.dev> On 1/26/26 17:28,
> > >>>> Biju Das wrote:
> > >>>>>> For s2idle issue on RZ/G3L is DMA device is in asserted state,
> > >>>>>> not forwarding any IRQ to cpu for wakeup.
> > >>>>>>
> > >>>>>> For S2RAM issue on RZ/G3L is during suspend hardware turns
> > >>>>>> DMAACLK off/ Asserted state. Clock framwork is not turning On DMAACLK as it critical clk.
> > >>>>>>
> > >>>>>> Can you please check your TF-A for the second case? First case,
> > >>>>>> RZ/G3S may ok for reset assert state, it can forward IRQs to CPU.
> > >>>>>
> > >>>>> Just to summarize, currently there are 2 differences identified between RZ/G3S and RZ/G3L:
> > >>>>>
> > >>>>> SoC differences for s2idle:
> > >>>>>
> > >>>>> RZ/G3S: Can wake the system if the DMA device is in the assert
> > >>>>> state
> > >>>>>
> > >>>>> RZ/G3L: Cannot wake the system if the DMA device is in the assert state.
> > >>>>>
> > >>>>>
> > >>>>> TF-A differences for s2ram:
> > >>>>>
> > >>>>> RZ/G3S: TF_A turns on DMA_ACLK during boot/resume.
> > >>>>>
> > >>>>> RZ/G3L: TF_A does not handle DMA_ACLK during boot/resume.
> > >>>>
> > >>>> I'm seeing at [1] you are addressing these differences in the
> > >>>> clock/reset drivers. With that, are you still considering this patch is breaking your system?
> > >>>
> > >>> Still, thinking whether to add critical reset or go with SoC quirk in DMA driver.
> > >>> Some SoCs need DMA should be deasserted like critical clock that
> > >>> can be handled either
> > >>>
> > >>> 1) Add a simple SoC quirk in DMA driver
> > >>>
> > >>> Or
> > >>>
> > >>> 2) Implement critical reset in SoC specific clock driver and check for all resets.
> > >>>
> > >>> Is simple SoC quirk in DMA driver, something can be done for RZ/G2L family SoCs?
> > >>
> > >> What if the DMA driver is not enabled?
> > >
> > > The below use cases will work (patch[1] - removing the code for
> > > deassert in cpg_resume) as there is no DMA driver to assert the reset.
> > >
> > > 1) system will boot without DMA driver
> > > 2) s2idle will work as there is no DMA driver to assert the reset.
> > > 3) s2ram will work without DMA driver.
> > >
> > > If DMA driver is enabled, then there is an issue with s2idle as DMA
> > > driver assert the reset and we cannot use serial console as wakeup
> > > source
> >
> > I think we're taking here about both DMA clocks and resets.
> >
> > What if the DMA clocks are declared critical in Linux and clocks and
> > resets are not handled by bootloader in probe or resume? Who will restore critical clocks?
>
> Patch [1] will restore critical clocks.
> >
> > >
> > > One solution is SoC quirk will prevent assert/deassert of the DMA
> > > reset during
> > > suspend/resume() for affected SoCs.
> >
> > This can't work w/o taking care of the DMA clocks in the clock driver
> > resume function (in case DMA clocks are critical). If so, why handling DMA clocks and resets
> differently?
>
>
> What will you prefer
>
> a single check in suspend/resume of DMA driver?
>
> Or
>
> Around 100 checks in suspend/resume in clock driver for checking critical resets for skipping DMA
> reset?
Just FYI,
With patch [1] alone + DMA as critical clock all the use case works on RZ/G3L.
1) System can boot without DMA driver
2) s2idle with serial wakeup works with DMA assert in DMA driver
3) s2ram works.
4) system can boot without bootloader turning DMA clocks/resets.
The issue we are discussing, if we remove, the cpg_suspend code from patch[1]
that will lead to s2idle breakage with serial console as wakeup source because
this patch does a DMA assert and Serial IRQ is not routed to CPU for Wakeup.
So, either implement one of the solutions to support this patch
1) Implement critical reset in reset framework
2) custom implementation in Renesas reset driver
3) Using SoC compatible and avoid assert in DMA driver in affected SoCs
4) just use patch [1]
Looking for efficient handling for this s2idle breakage with serial console
as wakeup source.
Cheers,
Biju
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-02-05 17:41 ` Biju Das
2026-02-06 7:25 ` Biju Das
@ 2026-02-06 9:58 ` Claudiu Beznea
2026-02-06 10:08 ` Biju Das
2026-03-12 10:07 ` Biju Das
1 sibling, 2 replies; 31+ messages in thread
From: Claudiu Beznea @ 2026-02-06 9:58 UTC (permalink / raw)
To: Biju Das, geert
Cc: vkoul@kernel.org, Prabhakar Mahadev Lad, lgirdwood@gmail.com,
broonie@kernel.org, perex@perex.cz, tiwai@suse.com,
p.zabel@pengutronix.de, geert+renesas@glider.be, Fabrizio Castro,
dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-sound@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Claudiu Beznea
Hi, Biju,
On 2/5/26 19:41, Biju Das wrote:
> Hi Claudiu,
>
>> -----Original Message-----
>> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
>> Sent: 05 February 2026 17:21
>> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>>
>> Hi, Biju,
>>
>> On 2/5/26 16:06, Biju Das wrote:
>>> Hi Geert,
>>>
>>>> -----Original Message-----
>>>> From: Geert Uytterhoeven <geert@linux-m68k.org>
>>>> Sent: 05 February 2026 13:34
>>>> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
>>>> support
>>>>
>>>> Hi Biju,
>>>>
>>>> On Thu, 5 Feb 2026 at 14:30, Biju Das <biju.das.jz@bp.renesas.com> wrote:
>>>>>> From: Claudiu Beznea <claudiu.beznea@tuxon.dev> On 1/26/26 17:28,
>>>>>> Biju Das wrote:
>>>>>>>> For s2idle issue on RZ/G3L is DMA device is in asserted state,
>>>>>>>> not forwarding any IRQ to cpu for wakeup.
>>>>>>>>
>>>>>>>> For S2RAM issue on RZ/G3L is during suspend hardware turns
>>>>>>>> DMAACLK off/ Asserted state. Clock framwork is not turning On DMAACLK as it critical clk.
>>>>>>>>
>>>>>>>> Can you please check your TF-A for the second case? First case,
>>>>>>>> RZ/G3S may ok for reset assert state, it can forward IRQs to CPU.
>>>>>>>
>>>>>>> Just to summarize, currently there are 2 differences identified between RZ/G3S and RZ/G3L:
>>>>>>>
>>>>>>> SoC differences for s2idle:
>>>>>>>
>>>>>>> RZ/G3S: Can wake the system if the DMA device is in the assert
>>>>>>> state
>>>>>>>
>>>>>>> RZ/G3L: Cannot wake the system if the DMA device is in the assert state.
>>>>>>>
>>>>>>>
>>>>>>> TF-A differences for s2ram:
>>>>>>>
>>>>>>> RZ/G3S: TF_A turns on DMA_ACLK during boot/resume.
>>>>>>>
>>>>>>> RZ/G3L: TF_A does not handle DMA_ACLK during boot/resume.
>>>>>>
>>>>>> I'm seeing at [1] you are addressing these differences in the
>>>>>> clock/reset drivers. With that, are you still considering this patch is breaking your system?
>>>>>
>>>>> Still, thinking whether to add critical reset or go with SoC quirk in DMA driver.
>>>>> Some SoCs need DMA should be deasserted like critical clock that can
>>>>> be handled either
>>>>>
>>>>> 1) Add a simple SoC quirk in DMA driver
>>>>>
>>>>> Or
>>>>>
>>>>> 2) Implement critical reset in SoC specific clock driver and check for all resets.
>>>>>
>>>>> Is simple SoC quirk in DMA driver, something can be done for RZ/G2L family SoCs?
>>>>
>>>> What if the DMA driver is not enabled?
>>>
>>> The below use cases will work (patch[1] - removing the code for
>>> deassert in cpg_resume) as there is no DMA driver to assert the reset.
>>>
>>> 1) system will boot without DMA driver
>>> 2) s2idle will work as there is no DMA driver to assert the reset.
>>> 3) s2ram will work without DMA driver.
>>>
>>> If DMA driver is enabled, then there is an issue with s2idle as DMA
>>> driver assert the reset and we cannot use serial console as wakeup
>>> source
>>
>> I think we're taking here about both DMA clocks and resets.
>>
>> What if the DMA clocks are declared critical in Linux and clocks and resets are not handled by
>> bootloader in probe or resume? Who will restore critical clocks?
>
> Patch [1] will restore critical clocks.
>>
>>>
>>> One solution is SoC quirk will prevent assert/deassert of the DMA
>>> reset during
>>> suspend/resume() for affected SoCs.
>>
>> This can't work w/o taking care of the DMA clocks in the clock driver resume function (in case DMA
>> clocks are critical). If so, why handling DMA clocks and resets differently?
>
>
> What will you prefer
>
> a single check in suspend/resume of DMA driver?
>
> Or
>
> Around 100 checks in suspend/resume in clock driver for checking critical resets for skipping DMA reset?
I see no conditions in your code. Just raw writes for DMA clocks and resets. I
suspect the intention for v2 is to loop over all the resets in the resume path
to find the critical one.
While reviewing it I asked to avoid asserting the DMA resets on reset assert
API. That could be handled either by adding the concept of critical assert in
the reset driver (or framework) of by just checking directly the reset ID to
match the DMA reset ID (as this is the only critical reset identified at the
moment).
To answer you, my personal taste would be:
- to handle the setup of the critical clocks and resets in a single driver, for
probe and suspend/resume as well
- to handle it in a SoC specific code as this is micro-architecture specific
issue; this problem is only for some of the SoCs, if I'm not wrong; the
manuals for some of the SoCs using this DMA driver states the following
(RZ/G3S HW manual, Rev.1.20., chapter 8.8.1):
In addition, need following register settings *even if DMA controller is not used*.
● Set CPG_CLKON_DMAC_REG register to supply a clock for DMA Controller.
Refer to Section 7.2.4, Clock Control Register DMAC_REG for register detail.
● Set CPG_RST_DMAC register to release a reset for DMA Controller.
Refer to Section 7.2.4, Reset Control Register DMAC for register detail.
Geert, Vinod: could you please let us know how would you like us to handle this?
Thank you,
Claudiu
^ permalink raw reply [flat|nested] 31+ messages in thread
* RE: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-02-06 9:58 ` Claudiu Beznea
@ 2026-02-06 10:08 ` Biju Das
2026-03-12 10:07 ` Biju Das
1 sibling, 0 replies; 31+ messages in thread
From: Biju Das @ 2026-02-06 10:08 UTC (permalink / raw)
To: Claudiu.Beznea, geert
Cc: vkoul@kernel.org, Prabhakar Mahadev Lad, lgirdwood@gmail.com,
broonie@kernel.org, perex@perex.cz, tiwai@suse.com,
p.zabel@pengutronix.de, geert+renesas@glider.be, Fabrizio Castro,
dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-sound@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Claudiu Beznea
Hi Claudiu,
> -----Original Message-----
> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> Sent: 06 February 2026 09:59
> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>
> Hi, Biju,
>
> On 2/5/26 19:41, Biju Das wrote:
> > Hi Claudiu,
> >
> >> -----Original Message-----
> >> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> >> Sent: 05 February 2026 17:21
> >> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> >> support
> >>
> >> Hi, Biju,
> >>
> >> On 2/5/26 16:06, Biju Das wrote:
> >>> Hi Geert,
> >>>
> >>>> -----Original Message-----
> >>>> From: Geert Uytterhoeven <geert@linux-m68k.org>
> >>>> Sent: 05 February 2026 13:34
> >>>> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> >>>> support
> >>>>
> >>>> Hi Biju,
> >>>>
> >>>> On Thu, 5 Feb 2026 at 14:30, Biju Das <biju.das.jz@bp.renesas.com> wrote:
> >>>>>> From: Claudiu Beznea <claudiu.beznea@tuxon.dev> On 1/26/26 17:28,
> >>>>>> Biju Das wrote:
> >>>>>>>> For s2idle issue on RZ/G3L is DMA device is in asserted state,
> >>>>>>>> not forwarding any IRQ to cpu for wakeup.
> >>>>>>>>
> >>>>>>>> For S2RAM issue on RZ/G3L is during suspend hardware turns
> >>>>>>>> DMAACLK off/ Asserted state. Clock framwork is not turning On DMAACLK as it critical clk.
> >>>>>>>>
> >>>>>>>> Can you please check your TF-A for the second case? First case,
> >>>>>>>> RZ/G3S may ok for reset assert state, it can forward IRQs to CPU.
> >>>>>>>
> >>>>>>> Just to summarize, currently there are 2 differences identified between RZ/G3S and RZ/G3L:
> >>>>>>>
> >>>>>>> SoC differences for s2idle:
> >>>>>>>
> >>>>>>> RZ/G3S: Can wake the system if the DMA device is in the assert
> >>>>>>> state
> >>>>>>>
> >>>>>>> RZ/G3L: Cannot wake the system if the DMA device is in the assert state.
> >>>>>>>
> >>>>>>>
> >>>>>>> TF-A differences for s2ram:
> >>>>>>>
> >>>>>>> RZ/G3S: TF_A turns on DMA_ACLK during boot/resume.
> >>>>>>>
> >>>>>>> RZ/G3L: TF_A does not handle DMA_ACLK during boot/resume.
> >>>>>>
> >>>>>> I'm seeing at [1] you are addressing these differences in the
> >>>>>> clock/reset drivers. With that, are you still considering this patch is breaking your system?
> >>>>>
> >>>>> Still, thinking whether to add critical reset or go with SoC quirk in DMA driver.
> >>>>> Some SoCs need DMA should be deasserted like critical clock that
> >>>>> can be handled either
> >>>>>
> >>>>> 1) Add a simple SoC quirk in DMA driver
> >>>>>
> >>>>> Or
> >>>>>
> >>>>> 2) Implement critical reset in SoC specific clock driver and check for all resets.
> >>>>>
> >>>>> Is simple SoC quirk in DMA driver, something can be done for RZ/G2L family SoCs?
> >>>>
> >>>> What if the DMA driver is not enabled?
> >>>
> >>> The below use cases will work (patch[1] - removing the code for
> >>> deassert in cpg_resume) as there is no DMA driver to assert the reset.
> >>>
> >>> 1) system will boot without DMA driver
> >>> 2) s2idle will work as there is no DMA driver to assert the reset.
> >>> 3) s2ram will work without DMA driver.
> >>>
> >>> If DMA driver is enabled, then there is an issue with s2idle as DMA
> >>> driver assert the reset and we cannot use serial console as wakeup
> >>> source
> >>
> >> I think we're taking here about both DMA clocks and resets.
> >>
> >> What if the DMA clocks are declared critical in Linux and clocks and
> >> resets are not handled by bootloader in probe or resume? Who will restore critical clocks?
> >
> > Patch [1] will restore critical clocks.
> >>
> >>>
> >>> One solution is SoC quirk will prevent assert/deassert of the DMA
> >>> reset during
> >>> suspend/resume() for affected SoCs.
> >>
> >> This can't work w/o taking care of the DMA clocks in the clock driver
> >> resume function (in case DMA clocks are critical). If so, why handling DMA clocks and resets
> differently?
> >
> >
> > What will you prefer
> >
> > a single check in suspend/resume of DMA driver?
> >
> > Or
> >
> > Around 100 checks in suspend/resume in clock driver for checking critical resets for skipping DMA
> reset?
>
> I see no conditions in your code. Just raw writes for DMA clocks and resets.
The bootloader handling part is now moved to CPG, so raw write is fine
for probe/resume, that will address the below cases.
To boot the system without DMA driver
To boot without bootloader turning on DMA clk/resets
To turn on DMA clk/resets to get console during s2ram.
Cheers,
Biju
^ permalink raw reply [flat|nested] 31+ messages in thread
* RE: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-02-06 9:58 ` Claudiu Beznea
2026-02-06 10:08 ` Biju Das
@ 2026-03-12 10:07 ` Biju Das
1 sibling, 0 replies; 31+ messages in thread
From: Biju Das @ 2026-03-12 10:07 UTC (permalink / raw)
To: Claudiu.Beznea, geert
Cc: vkoul@kernel.org, Prabhakar Mahadev Lad, lgirdwood@gmail.com,
broonie@kernel.org, perex@perex.cz, tiwai@suse.com,
p.zabel@pengutronix.de, geert+renesas@glider.be, Fabrizio Castro,
dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-sound@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Claudiu Beznea
Hi All,
> -----Original Message-----
> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> Sent: 06 February 2026 09:59
> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
>
> Hi, Biju,
>
> On 2/5/26 19:41, Biju Das wrote:
> > Hi Claudiu,
> >
> >> -----Original Message-----
> >> From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
> >> Sent: 05 February 2026 17:21
> >> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> >> support
> >>
> >> Hi, Biju,
> >>
> >> On 2/5/26 16:06, Biju Das wrote:
> >>> Hi Geert,
> >>>
> >>>> -----Original Message-----
> >>>> From: Geert Uytterhoeven <geert@linux-m68k.org>
> >>>> Sent: 05 February 2026 13:34
> >>>> Subject: Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM
> >>>> support
> >>>>
> >>>> Hi Biju,
> >>>>
> >>>> On Thu, 5 Feb 2026 at 14:30, Biju Das <biju.das.jz@bp.renesas.com> wrote:
> >>>>>> From: Claudiu Beznea <claudiu.beznea@tuxon.dev> On 1/26/26 17:28,
> >>>>>> Biju Das wrote:
> >>>>>>>> For s2idle issue on RZ/G3L is DMA device is in asserted state,
> >>>>>>>> not forwarding any IRQ to cpu for wakeup.
> >>>>>>>>
> >>>>>>>> For S2RAM issue on RZ/G3L is during suspend hardware turns
> >>>>>>>> DMAACLK off/ Asserted state. Clock framwork is not turning On DMAACLK as it critical clk.
> >>>>>>>>
> >>>>>>>> Can you please check your TF-A for the second case? First case,
> >>>>>>>> RZ/G3S may ok for reset assert state, it can forward IRQs to CPU.
> >>>>>>>
> >>>>>>> Just to summarize, currently there are 2 differences identified between RZ/G3S and RZ/G3L:
> >>>>>>>
> >>>>>>> SoC differences for s2idle:
> >>>>>>>
> >>>>>>> RZ/G3S: Can wake the system if the DMA device is in the assert
> >>>>>>> state
> >>>>>>>
> >>>>>>> RZ/G3L: Cannot wake the system if the DMA device is in the assert state.
> >>>>>>>
> >>>>>>>
> >>>>>>> TF-A differences for s2ram:
> >>>>>>>
> >>>>>>> RZ/G3S: TF_A turns on DMA_ACLK during boot/resume.
> >>>>>>>
> >>>>>>> RZ/G3L: TF_A does not handle DMA_ACLK during boot/resume.
> >>>>>>
> >>>>>> I'm seeing at [1] you are addressing these differences in the
> >>>>>> clock/reset drivers. With that, are you still considering this patch is breaking your system?
> >>>>>
> >>>>> Still, thinking whether to add critical reset or go with SoC quirk in DMA driver.
> >>>>> Some SoCs need DMA should be deasserted like critical clock that
> >>>>> can be handled either
> >>>>>
> >>>>> 1) Add a simple SoC quirk in DMA driver
> >>>>>
> >>>>> Or
> >>>>>
> >>>>> 2) Implement critical reset in SoC specific clock driver and check for all resets.
> >>>>>
> >>>>> Is simple SoC quirk in DMA driver, something can be done for RZ/G2L family SoCs?
> >>>>
> >>>> What if the DMA driver is not enabled?
> >>>
> >>> The below use cases will work (patch[1] - removing the code for
> >>> deassert in cpg_resume) as there is no DMA driver to assert the reset.
> >>>
> >>> 1) system will boot without DMA driver
> >>> 2) s2idle will work as there is no DMA driver to assert the reset.
> >>> 3) s2ram will work without DMA driver.
> >>>
> >>> If DMA driver is enabled, then there is an issue with s2idle as DMA
> >>> driver assert the reset and we cannot use serial console as wakeup
> >>> source
> >>
> >> I think we're taking here about both DMA clocks and resets.
> >>
> >> What if the DMA clocks are declared critical in Linux and clocks and
> >> resets are not handled by bootloader in probe or resume? Who will restore critical clocks?
> >
> > Patch [1] will restore critical clocks.
> >>
> >>>
> >>> One solution is SoC quirk will prevent assert/deassert of the DMA
> >>> reset during
> >>> suspend/resume() for affected SoCs.
> >>
> >> This can't work w/o taking care of the DMA clocks in the clock driver
> >> resume function (in case DMA clocks are critical). If so, why handling DMA clocks and resets
> differently?
> >
> >
> > What will you prefer
> >
> > a single check in suspend/resume of DMA driver?
> >
> > Or
> >
> > Around 100 checks in suspend/resume in clock driver for checking critical resets for skipping DMA
> reset?
>
> I see no conditions in your code. Just raw writes for DMA clocks and resets. I suspect the intention
> for v2 is to loop over all the resets in the resume path to find the critical one.
>
> While reviewing it I asked to avoid asserting the DMA resets on reset assert API. That could be
> handled either by adding the concept of critical assert in the reset driver (or framework) of by just
> checking directly the reset ID to match the DMA reset ID (as this is the only critical reset
> identified at the moment).
>
> To answer you, my personal taste would be:
> - to handle the setup of the critical clocks and resets in a single driver, for
> probe and suspend/resume as well
> - to handle it in a SoC specific code as this is micro-architecture specific
> issue; this problem is only for some of the SoCs, if I'm not wrong; the
> manuals for some of the SoCs using this DMA driver states the following
> (RZ/G3S HW manual, Rev.1.20., chapter 8.8.1):
>
> In addition, need following register settings *even if DMA controller is not used*.
>
> ● Set CPG_CLKON_DMAC_REG register to supply a clock for DMA Controller.
>
> Refer to Section 7.2.4, Clock Control Register DMAC_REG for register detail.
>
> ● Set CPG_RST_DMAC register to release a reset for DMA Controller.
>
> Refer to Section 7.2.4, Reset Control Register DMAC for register detail.
>
> Geert, Vinod: could you please let us know how would you like us to handle this?
FYI, A patch [1] already posted for
1) Supporting critical resets for RZ/G2L family
2) Restoring Critical clocks during resume
With this clk on/off, reset assert/deassert can be done from DMA driver during suspend/resume.
[1] https://lore.kernel.org/all/20260306134228.871815-1-biju.das.jz@bp.renesas.com/
Cheers,
Biju
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-01-26 10:31 ` [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support Claudiu
2026-01-26 11:03 ` Biju Das
@ 2026-03-12 12:26 ` Tommaso Merciai
2026-03-16 14:02 ` claudiu beznea
1 sibling, 1 reply; 31+ messages in thread
From: Tommaso Merciai @ 2026-03-12 12:26 UTC (permalink / raw)
To: Claudiu
Cc: vkoul, biju.das.jz, prabhakar.mahadev-lad.rj, lgirdwood, broonie,
perex, tiwai, p.zabel, geert+renesas, fabrizio.castro.jz,
dmaengine, linux-kernel, linux-sound, linux-renesas-soc,
Claudiu Beznea
Hi Claudiu,
Thanks for your patch.
On Mon, Jan 26, 2026 at 12:31:53PM +0200, Claudiu wrote:
> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>
> The Renesas RZ/G3S SoC supports a power saving mode in which power to most
> SoC components is turned off, including the DMA IP. Add suspend to RAM
> support to save and restore the DMA IP registers.
>
> Cyclic DMA channels require special handling. Since they can be paused and
> resumed during system suspend and resume, the driver restores additional
> registers for these channels during the resume phase. If a channel was not
> explicitly paused during suspend, the driver ensures that it is paused and
> resumed as part of the system suspend/resume flow. This might be the
> case of a serial device being used with no_console_suspend.
>
> For non-cyclic channels, the dev_pm_ops::prepare callback waits for all
> ongoing transfers to complete before allowing suspend-to-RAM to proceed.
>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
> drivers/dma/sh/rz-dmac.c | 183 +++++++++++++++++++++++++++++++++++++--
> 1 file changed, 175 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
> index ab5f49a0b9f2..8f3e2719e639 100644
> --- a/drivers/dma/sh/rz-dmac.c
> +++ b/drivers/dma/sh/rz-dmac.c
> @@ -69,11 +69,15 @@ struct rz_dmac_desc {
> * enum rz_dmac_chan_status: RZ DMAC channel status
> * @RZ_DMAC_CHAN_STATUS_ENABLED: Channel is enabled
> * @RZ_DMAC_CHAN_STATUS_PAUSED: Channel is paused though DMA engine callbacks
> + * @RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL: Channel is paused through driver internal logic
> + * @RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED: Channel was prepared for system suspend
> * @RZ_DMAC_CHAN_STATUS_CYCLIC: Channel is cyclic
> */
> enum rz_dmac_chan_status {
> RZ_DMAC_CHAN_STATUS_ENABLED,
> RZ_DMAC_CHAN_STATUS_PAUSED,
> + RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL,
> + RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED,
> RZ_DMAC_CHAN_STATUS_CYCLIC,
> };
>
> @@ -94,6 +98,10 @@ struct rz_dmac_chan {
> u32 chctrl;
> int mid_rid;
>
> + struct {
> + u32 nxla;
> + } pm_state;
> +
> struct list_head ld_free;
> struct list_head ld_queue;
> struct list_head ld_active;
> @@ -1002,10 +1010,17 @@ static int rz_dmac_device_pause(struct dma_chan *chan)
> return rz_dmac_device_pause_set(channel, RZ_DMAC_CHAN_STATUS_PAUSED);
> }
>
> +static int rz_dmac_device_pause_internal(struct rz_dmac_chan *channel)
> +{
> + lockdep_assert_held(&channel->vc.lock);
> +
> + return rz_dmac_device_pause_set(channel, RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL);
> +}
> +
> static int rz_dmac_device_resume_set(struct rz_dmac_chan *channel,
> enum rz_dmac_chan_status status)
> {
> - u32 val;
> + u32 val, chctrl;
> int ret;
>
> lockdep_assert_held(&channel->vc.lock);
> @@ -1013,14 +1028,33 @@ static int rz_dmac_device_resume_set(struct rz_dmac_chan *channel,
> if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED)))
> return 0;
>
> - rz_dmac_ch_writel(channel, CHCTRL_CLRSUS, CHCTRL, 1);
> - ret = read_poll_timeout_atomic(rz_dmac_ch_readl, val,
> - !(val & CHSTAT_SUS), 1, 1024, false,
> - channel, CHSTAT, 1);
> - if (ret)
> - return ret;
> + if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED)) {
> + /*
> + * We can be after a sleep state with power loss. If power was
> + * lost, the CHSTAT_SUS bit is zero. In this case, we need to
> + * enable the channel directly. Otherwise, just set the CLRSUS
> + * bit.
> + */
> + val = rz_dmac_ch_readl(channel, CHSTAT, 1);
> + if (val & CHSTAT_SUS)
> + chctrl = CHCTRL_CLRSUS;
> + else
> + chctrl = CHCTRL_SETEN;
> + } else {
> + chctrl = CHCTRL_CLRSUS;
> + }
> +
> + rz_dmac_ch_writel(channel, chctrl, CHCTRL, 1);
>
> - channel->status &= ~BIT(status);
> + if (chctrl & CHCTRL_CLRSUS) {
> + ret = read_poll_timeout_atomic(rz_dmac_ch_readl, val,
> + !(val & CHSTAT_SUS), 1, 1024, false,
> + channel, CHSTAT, 1);
> + if (ret)
> + return ret;
> + }
> +
> + channel->status &= ~(BIT(status) | BIT(RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED));
>
> return 0;
> }
> @@ -1034,6 +1068,13 @@ static int rz_dmac_device_resume(struct dma_chan *chan)
> return rz_dmac_device_resume_set(channel, RZ_DMAC_CHAN_STATUS_PAUSED);
> }
>
> +static int rz_dmac_device_resume_internal(struct rz_dmac_chan *channel)
> +{
> + lockdep_assert_held(&channel->vc.lock);
> +
> + return rz_dmac_device_resume_set(channel, RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL);
> +}
> +
> /*
> * -----------------------------------------------------------------------------
> * IRQ handling
> @@ -1438,6 +1479,131 @@ static void rz_dmac_remove(struct platform_device *pdev)
> pm_runtime_disable(&pdev->dev);
> }
>
> +static int rz_dmac_suspend_prepare(struct device *dev)
> +{
> + struct rz_dmac *dmac = dev_get_drvdata(dev);
> +
> + for (unsigned int i = 0; i < dmac->n_channels; i++) {
> + struct rz_dmac_chan *channel = &dmac->channels[i];
> +
> + guard(spinlock_irqsave)(&channel->vc.lock);
> +
> + /* Wait for transfer completion, except in cyclic case. */
> + if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_ENABLED) &&
> + !(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)))
> + return -EAGAIN;
> + }
> +
> + return 0;
> +}
> +
> +static void rz_dmac_suspend_recover(struct rz_dmac *dmac)
> +{
> + for (unsigned int i = 0; i < dmac->n_channels; i++) {
> + struct rz_dmac_chan *channel = &dmac->channels[i];
> +
> + guard(spinlock_irqsave)(&channel->vc.lock);
> +
> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)))
> + continue;
> +
> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL)))
> + continue;
> +
> + rz_dmac_device_resume_internal(channel);
> + }
> +}
> +
> +static int rz_dmac_suspend(struct device *dev)
> +{
> + struct rz_dmac *dmac = dev_get_drvdata(dev);
> + int ret;
> +
> + for (unsigned int i = 0; i < dmac->n_channels; i++) {
> + struct rz_dmac_chan *channel = &dmac->channels[i];
> +
> + guard(spinlock_irqsave)(&channel->vc.lock);
> +
> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)))
> + continue;
> +
> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED))) {
> + ret = rz_dmac_device_pause_internal(channel);
> + if (ret) {
> + dev_err(dev, "Failed to suspend channel %s\n",
> + dma_chan_name(&channel->vc.chan));
> + continue;
> + }
> + }
> +
> + channel->pm_state.nxla = rz_dmac_ch_readl(channel, NXLA, 1);
> + channel->status |= BIT(RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED);
> + }
> +
> + pm_runtime_put_sync(dmac->dev);
> +
> + ret = reset_control_assert(dmac->rstc);
> + if (ret) {
> + pm_runtime_resume_and_get(dmac->dev);
> + rz_dmac_suspend_recover(dmac);
> + }
> +
> + return ret;
> +}
Testing suspend/resume support on RZ/G3E (DMAC + RSPI) I'm seeing the
following when suspending:
rz_dmac_suspend()
[ 50.657802] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
[ 50.667577] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
[ 50.675984] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
[ 50.684394] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
[ 50.692804] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
[ 50.701221] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
[ 50.709642] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
[ 50.718062] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
[ 50.726480] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
[ 50.734900] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
I found out that this issue can be solved by:
When the IRQ handler thread completes a non-cyclic transfer and there
are no more descriptors queued (ld_queue is empty), invalidate all
link-mode descriptor headers and clear the RZ_DMAC_CHAN_STATUS_ENABLED
bit into the rz_dmac_irq_handler_thread():
static irqreturn_t rz_dmac_irq_handler_thread(int irq, void *dev_id)
{
struct rz_dmac_chan *channel = dev_id;
struct rz_dmac_desc *desc = NULL;
unsigned long flags;
spin_lock_irqsave(&channel->vc.lock, flags);
if (list_empty(&channel->ld_active)) {
/* Someone might have called terminate all */
goto out;
}
desc = list_first_entry(&channel->ld_active, struct rz_dmac_desc, node);
if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)) {
desc = channel->desc;
vchan_cyclic_callback(&desc->vd);
goto out;
} else {
vchan_cookie_complete(&desc->vd);
}
list_move_tail(channel->ld_active.next, &channel->ld_free);
if (!list_empty(&channel->ld_queue)) {
desc = list_first_entry(&channel->ld_queue, struct rz_dmac_desc,
node);
channel->desc = desc;
if (rz_dmac_xfer_desc(channel) == 0)
list_move_tail(channel->ld_queue.next, &channel->ld_active);
+ } else {
+ rz_dmac_invalidate_lmdesc(channel);
+ channel->status &= ~BIT(RZ_DMAC_CHAN_STATUS_ENABLED);
}
out:
spin_unlock_irqrestore(&channel->vc.lock, flags);
return IRQ_HANDLED;
}
> +
> +static int rz_dmac_resume(struct device *dev)
> +{
> + struct rz_dmac *dmac = dev_get_drvdata(dev);
> + int ret;
> +
> + ret = reset_control_deassert(dmac->rstc);
> + if (ret)
> + return ret;
> +
> + ret = pm_runtime_resume_and_get(dmac->dev);
> + if (ret) {
> + reset_control_assert(dmac->rstc);
> + return ret;
> + }
> +
> + rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_0_7_COMMON_BASE + DCTRL);
> + rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_8_15_COMMON_BASE + DCTRL);
> +
> + for (unsigned int i = 0; i < dmac->n_channels; i++) {
> + struct rz_dmac_chan *channel = &dmac->channels[i];
> +
> + guard(spinlock_irqsave)(&channel->vc.lock);
> +
> + rz_dmac_set_dma_req_no(dmac, channel->index, channel->mid_rid);
> +
> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC))) {
> + rz_dmac_ch_writel(&dmac->channels[i], CHCTRL_DEFAULT, CHCTRL, 1);
> + continue;
> + }
> +
> + rz_dmac_ch_writel(channel, channel->pm_state.nxla, NXLA, 1);
> + rz_dmac_ch_writel(channel, channel->chcfg, CHCFG, 1);
> + rz_dmac_ch_writel(channel, CHCTRL_SWRST, CHCTRL, 1);
> + rz_dmac_ch_writel(channel, channel->chctrl, CHCTRL, 1);
> +
> + if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL)) {
> + ret = rz_dmac_device_resume_internal(channel);
> + if (ret) {
> + dev_err(dev, "Failed to resume channel %s\n",
> + dma_chan_name(&channel->vc.chan));
> + continue;
> + }
> + }
> + }
> +
> + return 0;
> +}
Then on resume I'm seeing the following when testing DMAC + RSPI:
[ 52.831840] spi-nor spi0.0: SPI transfer failed: -110
[ 52.836950] spi_master spi0: failed to transfer one message from queue
[ 52.843474] spi_master spi0: noqueue transfer failed
Which I found out that can be solved by moving:
rz_dmac_set_dma_req_no(dmac, channel->index, channel->mid_rid);
after the cyclic check:
if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC))) {
rz_dmac_ch_writel(&dmac->channels[i], CHCTRL_DEFAULT, CHCTRL, 1);
continue;
}
+ rz_dmac_set_dma_req_no(dmac, channel->index, channel->mid_rid);
rz_dmac_ch_writel(channel, channel->pm_state.nxla, NXLA, 1);
rz_dmac_ch_writel(channel, channel->chcfg, CHCFG, 1);
rz_dmac_ch_writel(channel, CHCTRL_SWRST, CHCTRL, 1);
In this way
rz_dmac_set_dma_req_no()
Is only called for cyclic channels
What do you think?
Kind Regards,
Tommaso
> +
> +static const struct dev_pm_ops rz_dmac_pm_ops = {
> + .prepare = rz_dmac_suspend_prepare,
> + SYSTEM_SLEEP_PM_OPS(rz_dmac_suspend, rz_dmac_resume)
> +};
> +
> static const struct rz_dmac_info rz_dmac_v2h_info = {
> .icu_register_dma_req = rzv2h_icu_register_dma_req,
> .default_dma_req_no = RZV2H_ICU_DMAC_REQ_NO_DEFAULT,
> @@ -1464,6 +1630,7 @@ static struct platform_driver rz_dmac_driver = {
> .driver = {
> .name = "rz-dmac",
> .of_match_table = of_rz_dmac_match,
> + .pm = pm_sleep_ptr(&rz_dmac_pm_ops),
> },
> .probe = rz_dmac_probe,
> .remove = rz_dmac_remove,
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support
2026-03-12 12:26 ` Tommaso Merciai
@ 2026-03-16 14:02 ` claudiu beznea
0 siblings, 0 replies; 31+ messages in thread
From: claudiu beznea @ 2026-03-16 14:02 UTC (permalink / raw)
To: Tommaso Merciai
Cc: vkoul, biju.das.jz, prabhakar.mahadev-lad.rj, lgirdwood, broonie,
perex, tiwai, p.zabel, geert+renesas, fabrizio.castro.jz,
dmaengine, linux-kernel, linux-sound, linux-renesas-soc,
Claudiu Beznea
Hi, Tommaso,
On 3/12/26 14:26, Tommaso Merciai wrote:
> Hi Claudiu,
> Thanks for your patch.
>
> On Mon, Jan 26, 2026 at 12:31:53PM +0200, Claudiu wrote:
>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>
>> The Renesas RZ/G3S SoC supports a power saving mode in which power to most
>> SoC components is turned off, including the DMA IP. Add suspend to RAM
>> support to save and restore the DMA IP registers.
>>
>> Cyclic DMA channels require special handling. Since they can be paused and
>> resumed during system suspend and resume, the driver restores additional
>> registers for these channels during the resume phase. If a channel was not
>> explicitly paused during suspend, the driver ensures that it is paused and
>> resumed as part of the system suspend/resume flow. This might be the
>> case of a serial device being used with no_console_suspend.
>>
>> For non-cyclic channels, the dev_pm_ops::prepare callback waits for all
>> ongoing transfers to complete before allowing suspend-to-RAM to proceed.
>>
>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>> ---
[ ... ]
>> +static int rz_dmac_suspend(struct device *dev)
>> +{
>> + struct rz_dmac *dmac = dev_get_drvdata(dev);
>> + int ret;
>> +
>> + for (unsigned int i = 0; i < dmac->n_channels; i++) {
>> + struct rz_dmac_chan *channel = &dmac->channels[i];
>> +
>> + guard(spinlock_irqsave)(&channel->vc.lock);
>> +
>> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)))
>> + continue;
>> +
>> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED))) {
>> + ret = rz_dmac_device_pause_internal(channel);
>> + if (ret) {
>> + dev_err(dev, "Failed to suspend channel %s\n",
>> + dma_chan_name(&channel->vc.chan));
>> + continue;
>> + }
>> + }
>> +
>> + channel->pm_state.nxla = rz_dmac_ch_readl(channel, NXLA, 1);
>> + channel->status |= BIT(RZ_DMAC_CHAN_STATUS_SYS_SUSPENDED);
>> + }
>> +
>> + pm_runtime_put_sync(dmac->dev);
>> +
>> + ret = reset_control_assert(dmac->rstc);
>> + if (ret) {
>> + pm_runtime_resume_and_get(dmac->dev);
>> + rz_dmac_suspend_recover(dmac);
>> + }
>> +
>> + return ret;
>> +}
>
> Testing suspend/resume support on RZ/G3E (DMAC + RSPI) I'm seeing the
> following when suspending:
>
> rz_dmac_suspend()
>
> [ 50.657802] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
> [ 50.667577] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
> [ 50.675984] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
> [ 50.684394] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
> [ 50.692804] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
> [ 50.701221] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
> [ 50.709642] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
> [ 50.718062] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
> [ 50.726480] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
> [ 50.734900] rz-dmac 11400000.dma-controller: PM: device_prepare(): genpd_prepare returns -11
>
> I found out that this issue can be solved by:
>
> When the IRQ handler thread completes a non-cyclic transfer and there
> are no more descriptors queued (ld_queue is empty), invalidate all
> link-mode descriptor headers and clear the RZ_DMAC_CHAN_STATUS_ENABLED
> bit into the rz_dmac_irq_handler_thread():
>
> static irqreturn_t rz_dmac_irq_handler_thread(int irq, void *dev_id)
> {
> struct rz_dmac_chan *channel = dev_id;
> struct rz_dmac_desc *desc = NULL;
> unsigned long flags;
>
> spin_lock_irqsave(&channel->vc.lock, flags);
>
> if (list_empty(&channel->ld_active)) {
> /* Someone might have called terminate all */
> goto out;
> }
>
> desc = list_first_entry(&channel->ld_active, struct rz_dmac_desc, node);
>
> if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)) {
> desc = channel->desc;
> vchan_cyclic_callback(&desc->vd);
> goto out;
> } else {
> vchan_cookie_complete(&desc->vd);
> }
>
> list_move_tail(channel->ld_active.next, &channel->ld_free);
> if (!list_empty(&channel->ld_queue)) {
> desc = list_first_entry(&channel->ld_queue, struct rz_dmac_desc,
> node);
> channel->desc = desc;
> if (rz_dmac_xfer_desc(channel) == 0)
> list_move_tail(channel->ld_queue.next, &channel->ld_active);
> + } else {
> + rz_dmac_invalidate_lmdesc(channel);
> + channel->status &= ~BIT(RZ_DMAC_CHAN_STATUS_ENABLED);
> }
> out:
> spin_unlock_irqrestore(&channel->vc.lock, flags);
>
> return IRQ_HANDLED;
> }
>
>
>
>> +
>> +static int rz_dmac_resume(struct device *dev)
>> +{
>> + struct rz_dmac *dmac = dev_get_drvdata(dev);
>> + int ret;
>> +
>> + ret = reset_control_deassert(dmac->rstc);
>> + if (ret)
>> + return ret;
>> +
>> + ret = pm_runtime_resume_and_get(dmac->dev);
>> + if (ret) {
>> + reset_control_assert(dmac->rstc);
>> + return ret;
>> + }
>> +
>> + rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_0_7_COMMON_BASE + DCTRL);
>> + rz_dmac_writel(dmac, DCTRL_DEFAULT, CHANNEL_8_15_COMMON_BASE + DCTRL);
>> +
>> + for (unsigned int i = 0; i < dmac->n_channels; i++) {
>> + struct rz_dmac_chan *channel = &dmac->channels[i];
>> +
>> + guard(spinlock_irqsave)(&channel->vc.lock);
>> +
>> + rz_dmac_set_dma_req_no(dmac, channel->index, channel->mid_rid);
>> +
>> + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC))) {
>> + rz_dmac_ch_writel(&dmac->channels[i], CHCTRL_DEFAULT, CHCTRL, 1);
>> + continue;
>> + }
>> +
>> + rz_dmac_ch_writel(channel, channel->pm_state.nxla, NXLA, 1);
>> + rz_dmac_ch_writel(channel, channel->chcfg, CHCFG, 1);
>> + rz_dmac_ch_writel(channel, CHCTRL_SWRST, CHCTRL, 1);
>> + rz_dmac_ch_writel(channel, channel->chctrl, CHCTRL, 1);
>> +
>> + if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED_INTERNAL)) {
>> + ret = rz_dmac_device_resume_internal(channel);
>> + if (ret) {
>> + dev_err(dev, "Failed to resume channel %s\n",
>> + dma_chan_name(&channel->vc.chan));
>> + continue;
>> + }
>> + }
>> + }
>> +
>> + return 0;
>> +}
>
> Then on resume I'm seeing the following when testing DMAC + RSPI:
>
> [ 52.831840] spi-nor spi0.0: SPI transfer failed: -110
> [ 52.836950] spi_master spi0: failed to transfer one message from queue
> [ 52.843474] spi_master spi0: noqueue transfer failed
>
> Which I found out that can be solved by moving:
>
> rz_dmac_set_dma_req_no(dmac, channel->index, channel->mid_rid);
>
> after the cyclic check:
>
> if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC))) {
> rz_dmac_ch_writel(&dmac->channels[i], CHCTRL_DEFAULT, CHCTRL, 1);
> continue;
> }
>
> + rz_dmac_set_dma_req_no(dmac, channel->index, channel->mid_rid);
> rz_dmac_ch_writel(channel, channel->pm_state.nxla, NXLA, 1);
> rz_dmac_ch_writel(channel, channel->chcfg, CHCFG, 1);
> rz_dmac_ch_writel(channel, CHCTRL_SWRST, CHCTRL, 1);
>
> In this way
>
> rz_dmac_set_dma_req_no()
>
> Is only called for cyclic channels
>
> What do you think?
Thank you for trying this series and looking to provide fixes. Unfortunatelly, I
currently don't have at hand a platform with SPI enabled to check it. I'm going
to investigate the fixes you provided and integrate them in the next version.
Thank you,
Claudiu
^ permalink raw reply [flat|nested] 31+ messages in thread
end of thread, other threads:[~2026-03-16 14:02 UTC | newest]
Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-26 10:31 [PATCH 0/7] Renesas: dmaengine and ASoC fixes Claudiu
2026-01-26 10:31 ` [PATCH 1/7] dmaengine: sh: rz-dmac: Add enable status bit Claudiu
2026-01-26 10:31 ` [PATCH 2/7] dmaengine: sh: rz-dmac: Add pause " Claudiu
2026-01-26 10:31 ` [PATCH 3/7] dmaengine: sh: rz-dmac: Drop the update of CHCTRL_SETEN in channel->chctrl APIs Claudiu
2026-01-26 10:31 ` [PATCH 4/7] dmaengine: sh: rz-dmac: Add cyclic DMA support Claudiu
2026-01-26 10:31 ` [PATCH 5/7] dmaengine: sh: rz-dmac: Add suspend to RAM support Claudiu
2026-01-26 11:03 ` Biju Das
2026-01-26 12:04 ` Claudiu Beznea
2026-01-26 12:10 ` Biju Das
2026-01-26 12:39 ` Claudiu Beznea
2026-01-26 12:51 ` Biju Das
2026-01-26 13:06 ` Biju Das
2026-01-26 13:07 ` Claudiu Beznea
2026-01-26 13:12 ` Biju Das
2026-01-26 15:28 ` Biju Das
2026-02-05 13:00 ` Claudiu Beznea
2026-02-05 13:30 ` Biju Das
2026-02-05 13:33 ` Geert Uytterhoeven
2026-02-05 14:06 ` Biju Das
2026-02-05 17:20 ` Claudiu Beznea
2026-02-05 17:41 ` Biju Das
2026-02-06 7:25 ` Biju Das
2026-02-06 9:58 ` Claudiu Beznea
2026-02-06 10:08 ` Biju Das
2026-03-12 10:07 ` Biju Das
2026-03-12 12:26 ` Tommaso Merciai
2026-03-16 14:02 ` claudiu beznea
2026-01-26 10:31 ` [PATCH 6/7] ASoC: renesas: rz-ssi: Use generic PCM dmaengine APIs Claudiu
2026-01-26 14:26 ` Geert Uytterhoeven
2026-01-26 14:46 ` Claudiu Beznea
2026-01-26 10:31 ` [PATCH 7/7] dmaengine: sh: rz-dmac: Set the Link End (LE) bit on the last descriptor Claudiu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox