]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00169906-4 MXS-DMA : change the last parameter of mxs_dma_prep_slave_sg()
authorHuang Shijie <b32955@freescale.com>
Mon, 16 Jan 2012 09:39:12 +0000 (17:39 +0800)
committerOliver Wendt <ow@karo-electronics.de>
Mon, 30 Sep 2013 12:10:36 +0000 (14:10 +0200)
For a long DMA chain which may have more then two DMA Command Structures,
the current DMA code sets the WAIT4END bit at the last one, such as:

+-----+       +-----+    +-----+
| cmd | ------------> | cmd | ------------------>  | cmd |
+-----+       +-----+    +-----+
       ^
       |
       |
      set WAIT4END here

But in the NAND ECC read case, the WAIT4END bit should be set
not only at the last DMA Command Structure, but also at the middle one,
such as:

+-----+       +-----+    +-----+
| cmd | ------------> | cmd | ------------------>  | cmd |
+-----+       +-----+    +-----+
                         ^                            ^
 |                            |
 |                            |
set WAIT4END here too        set WAIT4END here

We set the WAIT4END in the middle DMA Command Structure to ensure
the BCH module finishs its job. If we do not wait in this situation,
the BCH module may be changed in the following DMA Command Structures,
and it maybe becomes unstable which will cause a DMA timeout
This has been catched in the MX6Q board.

So rewrite the last parameter of mxs_dma_prep_slave_sg().
Add some more flags to let the driver sets the WAIT4END as it needs.

Acked-by: Jason Liu <r64343@freescale.com>
Signed-off-by: Huang Shijie <b32955@freescale.com>
drivers/dma/mxs-dma.c

index 6899f811ea1be0b9a9b7423825e439456c23edf7..dda7525674b9f378e5d53fadb566ab546bb1dde8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
  *
  * Refer to drivers/dma/imx-sdma.c
  *
@@ -381,7 +381,7 @@ static void mxs_dma_free_chan_resources(struct dma_chan *chan)
 static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
                struct dma_chan *chan, struct scatterlist *sgl,
                unsigned int sg_len, enum dma_data_direction direction,
-               unsigned long append)
+               unsigned long flags)
 {
        struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
        struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
@@ -390,6 +390,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
        int i, j;
        u32 *pio;
        static int idx;
+       bool append = flags & MXS_DMA_F_APPEND;
 
        if (mxs_chan->status == DMA_IN_PROGRESS && !append)
                return NULL;
@@ -415,7 +416,6 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
                ccw->bits |= CCW_CHAIN;
                ccw->bits &= ~CCW_IRQ;
                ccw->bits &= ~CCW_DEC_SEM;
-               ccw->bits &= ~CCW_WAIT4END;
        } else {
                idx = 0;
        }
@@ -430,7 +430,8 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
                ccw->bits = 0;
                ccw->bits |= CCW_IRQ;
                ccw->bits |= CCW_DEC_SEM;
-               ccw->bits |= CCW_WAIT4END;
+               if (flags & MXS_DMA_F_WAIT4END)
+                       ccw->bits |= CCW_WAIT4END;
                ccw->bits |= CCW_HALT_ON_TERM;
                ccw->bits |= CCW_TERM_FLUSH;
                ccw->bits |= BF_CCW(sg_len, PIO_NUM);
@@ -461,7 +462,8 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
                                ccw->bits &= ~CCW_CHAIN;
                                ccw->bits |= CCW_IRQ;
                                ccw->bits |= CCW_DEC_SEM;
-                               ccw->bits |= CCW_WAIT4END;
+                               if (flags & MXS_DMA_F_WAIT4END)
+                                       ccw->bits |= CCW_WAIT4END;
                        }
                }
        }