@@ -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)
@@ -663,30 +664,37 @@ static void bcm2835_dma_fill_cb_chain_with_sg(
663
664
static void bcm2835_dma_abort (struct bcm2835_chan * c )
664
665
{
665
666
void __iomem * chan_base = c -> chan_base ;
666
- long int timeout = 10000 ;
667
-
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 ;
667
+ long int timeout = 100 ;
674
668
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 ) &&
683
+ -- timeout )
681
684
cpu_relax ();
682
685
683
- /* Peripheral might be stuck and fail to halt */
686
+ /* Peripheral might be stuck and fail to complete */
684
687
if (!timeout )
685
688
dev_err (c -> vc .chan .device -> dev ,
686
- "failed to halt dma\n" );
689
+ "failed to complete pause on dma %d (CS:%08x)\n" , c -> ch ,
690
+ readl (chan_base + BCM2711_DMA40_CS ));
687
691
692
+ /* Set CS back to default state */
688
693
writel (BCM2711_DMA40_PROT , chan_base + BCM2711_DMA40_CS );
689
- writel (0 , chan_base + BCM2711_DMA40_CB );
694
+
695
+ /* Reset the DMA */
696
+ writel (readl (chan_base + BCM2711_DMA40_DEBUG ) | BCM2711_DMA40_DEBUG_RESET ,
697
+ chan_base + BCM2711_DMA40_DEBUG );
690
698
} else {
691
699
/*
692
700
* A zero control block address means the channel is idle.
@@ -695,36 +703,34 @@ static void bcm2835_dma_abort(struct bcm2835_chan *c)
695
703
if (!readl (chan_base + BCM2835_DMA_ADDR ))
696
704
return ;
697
705
698
- /* Write 0 to the active bit - Pause the DMA */
699
- writel (readl (chan_base + BCM2835_DMA_CS ) & ~BCM2835_DMA_ACTIVE ,
700
- chan_base + BCM2835_DMA_CS );
701
-
702
- /* wait for DMA to be paused */
703
- while ((readl (chan_base + BCM2835_DMA_CS ) & BCM2835_DMA_WAITING_FOR_WRITES )
704
- && -- timeout )
705
- cpu_relax ();
706
-
707
- /* Peripheral might be stuck and fail to signal AXI write responses */
708
- if (!timeout )
709
- dev_err (c -> vc .chan .device -> dev ,
710
- "failed to pause dma\n" );
711
-
712
706
/* We need to clear the next DMA block pending */
713
707
writel (0 , chan_base + BCM2835_DMA_NEXTCB );
714
708
715
709
/* Abort the DMA, which needs to be enabled to complete */
716
710
writel (readl (chan_base + BCM2835_DMA_CS ) | BCM2835_DMA_ABORT | BCM2835_DMA_ACTIVE ,
717
- chan_base + BCM2835_DMA_CS );
711
+ chan_base + BCM2835_DMA_CS );
718
712
719
- /* wait for DMA to have been aborted */
720
- timeout = 10000 ;
713
+ /* wait for DMA to be aborted */
721
714
while ((readl (chan_base + BCM2835_DMA_CS ) & BCM2835_DMA_ABORT ) && -- timeout )
722
715
cpu_relax ();
723
716
724
- /* Peripheral might be stuck and fail to signal AXI write responses */
725
- if (!timeout )
717
+ /* Write 0 to the active bit - Pause the DMA */
718
+ writel (readl (chan_base + BCM2835_DMA_CS ) & ~BCM2835_DMA_ACTIVE ,
719
+ chan_base + BCM2835_DMA_CS );
720
+
721
+ /*
722
+ * Peripheral might be stuck and fail to complete
723
+ * This is expected when dreqs are enabled but not asserted
724
+ * so only report error in non dreq case
725
+ */
726
+ if (!timeout && !(readl (chan_base + BCM2835_DMA_TI ) &
727
+ (BCM2835_DMA_S_DREQ | BCM2835_DMA_D_DREQ )))
726
728
dev_err (c -> vc .chan .device -> dev ,
727
- "failed to abort dma\n" );
729
+ "failed to complete pause on dma %d (CS:%08x)\n" , c -> ch ,
730
+ readl (chan_base + BCM2835_DMA_CS ));
731
+
732
+ /* Set CS back to default state and reset the DMA */
733
+ writel (BCM2835_DMA_RESET , chan_base + BCM2835_DMA_CS );
728
734
}
729
735
}
730
736
0 commit comments