commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=67cb7ad8765dc14373421d7fe19c9ddb2d4a3d37 branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk
Signed-off-by: Sonic Zhang <[email protected]> --- drivers/mmc/host/bfin_sdh.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 files changed, 40 insertions(+), 1 deletions(-) diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c index c701878..b9b463e 100644 --- a/drivers/mmc/host/bfin_sdh.c +++ b/drivers/mmc/host/bfin_sdh.c @@ -69,6 +69,7 @@ struct sdh_host { int dma_len; unsigned long sclk; + unsigned int imask; unsigned int power_mode; unsigned int clk_div; @@ -88,6 +89,28 @@ static void sdh_stop_clock(struct sdh_host *host) SSYNC(); } +static void sdh_enable_stat_irq(struct sdh_host *host, unsigned int mask) +{ + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + host->imask |= mask; + bfin_write_SDH_MASK0(mask); + SSYNC(); + spin_unlock_irqrestore(&host->lock, flags); +} + +static void sdh_disable_stat_irq(struct sdh_host *host, unsigned int mask) +{ + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + host->imask &= ~mask; + bfin_write_SDH_MASK0(host->imask); + SSYNC(); + spin_unlock_irqrestore(&host->lock, flags); +} + static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) { unsigned int length; @@ -99,6 +122,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) host->data = "" data_ctl = 0; dma_cfg = 0; + length = data->blksz * data->blocks; bfin_write_SDH_DATA_LGTH(length); @@ -130,6 +154,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) } else host->dma_dir = DMA_TO_DEVICE; + sdh_enable_stat_irq(host, (DAT_CRC_FAIL | DAT_TIME_OUT | DAT_END)); host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma_dir); #if defined(CONFIG_BF54x) || defined(CONFIG_BF60x) dma_cfg |= DMAFLOW_ARRAY | RESTART | WDSIZE_32 | DMAEN; @@ -185,21 +210,31 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) static void sdh_start_cmd(struct sdh_host *host, struct mmc_command *cmd) { unsigned int sdh_cmd; + unsigned int stat_mask; dev_dbg(mmc_dev(host->mmc), "%s enter cmd: 0x%p\n", __func__, cmd); WARN_ON(host->cmd != NULL); host->cmd = cmd; sdh_cmd = 0; + stat_mask = 0; sdh_cmd |= cmd->opcode; - if (cmd->flags & MMC_RSP_PRESENT) + if (cmd->flags & MMC_RSP_PRESENT) { sdh_cmd |= CMD_RSP; + stat_mask |= CMD_RESP_END; + } else { + stat_mask |= CMD_SENT; + } if (cmd->flags & MMC_RSP_136) sdh_cmd |= CMD_L_RSP; + stat_mask |= CMD_CRC_FAIL | CMD_TIME_OUT; + + sdh_enable_stat_irq(host, stat_mask); + bfin_write_SDH_ARGUMENT(cmd->arg); bfin_write_SDH_COMMAND(sdh_cmd | CMD_E); bfin_write_SDH_CLK_CTL(bfin_read_SDH_CLK_CTL() | CLK_E); @@ -239,12 +274,16 @@ static int sdh_cmd_done(struct sdh_host *host, unsigned int stat) else if (stat & CMD_CRC_FAIL && cmd->flags & MMC_RSP_CRC) cmd->error = -EILSEQ; + sdh_disable_stat_irq(host, (CMD_SENT | CMD_RESP_END | CMD_TIME_OUT | CMD_CRC_FAIL)); + if (host->data && !cmd->error) { if (host->data->flags & MMC_DATA_WRITE) { ret = sdh_setup_data(host, host->data); if (ret) return 0; } + + sdh_enable_stat_irq(host, DAT_END | RX_OVERRUN | TX_UNDERRUN | DAT_TIME_OUT); } else sdh_finish_request(host, host->mrq);
_______________________________________________ Linux-kernel-commits mailing list [email protected] https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits
