aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVasily Khoruzhick <anarsoul@gmail.com>2014-06-01 13:22:09 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2014-07-09 05:26:13 -0400
commitb45e4b5093298e5d42f4a80f95f08e511dc06767 (patch)
treeec73d222490a07b750f1b84a2e92369de6183b21
parent1b3f626e64b50e4ac3bca046c71cfbaec815670d (diff)
mmc: s3cmci: port DMA code to dmaengine API
Utilise new s3c24xx-dma dmaengine driver for DMA ops. Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/host/Kconfig10
-rw-r--r--drivers/mmc/host/s3cmci.c180
-rw-r--r--drivers/mmc/host/s3cmci.h4
3 files changed, 52 insertions, 142 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index a5652548230a..9682ad1e94b5 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -440,6 +440,7 @@ config MMC_SPI
440config MMC_S3C 440config MMC_S3C
441 tristate "Samsung S3C SD/MMC Card Interface support" 441 tristate "Samsung S3C SD/MMC Card Interface support"
442 depends on ARCH_S3C24XX 442 depends on ARCH_S3C24XX
443 depends on S3C24XX_DMAC
443 help 444 help
444 This selects a driver for the MCI interface found in 445 This selects a driver for the MCI interface found in
445 Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs. 446 Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs.
@@ -477,15 +478,6 @@ config MMC_S3C_DMA
477 working properly and needs to be debugged before this 478 working properly and needs to be debugged before this
478 option is useful. 479 option is useful.
479 480
480config MMC_S3C_PIODMA
481 bool "Support for both PIO and DMA"
482 help
483 Compile both the PIO and DMA transfer routines into the
484 driver and let the platform select at run-time which one
485 is best.
486
487 See notes for the DMA option.
488
489endchoice 481endchoice
490 482
491config MMC_SDRICOH_CS 483config MMC_SDRICOH_CS
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 501ec210780c..e5516a226362 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -12,6 +12,7 @@
12 */ 12 */
13 13
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/dmaengine.h>
15#include <linux/dma-mapping.h> 16#include <linux/dma-mapping.h>
16#include <linux/clk.h> 17#include <linux/clk.h>
17#include <linux/mmc/host.h> 18#include <linux/mmc/host.h>
@@ -27,6 +28,7 @@
27#include <mach/dma.h> 28#include <mach/dma.h>
28#include <mach/gpio-samsung.h> 29#include <mach/gpio-samsung.h>
29 30
31#include <linux/platform_data/dma-s3c24xx.h>
30#include <linux/platform_data/mmc-s3cmci.h> 32#include <linux/platform_data/mmc-s3cmci.h>
31 33
32#include "s3cmci.h" 34#include "s3cmci.h"
@@ -140,10 +142,6 @@ static const int dbgmap_debug = dbg_err | dbg_debug;
140 dev_dbg(&host->pdev->dev, args); \ 142 dev_dbg(&host->pdev->dev, args); \
141 } while (0) 143 } while (0)
142 144
143static struct s3c2410_dma_client s3cmci_dma_client = {
144 .name = "s3c-mci",
145};
146
147static void finalize_request(struct s3cmci_host *host); 145static void finalize_request(struct s3cmci_host *host);
148static void s3cmci_send_request(struct mmc_host *mmc); 146static void s3cmci_send_request(struct mmc_host *mmc);
149static void s3cmci_reset(struct s3cmci_host *host); 147static void s3cmci_reset(struct s3cmci_host *host);
@@ -256,25 +254,8 @@ static inline bool s3cmci_host_usedma(struct s3cmci_host *host)
256{ 254{
257#ifdef CONFIG_MMC_S3C_PIO 255#ifdef CONFIG_MMC_S3C_PIO
258 return false; 256 return false;
259#elif defined(CONFIG_MMC_S3C_DMA) 257#else /* CONFIG_MMC_S3C_DMA */
260 return true; 258 return true;
261#else
262 return host->dodma;
263#endif
264}
265
266/**
267 * s3cmci_host_canpio - return true if host has pio code available
268 *
269 * Return true if the driver has been compiled with the PIO support code
270 * available.
271 */
272static inline bool s3cmci_host_canpio(void)
273{
274#ifdef CONFIG_MMC_S3C_PIO
275 return true;
276#else
277 return false;
278#endif 259#endif
279} 260}
280 261
@@ -841,60 +822,24 @@ static irqreturn_t s3cmci_irq_cd(int irq, void *dev_id)
841 return IRQ_HANDLED; 822 return IRQ_HANDLED;
842} 823}
843 824
844static void s3cmci_dma_done_callback(struct s3c2410_dma_chan *dma_ch, 825static void s3cmci_dma_done_callback(void *arg)
845 void *buf_id, int size,
846 enum s3c2410_dma_buffresult result)
847{ 826{
848 struct s3cmci_host *host = buf_id; 827 struct s3cmci_host *host = arg;
849 unsigned long iflags; 828 unsigned long iflags;
850 u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt;
851
852 mci_csta = readl(host->base + S3C2410_SDICMDSTAT);
853 mci_dsta = readl(host->base + S3C2410_SDIDSTA);
854 mci_fsta = readl(host->base + S3C2410_SDIFSTA);
855 mci_dcnt = readl(host->base + S3C2410_SDIDCNT);
856 829
857 BUG_ON(!host->mrq); 830 BUG_ON(!host->mrq);
858 BUG_ON(!host->mrq->data); 831 BUG_ON(!host->mrq->data);
859 BUG_ON(!host->dmatogo);
860 832
861 spin_lock_irqsave(&host->complete_lock, iflags); 833 spin_lock_irqsave(&host->complete_lock, iflags);
862 834
863 if (result != S3C2410_RES_OK) { 835 dbg(host, dbg_dma, "DMA FINISHED\n");
864 dbg(host, dbg_fail, "DMA FAILED: csta=0x%08x dsta=0x%08x "
865 "fsta=0x%08x dcnt:0x%08x result:0x%08x toGo:%u\n",
866 mci_csta, mci_dsta, mci_fsta,
867 mci_dcnt, result, host->dmatogo);
868
869 goto fail_request;
870 }
871
872 host->dmatogo--;
873 if (host->dmatogo) {
874 dbg(host, dbg_dma, "DMA DONE Size:%i DSTA:[%08x] "
875 "DCNT:[%08x] toGo:%u\n",
876 size, mci_dsta, mci_dcnt, host->dmatogo);
877
878 goto out;
879 }
880
881 dbg(host, dbg_dma, "DMA FINISHED Size:%i DSTA:%08x DCNT:%08x\n",
882 size, mci_dsta, mci_dcnt);
883 836
884 host->dma_complete = 1; 837 host->dma_complete = 1;
885 host->complete_what = COMPLETION_FINALIZE; 838 host->complete_what = COMPLETION_FINALIZE;
886 839
887out:
888 tasklet_schedule(&host->pio_tasklet); 840 tasklet_schedule(&host->pio_tasklet);
889 spin_unlock_irqrestore(&host->complete_lock, iflags); 841 spin_unlock_irqrestore(&host->complete_lock, iflags);
890 return;
891 842
892fail_request:
893 host->mrq->data->error = -EINVAL;
894 host->complete_what = COMPLETION_FINALIZE;
895 clear_imask(host);
896
897 goto out;
898} 843}
899 844
900static void finalize_request(struct s3cmci_host *host) 845static void finalize_request(struct s3cmci_host *host)
@@ -966,7 +911,7 @@ static void finalize_request(struct s3cmci_host *host)
966 * DMA channel and the fifo to clear out any garbage. */ 911 * DMA channel and the fifo to clear out any garbage. */
967 if (mrq->data->error != 0) { 912 if (mrq->data->error != 0) {
968 if (s3cmci_host_usedma(host)) 913 if (s3cmci_host_usedma(host))
969 s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH); 914 dmaengine_terminate_all(host->dma);
970 915
971 if (host->is2440) { 916 if (host->is2440) {
972 /* Clear failure register and reset fifo. */ 917 /* Clear failure register and reset fifo. */
@@ -992,29 +937,6 @@ request_done:
992 mmc_request_done(host->mmc, mrq); 937 mmc_request_done(host->mmc, mrq);
993} 938}
994 939
995static void s3cmci_dma_setup(struct s3cmci_host *host,
996 enum dma_data_direction source)
997{
998 static enum dma_data_direction last_source = -1;
999 static int setup_ok;
1000
1001 if (last_source == source)
1002 return;
1003
1004 last_source = source;
1005
1006 s3c2410_dma_devconfig(host->dma, source,
1007 host->mem->start + host->sdidata);
1008
1009 if (!setup_ok) {
1010 s3c2410_dma_config(host->dma, 4);
1011 s3c2410_dma_set_buffdone_fn(host->dma,
1012 s3cmci_dma_done_callback);
1013 s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
1014 setup_ok = 1;
1015 }
1016}
1017
1018static void s3cmci_send_command(struct s3cmci_host *host, 940static void s3cmci_send_command(struct s3cmci_host *host,
1019 struct mmc_command *cmd) 941 struct mmc_command *cmd)
1020{ 942{
@@ -1162,43 +1084,45 @@ static int s3cmci_prepare_pio(struct s3cmci_host *host, struct mmc_data *data)
1162 1084
1163static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data) 1085static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
1164{ 1086{
1165 int dma_len, i;
1166 int rw = data->flags & MMC_DATA_WRITE; 1087 int rw = data->flags & MMC_DATA_WRITE;
1088 struct dma_async_tx_descriptor *desc;
1089 struct dma_slave_config conf = {
1090 .src_addr = host->mem->start + host->sdidata,
1091 .dst_addr = host->mem->start + host->sdidata,
1092 .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
1093 .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
1094 };
1167 1095
1168 BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR); 1096 BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
1169 1097
1170 s3cmci_dma_setup(host, rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE); 1098 /* Restore prescaler value */
1171 s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH); 1099 writel(host->prescaler, host->base + S3C2410_SDIPRE);
1172
1173 dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
1174 rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
1175
1176 if (dma_len == 0)
1177 return -ENOMEM;
1178
1179 host->dma_complete = 0;
1180 host->dmatogo = dma_len;
1181
1182 for (i = 0; i < dma_len; i++) {
1183 int res;
1184
1185 dbg(host, dbg_dma, "enqueue %i: %08x@%u\n", i,
1186 sg_dma_address(&data->sg[i]),
1187 sg_dma_len(&data->sg[i]));
1188 1100
1189 res = s3c2410_dma_enqueue(host->dma, host, 1101 if (!rw)
1190 sg_dma_address(&data->sg[i]), 1102 conf.direction = DMA_DEV_TO_MEM;
1191 sg_dma_len(&data->sg[i])); 1103 else
1104 conf.direction = DMA_MEM_TO_DEV;
1192 1105
1193 if (res) { 1106 dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
1194 s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH); 1107 rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
1195 return -EBUSY;
1196 }
1197 }
1198 1108
1199 s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_START); 1109 dmaengine_slave_config(host->dma, &conf);
1110 desc = dmaengine_prep_slave_sg(host->dma, data->sg, data->sg_len,
1111 conf.direction,
1112 DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
1113 if (!desc)
1114 goto unmap_exit;
1115 desc->callback = s3cmci_dma_done_callback;
1116 desc->callback_param = host;
1117 dmaengine_submit(desc);
1118 dma_async_issue_pending(host->dma);
1200 1119
1201 return 0; 1120 return 0;
1121
1122unmap_exit:
1123 dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
1124 rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
1125 return -ENOMEM;
1202} 1126}
1203 1127
1204static void s3cmci_send_request(struct mmc_host *mmc) 1128static void s3cmci_send_request(struct mmc_host *mmc)
@@ -1676,10 +1600,6 @@ static int s3cmci_probe(struct platform_device *pdev)
1676 host->complete_what = COMPLETION_NONE; 1600 host->complete_what = COMPLETION_NONE;
1677 host->pio_active = XFER_NONE; 1601 host->pio_active = XFER_NONE;
1678 1602
1679#ifdef CONFIG_MMC_S3C_PIODMA
1680 host->dodma = host->pdata->use_dma;
1681#endif
1682
1683 host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1603 host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1684 if (!host->mem) { 1604 if (!host->mem) {
1685 dev_err(&pdev->dev, 1605 dev_err(&pdev->dev,
@@ -1765,17 +1685,17 @@ static int s3cmci_probe(struct platform_device *pdev)
1765 /* depending on the dma state, get a dma channel to use. */ 1685 /* depending on the dma state, get a dma channel to use. */
1766 1686
1767 if (s3cmci_host_usedma(host)) { 1687 if (s3cmci_host_usedma(host)) {
1768 host->dma = s3c2410_dma_request(DMACH_SDI, &s3cmci_dma_client, 1688 dma_cap_mask_t mask;
1769 host); 1689
1770 if (host->dma < 0) { 1690 dma_cap_zero(mask);
1691 dma_cap_set(DMA_SLAVE, mask);
1692
1693 host->dma = dma_request_slave_channel_compat(mask,
1694 s3c24xx_dma_filter, (void *)DMACH_SDI, &pdev->dev, "rx-tx");
1695 if (!host->dma) {
1771 dev_err(&pdev->dev, "cannot get DMA channel.\n"); 1696 dev_err(&pdev->dev, "cannot get DMA channel.\n");
1772 if (!s3cmci_host_canpio()) { 1697 ret = -EBUSY;
1773 ret = -EBUSY; 1698 goto probe_free_gpio_wp;
1774 goto probe_free_gpio_wp;
1775 } else {
1776 dev_warn(&pdev->dev, "falling back to PIO.\n");
1777 host->dodma = 0;
1778 }
1779 } 1699 }
1780 } 1700 }
1781 1701
@@ -1816,7 +1736,7 @@ static int s3cmci_probe(struct platform_device *pdev)
1816 mmc->max_segs = 128; 1736 mmc->max_segs = 128;
1817 1737
1818 dbg(host, dbg_debug, 1738 dbg(host, dbg_debug,
1819 "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n", 1739 "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%p.\n",
1820 (host->is2440?"2440":""), 1740 (host->is2440?"2440":""),
1821 host->base, host->irq, host->irq_cd, host->dma); 1741 host->base, host->irq, host->irq_cd, host->dma);
1822 1742
@@ -1852,7 +1772,7 @@ static int s3cmci_probe(struct platform_device *pdev)
1852 1772
1853 probe_free_dma: 1773 probe_free_dma:
1854 if (s3cmci_host_usedma(host)) 1774 if (s3cmci_host_usedma(host))
1855 s3c2410_dma_free(host->dma, &s3cmci_dma_client); 1775 dma_release_channel(host->dma);
1856 1776
1857 probe_free_gpio_wp: 1777 probe_free_gpio_wp:
1858 if (!host->pdata->no_wprotect) 1778 if (!host->pdata->no_wprotect)
@@ -1914,7 +1834,7 @@ static int s3cmci_remove(struct platform_device *pdev)
1914 tasklet_disable(&host->pio_tasklet); 1834 tasklet_disable(&host->pio_tasklet);
1915 1835
1916 if (s3cmci_host_usedma(host)) 1836 if (s3cmci_host_usedma(host))
1917 s3c2410_dma_free(host->dma, &s3cmci_dma_client); 1837 dma_release_channel(host->dma);
1918 1838
1919 free_irq(host->irq, host); 1839 free_irq(host->irq, host);
1920 1840
diff --git a/drivers/mmc/host/s3cmci.h b/drivers/mmc/host/s3cmci.h
index c76b53dbeb61..cc2e46cb5c64 100644
--- a/drivers/mmc/host/s3cmci.h
+++ b/drivers/mmc/host/s3cmci.h
@@ -26,7 +26,7 @@ struct s3cmci_host {
26 void __iomem *base; 26 void __iomem *base;
27 int irq; 27 int irq;
28 int irq_cd; 28 int irq_cd;
29 int dma; 29 struct dma_chan *dma;
30 30
31 unsigned long clk_rate; 31 unsigned long clk_rate;
32 unsigned long clk_div; 32 unsigned long clk_div;
@@ -36,8 +36,6 @@ struct s3cmci_host {
36 int is2440; 36 int is2440;
37 unsigned sdiimsk; 37 unsigned sdiimsk;
38 unsigned sdidata; 38 unsigned sdidata;
39 int dodma;
40 int dmatogo;
41 39
42 bool irq_disabled; 40 bool irq_disabled;
43 bool irq_enabled; 41 bool irq_enabled;