Blackfin: dma_memcpy(): fix random failures
We have to make sure the DMA channel is actually disabled in hardware before
attempting to reprogram it. Otherwise the new settings are ignored and we
end up with random hangs/failures.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
diff --git a/lib_blackfin/string.c b/lib_blackfin/string.c
index 36eecdf..e458718 100644
--- a/lib_blackfin/string.c
+++ b/lib_blackfin/string.c
@@ -136,6 +136,14 @@
*/
void dma_memcpy_nocache(void *dst, const void *src, size_t count)
{
+ /* Disable DMA in case it's still running (older u-boot's did not
+ * always turn them off). Do it before the if statement below so
+ * we can be cheap and not do a SSYNC() due to the forced abort.
+ */
+ bfin_write_MDMA_D0_CONFIG(0);
+ bfin_write_MDMA_S0_CONFIG(0);
+ bfin_write_MDMA_D0_IRQ_STATUS(DMA_RUN | DMA_DONE | DMA_ERR);
+
/* Scratchpad cannot be a DMA source or destination */
if (((unsigned long)src >= L1_SRAM_SCRATCH &&
(unsigned long)src < L1_SRAM_SCRATCH_END) ||
@@ -143,10 +151,6 @@
(unsigned long)dst < L1_SRAM_SCRATCH_END))
hang();
- bfin_write_MDMA_S0_CONFIG(0);
- bfin_write_MDMA_D0_CONFIG(0);
- bfin_write_MDMA_D0_IRQ_STATUS(DMA_RUN | DMA_DONE | DMA_ERR);
-
/* Copy sram functions from sdram to sram */
/* Setup destination start address */
bfin_write_MDMA_D0_START_ADDR(dst);
@@ -164,14 +168,13 @@
/* Enable source DMA */
bfin_write_MDMA_S0_CONFIG(DMAEN);
-
- bfin_write_MDMA_D0_CONFIG(WNR | DMAEN);
+ bfin_write_MDMA_D0_CONFIG(WNR | DMAEN | DI_EN);
SSYNC();
- while (bfin_read_MDMA_D0_IRQ_STATUS() & DMA_RUN)
+ while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE))
continue;
- bfin_write_MDMA_D0_IRQ_STATUS(bfin_read_MDMA_D0_IRQ_STATUS() | DMA_RUN | DMA_DONE | DMA_ERR);
+ bfin_write_MDMA_D0_IRQ_STATUS(DMA_RUN | DMA_DONE | DMA_ERR);
bfin_write_MDMA_D0_CONFIG(0);
bfin_write_MDMA_S0_CONFIG(0);
}