MMC: OMAP: New functions to support MMC multislot: mmc_omap_release_dma() and mmc_omap_abort_xfer().
Subsystems (2)
PATCH 3/17 MMC: OMAP: New functions to support MMC multislot: mmc_omap_release_dma() and mmc_omap_abort_xfer().
From: Juha Yrjola <[email protected]>
New functions to support MMC multislot: mmc_omap_release_dma() and mmc_omap_abort_xfer().
Signed-off-by Juha Yrjola <[email protected]>
New functions to support MMC multislot:mmc_omap_release_dma() and mmc_omap_abort_xfer().
Signed-off-by Juha Yrjola <[email protected]>
drivers/mmc/host/omap.c +59 -18
@@ -339,26 +339,32 @@ mmc_omap_start_command(struct mmc_omap_h }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 (abort) +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; +if (host->dma_in_use) +mmc_omap_release_dma (host, data, data->error !=MMC_ERR_NONE ); -BUG_ON (host->dma_ch <0 ); -if (data->error !=MMC_ERR_NONE ) -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); - } 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.
@@ -366,8 +372,12 @@ mmc_omap_xfer_done(struct mmc_omap_host*/ 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 ; }
@@ -375,6 +385,32 @@ mmc_omap_xfer_done(struct mmc_omap_host }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) {unsigned long flags;
@@ -451,9 +487,14 @@ mmc_omap_cmd_done(struct mmc_omap_host * }if (host->data ==NULL || cmd->error !=MMC_ERR_NONE ) { +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); } }