aboutsummaryrefslogtreecommitdiffstats
path: root/recipes-kernel/linux/linux-yocto-3.14/h1940/0015-s3cmci-port-DMA-code-to-dmaengine-API.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-kernel/linux/linux-yocto-3.14/h1940/0015-s3cmci-port-DMA-code-to-dmaengine-API.patch')
-rw-r--r--recipes-kernel/linux/linux-yocto-3.14/h1940/0015-s3cmci-port-DMA-code-to-dmaengine-API.patch370
1 files changed, 370 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-yocto-3.14/h1940/0015-s3cmci-port-DMA-code-to-dmaengine-API.patch b/recipes-kernel/linux/linux-yocto-3.14/h1940/0015-s3cmci-port-DMA-code-to-dmaengine-API.patch
new file mode 100644
index 0000000..735f558
--- /dev/null
+++ b/recipes-kernel/linux/linux-yocto-3.14/h1940/0015-s3cmci-port-DMA-code-to-dmaengine-API.patch
@@ -0,0 +1,370 @@
+From f237d97db372b315f940defc63ffb75b07d903f9 Mon Sep 17 00:00:00 2001
+From: Vasily Khoruzhick <anarsoul@gmail.com>
+Date: Fri, 13 Aug 2010 20:01:53 +0300
+Subject: [PATCH 15/17] s3cmci: port DMA code to dmaengine API
+
+Utilise new s3c24xx-dma dmaengine driver for DMA ops.
+
+Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
+---
+ drivers/mmc/host/Kconfig | 9 ---
+ drivers/mmc/host/s3cmci.c | 183 +++++++++++++++-------------------------------
+ drivers/mmc/host/s3cmci.h | 6 +-
+ 3 files changed, 61 insertions(+), 137 deletions(-)
+
+diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
+index 1384f67..45c791c3 100644
+--- a/drivers/mmc/host/Kconfig
++++ b/drivers/mmc/host/Kconfig
+@@ -457,15 +457,6 @@ config MMC_S3C_DMA
+ working properly and needs to be debugged before this
+ option is useful.
+
+-config MMC_S3C_PIODMA
+- bool "Support for both PIO and DMA"
+- help
+- Compile both the PIO and DMA transfer routines into the
+- driver and let the platform select at run-time which one
+- is best.
+-
+- See notes for the DMA option.
+-
+ endchoice
+
+ config MMC_SDRICOH_CS
+diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
+index f237826..9f32a30 100644
+--- a/drivers/mmc/host/s3cmci.c
++++ b/drivers/mmc/host/s3cmci.c
+@@ -12,6 +12,7 @@
+ */
+
+ #include <linux/module.h>
++#include <linux/dmaengine.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/clk.h>
+ #include <linux/mmc/host.h>
+@@ -24,9 +25,9 @@
+ #include <linux/io.h>
+
+ #include <plat/gpio-cfg.h>
+-#include <mach/dma.h>
+ #include <mach/gpio-samsung.h>
+
++#include <linux/platform_data/dma-s3c24xx.h>
+ #include <linux/platform_data/mmc-s3cmci.h>
+
+ #include "s3cmci.h"
+@@ -140,10 +141,6 @@ static const int dbgmap_debug = dbg_err | dbg_debug;
+ dev_dbg(&host->pdev->dev, args); \
+ } while (0)
+
+-static struct s3c2410_dma_client s3cmci_dma_client = {
+- .name = "s3c-mci",
+-};
+-
+ static void finalize_request(struct s3cmci_host *host);
+ static void s3cmci_send_request(struct mmc_host *mmc);
+ static void s3cmci_reset(struct s3cmci_host *host);
+@@ -256,25 +253,8 @@ static inline bool s3cmci_host_usedma(struct s3cmci_host *host)
+ {
+ #ifdef CONFIG_MMC_S3C_PIO
+ return false;
+-#elif defined(CONFIG_MMC_S3C_DMA)
+- return true;
+-#else
+- return host->dodma;
+-#endif
+-}
+-
+-/**
+- * s3cmci_host_canpio - return true if host has pio code available
+- *
+- * Return true if the driver has been compiled with the PIO support code
+- * available.
+- */
+-static inline bool s3cmci_host_canpio(void)
+-{
+-#ifdef CONFIG_MMC_S3C_PIO
++#else /* CONFIG_MMC_S3C_DMA */
+ return true;
+-#else
+- return false;
+ #endif
+ }
+
+@@ -841,11 +821,9 @@ static irqreturn_t s3cmci_irq_cd(int irq, void *dev_id)
+ return IRQ_HANDLED;
+ }
+
+-static void s3cmci_dma_done_callback(struct s3c2410_dma_chan *dma_ch,
+- void *buf_id, int size,
+- enum s3c2410_dma_buffresult result)
++static void s3cmci_dma_done_callback(void *arg)
+ {
+- struct s3cmci_host *host = buf_id;
++ struct s3cmci_host *host = arg;
+ unsigned long iflags;
+ u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt;
+
+@@ -856,45 +834,17 @@ static void s3cmci_dma_done_callback(struct s3c2410_dma_chan *dma_ch,
+
+ BUG_ON(!host->mrq);
+ BUG_ON(!host->mrq->data);
+- BUG_ON(!host->dmatogo);
+
+ spin_lock_irqsave(&host->complete_lock, iflags);
+
+- if (result != S3C2410_RES_OK) {
+- dbg(host, dbg_fail, "DMA FAILED: csta=0x%08x dsta=0x%08x "
+- "fsta=0x%08x dcnt:0x%08x result:0x%08x toGo:%u\n",
+- mci_csta, mci_dsta, mci_fsta,
+- mci_dcnt, result, host->dmatogo);
+-
+- goto fail_request;
+- }
+-
+- host->dmatogo--;
+- if (host->dmatogo) {
+- dbg(host, dbg_dma, "DMA DONE Size:%i DSTA:[%08x] "
+- "DCNT:[%08x] toGo:%u\n",
+- size, mci_dsta, mci_dcnt, host->dmatogo);
+-
+- goto out;
+- }
+-
+- dbg(host, dbg_dma, "DMA FINISHED Size:%i DSTA:%08x DCNT:%08x\n",
+- size, mci_dsta, mci_dcnt);
++ dbg(host, dbg_dma, "DMA FINISHED\n");
+
+ host->dma_complete = 1;
+ host->complete_what = COMPLETION_FINALIZE;
+
+-out:
+ tasklet_schedule(&host->pio_tasklet);
+ spin_unlock_irqrestore(&host->complete_lock, iflags);
+- return;
+
+-fail_request:
+- host->mrq->data->error = -EINVAL;
+- host->complete_what = COMPLETION_FINALIZE;
+- clear_imask(host);
+-
+- goto out;
+ }
+
+ static void finalize_request(struct s3cmci_host *host)
+@@ -966,7 +916,7 @@ static void finalize_request(struct s3cmci_host *host)
+ * DMA channel and the fifo to clear out any garbage. */
+ if (mrq->data->error != 0) {
+ if (s3cmci_host_usedma(host))
+- s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
++ dmaengine_terminate_all(host->dma);
+
+ if (host->is2440) {
+ /* Clear failure register and reset fifo. */
+@@ -992,29 +942,6 @@ request_done:
+ mmc_request_done(host->mmc, mrq);
+ }
+
+-static void s3cmci_dma_setup(struct s3cmci_host *host,
+- enum dma_data_direction source)
+-{
+- static enum dma_data_direction last_source = -1;
+- static int setup_ok;
+-
+- if (last_source == source)
+- return;
+-
+- last_source = source;
+-
+- s3c2410_dma_devconfig(host->dma, source,
+- host->mem->start + host->sdidata);
+-
+- if (!setup_ok) {
+- s3c2410_dma_config(host->dma, 4);
+- s3c2410_dma_set_buffdone_fn(host->dma,
+- s3cmci_dma_done_callback);
+- s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
+- setup_ok = 1;
+- }
+-}
+-
+ static void s3cmci_send_command(struct s3cmci_host *host,
+ struct mmc_command *cmd)
+ {
+@@ -1162,43 +1089,44 @@ static int s3cmci_prepare_pio(struct s3cmci_host *host, struct mmc_data *data)
+
+ static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
+ {
+- int dma_len, i;
+ int rw = data->flags & MMC_DATA_WRITE;
++ struct dma_slave_config conf = {
++ .src_addr = host->mem->start + host->sdidata,
++ .dst_addr = host->mem->start + host->sdidata,
++ .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
++ .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
++ };
+
+ BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
+
+- s3cmci_dma_setup(host, rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+- s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
+-
+- dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+- rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+-
+- if (dma_len == 0)
+- return -ENOMEM;
+-
+- host->dma_complete = 0;
+- host->dmatogo = dma_len;
+-
+- for (i = 0; i < dma_len; i++) {
+- int res;
+-
+- dbg(host, dbg_dma, "enqueue %i: %08x@%u\n", i,
+- sg_dma_address(&data->sg[i]),
+- sg_dma_len(&data->sg[i]));
++ /* Restore prescaler value */
++ writel(host->prescaler, host->base + S3C2410_SDIPRE);
+
+- res = s3c2410_dma_enqueue(host->dma, host,
+- sg_dma_address(&data->sg[i]),
+- sg_dma_len(&data->sg[i]));
++ if (!rw)
++ conf.direction = DMA_DEV_TO_MEM;
++ else
++ conf.direction = DMA_MEM_TO_DEV;
+
+- if (res) {
+- s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
+- return -EBUSY;
+- }
+- }
++ dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
++ rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+
+- s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_START);
++ dmaengine_slave_config(host->dma, &conf);
++ host->desc = dmaengine_prep_slave_sg(host->dma, data->sg, data->sg_len,
++ conf.direction,
++ DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
++ if (!host->desc)
++ goto unmap_exit;
++ host->desc->callback = s3cmci_dma_done_callback;
++ host->desc->callback_param = host;
++ dmaengine_submit(host->desc);
++ dma_async_issue_pending(host->dma);
+
+ return 0;
++
++unmap_exit:
++ dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
++ rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
++ return -ENOMEM;
+ }
+
+ static void s3cmci_send_request(struct mmc_host *mmc)
+@@ -1676,10 +1604,6 @@ static int s3cmci_probe(struct platform_device *pdev)
+ host->complete_what = COMPLETION_NONE;
+ host->pio_active = XFER_NONE;
+
+-#ifdef CONFIG_MMC_S3C_PIODMA
+- host->dodma = host->pdata->use_dma;
+-#endif
+-
+ host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!host->mem) {
+ dev_err(&pdev->dev,
+@@ -1765,17 +1689,26 @@ static int s3cmci_probe(struct platform_device *pdev)
+ /* depending on the dma state, get a dma channel to use. */
+
+ if (s3cmci_host_usedma(host)) {
+- host->dma = s3c2410_dma_request(DMACH_SDI, &s3cmci_dma_client,
+- host);
+- if (host->dma < 0) {
++ struct resource *res;
++ dma_cap_mask_t mask;
++
++ res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
++ if (!res) {
++ dev_err(&pdev->dev,
++ "failed to get dma resource.\n");
++ ret = -ENOENT;
++ goto probe_free_gpio_wp;
++ }
++
++ dma_cap_zero(mask);
++ dma_cap_set(DMA_SLAVE, mask);
++
++ host->dma = dma_request_channel(mask,
++ s3c24xx_dma_filter, (void *)res->start);
++ if (!host->dma) {
+ dev_err(&pdev->dev, "cannot get DMA channel.\n");
+- if (!s3cmci_host_canpio()) {
+- ret = -EBUSY;
+- goto probe_free_gpio_wp;
+- } else {
+- dev_warn(&pdev->dev, "falling back to PIO.\n");
+- host->dodma = 0;
+- }
++ ret = -EBUSY;
++ goto probe_free_gpio_wp;
+ }
+ }
+
+@@ -1816,7 +1749,7 @@ static int s3cmci_probe(struct platform_device *pdev)
+ mmc->max_segs = 128;
+
+ dbg(host, dbg_debug,
+- "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n",
++ "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%p.\n",
+ (host->is2440?"2440":""),
+ host->base, host->irq, host->irq_cd, host->dma);
+
+@@ -1852,7 +1785,7 @@ static int s3cmci_probe(struct platform_device *pdev)
+
+ probe_free_dma:
+ if (s3cmci_host_usedma(host))
+- s3c2410_dma_free(host->dma, &s3cmci_dma_client);
++ dma_release_channel(host->dma);
+
+ probe_free_gpio_wp:
+ if (!host->pdata->no_wprotect)
+@@ -1914,7 +1847,7 @@ static int s3cmci_remove(struct platform_device *pdev)
+ tasklet_disable(&host->pio_tasklet);
+
+ if (s3cmci_host_usedma(host))
+- s3c2410_dma_free(host->dma, &s3cmci_dma_client);
++ dma_release_channel(host->dma);
+
+ free_irq(host->irq, host);
+
+diff --git a/drivers/mmc/host/s3cmci.h b/drivers/mmc/host/s3cmci.h
+index c76b53d..09dbbcd 100644
+--- a/drivers/mmc/host/s3cmci.h
++++ b/drivers/mmc/host/s3cmci.h
+@@ -26,7 +26,9 @@ struct s3cmci_host {
+ void __iomem *base;
+ int irq;
+ int irq_cd;
+- int dma;
++ struct dma_chan *dma;
++ struct dma_async_tx_descriptor
++ *desc;
+
+ unsigned long clk_rate;
+ unsigned long clk_div;
+@@ -36,8 +38,6 @@ struct s3cmci_host {
+ int is2440;
+ unsigned sdiimsk;
+ unsigned sdidata;
+- int dodma;
+- int dmatogo;
+
+ bool irq_disabled;
+ bool irq_enabled;
+--
+1.9.3
+