Merge remote-tracking branch 'origin/develop-3.0-rk30' into develop-3.0
[firefly-linux-kernel-4.4.55.git] / drivers / mmc / host / rk29_sdmmc.c
index 3301c03f52fe6c0453cfa80b37f7f0c2a91527a6..625973bcce534cd52ee2cb6f1799a6a2a7175868 100755 (executable)
 #include <linux/mmc/card.h>
 
 #include <mach/board.h>
-#include <mach/rk29_iomap.h>
+#include <mach/io.h>
 #include <mach/gpio.h>
 #include <mach/iomux.h>
 
 #include <asm/dma.h>
-#include <mach/rk29-dma-pl330.h>
+#include <mach/dma-pl330.h>
 #include <asm/scatterlist.h>
 
 #include "rk29_sdmmc.h"
@@ -54,7 +54,7 @@
 #define RK29_SDMMC_xbw_Debug 0
 
 #if RK29_SDMMC_xbw_Debug 
-int debug_level = 7;
+int debug_level = 5;
 #define xbwprintk(n, format, arg...) \
        if (n <= debug_level) {  \
                printk(format,##arg); \
@@ -63,23 +63,35 @@ int debug_level = 7;
 #define xbwprintk(n, arg...)
 #endif
 
-#define RK29_SDMMC_ERROR_FLAGS         (SDMMC_INT_FRUN | SDMMC_INT_RTO | SDMMC_INT_HLE )
+#define RK29_SDMMC_ERROR_FLAGS         (SDMMC_INT_FRUN | SDMMC_INT_HLE )
 
+#if defined(CONFIG_ARCH_RK29) 
 #define RK29_SDMMC_INTMASK_USEDMA   (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_CD)
 #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 )
 
+#elif defined(CONFIG_ARCH_RK30)
+#define RK29_SDMMC_INTMASK_USEDMA   (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | SDMMC_INT_UNBUSY |RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_CD)
+#define RK29_SDMMC_INTMASK_USEIO    (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | SDMMC_INT_UNBUSY |RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_CD| SDMMC_INT_TXDR | SDMMC_INT_RXDR )
+#endif
 
-#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   3000  //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_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.2.01 The last modify date is 2011-08-19,modifyed by XBW." 
+#define RK29_SDMMC_VERSION "Ver.3.03 The last modify date is 2012-03-23,modifyed by XBW."
 
+#if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD) 
 #define RK29_CTRL_SDMMC_ID   0  //mainly used by SDMMC
 #define RK29_CTRL_SDIO1_ID   1  //mainly used by sdio-wifi
 #define RK29_CTRL_SDIO2_ID   2  //mainly used by sdio-card
+#else
+#define RK29_CTRL_SDMMC_ID   5  
+#define RK29_CTRL_SDIO1_ID   1  
+#define RK29_CTRL_SDIO2_ID   2  
+#endif
 
+#define SDMMC_CLOCK_TEST     0
 #define RK29_SDMMC_NOTIFY_REMOVE_INSERTION /* use sysfs to notify the removal or insertion of sd-card*/
 //#define RK29_SDMMC_LIST_QUEUE            /* use list-queue for multi-card*/
 
@@ -140,7 +152,6 @@ typedef struct TagSDC_INT_INFO
 
 struct rk29_sdmmc {
        spinlock_t              lock;
-       spinlock_t              request_lock;
        void __iomem    *regs;
        struct clk              *clk;
 
@@ -198,10 +209,19 @@ struct rk29_sdmmc {
 
     unsigned int            oldstatus;
     unsigned int            complete_done;
+    unsigned int            retryfunc;
+    
 #ifdef CONFIG_PM
     int gpio_irq;
        int gpio_det;
 #endif
+
+#if defined(CONFIG_SDMMC0_RK29_WRITE_PROTECT) || defined(CONFIG_SDMMC1_RK29_WRITE_PROTECT)
+    int write_protect;
+#endif
+
+    void (*set_iomux)(int device_id, unsigned int bus_width);
+
 };
 
 
@@ -211,6 +231,8 @@ static struct rk29_sdmmc    *globalSDhost[3];
 
 #define rk29_sdmmc_test_and_clear_pending(host, event)         \
        test_and_clear_bit(event, &host->pending_events)
+#define rk29_sdmmc_test_pending(host, event)           \
+       test_bit(event, &host->pending_events)
 #define rk29_sdmmc_set_completed(host, event)                  \
        set_bit(event, &host->completed_events)
 
@@ -218,6 +240,8 @@ 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);
+int rk29_sdmmc_hw_init(void *data);
 
 static void rk29_sdmmc_write(unsigned char  __iomem    *regbase, unsigned int regOff,unsigned int val)
 {
@@ -271,20 +295,18 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a
     
     if( !strncmp(buf,"version" , strlen("version")))
     {
-        printk("The driver SDMMC named 'rk29_sdmmc.c' is %s. ====xbw====\n", RK29_SDMMC_VERSION);
+        printk("\n The driver SDMMC named 'rk29_sdmmc.c' is %s. ==xbw==\n", RK29_SDMMC_VERSION);
         return count;
     }
     
-    spin_lock(&host->lock);
-    
     //envalue the address of host base on input-parameter.
     if( !strncmp(buf,"sd-" , strlen("sd-")) )
     {
-        host = (struct rk29_sdmmc      *)globalSDhost[RK29_CTRL_SDMMC_ID];
+        host = (struct rk29_sdmmc      *)globalSDhost[0];
         if(!host)
         {
             printk("%s..%d.. fail to call progress_store because the host is null. ==xbw==\n",__FUNCTION__,__LINE__);
-            goto progress_store_out;
+            return count;
         }
     }    
     else if(  !strncmp(buf,"sdio1-" , strlen("sdio1-")) )
@@ -293,7 +315,7 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a
         if(!host)
         {
             printk("%s..%d.. fail to call progress_store because the host-sdio1 is null. ==xbw==\n",__FUNCTION__,__LINE__);
-            goto progress_store_out;
+            return count;
         }
     }
     else if(  !strncmp(buf,"sdio2-" , strlen("sdio2-")) )
@@ -302,15 +324,17 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a
         if(!host)
         {
             printk("%s..%d.. fail to call progress_store because the host-sdio2 is null. ==xbw==\n",__FUNCTION__,__LINE__);
-            goto progress_store_out;
+            return count;
         }
     }
     else
     {
         printk("%s..%d.. You want to use sysfs for SDMMC but input-parameter is wrong.====xbw====\n",__FUNCTION__,__LINE__);
-        goto progress_store_out;//return count;
+        return count;
     }
 
+    spin_lock(&host->lock);
+
     if(strncmp(buf,oldbuf , strlen(buf)))
     {
            printk(".%d.. MMC0 receive the message %s from VOLD.====xbw[%s]====\n", __LINE__, buf, host->dma_name);
@@ -322,8 +346,10 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a
      *  insert card state-change:  No-Media ==> Pending ==> Idle-Unmounted ==> Checking ==>Mounted
      *  remove card state-change:  Unmounting ==> Idle-Unmounted ==> No-Media
     */
+    #if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD)
     if(RK29_CTRL_SDMMC_ID == host->pdev->id)
     {
+#if 1 //to wirte log in log-file-system during the stage of umount. Modifyed by xbw at 2011-12-26
         if(!strncmp(buf, "sd-Unmounting", strlen("sd-Unmounting")))
         {
             if(unmounting_times++%10 == 0)
@@ -331,9 +357,27 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a
                 printk(".%d.. MMC0 receive the message Unmounting(waitTimes=%d) from VOLD.====xbw[%s]====\n", \
                     __LINE__, unmounting_times, host->dma_name);
             }
-            host->mmc->re_initialized_flags = 0;
-            mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_REMOVAL_DELAY));
+
+            if(0 == host->mmc->re_initialized_flags)
+                mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_REMOVAL_DELAY*2));
         }
+        else if(!strncmp(buf, "sd-Idle-Unmounted", strlen("sd-Idle-Unmounted")))
+        {
+            if(0 == host->mmc->re_initialized_flags)
+                mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_REMOVAL_DELAY*2));
+        }
+#else
+        if(!strncmp(buf, "sd-Unmounting", strlen("sd-Unmounting")))
+        {
+            if(unmounting_times++%10 == 0)
+            {
+                printk(".%d.. MMC0 receive the message Unmounting(waitTimes=%d) from VOLD.====xbw[%s]====\n", \
+                    __LINE__, unmounting_times, host->dma_name);
+            }
+            host->mmc->re_initialized_flags = 0;
+            mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_REMOVAL_DELAY*2));
+        } 
+#endif
         else if( !strncmp(buf, "sd-No-Media", strlen("sd-No-Media")))
         {
             printk(".%d.. MMC0 receive the message No-Media from VOLD. waitTimes=%d ====xbw[%s]====\n" ,\
@@ -359,6 +403,7 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a
         else if( !strncmp(buf,"sd-reset" , strlen("sd-reset")) ) 
         {
             printk(".%d.. Now manual reset for SDMMC0. ====xbw[%s]====\n",__LINE__, host->dma_name);
+            rk29_sdmmc_hw_init(host);
             mmc_detect_change(host->mmc, 0);           
         }
         else if( !strncmp(buf, "sd-regs", strlen("sd-regs")))
@@ -368,6 +413,22 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a
         }
 
     }
+    #else
+    if(0 == host->pdev->id)
+    {
+        if( !strncmp(buf,"sd-reset" , strlen("sd-reset")) ) 
+        {
+            printk(".%d.. Now manual reset for SDMMC0. ====xbw[%s]====\n",__LINE__, host->dma_name);
+            rk29_sdmmc_hw_init(host);
+            mmc_detect_change(host->mmc, 0);           
+        }
+        else if( !strncmp(buf, "sd-regs", strlen("sd-regs")))
+        {
+            printk(".%d.. Now printk the register of SDMMC0. ====xbw[%s]====\n",__LINE__, host->dma_name); 
+            rk29_sdmmc_regs_printk(host);
+        }
+    }
+    #endif
     else if(RK29_CTRL_SDIO1_ID == host->pdev->id)
     {
         if( !strncmp(buf, "sdio1-regs", strlen("sdio1-regs")))
@@ -378,6 +439,7 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a
         else if( !strncmp(buf,"sdio1-reset" , strlen("sdio1-reset")) ) 
         {
             printk(".%d.. Now manual reset for SDMMC1. ====xbw[%s]====\n",__LINE__, host->dma_name);
+            rk29_sdmmc_hw_init(host);
             mmc_detect_change(host->mmc, 0);           
         }
     }
@@ -391,11 +453,11 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a
         else if( !strncmp(buf,"sdio2-reset" , strlen("sdio2-reset")) ) 
         {
             printk(".%d.. Now manual reset for SDMMC2. ====xbw[%s]====\n",__LINE__, host->dma_name);
+            rk29_sdmmc_hw_init(host);
             mmc_detect_change(host->mmc, 0);           
         }
     }
     
-progress_store_out:
     spin_unlock(&host->lock);
     
     return count;
@@ -407,7 +469,7 @@ struct kobj_attribute mmc_reset_attrs =
 {
         .attr = {
                 .name = "rescan",
-                .mode = 0777},
+                .mode = 0764},
         .show = NULL,
         .store = rk29_sdmmc_progress_store,
 };
@@ -643,14 +705,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*10;//wait 60ms cycle.
        
        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
 
@@ -658,6 +786,8 @@ static int rk29_sdmmc_start_command(struct rk29_sdmmc *host, struct mmc_command
     xbwprintk(5, "\n%s..%d..************.start cmd=%d, arg=0x%x ********=====xbw[%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))
        {
@@ -679,7 +809,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;
 }
 
@@ -715,9 +846,9 @@ static int rk29_sdmmc_reset_fifo(struct rk29_sdmmc *host)
 
 static int rk29_sdmmc_wait_unbusy(struct rk29_sdmmc *host)
 {
-       int time_out = 250000; //max is 250ms
+       int time_out = 500000;//250000; //max is 250ms; //adapt the value to the sick card.  modify at 2011-10-08
 
-       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--;
@@ -732,22 +863,6 @@ static int rk29_sdmmc_wait_unbusy(struct rk29_sdmmc *host)
        return SDM_SUCCESS;
 }
 
-static void send_stop_cmd(struct rk29_sdmmc *host)
-{
-    mod_timer(&host->request_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_SEND_START_TIMEOUT+250));
-               
-    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;
-    
-    host->cmdr = rk29_sdmmc_prepare_command(&host->stopcmd);
-    rk29_sdmmc_start_command(host, &host->stopcmd, host->cmdr);    
-}
-
 static void rk29_sdmmc_dma_cleanup(struct rk29_sdmmc *host)
 {
        if (host->data) 
@@ -809,6 +924,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) 
@@ -949,14 +1113,14 @@ static int rk29_sdmmc_prepare_write_data(struct rk29_sdmmc *host, struct mmc_dat
         } 
         else 
         {
-            xbwprintk(3, "%s..%d...   trace data,   ======xbw=[%s]====\n", __FUNCTION__, __LINE__,  host->dma_name);
+            xbwprintk(7, "%s..%d...   trace data,   ======xbw=[%s]====\n", __FUNCTION__, __LINE__,  host->dma_name);
             output = rk29_sdmmc_submit_data_dma(host, data);
             if(output)
             {
                        host->dodma = 0;
                                
-                   printk("%s..%d... CMD%d setupDMA failure!!!!!  ==xbw[%s]==\n", \
-                                               __FUNCTION__, __LINE__, host->cmd->opcode, host->dma_name);
+                   printk("%s..%d... CMD%d setupDMA failure!!!!! pre_cmd=%d  ==xbw[%s]==\n", \
+                                               __FUNCTION__, __LINE__, host->cmd->opcode,host->old_cmd, host->dma_name);
                    
                                host->errorstep = 0x81;
 
@@ -1134,6 +1298,7 @@ static void rk29_sdmmc_submit_data(struct rk29_sdmmc *host, struct mmc_data *dat
     {
         host->data = data;
         data->error = 0;
+        host->cmd->data = data;
 
         data->bytes_xfered = 0;
         host->pbuf = (u32*)sg_virt(data->sg);
@@ -1151,13 +1316,13 @@ 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...   trace data,  CMD%d, data->blksz=%d, data->blocks=%d   ======xbw=[%s]====\n", \
-            __FUNCTION__, __LINE__, host->cmd->opcode,data->blksz, data->blocks,  host->dma_name);
+        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)
                {
                    host->cmdr |= (SDMMC_CMD_DAT_WRITE | SDMMC_CMD_DAT_EXP);
-            xbwprintk(3, "%s..%d...   write data, len=%d     ======xbw=[%s]====\n", \
+            xbwprintk(7, "%s..%d...   write data, len=%d     ======xbw=[%s]====\n", \
                                        __FUNCTION__, __LINE__, data->blksz*data->blocks, host->dma_name);
                    
                        ret = rk29_sdmmc_prepare_write_data(host, data);
@@ -1165,7 +1330,7 @@ static void rk29_sdmmc_submit_data(struct rk29_sdmmc *host, struct mmc_data *dat
            else
            {
                host->cmdr |= (SDMMC_CMD_DAT_READ | SDMMC_CMD_DAT_EXP);
-            xbwprintk(3, "%s..%d...   read data  len=%d   ======xbw=[%s]====\n", \
+            xbwprintk(7, "%s..%d...   read data  len=%d   ======xbw=[%s]====\n", \
                                        __FUNCTION__, __LINE__, data->blksz*data->blocks, host->dma_name);
                
                        ret = rk29_sdmmc_prepare_read_data(host, data);
@@ -1182,12 +1347,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*10;//wait 60ms cycle.
        
        rk29_sdmmc_write(host->regs, SDMMC_CMD, SDMMC_CMD_START | cmd);         
-       while (--tmo && readl(host->regs + SDMMC_CMD) & SDMMC_CMD_START)
+       while (--tmo && (rk29_sdmmc_read(host->regs, SDMMC_CMD) & SDMMC_CMD_START))
        {
-           cpu_relax();
+           udelay(2);
        }
        
        if(!tmo) 
@@ -1205,16 +1370,41 @@ static int sdmmc_send_cmd_start(struct rk29_sdmmc *host, unsigned int cmd)
 static int rk29_sdmmc_get_cd(struct mmc_host *mmc)
 {
        struct rk29_sdmmc *host = mmc_priv(mmc);
-       u32 cdetect;
+       u32 cdetect=1;
 
-#ifdef CONFIG_PM
-       if(host->gpio_det == INVALID_GPIO)
-               return 1;
-#endif
+    switch(host->pdev->id)
+    {
+        case 0:
+        {
+            #ifdef CONFIG_PM
+               if(host->gpio_det == INVALID_GPIO)
+                       return 1;
+            #endif
+
+               cdetect = rk29_sdmmc_read(host->regs, SDMMC_CDETECT);
+
+            cdetect = (cdetect & SDMMC_CARD_DETECT_N)?0:1;
+
+            break;
+        }        
 
-       cdetect = rk29_sdmmc_read(host->regs, SDMMC_CDETECT);
+        case 1:
+        {
+            #if defined(CONFIG_USE_SDMMC1_FOR_WIFI_DEVELOP_BOARD)
+            cdetect = 1;
+            #else
+            cdetect = test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags)?1:0;
+            #endif
+            break;
+        }
+        
+        default:
+            cdetect = 1;
+            break;
+    
+       }
 
-       return (cdetect & SDMMC_CARD_DETECT_N)?0:1;
+        return cdetect;
 }
 
 
@@ -1241,8 +1431,11 @@ int rk29_sdmmc_reset_controller(struct rk29_sdmmc *host)
     }
    
     /* reset */
+#if defined(CONFIG_ARCH_RK29)     
     rk29_sdmmc_write(host->regs, SDMMC_CTRL,(SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET ));
-
+#elif defined(CONFIG_ARCH_RK30)
+    rk29_sdmmc_write(host->regs, SDMMC_CTRL,(SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET));
+#endif
     timeOut = 1000;
     value = rk29_sdmmc_read(host->regs, SDMMC_CTRL);
     while (( value & (SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_RESET)) && (timeOut > 0))
@@ -1290,7 +1483,26 @@ int rk29_sdmmc_reset_controller(struct rk29_sdmmc *host)
                }
                else
                {
-                   rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEDMA | SDMMC_INT_SDIO);
+                   if(0== host->pdev->id)
+                   {
+                   #if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD)
+                   rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEDMA | SDMMC_INT_SDIO);
+                   #else
+                   rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEDMA);
+                   #endif
+                   }
+                   else if(1== host->pdev->id)
+                   {
+                      #if !defined(CONFIG_USE_SDMMC1_FOR_WIFI_DEVELOP_BOARD)
+                   rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEDMA | SDMMC_INT_SDIO);
+                  #else
+                   rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEDMA);
+                  #endif 
+                   }
+                   else
+                   {
+                       rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEDMA | SDMMC_INT_SDIO);
+                   }
                }
        }
        else
@@ -1301,7 +1513,26 @@ int rk29_sdmmc_reset_controller(struct rk29_sdmmc *host)
                }
                else
                {
-                   rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEIO | SDMMC_INT_SDIO);
+                   if(0== host->pdev->id)
+                   {
+                   #if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD)
+                   rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEIO | SDMMC_INT_SDIO);
+                   #else
+                   rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEIO);
+                   #endif
+                   }
+                   else if(1== host->pdev->id)
+                   {
+                       #if !defined(CONFIG_USE_SDMMC1_FOR_WIFI_DEVELOP_BOARD)
+                   rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEIO | SDMMC_INT_SDIO);
+                   #else
+                   rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEIO);
+                   #endif
+                   }
+                   else
+                   {
+                       rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEDMA | SDMMC_INT_SDIO);
+                   }
                }               
     }
 
@@ -1326,7 +1557,7 @@ static int rk29_sdmmc_control_clock(struct rk29_sdmmc *host, bool enable)
     tmo = 1000;
        while (--tmo && (rk29_sdmmc_read(host->regs, SDMMC_CMD) & SDMMC_CMD_START))
        {
-               cpu_relax();
+               udelay(1);//cpu_relax();
        }
        if(!tmo)
        {
@@ -1338,14 +1569,28 @@ static int rk29_sdmmc_control_clock(struct rk29_sdmmc *host, bool enable)
     if(RK29_CTRL_SDMMC_ID == host->pdev->id)
     { 
         //SDMMC use low-power mode
+        #if SDMMC_CLOCK_TEST
         if (enable)
         {
-            value = (SDMMC_CLKEN_LOW_PWR | SDMMC_CLKEN_ENABLE);
+            value = (SDMMC_CLKEN_ENABLE);
         }
         else
         {
-            value = (SDMMC_CLKEN_LOW_PWR | SDMMC_CLKEN_DISABLE);
+            value = (SDMMC_CLKEN_DISABLE);
         }
+        
+        #else
+        {
+            if (enable)
+            {
+                value = (SDMMC_CLKEN_LOW_PWR | SDMMC_CLKEN_ENABLE);
+            }
+            else
+            {
+                value = (SDMMC_CLKEN_LOW_PWR | SDMMC_CLKEN_DISABLE);
+            }
+        }
+        #endif
     }
     else
     {
@@ -1372,7 +1617,7 @@ static int rk29_sdmmc_control_clock(struct rk29_sdmmc *host, bool enable)
     return SDM_SUCCESS;
 
 Error_exit:
-    printk("\n%s....%d..  control clock fail!!! Enable=%d, ret=%d ===xbw[%s]====\n",\
+    printk("\n%s....%d..  control clock fail!!! Enable=%d, ret=0x%x ===xbw[%s]====\n",\
                        __FILE__,__LINE__,enable,ret, host->dma_name);
 
     return ret;
@@ -1433,7 +1678,7 @@ int rk29_sdmmc_change_clk_div(struct rk29_sdmmc *host, u32 freqHz)
     tmo = 1000;
        while (--tmo && (rk29_sdmmc_read(host->regs, SDMMC_CMD) & SDMMC_CMD_START))
        {
-               cpu_relax();
+               udelay(1);//cpu_relax();
        }
        if(!tmo)
        {
@@ -1470,19 +1715,24 @@ int rk29_sdmmc_change_clk_div(struct rk29_sdmmc *host, u32 freqHz)
     
 SetFreq_error:
 
-    printk("%s..%s..%d..  change division fail, ret=%d  !!! ====xbw[%s]====\n",\
-        __FILE__, __FUNCTION__,__LINE__,ret, host->dma_name);
+    printk("%s..%d..  change division fail, errorStep=0x%x,ret=%d  !!! ====xbw[%s]====\n",\
+        __FILE__, __LINE__,host->errorstep,ret, host->dma_name);
         
     return ret;
     
 }
 
-
-
-static int rk29_sdmmc_hw_init(struct rk29_sdmmc *host)
+int rk29_sdmmc_hw_init(void *data)
 {
+    struct rk29_sdmmc *host = (struct rk29_sdmmc *)data;
+
+    //set the iomux
+    host->ctype = SDMMC_CTYPE_1BIT;
+    host->set_iomux(host->pdev->id, host->ctype);
+    
     /* reset controller */
     rk29_sdmmc_reset_controller(host);
+
     rk29_sdmmc_change_clk_div(host, FOD_FREQ);
     
     return SDM_SUCCESS;    
@@ -1490,23 +1740,6 @@ static int rk29_sdmmc_hw_init(struct rk29_sdmmc *host)
 
 
 
-int rk29_sdmmc_set_iomux(struct rk29_sdmmc *host)
-{
-    #if 0
-    switch (host->busWidth)
-    {
-        case 
-       rk29_mux_api_set(GPIO1D1_SDMMC0CMD_NAME, GPIO1H_SDMMC0_CMD);
-       rk29_mux_api_set(GPIO1D0_SDMMC0CLKOUT_NAME, GPIO1H_SDMMC0_CLKOUT);
-       rk29_mux_api_set(GPIO1D2_SDMMC0DATA0_NAME, GPIO1H_SDMMC0_DATA0);
-       rk29_mux_api_set(GPIO1D3_SDMMC0DATA1_NAME, GPIO1H_SDMMC0_DATA1);
-       rk29_mux_api_set(GPIO1D4_SDMMC0DATA2_NAME, GPIO1H_SDMMC0_DATA2);
-       }
-    #endif
-    
-       return 0;
-}
-
 int rk29_sdmmc_set_buswidth(struct rk29_sdmmc *host)
 {
     //int ret;
@@ -1520,7 +1753,8 @@ int rk29_sdmmc_set_buswidth(struct rk29_sdmmc *host)
         default:
             return SDM_PARAM_ERROR;
     }
-    rk29_sdmmc_set_iomux(host);
+
+    host->set_iomux(host->pdev->id, host->ctype);
 
     /* Set the current  bus width */
        rk29_sdmmc_write(host->regs, SDMMC_CTYPE, host->ctype);
@@ -1529,57 +1763,11 @@ 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)
+        return; //not to generate error flag if the command has been over.
+        
     switch(host->state)
     {
         case STATE_IDLE:
@@ -1629,6 +1817,9 @@ 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_irqsave(&host->lock, iflags);
        
        if(STATE_SENDING_CMD == host->state)
        {
@@ -1640,6 +1831,7 @@ static void rk29_sdmmc_INT_CMD_DONE_timeout(unsigned long host_data)
             
         rk29_sdmmc_dealwith_timeout(host);        
        }
+       spin_unlock_irqrestore(&host->lock, iflags);
        
 }
 
@@ -1647,6 +1839,9 @@ 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_irqsave(&host->lock, iflags);
 
 
        if( (host->cmdr & SDMMC_CMD_DAT_EXP) && (STATE_DATA_BUSY == host->state))
@@ -1659,6 +1854,8 @@ static void rk29_sdmmc_INT_DTO_timeout(unsigned long host_data)
 
            rk29_sdmmc_dealwith_timeout(host);  
        }
+       spin_unlock_irqrestore(&host->lock, iflags);
  
 }
 
@@ -1678,7 +1875,6 @@ static int rk29_sdmmc_start_request(struct mmc_host *mmc )
        mrq = host->new_mrq;
        cmd = mrq->cmd;
        cmd->error = 0;
-       host->complete_done = 0;
        
        cmdr = rk29_sdmmc_prepare_command(cmd);
        ret = SDM_SUCCESS;
@@ -1712,6 +1908,7 @@ static int rk29_sdmmc_start_request(struct mmc_host *mmc )
                 printk("%s..Error happen in CMD_PRV_DAT_WAIT. STATUS-reg=0x%x ===xbw[%s]===\n", \
                     __FUNCTION__, rk29_sdmmc_read(host->regs, SDMMC_STATUS),host->dma_name);
             }
+            rk29_sdmmc_clear_fifo(host);
             goto start_request_Err; 
         }
     }
@@ -1721,27 +1918,21 @@ static int rk29_sdmmc_start_request(struct mmc_host *mmc )
        mrq = host->mrq;
        cmd = mrq->cmd;
        cmd->error = 0;
+       cmd->data = NULL;
 
     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;
 
-    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);
@@ -1770,6 +1961,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",\
@@ -1789,9 +1981,18 @@ start_request_Err:
     }
 
     host->state = STATE_IDLE;  //modifyed by xbw  at 2011-08-15
-    spin_unlock_irqrestore(&host->lock, iflags);
     
-    mmc_request_done(host->mmc, host->mrq);
+    if(host->mrq && host->mmc->doneflag)
+    {
+        host->mmc->doneflag = 0;
+        spin_unlock_irqrestore(&host->lock, iflags);
+        
+        mmc_request_done(host->mmc, host->mrq);
+    }
+    else
+    {
+        spin_unlock_irqrestore(&host->lock, iflags);
+    }
     
     return ret; 
        
@@ -1803,8 +2004,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
@@ -1815,13 +2014,15 @@ static void rk29_sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
            printk("%s..%d..  ==== The %s had been closed by myself for the experiment. ====xbw[%s]===\n",\
                                __FUNCTION__, __LINE__, host->dma_name, host->dma_name);
 
+        host->state = STATE_IDLE;
+        rk29_sdmmc_write(host->regs, SDMMC_RINTSTS, 0xFFFFFFFF);
         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)
@@ -1854,17 +2055,18 @@ static void rk29_sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
                    }
                    else
                    {
-                       if(host->error_times++ % (RK29_ERROR_PRINTK_INTERVAL*2) ==0)
+                       if(host->error_times++ % (RK29_ERROR_PRINTK_INTERVAL*3) ==0)
                        {
                                printk("%s: Refuse to run CMD%2d(arg=0x%8x) due to the removal of card.  3==xbw[%s]==\n", \
                                    __FUNCTION__, mrq->cmd->opcode, mrq->cmd->arg, host->dma_name);
                        }
+                       host->old_cmd = mrq->cmd->opcode;
                    }       
                }
-
+            host->state = STATE_IDLE;
             spin_unlock_irqrestore(&host->lock, iflags);
                mmc_request_done(mmc, mrq);
-               goto request_ext;//return;
+               return;
        }
        else
        {
@@ -1872,26 +2074,30 @@ static void rk29_sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
                {       
                        host->old_cmd = mrq->cmd->opcode;
                                host->error_times = 0;
-                       }
+                       }                       
        }
        }
        else
        {
         host->old_cmd = mrq->cmd->opcode;
         host->error_times = 0;
+
+        if(!test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags))
+               {
+                   host->state = STATE_IDLE;
+                   mrq->cmd->error = -ENOMEDIUM;
+            spin_unlock_irqrestore(&host->lock, iflags);
+               mmc_request_done(mmc, mrq);
+               return;
+               }
+
        }
        
-       #if 1
-       if(host->state != STATE_IDLE)
-       {
-            printk("%s..%d..state Error! ,old_state=%d, OldCMD=%d ,NewCMD%2d,arg=0x%x ===xbw[%s]===\n", \
-                               __FUNCTION__, __LINE__, host->state, host->cmd->opcode,mrq->cmd->opcode,mrq->cmd->arg, host->dma_name);
-       }
-           
+       #if 1  
+    host->new_mrq = mrq;        
 
        spin_unlock_irqrestore(&host->lock, iflags);
         
-    host->new_mrq = mrq;        
     rk29_sdmmc_start_request(mmc);
        
        #else
@@ -1920,14 +2126,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);
+
 }
 
 
@@ -1941,25 +2145,28 @@ static void rk29_sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
     spin_lock_irqsave(&host->lock, iflags);
 
-    /*
-     * Waiting SDIO controller to be IDLE.
-    */
-    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 <= 0)
-       {
-               printk("%s..%d...Waiting for SDMMC%d controller to be IDLE timeout.==xbw[%s]===\n", \
-                               __FUNCTION__, __LINE__, host->pdev->id, host->dma_name);
+    if(test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags) || (RK29_CTRL_SDMMC_ID == host->pdev->id))
+    {
+        /*
+         * Waiting SDIO controller to be IDLE.
+        */
+        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 <= 0)
+       {
+               printk("%s..%d...Waiting for SDMMC%d controller to be IDLE timeout.==xbw[%s]===\n", \
+                               __FUNCTION__, __LINE__, host->pdev->id, host->dma_name);
 
-               goto out;
+               goto out;
+       }
        }
 
     //if(host->bus_mode != ios->power_mode)
@@ -2008,7 +2215,9 @@ static void rk29_sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        
        }
 
-    
+    if(!(test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags) || (RK29_CTRL_SDIO1_ID != host->pdev->id)))
+        goto out; //exit the set_ios directly if the SDIO is not present. 
+        
        if(host->ctype != ios->bus_width)
        {
        switch (ios->bus_width) 
@@ -2047,10 +2256,42 @@ out:
 
 static int rk29_sdmmc_get_ro(struct mmc_host *mmc)
 {
-       struct rk29_sdmmc *host = mmc_priv(mmc);
-       u32 wrtprt = rk29_sdmmc_read(host->regs, SDMMC_WRTPRT);
+    struct rk29_sdmmc *host = mmc_priv(mmc);
+    int ret=0;
+
+    switch(host->pdev->id)
+    {
+        case 0:
+        {
+            #if defined(CONFIG_SDMMC0_RK29_WRITE_PROTECT) || defined(CONFIG_SDMMC1_RK29_WRITE_PROTECT)            
+               if(INVALID_GPIO == host->write_protect)
+                   ret = 0;//no write-protect
+               else
+                ret = gpio_get_value(host->write_protect)?1:0;
+           
+            xbwprintk(7,"%s..%d.. write_prt_pin=%d, get_ro=%d ===xbw[%s]===\n",\
+                __FUNCTION__, __LINE__,host->write_protect, ret, host->dma_name);
+                            
+            #else
+               u32 wrtprt = rk29_sdmmc_read(host->regs, SDMMC_WRTPRT);
+               
+               ret = (wrtprt & SDMMC_WRITE_PROTECT)?1:0;
+            #endif
+
+            break;
+        }
+        
+        case 1:
+            ret = 0;//no write-protect
+            break;
+        
+        default:
+            ret = 0;
+        break;   
+    }
+
+    return ret;
 
-       return (wrtprt & SDMMC_WRITE_PROTECT)?1:0;
 }
 
 
@@ -2076,6 +2317,54 @@ 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)
+    {
+        rk29_sdmmc_write(host->regs, SDMMC_RINTSTS, 0xFFFFFFFF);
+    }
+
+    rk29_sdmmc_stop_dma(host);
+    rk29_sdmmc_control_host_dma(host, FALSE);
+    host->dodma = 0;
+   
+    //Clean the fifo.
+    for(timeout=0; timeout<FIFO_DEPTH; timeout++)
+    {
+        if(rk29_sdmmc_read(host->regs, SDMMC_STATUS) & SDMMC_STAUTS_FIFO_EMPTY)
+            break;
+            
+        value = rk29_sdmmc_read(host->regs, SDMMC_DATA);
+    }
+
+     /* reset */
+    timeout = 1000;
+    value = rk29_sdmmc_read(host->regs, SDMMC_CTRL);
+    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--;
+        value = rk29_sdmmc_read(host->regs, SDMMC_CTRL);
+    }
+
+    if (timeout == 0)
+    {
+        host->errorstep = 0x0A;
+        ret = SDM_WAIT_FOR_FIFORESET_TIMEOUT;
+    }
+
+    return ret;
+}
+
+
 
 static const struct mmc_host_ops rk29_sdmmc_ops[] = {
        {
@@ -2087,6 +2376,8 @@ static const struct mmc_host_ops rk29_sdmmc_ops[] = {
        {
                .request        = rk29_sdmmc_request,
                .set_ios        = rk29_sdmmc_set_ios,
+               .get_ro         = rk29_sdmmc_get_ro,
+               .get_cd         = rk29_sdmmc_get_cd,
                .enable_sdio_irq = rk29_sdmmc_enable_sdio_irq,
                .init_card       = rk29_sdmmc_init_card,
        },
@@ -2094,7 +2385,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",\
@@ -2119,17 +2410,14 @@ 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))
             {
-                cmd->data->error = -EILSEQ;;//mrq->data->error = -EILSEQ;                
+                cmd->data->error = -EILSEQ;               
                 output = SDM_DATA_CRC_ERROR;
                 host->errorstep = 0x16; 
             }
@@ -2187,26 +2475,34 @@ static void rk29_sdmmc_request_end(struct rk29_sdmmc *host, struct mmc_command *
         if ((mmc_resp_type(cmd) == MMC_RSP_R1B) || (MMC_STOP_TRANSMISSION == cmd->opcode))
         {
             output = rk29_sdmmc_wait_unbusy(host);
-            if(SDM_SUCCESS != output)
+            if((SDM_SUCCESS != output) && (!host->mrq->cmd->error))
             {
+                printk("%s..%d...   CMD12 wait busy timeout!!!!! errorStep=0x%x     ====xbw=[%s]====\n", \
+                                               __FUNCTION__, __LINE__, host->errorstep, host->dma_name);
+                rk29_sdmmc_clear_fifo(host);
                 cmd->error = -ETIMEDOUT;
                 host->mrq->cmd->error = -ETIMEDOUT;
                 host->errorstep = 0x1C;
-                printk("%s..%d...   CMD12 wait busy timeout!!!!!      ====xbw=[%s]====\n", \
-                                               __FUNCTION__, __LINE__,  host->dma_name);
             }
         }
     }
-
+    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);
+    { 
+        if( (!cmd->error) && (0==cmd->retries))
+        {         
+            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:
 
@@ -2360,7 +2656,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);
 
@@ -2374,10 +2670,14 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv)
        struct rk29_sdmmc       *host = (struct rk29_sdmmc *)priv;
        struct mmc_data         *data = host->cmd->data;
        enum rk29_sdmmc_state   state = host->state;
-
-       spin_lock(&host->lock);
-
+       int pending_flag, stopflag;
+       unsigned long iflags;
+    
+       spin_lock_irqsave(&host->lock, iflags); 
+       
        state = host->state;
+       pending_flag = 0;
+       stopflag = 0;
        
        do 
        {
@@ -2397,6 +2697,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
 
@@ -2412,9 +2713,9 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv)
                                                        __FUNCTION__, __LINE__,host->cmd->opcode,host->dma_name);
                     
                     host->complete_done = 1;
-                    goto unlock;
+                    break;
                 }
-
+                host->errorstep = 0xfa;
                 if(host->cmd->error)
                 {
                     del_timer_sync(&host->DTO_timer); //delete the timer for INT_DTO
@@ -2424,16 +2725,20 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv)
                         xbwprintk(7, "%s..%d..  cmderr, so call send_stop_cmd() ====xbw[%s]====\n", \
                                                                __FUNCTION__, __LINE__, host->dma_name);
 
+                        #if 0
                         state = STATE_SENDING_CMD;//STATE_SENDING_STOP; 
-                        send_stop_cmd(host);                        
+                        send_stop_cmd(host);
+                        #else
+                        stopflag = 1;  //Moidfyed by xbw at 2011-09-08
+                        #endif
                         break;
                     }
 
                     rk29_sdmmc_set_pending(host, EVENT_DATA_COMPLETE);
                 }
 
-
-                state = STATE_DATA_BUSY; 
+                host->errorstep = 0xf9;
+                state = STATE_DATA_BUSY;
                 /* fall through */
             }
 
@@ -2444,7 +2749,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
 
@@ -2457,17 +2762,22 @@ 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 = 1;
-                       goto unlock;
+                       host->complete_done = 2;
+                       break;
                     }
 
                 }
-
+                host->errorstep = 0xf4;
                 xbwprintk(7, "%s..%d..  after DATA_COMPLETE, so call send_stop_cmd() ====xbw[%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;
             }
 
@@ -2483,26 +2793,63 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv)
                 del_timer_sync(&host->request_timer); //delete the timer for INT_CMD_DONE int CMD12
                 rk29_sdmmc_request_end(host, host->cmd);
                 
-                host->complete_done = 1;
-                goto unlock;
+                host->complete_done = 3;
+                break;
             }
                
         }
-       } while(0);
+
+        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) );
+        if(pending_flag)
+        {
+            xbwprintk(7, "%s..%d...  cmd=%d(arg=0x%x),completedone=%d, retrycount=%d, doneflag=%d, \n \
+                host->state=0x%x, switchstate=%x, \n \
+                pendingEvent=0x%lu, completeEvents=0x%lu, \n \
+                mrqCMD=%d, arg=0x%x \n ====xbw[%s]====\n",\
+                
+                __FUNCTION__, __LINE__,host->cmd->opcode, host->cmd->arg, host->complete_done,\
+                host->retryfunc, host->mmc->doneflag,host->state, state, \
+                host->pending_events,host->completed_events,\
+                host->mrq->cmd->opcode, host->mrq->cmd->arg, host->dma_name);
+                
+            cpu_relax();
+        }
+                        
+       } while(pending_flag && ++host->retryfunc); //while(0);
+
+        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)
     {
-        spin_unlock(&host->lock);
+        host->errorstep = 0xf2;
+        spin_unlock_irqrestore(&host->lock, iflags);
         return;
     }
-    
+    host->errorstep = 0xf3; 
         host->state = STATE_IDLE;
-        spin_unlock(&host->lock);
         
-        mmc_request_done(host->mmc, host->mrq);
+        if(host->mrq && host->mmc->doneflag)
+        {
+           host->mmc->doneflag = 0;
+           spin_unlock_irqrestore(&host->lock, iflags);
+           
+           mmc_request_done(host->mmc, host->mrq);
+        }
+        else
+        {
+           spin_unlock_irqrestore(&host->lock, iflags);
+        }
 }
 
 
@@ -2510,16 +2857,16 @@ 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;
-           mod_timer(&host->DTO_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_WAIT_DTO_INTERNVAL*multi));
+        multi += (host->cmd->retries>2)?2:host->cmd->retries;
+           mod_timer(&host->DTO_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_WAIT_DTO_INTERNVAL*multi));//max wait 8s larger  
        }
        
        smp_wmb();
@@ -2541,8 +2888,7 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id)
     pending = rk29_sdmmc_read(host->regs, SDMMC_MINTSTS);// read only mask reg
     if (!pending)
     {
-       spin_unlock_irqrestore(&host->lock, iflags);
-        return IRQ_HANDLED;
+       goto Exit_INT;
     }
 
 
@@ -2561,6 +2907,8 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id)
            host->error_times = 0;
 
            #if 1
+           del_timer(&host->request_timer);
+               del_timer(&host->DTO_timer);
            rk29_sdmmc_dealwith_timeout(host);              
             #endif
                            
@@ -2570,7 +2918,7 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id)
 
                if(host->mmc->re_initialized_flags)
                    {
-                       mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_REMOVAL_DELAY/2));
+                       mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_REMOVAL_DELAY));
                    }
                    else
                    {
@@ -2587,8 +2935,7 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id)
 
        }
 
-        spin_unlock_irqrestore(&host->lock, iflags);
-        return IRQ_HANDLED;
+        goto Exit_INT;
 
     }  
 
@@ -2597,10 +2944,12 @@ 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);
+
+        goto Exit_INT;
     }
 
     if(pending & SDMMC_INT_SDIO) 
@@ -2610,6 +2959,8 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id)
 
         rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_SDIO);
         mmc_signal_sdio_irq(host->mmc);
+
+        goto Exit_INT;
     }
 
 
@@ -2627,8 +2978,7 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id)
         if(!(pending & SDMMC_INT_CMD_DONE))
             tasklet_schedule(&host->tasklet);
 
-        spin_unlock_irqrestore(&host->lock, iflags);
-        return IRQ_HANDLED;
+        goto Exit_INT;
     }
 
 
@@ -2638,8 +2988,7 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id)
                                __FUNCTION__, pending,host->cmd->opcode, host->cmd->arg, host->cmd->retries, host->dma_name);         
     
         rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_HLE); 
-        spin_unlock_irqrestore(&host->lock, iflags);
-        return IRQ_HANDLED;
+        goto Exit_INT;
     }
 
 
@@ -2649,18 +2998,15 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id)
                                __FUNCTION__, __LINE__,host->cmd->opcode,pending, host->dma_name);
         
         rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_DTO); 
-        del_timer_sync(&host->DTO_timer); //delete the timer for INT_DTO
+        del_timer(&host->DTO_timer); //delete the timer for INT_DTO
 
-        if (!host->data_status)
-               host->data_status = status;
+       host->data_status |= status;
 
         smp_wmb();
 
         rk29_sdmmc_set_pending(host, EVENT_DATA_COMPLETE);
         tasklet_schedule(&host->tasklet);
-
-        spin_unlock_irqrestore(&host->lock, iflags);
-        return IRQ_HANDLED;
+        goto Exit_INT;
     }
 
 
@@ -2670,10 +3016,19 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id)
                                __FUNCTION__, pending, host->cmd->opcode, host->cmd->arg, host->cmd->retries,host->dma_name);
        
         rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_FRUN); 
-        spin_unlock_irqrestore(&host->lock, iflags);
-        return IRQ_HANDLED;
+        goto Exit_INT;
     }
 
+#if defined(CONFIG_ARCH_RK30)
+    if(pending & SDMMC_INT_UNBUSY) 
+    {
+      //  printk("%d..%s:  ==test=== xbw======\n", __LINE__, __FUNCTION__);
+       // rk29_sdmmc_regs_printk(host);
+        rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_UNBUSY); 
+        goto Exit_INT;
+    }
+#endif
+
     if (pending & SDMMC_INT_RXDR) 
     {  
         xbwprintk(6, "%s..%d..  SDMMC_INT_RXDR  INT=0x%x   ====xbw[%s]====\n", \
@@ -2693,6 +3048,8 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id)
         rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_TXDR);  //  clear interrupt
     }
 
+Exit_INT:
+
        spin_unlock_irqrestore(&host->lock, iflags);
        return IRQ_HANDLED;
 }
@@ -2711,7 +3068,7 @@ static void rk29_sdmmc_detect_change(unsigned long data)
    
        smp_rmb();
 
-    if(RK29_CTRL_SDMMC_ID == host->pdev->id)
+    if((RK29_CTRL_SDMMC_ID == host->pdev->id) && rk29_sdmmc_get_cd(host->mmc))
     {
         host->mmc->re_initialized_flags =1;
     }
@@ -2727,12 +3084,14 @@ static void rk29_sdmmc1_check_status(unsigned long data)
         unsigned int status;
 
     status = pdata->status(mmc_dev(host->mmc));
-
+    
+    pr_info("%s: slot status change detected(%d-%d)\n",mmc_hostname(host->mmc), host->oldstatus, status);
+    
     if (status ^ host->oldstatus)
-    {
-        pr_info("%s: slot status change detected(%d-%d)\n",mmc_hostname(host->mmc), host->oldstatus, status);
+    {        
         if (status) 
         {
+            rk29_sdmmc_hw_init(host);
             set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
             mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(200));
         }
@@ -2749,7 +3108,7 @@ static void rk29_sdmmc1_check_status(unsigned long data)
 static void rk29_sdmmc1_status_notify_cb(int card_present, void *dev_id)
 {
         struct rk29_sdmmc *host = dev_id;
-        printk(KERN_INFO "%s, card_present %d\n", mmc_hostname(host->mmc), card_present);
+        //printk(KERN_INFO "%s, card_present %d\n", mmc_hostname(host->mmc), card_present);
         rk29_sdmmc1_check_status((unsigned long)host);
 }
 
@@ -2800,23 +3159,26 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
        host->error_times = 0;
        host->state = STATE_IDLE;
        host->complete_done = 0;
+       host->retryfunc = 0;
+       host->mrq = NULL;
+       host->new_mrq = NULL;
        
 #ifdef CONFIG_PM
     host->gpio_det = pdata->detect_irq;
 #endif
+    host->set_iomux = pdata->set_iomux;
 
        if(pdata->io_init)
                pdata->io_init();
                
        spin_lock_init(&host->lock);
-    spin_lock_init(&host->request_lock);
     
 #ifdef RK29_SDMMC_LIST_QUEUE   
        INIT_LIST_HEAD(&host->queue);
 #endif 
 
        host->clk = clk_get(&pdev->dev, "mmc");
-       
+
 #if RK29_SDMMC_DEFAULT_SDIO_FREQ
     clk_set_rate(host->clk,SDHC_FPP_FREQ);
 #else    
@@ -2826,7 +3188,7 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
            clk_set_rate(host->clk,RK29_MAX_SDIO_FREQ); 
 
 #endif
-               
+
        clk_enable(host->clk);
        clk_enable(clk_get(&pdev->dev, "hclk_mmc"));
 
@@ -2839,7 +3201,9 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
        }
 
     mmc->ops = &rk29_sdmmc_ops[pdev->id];
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))    
        mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY;
+#endif 
        mmc->f_min = FOD_FREQ;
        
 #if RK29_SDMMC_DEFAULT_SDIO_FREQ
@@ -2851,7 +3215,7 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
     }
     else
     {
-        mmc->f_max = RK29_MAX_SDIO_FREQ;//SDHC_FPP_FREQ / 2;
+        mmc->f_max = RK29_MAX_SDIO_FREQ;
     }
 
 #endif 
@@ -2860,12 +3224,18 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
                      | MMC_VDD_31_32|MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_34_35| MMC_VDD_35_36;    ///set valid volage 2.7---3.6v
        mmc->caps = pdata->host_caps;
        mmc->re_initialized_flags = 1;
+       mmc->doneflag = 1;
+       mmc->sdmmc_host_hw_init = rk29_sdmmc_hw_init;
 
     /*
         * We can do SGIO
        */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+       mmc->max_segs = 64;
+#else
        mmc->max_phys_segs = 64;
        mmc->max_hw_segs = 64; 
+#endif
 
        /*
         * Block size can be up to 2048 bytes, but must be a power of two.
@@ -2891,6 +3261,11 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
 
        tasklet_init(&host->tasklet, rk29_sdmmc_tasklet_func, (unsigned long)host);
 
+    /* Create card detect handler thread  */
+       setup_timer(&host->detect_timer, rk29_sdmmc_detect_change,(unsigned long)host);
+       setup_timer(&host->request_timer,rk29_sdmmc_INT_CMD_DONE_timeout,(unsigned long)host);
+       setup_timer(&host->DTO_timer,rk29_sdmmc_INT_DTO_timeout,(unsigned long)host);
+
        irq = platform_get_irq(pdev, 0);
        if (irq < 0)
        {
@@ -2902,6 +3277,9 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
     memcpy(host->dma_name, pdata->dma_name, 8);    
        host->use_dma = pdata->use_dma;
 
+    xbwprintk(7,"%s..%s..%d..***********  Bus clock= %d Khz  ====xbw[%s]===\n",\
+        __FILE__, __FUNCTION__,__LINE__,clk_get_rate(host->clk)/1000, host->dma_name);
+
        /*DMA init*/
        if(host->use_dma)
        {
@@ -2947,6 +3325,10 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
                host->dma_addr = regs->start + SDMMC_DATA;
        }
 
+#if defined(CONFIG_SDMMC0_RK29_WRITE_PROTECT) || defined(CONFIG_SDMMC1_RK29_WRITE_PROTECT)
+       host->write_protect = pdata->write_prt; 
+#endif 
+
     rk29_sdmmc_hw_init(host);
 
     ret = request_irq(irq, rk29_sdmmc_interrupt, 0, dev_name(&pdev->dev), host);
@@ -2966,7 +3348,30 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
 
     if(RK29_CTRL_SDMMC_ID== host->pdev->id)
     {
-        clear_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+        if(rk29_sdmmc_get_cd(host->mmc))
+        {
+            set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+        }
+        else
+        {
+            clear_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+        }
+    }
+    else
+    {
+        #if defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD)
+        if(0== host->pdev->id)
+        {
+            set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+        }
+        #endif
+
+        #if defined(CONFIG_USE_SDMMC1_FOR_WIFI_DEVELOP_BOARD)
+        if(1== host->pdev->id)
+        {
+            set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+        }
+        #endif
     }
 
 
@@ -2980,10 +3385,6 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
         }
     }
 
-    /* Create card detect handler thread  */
-       setup_timer(&host->detect_timer, rk29_sdmmc_detect_change,(unsigned long)host);
-       setup_timer(&host->request_timer,rk29_sdmmc_INT_CMD_DONE_timeout,(unsigned long)host);
-       setup_timer(&host->DTO_timer,rk29_sdmmc_INT_DTO_timeout,(unsigned long)host);
 
        platform_set_drvdata(pdev, mmc);        
 
@@ -2992,7 +3393,7 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
 #ifdef RK29_SDMMC_NOTIFY_REMOVE_INSERTION
     
     globalSDhost[pdev->id] = (struct rk29_sdmmc        *)host;
-    if(RK29_CTRL_SDMMC_ID== host->pdev->id)
+    if(0== host->pdev->id)
     {
         rk29_sdmmc_progress_add_attr(pdev);
     }
@@ -3068,6 +3469,7 @@ static int __exit rk29_sdmmc_remove(struct platform_device *pdev)
 
 #ifdef CONFIG_PM
 
+#if defined(CONFIG_ARCH_RK29)
 static irqreturn_t det_keys_isr(int irq, void *dev_id)
 {
        struct rk29_sdmmc *host = dev_id;
@@ -3103,6 +3505,43 @@ static void rk29_sdmmc_sdcard_resume(struct rk29_sdmmc *host)
        rk29_mux_api_set(GPIO2A2_SDMMC0DETECTN_NAME, GPIO2L_SDMMC0_DETECT_N);
 }
 
+#elif defined(CONFIG_ARCH_RK30)
+static irqreturn_t det_keys_isr(int irq, void *dev_id)
+{
+       struct rk29_sdmmc *host = dev_id;
+       dev_info(&host->pdev->dev, "sd det_gpio changed(%s), send wakeup key!\n",
+               gpio_get_value(RK30_PIN3_PB6)?"removed":"insert");
+       rk29_sdmmc_detect_change((unsigned long)dev_id);
+
+       return IRQ_HANDLED;
+}
+
+static int rk29_sdmmc_sdcard_suspend(struct rk29_sdmmc *host)
+{
+       int ret = 0;
+       rk29_mux_api_set(GPIO3B6_SDMMC0DETECTN_NAME, GPIO3B_GPIO3B6);
+       gpio_request(RK30_PIN3_PB6, "sd_detect");
+       gpio_direction_input(RK30_PIN3_PB6);
+
+       host->gpio_irq = gpio_to_irq(RK30_PIN3_PB6);
+       ret = request_irq(host->gpio_irq, det_keys_isr,
+                                           (gpio_get_value(RK30_PIN3_PB6))?IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING,
+                                           "sd_detect",
+                                           host);
+       
+       enable_irq_wake(host->gpio_irq);
+
+       return ret;
+}
+static void rk29_sdmmc_sdcard_resume(struct rk29_sdmmc *host)
+{
+       disable_irq_wake(host->gpio_irq);
+       free_irq(host->gpio_irq,host);
+       gpio_free(RK30_PIN3_PB6);
+       rk29_mux_api_set(GPIO3B6_SDMMC0DETECTN_NAME, GPIO3B_SDMMC0_DETECT_N);
+}
+
+#endif
 
 
 static int rk29_sdmmc_suspend(struct platform_device *pdev, pm_message_t state)