Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 91778
b: refs/heads/master
c: a914ded
h: refs/heads/master
v: v3
  • Loading branch information
Juha Yrjola authored and Pierre Ossman committed Apr 18, 2008
1 parent ae95db3 commit 0c1ffb8
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5a0f3f1f71e0bc4a843673e8e7cf09a32bb07c32
refs/heads/master: a914ded23565d8688e2b7e435916630def5bdd19
79 changes: 60 additions & 19 deletions trunk/drivers/mmc/host/omap.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,42 +326,78 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd)
OMAP_MMC_WRITE(host, CMD, cmdreg);
}

static void
mmc_omap_release_dma(struct mmc_omap_host *host, struct mmc_data *data,
int abort)
{
enum dma_data_direction dma_data_dir;

BUG_ON(host->dma_ch < 0);
if (data->error)
omap_stop_dma(host->dma_ch);
/* Release DMA channel lazily */
mod_timer(&host->dma_timer, jiffies + HZ);
if (data->flags & MMC_DATA_WRITE)
dma_data_dir = DMA_TO_DEVICE;
else
dma_data_dir = DMA_FROM_DEVICE;
dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len,
dma_data_dir);
}

static void
mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
{
if (host->dma_in_use) {
enum dma_data_direction dma_data_dir;

BUG_ON(host->dma_ch < 0);
if (data->error)
omap_stop_dma(host->dma_ch);
/* Release DMA channel lazily */
mod_timer(&host->dma_timer, jiffies + HZ);
if (data->flags & MMC_DATA_WRITE)
dma_data_dir = DMA_TO_DEVICE;
else
dma_data_dir = DMA_FROM_DEVICE;
dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len,
dma_data_dir);
}
if (host->dma_in_use)
mmc_omap_release_dma(host, data, data->error);

host->data = NULL;
host->sg_len = 0;
clk_disable(host->fclk);

/* NOTE: MMC layer will sometimes poll-wait CMD13 next, issuing
* dozens of requests until the card finishes writing data.
* It'd be cheaper to just wait till an EOFB interrupt arrives...
*/

if (!data->stop) {
struct mmc_host *mmc;

host->mrq = NULL;
mmc_request_done(host->mmc, data->mrq);
mmc = host->mmc;
mmc_omap_release_slot(host->current_slot);
mmc_request_done(mmc, data->mrq);
return;
}

mmc_omap_start_command(host, data->stop);
}

static void
mmc_omap_abort_xfer(struct mmc_omap_host *host, struct mmc_data *data)
{
int loops;
u16 ie;

if (host->dma_in_use)
mmc_omap_release_dma(host, data, 1);

host->data = NULL;
host->sg_len = 0;

ie = OMAP_MMC_READ(host, IE);
OMAP_MMC_WRITE(host, IE, 0);
OMAP_MMC_WRITE(host, CMD, 1 << 7);
loops = 0;
while (!(OMAP_MMC_READ(host, STAT) & OMAP_MMC_STAT_END_OF_CMD)) {
udelay(1);
loops++;
if (loops == 100000)
break;
}
OMAP_MMC_WRITE(host, STAT, OMAP_MMC_STAT_END_OF_CMD);
OMAP_MMC_WRITE(host, IE, ie);
}

static void
mmc_omap_end_of_data(struct mmc_omap_host *host, struct mmc_data *data)
{
Expand Down Expand Up @@ -439,9 +475,14 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
}

if (host->data == NULL || cmd->error) {
struct mmc_host *mmc;

if (host->data != NULL)
mmc_omap_abort_xfer(host, host->data);
host->mrq = NULL;
clk_disable(host->fclk);
mmc_request_done(host->mmc, cmd->mrq);
mmc = host->mmc;
mmc_omap_release_slot(host->current_slot);
mmc_request_done(mmc, cmd->mrq);
}
}

Expand Down

0 comments on commit 0c1ffb8

Please sign in to comment.