From cb0fc6dd74b4693d9dbd8b2910631045732277ab Mon Sep 17 00:00:00 2001 From: xbw Date: Tue, 11 Sep 2012 17:39:57 +0800 Subject: [PATCH] SDMMC: improve the process of request ,about the CMD or DTO timeout --- drivers/mmc/host/rk29_sdmmc.c | 124 ++++++++++++++++------------------ 1 file changed, 58 insertions(+), 66 deletions(-) diff --git a/drivers/mmc/host/rk29_sdmmc.c b/drivers/mmc/host/rk29_sdmmc.c index 98f182524fd5..63345836bab3 100755 --- a/drivers/mmc/host/rk29_sdmmc.c +++ b/drivers/mmc/host/rk29_sdmmc.c @@ -98,7 +98,7 @@ int debug_level = 5; #define RK29_SDMMC_WAIT_DTO_INTERNVAL 4500 //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_VERSION "Ver.4.03 The last modify date is 2012-08-21" +#define RK29_SDMMC_VERSION "Ver.4.04 The last modify date is 2012-09-05" #if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD) #define RK29_CTRL_SDMMC_ID 0 //mainly used by SDMMC @@ -116,11 +116,12 @@ int debug_level = 5; //#define RK29_SDMMC_LIST_QUEUE /* use list-queue for multi-card*/ #define RK29_SDMMC_DEFAULT_SDIO_FREQ 0 // 1--run in default frequency(50Mhz); 0---run in 25Mhz, -#ifdef CONFIG_ARCH_RK2928 -#define RK29_MAX_SDIO_FREQ 25000000 //set max-sdio-frequency 25Mhz at the present time +#if defined(CONFIG_MT6620) +#define RK29_MAX_SDIO_FREQ 45000000 //set max-sdio-frequency 45Mhz in MTK module. #else -#define RK29_MAX_SDIO_FREQ 45000000 //set max-sdio-frequency 25Mhz at the present time +#define RK29_MAX_SDIO_FREQ 25000000 //set max-sdio-frequency 25Mhz at the present time #endif + enum { EVENT_CMD_COMPLETE = 0, EVENT_DATA_COMPLETE, @@ -818,11 +819,10 @@ static int rk29_sdmmc_start_command(struct rk29_sdmmc *host, struct mmc_command host->old_cmd = cmd->opcode; host->errorstep = 0; host->pending_events = 0; - host->completed_events = 0; - host->complete_done = 0; + host->completed_events = 0; host->retryfunc = 0; host->cmd_status = 0; - + if(MMC_STOP_TRANSMISSION != cmd->opcode) { host->data_status = 0; @@ -844,13 +844,15 @@ static int rk29_sdmmc_start_command(struct rk29_sdmmc *host, struct mmc_command xbwprintk(1,"\n%s..%d..************.start cmd=%d, arg=0x%x ******** [%s]\n", \ __FUNCTION__, __LINE__, cmd->opcode, cmd->arg, host->dma_name); - host->mmc->doneflag = 1; /* wait until CIU accepts the command */ while (--tmo && (rk29_sdmmc_read(host->regs, SDMMC_CMD) & SDMMC_CMD_START)) { udelay(2);//cpu_relax(); } + + host->complete_done = 0; + host->mmc->doneflag = 1; if(!tmo) { @@ -988,7 +990,7 @@ static void rk29_sdmmc_control_host_dma(struct rk29_sdmmc *host, bool enable) static void send_stop_cmd(struct rk29_sdmmc *host) { - int ret; + int ret, i; // int timeout = 250; // unsigned int value; @@ -1012,39 +1014,18 @@ static void send_stop_cmd(struct rk29_sdmmc *host) } } -#if 0 //modifyed at 2012-08-16 - while (--timeout > 0) - { - value = rk29_sdmmc_read(host->regs, SDMMC_STATUS); - if ((value & SDMMC_STAUTS_DATA_BUSY) == 0 &&(value & SDMMC_CMD_FSM_MASK) == SDMMC_CMD_FSM_IDLE) - { - break; - } - mdelay(1); - } - - if(!timeout) - { - printk(KERN_ERR "%d... cmd=%d(arg=0x%x),blksz=%d,blocks=%d,errorStep=0x%x, host->state=%x [%s]\n",\ - __LINE__,host->cmd->opcode, host->cmd->arg, host->cmd->data->blksz, host->cmd->data->blocks,host->errorstep,host->state,host->dma_name); + i = 0; + while(++i>2) + { + ret = rk29_sdmmc_wait_unbusy(host); + if(SDM_SUCCESS == ret) + break; + + mod_timer(&host->request_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_SEND_START_TIMEOUT+2500)); + xbwprintk(7, "%d..%s: retry times=%d before send_stop_cmd [%s].\n", __LINE__, __FUNCTION__, i, host->dma_name); - //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 [%s]\n", \ - __FUNCTION__, __LINE__, host->dma_name); - } - } -#endif host->errorstep = 0xe1; mod_timer(&host->request_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_SEND_START_TIMEOUT+2500)); @@ -1962,8 +1943,8 @@ static void rk29_sdmmc_INT_CMD_DONE_timeout(unsigned long host_data) { if((0==host->cmd->retries)&&(12 != host->cmd->opcode)) { - printk(KERN_WARNING "%d... cmd=%d, INT_CMD_DONE timeout, errorStep=0x%x, host->state=%x [%s]\n",\ - __LINE__,host->cmd->opcode, host->errorstep,host->state,host->dma_name); + printk(KERN_WARNING "%d... cmd=%d(arg=0x%x), INT_CMD_DONE timeout, errorStep=0x%x, host->state=%x [%s]\n",\ + __LINE__,host->cmd->opcode, host->cmd->arg,host->errorstep,host->state,host->dma_name); } rk29_sdmmc_write(host->regs, SDMMC_RINTSTS, 0xFFFFFFFE); // clear INT,except for SDMMC_INT_CD rk29_sdmmc_dealwith_timeout(host); @@ -2034,8 +2015,8 @@ static int rk29_sdmmc_start_request(struct mmc_host *mmc ) //check data-busy if the current command has the bit13 in command register. if( cmdr & SDMMC_CMD_PRV_DAT_WAIT ) - { - if(rk29_sdmmc_read(host->regs, SDMMC_STATUS) & SDMMC_STAUTS_DATA_BUSY) + { + if(SDM_SUCCESS != rk29_sdmmc_wait_unbusy(host)) //if(rk29_sdmmc_read(host->regs, SDMMC_STATUS) & SDMMC_STAUTS_DATA_BUSY) { host->mrq = host->new_mrq;/// cmd->error = -ETIMEDOUT; @@ -2121,9 +2102,10 @@ start_request_Err: host->state = STATE_IDLE; //modifyed by xbw at 2011-08-15 - if(host->mrq && host->mmc->doneflag) + if(host->mrq && host->mmc->doneflag && host->complete_done) { host->mmc->doneflag = 0; + host->complete_done = 0; spin_unlock_irqrestore(&host->lock, iflags); mmc_request_done(host->mmc, host->mrq); @@ -2141,6 +2123,7 @@ start_request_Err: static void rk29_sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) { unsigned long iflags; + int i,ret; struct rk29_sdmmc *host = mmc_priv(mmc); spin_lock_irqsave(&host->lock, iflags); @@ -2161,6 +2144,14 @@ static void rk29_sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) } #endif + i=0; + while(++i>2) + { + ret = rk29_sdmmc_wait_unbusy(host); + if(SDM_SUCCESS == ret) + break; + } + xbwprintk(6, "\n%s..%d..New cmd=%2d(arg=0x%8x)=== cardPresent=0x%lu, state=0x%x [%s]\n", \ __FUNCTION__, __LINE__,mrq->cmd->opcode, mrq->cmd->arg,host->flags,host->state, host->dma_name); @@ -2904,17 +2895,13 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv) { del_timer_sync(&host->DTO_timer); //delete the timer for INT_DTO - if(data->stop) + if((data->stop) && (MMC_STOP_TRANSMISSION != host->cmd->opcode)) { xbwprintk(7, "%s..%d.. cmderr, so call send_stop_cmd() [%s]\n", \ __FUNCTION__, __LINE__, host->dma_name); - #if 0 - state = STATE_SENDING_CMD;//STATE_SENDING_STOP; - send_stop_cmd(host); - #else stopflag = 1; //Moidfyed by xbw at 2011-09-08 - #endif + break; } @@ -2937,7 +2924,7 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv) rk29_sdmmc_set_completed(host, EVENT_DATA_COMPLETE); #if SDMMC_USE_INT_UNBUSY - if((24==host->cmd->opcode)||(25==host->cmd->opcode)) + if((MMC_WRITE_BLOCK==host->cmd->opcode)||(MMC_WRITE_MULTIPLE_BLOCK==host->cmd->opcode)) { /* ** use DTO_timer for waiting for INT_UNBUSY. @@ -2960,7 +2947,7 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv) case STATE_DATA_UNBUSY: { #if SDMMC_USE_INT_UNBUSY - if((24==host->cmd->opcode)||(25==host->cmd->opcode)) + if((MMC_WRITE_BLOCK==host->cmd->opcode)||(MMC_WRITE_MULTIPLE_BLOCK==host->cmd->opcode)) { if (!rk29_sdmmc_test_and_clear_pending(host, EVENT_DATA_UNBUSY)) break; @@ -2988,12 +2975,7 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv) xbwprintk(7, "%s..%d.. after DATA_COMPLETE, so call send_stop_cmd() [%s]\n", \ __FUNCTION__, __LINE__, host->dma_name); - #if 0 - state = STATE_SENDING_CMD; - send_stop_cmd(host); - #else stopflag = 2; //Moidfyed by xbw at 2011-09-08 - #endif break; } @@ -3021,7 +3003,8 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv) } pending_flag = (host->complete_done > 0) && (host->retryfunc<50) \ - && (rk29_sdmmc_test_pending(host, EVENT_CMD_COMPLETE)|| rk29_sdmmc_test_pending(host, EVENT_DATA_COMPLETE) ); + && (rk29_sdmmc_test_pending(host, EVENT_CMD_COMPLETE)|| rk29_sdmmc_test_pending(host, EVENT_DATA_COMPLETE) ) \ + && test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags); if(pending_flag) { @@ -3040,20 +3023,28 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv) } while(pending_flag && ++host->retryfunc); //while(0); - if(0!=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)); - host->errorstep = 0xe0; - state = STATE_SENDING_CMD; - send_stop_cmd(host); //Moidfyed by xbw at 2011-09-08 + host->errorstep = 0xe0; + + if(test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags)) + { + state = STATE_SENDING_CMD; + send_stop_cmd(host); //Moidfyed by xbw at 2011-09-08 + } + else + { + host->complete_done = 5; + } } host->state = state; - if(0==host->complete_done) + if((0==host->complete_done)&& host->mmc->doneflag && test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags)) { host->errorstep = 0xf2; @@ -3074,9 +3065,10 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv) host->errorstep = 0xf3; host->state = STATE_IDLE; - if(host->mrq && host->mmc->doneflag) + if(host->mrq && host->mmc->doneflag && host->complete_done) { host->mmc->doneflag = 0; + host->complete_done = 0; spin_unlock(&host->lock);//spin_unlock_irqrestore(&host->lock, iflags); rk29_sdmmc_enable_irq(host, true); mmc_request_done(host->mmc, host->mrq); @@ -3599,7 +3591,7 @@ static int rk29_sdmmc_probe(struct platform_device *pdev) host->write_protect = pdata->write_prt; #endif -#if 0 +#if defined(CONFIG_ARCH_RK29) if(RK29_CTRL_SDMMC_ID == host->pdev->id) { rk29_sdmmc_hw_init(host); -- 2.34.1