diff options
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.patch | 370 |
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 + |