[PATCH 1/5] dmaengine: mxs-dma: add dma support for i.MX23/28
From: Shawn Guo <hidden>
Date: 2011-02-09 00:17:21
On Tue, Feb 08, 2011 at 03:41:55PM +0100, Lothar Wa?mann wrote:
Hi,quoted
On Sat, Feb 05, 2011 at 10:08:12AM +0800, Shawn Guo wrote:quoted
This patch adds dma support for Freescale MXS-based SoC i.MX23/28, including apbh-dma and apbx-dma. * apbh-dma and apbx-dma are supported in the driver as two instances, and have to be filtered by dma clients via device id. It becomes the convention that apbh-dma always gets registered prior to apbx-dma. * apbh-dma is different between mx23 and mx28, hardware version register is used to handle the differences. * Every the mxs dma channel is statically assigned to client device by soc design with fixed irq. The irq number is being passed by alloc_chan function with mxs_dma_data, and client driver has to filter the correct channel by its channel id. * mxs-dma supports pio function besides data transfer. The driver uses dma_data_direction DMA_NONE to identify the pio mode, and steals sgl and sg_len to get pio words and numbers from clients. * mxs dmaengine has some very specific features, like sense function and the special NAND support (nand_lock, nand_wait4ready). These are too specific to implemented in generic dmaengine driver. * The parameter "flags" of prep functions is currently being used to pass wait4end flag from clients. * The driver refers to imx-sdma and only a single descriptor is statically assigned to each channel. Signed-off-by: Shawn Guo <redacted> --- arch/arm/mach-mxs/include/mach/dma.h | 16 + drivers/dma/Kconfig | 8 + drivers/dma/Makefile | 1 + drivers/dma/mxs-dma.c | 702 ++++++++++++++++++++++++++++++++++ 4 files changed, 727 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-mxs/include/mach/dma.h create mode 100644 drivers/dma/mxs-dma.cdiff --git a/arch/arm/mach-mxs/include/mach/dma.h b/arch/arm/mach-mxs/include/mach/dma.h new file mode 100644 index 0000000..429f431 --- /dev/null +++ b/arch/arm/mach-mxs/include/mach/dma.h + +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 flags) +{ + struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); + struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; + struct mxs_dma_ccw *ccw; + struct scatterlist *sg; + int ret, i, j; + u32 *pio; + + dev_dbg(mxs_dma->dev, "%s: channel %d\n", __func__, chan->chan_id); + + if (mxs_chan->status == DMA_IN_PROGRESS) + return NULL; + + mxs_chan->status = DMA_IN_PROGRESS; + mxs_chan->flags = 0; + + dev_dbg(mxs_dma->dev, "%s: setting up %d entries\n", __func__, sg_len); + + if (sg_len > ((direction == DMA_NONE) ? MXS_PIO_WORDS : NUM_CCW)) { + dev_err(mxs_dma->dev, "maximum number of sg exceeded: %d > %d\n", + sg_len, NUM_CCW); + ret = -EINVAL; + goto err_out; + } + + if (direction == DMA_NONE) { + ccw = &mxs_chan->ccw[0]; + pio = (u32 *) sgl; + + for (j = 0; j < sg_len;) + ccw->pio_words[j++] = *pio++; + + ccw->next = 0; + ccw->bits.chain = 0; + ccw->bits.irq = 1; + ccw->bits.dec_sem = 1; + ccw->bits.wait4end = flags; + ccw->bits.halt_on_terminate = 1; + ccw->bits.terminate_flush = 1; + ccw->bits.pio_num = sg_len; + ccw->bits.command = MXS_DMA_NO_XFER;Does this have a valid usecase? I would just return some error code here. pio_num and pio_words are unused in the driver and I don't think a dmaengine driver should have some kind of PIO fallback.Actually 'PIO' is a misnomer here. It's the free scaled way of implementing a simple feature (chained DMA with mixed transfer modes) in a complicated and obfuscated way. What's behinde the 'PIO' transfers is programming controller registers via DMA along with the actual DMA data transfer. DMA_NONE simply means, that the DMA transfer does only the register programming but does not transfer any payload. The 'pio_words' are the values that are being written to consecutive locations of e.g. the SPI controller register address space. The programming is actually done by DMA, in any case.
I'm waiting for this reply ;) i.MX23/28 Reference Manual uses word "PIO" for the working mode that Lothar has explained. It seems that "PIO" in mxs-dma needs some more documents. It's true that mxs dma hardware is designed to program peripheral registers along with data transfer with ccw chain. But it's hard for generic dmaengine model to implement that. The client device driver gets the data in scatter-gather list to transfer. It requires client driver to manipulate the sgl to get pio ccw inserted properly to get the "along with" implemented. This is not a reasonable implementation to me. I still chose to keep the pio mode in the implementation in "single step" rather than "along with" way. That means client driver has to issue one dma request to program client device registers, and issue another one to transfer data. The natural thought is that the pio support can totally be saved with cpu programming. But looking at any mxs dma client device in reference manual, you will find it gets two irq lines, irq_dma and irq_error. For ssp (mmc) example, when one mmc command is issued and completed without error, you have to either polling ssp status register or use pio dma and irq_dma interrupt to know the completion. That's to say I keep the pio support in single ccw way to help client device driver utilize the interrupt capability somehow. Actually, besides the pio mode, mxs dma hardware has some other supports that are incompatible with dmaengine driver model, like sense command and some nand specific supports. I simply chose not implement them. Regards, Shawn