diff options
author | Ben Dooks <ben@simtec.co.uk> | 2009-10-01 18:44:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-10-01 19:11:15 -0400 |
commit | 26f14947dbf31d60d1a67eee837a6d28c1e8830d (patch) | |
tree | e54c009f30d9df49bb2c421eeafec266d67be720 | |
parent | c225889375fea2a542f1c9dedffec4c7b8ebc9ab (diff) |
s3cmci: Kconfig selection for PIO/DMA/Both
Add a selection for the data transfer mode of the s3cmci driver, allowing
for either a configuration or rumtime selection of the use of the DMA or
PIO transfer code.
The PIO only mode is 476 bytes smaller than the driver with both methods
compiled in.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
Cc: <linux-mmc@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-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 | ||