/* * MMC controller IRQ handler */ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) { struct mmc_omap_host *host = dev_id; int end_cmd = 0, end_trans = 0, status; if (host->cmd == NULL && host->data == NULL) { OMAP_HSMMC_WRITE(host->base, STAT, OMAP_HSMMC_READ(host->base, STAT)); return IRQ_HANDLED; } status = OMAP_HSMMC_READ(host->base, STAT); dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); if (status & ERR) { if ((status & CMD_TIMEOUT) || (status & CMD_CRC)) { if (host->cmd) { if (status & CMD_TIMEOUT) host->cmd->error = -ETIMEDOUT; else host->cmd->error = -EILSEQ; end_cmd = 1; } if (host->data) mmc_dma_cleanup(host); } if ((status & DATA_TIMEOUT) || (status & DATA_CRC)) { if (host->data) { if (status & DATA_TIMEOUT) mmc_dma_cleanup(host); else host->data->error = -EILSEQ; end_trans = 1; } } if (status & CARD_ERR) { dev_dbg(mmc_dev(host->mmc), "Ignoring card err CMD%d\n", host->cmd->opcode); if (host->cmd) end_cmd = 1; if (host->data) end_trans = 1; } } OMAP_HSMMC_WRITE(host->base, STAT, status); if (end_cmd || (status & CC)) mmc_omap_cmd_done(host, host->cmd); if (end_trans || (status & TC)) mmc_omap_xfer_done(host, host->data); return IRQ_HANDLED; }
/* * MMC controller IRQ handler */ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) { struct mmc_omap_host *host = dev_id; struct mmc_data *data; int end_cmd = 0, end_trans = 0, status; omap_hsmmc_enable_clks(host); if (host->cmd == NULL && host->data == NULL) { OMAP_HSMMC_WRITE(host->base, STAT, OMAP_HSMMC_READ(host->base, STAT)); return IRQ_HANDLED; } data = host->data; status = OMAP_HSMMC_READ(host->base, STAT); dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); if (status & ERR) { #ifdef CONFIG_MMC_DEBUG mmc_omap_report_irq(host, status); #endif if ((status & CMD_TIMEOUT) || (status & CMD_CRC) || (status & CMD_CEB) || (status & CMD_CIE)) { if (host->cmd) { if (status & CMD_TIMEOUT) { mmc_omap_reset_controller_fsm(host, SRC); host->cmd->error = -ETIMEDOUT; } else { host->cmd->error = -EILSEQ; } end_cmd = 1; } if (host->data) { mmc_dma_cleanup(host, -ETIMEDOUT); mmc_omap_reset_controller_fsm(host, SRD); } } if ((status & DATA_TIMEOUT) || (status & DATA_CRC) || (status & DATA_DEB)) { if (host->data) { if (status & DATA_TIMEOUT) mmc_dma_cleanup(host, -ETIMEDOUT); else mmc_dma_cleanup(host, -EILSEQ); mmc_omap_reset_controller_fsm(host, SRD); end_trans = 1; } } if (status & CARD_ERR) { dev_dbg(mmc_dev(host->mmc), "Ignoring card err CMD%d\n", host->cmd->opcode); if (host->cmd) end_cmd = 1; if (host->data) end_trans = 1; } } OMAP_HSMMC_WRITE(host->base, STAT, status); if (end_cmd || (status & CC)) mmc_omap_cmd_done(host, host->cmd); if (end_trans || (status & TC)) mmc_omap_xfer_done(host, data); /* Perform one dummy read to ensure the previous write actually went through */ status = OMAP_HSMMC_READ(host->base, STAT); return IRQ_HANDLED; }
/* * MMC controller IRQ handler */ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) { struct mmc_omap_host *host = dev_id; struct mmc_data *data; int end_cmd = 0, end_trans = 0, status; /* * TODO: * Is this necessary? The fact that we have taken * an interrupt is a premise that CLKs are ON. */ mmc_clk_try_enable(host); if (host->cmd == NULL && host->data == NULL) { OMAP_HSMMC_WRITE(host->base, STAT, OMAP_HSMMC_READ(host->base, STAT)); return IRQ_HANDLED; } data = host->data; status = OMAP_HSMMC_READ(host->base, STAT); dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); if (status & ERR) { #ifdef CONFIG_MMC_DEBUG mmc_omap_report_irq(host, status); #endif if ((status & CMD_TIMEOUT) || (status & CMD_CRC)) { if (host->cmd) { if (status & CMD_TIMEOUT) { OMAP_HSMMC_WRITE(host->base, SYSCTL, OMAP_HSMMC_READ(host->base, SYSCTL) | SRC); while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRC) ; host->cmd->error = -ETIMEDOUT; } else { host->cmd->error = -EILSEQ; } end_cmd = 1; } if (host->data) mmc_dma_cleanup(host); } if ((status & DATA_TIMEOUT) || (status & DATA_CRC)) { if (host->data) { if (status & DATA_TIMEOUT) { dev_info(mmc_dev(host->mmc), "MMC DATA TIMEOUT\n"); mmc_dma_cleanup(host); } else { dev_info(mmc_dev(host->mmc), "MMC DATA CRC\n"); host->data->error = -EILSEQ; } end_trans = 1; } } if (status & CARD_ERR) { dev_dbg(mmc_dev(host->mmc), "Ignoring card err CMD%d\n", host->cmd->opcode); if (host->cmd) end_cmd = 1; if (host->data) end_trans = 1; } } OMAP_HSMMC_WRITE(host->base, STAT, status); if (end_cmd || (status & CC)) mmc_omap_cmd_done(host, host->cmd); if (end_trans || (status & TC)) mmc_omap_xfer_done(host, data); return IRQ_HANDLED; }