Commit 49db68d4 authored by Emil Renner Berthing's avatar Emil Renner Berthing Committed by Vinod Koul

dmaengine: dw-axi-dmac: Fix RMW on channel suspend register

When the DMA is configured for more than 8 channels the bits controlling
suspend moves to another register. However when adding support for this
the new register would be completely overwritten in one case and
overwritten with values from the old register in another case.

Found by comparing the parallel implementation of more than 8 channel
support for the StarFive JH7100 SoC by Samin.

Fixes: 82435166 ("dmaengine: dw-axi-dmac: support DMAX_NUM_CHANNELS > 8")
Co-developed-by: default avatarSamin Guo <samin.guo@starfivetech.com>
Signed-off-by: default avatarSamin Guo <samin.guo@starfivetech.com>
Signed-off-by: default avatarEmil Renner Berthing <kernel@esmil.dk>
Link: https://lore.kernel.org/r/20220627090939.1775717-1-emil.renner.berthing@canonical.comSigned-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 44c4237c
...@@ -1164,7 +1164,8 @@ static int dma_chan_pause(struct dma_chan *dchan) ...@@ -1164,7 +1164,8 @@ static int dma_chan_pause(struct dma_chan *dchan)
BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT; BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT;
axi_dma_iowrite32(chan->chip, DMAC_CHEN, val); axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
} else { } else {
val = BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT | val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
val |= BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT |
BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT; BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT;
axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val); axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val);
} }
...@@ -1190,12 +1191,13 @@ static inline void axi_chan_resume(struct axi_dma_chan *chan) ...@@ -1190,12 +1191,13 @@ static inline void axi_chan_resume(struct axi_dma_chan *chan)
{ {
u32 val; u32 val;
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
if (chan->chip->dw->hdata->reg_map_8_channels) { if (chan->chip->dw->hdata->reg_map_8_channels) {
val = axi_dma_ioread32(chan->chip, DMAC_CHEN);
val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT); val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP_SHIFT);
val |= (BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT); val |= (BIT(chan->id) << DMAC_CHAN_SUSP_WE_SHIFT);
axi_dma_iowrite32(chan->chip, DMAC_CHEN, val); axi_dma_iowrite32(chan->chip, DMAC_CHEN, val);
} else { } else {
val = axi_dma_ioread32(chan->chip, DMAC_CHSUSPREG);
val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT); val &= ~(BIT(chan->id) << DMAC_CHAN_SUSP2_SHIFT);
val |= (BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT); val |= (BIT(chan->id) << DMAC_CHAN_SUSP2_WE_SHIFT);
axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val); axi_dma_iowrite32(chan->chip, DMAC_CHSUSPREG, val);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment