aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2011-02-18 04:21:09 -0500
committerChris Ball <cjb@laptop.org>2011-03-15 13:49:32 -0400
commitf53fbde48ef0a5ce7733fbc84da18014d0a11cf0 (patch)
tree2b4114de4c09fcddd437f395a6c4f6042fa5c2be /drivers
parentc9b2a06fb0efda37241861915a8639c27bddaa85 (diff)
mmc: mxcmmc: use dmaengine API
This switches the mxcmmc driver to use the dmaengine API. Unlike the old one this one is always present in the tree, even if no DMA is implemented, hence we can remove all the #ifdefs in from the driver. The driver automatically switches to PIO mode if no DMA support or no suitable channel is available. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/mxcmmc.c181
1 files changed, 104 insertions, 77 deletions
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index 4428594261c5..cc20e0259325 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -32,16 +32,14 @@
32#include <linux/io.h> 32#include <linux/io.h>
33#include <linux/gpio.h> 33#include <linux/gpio.h>
34#include <linux/regulator/consumer.h> 34#include <linux/regulator/consumer.h>
35#include <linux/dmaengine.h>
35 36
36#include <asm/dma.h> 37#include <asm/dma.h>
37#include <asm/irq.h> 38#include <asm/irq.h>
38#include <asm/sizes.h> 39#include <asm/sizes.h>
39#include <mach/mmc.h> 40#include <mach/mmc.h>
40 41
41#ifdef CONFIG_ARCH_MX2 42#include <mach/dma.h>
42#include <mach/dma-mx1-mx2.h>
43#define HAS_DMA
44#endif
45 43
46#define DRIVER_NAME "mxc-mmc" 44#define DRIVER_NAME "mxc-mmc"
47 45
@@ -118,7 +116,8 @@ struct mxcmci_host {
118 void __iomem *base; 116 void __iomem *base;
119 int irq; 117 int irq;
120 int detect_irq; 118 int detect_irq;
121 int dma; 119 struct dma_chan *dma;
120 struct dma_async_tx_descriptor *desc;
122 int do_dma; 121 int do_dma;
123 int default_irq_mask; 122 int default_irq_mask;
124 int use_sdio; 123 int use_sdio;
@@ -129,7 +128,6 @@ struct mxcmci_host {
129 struct mmc_command *cmd; 128 struct mmc_command *cmd;
130 struct mmc_data *data; 129 struct mmc_data *data;
131 130
132 unsigned int dma_nents;
133 unsigned int datasize; 131 unsigned int datasize;
134 unsigned int dma_dir; 132 unsigned int dma_dir;
135 133
@@ -144,6 +142,11 @@ struct mxcmci_host {
144 spinlock_t lock; 142 spinlock_t lock;
145 143
146 struct regulator *vcc; 144 struct regulator *vcc;
145
146 int burstlen;
147 int dmareq;
148 struct dma_slave_config dma_slave_config;
149 struct imx_dma_data dma_data;
147}; 150};
148 151
149static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); 152static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);
@@ -206,17 +209,16 @@ static void mxcmci_softreset(struct mxcmci_host *host)
206 209
207 writew(0xff, host->base + MMC_REG_RES_TO); 210 writew(0xff, host->base + MMC_REG_RES_TO);
208} 211}
212static int mxcmci_setup_dma(struct mmc_host *mmc);
209 213
210static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) 214static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
211{ 215{
212 unsigned int nob = data->blocks; 216 unsigned int nob = data->blocks;
213 unsigned int blksz = data->blksz; 217 unsigned int blksz = data->blksz;
214 unsigned int datasize = nob * blksz; 218 unsigned int datasize = nob * blksz;
215#ifdef HAS_DMA
216 struct scatterlist *sg; 219 struct scatterlist *sg;
217 int i; 220 int i, nents;
218 int ret; 221
219#endif
220 if (data->flags & MMC_DATA_STREAM) 222 if (data->flags & MMC_DATA_STREAM)
221 nob = 0xffff; 223 nob = 0xffff;
222 224
@@ -227,7 +229,9 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
227 writew(blksz, host->base + MMC_REG_BLK_LEN); 229 writew(blksz, host->base + MMC_REG_BLK_LEN);
228 host->datasize = datasize; 230 host->datasize = datasize;
229 231
230#ifdef HAS_DMA 232 if (!mxcmci_use_dma(host))
233 return 0;
234
231 for_each_sg(data->sg, sg, data->sg_len, i) { 235 for_each_sg(data->sg, sg, data->sg_len, i) {
232 if (sg->offset & 3 || sg->length & 3) { 236 if (sg->offset & 3 || sg->length & 3) {
233 host->do_dma = 0; 237 host->do_dma = 0;
@@ -235,34 +239,30 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
235 } 239 }
236 } 240 }
237 241
238 if (data->flags & MMC_DATA_READ) { 242 if (data->flags & MMC_DATA_READ)
239 host->dma_dir = DMA_FROM_DEVICE; 243 host->dma_dir = DMA_FROM_DEVICE;
240 host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, 244 else
241 data->sg_len, host->dma_dir);
242
243 ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents,
244 datasize,
245 host->res->start + MMC_REG_BUFFER_ACCESS,
246 DMA_MODE_READ);
247 } else {
248 host->dma_dir = DMA_TO_DEVICE; 245 host->dma_dir = DMA_TO_DEVICE;
249 host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
250 data->sg_len, host->dma_dir);
251 246
252 ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, 247 nents = dma_map_sg(host->dma->device->dev, data->sg,
253 datasize, 248 data->sg_len, host->dma_dir);
254 host->res->start + MMC_REG_BUFFER_ACCESS, 249 if (nents != data->sg_len)
255 DMA_MODE_WRITE); 250 return -EINVAL;
256 } 251
252 host->desc = host->dma->device->device_prep_slave_sg(host->dma,
253 data->sg, data->sg_len, host->dma_dir,
254 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
257 255
258 if (ret) { 256 if (!host->desc) {
259 dev_err(mmc_dev(host->mmc), "failed to setup DMA : %d\n", ret); 257 dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len,
260 return ret; 258 host->dma_dir);
259 host->do_dma = 0;
260 return 0; /* Fall back to PIO */
261 } 261 }
262 wmb(); 262 wmb();
263 263
264 imx_dma_enable(host->dma); 264 dmaengine_submit(host->desc);
265#endif /* HAS_DMA */ 265
266 return 0; 266 return 0;
267} 267}
268 268
@@ -337,13 +337,11 @@ static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat)
337 struct mmc_data *data = host->data; 337 struct mmc_data *data = host->data;
338 int data_error; 338 int data_error;
339 339
340#ifdef HAS_DMA
341 if (mxcmci_use_dma(host)) { 340 if (mxcmci_use_dma(host)) {
342 imx_dma_disable(host->dma); 341 dmaengine_terminate_all(host->dma);
343 dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_nents, 342 dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len,
344 host->dma_dir); 343 host->dma_dir);
345 } 344 }
346#endif
347 345
348 if (stat & STATUS_ERR_MASK) { 346 if (stat & STATUS_ERR_MASK) {
349 dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", 347 dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",
@@ -545,7 +543,6 @@ static void mxcmci_datawork(struct work_struct *work)
545 } 543 }
546} 544}
547 545
548#ifdef HAS_DMA
549static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat) 546static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat)
550{ 547{
551 struct mmc_data *data = host->data; 548 struct mmc_data *data = host->data;
@@ -568,7 +565,6 @@ static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat)
568 mxcmci_finish_request(host, host->req); 565 mxcmci_finish_request(host, host->req);
569 } 566 }
570} 567}
571#endif /* HAS_DMA */
572 568
573static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat) 569static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat)
574{ 570{
@@ -606,12 +602,10 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
606 sdio_irq = (stat & STATUS_SDIO_INT_ACTIVE) && host->use_sdio; 602 sdio_irq = (stat & STATUS_SDIO_INT_ACTIVE) && host->use_sdio;
607 spin_unlock_irqrestore(&host->lock, flags); 603 spin_unlock_irqrestore(&host->lock, flags);
608 604
609#ifdef HAS_DMA
610 if (mxcmci_use_dma(host) && 605 if (mxcmci_use_dma(host) &&
611 (stat & (STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE))) 606 (stat & (STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE)))
612 writel(STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE, 607 writel(STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE,
613 host->base + MMC_REG_STATUS); 608 host->base + MMC_REG_STATUS);
614#endif
615 609
616 if (sdio_irq) { 610 if (sdio_irq) {
617 writel(STATUS_SDIO_INT_ACTIVE, host->base + MMC_REG_STATUS); 611 writel(STATUS_SDIO_INT_ACTIVE, host->base + MMC_REG_STATUS);
@@ -621,14 +615,14 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
621 if (stat & STATUS_END_CMD_RESP) 615 if (stat & STATUS_END_CMD_RESP)
622 mxcmci_cmd_done(host, stat); 616 mxcmci_cmd_done(host, stat);
623 617
624#ifdef HAS_DMA
625 if (mxcmci_use_dma(host) && 618 if (mxcmci_use_dma(host) &&
626 (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) 619 (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE)))
627 mxcmci_data_done(host, stat); 620 mxcmci_data_done(host, stat);
628#endif 621
629 if (host->default_irq_mask && 622 if (host->default_irq_mask &&
630 (stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL))) 623 (stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL)))
631 mmc_detect_change(host->mmc, msecs_to_jiffies(200)); 624 mmc_detect_change(host->mmc, msecs_to_jiffies(200));
625
632 return IRQ_HANDLED; 626 return IRQ_HANDLED;
633} 627}
634 628
@@ -642,9 +636,10 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req)
642 636
643 host->req = req; 637 host->req = req;
644 host->cmdat &= ~CMD_DAT_CONT_INIT; 638 host->cmdat &= ~CMD_DAT_CONT_INIT;
645#ifdef HAS_DMA 639
646 host->do_dma = 1; 640 if (host->dma)
647#endif 641 host->do_dma = 1;
642
648 if (req->data) { 643 if (req->data) {
649 error = mxcmci_setup_data(host, req->data); 644 error = mxcmci_setup_data(host, req->data);
650 if (error) { 645 if (error) {
@@ -660,6 +655,7 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req)
660 } 655 }
661 656
662 error = mxcmci_start_cmd(host, req->cmd, cmdat); 657 error = mxcmci_start_cmd(host, req->cmd, cmdat);
658
663out: 659out:
664 if (error) 660 if (error)
665 mxcmci_finish_request(host, req); 661 mxcmci_finish_request(host, req);
@@ -698,22 +694,46 @@ static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios)
698 prescaler, divider, clk_in, clk_ios); 694 prescaler, divider, clk_in, clk_ios);
699} 695}
700 696
697static int mxcmci_setup_dma(struct mmc_host *mmc)
698{
699 struct mxcmci_host *host = mmc_priv(mmc);
700 struct dma_slave_config *config = &host->dma_slave_config;
701
702 config->dst_addr = host->res->start + MMC_REG_BUFFER_ACCESS;
703 config->src_addr = host->res->start + MMC_REG_BUFFER_ACCESS;
704 config->dst_addr_width = 4;
705 config->src_addr_width = 4;
706 config->dst_maxburst = host->burstlen;
707 config->src_maxburst = host->burstlen;
708
709 return dmaengine_slave_config(host->dma, config);
710}
711
701static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 712static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
702{ 713{
703 struct mxcmci_host *host = mmc_priv(mmc); 714 struct mxcmci_host *host = mmc_priv(mmc);
704#ifdef HAS_DMA 715 int burstlen, ret;
705 unsigned int blen; 716
706 /* 717 /*
707 * use burstlen of 64 in 4 bit mode (--> reg value 0) 718 * use burstlen of 64 in 4 bit mode (--> reg value 0)
708 * use burstlen of 16 in 1 bit mode (--> reg value 16) 719 * use burstlen of 16 in 1 bit mode (--> reg value 16)
709 */ 720 */
710 if (ios->bus_width == MMC_BUS_WIDTH_4) 721 if (ios->bus_width == MMC_BUS_WIDTH_4)
711 blen = 0; 722 burstlen = 64;
712 else 723 else
713 blen = 16; 724 burstlen = 16;
725
726 if (mxcmci_use_dma(host) && burstlen != host->burstlen) {
727 host->burstlen = burstlen;
728 ret = mxcmci_setup_dma(mmc);
729 if (ret) {
730 dev_err(mmc_dev(host->mmc),
731 "failed to config DMA channel. Falling back to PIO\n");
732 dma_release_channel(host->dma);
733 host->do_dma = 0;
734 }
735 }
714 736
715 imx_dma_config_burstlen(host->dma, blen);
716#endif
717 if (ios->bus_width == MMC_BUS_WIDTH_4) 737 if (ios->bus_width == MMC_BUS_WIDTH_4)
718 host->cmdat |= CMD_DAT_CONT_BUS_WIDTH_4; 738 host->cmdat |= CMD_DAT_CONT_BUS_WIDTH_4;
719 else 739 else
@@ -794,6 +814,18 @@ static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card)
794 host->caps |= MMC_CAP_4_BIT_DATA; 814 host->caps |= MMC_CAP_4_BIT_DATA;
795} 815}
796 816
817static bool filter(struct dma_chan *chan, void *param)
818{
819 struct mxcmci_host *host = param;
820
821 if (!imx_dma_is_general_purpose(chan))
822 return false;
823
824 chan->private = &host->dma_data;
825
826 return true;
827}
828
797static const struct mmc_host_ops mxcmci_ops = { 829static const struct mmc_host_ops mxcmci_ops = {
798 .request = mxcmci_request, 830 .request = mxcmci_request,
799 .set_ios = mxcmci_set_ios, 831 .set_ios = mxcmci_set_ios,
@@ -808,6 +840,7 @@ static int mxcmci_probe(struct platform_device *pdev)
808 struct mxcmci_host *host = NULL; 840 struct mxcmci_host *host = NULL;
809 struct resource *iores, *r; 841 struct resource *iores, *r;
810 int ret = 0, irq; 842 int ret = 0, irq;
843 dma_cap_mask_t mask;
811 844
812 printk(KERN_INFO "i.MX SDHC driver\n"); 845 printk(KERN_INFO "i.MX SDHC driver\n");
813 846
@@ -883,29 +916,23 @@ static int mxcmci_probe(struct platform_device *pdev)
883 916
884 writel(host->default_irq_mask, host->base + MMC_REG_INT_CNTR); 917 writel(host->default_irq_mask, host->base + MMC_REG_INT_CNTR);
885 918
886#ifdef HAS_DMA
887 host->dma = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_LOW);
888 if (host->dma < 0) {
889 dev_err(mmc_dev(host->mmc), "imx_dma_request_by_prio failed\n");
890 ret = -EBUSY;
891 goto out_clk_put;
892 }
893
894 r = platform_get_resource(pdev, IORESOURCE_DMA, 0); 919 r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
895 if (!r) { 920 if (r) {
896 ret = -EINVAL; 921 host->dmareq = r->start;
897 goto out_free_dma; 922 host->dma_data.peripheral_type = IMX_DMATYPE_SDHC;
923 host->dma_data.priority = DMA_PRIO_LOW;
924 host->dma_data.dma_request = host->dmareq;
925 dma_cap_zero(mask);
926 dma_cap_set(DMA_SLAVE, mask);
927 host->dma = dma_request_channel(mask, filter, host);
928 if (host->dma)
929 mmc->max_seg_size = dma_get_max_seg_size(
930 host->dma->device->dev);
898 } 931 }
899 932
900 ret = imx_dma_config_channel(host->dma, 933 if (!host->dma)
901 IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_FIFO, 934 dev_info(mmc_dev(host->mmc), "dma not available. Using PIO\n");
902 IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, 935
903 r->start, 0);
904 if (ret) {
905 dev_err(mmc_dev(host->mmc), "failed to config DMA channel\n");
906 goto out_free_dma;
907 }
908#endif
909 INIT_WORK(&host->datawork, mxcmci_datawork); 936 INIT_WORK(&host->datawork, mxcmci_datawork);
910 937
911 ret = request_irq(host->irq, mxcmci_irq, 0, DRIVER_NAME, host); 938 ret = request_irq(host->irq, mxcmci_irq, 0, DRIVER_NAME, host);
@@ -928,9 +955,8 @@ static int mxcmci_probe(struct platform_device *pdev)
928out_free_irq: 955out_free_irq:
929 free_irq(host->irq, host); 956 free_irq(host->irq, host);
930out_free_dma: 957out_free_dma:
931#ifdef HAS_DMA 958 if (host->dma)
932 imx_dma_free(host->dma); 959 dma_release_channel(host->dma);
933#endif
934out_clk_put: 960out_clk_put:
935 clk_disable(host->clk); 961 clk_disable(host->clk);
936 clk_put(host->clk); 962 clk_put(host->clk);
@@ -960,9 +986,10 @@ static int mxcmci_remove(struct platform_device *pdev)
960 986
961 free_irq(host->irq, host); 987 free_irq(host->irq, host);
962 iounmap(host->base); 988 iounmap(host->base);
963#ifdef HAS_DMA 989
964 imx_dma_free(host->dma); 990 if (host->dma)
965#endif 991 dma_release_channel(host->dma);
992
966 clk_disable(host->clk); 993 clk_disable(host->clk);
967 clk_put(host->clk); 994 clk_put(host->clk);
968 995