diff options
-rw-r--r-- | arch/arm/plat-s3c24xx/include/plat/mci.h | 1 | ||||
-rw-r--r-- | drivers/mmc/host/Kconfig | 34 | ||||
-rw-r--r-- | drivers/mmc/host/s3cmci.c | 39 |
3 files changed, 66 insertions, 8 deletions
diff --git a/arch/arm/plat-s3c24xx/include/plat/mci.h b/arch/arm/plat-s3c24xx/include/plat/mci.h index 2d0852ac3b27..f1bd6d4198d4 100644 --- a/arch/arm/plat-s3c24xx/include/plat/mci.h +++ b/arch/arm/plat-s3c24xx/include/plat/mci.h | |||
@@ -4,6 +4,7 @@ | |||
4 | struct s3c24xx_mci_pdata { | 4 | struct s3c24xx_mci_pdata { |
5 | unsigned int wprotect_invert : 1; | 5 | unsigned int wprotect_invert : 1; |
6 | unsigned int detect_invert : 1; /* set => detect active high. */ | 6 | unsigned int detect_invert : 1; /* set => detect active high. */ |
7 | unsigned int use_dma : 1; | ||
7 | 8 | ||
8 | unsigned int gpio_detect; | 9 | unsigned int gpio_detect; |
9 | unsigned int gpio_wprotect; | 10 | unsigned int gpio_wprotect; |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 7cb057f3f883..cf6a6545240b 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -276,6 +276,40 @@ config MMC_S3C | |||
276 | 276 | ||
277 | If unsure, say N. | 277 | If unsure, say N. |
278 | 278 | ||
279 | choice | ||
280 | prompt "Samsung S3C SD/MMC transfer code" | ||
281 | depends on MMC_S3C | ||
282 | |||
283 | config MMC_S3C_PIO | ||
284 | bool "Use PIO transfers only" | ||
285 | help | ||
286 | Use PIO to transfer data between memory and the hardware. | ||
287 | |||
288 | PIO is slower than DMA as it requires CPU instructions to | ||
289 | move the data. This has been the traditional default for | ||
290 | the S3C MCI driver. | ||
291 | |||
292 | config MMC_S3C_DMA | ||
293 | bool "Use DMA transfers only (EXPERIMENTAL)" | ||
294 | depends on EXPERIMENTAL | ||
295 | help | ||
296 | Use DMA to transfer data between memory and the hardare. | ||
297 | |||
298 | Currently, the DMA support in this driver seems to not be | ||
299 | working properly and needs to be debugged before this | ||
300 | option is useful. | ||
301 | |||
302 | config MMC_S3C_PIODMA | ||
303 | bool "Support for both PIO and DMA (EXPERIMENTAL)" | ||
304 | help | ||
305 | Compile both the PIO and DMA transfer routines into the | ||
306 | driver and let the platform select at run-time which one | ||
307 | is best. | ||
308 | |||
309 | See notes for the DMA option. | ||
310 | |||
311 | endchoice | ||
312 | |||
279 | config MMC_SDRICOH_CS | 313 | config MMC_SDRICOH_CS |
280 | tristate "MMC/SD driver for Ricoh Bay1Controllers (EXPERIMENTAL)" | 314 | tristate "MMC/SD driver for Ricoh Bay1Controllers (EXPERIMENTAL)" |
281 | depends on EXPERIMENTAL && PCI && PCMCIA | 315 | depends on EXPERIMENTAL && PCI && PCMCIA |
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 7660ac4572e5..0adf31895f2a 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c | |||
@@ -164,6 +164,25 @@ static void dbg_dumpregs(struct s3cmci_host *host, char *prefix) { } | |||
164 | 164 | ||
165 | #endif /* CONFIG_MMC_DEBUG */ | 165 | #endif /* CONFIG_MMC_DEBUG */ |
166 | 166 | ||
167 | /** | ||
168 | * s3cmci_host_usedma - return whether the host is using dma or pio | ||
169 | * @host: The host state | ||
170 | * | ||
171 | * Return true if the host is using DMA to transfer data, else false | ||
172 | * to use PIO mode. Will return static data depending on the driver | ||
173 | * configuration. | ||
174 | */ | ||
175 | static inline bool s3cmci_host_usedma(struct s3cmci_host *host) | ||
176 | { | ||
177 | #ifdef CONFIG_MMC_S3C_PIO | ||
178 | return false; | ||
179 | #elif defined(CONFIG_MMC_S3C_DMA) | ||
180 | return true; | ||
181 | #else | ||
182 | return host->dodma; | ||
183 | #endif | ||
184 | } | ||
185 | |||
167 | static inline u32 enable_imask(struct s3cmci_host *host, u32 imask) | 186 | static inline u32 enable_imask(struct s3cmci_host *host, u32 imask) |
168 | { | 187 | { |
169 | u32 newmask; | 188 | u32 newmask; |
@@ -560,7 +579,7 @@ static irqreturn_t s3cmci_irq(int irq, void *dev_id) | |||
560 | goto irq_out; | 579 | goto irq_out; |
561 | } | 580 | } |
562 | 581 | ||
563 | if (!host->dodma) { | 582 | if (!s3cmci_host_usedma(host)) { |
564 | if ((host->pio_active == XFER_WRITE) && | 583 | if ((host->pio_active == XFER_WRITE) && |
565 | (mci_fsta & S3C2410_SDIFSTA_TFDET)) { | 584 | (mci_fsta & S3C2410_SDIFSTA_TFDET)) { |
566 | 585 | ||
@@ -796,7 +815,7 @@ static void finalize_request(struct s3cmci_host *host) | |||
796 | 815 | ||
797 | if (cmd->data && (cmd->error == 0) && | 816 | if (cmd->data && (cmd->error == 0) && |
798 | (cmd->data->error == 0)) { | 817 | (cmd->data->error == 0)) { |
799 | if (host->dodma && (!host->dma_complete)) { | 818 | if (s3cmci_host_usedma(host) && (!host->dma_complete)) { |
800 | dbg(host, dbg_dma, "DMA Missing!\n"); | 819 | dbg(host, dbg_dma, "DMA Missing!\n"); |
801 | return; | 820 | return; |
802 | } | 821 | } |
@@ -848,7 +867,7 @@ static void finalize_request(struct s3cmci_host *host) | |||
848 | /* If we had an error while transfering data we flush the | 867 | /* If we had an error while transfering data we flush the |
849 | * DMA channel and the fifo to clear out any garbage. */ | 868 | * DMA channel and the fifo to clear out any garbage. */ |
850 | if (mrq->data->error != 0) { | 869 | if (mrq->data->error != 0) { |
851 | if (host->dodma) | 870 | if (s3cmci_host_usedma(host)) |
852 | s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH); | 871 | s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH); |
853 | 872 | ||
854 | if (host->is2440) { | 873 | if (host->is2440) { |
@@ -968,7 +987,7 @@ static int s3cmci_setup_data(struct s3cmci_host *host, struct mmc_data *data) | |||
968 | 987 | ||
969 | dcon = data->blocks & S3C2410_SDIDCON_BLKNUM_MASK; | 988 | dcon = data->blocks & S3C2410_SDIDCON_BLKNUM_MASK; |
970 | 989 | ||
971 | if (host->dodma) | 990 | if (s3cmci_host_usedma(host)) |
972 | dcon |= S3C2410_SDIDCON_DMAEN; | 991 | dcon |= S3C2410_SDIDCON_DMAEN; |
973 | 992 | ||
974 | if (host->bus_width == MMC_BUS_WIDTH_4) | 993 | if (host->bus_width == MMC_BUS_WIDTH_4) |
@@ -1114,7 +1133,7 @@ static void s3cmci_send_request(struct mmc_host *mmc) | |||
1114 | return; | 1133 | return; |
1115 | } | 1134 | } |
1116 | 1135 | ||
1117 | if (host->dodma) | 1136 | if (s3cmci_host_usedma(host)) |
1118 | res = s3cmci_prepare_dma(host, cmd->data); | 1137 | res = s3cmci_prepare_dma(host, cmd->data); |
1119 | else | 1138 | else |
1120 | res = s3cmci_prepare_pio(host, cmd->data); | 1139 | res = s3cmci_prepare_pio(host, cmd->data); |
@@ -1398,7 +1417,7 @@ static int s3cmci_state_show(struct seq_file *seq, void *v) | |||
1398 | seq_printf(seq, "IRQ disabled = %d\n", host->irq_disabled); | 1417 | seq_printf(seq, "IRQ disabled = %d\n", host->irq_disabled); |
1399 | seq_printf(seq, "IRQ state = %d\n", host->irq_state); | 1418 | seq_printf(seq, "IRQ state = %d\n", host->irq_state); |
1400 | seq_printf(seq, "CD IRQ = %d\n", host->irq_cd); | 1419 | seq_printf(seq, "CD IRQ = %d\n", host->irq_cd); |
1401 | seq_printf(seq, "Do DMA = %d\n", host->dodma); | 1420 | seq_printf(seq, "Do DMA = %d\n", s3cmci_host_usedma(host)); |
1402 | seq_printf(seq, "SDIIMSK at %d\n", host->sdiimsk); | 1421 | seq_printf(seq, "SDIIMSK at %d\n", host->sdiimsk); |
1403 | seq_printf(seq, "SDIDATA at %d\n", host->sdidata); | 1422 | seq_printf(seq, "SDIDATA at %d\n", host->sdidata); |
1404 | 1423 | ||
@@ -1559,12 +1578,15 @@ static int __devinit s3cmci_probe(struct platform_device *pdev) | |||
1559 | host->clk_div = 2; | 1578 | host->clk_div = 2; |
1560 | } | 1579 | } |
1561 | 1580 | ||
1562 | host->dodma = 0; | ||
1563 | host->complete_what = COMPLETION_NONE; | 1581 | host->complete_what = COMPLETION_NONE; |
1564 | host->pio_active = XFER_NONE; | 1582 | host->pio_active = XFER_NONE; |
1565 | 1583 | ||
1566 | host->dma = S3CMCI_DMA; | 1584 | host->dma = S3CMCI_DMA; |
1567 | 1585 | ||
1586 | #ifdef CONFIG_MMC_S3C_PIODMA | ||
1587 | host->dodma = host->pdata->dma; | ||
1588 | #endif | ||
1589 | |||
1568 | host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1590 | host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1569 | if (!host->mem) { | 1591 | if (!host->mem) { |
1570 | dev_err(&pdev->dev, | 1592 | dev_err(&pdev->dev, |
@@ -1702,7 +1724,8 @@ static int __devinit s3cmci_probe(struct platform_device *pdev) | |||
1702 | s3cmci_debugfs_attach(host); | 1724 | s3cmci_debugfs_attach(host); |
1703 | 1725 | ||
1704 | platform_set_drvdata(pdev, mmc); | 1726 | platform_set_drvdata(pdev, mmc); |
1705 | dev_info(&pdev->dev, "initialisation done.\n"); | 1727 | dev_info(&pdev->dev, "%s - using %s\n", mmc_hostname(mmc), |
1728 | s3cmci_host_usedma(host) ? "dma" : "pio"); | ||
1706 | 1729 | ||
1707 | return 0; | 1730 | return 0; |
1708 | 1731 | ||