The xdma's channel status register may be read and cleared
simultaneously, by accessing it via separate XDMA_CHAN_STATUS_RC
register. Therefore, it is possible to simplify the code
by just getting rid of a separate redundant write.
Also, implement the actual status register checking as well.
Previously, the cyclic callback would be scheduled regardless of the
status register state. Fix it.
Signed-off-by: Jan Kuliga <[email protected]>
---
drivers/dma/xilinx/xdma-regs.h | 2 ++
drivers/dma/xilinx/xdma.c | 17 +++++++++--------
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/dma/xilinx/xdma-regs.h b/drivers/dma/xilinx/xdma-regs.h
index 654c5e41112d..6bf7ae84e452 100644
--- a/drivers/dma/xilinx/xdma-regs.h
+++ b/drivers/dma/xilinx/xdma-regs.h
@@ -116,6 +116,8 @@ struct xdma_hw_desc {
CHAN_CTRL_IE_WRITE_ERROR | \
CHAN_CTRL_IE_DESC_ERROR)
+#define XDMA_CHAN_STATUS_MASK CHAN_CTRL_START
+
/* bits of the channel interrupt enable mask */
#define CHAN_IM_DESC_ERROR BIT(19)
#define CHAN_IM_READ_ERROR BIT(9)
diff --git a/drivers/dma/xilinx/xdma.c b/drivers/dma/xilinx/xdma.c
index 58539a093de2..dc7f43f17103 100644
--- a/drivers/dma/xilinx/xdma.c
+++ b/drivers/dma/xilinx/xdma.c
@@ -809,15 +809,16 @@ static irqreturn_t xdma_channel_isr(int irq, void *dev_id)
desc->completed_desc_num += complete_desc_num;
- if (desc->cyclic) {
- ret = regmap_read(xdev->rmap, xchan->base + XDMA_CHAN_STATUS,
- &st);
- if (ret)
- goto out;
-
- regmap_write(xdev->rmap, xchan->base + XDMA_CHAN_STATUS, st);
+ /* clear-on-read the status register */
+ ret = regmap_read(xdev->rmap, xchan->base + XDMA_CHAN_STATUS_RC,
+ &st);
+ if (ret)
+ goto out;
- vchan_cyclic_callback(vd);
+ if (desc->cyclic) {
+ st &= XDMA_CHAN_STATUS_MASK;
+ if (st & CHAN_CTRL_IE_DESC_COMPLETED)
+ vchan_cyclic_callback(vd);
goto out;
}
--
2.34.1