@@ -245,6 +245,7 @@ struct bcm2835_desc {
245
245
#define BCM2711_DMA40_ERR BIT(10)
246
246
#define BCM2711_DMA40_QOS (x ) (((x) & 0x1f) << 16)
247
247
#define BCM2711_DMA40_PANIC_QOS (x ) (((x) & 0x1f) << 20)
248
+ #define BCM2711_DMA40_TRANSACTIONS BIT(25)
248
249
#define BCM2711_DMA40_WAIT_FOR_WRITES BIT(28)
249
250
#define BCM2711_DMA40_DISDEBUG BIT(29)
250
251
#define BCM2711_DMA40_ABORT BIT(30)
@@ -665,28 +666,30 @@ static void bcm2835_dma_abort(struct bcm2835_chan *c)
665
666
void __iomem * chan_base = c -> chan_base ;
666
667
long int timeout = 10000 ;
667
668
668
- /*
669
- * A zero control block address means the channel is idle.
670
- * (The ACTIVE flag in the CS register is not a reliable indicator.)
671
- */
672
- if (!readl (chan_base + BCM2835_DMA_ADDR ))
673
- return ;
674
-
675
669
if (c -> is_40bit_channel ) {
676
- /* Halt the current DMA */
677
- writel (readl (chan_base + BCM2711_DMA40_CS ) | BCM2711_DMA40_HALT ,
670
+ /*
671
+ * A zero control block address means the channel is idle.
672
+ * (The ACTIVE flag in the CS register is not a reliable indicator.)
673
+ */
674
+ if (!readl (chan_base + BCM2711_DMA40_CB ))
675
+ return ;
676
+
677
+ /* Pause the current DMA */
678
+ writel (readl (chan_base + BCM2711_DMA40_CS ) & ~BCM2711_DMA40_ACTIVE ,
678
679
chan_base + BCM2711_DMA40_CS );
679
680
680
- while ((readl (chan_base + BCM2711_DMA40_CS ) & BCM2711_DMA40_HALT ) && -- timeout )
681
+ /* wait for outstanding transactions to complete */
682
+ while ((readl (chan_base + BCM2711_DMA40_CS ) & BCM2711_DMA40_TRANSACTIONS ) && -- timeout )
681
683
cpu_relax ();
682
684
683
- /* Peripheral might be stuck and fail to halt */
685
+ /* Peripheral might be stuck and fail to complete */
684
686
if (!timeout )
685
687
dev_err (c -> vc .chan .device -> dev ,
686
- "failed to halt dma\n" );
688
+ "failed to complete pause on dma %d (CS:%08x)\n" , c -> ch ,
689
+ readl (chan_base + BCM2711_DMA40_CS ));
687
690
688
- writel ( BCM2711_DMA40_PROT , chan_base + BCM2711_DMA40_CS );
689
- writel (0 , chan_base + BCM2711_DMA40_CB );
691
+ /* Reset the DMA */
692
+ writel (BCM2711_DMA40_DEBUG_RESET , chan_base + BCM2711_DMA40_DEBUG );
690
693
} else {
691
694
/*
692
695
* A zero control block address means the channel is idle.
@@ -704,27 +707,15 @@ static void bcm2835_dma_abort(struct bcm2835_chan *c)
704
707
&& -- timeout )
705
708
cpu_relax ();
706
709
707
- /* Peripheral might be stuck and fail to signal AXI write responses */
710
+ /* Peripheral might be stuck and fail to complete */
708
711
if (!timeout )
709
712
dev_err (c -> vc .chan .device -> dev ,
710
- "failed to pause dma\n" );
713
+ "failed to complete pause on dma %d (CS:%08x)\n" , c -> ch ,
714
+ readl (chan_base + BCM2835_DMA_CS ));
711
715
712
- /* We need to clear the next DMA block pending */
713
- writel (0 , chan_base + BCM2835_DMA_NEXTCB );
714
-
715
- /* Abort the DMA, which needs to be enabled to complete */
716
- writel (readl (chan_base + BCM2835_DMA_CS ) | BCM2835_DMA_ABORT | BCM2835_DMA_ACTIVE ,
717
- chan_base + BCM2835_DMA_CS );
718
-
719
- /* wait for DMA to have been aborted */
720
- timeout = 10000 ;
721
- while ((readl (chan_base + BCM2835_DMA_CS ) & BCM2835_DMA_ABORT ) && -- timeout )
722
- cpu_relax ();
723
-
724
- /* Peripheral might be stuck and fail to signal AXI write responses */
725
- if (!timeout )
726
- dev_err (c -> vc .chan .device -> dev ,
727
- "failed to abort dma\n" );
716
+ /* Reset the DMA */
717
+ writel (readl (chan_base + BCM2835_DMA_CS ) | BCM2835_DMA_RESET ,
718
+ chan_base + BCM2835_DMA_CS );
728
719
}
729
720
}
730
721
0 commit comments