fix the wirte-data timeout during SDcard copy by USB
authorxbw <xbw@rock-chips.com>
Sat, 8 Oct 2011 03:06:37 +0000 (11:06 +0800)
committerxbw <xbw@rock-chips.com>
Sat, 8 Oct 2011 03:06:37 +0000 (11:06 +0800)
drivers/mmc/core/core.c
drivers/mmc/host/rk29_sdmmc.c
drivers/mmc/host/rk29_sdmmc.h [changed mode: 0644->0755]

index 519722a41b6b95fcbebc0a5a863e0cdaf7820fed..20e0f52d9785ddba048ba5ad6b61835a1b0ab4b2 100755 (executable)
@@ -195,7 +195,9 @@ static void mmc_wait_done(struct mmc_request *mrq)
  */
 void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
 {
-    unsigned long waittime;
+    unsigned long datasize, waittime=0xFFFF;
+    u32 multi, unit;
+    
        DECLARE_COMPLETION_ONSTACK(complete);
 
        mrq->done_data = &complete;
@@ -204,11 +206,34 @@ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
        mmc_start_request(host, mrq);
 
 #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
-    waittime = wait_for_completion_timeout(&complete,HZ*7); //for cmd dead. Modifyed by xbw at 2011-06-02
+    if( strncmp( mmc_hostname(host) ,"mmc0" , strlen("mmc0")) ) 
+    {
+        waittime = wait_for_completion_timeout(&complete,HZ*2); //sdio; for cmd dead. Modifyed by xbw at 2011-06-02
+    }
+    else
+    {   
+        //calculate the timeout value for SDMMC; added by xbw at 2011-09-27
+        if(mrq->data)
+        {
+            unit = 3*(1<<20);// unit=3MB
+            datasize = mrq->data->blksz*mrq->data->blocks;
+            multi = datasize/unit;
+            multi += (datasize%unit)?1:0;
+            multi = (multi>0) ? multi : 1;
+            multi += (mrq->cmd->retries>0)?1:0;
+            waittime = wait_for_completion_timeout(&complete,HZ*2*multi);
+        }
+        else
+        {
+            waittime = wait_for_completion_timeout(&complete,HZ*2);
+        }
+    }
+    
     if(waittime <= 1)
     {
         host->doneflag = 0;
-        printk("%s...%d..  =====!!!!!!!!!CMD%d timeout ===xbw===\n",__FUNCTION__, __LINE__, mrq->cmd->opcode);
+        printk("%s..%d.. !!!!! wait for CMD%d timeout ===xbw[%s]===\n",\
+            __FUNCTION__, __LINE__, mrq->cmd->opcode, mmc_hostname(host));
     }
 #else    
        wait_for_completion(&complete);
index d2b735764cf30146beb24c75a8a8b6dbaad59e0f..46d69156d9a07448a0cbbef4e93a52d9fc594533 100755 (executable)
@@ -52,7 +52,7 @@
 #define RK29_SDMMC_xbw_Debug 0
 
 #if RK29_SDMMC_xbw_Debug 
-int debug_level = 7;
+int debug_level = 4;
 #define xbwprintk(n, format, arg...) \
        if (n <= debug_level) {  \
                printk(format,##arg); \
@@ -67,12 +67,12 @@ int debug_level = 7;
 #define RK29_SDMMC_INTMASK_USEIO    (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_CD| SDMMC_INT_TXDR | SDMMC_INT_RXDR )
 
 
-#define RK29_SDMMC_SEND_START_TIMEOUT   2000  //The time interval from the time SEND_CMD to START_CMD_BIT cleared.
+#define RK29_SDMMC_SEND_START_TIMEOUT   1000  //The time interval from the time SEND_CMD to START_CMD_BIT cleared.
 #define RK29_ERROR_PRINTK_INTERVAL      200   //The time interval between the two printk for the same error. 
-#define RK29_SDMMC_WAIT_DTO_INTERNVAL   1500  //The time interval from the CMD_DONE_INT to DTO_INT
-#define RK29_SDMMC_REMOVAL_DELAY        2000  //The time interval from the CD_INT to detect_timer react.
+#define RK29_SDMMC_WAIT_DTO_INTERNVAL   1000  //The time interval from the CMD_DONE_INT to DTO_INT
+#define RK29_SDMMC_REMOVAL_DELAY        1000  //The time interval from the CD_INT to detect_timer react.
 
-#define RK29_SDMMC_VERSION "Ver.2.09 The last modify date is 2011-09-22,modifyed by XBW." 
+#define RK29_SDMMC_VERSION "Ver.2.10 The last modify date is 2011-09-30,modifyed by XBW." 
 
 #define RK29_CTRL_SDMMC_ID   0  //mainly used by SDMMC
 #define RK29_CTRL_SDIO1_ID   1  //mainly used by sdio-wifi
@@ -138,7 +138,6 @@ typedef struct TagSDC_INT_INFO
 
 struct rk29_sdmmc {
        spinlock_t              lock;
-       spinlock_t              request_lock;
        void __iomem    *regs;
        struct clk              *clk;
 
@@ -225,6 +224,7 @@ static struct rk29_sdmmc    *globalSDhost[3];
        set_bit(event, &host->pending_events)
 
 static void rk29_sdmmc_start_error(struct rk29_sdmmc *host);
+static int rk29_sdmmc_clear_fifo(struct rk29_sdmmc *host);
 
 static void rk29_sdmmc_write(unsigned char  __iomem    *regbase, unsigned int regOff,unsigned int val)
 {
@@ -650,15 +650,80 @@ static u32 rk29_sdmmc_prepare_command(struct mmc_command *cmd)
        return cmdr;
 }
 
+void  rk29_sdmmc_set_frq(struct rk29_sdmmc *host)
+{
+    struct mmc_host *mmchost = platform_get_drvdata(host->pdev);
+    struct mmc_card    *card;
+    struct mmc_ios *ios;
+       unsigned int max_dtr;
+    
+    extern void mmc_set_clock(struct mmc_host *host, unsigned int hz);
+
+    if(!mmchost)
+        return;
+
+    card = (struct mmc_card    *)mmchost->card;
+    ios  = ( struct mmc_ios *)&mmchost->ios;
+
+    if(!card && !ios)
+        return;
+
+    if(MMC_POWER_ON == ios->power_mode)
+        return;
+
+    max_dtr = (unsigned int)-1;
+    
+    if (mmc_card_highspeed(card)) 
+    {
+        if (max_dtr > card->ext_csd.hs_max_dtr)
+            max_dtr = card->ext_csd.hs_max_dtr;
+            
+    }
+    else if (max_dtr > card->csd.max_dtr) 
+    {
+        if(MMC_TYPE_SD == card->type)
+        {
+               max_dtr = (card->csd.max_dtr > SD_FPP_FREQ) ? SD_FPP_FREQ : (card->csd.max_dtr);
+           }
+           else
+           {   
+            max_dtr = (card->csd.max_dtr > MMC_FPP_FREQ) ? MMC_FPP_FREQ : (card->csd.max_dtr);
+           }       
+    }
+
+    xbwprintk(7, "%s..%d...  call mmc_set_clock() set clk=%d ===xbw[%s]===\n", \
+                       __FUNCTION__, __LINE__, max_dtr, host->dma_name);
+
+  
+    mmc_set_clock(mmchost, max_dtr);
+
+}
+
 
 static int rk29_sdmmc_start_command(struct rk29_sdmmc *host, struct mmc_command *cmd, u32 cmd_flags)
 {
-       int tmo = RK29_SDMMC_SEND_START_TIMEOUT*2;
+       int tmo = RK29_SDMMC_SEND_START_TIMEOUT*3;
        
        host->cmd = cmd;
        host->old_cmd = cmd->opcode;
        host->errorstep = 0;
-               
+       host->pending_events = 0;
+       host->completed_events = 0;     
+       host->complete_done = 0;
+    host->retryfunc = 0;
+    host->cmd_status = 0;
+
+    if(MMC_STOP_TRANSMISSION != cmd->opcode)
+    {
+        host->data_status = 0;
+    }
+    
+    if(RK29_CTRL_SDMMC_ID == host->pdev->id)
+    {
+        //adjust the frequency division control of SDMMC0 every time.
+        rk29_sdmmc_set_frq(host);
+    }
+                       
        rk29_sdmmc_write(host->regs, SDMMC_CMDARG, cmd->arg); // write to SDMMC_CMDARG register
        rk29_sdmmc_write(host->regs, SDMMC_CMD, cmd_flags | SDMMC_CMD_START); // write to SDMMC_CMD register
 
@@ -689,7 +754,8 @@ static int rk29_sdmmc_start_command(struct rk29_sdmmc *host, struct mmc_command
                host->errorstep = 0x1;
                return SDM_WAIT_FOR_CMDSTART_TIMEOUT;
        }
-    
+    host->errorstep = 0xfe;
        return SDM_SUCCESS;
 }
 
@@ -727,7 +793,7 @@ static int rk29_sdmmc_wait_unbusy(struct rk29_sdmmc *host)
 {
        int time_out = 250000; //max is 250ms
 
-       while (rk29_sdmmc_read(host->regs, SDMMC_STATUS) & SDMMC_STAUTS_DATA_BUSY
+       while (rk29_sdmmc_read(host->regs, SDMMC_STATUS) & (SDMMC_STAUTS_DATA_BUSY|SDMMC_STAUTS_MC_BUSY)
        {
                udelay(1);
                time_out--;
@@ -742,38 +808,6 @@ static int rk29_sdmmc_wait_unbusy(struct rk29_sdmmc *host)
        return SDM_SUCCESS;
 }
 
-static void send_stop_cmd(struct rk29_sdmmc *host)
-{
-    int ret;
-    
-    mod_timer(&host->request_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_SEND_START_TIMEOUT+600));
-               
-    host->stopcmd.opcode = MMC_STOP_TRANSMISSION;
-    host->stopcmd.flags  = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;;
-    host->stopcmd.arg = 0;
-    host->stopcmd.data = NULL;
-    host->stopcmd.mrq = NULL;
-    host->stopcmd.retries = 0;
-    host->stopcmd.error = 0;
-    if(host->mrq && host->mrq->stop)
-    {
-        host->mrq->stop->error = 0;
-    }
-    
-    host->cmdr = rk29_sdmmc_prepare_command(&host->stopcmd);
-    
-    rk29_sdmmc_wait_unbusy(host);
-    
-    ret = rk29_sdmmc_start_command(host, &host->stopcmd, host->cmdr); 
-    if(SDM_SUCCESS != ret)
-    {
-        rk29_sdmmc_start_error(host);
-
-        host->state = STATE_IDLE;
-        host->complete_done = 4;
-    }
-}
-
 static void rk29_sdmmc_dma_cleanup(struct rk29_sdmmc *host)
 {
        if (host->data) 
@@ -835,6 +869,55 @@ static void rk29_sdmmc_control_host_dma(struct rk29_sdmmc *host, bool enable)
     rk29_sdmmc_write(host->regs, SDMMC_CTRL, value);
 }
 
+static void send_stop_cmd(struct rk29_sdmmc *host)
+{
+    int ret;
+
+    if(host->mrq->cmd->error)
+    {
+        //stop DMA
+        if(host->dodma)
+        {
+            rk29_sdmmc_stop_dma(host);
+            rk29_sdmmc_control_host_dma(host, FALSE);
+
+            host->dodma = 0;
+        }
+        
+        ret= rk29_sdmmc_clear_fifo(host);
+        if(SDM_SUCCESS != ret)
+        {
+            xbwprintk(3, "%s..%d..  clear fifo error before call CMD_STOP ====xbw[%s]====\n", \
+                                                       __FUNCTION__, __LINE__, host->dma_name);
+        }
+    }
+    
+    mod_timer(&host->request_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_SEND_START_TIMEOUT+1500));
+               
+    host->stopcmd.opcode = MMC_STOP_TRANSMISSION;
+    host->stopcmd.flags  = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;;
+    host->stopcmd.arg = 0;
+    host->stopcmd.data = NULL;
+    host->stopcmd.mrq = NULL;
+    host->stopcmd.retries = 0;
+    host->stopcmd.error = 0;
+    if(host->mrq && host->mrq->stop)
+    {
+        host->mrq->stop->error = 0;
+    }
+    
+    host->cmdr = rk29_sdmmc_prepare_command(&host->stopcmd);
+    
+    ret = rk29_sdmmc_start_command(host, &host->stopcmd, host->cmdr); 
+    if(SDM_SUCCESS != ret)
+    {
+        rk29_sdmmc_start_error(host);
+
+        host->state = STATE_IDLE;
+        host->complete_done = 4;
+    }
+}
+
 
 /* This function is called by the DMA driver from tasklet context. */
 static void rk29_sdmmc_dma_complete(void *arg, int size, enum rk29_dma_buffresult result) 
@@ -1178,7 +1261,7 @@ static void rk29_sdmmc_submit_data(struct rk29_sdmmc *host, struct mmc_data *dat
                rk29_sdmmc_write(host->regs, SDMMC_BYTCNT,data->blksz*data->blocks);
                rk29_sdmmc_write(host->regs, SDMMC_BLKSIZ,data->blksz);
 
-        xbwprintk(3, "%s..%d..CMD%d(arg=0x%x), data->blksz=%d, data->blocks=%d   ==xbw=[%s]==\n", \
+        xbwprintk(6, "%s..%d..CMD%d(arg=0x%x), data->blksz=%d, data->blocks=%d   ==xbw=[%s]==\n", \
             __FUNCTION__, __LINE__, host->cmd->opcode,host->cmd->arg,data->blksz, data->blocks,  host->dma_name);
             
                if (data->flags & MMC_DATA_WRITE)
@@ -1209,12 +1292,12 @@ static void rk29_sdmmc_submit_data(struct rk29_sdmmc *host, struct mmc_data *dat
 
 static int sdmmc_send_cmd_start(struct rk29_sdmmc *host, unsigned int cmd)
 {
-       int tmo = 1000;
+       int tmo = RK29_SDMMC_SEND_START_TIMEOUT*3;;
        
        rk29_sdmmc_write(host->regs, SDMMC_CMD, SDMMC_CMD_START | cmd);         
        while (--tmo && readl(host->regs + SDMMC_CMD) & SDMMC_CMD_START)
        {
-           cpu_relax();
+           udelay(2);
        }
        
        if(!tmo) 
@@ -1556,55 +1639,6 @@ int rk29_sdmmc_set_buswidth(struct rk29_sdmmc *host)
 }
 
 
-void  rk29_sdmmc_set_frq(struct rk29_sdmmc *host)
-{
-    struct mmc_host *mmchost = platform_get_drvdata(host->pdev);
-    struct mmc_card    *card;
-    struct mmc_ios *ios;
-       unsigned int max_dtr;
-    
-    extern void mmc_set_clock(struct mmc_host *host, unsigned int hz);
-
-    if(!mmchost)
-        return;
-
-    card = (struct mmc_card    *)mmchost->card;
-    ios  = ( struct mmc_ios *)&mmchost->ios;
-
-    if(!card && !ios)
-        return;
-
-    if(MMC_POWER_ON == ios->power_mode)
-        return;
-
-    max_dtr = (unsigned int)-1;
-    
-    if (mmc_card_highspeed(card)) 
-    {
-        if (max_dtr > card->ext_csd.hs_max_dtr)
-            max_dtr = card->ext_csd.hs_max_dtr;
-            
-    }
-    else if (max_dtr > card->csd.max_dtr) 
-    {
-        if(MMC_TYPE_SD == card->type)
-        {
-               max_dtr = (card->csd.max_dtr > SD_FPP_FREQ) ? SD_FPP_FREQ : (card->csd.max_dtr);
-           }
-           else
-           {   
-            max_dtr = (card->csd.max_dtr > MMC_FPP_FREQ) ? MMC_FPP_FREQ : (card->csd.max_dtr);
-           }       
-    }
-
-    xbwprintk(7, "%s..%d...  call mmc_set_clock() set clk=%d ===xbw[%s]===\n", \
-                       __FUNCTION__, __LINE__, max_dtr, host->dma_name);
-
-  
-    mmc_set_clock(mmchost, max_dtr);
-
-}
-
 static void rk29_sdmmc_dealwith_timeout(struct rk29_sdmmc *host)
 { 
     if(0 == host->mmc->doneflag)
@@ -1763,26 +1797,17 @@ static int rk29_sdmmc_start_request(struct mmc_host *mmc )
 
     host->cmdr = cmdr;
     host->cmd = cmd;
-       host->pending_events = 0;
-       host->completed_events = 0;
        host->data_status = 0;
        host->data = NULL;
        
        host->errorstep = 0;
        host->dodma = 0;
-    host->complete_done = 0;
-    host->retryfunc = 0;
 
-    if(RK29_CTRL_SDMMC_ID == host->pdev->id)
-    {
-        //adjust the frequency division control of SDMMC0 every time.
-        rk29_sdmmc_set_frq(host);
-    }
-       
+
 
     //setting for the data
        rk29_sdmmc_submit_data(host, mrq->data);
-
+    host->errorstep = 0xff;
 
        xbwprintk(7, "%s..%d...    CMD%d  begin to call rk29_sdmmc_start_command() ===xbw[%s]===\n", \
                        __FUNCTION__, __LINE__ , cmd->opcode,host->dma_name);
@@ -1811,6 +1836,7 @@ static int rk29_sdmmc_start_request(struct mmc_host *mmc )
         
         goto start_request_Err; 
        }
+       host->errorstep = 0xfd;
 
     xbwprintk(7, "%s..%d...  CMD=%d, wait for INT_CMD_DONE, ret=%d , \n  \
         host->state=0x%x, cmdINT=0x%x \n    host->pendingEvent=0x%lu, host->completeEvents=0x%lu =========xbw=[%s]=====\n\n",\
@@ -1853,8 +1879,6 @@ static void rk29_sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
     unsigned long iflags;
        struct rk29_sdmmc *host = mmc_priv(mmc); 
        
-    spin_lock(&host->request_lock);
-
     spin_lock_irqsave(&host->lock, iflags);
     
        #if 0
@@ -1868,11 +1892,11 @@ static void rk29_sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
         host->state = STATE_IDLE;
         spin_unlock_irqrestore(&host->lock, iflags);
            mmc_request_done(mmc, mrq);
-               goto request_ext;//return;
+               return;
        }
        #endif
 
-    xbwprintk(3, "\n%s..%d..New cmd=%2d(arg=0x%8x)=== cardPresent=0x%lu, state=0x%x ==xbw[%s]==\n", \
+    xbwprintk(6, "\n%s..%d..New cmd=%2d(arg=0x%8x)=== cardPresent=0x%lu, state=0x%x ==xbw[%s]==\n", \
         __FUNCTION__, __LINE__,mrq->cmd->opcode, mrq->cmd->arg,host->flags,host->state, host->dma_name);
 
     if(RK29_CTRL_SDMMC_ID == host->pdev->id)
@@ -1916,7 +1940,7 @@ static void rk29_sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
             host->state = STATE_IDLE;
             spin_unlock_irqrestore(&host->lock, iflags);
                mmc_request_done(mmc, mrq);
-               goto request_ext;//return;
+               return;
        }
        else
        {
@@ -1972,14 +1996,12 @@ static void rk29_sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
                spin_unlock_irqrestore(&host->lock, iflags);            
                mmc_request_done(mmc, mrq);
                
-               goto request_ext;//return;
+               return;
                                
         #endif 
        }       
        #endif
-       
-request_ext:
-    spin_unlock(&host->request_lock);
+
 }
 
 
@@ -2147,6 +2169,7 @@ static void  rk29_sdmmc_init_card(struct mmc_host *mmc, struct mmc_card *card)
 static int rk29_sdmmc_clear_fifo(struct rk29_sdmmc *host)
 {
     unsigned int timeout, value;
+    int ret = SDM_SUCCESS;
 
     if(RK29_CTRL_SDMMC_ID == host->pdev->id)
     {
@@ -2171,11 +2194,14 @@ static int rk29_sdmmc_clear_fifo(struct rk29_sdmmc *host)
     }
 
      /* reset */
-    rk29_sdmmc_write(host->regs, SDMMC_CTRL,(SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET ));
-
     timeout = 1000;
     value = rk29_sdmmc_read(host->regs, SDMMC_CTRL);
-    while (( value & (SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_RESET)) && (timeout > 0))
+    value |= (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET);
+    rk29_sdmmc_write(host->regs, SDMMC_CTRL, value);
+
+    value = rk29_sdmmc_read(host->regs, SDMMC_CTRL);
+    
+    while( (value & (SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_RESET | SDMMC_CTRL_DMA_RESET)) && (timeout > 0))
     {
         udelay(1);
         timeout--;
@@ -2185,8 +2211,10 @@ static int rk29_sdmmc_clear_fifo(struct rk29_sdmmc *host)
     if (timeout == 0)
     {
         host->errorstep = 0x0A;
-        return SDM_WAIT_FOR_FIFORESET_TIMEOUT;
+        ret = SDM_WAIT_FOR_FIFORESET_TIMEOUT;
     }
+
+    return ret;
 }
 
 
@@ -2208,7 +2236,7 @@ static const struct mmc_host_ops rk29_sdmmc_ops[] = {
 
 static void rk29_sdmmc_request_end(struct rk29_sdmmc *host, struct mmc_command *cmd)
 {
-       u32 status;
+       u32 status = host->data_status;
        int output=SDM_SUCCESS;
 
        xbwprintk(7, "%s..%d...  cmd=%d, host->state=0x%x,\n   pendingEvent=0x%lu, completeEvents=0x%lu ====xbw=[%s]====\n\n",\
@@ -2233,12 +2261,9 @@ static void rk29_sdmmc_request_end(struct rk29_sdmmc *host, struct mmc_command *
     {
         goto exit;//It need not to wait-for-busy if the CMD-ERROR happen.
     }
-
+    host->errorstep = 0xf7;
     if(cmd->data)
-    {
-
-        status = host->data_status;
-        
+    {        
         if(host->cmdr & SDMMC_CMD_DAT_WRITE)
         {
             if(status & (SDMMC_INT_DCRC | SDMMC_INT_EBE))
@@ -2303,6 +2328,7 @@ static void rk29_sdmmc_request_end(struct rk29_sdmmc *host, struct mmc_command *
             output = rk29_sdmmc_wait_unbusy(host);
             if(SDM_SUCCESS != output)
             {
+                rk29_sdmmc_clear_fifo(host);
                 cmd->error = -ETIMEDOUT;
                 host->mrq->cmd->error = -ETIMEDOUT;
                 host->errorstep = 0x1C;
@@ -2311,17 +2337,23 @@ static void rk29_sdmmc_request_end(struct rk29_sdmmc *host, struct mmc_command *
             }
         }
     }
-
+    host->errorstep = 0xf6;
+    
     //trace error
     if(cmd->data && cmd->data->error)
-    {
+    { 
         if( (!cmd->error) && (0==cmd->retries) && (host->error_times++%RK29_ERROR_PRINTK_INTERVAL == 0))
-        {
-            printk("%s..%d......CMD=%d error!!!, arg=%x, errorTimes=%d, errorStep=0x%x ! ====xbw[%s]====\n",\
-                __FUNCTION__, __LINE__, cmd->opcode, cmd->arg, host->error_times,host->errorstep, host->dma_name);
+        {         
+            printk("%s..%d......CMD=%d error!!!(arg=0x%x,cmdretry=%d,blksize=%d, blocks=%d), \n \
+                statusReg=0x%x, ctrlReg=0x%x, nerrorTimes=%d, errorStep=0x%x ====xbw[%s]====\n",\
+                __FUNCTION__, __LINE__, cmd->opcode, cmd->arg, cmd->retries,cmd->data->blksz, cmd->data->blocks,
+                rk29_sdmmc_read(host->regs, SDMMC_STATUS),
+                rk29_sdmmc_read(host->regs, SDMMC_CTRL),
+                host->error_times,host->errorstep, host->dma_name);
         }
         cmd->error = -ENODATA;
     }
+    host->errorstep = 0xf5;
 
 exit:
 
@@ -2475,7 +2507,7 @@ static void rk29_sdmmc_start_error(struct rk29_sdmmc *host)
 {
     host->cmd->error = -EIO;
     host->mrq->cmd->error = -EIO;
-    host->cmd_status = SDMMC_INT_RTO;
+    host->cmd_status |= SDMMC_INT_RTO;
 
     del_timer_sync(&host->request_timer);
 
@@ -2516,6 +2548,7 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv)
 
                 if (!rk29_sdmmc_test_and_clear_pending(host, EVENT_CMD_COMPLETE))
                        break;
+                 host->errorstep = 0xfb;
 
                 del_timer_sync(&host->request_timer); //delete the timer for INT_COME_DONE
 
@@ -2531,9 +2564,9 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv)
                                                        __FUNCTION__, __LINE__,host->cmd->opcode,host->dma_name);
                     
                     host->complete_done = 1;
-                    break;//goto unlock;
+                    break;
                 }
-
+                host->errorstep = 0xfa;
                 if(host->cmd->error)
                 {
                     del_timer_sync(&host->DTO_timer); //delete the timer for INT_DTO
@@ -2555,7 +2588,7 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv)
                     rk29_sdmmc_set_pending(host, EVENT_DATA_COMPLETE);
                 }
 
-
+                host->errorstep = 0xf9;
                 state = STATE_DATA_BUSY;
                 /* fall through */
             }
@@ -2567,7 +2600,7 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv)
 
                 if (!rk29_sdmmc_test_and_clear_pending(host, EVENT_DATA_COMPLETE))
                        break;  
-
+                host->errorstep = 0xf8;
                 rk29_sdmmc_set_completed(host, EVENT_DATA_COMPLETE);
                 del_timer_sync(&host->DTO_timer); //delete the timer for INT_DTO
 
@@ -2581,11 +2614,11 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv)
                     if(!( (MMC_READ_SINGLE_BLOCK == host->cmd->opcode)&&( -EIO == data->error))) //deal with START_BIT_ERROR
                     {
                        host->complete_done = 2;
-                       break;//goto unlock;
+                       break;
                     }
 
                 }
-
+                host->errorstep = 0xf4;
                 xbwprintk(7, "%s..%d..  after DATA_COMPLETE, so call send_stop_cmd() ====xbw[%s]====\n", \
                                                __FUNCTION__, __LINE__, host->dma_name);
 
@@ -2593,7 +2626,7 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv)
                 state = STATE_SENDING_CMD;
                 send_stop_cmd(host);
                 #else
-                stopflag = 1; //Moidfyed by xbw at 2011-09-08
+                stopflag = 2; //Moidfyed by xbw at 2011-09-08
                 #endif
                 
                 break;
@@ -2612,7 +2645,7 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv)
                 rk29_sdmmc_request_end(host, host->cmd);
                 
                 host->complete_done = 3;
-                break;//goto unlock;
+                break;
             }
                
         }
@@ -2636,21 +2669,25 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv)
                         
        } while(pending_flag && ++host->retryfunc); //while(0);
 
-        if(1==stopflag)
+        if(0!=stopflag)
     {
+        if(host->cmd->error)
+        xbwprintk(3,"%d:  call send_stop_cmd== %d,  completedone=%d, doneflag=%d, hoststate=%x, statusReg=0x%x \n", \
+            __LINE__,stopflag, host->complete_done, host->mmc->doneflag, state, rk29_sdmmc_read(host->regs, SDMMC_STATUS));
+            
         state = STATE_SENDING_CMD;
         send_stop_cmd(host);   //Moidfyed by xbw at 2011-09-08
     }
 
        host->state = state;
-               
-unlock:          
+                
     if(0==host->complete_done)
     {
+        host->errorstep = 0xf2;
         spin_unlock_irqrestore(&host->lock, iflags);
         return;
     }
-    
+    host->errorstep = 0xf3; 
         host->state = STATE_IDLE;
         
         if(host->mrq && host->mmc->doneflag)
@@ -2671,15 +2708,15 @@ static inline void rk29_sdmmc_cmd_interrupt(struct rk29_sdmmc *host, u32 status)
 {
     u32 multi, unit;
     
-       if(!host->cmd_status) 
-               host->cmd_status = status;
-
+       host->cmd_status |= status;
+    host->errorstep = 0xfc;
     if((MMC_STOP_TRANSMISSION != host->cmd->opcode) && (host->cmdr & SDMMC_CMD_DAT_EXP))
     {
-        unit = 5*1024*1024;
+        unit = 3*1024*1024;
         multi = rk29_sdmmc_read(host->regs, SDMMC_BYTCNT)/unit;
         multi += ((rk29_sdmmc_read(host->regs, SDMMC_BYTCNT)%unit) ? 1 :0 );
         multi = (multi>0) ? multi : 1;
+        multi += (host->cmd->retries>2)?2:host->cmd->retries;
            mod_timer(&host->DTO_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_WAIT_DTO_INTERNVAL*multi));
        }
        
@@ -2721,6 +2758,8 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id)
            host->error_times = 0;
 
            #if 1
+           del_timer_sync(&host->request_timer);
+               del_timer_sync(&host->DTO_timer);
            rk29_sdmmc_dealwith_timeout(host);              
             #endif
                            
@@ -2756,7 +2795,7 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id)
 
         xbwprintk(6, "%s..%d..  CMD%d INT_CMD_DONE  INT=0x%x   ====xbw[%s]====\n", \
                                __FUNCTION__, __LINE__, host->cmd->opcode,pending, host->dma_name);
-
+        
         rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_CMD_DONE);  //  clear interrupt
 
         rk29_sdmmc_cmd_interrupt(host, status);
@@ -2812,8 +2851,7 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id)
         rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_DTO); 
         del_timer_sync(&host->DTO_timer); //delete the timer for INT_DTO
 
-        if (!host->data_status)
-               host->data_status = status;
+       host->data_status |= status;
 
         smp_wmb();
 
@@ -2972,7 +3010,6 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
                pdata->io_init();
                
        spin_lock_init(&host->lock);
-    spin_lock_init(&host->request_lock);
     
 #ifdef RK29_SDMMC_LIST_QUEUE   
        INIT_LIST_HEAD(&host->queue);
old mode 100644 (file)
new mode 100755 (executable)
index 1f6ef4a..fd59b86
@@ -54,6 +54,7 @@
 #define SDMMC_CTRL_OD_PULLUP     RK2818_BIT(24)
 #define SDMMC_CTRL_DMA_ENABLE     RK2818_BIT(5)
 #define SDMMC_CTRL_INT_ENABLE     RK2818_BIT(4)
+#define SDMMC_CTRL_DMA_RESET      RK2818_BIT(2)
 #define SDMMC_CTRL_FIFO_RESET     RK2818_BIT(1)
 #define SDMMC_CTRL_RESET          RK2818_BIT(0)
 
 
 
 /* Status register defines (base+0x48)*/
+#define SDMMC_STAUTS_MC_BUSY   RK2818_BIT(10)
 #define SDMMC_STAUTS_DATA_BUSY RK2818_BIT(9)       //Card busy
 #define SDMMC_CMD_FSM_MASK             (0x0F << 4)     //Command FSM status mask
 #define SDMMC_CMD_FSM_IDLE      (0x00)                 //CMD FSM is IDLE