return cmdr;
 }
 
+static inline void dw_mci_set_cto(struct dw_mci *host)
+{
+       unsigned int cto_clks;
+       unsigned int cto_ms;
+
+       cto_clks = mci_readl(host, TMOUT) & 0xff;
+       cto_ms = DIV_ROUND_UP(cto_clks, host->bus_hz / 1000);
+
+       /* add a bit spare time */
+       cto_ms += 10;
+
+       mod_timer(&host->cto_timer,
+                 jiffies + msecs_to_jiffies(cto_ms) + 1);
+}
+
 static void dw_mci_start_command(struct dw_mci *host,
                                 struct mmc_command *cmd, u32 cmd_flags)
 {
        wmb(); /* drain writebuffer */
        dw_mci_wait_while_busy(host, cmd_flags);
 
+       /* response expected command only */
+       if (cmd_flags & SDMMC_CMD_RESP_EXP)
+               dw_mci_set_cto(host);
+
        mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START);
 }
 
                }
 
                if (pending & DW_MCI_CMD_ERROR_FLAGS) {
+                       del_timer(&host->cto_timer);
                        mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS);
                        host->cmd_status = pending;
                        smp_wmb(); /* drain writebuffer */
                }
 
                if (pending & SDMMC_INT_CMD_DONE) {
+                       del_timer(&host->cto_timer);
                        mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE);
                        dw_mci_cmd_interrupt(host, pending);
                }
        tasklet_schedule(&host->tasklet);
 }
 
+static void dw_mci_cto_timer(unsigned long arg)
+{
+       struct dw_mci *host = (struct dw_mci *)arg;
+
+       switch (host->state) {
+       case STATE_SENDING_CMD11:
+       case STATE_SENDING_CMD:
+       case STATE_SENDING_STOP:
+               /*
+                * If CMD_DONE interrupt does NOT come in sending command
+                * state, we should notify the driver to terminate current
+                * transfer and report a command timeout to the core.
+                */
+               host->cmd_status = SDMMC_INT_RTO;
+               set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
+               tasklet_schedule(&host->tasklet);
+               break;
+       default:
+               dev_warn(host->dev, "Unexpected command timeout, state %d\n",
+                        host->state);
+               break;
+       }
+}
+
 static void dw_mci_dto_timer(unsigned long arg)
 {
        struct dw_mci *host = (struct dw_mci *)arg;
        setup_timer(&host->cmd11_timer,
                    dw_mci_cmd11_timer, (unsigned long)host);
 
+       setup_timer(&host->cto_timer,
+                   dw_mci_cto_timer, (unsigned long)host);
+
        setup_timer(&host->dto_timer,
                    dw_mci_dto_timer, (unsigned long)host);