From 02b08b06e7d7d896e7e5ed005f961f98d963d2fc Mon Sep 17 00:00:00 2001 From: xbw Date: Sat, 8 Oct 2011 11:06:37 +0800 Subject: [PATCH] fix the wirte-data timeout during SDcard copy by USB --- drivers/mmc/core/core.c | 31 +++- drivers/mmc/host/rk29_sdmmc.c | 337 +++++++++++++++++++--------------- drivers/mmc/host/rk29_sdmmc.h | 2 + 3 files changed, 217 insertions(+), 153 deletions(-) mode change 100644 => 100755 drivers/mmc/host/rk29_sdmmc.h diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 519722a41b6b..20e0f52d9785 100755 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -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); diff --git a/drivers/mmc/host/rk29_sdmmc.c b/drivers/mmc/host/rk29_sdmmc.c index d2b735764cf3..46d69156d9a0 100755 --- a/drivers/mmc/host/rk29_sdmmc.c +++ b/drivers/mmc/host/rk29_sdmmc.c @@ -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); diff --git a/drivers/mmc/host/rk29_sdmmc.h b/drivers/mmc/host/rk29_sdmmc.h old mode 100644 new mode 100755 index 1f6ef4a8f89e..fd59b868ce2a --- a/drivers/mmc/host/rk29_sdmmc.h +++ b/drivers/mmc/host/rk29_sdmmc.h @@ -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) @@ -131,6 +132,7 @@ /* 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 -- 2.34.1