Make sure FIFO does not need to be serviced before handling other
interrupt sources.
Signed-off-by: Troy Kisky <[EMAIL PROTECTED]>
Signed-off-by: Bernard Blackham <[EMAIL PROTECTED]>
---
drivers/mmc/host/davinci_mmc.c | 454 +++++++++++++++++++---------------------
1 files changed, 218 insertions(+), 236 deletions(-)
Index: linux-davinci-2.6.24.git/drivers/mmc/host/davinci_mmc.c
===================================================================
--- linux-davinci-2.6.24.git.orig/drivers/mmc/host/davinci_mmc.c
2008-02-16 14:06:50.000000000 +0900
+++ linux-davinci-2.6.24.git/drivers/mmc/host/davinci_mmc.c 2008-02-16
14:10:49.000000000 +0900
@@ -919,294 +919,275 @@
}
}
-static irqreturn_t mmc_davinci_irq(int irq, void *dev_id)
+static inline int handle_core_command(
+ struct mmc_davinci_host *host, unsigned int status)
{
- struct mmc_davinci_host *host = (struct mmc_davinci_host *)dev_id;
- u16 status;
- int end_command;
- int end_transfer;
+ int end_command = 0;
+ int end_transfer = 0;
+ unsigned int qstatus;
unsigned long flags;
- if (host->is_core_command) {
- if (host->cmd == NULL && host->data == NULL) {
- status = readl(host->base + DAVINCI_MMCST0);
- dev_dbg(mmc_dev(host->mmc),
- "Spurious interrupt 0x%04x\r\n", status);
- /* Disable the interrupt from mmcsd */
- writel(0, host->base + DAVINCI_MMCIM);
- return IRQ_HANDLED;
+ if ((host->is_card_initialized) && (host->new_card_state == 0)) {
+ if (host->cmd) {
+ host->cmd->error = -ETIMEDOUT;
+ mmc_davinci_cmd_done(host, host->cmd);
}
+ dev_dbg(mmc_dev(host->mmc), "From code segment "
+ "excuted when card removed\n");
+ return -1;
}
- end_command = 0;
- end_transfer = 0;
- status = readl(host->base + DAVINCI_MMCST0);
- if (status == 0)
- return IRQ_HANDLED;
+ qstatus = status;
+ while (1) {
+ if ((status & MMCSD_EVENT_WRITE) &&
+ (host->data_dir == DAVINCI_MMC_DATADIR_WRITE)
+ && (host->bytes_left > 0)) {
+ /* Buffer almost empty */
+ davinci_fifo_data_trans(host, mmcsd_cfg.rw_threshold);
+ }
- if (host->is_core_command) {
- if (host->is_card_initialized) {
- if (host->new_card_state == 0) {
- if (host->cmd) {
- host->cmd->error = -ETIMEDOUT;
- mmc_davinci_cmd_done(host, host->cmd);
- }
- dev_dbg(mmc_dev(host->mmc),
- "From code segment executed "
- "when card removed\n");
- return IRQ_HANDLED;
- }
+ if ((status & MMCSD_EVENT_READ) &&
+ (host->data_dir == DAVINCI_MMC_DATADIR_READ)
+ && (host->bytes_left > 0)) {
+ /* Buffer almost empty */
+ davinci_fifo_data_trans(host, mmcsd_cfg.rw_threshold);
+ }
+ status = readl(host->base + DAVINCI_MMCST0);
+ if (!status)
+ break;
+ qstatus |= status;
+ if (host->data == NULL) {
+ dev_dbg(mmc_dev(host->mmc), "Status is %x at end of "
+ "ISR when host->data is NULL", status);
+ break;
}
+ }
- while (status != 0) {
- if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
- if (status & MMCSD_EVENT_WRITE) {
- /* Buffer almost empty */
- if (host->bytes_left > 0)
- davinci_fifo_data_trans(host,
- mmcsd_cfg.rw_threshold);
- }
+ if (qstatus & MMCSD_EVENT_BLOCK_XFERRED) {
+ /* Block sent/received */
+ if (host->data != NULL) {
+ if ((host->do_dma == 0) && (host->bytes_left > 0)) {
+ /* if datasize<mmcsd_cfg.rw_threshold
+ * no RX ints are generated
+ */
+ davinci_fifo_data_trans(host,
+ mmcsd_cfg.rw_threshold);
}
+ end_transfer = 1;
+ } else {
+ dev_warn(mmc_dev(host->mmc), "TC:host->data is NULL\n");
+ }
+ }
- if (host->data_dir == DAVINCI_MMC_DATADIR_READ) {
- if (status & MMCSD_EVENT_READ) {
- /* Buffer almost empty */
- if (host->bytes_left > 0)
- davinci_fifo_data_trans(host,
- mmcsd_cfg.rw_threshold);
- }
- }
+ if (qstatus & MMCSD_EVENT_ERROR_DATATIMEOUT) {
+ /* Data timeout */
+ if (host->data && host->new_card_state != 0) {
+ host->data->error = -ETIMEDOUT;
+ spin_lock_irqsave(&host->lock, flags);
+ host->is_card_removed = 1;
+ host->new_card_state = 0;
+ host->is_card_initialized = 0;
+ spin_unlock_irqrestore(&host->lock, flags);
+ dev_dbg(mmc_dev(host->mmc), "MMCSD: Data timeout, "
+ "CMD%d and status is %x\n",
+ host->cmd->opcode, status);
+
+ if (host->cmd)
+ host->cmd->error = -ETIMEDOUT;
+ end_transfer = 1;
+ }
+ }
- if (status & MMCSD_EVENT_BLOCK_XFERRED) {
- /* Block sent/received */
- if (host->data != NULL) {
- if (host->do_dma == 1) {
- end_transfer = 1;
- } else {
- /* if datasize < 32 no RX ints
- * are generated */
- if (host->bytes_left > 0)
- davinci_fifo_data_trans(
- host,
- mmcsd_cfg.rw_threshold
- );
- end_transfer = 1;
- }
- } else {
- dev_warn(mmc_dev(host->mmc),
- "TC:host->data is NULL\n");
- }
- }
+ if (qstatus & MMCSD_EVENT_ERROR_DATACRC) {
+ u32 temp;
+ /* DAT line portion is disabled and in reset state */
+ temp = readl(host->base + DAVINCI_MMCCTL);
+
+ writel(temp | MMCCTL_CMDRST,
+ host->base + DAVINCI_MMCCTL);
+
+ udelay(10);
+
+ writel(temp & ~MMCCTL_CMDRST,
+ host->base + DAVINCI_MMCCTL);
+
+ /* Data CRC error */
+ if (host->data) {
+ host->data->error = -EILSEQ;
+ dev_dbg(mmc_dev(host->mmc), "MMCSD: Data CRC error, "
+ "bytes left %d\n", host->bytes_left);
+ end_transfer = 1;
+ } else {
+ dev_dbg(mmc_dev(host->mmc), "MMCSD: Data CRC error\n");
+ }
+ }
- if (status & MMCSD_EVENT_ERROR_DATATIMEOUT) {
- /* Data timeout */
- if (host->data && host->new_card_state != 0) {
- host->data->error = -ETIMEDOUT;
- spin_lock_irqsave(&host->lock, flags);
- host->is_card_removed = 1;
- host->new_card_state = 0;
- host->is_card_initialized = 0;
- spin_unlock_irqrestore(&host->lock,
- flags);
- dev_dbg(mmc_dev(host->mmc),
- "MMCSD: Data timeout, "
- "CMD%d and status is %x\r\n",
- host->cmd->opcode, status);
-
- if (host->cmd)
- host->cmd->error =
- -ETIMEDOUT;
- end_transfer = 1;
- }
+ if (qstatus & MMCSD_EVENT_ERROR_CMDTIMEOUT) {
+ if (host->do_dma)
+ davinci_abort_dma(host);
+
+ /* Command timeout */
+ if (host->cmd) {
+ /* Timeouts are normal in case of
+ * MMC_SEND_STATUS
+ */
+ if (host->cmd->opcode != MMC_ALL_SEND_CID) {
+ dev_dbg(mmc_dev(host->mmc), "MMCSD: CMD%d "
+ "timeout, status %x\n",
+ host->cmd->opcode, status);
+ spin_lock_irqsave(&host->lock, flags);
+ host->new_card_state = 0;
+ host->is_card_initialized = 0;
+ spin_unlock_irqrestore(&host->lock, flags);
}
+ host->cmd->error = -ETIMEDOUT;
+ end_command = 1;
+ }
+ }
- if (status & MMCSD_EVENT_ERROR_DATACRC) {
- u32 temp;
- /* DAT line portion is disabled
- * and in reset state */
- temp = readl(host->base + DAVINCI_MMCCTL);
-
- writel(temp | MMCCTL_CMDRST,
- host->base + DAVINCI_MMCCTL);
-
- udelay(10);
-
- writel(temp & ~MMCCTL_CMDRST,
- host->base + DAVINCI_MMCCTL);
-
- /* Data CRC error */
- if (host->data) {
- host->data->error = -EILSEQ;
- dev_dbg(mmc_dev(host->mmc),
- "MMCSD: Data CRC error, "
- "bytes left %d\r\n",
- host->bytes_left);
- end_transfer = 1;
- } else {
- dev_dbg(mmc_dev(host->mmc),
- "MMCSD: Data CRC error\r\n");
- }
- }
+ if (qstatus & MMCSD_EVENT_ERROR_CMDCRC) {
+ /* Command CRC error */
+ dev_dbg(mmc_dev(host->mmc), "Command CRC error\n");
+ if (host->cmd) {
+ /* Ignore CMD CRC errors during high speed operation */
+ if (host->mmc->ios.clock <= 25000000)
+ host->cmd->error = -EILSEQ;
+ end_command = 1;
+ }
+ }
- if (status & MMCSD_EVENT_ERROR_CMDTIMEOUT) {
- if (host->do_dma)
- /* abort DMA transfer */
- davinci_abort_dma(host);
-
- /* Command timeout */
- if (host->cmd) {
- /* Timeouts are normal in case of
- * MMC_SEND_STATUS
- */
- if (host->cmd->opcode !=
- MMC_ALL_SEND_CID) {
- dev_dbg(mmc_dev(host->mmc),
- "MMCSD: CMD%d timeout,"
- " status %x\r\n",
- host->cmd->opcode,
- status);
- spin_lock_irqsave(&host->lock,
- flags);
- host->new_card_state = 0;
- host->is_card_initialized = 0;
- spin_unlock_irqrestore(
- &host->lock, flags);
- }
- host->cmd->error = -ETIMEDOUT;
- end_command = 1;
+ if (qstatus & MMCSD_EVENT_EOFCMD) {
+ /* End of command phase */
+ end_command = 1;
+ }
- }
- }
+ if (end_command)
+ mmc_davinci_cmd_done(host, host->cmd);
+ if (end_transfer)
+ mmc_davinci_xfer_done(host, host->data);
+ return 0;
+}
- if (status & MMCSD_EVENT_ERROR_CMDCRC) {
- /* Command CRC error */
- dev_dbg(mmc_dev(host->mmc),
- "Command CRC error\r\n");
- if (host->cmd) {
- /* Ignore CMD CRC errors during
- * high speed operation */
- if (host->mmc->ios.clock <= 25000000)
- host->cmd->error = -EILSEQ;
- end_command = 1;
- }
- }
+static inline void handle_other_commands(
+ struct mmc_davinci_host *host, unsigned int status)
+{
+ unsigned long flags;
+ if (host->cmd_code == 13) {
+ if (status & MMCSD_EVENT_EOFCMD) {
+ spin_lock_irqsave(&host->lock, flags);
+ host->new_card_state = 1;
+ spin_unlock_irqrestore(&host->lock, flags);
+ } else {
+ spin_lock_irqsave(&host->lock, flags);
+ host->is_card_removed = 1;
+ host->new_card_state = 0;
+ host->is_card_initialized = 0;
+ spin_unlock_irqrestore(&host->lock, flags);
+ }
- if (status & MMCSD_EVENT_EOFCMD) {
- /* End of command phase */
- end_command = 1;
- }
+ spin_lock_irqsave(&host->lock, flags);
+ host->is_card_detect_progress = 0;
+ spin_unlock_irqrestore(&host->lock, flags);
- status = readl(host->base + DAVINCI_MMCST0);
- if (host->data == NULL) {
- if (status != 0) {
- dev_dbg(mmc_dev(host->mmc),
- "Status is %x at end of ISR "
- "when host->data is NULL\n",
- status);
- status = 0;
- }
- }
+ if (host->is_req_queued_up) {
+ mmc_davinci_request(host->mmc, host->que_mmc_request);
+ spin_lock_irqsave(&host->lock, flags);
+ host->is_req_queued_up = 0;
+ spin_unlock_irqrestore(&host->lock, flags);
}
- if (end_command)
- mmc_davinci_cmd_done(host, host->cmd);
- if (end_transfer)
- mmc_davinci_xfer_done(host, host->data);
-
- } else {
- if (host->cmd_code == 13) {
- if (status & MMCSD_EVENT_EOFCMD) {
- spin_lock_irqsave(&host->lock, flags);
- host->new_card_state = 1;
- spin_unlock_irqrestore(&host->lock, flags);
+ }
- } else {
- spin_lock_irqsave(&host->lock, flags);
- host->is_card_removed = 1;
- host->new_card_state = 0;
- host->is_card_initialized = 0;
- spin_unlock_irqrestore(&host->lock, flags);
- }
+ if (host->cmd_code == 1 || host->cmd_code == 55) {
+ if (status & MMCSD_EVENT_EOFCMD) {
+ spin_lock_irqsave(&host->lock, flags);
+ host->is_card_removed = 0;
+ host->new_card_state = 1;
+ host->is_card_initialized = 0;
+ spin_unlock_irqrestore(&host->lock, flags);
+ } else {
spin_lock_irqsave(&host->lock, flags);
- host->is_card_detect_progress = 0;
+ host->is_card_removed = 1;
+ host->new_card_state = 0;
+ host->is_card_initialized = 0;
spin_unlock_irqrestore(&host->lock, flags);
+ }
- if (host->is_req_queued_up) {
- mmc_davinci_request(host->mmc,
- host->que_mmc_request);
- spin_lock_irqsave(&host->lock, flags);
- host->is_req_queued_up = 0;
- spin_unlock_irqrestore(&host->lock, flags);
- }
+ spin_lock_irqsave(&host->lock, flags);
+ host->is_card_detect_progress = 0;
+ spin_unlock_irqrestore(&host->lock, flags);
+ if (host->is_req_queued_up) {
+ mmc_davinci_request(host->mmc, host->que_mmc_request);
+ spin_lock_irqsave(&host->lock, flags);
+ host->is_req_queued_up = 0;
+ spin_unlock_irqrestore(&host->lock, flags);
}
+ }
- if (host->cmd_code == 1 || host->cmd_code == 55) {
- if (status & MMCSD_EVENT_EOFCMD) {
- spin_lock_irqsave(&host->lock, flags);
- host->is_card_removed = 0;
- host->new_card_state = 1;
- host->is_card_initialized = 0;
- spin_unlock_irqrestore(&host->lock, flags);
- } else {
+ if (host->cmd_code == 0) {
+ if (status & MMCSD_EVENT_EOFCMD) {
+ static int flag_sd_mmc;
+ host->is_core_command = 0;
- spin_lock_irqsave(&host->lock, flags);
- host->is_card_removed = 1;
- host->new_card_state = 0;
- host->is_card_initialized = 0;
- spin_unlock_irqrestore(&host->lock, flags);
+ if (flag_sd_mmc) {
+ flag_sd_mmc = 0;
+ host->cmd_code = 1;
+ /* Issue cmd1 */
+ writel(0x80300000,
+ host->base + DAVINCI_MMCARGHL);
+ writel(MMCCMD_RSPFMT_R3 | 1,
+ host->base + DAVINCI_MMCCMD);
+ } else {
+ flag_sd_mmc = 1;
+ host->cmd_code = 55;
+ /* Issue cmd55 */
+ writel(0x0,
+ host->base + DAVINCI_MMCARGHL);
+ writel(MMCCMD_RSPFMT_R1456 | 55,
+ host->base + DAVINCI_MMCCMD);
}
+ dev_dbg(mmc_dev(host->mmc),
+ "MMC-Probing mmc with cmd%d\n", host->cmd_code);
+ } else {
spin_lock_irqsave(&host->lock, flags);
+ host->new_card_state = 0;
+ host->is_card_initialized = 0;
host->is_card_detect_progress = 0;
spin_unlock_irqrestore(&host->lock, flags);
-
- if (host->is_req_queued_up) {
- mmc_davinci_request(host->mmc,
- host->que_mmc_request);
- spin_lock_irqsave(&host->lock, flags);
- host->is_req_queued_up = 0;
- spin_unlock_irqrestore(&host->lock, flags);
- }
}
+ }
+}
- if (host->cmd_code == 0) {
- if (status & MMCSD_EVENT_EOFCMD) {
- static int flag_sd_mmc;
- host->is_core_command = 0;
-
- if (flag_sd_mmc) {
- flag_sd_mmc = 0;
- host->cmd_code = 1;
- /* Issue cmd1 */
- writel(0x80300000,
- host->base + DAVINCI_MMCARGHL);
- writel(MMCCMD_RSPFMT_R3 | 1,
- host->base + DAVINCI_MMCCMD);
- } else {
- flag_sd_mmc = 1;
- host->cmd_code = 55;
- /* Issue cmd55 */
- writel(0x0,
- host->base + DAVINCI_MMCARGHL);
- writel(MMCCMD_RSPFMT_R1456 | 55,
- host->base + DAVINCI_MMCCMD);
- }
-
- dev_dbg(mmc_dev(host->mmc),
- "MMC-Probing mmc with cmd%d\n",
- host->cmd_code);
- } else {
- spin_lock_irqsave(&host->lock, flags);
- host->new_card_state = 0;
- host->is_card_initialized = 0;
- host->is_card_detect_progress = 0;
- spin_unlock_irqrestore(&host->lock, flags);
- }
- }
+static irqreturn_t mmc_davinci_irq(int irq, void *dev_id)
+{
+ struct mmc_davinci_host *host = (struct mmc_davinci_host *)dev_id;
+ unsigned int status;
+ if (host->is_core_command) {
+ if (host->cmd == NULL && host->data == NULL) {
+ status = readl(host->base + DAVINCI_MMCST0);
+ dev_dbg(mmc_dev(host->mmc),
+ "Spurious interrupt 0x%04x\n", status);
+ /* Disable the interrupt from mmcsd */
+ writel(0, host->base + DAVINCI_MMCIM);
+ return IRQ_HANDLED;
+ }
}
+ do {
+ status = readl(host->base + DAVINCI_MMCST0);
+ if (status == 0)
+ break;
+
+ if (host->is_core_command) {
+ if (handle_core_command(host, status))
+ break;
+ } else {
+ handle_other_commands(host, status);
+ }
+ } while (1);
return IRQ_HANDLED;
}
_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source