commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=55d0b407723520da51cbb77732a79b261ccf6dc2 branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk
Enable all RSI interrupts when power on. No need to change interrupts mask in interupt context and mmc_host_ops. No need to disable local irqs in mmc_host_ops. Don't call get_sclk in interrupt context. get_sclk may sleep. Signed-off-by: Sonic Zhang <[email protected]> Signed-off-by: Bob Liu <[email protected]> --- drivers/mmc/host/bfin_sdh.c | 71 +++++++++++++++---------------------------- 1 files changed, 25 insertions(+), 46 deletions(-) diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c index 155940a..96296f8 100644 --- a/drivers/mmc/host/bfin_sdh.c +++ b/drivers/mmc/host/bfin_sdh.c @@ -81,7 +81,7 @@ struct sdh_host { dma_addr_t sg_dma; int dma_len; - unsigned int imask; + unsigned long sclk; unsigned int power_mode; unsigned int clk_div; @@ -101,28 +101,6 @@ 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; @@ -153,7 +131,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) bfin_write_SDH_DATA_CTL(data_ctl); /* the time of a host clock period in ns */ - cycle_ns = 1000000000 / (get_sclk() / (2 * (host->clk_div + 1))); + cycle_ns = 1000000000 / (host->sclk / (2 * (host->clk_div + 1))); timeout = data->timeout_ns / cycle_ns; timeout += data->timeout_clks; bfin_write_SDH_DATA_TIMER(timeout); @@ -165,7 +143,6 @@ 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; @@ -221,31 +198,21 @@ 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); @@ -285,16 +252,12 @@ 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); @@ -325,7 +288,6 @@ static int sdh_data_done(struct sdh_host *host, unsigned int stat) else data->bytes_xfered = 0; - sdh_disable_stat_irq(host, DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN); bfin_write_SDH_STATUS_CLR(DAT_END_STAT | DAT_TIMEOUT_STAT | \ DAT_CRC_FAIL_STAT | DAT_BLK_END_STAT | RX_OVERRUN | TX_UNDERRUN); bfin_write_SDH_DATA_CTL(0); @@ -350,22 +312,24 @@ static void sdh_request(struct mmc_host *mmc, struct mmc_request *mrq) dev_dbg(mmc_dev(host->mmc), "%s enter, mrp:%p, cmd:%p\n", __func__, mrq, mrq->cmd); WARN_ON(host->mrq != NULL); + spin_lock(&host->lock); host->mrq = mrq; host->data = "" if (mrq->data && mrq->data->flags & MMC_DATA_READ) { ret = sdh_setup_data(host, mrq->data); if (ret) - return; + goto data_err; } sdh_start_cmd(host, mrq->cmd); +data_err: + spin_unlock(&host->lock); } static void sdh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct sdh_host *host; - unsigned long flags; u16 clk_ctl = 0; #ifndef RSI_BLKSZ u16 pwr_ctl = 0; @@ -373,7 +337,7 @@ static void sdh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) u16 cfg; host = mmc_priv(mmc); - spin_lock_irqsave(&host->lock, flags); + spin_lock(&host->lock); cfg = bfin_read_SDH_CFG(); cfg |= MWE; @@ -443,11 +407,20 @@ static void sdh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) clk_ctl |= CLK_E; host->clk_div = clk_div; bfin_write_SDH_CLK_CTL(clk_ctl); - SSYNC(); + } else sdh_stop_clock(host); - spin_unlock_irqrestore(&host->lock, flags); + /* set up sdh interrupt mask*/ + if (ios->power_mode == MMC_POWER_ON) + bfin_write_SDH_MASK0(DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | + RX_OVERRUN | TX_UNDERRUN | CMD_SENT | CMD_RESP_END | + CMD_TIME_OUT | CMD_CRC_FAIL); + else + bfin_write_SDH_MASK0(0); + SSYNC(); + + spin_unlock(&host->lock); dev_dbg(mmc_dev(host->mmc), "SDH: clk_div = 0x%x actual clock:%ld expected clock:%d\n", host->clk_div, @@ -479,6 +452,9 @@ static irqreturn_t sdh_stat_irq(int irq, void *devid) int handled = 0; dev_dbg(mmc_dev(host->mmc), "%s enter\n", __func__); + + spin_lock(&host->lock); + status = bfin_read_SDH_E_STATUS(); if (status & SD_CARD_DET) { mmc_detect_change(host->mmc, 0); @@ -496,6 +472,8 @@ static irqreturn_t sdh_stat_irq(int irq, void *devid) if (status & (DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN)) handled |= sdh_data_done(host, status); + spin_unlock(&host->lock); + dev_dbg(mmc_dev(host->mmc), "%s exit\n\n", __func__); return IRQ_RETVAL(handled); @@ -536,6 +514,7 @@ static int __devinit sdh_probe(struct platform_device *pdev) mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NEEDS_POLL; host = mmc_priv(mmc); host->mmc = mmc; + host->sclk = get_sclk(); spin_lock_init(&host->lock); host->irq = drv_data->irq_int0;
_______________________________________________ Linux-kernel-commits mailing list [email protected] https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits
