All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
To: Claudiu Beznea <claudiu.beznea@kernel.org>
Cc: vkoul@kernel.org, Frank.Li@kernel.org, lgirdwood@gmail.com,
	broonie@kernel.org, perex@perex.cz, tiwai@suse.com,
	biju.das.jz@bp.renesas.com,
	prabhakar.mahadev-lad.rj@bp.renesas.com, p.zabel@pengutronix.de,
	geert+renesas@glider.be, kuninori.morimoto.gx@renesas.com,
	long.luu.ur@renesas.com, claudiu.beznea@tuxon.dev,
	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>,
	John Madieu <john.madieu.xa@bp.renesas.com>
Subject: Re: [PATCH v6 12/18] dmaengine: sh: rz-dmac: Add cyclic DMA support
Date: Thu, 28 May 2026 15:51:08 +0200	[thread overview]
Message-ID: <ahhITG7H_yk2_alj@tom-desktop> (raw)
In-Reply-To: <20260526084710.3491480-13-claudiu.beznea@kernel.org>

On Tue, May 26, 2026 at 11:47:04AM +0300, Claudiu Beznea wrote:
> 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.
>

Tested-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>

> Tested-by: John Madieu <john.madieu.xa@bp.renesas.com>
> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> ---
> 
> Changes in v6:
> - collected tags
> 
> Changes in v5:
> - none
> 
> Changes in v4:
> - drop the nxla update logic in rz_dmac_lmdesc_recycle() as this is
>   not needed for any kind of transfers
> - drop the update of channel->status = 0 from rz_dmac_free_chan_resources()
>   and rz_dmac_terminate_all() as this was moved in patch 09/17
> 
> Changes in v3:
> - updated rz_dmac_lmdesc_recycle() to restore the lmdesc->nxla
> - in rz_dmac_prepare_descs_for_cyclic() update directly the
>   desc->start_lmdesc with the descriptor pointer insted of the
>   descriptor address
> - used rz_dmac_lmdesc_addr() to compute the descritor address
> - set channel->status = 0 in rz_dmac_free_chan_resources()
> - in rz_dmac_prep_dma_cyclic() check for invalid periods or buffer len
>   and limit the critical area protected by spinlock
> - set channel->status = 0 in rz_dmac_terminate_all()
> - updated rz_dmac_calculate_residue_bytes_in_vd() to use 
>   rz_dmac_lmdesc_addr()
> - dropped goto in rz_dmac_irq_handler_thread() as it is not needed
>   anymore; dropped also the local variable desc
> 
> Changes in v2:
> - none
> 
>  drivers/dma/sh/rz-dmac.c | 136 +++++++++++++++++++++++++++++++++++++--
>  1 file changed, 130 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
> index c9c00650ddd5..8fd8a4bd9cc9 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 {
> @@ -67,9 +68,11 @@ struct rz_dmac_desc {
>  /**
>   * enum rz_dmac_chan_status: RZ DMAC channel status
>   * @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_PAUSED,
> +	RZ_DMAC_CHAN_STATUS_CYCLIC,
>  };
>  
>  struct rz_dmac_chan {
> @@ -191,6 +194,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
> @@ -431,6 +435,57 @@ static void rz_dmac_prepare_descs_for_slave_sg(struct rz_dmac_chan *channel)
>  	channel->chctrl = 0;
>  }
>  
> +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;
> +
> +	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;
> +	d->start_lmdesc = 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 = rz_dmac_lmdesc_addr(channel, d->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 void rz_dmac_xfer_desc(struct rz_dmac_chan *chan)
>  {
>  	struct virt_dma_desc *vd;
> @@ -452,6 +507,10 @@ static void rz_dmac_xfer_desc(struct rz_dmac_chan *chan)
>  	case RZ_DMAC_DESC_SLAVE_SG:
>  		rz_dmac_prepare_descs_for_slave_sg(chan);
>  		break;
> +
> +	case RZ_DMAC_DESC_CYCLIC:
> +		rz_dmac_prepare_descs_for_cyclic(chan);
> +		break;
>  	}
>  
>  	rz_dmac_enable_hw(chan);
> @@ -586,6 +645,55 @@ 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);
> +	struct rz_dmac_desc *desc;
> +	size_t periods;
> +
> +	if (!is_slave_direction(direction))
> +		return NULL;
> +
> +	if (!period_len || !buf_len)
> +		return NULL;
> +
> +	periods = buf_len / period_len;
> +	if (!periods || periods > DMAC_NR_LMDESC)
> +		return NULL;
> +
> +	scoped_guard(spinlock_irqsave, &channel->vc.lock) {
> +		if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC))
> +			return NULL;
> +
> +		desc = list_first_entry_or_null(&channel->ld_free, struct rz_dmac_desc, node);
> +		if (!desc)
> +			return NULL;
> +
> +		list_del(&desc->node);
> +
> +		channel->status |= BIT(RZ_DMAC_CHAN_STATUS_CYCLIC);
> +	}
> +
> +	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;
> +	}
> +
> +	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);
> @@ -733,9 +841,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)) {
> +		u32 start_lmdesc_addr = rz_dmac_lmdesc_addr(channel, desc->start_lmdesc);
> +
> +		while (lmdesc->nxla != start_lmdesc_addr) {
> +			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);
> @@ -928,10 +1045,14 @@ static irqreturn_t rz_dmac_irq_handler_thread(int irq, void *dev_id)
>  	if (!desc)
>  		return IRQ_HANDLED;
>  
> -	vchan_cookie_complete(&desc->vd);
> -	channel->desc = NULL;
> +	if (channel->status & BIT(RZ_DMAC_CHAN_STATUS_CYCLIC)) {
> +		vchan_cyclic_callback(&desc->vd);
> +	} else {
> +		vchan_cookie_complete(&desc->vd);
> +		channel->desc = NULL;
>  
> -	rz_dmac_xfer_desc(channel);
> +		rz_dmac_xfer_desc(channel);
> +	}
>  
>  	return IRQ_HANDLED;
>  }
> @@ -1183,6 +1304,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);
> @@ -1194,6 +1317,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
> 

  parent reply	other threads:[~2026-05-28 13:51 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-26  8:46 [PATCH v6 00/18] Renesas: dmaengine and ASoC fixes Claudiu Beznea
2026-05-26  8:46 ` [PATCH v6 01/18] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up Claudiu Beznea
2026-05-26  8:54   ` Biju Das
2026-05-26  9:45     ` Claudiu Beznea
2026-05-26  9:51       ` Biju Das
2026-05-26 10:25         ` Claudiu Beznea
2026-05-26 10:39           ` Biju Das
2026-05-26  9:20   ` sashiko-bot
2026-05-28 13:44   ` Tommaso Merciai
2026-05-26  8:46 ` [PATCH v6 02/18] dmaengine: sh: rz-dmac: Fix incorrect NULL check for list_first_entry() Claudiu Beznea
2026-05-26  9:03   ` sashiko-bot
2026-05-28 13:45   ` Tommaso Merciai
2026-05-26  8:46 ` [PATCH v6 03/18] dmaengine: sh: rz-dmac: Use list_first_entry_or_null() Claudiu Beznea
2026-05-28 13:45   ` Tommaso Merciai
2026-05-26  8:46 ` [PATCH v6 04/18] dmaengine: sh: rz-dmac: Use rz_dmac_disable_hw() Claudiu Beznea
2026-05-26  9:15   ` sashiko-bot
2026-05-28 13:46   ` Tommaso Merciai
2026-05-26  8:46 ` [PATCH v6 05/18] dmaengine: sh: rz-dmac: Add helper to compute the lmdesc address Claudiu Beznea
2026-05-28 13:47   ` Tommaso Merciai
2026-05-26  8:46 ` [PATCH v6 06/18] dmaengine: sh: rz-dmac: Save the start LM descriptor Claudiu Beznea
2026-05-26  9:41   ` sashiko-bot
2026-05-28 13:47   ` Tommaso Merciai
2026-05-26  8:46 ` [PATCH v6 07/18] dmaengine: sh: rz-dmac: Add helper to check if the channel is enabled Claudiu Beznea
2026-05-28 13:48   ` Tommaso Merciai
2026-05-26  8:47 ` [PATCH v6 08/18] dmaengine: sh: rz-dmac: Add helper to check if the channel is paused Claudiu Beznea
2026-05-28 13:48   ` Tommaso Merciai
2026-05-26  8:47 ` [PATCH v6 09/18] dmaengine: sh: rz-dmac: Use virt-dma APIs for channel descriptor processing Claudiu Beznea
2026-05-26  9:28   ` sashiko-bot
2026-05-28 13:49   ` Tommaso Merciai
2026-05-26  8:47 ` [PATCH v6 10/18] dmaengine: sh: rz-dmac: Refactor pause/resume code Claudiu Beznea
2026-05-26  9:28   ` sashiko-bot
2026-05-28 13:50   ` Tommaso Merciai
2026-05-26  8:47 ` [PATCH v6 11/18] dmaengine: sh: rz-dmac: Drop the update of channel->chctrl with CHCTRL_SETEN Claudiu Beznea
2026-05-26  9:11   ` sashiko-bot
2026-05-28 13:50   ` Tommaso Merciai
2026-05-26  8:47 ` [PATCH v6 12/18] dmaengine: sh: rz-dmac: Add cyclic DMA support Claudiu Beznea
2026-05-26  9:31   ` sashiko-bot
2026-05-28 13:51   ` Tommaso Merciai [this message]
2026-05-26  8:47 ` [PATCH v6 13/18] dmaengine: sh: rz-dmac: Adjust rz_dmac_chan_get_residue() to return error codes Claudiu Beznea
2026-05-28 13:51   ` Tommaso Merciai
2026-05-26  8:47 ` [PATCH v6 14/18] dmaengine: sh: rz-dmac: Add runtime PM support Claudiu Beznea
2026-05-26  9:57   ` sashiko-bot
2026-05-28 13:52   ` Tommaso Merciai
2026-05-26  8:47 ` [PATCH v6 15/18] dmaengine: sh: rz-dmac: Add suspend to RAM support Claudiu Beznea
2026-05-26  9:43   ` sashiko-bot
2026-05-28 14:38   ` Tommaso Merciai
2026-05-26  8:47 ` [PATCH v6 16/18] ASoC: renesas: rz-ssi: Add pause support Claudiu Beznea
2026-05-26  9:46   ` sashiko-bot
2026-05-26  8:47 ` [PATCH v6 17/18] ASoC: renesas: rz-ssi: Use generic PCM dmaengine APIs Claudiu Beznea
2026-05-26 10:00   ` sashiko-bot
2026-05-26  8:47 ` [PATCH v6 18/18] dmaengine: sh: rz-dmac: Set the Link End (LE) bit on the last descriptor Claudiu Beznea
2026-05-26  9:43   ` sashiko-bot
2026-05-28 14:39   ` Tommaso Merciai
2026-06-02 13:30 ` [PATCH v6 00/18] Renesas: dmaengine and ASoC fixes Claudiu Beznea

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ahhITG7H_yk2_alj@tom-desktop \
    --to=tommaso.merciai.xr@bp.renesas.com \
    --cc=Frank.Li@kernel.org \
    --cc=biju.das.jz@bp.renesas.com \
    --cc=broonie@kernel.org \
    --cc=claudiu.beznea.uj@bp.renesas.com \
    --cc=claudiu.beznea@kernel.org \
    --cc=claudiu.beznea@tuxon.dev \
    --cc=dmaengine@vger.kernel.org \
    --cc=geert+renesas@glider.be \
    --cc=john.madieu.xa@bp.renesas.com \
    --cc=kuninori.morimoto.gx@renesas.com \
    --cc=lgirdwood@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-renesas-soc@vger.kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=long.luu.ur@renesas.com \
    --cc=p.zabel@pengutronix.de \
    --cc=perex@perex.cz \
    --cc=prabhakar.mahadev-lad.rj@bp.renesas.com \
    --cc=tiwai@suse.com \
    --cc=vkoul@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.