From: xbw Date: Sat, 31 Mar 2012 08:49:10 +0000 (+0800) Subject: mmc: add the timeout-timer for waiting for SDMMC_INT_UNBUSY X-Git-Tag: firefly_0821_release~9529 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=149f9645ec1f8458091513d2d1c7a41b990fbbd7;p=firefly-linux-kernel-4.4.55.git mmc: add the timeout-timer for waiting for SDMMC_INT_UNBUSY --- diff --git a/drivers/mmc/host/rk29_sdmmc.c b/drivers/mmc/host/rk29_sdmmc.c index 44c946ec0bb2..b61c3516aba7 100755 --- a/drivers/mmc/host/rk29_sdmmc.c +++ b/drivers/mmc/host/rk29_sdmmc.c @@ -84,7 +84,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.3.04 The last modify date is 2012-03-29,modifyed by XBW." +#define RK29_SDMMC_VERSION "Ver.3.05 The last modify date is 2012-03-31,modifyed by XBW." #if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD) #define RK29_CTRL_SDMMC_ID 0 //mainly used by SDMMC @@ -161,7 +161,6 @@ typedef struct TagSDC_INT_INFO struct rk29_sdmmc { spinlock_t lock; - spinlock_t irqlock; void __iomem *regs; struct clk *clk; @@ -1093,7 +1092,6 @@ static int rk29_sdmmc_submit_data_dma(struct rk29_sdmmc *host, struct mmc_data * static int rk29_sdmmc_prepare_write_data(struct rk29_sdmmc *host, struct mmc_data *data) { - //uint32 value; int output; u32 i = 0; u32 dataLen; @@ -1785,24 +1783,7 @@ static void rk29_sdmmc_dealwith_timeout(struct rk29_sdmmc *host) switch(host->state) { case STATE_IDLE: - { - #if 1 - break; - #else - if(!host->cmd) - break; - - host->cmd->error = -EIO; - - if(host->cmd->data) - { - host->cmd->data->error = -EILSEQ; - } - host->state = STATE_SENDING_CMD; - /* fall through */ - #endif - } - + break; case STATE_SENDING_CMD: host->cmd_status |= SDMMC_INT_RTO; host->cmd->error = -ETIME; @@ -1833,6 +1814,10 @@ static void rk29_sdmmc_dealwith_timeout(struct rk29_sdmmc *host) rk29_sdmmc_set_pending(host, EVENT_CMD_COMPLETE); tasklet_schedule(&host->tasklet); break; + case STATE_DATA_END: + break; + default: + break; } } @@ -1840,7 +1825,6 @@ static void rk29_sdmmc_dealwith_timeout(struct rk29_sdmmc *host) static void rk29_sdmmc_INT_CMD_DONE_timeout(unsigned long host_data) { struct rk29_sdmmc *host = (struct rk29_sdmmc *) host_data; - unsigned long iflags; spin_lock(&host->lock); @@ -1862,11 +1846,14 @@ static void rk29_sdmmc_INT_CMD_DONE_timeout(unsigned long host_data) static void rk29_sdmmc_INT_DTO_timeout(unsigned long host_data) { struct rk29_sdmmc *host = (struct rk29_sdmmc *) host_data; - unsigned long iflags; spin_lock(&host->lock); - if( (host->cmdr & SDMMC_CMD_DAT_EXP) && (STATE_DATA_BUSY == host->state)) +#if SDMMC_USE_INT_UNBUSY + if( (host->cmdr & SDMMC_CMD_DAT_EXP) &&((STATE_DATA_BUSY == host->state)||(STATE_DATA_UNBUSY == host->state) )) +#else + if( (host->cmdr & SDMMC_CMD_DAT_EXP) && (STATE_DATA_BUSY == host->state)) +#endif { if(0==host->cmd->retries) { @@ -1892,7 +1879,6 @@ static int rk29_sdmmc_start_request(struct mmc_host *mmc ) u32 cmdr, ret; unsigned long iflags; - //spin_lock(&host->lock);// spin_lock_irqsave(&host->lock, iflags); mrq = host->new_mrq; @@ -1991,7 +1977,6 @@ static int rk29_sdmmc_start_request(struct mmc_host *mmc ) __FUNCTION__, __LINE__, host->cmd->opcode,ret, \ host->state,host->cmd_status, host->pending_events,host->completed_events,host->dma_name); - //spin_unlock(&host->lock);// spin_unlock_irqrestore(&host->lock, iflags); return SDM_SUCCESS; @@ -2010,16 +1995,13 @@ start_request_Err: if(host->mrq && host->mmc->doneflag) { host->mmc->doneflag = 0; - //spin_unlock(&host->lock);// spin_unlock_irqrestore(&host->lock, iflags); mmc_request_done(host->mmc, host->mrq); } else { - //spin_unlock(&host->lock);// - spin_unlock_irqrestore(&host->lock, iflags); - + spin_unlock_irqrestore(&host->lock, iflags); } return ret; @@ -2170,10 +2152,9 @@ static void rk29_sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { int timeout = 250; unsigned int value; - unsigned long iflags; struct rk29_sdmmc *host = mmc_priv(mmc); - spin_lock(&host->lock);//spin_lock_irqsave(&host->lock, iflags); + spin_lock(&host->lock); if(test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags) || (RK29_CTRL_SDMMC_ID == host->pdev->id)) { @@ -2281,7 +2262,7 @@ static void rk29_sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } out: - spin_unlock(&host->lock);//spin_unlock_irqrestore(&host->lock, iflags); + spin_unlock(&host->lock); } @@ -2695,24 +2676,8 @@ static void rk29_sdmmc_start_error(struct rk29_sdmmc *host) rk29_sdmmc_command_complete(host, host->mrq->cmd); rk29_sdmmc_request_end(host, host->mrq->cmd); - -} -static void rk29_sdmmc_enable_irq(struct rk29_sdmmc *host, bool enable) -{ - unsigned long iflags; - spin_lock_irqsave(&host->irqlock, iflags); - if(enable) - { - enable_irq(host->irq); - } - else - { - disable_irq(host->irq); - } - spin_unlock_irqrestore(&host->irqlock, iflags); } - static void rk29_sdmmc_tasklet_func(unsigned long priv) { struct rk29_sdmmc *host = (struct rk29_sdmmc *)priv; @@ -2720,10 +2685,7 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv) enum rk29_sdmmc_state state = host->state; int pending_flag, stopflag; unsigned long iflags; - - //rk29_sdmmc_enable_irq(host, 0); - //disable_irq(host->irq); - //spin_lock(&host->lock);// + spin_lock_irqsave(&host->lock, iflags); state = host->state; @@ -2802,22 +2764,38 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv) break; host->errorstep = 0xf8; rk29_sdmmc_set_completed(host, EVENT_DATA_COMPLETE); - del_timer_sync(&host->DTO_timer); //delete the timer for INT_DTO - #if SDMMC_USE_INT_UNBUSY + #if SDMMC_USE_INT_UNBUSY + if((24==host->cmd->opcode)||(25==host->cmd->opcode)) + { + /* + ** use DTO_timer for waiting for INT_UNBUSY. + ** max 250ms in specification, but adapt 500 for the compatibility of all kinds of sick sdcard. + */ + mod_timer(&host->DTO_timer, jiffies + msecs_to_jiffies(250)); + } + else + { + del_timer_sync(&host->DTO_timer); //delete the timer for INT_DTO + } + state = STATE_DATA_UNBUSY; - #endif + + #else + del_timer_sync(&host->DTO_timer); //delete the timer for INT_DTO + #endif } case STATE_DATA_UNBUSY: { #if SDMMC_USE_INT_UNBUSY if((24==host->cmd->opcode)||(25==host->cmd->opcode)) - { // printk("%d: ******************1111111111, hoststate=%x*******************\n", __LINE__, state); + { if (!rk29_sdmmc_test_and_clear_pending(host, EVENT_DATA_UNBUSY)) - break; + break; + + del_timer_sync(&host->DTO_timer); } - // printk("%d: ******************222222222*******************\n", __LINE__); rk29_sdmmc_set_completed(host, EVENT_DATA_UNBUSY); state = STATE_DATA_END; #endif @@ -2864,12 +2842,16 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv) host->complete_done = 3; break; } - + + case STATE_DATA_END: + break; + default: + break; } 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) ); -// pending_flag=0; + if(pending_flag) { xbwprintk(7, "%s..%d... cmd=%d(arg=0x%x),completedone=%d, retrycount=%d, doneflag=%d, \n \ @@ -2886,7 +2868,6 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv) } } while(pending_flag && ++host->retryfunc); //while(0); - // printk("%d: ******************333333333*******************\n", __LINE__); if(0!=stopflag) { @@ -2904,11 +2885,7 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv) { host->errorstep = 0xf2; - // printk("%d: ******************44444444444, hoststat=%x*******************\n", __LINE__, host->state); spin_unlock_irqrestore(&host->lock, iflags); - - - //enable_irq(host->irq); return; } host->errorstep = 0xf3; @@ -2917,22 +2894,12 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv) if(host->mrq && host->mmc->doneflag) { host->mmc->doneflag = 0; - - //rk29_sdmmc_enable_irq(host, 1); - //enable_irq(host->irq); - //spin_unlock(&host->lock);// - spin_unlock_irqrestore(&host->lock, iflags); - + spin_unlock_irqrestore(&host->lock, iflags); mmc_request_done(host->mmc, host->mrq); } else { - - //rk29_sdmmc_enable_irq(host, 1); - //enable_irq(host->irq); - //spin_unlock(&host->lock); - spin_unlock_irqrestore(&host->lock, iflags); - + spin_unlock_irqrestore(&host->lock, iflags); } } @@ -2965,9 +2932,8 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id) bool present; bool present_old; int sdio_irq=0; - //unsigned long iflags; - spin_lock(&host->lock);//spin_lock_irqsave(&host->lock, iflags); + spin_lock(&host->lock); status = rk29_sdmmc_read(host->regs, SDMMC_RINTSTS); pending = rk29_sdmmc_read(host->regs, SDMMC_MINTSTS);// read only mask reg @@ -3064,9 +3030,8 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id) if(!(pending & SDMMC_INT_CMD_DONE)) { - //disable_irq_nosync(host->irq); tasklet_schedule(&host->tasklet); - } + } goto Exit_INT; } @@ -3109,27 +3074,6 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id) goto Exit_INT; } -#if SDMMC_USE_INT_UNBUSY - if(pending & SDMMC_INT_UNBUSY) - { - xbwprintk(1, "%d..%s: INT=0x%x ,RINTSTS=0x%x, CMD%d(arg=0x%x, retries=%d),host->state=0x%x ==xbw[%s]==\n *********\n", \ - __LINE__,__FUNCTION__, pending,status, host->cmd->opcode, host->cmd->arg, host->cmd->retries, host->state,host->dma_name); - - rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_UNBUSY); - - if(!((pending & SDMMC_INT_TXDR)||(pending & SDMMC_INT_RXDR)) ) - { - host->data_status = status; - smp_wmb(); - // printk("%d: ******************000000000000*******************\n", __LINE__); - rk29_sdmmc_set_pending(host, EVENT_DATA_UNBUSY); - tasklet_schedule(&host->tasklet); - } - - goto Exit_INT; - } -#endif - if (pending & SDMMC_INT_RXDR) { xbwprintk(6, "%s..%d.. SDMMC_INT_RXDR INT=0x%x ====xbw[%s]====\n", \ @@ -3143,15 +3087,32 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id) { xbwprintk(6, "%s..%d.. SDMMC_INT_TXDR INT=0x%x ====xbw[%s]====\n", \ __FUNCTION__, __LINE__, pending, host->dma_name); - - rk29_sdmmc_do_pio_write(host); - + rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_TXDR); // clear interrupt + rk29_sdmmc_do_pio_write(host); } +#if SDMMC_USE_INT_UNBUSY + if(pending & SDMMC_INT_UNBUSY) + { + xbwprintk(1, "%d..%s: INT=0x%x ,RINTSTS=0x%x, CMD%d(arg=0x%x, retries=%d),host->state=0x%x ==xbw[%s]==\n", \ + __LINE__,__FUNCTION__, pending,status, host->cmd->opcode, host->cmd->arg, host->cmd->retries, \ + host->state,host->dma_name); + + rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_UNBUSY); + + host->data_status = status; + smp_wmb(); + rk29_sdmmc_set_pending(host, EVENT_DATA_UNBUSY); + tasklet_schedule(&host->tasklet); + + goto Exit_INT; + } +#endif + Exit_INT: - spin_unlock(&host->lock);//spin_unlock_irqrestore(&host->lock, iflags); + spin_unlock(&host->lock); if(1 == sdio_irq) { @@ -3279,7 +3240,6 @@ static int rk29_sdmmc_probe(struct platform_device *pdev) pdata->io_init(); spin_lock_init(&host->lock); - spin_lock_init(&host->irqlock); #ifdef RK29_SDMMC_LIST_QUEUE INIT_LIST_HEAD(&host->queue);