From d26eb4a75a4a2bbf27305e62ad82cedf5f8c577c Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Fri, 21 Nov 2025 14:36:57 +0100 Subject: [PATCH] dmaengine: stm32-dma3: introduce channel semaphore helpers Before restoring semaphore status after suspend, introduce new functions to handle semaphore operations : - stm32_dma3_get_chan_sem() to take the semaphore - stm32_dma3_put_chan_sem() to release the semaphore Also, use a new boolean variable semaphore_taken, which is true when the semaphore has been taken and false when it has been released. Signed-off-by: Amelie Delaunay Link: https://patch.msgid.link/20251121-dma3_improv-v2-2-76a207b13ea6@foss.st.com Signed-off-by: Vinod Koul --- drivers/dma/stm32/stm32-dma3.c | 55 +++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/drivers/dma/stm32/stm32-dma3.c b/drivers/dma/stm32/stm32-dma3.c index 9500164c8f68..a1583face7ec 100644 --- a/drivers/dma/stm32/stm32-dma3.c +++ b/drivers/dma/stm32/stm32-dma3.c @@ -288,6 +288,7 @@ struct stm32_dma3_chan { u32 fifo_size; u32 max_burst; bool semaphore_mode; + bool semaphore_taken; struct stm32_dma3_dt_conf dt_config; struct dma_slave_config dma_config; u8 config_set; @@ -1063,11 +1064,50 @@ static irqreturn_t stm32_dma3_chan_irq(int irq, void *devid) return IRQ_HANDLED; } +static int stm32_dma3_get_chan_sem(struct stm32_dma3_chan *chan) +{ + struct stm32_dma3_ddata *ddata = to_stm32_dma3_ddata(chan); + u32 csemcr, ccid; + + csemcr = readl_relaxed(ddata->base + STM32_DMA3_CSEMCR(chan->id)); + /* Make an attempt to take the channel semaphore if not already taken */ + if (!(csemcr & CSEMCR_SEM_MUTEX)) { + writel_relaxed(CSEMCR_SEM_MUTEX, ddata->base + STM32_DMA3_CSEMCR(chan->id)); + csemcr = readl_relaxed(ddata->base + STM32_DMA3_CSEMCR(chan->id)); + } + + /* Check if channel is under CID1 control */ + ccid = FIELD_GET(CSEMCR_SEM_CCID, csemcr); + if (!(csemcr & CSEMCR_SEM_MUTEX) || ccid != CCIDCFGR_CID1) + goto bad_cid; + + chan->semaphore_taken = true; + dev_dbg(chan2dev(chan), "under CID1 control (semcr=0x%08x)\n", csemcr); + + return 0; + +bad_cid: + chan->semaphore_taken = false; + dev_err(chan2dev(chan), "not under CID1 control (in-use by CID%d)\n", ccid); + + return -EACCES; +} + +static void stm32_dma3_put_chan_sem(struct stm32_dma3_chan *chan) +{ + struct stm32_dma3_ddata *ddata = to_stm32_dma3_ddata(chan); + + if (chan->semaphore_taken) { + writel_relaxed(0, ddata->base + STM32_DMA3_CSEMCR(chan->id)); + chan->semaphore_taken = false; + dev_dbg(chan2dev(chan), "no more under CID1 control\n"); + } +} + static int stm32_dma3_alloc_chan_resources(struct dma_chan *c) { struct stm32_dma3_chan *chan = to_stm32_dma3_chan(c); struct stm32_dma3_ddata *ddata = to_stm32_dma3_ddata(chan); - u32 id = chan->id, csemcr, ccid; int ret; ret = pm_runtime_resume_and_get(ddata->dma_dev.dev); @@ -1092,16 +1132,9 @@ static int stm32_dma3_alloc_chan_resources(struct dma_chan *c) /* Take the channel semaphore */ if (chan->semaphore_mode) { - writel_relaxed(CSEMCR_SEM_MUTEX, ddata->base + STM32_DMA3_CSEMCR(id)); - csemcr = readl_relaxed(ddata->base + STM32_DMA3_CSEMCR(id)); - ccid = FIELD_GET(CSEMCR_SEM_CCID, csemcr); - /* Check that the channel is well taken */ - if (ccid != CCIDCFGR_CID1) { - dev_err(chan2dev(chan), "Not under CID1 control (in-use by CID%d)\n", ccid); - ret = -EPERM; + ret = stm32_dma3_get_chan_sem(chan); + if (ret) goto err_pool_destroy; - } - dev_dbg(chan2dev(chan), "Under CID1 control (semcr=0x%08x)\n", csemcr); } return 0; @@ -1135,7 +1168,7 @@ static void stm32_dma3_free_chan_resources(struct dma_chan *c) /* Release the channel semaphore */ if (chan->semaphore_mode) - writel_relaxed(0, ddata->base + STM32_DMA3_CSEMCR(chan->id)); + stm32_dma3_put_chan_sem(chan); pm_runtime_put_sync(ddata->dma_dev.dev); -- 2.47.3