diff options
author | Haavard Skinnemoen <haavard.skinnemoen@atmel.com> | 2008-07-30 20:29:03 +0200 |
---|---|---|
committer | Haavard Skinnemoen <haavard.skinnemoen@atmel.com> | 2008-10-05 20:39:21 +0200 |
commit | 65e8b083fc8ec303499baa1924ae032d46d29990 (patch) | |
tree | 4c3e1b4cb6c18e2abe55e590b75e97edf4243cc7 /arch/avr32/mach-at32ap | |
parent | 965ebf33ea5afb6386f5b57cc71e6572253746b3 (diff) | |
download | op-kernel-dev-65e8b083fc8ec303499baa1924ae032d46d29990.zip op-kernel-dev-65e8b083fc8ec303499baa1924ae032d46d29990.tar.gz |
atmel-mci: Add experimental DMA support
This adds support for DMA transfers through the generic DMA engine
framework with the DMA slave extensions.
The driver has been tested using mmc-block and ext3fs on several SD,
SDHC and MMC+ cards. Reads and writes work fine, with read transfer
rates up to 7.5 MiB/s on fast cards with debugging disabled.
Unfortunately, the driver has been known to lock up from time to time
with DMA enabled, so DMA support is currently optional and marked
EXPERIMENTAL. However, I didn't see any problems while testing 13
different cards (MMC, SD and SDHC of different brands and sizes), so I
suspect the "Initialize BLKR before sending data transfer command" fix
that was posted earlier fixed this as well.
Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com>
Diffstat (limited to 'arch/avr32/mach-at32ap')
-rw-r--r-- | arch/avr32/mach-at32ap/at32ap700x.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index 9967d5a..f1b9a3a 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -1273,6 +1273,7 @@ struct platform_device *__init at32_add_device_mci(unsigned int id, struct mci_platform_data *data) { struct platform_device *pdev; + struct dw_dma_slave *dws; if (id != 0 || !data) return NULL; @@ -1289,6 +1290,21 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) ARRAY_SIZE(atmel_mci0_resource))) goto fail; + if (data->dma_slave) + dws = kmemdup(to_dw_dma_slave(data->dma_slave), + sizeof(struct dw_dma_slave), GFP_KERNEL); + else + dws = kzalloc(sizeof(struct dw_dma_slave), GFP_KERNEL); + + dws->slave.dev = &pdev->dev; + dws->slave.dma_dev = &dw_dmac0_device.dev; + dws->slave.reg_width = DMA_SLAVE_WIDTH_32BIT; + dws->cfg_hi = (DWC_CFGH_SRC_PER(0) + | DWC_CFGH_DST_PER(1)); + dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL + | DWC_CFGL_HS_SRC_POL); + + data->dma_slave = &dws->slave; if (platform_device_add_data(pdev, data, sizeof(struct mci_platform_data))) |