Make sure fifo does not need serviced before handling
other interrupt sources
Signed-off-by: Troy Kisky <[EMAIL PROTECTED]>
---
drivers/mmc/host/davinci_mmc.c | 454 +++++++++++++++++++---------------------
1 files changed, 218 insertions(+), 236 deletions(-)
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 6b1182c..9a70c97 100755
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -960,283 +960,265 @@ static void mmc_davinci_cmd_done(struct
mmc_davinci_host *host,
}
}
-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 = mmcsd_regs->mmc_st0;
- dev_dbg(&mmc_dev, "Spurious interrupt 0x%04x\r\n",
- status);
- /* Disable the interrupt from mmcsd */
- mmcsd_regs->mmc_im = 0;
- return IRQ_HANDLED;
+ if ((is_card_initialized) && (new_card_state == 0)) {
+ if (host->cmd) {
+ host->cmd->error = -ETIMEDOUT;
+ mmc_davinci_cmd_done(host, host->cmd);
}
+ dev_dbg(&mmc_dev, "From code segment "
+ "excuted when card removed\n");
+ return -1;
}
- end_command = 0;
- end_transfer = 0;
- status = mmcsd_regs->mmc_st0;
- 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 (is_card_initialized) {
- if (new_card_state == 0) {
- if (host->cmd) {
- host->cmd->error = -ETIMEDOUT;
- mmc_davinci_cmd_done(host, host->cmd);
- }
- dev_dbg(&mmc_dev,
- "From code segment excuted 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 = mmcsd_regs->mmc_st0;
+ if (!status)
+ break;
+ qstatus |= status;
+ if (host->data == NULL) {
+ dev_dbg(&mmc_dev, "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, "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) && (new_card_state != 0)) {
+ host->data->error = -ETIMEDOUT;
+ spin_lock_irqsave(&mmc_lock, flags);
+ is_card_removed = 1;
+ new_card_state = 0;
+ is_card_initialized = 0;
+ spin_unlock_irqrestore(&mmc_lock, flags);
+ dev_dbg(&mmc_dev, "MMCSD: Data timeout, "
+ "CMD%d and status is %x\r\n",
+ host->cmd->opcode, status);
- 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,
- "TC:host->data is NULL\n");
- }
- }
+ if (host->cmd)
+ host->cmd->error = -ETIMEDOUT;
+ end_transfer = 1;
+ }
+ }
- if (status & MMCSD_EVENT_ERROR_DATATIMEOUT) {
- /* Data timeout */
- if ((host->data) && (new_card_state != 0)) {
- host->data->error = -ETIMEDOUT;
- spin_lock_irqsave(&mmc_lock, flags);
- is_card_removed = 1;
- new_card_state = 0;
- is_card_initialized = 0;
- spin_unlock_irqrestore(&mmc_lock,
- flags);
- dev_dbg(&mmc_dev,
- "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_DATACRC) {
+ /* DAT line portion is disabled and in reset state */
+ mmcsd_regs->mmc_ctl |= (1 << 1);
+ udelay(10);
+ mmcsd_regs->mmc_ctl &= ~(1 << 1);
+
+ /* Data CRC error */
+ if (host->data) {
+ host->data->error = -EILSEQ;
+ dev_dbg(&mmc_dev, "MMCSD: Data CRC error, "
+ "bytes left %d\r\n", host->bytes_left);
+ end_transfer = 1;
+ } else {
+ dev_dbg(&mmc_dev, "MMCSD: Data CRC error\r\n");
+ }
+ }
- if (status & MMCSD_EVENT_ERROR_DATACRC) {
- /* DAT line portion is diabled and in reset
state */
- mmcsd_regs->mmc_ctl =
- mmcsd_regs->mmc_ctl | (1 << 1);
- udelay(10);
- mmcsd_regs->mmc_ctl =
- mmcsd_regs->mmc_ctl & ~(1 << 1);
-
- /* Data CRC error */
- if (host->data) {
- host->data->error = -EILSEQ;
- dev_dbg(&mmc_dev,
- "MMCSD: Data CRC error, bytes
left %d\r\n",
- host->bytes_left);
- end_transfer = 1;
- } else {
- dev_dbg(&mmc_dev,
- "MMCSD: Data CRC error\r\n");
- }
+ 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, "MMCSD: CMD%d timeout,"
+ " status %x\r\n", host->cmd->opcode,
+ status);
+ spin_lock_irqsave(&mmc_lock, flags);
+ new_card_state = 0;
+ is_card_initialized = 0;
+ spin_unlock_irqrestore(&mmc_lock, flags);
}
+ host->cmd->error = -ETIMEDOUT;
+ 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,
- "MMCSD: CMD%d timeout,"
- " status %x\r\n",
- host->cmd->opcode,
- status);
- spin_lock_irqsave(&mmc_lock,
- flags);
- new_card_state = 0;
- is_card_initialized = 0;
- spin_unlock_irqrestore(
- &mmc_lock, flags);
- }
- host->cmd->error = -ETIMEDOUT;
- end_command = 1;
-
- }
- }
+ if (qstatus & MMCSD_EVENT_ERROR_CMDCRC) {
+ /* Command CRC error */
+ dev_dbg(&mmc_dev, "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;
+ }
+ }
- if (status & MMCSD_EVENT_ERROR_CMDCRC) {
- /* Command CRC error */
- dev_dbg(&mmc_dev, "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;
- }
- }
+ if (qstatus & MMCSD_EVENT_EOFCMD) {
+ /* End of command phase */
+ end_command = 1;
+ }
- if (status & 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 (host->data == NULL) {
- status = mmcsd_regs->mmc_st0;
- if (status != 0) {
- dev_dbg(&mmc_dev,
- "Status is %x at end of ISR
when host->data is NULL",
- status);
- status = 0;
+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(&mmc_lock, flags);
+ new_card_state = 1;
+ spin_unlock_irqrestore(&mmc_lock, flags);
- }
- } else {
- status = mmcsd_regs->mmc_st0;
- }
+ } else {
+ spin_lock_irqsave(&mmc_lock, flags);
+ is_card_removed = 1;
+ new_card_state = 0;
+ is_card_initialized = 0;
+ spin_unlock_irqrestore(&mmc_lock, flags);
}
- if (end_command)
- mmc_davinci_cmd_done(host, host->cmd);
- if (end_transfer)
- mmc_davinci_xfer_done(host, host->data);
+ spin_lock_irqsave(&mmc_lock, flags);
+ is_card_detect_progress = 0;
+ spin_unlock_irqrestore(&mmc_lock, flags);
- } else {
- if (host->cmd_code == 13) {
- if (status & MMCSD_EVENT_EOFCMD) {
- spin_lock_irqsave(&mmc_lock, flags);
- new_card_state = 1;
- spin_unlock_irqrestore(&mmc_lock, flags);
+ if (is_req_queued_up) {
+ mmc_davinci_request(que_mmc_host, que_mmc_request);
+ spin_lock_irqsave(&mmc_lock, flags);
+ is_req_queued_up = 0;
+ spin_unlock_irqrestore(&mmc_lock, flags);
+ }
- } else {
- spin_lock_irqsave(&mmc_lock, flags);
- is_card_removed = 1;
- new_card_state = 0;
- is_card_initialized = 0;
- spin_unlock_irqrestore(&mmc_lock, flags);
- }
+ }
+ if (host->cmd_code == 1 || host->cmd_code == 55) {
+ if (status & MMCSD_EVENT_EOFCMD) {
spin_lock_irqsave(&mmc_lock, flags);
- is_card_detect_progress = 0;
+ is_card_removed = 0;
+ new_card_state = 1;
+ is_card_initialized = 0;
spin_unlock_irqrestore(&mmc_lock, flags);
+ } else {
- if (is_req_queued_up) {
- mmc_davinci_request(que_mmc_host,
- que_mmc_request);
- spin_lock_irqsave(&mmc_lock, flags);
- is_req_queued_up = 0;
- spin_unlock_irqrestore(&mmc_lock, flags);
- }
+ spin_lock_irqsave(&mmc_lock, flags);
+ is_card_removed = 1;
+ new_card_state = 0;
+ is_card_initialized = 0;
+ spin_unlock_irqrestore(&mmc_lock, flags);
+ }
+
+ spin_lock_irqsave(&mmc_lock, flags);
+ is_card_detect_progress = 0;
+ spin_unlock_irqrestore(&mmc_lock, flags);
+ if (is_req_queued_up) {
+ mmc_davinci_request(que_mmc_host, que_mmc_request);
+ spin_lock_irqsave(&mmc_lock, flags);
+ is_req_queued_up = 0;
+ spin_unlock_irqrestore(&mmc_lock, flags);
}
+ }
- if (host->cmd_code == 1 || host->cmd_code == 55) {
- if (status & MMCSD_EVENT_EOFCMD) {
- spin_lock_irqsave(&mmc_lock, flags);
- is_card_removed = 0;
- new_card_state = 1;
- is_card_initialized = 0;
- spin_unlock_irqrestore(&mmc_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(&mmc_lock, flags);
- is_card_removed = 1;
- new_card_state = 0;
- is_card_initialized = 0;
- spin_unlock_irqrestore(&mmc_lock, flags);
+ if (flag_sd_mmc) {
+ flag_sd_mmc = 0;
+ host->cmd_code = 1;
+ /* Issue cmd1 */
+ mmcsd_regs->mmc_arghl = 0x80300000;
+ mmcsd_regs->mmc_cmd = 0x00000601;
+ } else {
+ flag_sd_mmc = 1;
+ host->cmd_code = 55;
+ /* Issue cmd55 */
+ mmcsd_regs->mmc_arghl = 0x0;
+ mmcsd_regs->mmc_cmd = (0x0 | (1 << 9) | 55);
}
+ dev_dbg(&mmc_dev, "MMC-Probing mmc with cmd%d\n",
+ host->cmd_code);
+ } else {
spin_lock_irqsave(&mmc_lock, flags);
+ new_card_state = 0;
+ is_card_initialized = 0;
is_card_detect_progress = 0;
spin_unlock_irqrestore(&mmc_lock, flags);
-
- if (is_req_queued_up) {
- mmc_davinci_request(que_mmc_host,
- que_mmc_request);
- spin_lock_irqsave(&mmc_lock, flags);
- is_req_queued_up = 0;
- spin_unlock_irqrestore(&mmc_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 */
- mmcsd_regs->mmc_arghl = 0x80300000;
- mmcsd_regs->mmc_cmd = 0x00000601;
- } else {
- flag_sd_mmc = 1;
- host->cmd_code = 55;
- /* Issue cmd55 */
- mmcsd_regs->mmc_arghl = 0x0;
- mmcsd_regs->mmc_cmd =
- ((0x0 | (1 << 9) | 55));
- }
-
- dev_dbg(&mmc_dev,
- "MMC-Probing mmc with cmd%d\n",
- host->cmd_code);
- } else {
- spin_lock_irqsave(&mmc_lock, flags);
- new_card_state = 0;
- is_card_initialized = 0;
- is_card_detect_progress = 0;
- spin_unlock_irqrestore(&mmc_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 = mmcsd_regs->mmc_st0;
+ dev_dbg(&mmc_dev, "Spurious interrupt 0x%04x\r\n",
+ status);
+ /* Disable the interrupt from mmcsd */
+ mmcsd_regs->mmc_im = 0;
+ return IRQ_HANDLED;
+ }
}
+ do {
+ status = mmcsd_regs->mmc_st0;
+ 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;
}
--
1.5.4
_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source