Skip to content

Commit

Permalink
s3cmci: Kconfig selection for PIO/DMA/Both
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ben Dooks authored and Linus Torvalds committed Oct 1, 2009
1 parent c225889 commit 26f1494
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 8 deletions.
1 change: 1 addition & 0 deletions arch/arm/plat-s3c24xx/include/plat/mci.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
struct s3c24xx_mci_pdata {
unsigned int wprotect_invert : 1;
unsigned int detect_invert : 1; /* set => detect active high. */
unsigned int use_dma : 1;

unsigned int gpio_detect;
unsigned int gpio_wprotect;
Expand Down
34 changes: 34 additions & 0 deletions drivers/mmc/host/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,40 @@ config MMC_S3C

If unsure, say N.

choice
prompt "Samsung S3C SD/MMC transfer code"
depends on MMC_S3C

config MMC_S3C_PIO
bool "Use PIO transfers only"
help
Use PIO to transfer data between memory and the hardware.

PIO is slower than DMA as it requires CPU instructions to
move the data. This has been the traditional default for
the S3C MCI driver.

config MMC_S3C_DMA
bool "Use DMA transfers only (EXPERIMENTAL)"
depends on EXPERIMENTAL
help
Use DMA to transfer data between memory and the hardare.

Currently, the DMA support in this driver seems to not be
working properly and needs to be debugged before this
option is useful.

config MMC_S3C_PIODMA
bool "Support for both PIO and DMA (EXPERIMENTAL)"
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
tristate "MMC/SD driver for Ricoh Bay1Controllers (EXPERIMENTAL)"
depends on EXPERIMENTAL && PCI && PCMCIA
Expand Down
39 changes: 31 additions & 8 deletions drivers/mmc/host/s3cmci.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,25 @@ static void dbg_dumpregs(struct s3cmci_host *host, char *prefix) { }

#endif /* CONFIG_MMC_DEBUG */

/**
* s3cmci_host_usedma - return whether the host is using dma or pio
* @host: The host state
*
* Return true if the host is using DMA to transfer data, else false
* to use PIO mode. Will return static data depending on the driver
* configuration.
*/
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
}

static inline u32 enable_imask(struct s3cmci_host *host, u32 imask)
{
u32 newmask;
Expand Down Expand Up @@ -560,7 +579,7 @@ static irqreturn_t s3cmci_irq(int irq, void *dev_id)
goto irq_out;
}

if (!host->dodma) {
if (!s3cmci_host_usedma(host)) {
if ((host->pio_active == XFER_WRITE) &&
(mci_fsta & S3C2410_SDIFSTA_TFDET)) {

Expand Down Expand Up @@ -796,7 +815,7 @@ static void finalize_request(struct s3cmci_host *host)

if (cmd->data && (cmd->error == 0) &&
(cmd->data->error == 0)) {
if (host->dodma && (!host->dma_complete)) {
if (s3cmci_host_usedma(host) && (!host->dma_complete)) {
dbg(host, dbg_dma, "DMA Missing!\n");
return;
}
Expand Down Expand Up @@ -848,7 +867,7 @@ static void finalize_request(struct s3cmci_host *host)
/* If we had an error while transfering data we flush the
* DMA channel and the fifo to clear out any garbage. */
if (mrq->data->error != 0) {
if (host->dodma)
if (s3cmci_host_usedma(host))
s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);

if (host->is2440) {
Expand Down Expand Up @@ -968,7 +987,7 @@ static int s3cmci_setup_data(struct s3cmci_host *host, struct mmc_data *data)

dcon = data->blocks & S3C2410_SDIDCON_BLKNUM_MASK;

if (host->dodma)
if (s3cmci_host_usedma(host))
dcon |= S3C2410_SDIDCON_DMAEN;

if (host->bus_width == MMC_BUS_WIDTH_4)
Expand Down Expand Up @@ -1114,7 +1133,7 @@ static void s3cmci_send_request(struct mmc_host *mmc)
return;
}

if (host->dodma)
if (s3cmci_host_usedma(host))
res = s3cmci_prepare_dma(host, cmd->data);
else
res = s3cmci_prepare_pio(host, cmd->data);
Expand Down Expand Up @@ -1398,7 +1417,7 @@ static int s3cmci_state_show(struct seq_file *seq, void *v)
seq_printf(seq, "IRQ disabled = %d\n", host->irq_disabled);
seq_printf(seq, "IRQ state = %d\n", host->irq_state);
seq_printf(seq, "CD IRQ = %d\n", host->irq_cd);
seq_printf(seq, "Do DMA = %d\n", host->dodma);
seq_printf(seq, "Do DMA = %d\n", s3cmci_host_usedma(host));
seq_printf(seq, "SDIIMSK at %d\n", host->sdiimsk);
seq_printf(seq, "SDIDATA at %d\n", host->sdidata);

Expand Down Expand Up @@ -1559,12 +1578,15 @@ static int __devinit s3cmci_probe(struct platform_device *pdev)
host->clk_div = 2;
}

host->dodma = 0;
host->complete_what = COMPLETION_NONE;
host->pio_active = XFER_NONE;

host->dma = S3CMCI_DMA;

#ifdef CONFIG_MMC_S3C_PIODMA
host->dodma = host->pdata->dma;
#endif

host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!host->mem) {
dev_err(&pdev->dev,
Expand Down Expand Up @@ -1702,7 +1724,8 @@ static int __devinit s3cmci_probe(struct platform_device *pdev)
s3cmci_debugfs_attach(host);

platform_set_drvdata(pdev, mmc);
dev_info(&pdev->dev, "initialisation done.\n");
dev_info(&pdev->dev, "%s - using %s\n", mmc_hostname(mmc),
s3cmci_host_usedma(host) ? "dma" : "pio");

return 0;

Expand Down

0 comments on commit 26f1494

Please sign in to comment.