From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 160653CEBB7; Tue, 26 May 2026 08:48:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779785293; cv=none; b=fyoOkeWds3ye3hi1sKliimBoosnu6nVqWiXnBcZ+hFuFfJ2NXiVT5Wq/DEemQmaEVIjIf60k7bjBXDorir0tXTghUHagBulfBSkrZ3946FLUMYGsiiuKzfbEeLnRgKowt6+afV/C27/DeXZ0tItglLhKcemqsiJJXT86rihQ22A= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779785293; c=relaxed/simple; bh=I3V+MZJeUrJmTY5EM3NLNs+vytZspxCjwYRZrhyWHms=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=krG/b5w6KChv7VS414MSHPgmBkS9EuWWf5OKkagBSLlzsA0o7HLOotBPlHXU3LkWd4R2L86W7OM5ZGlbj60ie3UWlaXuCeBFJLS7FsIG7JPzDyv6z5GvRk8plgpdOm4Bvz6JAT2q/djtjeFLTUQiB2tU2WnfnJTMJq7K9ls6lqs= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bHeL4qS8; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bHeL4qS8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6AAC31F00A3A; Tue, 26 May 2026 08:48:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779785291; bh=s+5oQkS0ctJPorySv0Wf7N8noj5KZXuB7v8SJnjyOEk=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=bHeL4qS82QMMz3zB1U/sOaz8kbF/cW28g0P3xn3GNoTAKRguM3IagP1LUs9X3ESfO Nfg3kRAb5T8gzg+2sC/HEG53E7sAL6nML1tQy0pXcQIV87aIr4s99sV4GcaCjWAuoF /JFKdlIsVfetq+CnFLcuAU8I58dpV63PRLEQ3sgZuL2AaTIi9vwZFL0LP7iU5BGp3H rycleLPlQkhmMZUWvi7hWFdM224HA7SGSWZGtj2mpL2ot0yH2JKWSQaA675CEuRz5L JrR4YyVBiYDryhqwmqXn+hKBUKI7ZyZRD2cU9sqV+Md5OQUK5gN6gR2XJe9PqXiPAZ BiFsB9tBnR7Jw== From: Claudiu Beznea To: 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 Cc: claudiu.beznea@kernel.org, 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 , John Madieu Subject: [PATCH v6 10/18] dmaengine: sh: rz-dmac: Refactor pause/resume code Date: Tue, 26 May 2026 11:47:02 +0300 Message-ID: <20260526084710.3491480-11-claudiu.beznea@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260526084710.3491480-1-claudiu.beznea@kernel.org> References: <20260526084710.3491480-1-claudiu.beznea@kernel.org> Precedence: bulk X-Mailing-List: dmaengine@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Claudiu Beznea Subsequent patches will add suspend/resume and cyclic DMA support to the rz-dmac driver. This support needs to work on SoCs where power to most components (including DMA) is turned off during system suspend. For this, some channels (for example cyclic ones) may need to be paused and resumed manually by the DMA driver during system suspend/resume. Refactor the pause/resume support so the same code can be reused in the system suspend/resume path. Tested-by: John Madieu Signed-off-by: Claudiu Beznea --- Changes in v6: - collected tags Changes in v5: - none Changes in v4: - reset channel->status in rz_dmac_free_chan_resources() and rz_dmac_terminate_all() Changes in v3: - none, this patch new new drivers/dma/sh/rz-dmac.c | 73 ++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 11 deletions(-) diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c index 1f884ec101f8..557364443a5f 100644 --- a/drivers/dma/sh/rz-dmac.c +++ b/drivers/dma/sh/rz-dmac.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -63,6 +64,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_PAUSED: Channel is paused though DMA engine callbacks + */ +enum rz_dmac_chan_status { + RZ_DMAC_CHAN_STATUS_PAUSED, +}; + struct rz_dmac_chan { struct virt_dma_chan vc; void __iomem *ch_base; @@ -74,6 +83,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; @@ -491,6 +502,8 @@ static void rz_dmac_free_chan_resources(struct dma_chan *chan) channel->mid_rid = -EINVAL; } + channel->status = 0; + spin_unlock_irqrestore(&channel->vc.lock, flags); vchan_free_chan_resources(&channel->vc); @@ -589,6 +602,9 @@ static int rz_dmac_terminate_all(struct dma_chan *chan) } 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); @@ -795,35 +811,70 @@ 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, + unsigned long set_bitmask) { - struct rz_dmac_chan *channel = to_rz_dmac_chan(chan); + int ret = 0; u32 val; - guard(spinlock_irqsave)(&channel->vc.lock); + lockdep_assert_held(&channel->vc.lock); if (!rz_dmac_chan_is_enabled(channel)) return 0; + if (rz_dmac_chan_is_paused(channel)) + goto set_bit; + 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); + +set_bit: + channel->status |= set_bitmask; + + return ret; } -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); + return rz_dmac_device_pause_set(channel, BIT(RZ_DMAC_CHAN_STATUS_PAUSED)); +} + +static int rz_dmac_device_resume_set(struct rz_dmac_chan *channel, + unsigned long clear_bitmask) +{ + int ret = 0; + u32 val; + + lockdep_assert_held(&channel->vc.lock); + /* Do not check CHSTAT_SUS but rely on HW capabilities. */ 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); + + channel->status &= ~clear_bitmask; + + return ret; +} + +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); + + if (!(channel->status & BIT(RZ_DMAC_CHAN_STATUS_PAUSED))) + return 0; + + return rz_dmac_device_resume_set(channel, BIT(RZ_DMAC_CHAN_STATUS_PAUSED)); } /* -- 2.43.0