From: 杨云 <yangyun@rock-chips.com>
Date: Fri, 15 Jul 2011 06:52:57 +0000 (+0800)
Subject: RK29 SDMMC Ver1.14 2011-06-26 release from XBW
X-Git-Tag: firefly_0821_release~10132^2~1
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=543f1a582cda4d8b4945bbda8a9a876b76712ba1;p=firefly-linux-kernel-4.4.55.git

RK29 SDMMC Ver1.14 2011-06-26 release from XBW
---

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 98f74b0087b5..a428440e9199 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -43,6 +43,7 @@
 
 MODULE_ALIAS("mmc:block");
 
+static DEFINE_MUTEX(block_mutex); //added by xbw at 2011-04-21
 /*
  * max 8 partitions per card
  */
@@ -106,6 +107,7 @@ static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
 	struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
 	int ret = -ENXIO;
 
+	mutex_lock(&block_mutex); //added by xbw at 2011-04-21
 	if (md) {
 		if (md->usage == 2)
 			check_disk_change(bdev);
@@ -116,6 +118,7 @@ static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
 			ret = -EROFS;
 		}
 	}
+	mutex_unlock(&block_mutex);
 
 	return ret;
 }
@@ -124,7 +127,9 @@ static int mmc_blk_release(struct gendisk *disk, fmode_t mode)
 {
 	struct mmc_blk_data *md = disk->private_data;
 
+	mutex_lock(&block_mutex); //added by xbw at 2011-04-21
 	mmc_blk_put(md);
+	mutex_unlock(&block_mutex);
 	return 0;
 }
 
@@ -224,6 +229,7 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
 	return result;
 }
 
+#if 0 //Deleted by xbw@2011-03-21
 static u32 get_card_status(struct mmc_card *card, struct request *req)
 {
 	struct mmc_command cmd;
@@ -240,6 +246,7 @@ static u32 get_card_status(struct mmc_card *card, struct request *req)
 		       req->rq_disk->disk_name, err);
 	return cmd.resp[0];
 }
+#endif
 
 static int
 mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
@@ -283,14 +290,17 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 #endif
 
 	mmc_claim_host(card->host);
+	//card->host->re_initialized_flags = 0; //added by xbw@2011-04-07
 
 	do {
-		struct mmc_command cmd;
+		//struct mmc_command cmd;//Deleted by xbw@2011-03-21
 		u32 readcmd, writecmd, status = 0;
 
 		memset(&brq, 0, sizeof(struct mmc_blk_request));
 		brq.mrq.cmd = &brq.cmd;
 		brq.mrq.data = &brq.data;
+		
+		brq.cmd.retries = 2; //suppot retry read-write; added by xbw@2011-03-21
 
 		brq.cmd.arg = blk_rq_pos(req);
 		if (!mmc_card_blockaddr(card))
@@ -371,6 +381,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 
 		mmc_queue_bounce_post(mq);
 
+        #if 0 //not turn CMD18 to CMD17. deleted by xbw at 2011-04-21
+
 		/*
 		 * Check for errors here, but don't jump to cmd_err
 		 * until later as we need to wait for the card to leave
@@ -384,10 +396,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 				disable_multi = 1;
 				continue;
 			}
-			status = get_card_status(card, req);
+			
+			//status = get_card_status(card, req); //Deleted by xbw@2011-03-21
+			
 		} else if (disable_multi == 1) {
 			disable_multi = 0;
-		}
+		}   
+        #endif
 
 		if (brq.cmd.error) {
 			printk(KERN_DEBUG "%s: error %d sending read/write "
@@ -414,7 +429,10 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 			       brq.stop.resp[0], status);
 		}
 
+ #if 0 //Deleted by xbw@2011-03-21
 		if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
+
+		   
 			do {
 				int err;
 
@@ -435,6 +453,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 			} while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||
 				(R1_CURRENT_STATE(cmd.resp[0]) == 7));
 
+
 #if 0
 			if (cmd.resp[0] & ~0x00000900)
 				printk(KERN_ERR "%s: status = %08x\n",
@@ -443,8 +462,9 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 				goto cmd_err;
 #endif
 		}
+#endif		
 
-		if (brq.cmd.error || brq.stop.error || brq.data.error) {
+		if (brq.cmd.error || brq.stop.error || brq.data.error) {		
 			if (rq_data_dir(req) == READ) {
 				/*
 				 * After an error, we redo I/O one sector at a
@@ -571,6 +591,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
 	 */
 
 	sprintf(md->disk->disk_name, "mmcblk%d", devidx);
+	printk("%s..%d **** devidx=%d, dev_use[0]=%lu, disk_name=%s *** ==xbw[%s]==\n",__FUNCTION__,__LINE__, devidx, dev_use[0], md->disk->disk_name,mmc_hostname(card->host));
 
 	blk_queue_logical_block_size(md->queue.queue, 512);
 
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 812b22035626..bdb165f93046 100755
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -279,7 +279,6 @@ void mmc_remove_card(struct mmc_card *card)
 #endif
 
 	if (mmc_card_present(card)) {
-		mmc_card_clr_present(card);
 		if (mmc_host_is_spi(card->host)) {
 			printk(KERN_INFO "%s: SPI card removed\n",
 				mmc_hostname(card->host));
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 5148f8e5ea71..f0ddaa7b4cc7 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -202,7 +202,11 @@ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
 
 	mmc_start_request(host, mrq);
 
+    #if 0
 	wait_for_completion(&complete);
+	#else
+	wait_for_completion_timeout(&complete,HZ*3); //for cmd dead. Modifyed by xbw at 2011-06-02
+	#endif
 }
 
 EXPORT_SYMBOL(mmc_wait_for_req);
@@ -1067,18 +1071,8 @@ void mmc_rescan(struct work_struct *work)
 	u32 ocr;
 	int err;
 	int extend_wakelock = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&host->lock, flags);
-
-	if (host->rescan_disable) {
-		spin_unlock_irqrestore(&host->lock, flags);
-		return;
-	}
-
-	spin_unlock_irqrestore(&host->lock, flags);
-
 
+    
 	mmc_bus_get(host);
 
 	/* if there is a card registered, check whether it is still present */
@@ -1109,54 +1103,105 @@ void mmc_rescan(struct work_struct *work)
 	 * release the lock here.
 	 */
 	mmc_bus_put(host);
+    printk("\n%s...%d..  ===== mmc_rescan Begin....======xbw[%s]=====\n",__FILE__, __LINE__, mmc_hostname(host));
 
 	if (host->ops->get_cd && host->ops->get_cd(host) == 0)
+	{
+	    printk("\n=================\n%s..%d..  ====find no SDMMC host.====xbw[%s]=====\n", \
+	        __FUNCTION__, __LINE__, mmc_hostname(host));
+	        
 		goto out;
+	}
 
 	mmc_claim_host(host);
-
+	
 	mmc_power_up(host);
+	
 	mmc_go_idle(host);
 
-	mmc_send_if_cond(host, host->ocr_avail);
-
-	/*
-	 * First we search for SDIO...
-	 */
-	err = mmc_send_io_op_cond(host, 0, &ocr);
-	if (!err) {
-		if (mmc_attach_sdio(host, ocr))
-			mmc_power_off(host);
-		extend_wakelock = 1;
-		goto out;
-	}
-
-	/*
-	 * ...then normal SD...
-	 */
-	err = mmc_send_app_op_cond(host, 0, &ocr);
-	if (!err) {
-		if (mmc_attach_sd(host, ocr))
-			mmc_power_off(host);
-		extend_wakelock = 1;
-		goto out;
-	}
-
-	/*
-	 * ...and finally MMC.
-	 */
-	err = mmc_send_op_cond(host, 0, &ocr);
-	if (!err) {
-		if (mmc_attach_mmc(host, ocr))
-			mmc_power_off(host);
-		extend_wakelock = 1;
-		goto out;
-	}
+    /*
+        In oder to improve the initialization process in rockchip IC, I modify the following code about the the initialization process of SDIO-SD-MMC.
+        So I deleted the CMD8 and add a conditional to distinguish between the two card type,i.e.SDMMC process and SDIO process.
+        For detail,please refer to "RK29XX Technical Reference Manual" and "SD-MMC-SDIO Specifications".
+        Noted by xbw@2011-04-09
+    */
+
+    //mmc_send_if_cond(host, host->ocr_avail); //deleted by xbw@2011-04-09
+
+     if( strncmp( mmc_hostname(host) ,"mmc0" , strlen("mmc0")) ){
+    	/*
+    	 * First we search for SDIO...
+    	 */
+    	err = mmc_send_io_op_cond(host, 0, &ocr);
+    	if (!err) {
+    		printk("\n%s..%d..  ===== Begin to identify card as SDIO-card===xbw[%s]===\n",__FUNCTION__, __LINE__, mmc_hostname(host));
+
+    		if (mmc_attach_sdio(host, ocr))
+    		{
+    		    printk("\n=====\n %s..%d..  ===== Initialize SDIO-card unsuccessfully!!! ===xbw[%s]===\n=====\n",\
+    		        __FUNCTION__,  __LINE__, mmc_hostname(host));
+    		        
+    			mmc_power_off(host);
+    		}
+    		else
+    		{
+    		    printk("%s..%d..  ===== Initialize SDIO successfully. ===xbw[%s]===\n",__FUNCTION__,  __LINE__, mmc_hostname(host));
+    		}
+    		extend_wakelock = 1;
+    		goto out;
+    	}
+    }
+
+
+    /*
+     * ...then normal SD...
+     */
+    err = mmc_send_app_op_cond(host, 0, &ocr);
+    if (!err) {
+    	printk("\n%s..%d..  ===== Begin to identify card as SD-card ===xbw[%s]===\n",__FUNCTION__, __LINE__, mmc_hostname(host));
+
+    	if (mmc_attach_sd(host, ocr))
+    	{
+    	    printk("\n=====\n%s..%d..  ===== Initialize SD-card unsuccessfully!!! ===xbw[%s]===\n====\n",\
+    	        __FUNCTION__,  __LINE__, mmc_hostname(host));
+    	        
+    		mmc_power_off(host);
+    	}
+    	else
+    	{
+    	    printk("%s..%d..  ===== Initialize SD-card successfully. ===xbw[%s]===\n",__FUNCTION__,  __LINE__, mmc_hostname(host));
+    	}
+    	extend_wakelock = 1;
+    	goto out;
+    }
+
+    /*
+     * ...and finally MMC.
+     */
+    err = mmc_send_op_cond(host, 0, &ocr);
+    if (!err) {
+        printk("\n%s..%d..  ===== Begin to identify card as MMC-card ===xbw[%s]===\n", __FUNCTION__, __LINE__, mmc_hostname(host));
+
+    	if (mmc_attach_mmc(host, ocr))
+    	{
+    	    printk("\n =====\n%s..%d..  ===== Initialize MMC-card unsuccessfully!!! ===xbw[%s]===\n======\n",\
+    	        __FUNCTION__,  __LINE__, mmc_hostname(host));
+    	        
+    		mmc_power_off(host);
+    	}
+    	else
+    	{
+    	    printk("%s...%d..  ===== Initialize MMC-card successfully. ===xbw[%s]===\n",__FUNCTION__,  __LINE__, mmc_hostname(host));
+    	}
+    	extend_wakelock = 1;
+    	goto out;
+    }
 
 	mmc_release_host(host);
 	mmc_power_off(host);
 
 out:
+
 	if (extend_wakelock)
 		wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2);
 	else
@@ -1292,6 +1337,7 @@ int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
 	if (mmc_bus_needs_resume(host))
 		return 0;
 
+    printk("%s: %s go into suspend function.\n",__FUNCTION__, mmc_hostname(host));
 	if (host->caps & MMC_CAP_DISABLE)
 		cancel_delayed_work(&host->disable);
 	cancel_delayed_work(&host->detect);
@@ -1301,9 +1347,21 @@ int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
 	if (host->bus_ops && !host->bus_dead) {
 		if (host->bus_ops->suspend)
 			err = host->bus_ops->suspend(host);
+		if (err == -ENOSYS || !host->bus_ops->resume) {
+			/*
+			 * We simply "remove" the card in this case.
+			 * It will be redetected on resume.
+			 */
+			if (host->bus_ops->remove)
+				host->bus_ops->remove(host);
+			mmc_claim_host(host);
+			mmc_detach_bus(host);
+			mmc_release_host(host);
+			err = 0;
+		}
 	}
 	mmc_bus_put(host);
-
+    printk("%s: %s exit suspend function.\n",__FUNCTION__, mmc_hostname(host));
 	if (!err)
 		mmc_power_off(host);
 
@@ -1331,65 +1389,39 @@ int mmc_resume_host(struct mmc_host *host)
 		mmc_power_up(host);
 		mmc_select_voltage(host, host->ocr);
 		BUG_ON(!host->bus_ops->resume);
+		
+		#if 0 //panic if the card is being removed during the resume, deleted by xbw at 2011-06-20
 		err = host->bus_ops->resume(host);
 		if (err) {
 			printk(KERN_WARNING "%s: error %d during resume "
 					    "(card was removed?)\n",
 					    mmc_hostname(host), err);
+			if (host->bus_ops->remove)
+				host->bus_ops->remove(host);
+			mmc_claim_host(host);
+			mmc_detach_bus(host);
+			mmc_release_host(host);
+			/* no need to bother upper layers */
 			err = 0;
 		}
+		#else
+		host->bus_ops->resume(host);
+
+		#endif
 	}
 	mmc_bus_put(host);
 
+	/*
+	 * We add a slight delay here so that resume can progress
+	 * in parallel.
+	 */
+	mmc_detect_change(host, 1);
+
 	return err;
 }
-EXPORT_SYMBOL(mmc_resume_host);
-
-/* Do the card removal on suspend if card is assumed removeable
- * Do that in pm notifier while userspace isn't yet frozen, so we will be able
-   to sync the card.
-*/
-int mmc_pm_notify(struct notifier_block *notify_block,
-					unsigned long mode, void *unused)
-{
-	struct mmc_host *host = container_of(
-		notify_block, struct mmc_host, pm_notify);
-	unsigned long flags;
-
-
-	switch (mode) {
-	case PM_HIBERNATION_PREPARE:
-	case PM_SUSPEND_PREPARE:
-
-		spin_lock_irqsave(&host->lock, flags);
-		host->rescan_disable = 1;
-		spin_unlock_irqrestore(&host->lock, flags);
-		cancel_delayed_work_sync(&host->detect);
-
-		if (!host->bus_ops || host->bus_ops->suspend)
-			break;
-
-		mmc_claim_host(host);
-
-		if (host->bus_ops->remove)
-			host->bus_ops->remove(host);
-
-		mmc_detach_bus(host);
-		mmc_release_host(host);
-		break;
 
-	case PM_POST_SUSPEND:
-	case PM_POST_HIBERNATION:
-
-		spin_lock_irqsave(&host->lock, flags);
-		host->rescan_disable = 0;
-		spin_unlock_irqrestore(&host->lock, flags);
-		mmc_detect_change(host, 0);
-
-	}
+EXPORT_SYMBOL(mmc_resume_host);
 
-	return 0;
-}
 #endif
 
 #ifdef CONFIG_MMC_EMBEDDED_SDIO
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 94f35ca5c413..a268d12f1af0 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -16,7 +16,6 @@
 #include <linux/idr.h>
 #include <linux/pagemap.h>
 #include <linux/leds.h>
-#include <linux/suspend.h>
 
 #include <linux/mmc/host.h>
 
@@ -85,9 +84,6 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
 	init_waitqueue_head(&host->wq);
 	INIT_DELAYED_WORK(&host->detect, mmc_rescan);
 	INIT_DELAYED_WORK_DEFERRABLE(&host->disable, mmc_host_deeper_disable);
-#ifdef CONFIG_PM
-	host->pm_notify.notifier_call = mmc_pm_notify;
-#endif
 
 	/*
 	 * By default, hosts do not support SGIO or large requests.
@@ -136,8 +132,6 @@ int mmc_add_host(struct mmc_host *host)
 #endif
 
 	mmc_start_host(host);
-        if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY))
-	   register_pm_notifier(&host->pm_notify);
 
 	return 0;
 }
@@ -154,8 +148,6 @@ EXPORT_SYMBOL(mmc_add_host);
  */
 void mmc_remove_host(struct mmc_host *host)
 {
-        if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY))	
-           unregister_pm_notifier(&host->pm_notify);
 	mmc_stop_host(host);
 
 #ifdef CONFIG_DEBUG_FS
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 32af45c419f4..32eefeb98aa5 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -321,7 +321,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	/* The extra bit indicates that we support high capacity */
 	err = mmc_send_op_cond(host, ocr | (1 << 30), NULL);
 	if (err)
+	{
+	    printk("%s..%d..  ====*Identify the card as MMC , but OCR error, so fail to initialize.===xbw[%s]===\n", __FUNCTION__, __LINE__, mmc_hostname(host));
 		goto err;
+	}
 
 	/*
 	 * For SPI, enable CRC as appropriate.
@@ -438,6 +441,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		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) {
+		card->csd.max_dtr = (card->csd.max_dtr > MMC_FPP_FREQ) ? MMC_FPP_FREQ : (card->csd.max_dtr); //in order to expand the compatibility of card. Added by xbw@2011-03-21
 		max_dtr = card->csd.max_dtr;
 	}
 
@@ -660,6 +664,7 @@ static void mmc_attach_bus_ops(struct mmc_host *host)
 int mmc_attach_mmc(struct mmc_host *host, u32 ocr)
 {
 	int err;
+	int retry_times = 3;
 
 	BUG_ON(!host);
 	WARN_ON(!host->claimed);
@@ -705,9 +710,33 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr)
 
 	mmc_release_host(host);
 
+#if 0 // Deleted by xbw at 2011-04-09
+    err = mmc_add_card(host->card);
+	if (err)
+		goto remove_card;
+
+#else //modifyed by xbw at 2011--04-11
+
+Retry_add:
 	err = mmc_add_card(host->card);
 	if (err)
+	{
+	    //retry add the card; Added by xbw
+        if((--retry_times >= 0))
+        {        
+            printk("\n%s..%s..%d   ****error in add partition, so retry.  ===xbw[%s]===\n",__FUNCTION__,__FILE__,__LINE__, mmc_hostname(host));   
+            /* sleep some time */
+            set_current_state(TASK_INTERRUPTIBLE);
+            schedule_timeout(HZ/2);
+            
+            goto Retry_add;
+        }
+
 		goto remove_card;
+    
+	}
+#endif
+		
 
 	return 0;
 
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 8fe5e9ece251..53bca2f724eb 100755
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -362,7 +362,10 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
 
 	err = mmc_send_app_op_cond(host, ocr, NULL);
 	if (err)
+	{
+	    printk("%s..%d..  ====*Identify the card as SD , but OCR error, so fail to initialize.===xbw[%s]===\n", __FUNCTION__, __LINE__, mmc_hostname(host));
 		goto err;
+	}
 
 	/*
 	 * Fetch CID from card.
@@ -458,6 +461,11 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
 				printk(KERN_WARNING
 				       "%s: read switch failed (attempt %d)\n",
 				       mmc_hostname(host), retries);
+				
+				if(0 == host->re_initialized_flags)
+				{
+					 break; //Added by xbw at 2011-06-21
+				}       
 			}
 		}
 #else
@@ -496,6 +504,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
 		if (max_dtr > card->sw_caps.hs_max_dtr)
 			max_dtr = card->sw_caps.hs_max_dtr;
 	} else if (max_dtr > card->csd.max_dtr) {
+	    card->csd.max_dtr = (card->csd.max_dtr > SD_FPP_FREQ) ? SD_FPP_FREQ : (card->csd.max_dtr); //in order to expand the compatibility of card. Added by xbw@2011-03-21
 		max_dtr = card->csd.max_dtr;
 	}
 
@@ -576,6 +585,13 @@ static void mmc_sd_detect(struct mmc_host *host)
 		err = mmc_send_status(host->card, NULL);
 		if (err) {
 			retries--;
+		  
+		  if(0 == host->re_initialized_flags)
+			{
+				 retries = 0;
+				 break; //Added by xbw at 2011-06-21
+			}
+			
 			udelay(5);
 			continue;
 		}
@@ -636,6 +652,7 @@ static int mmc_sd_resume(struct mmc_host *host)
 #ifdef CONFIG_MMC_PARANOID_SD_INIT
 	retries = 5;
 	while (retries) {
+
 		err = mmc_sd_init_card(host, host->ocr, host->card);
 
 		if (err) {
@@ -643,6 +660,11 @@ static int mmc_sd_resume(struct mmc_host *host)
 			       mmc_hostname(host), err, retries);
 			mdelay(5);
 			retries--;
+						
+			if(0 == host->re_initialized_flags)
+			{
+				 break; //Added by xbw at 2011-06-21
+			}
 			continue;
 		}
 		break;
@@ -715,6 +737,8 @@ static void mmc_sd_attach_bus_ops(struct mmc_host *host)
 int mmc_attach_sd(struct mmc_host *host, u32 ocr)
 {
 	int err;
+	int retry_times = 3;
+	
 #ifdef CONFIG_MMC_PARANOID_SD_INIT
 	int retries;
 #endif
@@ -772,6 +796,12 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr)
 		err = mmc_sd_init_card(host, host->ocr, NULL);
 		if (err) {
 			retries--;
+			
+			if(0 == host->re_initialized_flags)
+			{
+				 retries = 0;
+				 break; //Added by xbw at 2011-06-21
+			}
 			continue;
 		}
 		break;
@@ -790,9 +820,32 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr)
 
 	mmc_release_host(host);
 
+#if 0 // Deleted by xbw at 2011-04-09
+    err = mmc_add_card(host->card);
+	if (err)
+		goto remove_card;
+
+#else //modifyed by xbw at 2011--04-11
+
+Retry_add:
 	err = mmc_add_card(host->card);
 	if (err)
+	{
+	    //retry add the card; Added by xbw
+        if((--retry_times >= 0))
+        {        
+            printk("\n%s..%s..%d   ****error in add partition, so retry.  ===xbw[%s]===\n",__FUNCTION__,__FILE__,__LINE__, mmc_hostname(host));   
+            /* sleep some time */
+            set_current_state(TASK_INTERRUPTIBLE);
+            schedule_timeout(HZ/2);
+            
+            goto Retry_add;
+        }
+
 		goto remove_card;
+    
+	}
+#endif	
 
 	return 0;
 
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 21fffa2094bd..735e41f5c778 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -241,7 +241,10 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	err = mmc_send_io_op_cond(host, host->ocr, &ocr);
 	if (err)
+	{
+	    printk("%s..%d..  ====*Identify the card as SDIO , but OCR error, so fail to initialize.===xbw[%s]===\n", __FUNCTION__, __LINE__, mmc_hostname(host));
 		goto err;
+	}
 
 	/*
 	 * For SPI, enable CRC as appropriate.
@@ -278,14 +281,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
 		if (err)
 			goto remove;
 
-		/*
-		 * Update oldcard with the new RCA received from the SDIO
-		 * device -- we're doing this so that it's updated in the
-		 * "card" struct when oldcard overwrites that later.
-		 */
-		if (oldcard)
-			oldcard->rca = card->rca;
-
 		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
 	}
 
diff --git a/drivers/mmc/host/rk29_sdmmc.c b/drivers/mmc/host/rk29_sdmmc.c
index b33d69c2300b..7e00db34ae8f 100755
--- a/drivers/mmc/host/rk29_sdmmc.c
+++ b/drivers/mmc/host/rk29_sdmmc.c
@@ -10,6 +10,7 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
+ *
  * mount -t debugfs debugfs /data/debugfs;cat /data/debugfs/mmc0/status
  * echo 't' >/proc/sysrq-trigger
  * echo 19 >/sys/module/wakelock/parameters/debug_mask
@@ -35,7 +36,6 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/card.h>
-#include <linux/earlysuspend.h>
 
 #include <mach/board.h>
 #include <mach/rk29_iomap.h>
@@ -46,73 +46,63 @@
 #include <mach/rk29-dma-pl330.h>
 #include <asm/scatterlist.h>
 
-#include "rk2818-sdmmc.h"
+#include "rk29_sdmmc.h"
+
+
+#define RK29_SDMMC_xbw_Debug 0
+
+#if RK29_SDMMC_xbw_Debug 
+int debug_level = 7;
+#define xbwprintk(n, format, arg...) \
+	if (n <= debug_level) {	 \
+		printk(format,##arg); \
+	}
+#else
+#define xbwprintk(n, arg...)
+#endif
+
+#define RK29_SDMMC_ERROR_FLAGS		(SDMMC_INT_FRUN | SDMMC_INT_RTO | SDMMC_INT_HLE )
+
+#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 )
 
-#define RK29_SDMMC_DATA_ERROR_FLAGS	(SDMMC_INT_DRTO | SDMMC_INT_DCRC | SDMMC_INT_HTO | SDMMC_INT_SBE | SDMMC_INT_EBE | SDMMC_INT_FRUN)
-#define RK29_SDMMC_CMD_ERROR_FLAGS	(SDMMC_INT_RTO | SDMMC_INT_RCRC | SDMMC_INT_RE | SDMMC_INT_HLE)
-#define RK29_SDMMC_ERROR_FLAGS		(RK29_SDMMC_DATA_ERROR_FLAGS | RK29_SDMMC_CMD_ERROR_FLAGS | SDMMC_INT_HLE)
 
-#define RK29_SDMMC_TMO_COUNT		10000
+#define RK29_SDMMC_SEND_START_TIMEOUT   5000  //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_VERSION "Ver.1.14. The last modify date is 2011-06-26,modifyed by XBW." 
+
+#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
+
+#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*/
 
-#define RK29_SDCARD_CLK				48  //48Mhz
-#define RK29_SDIO_CLK				36	//36Mhz
 
 enum {
 	EVENT_CMD_COMPLETE = 0,
-	EVENT_XFER_COMPLETE,
 	EVENT_DATA_COMPLETE,
 	EVENT_DATA_ERROR,
 	EVENT_XFER_ERROR
 };
-enum {
-	MRQ_REQUEST_START = 0,
-	MRQ_INT_CMD_DONE,  //1
-	MRQ_INT_CMD_ERR,  //2
-	MRQ_INT_DATA_DONE,  //3
-	MRQ_INT_DATA_ERR,  //4
-	MRQ_INT_CD,  //5
-	MRQ_INT_SDIO,  //6
-	MRQ_HAS_DATA,  //7
-	MRQ_HAS_STOP,  //8
-	MRQ_CMD_START_TMO,  //9
-	MRQ_CMD_START_DONE,  //10
-	MRQ_STOP_START_TMO,  //11
-	MRQ_STOP_START_DONE,  //12
-	MRQ_CLK_START_TMO,  //13
-	MRQ_CLK_START_DONE,  //14
-	MRQ_RESET_CTRL_ERR,  //15
-	MRQ_RESET_CTRL_DONE,  //16
-	MRQ_DMA_SET_ERR,  //17
-	MRQ_START_DMA,	//18
-	MRQ_STOP_DMA,  //19
-	MRQ_DMA_DONE,  //20
-	MRQ_REQUEST_DONE,  //21
-};
+
 enum rk29_sdmmc_state {
 	STATE_IDLE = 0,
 	STATE_SENDING_CMD,
-	STATE_SENDING_DATA,
 	STATE_DATA_BUSY,
 	STATE_SENDING_STOP,
-	STATE_DATA_ERROR,
 };
-#define rk29_sdmmc_test_and_clear_pending(host, event)		\
-	test_and_clear_bit(event, &host->pending_events)
-#define rk29_sdmmc_set_completed(host, event)			\
-		set_bit(event, &host->completed_events)
-#define rk29_sdmmc_set_pending(host, event)				\
-	set_bit(event, &host->pending_events)
-#define rk29_sdmmc_set_mrq_status(host, status)				\
-		set_bit(status, &host->mrq_status)
-#define rk29_sdmmc_test_mrq_status(host, status)				\
-			test_bit(status, &host->mrq_status)
 
 struct rk29_sdmmc_dma_info {
 	enum dma_ch chn;
 	char *name;
 	struct rk29_dma_client client;
 };
-static struct rk29_sdmmc_dma_info dma_infos[] = {
+
+static struct rk29_sdmmc_dma_info rk29_sdmmc_dma_infos[]= {
 	{
 		.chn = DMACH_SDMMC,
 		.client = {
@@ -125,61 +115,105 @@ static struct rk29_sdmmc_dma_info dma_infos[] = {
 			.name = "rk29-dma-sdio1",
 		}
 	},
+
+	{
+		.chn = DMACH_EMMC,
+		.client = {
+			.name = "rk29-dma-sdio2",
+		}
+	},
 };
-static int rk29_sdmmc_is_sdio(struct rk29_sdmmc_platform_data *pdata)
+
+
+/* Interrupt Information */
+typedef struct TagSDC_INT_INFO
 {
-	if(strncmp(pdata->dma_name, "sdio", strlen("sdio")) == 0)
-		return 1;
-	else
-		return 0;
-}
+    u32     transLen;               //the length of data sent.
+    u32     desLen;                 //the total length of the all data.
+    u32    *pBuf;                   //the data buffer for interrupt read or write.
+}SDC_INT_INFO_T;
+
 
 struct rk29_sdmmc {
-	struct device 				*dev;
+	spinlock_t		lock;
+	void __iomem		*regs;
+	struct clk 		*clk;
+
+	struct mmc_request	*mrq;
+	struct mmc_request	*new_mrq;
+	struct mmc_command	*cmd;
+	struct mmc_data		*data;
+
+	dma_addr_t		dma_addr;;
+	unsigned int	use_dma:1;
+	char			dma_name[8];
+	u32			cmd_status;
+	u32			data_status;
+	u32			stop_cmdr;
+
+    u32         old_div;
+	u32			cmdr;   //the value setted into command-register
+	u32			dodma;  //sign the DMA used for transfer.
+	u32         errorstep;//record the error point.
+	u32         *pbuf;
+	SDC_INT_INFO_T    intInfo; 
+    struct rk29_sdmmc_dma_info 	dma_info;
+    
+	int error_times;
+	u32 old_cmd;
 	
-	int							is_sdio;
-	int							is_init;
-	int							gpio_det;
-	int							gpio_irq;
-	int							irq;
-
-	int							enable_sd_warkup;
-
-	unsigned int				clock;
-	unsigned int				ios_clock;
-	unsigned int				div;
-	spinlock_t					lock;
-	unsigned int				stop_cmdr;
-	unsigned int				cmd_intsts;
-	unsigned int				data_intsts;
-	unsigned long				pending_events;
-	unsigned long				completed_events;
-	unsigned long				mrq_status;
-	unsigned long				old_mrq_status;
-
-	unsigned int				bus_hz;
+	struct tasklet_struct	tasklet;
+	unsigned long		pending_events;
+	unsigned long		completed_events;
+	enum rk29_sdmmc_state	state;
+
+#ifdef RK29_SDMMC_LIST_QUEUE
+	struct list_head	queue;
+	struct list_head	queue_node;
+#endif
+
+	u32			bus_hz;
+	struct platform_device	*pdev;
+	struct mmc_host		*mmc;
+	u32			ctype;
+	unsigned int		clock;
+	unsigned long		flags;
 	
+#define RK29_SDMMC_CARD_PRESENT	0
 
-	void __iomem				*regs;
+	int			id;
 
-	struct mmc_host 			*mmc;
-	struct delayed_work			work;
-	struct rk29_sdmmc_dma_info 	dma_info;
-	struct tasklet_struct		tasklet;
-	struct mmc_request			*mrq;
-	struct mmc_command			*cmd;
-	struct clk 					*clk;
-	struct timer_list			monitor_timer;
+	struct timer_list	detect_timer; 
+	struct timer_list	request_timer; //the timer for INT_CMD_DONE
+	struct timer_list	DTO_timer;     //the timer for INT_DTO
+	struct mmc_command	stopcmd;
 
-	enum rk29_sdmmc_state		state;
-	dma_addr_t      			dma_addr;
-	
-	int (*get_wifi_cd)(struct device *);
-#ifdef CONFIG_HAS_EARLYSUSPEND
-	struct early_suspend		early_suspend;
+	/* flag for current bus settings */
+    u32 bus_mode;
+
+    unsigned int            oldstatus;
+
+#ifdef CONFIG_PM
+    int gpio_irq;
+	int gpio_det;
 #endif
 };
-struct rk29_sdmmc *sdio_host = NULL;
+
+
+#ifdef RK29_SDMMC_NOTIFY_REMOVE_INSERTION
+static struct rk29_sdmmc    *globalSDhost[3];
+#endif
+
+#define rk29_sdmmc_test_and_clear_pending(host, event)		\
+	test_and_clear_bit(event, &host->pending_events)
+#define rk29_sdmmc_set_completed(host, event)			\
+	set_bit(event, &host->completed_events)
+
+#define rk29_sdmmc_set_pending(host, event)				\
+	set_bit(event, &host->pending_events)
+
+static void rk29_sdmmc_start_error(struct rk29_sdmmc *host);
+
 static void rk29_sdmmc_write(unsigned char  __iomem	*regbase, unsigned int regOff,unsigned int val)
 {
 	__raw_writel(val,regbase + regOff);
@@ -190,52 +224,209 @@ static unsigned int rk29_sdmmc_read(unsigned char  __iomem	*regbase, unsigned in
 	return __raw_readl(regbase + regOff);
 }
 
+static int rk29_sdmmc_regs_printk(struct rk29_sdmmc *host)
+{
+	printk("SDMMC_CTRL:   \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CTRL));
+	printk("SDMMC_PWREN:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_PWREN));
+	printk("SDMMC_CLKDIV: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CLKDIV));
+	printk("SDMMC_CLKSRC: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CLKSRC));
+	printk("SDMMC_CLKENA: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CLKENA));
+	printk("SDMMC_TMOUT:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_TMOUT));
+	printk("SDMMC_CTYPE:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CTYPE));
+	printk("SDMMC_BLKSIZ: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_BLKSIZ));
+	printk("SDMMC_BYTCNT: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_BYTCNT));
+	printk("SDMMC_INTMASK:\t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_INTMASK));
+	printk("SDMMC_CMDARG: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CMDARG));
+	printk("SDMMC_CMD:    \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CMD));
+	printk("SDMMC_RESP0:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RESP0));
+	printk("SDMMC_RESP1:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RESP1));
+	printk("SDMMC_RESP2:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RESP2));
+	printk("SDMMC_RESP3:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RESP3));
+	printk("SDMMC_MINTSTS:\t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_MINTSTS));
+	printk("SDMMC_RINTSTS:\t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RINTSTS));
+	printk("SDMMC_STATUS: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_STATUS));
+	printk("SDMMC_FIFOTH: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_FIFOTH));
+	printk("SDMMC_CDETECT:\t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CDETECT));
+	printk("SDMMC_WRTPRT: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_WRTPRT));
+	printk("SDMMC_TCBCNT: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_TCBCNT));
+	printk("SDMMC_TBBCNT: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_TBBCNT));
+	printk("SDMMC_DEBNCE: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_DEBNCE));
+	printk("=======printk %s-register end =========\n", host->dma_name);
+	return 0;
+}
 
-#if defined (CONFIG_DEBUG_FS)
-/*
- * The debugfs stuff below is mostly optimized away when
- * CONFIG_DEBUG_FS is not set.
- */
-static int rk29_sdmmc_req_show(struct seq_file *s, void *v)
+
+#ifdef RK29_SDMMC_NOTIFY_REMOVE_INSERTION
+ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *attr,
+			 const char *buf, size_t count)
 {
-	struct rk29_sdmmc	*host = s->private;
-	struct mmc_request	*mrq;
-	struct mmc_command	*cmd;
-	struct mmc_command	*stop;
-	struct mmc_data		*data;
+    struct rk29_sdmmc	*host = NULL;
+    
+    if( !strncmp(buf,"version" , strlen("version")))
+    {
+        printk("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];
+        if(!host)
+        {
+            printk("%s..%d.. fail to call progress_store because the host is null. ==xbw==\n",__FUNCTION__,__LINE__);
+            goto progress_store_out;
+        }
+    }    
+    else if(  !strncmp(buf,"sdio1-" , strlen("sdio1-")) )
+    {
+        host = (struct rk29_sdmmc	*)globalSDhost[RK29_CTRL_SDIO1_ID];
+        if(!host)
+        {
+            printk("%s..%d.. fail to call progress_store because the host-sdio1 is null. ==xbw==\n",__FUNCTION__,__LINE__);
+            goto progress_store_out;
+        }
+    }
+    else if(  !strncmp(buf,"sdio2-" , strlen("sdio2-")) )
+    {
+        host = (struct rk29_sdmmc	*)globalSDhost[RK29_CTRL_SDIO2_ID];
+        if(!host)
+        {
+            printk("%s..%d.. fail to call progress_store because the host-sdio2 is null. ==xbw==\n",__FUNCTION__,__LINE__);
+            goto progress_store_out;
+        }
+    }
+    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;
+    }
 
-	/* Make sure we get a consistent snapshot */
-	spin_lock(&host->lock);
-	mrq = host->mrq;
+	//printk(".%d.. MMC0 receive the message %s from VOLD.====xbw[%s]====\n", __LINE__, buf, host->dma_name);
+    
+	/*
+     *  //deal with the message
+     *  insert card state-change:  No-Media ==> Pending ==> Idle-Unmounted ==> Checking ==>Mounted
+     *  remove card state-change:  Unmounting ==> Idle-Unmounted ==> No-Media
+    */
+    if(RK29_CTRL_SDMMC_ID == host->pdev->id)
+    {
+        if(!strncmp(buf, "sd-Unmounting", strlen("sd-Unmounting")))
+        {
+           printk(".%d.. MMC0 receive the message State_Unmounting from VOLD.====xbw[%s]====\n", __LINE__, host->dma_name);
+           host->mmc->re_initialized_flags = 0;
+           mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_REMOVAL_DELAY));
+        }
+        else if( !strncmp(buf, "sd-No-Media", strlen("sd-No-Media")))
+        {
+            printk(".%d.. MMC0 receive the message No-Media from VOLD.====xbw[%s]====\n" ,__LINE__, host->dma_name);
+            del_timer_sync(&host->detect_timer);
+            host->mmc->re_initialized_flags = 1;
+
+            if(test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags))
+            {
+                mmc_detect_change(host->mmc, 0);
+            }
+        }
+        else if( !strncmp(buf, "sd-Ready", strlen("sd-Ready")))
+        {
+            printk(".%d.. MMC0 receive the message State_Ready(ReInitFlag=%d) from VOLD.====xbw[%s]====\n" ,\
+								__LINE__, host->mmc->re_initialized_flags, host->dma_name);
+
+						if(0==host->mmc->re_initialized_flags)
+						{
+							host->mmc->re_initialized_flags = 1;            
+							//del_timer_sync(&host->detect_timer);
+						}
+        }
+        else if( !strncmp(buf,"sd-reset" , strlen("sd-reset")) ) 
+        {
+            printk(".%d.. Now manual reset for SDMMC0. ====xbw[%s]====\n",__LINE__, host->dma_name);
+            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);
+        }
 
-	if (mrq) {
-		cmd = mrq->cmd;
-		data = mrq->data;
-		stop = mrq->stop;
+    }
+    else if(RK29_CTRL_SDIO1_ID == host->pdev->id)
+    {
+        if( !strncmp(buf, "sdio1-regs", strlen("sdio1-regs")))
+        {
+            printk(".%d.. Now printk the register of SDMMC1. ====xbw[%s]====\n",__LINE__, host->dma_name); 
+            rk29_sdmmc_regs_printk(host);
+        }
+        else if( !strncmp(buf,"sdio1-reset" , strlen("sdio1-reset")) ) 
+        {
+            printk(".%d.. Now manual reset for SDMMC1. ====xbw[%s]====\n",__LINE__, host->dma_name);
+            mmc_detect_change(host->mmc, 0);           
+        }
+    }
+    else if(RK29_CTRL_SDIO2_ID == host->pdev->id)
+    {
+        if( !strncmp(buf, "sdio2-regs", strlen("sdio2-regs")))
+        {
+            printk(".%d.. Now printk the register of SDMMC2. ====xbw[%s]====\n",__LINE__, host->dma_name); 
+            rk29_sdmmc_regs_printk(host);
+        }
+        else if( !strncmp(buf,"sdio2-reset" , strlen("sdio2-reset")) ) 
+        {
+            printk(".%d.. Now manual reset for SDMMC2. ====xbw[%s]====\n",__LINE__, host->dma_name);
+            mmc_detect_change(host->mmc, 0);           
+        }
+    }
+    
+progress_store_out:
+    spin_unlock(&host->lock);
+    
+    return count;
+}
 
-		if (cmd)
-			seq_printf(s,
-				"CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
-				cmd->opcode, cmd->arg, cmd->flags,
-				cmd->resp[0], cmd->resp[1], cmd->resp[2],
-				cmd->resp[2], cmd->error);
-		if (data)
-			seq_printf(s, "DATA %u / %u * %u flg %x err %d\n",
-				data->bytes_xfered, data->blocks,
-				data->blksz, data->flags, data->error);
-		if (stop)
-			seq_printf(s,
-				"CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
-				stop->opcode, stop->arg, stop->flags,
-				stop->resp[0], stop->resp[1], stop->resp[2],
-				stop->resp[2], stop->error);
-	}
 
-	spin_unlock(&host->lock);
 
-	return 0;
+struct kobj_attribute mmc_reset_attrs = 
+{
+        .attr = {
+                .name = "rescan",
+                .mode = 0777},
+        .show = NULL,
+        .store = rk29_sdmmc_progress_store,
+};
+struct attribute *mmc_attrs[] = 
+{
+        &mmc_reset_attrs.attr,
+        NULL
+};
+
+static struct kobj_type mmc_kset_ktype = {
+	.sysfs_ops	= &kobj_sysfs_ops,
+	.default_attrs = &mmc_attrs[0],
+};
+
+static int rk29_sdmmc_progress_add_attr( struct platform_device *pdev )
+{
+        int result;
+		 struct kobject *parentkobject; 
+        struct kobject * me = kmalloc(sizeof(struct kobject) , GFP_KERNEL );
+        if(!me)
+        {
+            return -ENOMEM;
+        }
+        memset(me ,0,sizeof(struct kobject));
+        kobject_init( me , &mmc_kset_ktype );
+        
+        parentkobject = &pdev->dev.kobj ;
+		result = kobject_add( me , parentkobject->parent->parent->parent,"%s", "sd-sdio" );	
+
+        return result;
 }
+#endif
 
+#if defined (CONFIG_DEBUG_FS)
 static int rk29_sdmmc_regs_show(struct seq_file *s, void *v)
 {
 	struct rk29_sdmmc	*host = s->private;
@@ -269,20 +460,51 @@ static int rk29_sdmmc_regs_show(struct seq_file *s, void *v)
 	return 0;
 }
 
-static int rk29_sdmmc_status_show(struct seq_file *s, void *v)
+
+/*
+ * The debugfs stuff below is mostly optimized away when
+ * CONFIG_DEBUG_FS is not set.
+ */
+static int rk29_sdmmc_req_show(struct seq_file *s, void *v)
 {
 	struct rk29_sdmmc	*host = s->private;
+	struct mmc_request	*mrq;
+	struct mmc_command	*cmd;
+	struct mmc_command	*stop;
+	struct mmc_data		*data;
+
+	/* Make sure we get a consistent snapshot */
+	spin_lock(&host->lock);
+	mrq = host->mrq;
+
+	if (mrq) {
+		cmd = mrq->cmd;
+		data = mrq->data;
+		stop = mrq->stop;
+
+		if (cmd)
+			seq_printf(s,
+				"CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
+				cmd->opcode, cmd->arg, cmd->flags,
+				cmd->resp[0], cmd->resp[1], cmd->resp[2],
+				cmd->resp[2], cmd->error);
+		if (data)
+			seq_printf(s, "DATA %u / %u * %u flg %x err %d\n",
+				data->bytes_xfered, data->blocks,
+				data->blksz, data->flags, data->error);
+		if (stop)
+			seq_printf(s,
+				"CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
+				stop->opcode, stop->arg, stop->flags,
+				stop->resp[0], stop->resp[1], stop->resp[2],
+				stop->resp[2], stop->error);
+	}
 
-	seq_printf(s, "state:   \t\t0x%08x\n", host->state);
-	seq_printf(s, "pending_events:   \t0x%08lx\n", host->pending_events);
-	seq_printf(s, "completed_events:   \t0x%08lx\n", host->completed_events);
-	seq_printf(s, "mrq_status:   \t\t0x%08lx\n", host->mrq_status);
-	seq_printf(s, "old_mrq_status:   \t0x%08lx\n", host->old_mrq_status);
+	spin_unlock(&host->lock);
 
 	return 0;
 }
 
-
 static int rk29_sdmmc_req_open(struct inode *inode, struct file *file)
 {
 	return single_open(file, rk29_sdmmc_req_show, inode->i_private);
@@ -296,6 +518,7 @@ static const struct file_operations rk29_sdmmc_req_fops = {
 	.release	= single_release,
 };
 
+
 static int rk29_sdmmc_regs_open(struct inode *inode, struct file *file)
 {
 	return single_open(file, rk29_sdmmc_regs_show, inode->i_private);
@@ -308,18 +531,6 @@ static const struct file_operations rk29_sdmmc_regs_fops = {
 	.llseek		= seq_lseek,
 	.release	= single_release,
 };
-static int rk29_sdmmc_status_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, rk29_sdmmc_status_show, inode->i_private);
-}
-
-static const struct file_operations rk29_sdmmc_status_fops = {
-	.owner		= THIS_MODULE,
-	.open		= rk29_sdmmc_status_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
 
 static void rk29_sdmmc_init_debugfs(struct rk29_sdmmc *host)
 {
@@ -331,7 +542,10 @@ static void rk29_sdmmc_init_debugfs(struct rk29_sdmmc *host)
 	if (!root)
 		return;
 
-	node = debugfs_create_file("regs", S_IRUSR, root, host,&rk29_sdmmc_regs_fops);
+	node = debugfs_create_file("regs", S_IRUSR, root, host,
+			&rk29_sdmmc_regs_fops);
+	if (IS_ERR(node))
+		return;
 	if (!node)
 		goto err;
 
@@ -339,7 +553,17 @@ static void rk29_sdmmc_init_debugfs(struct rk29_sdmmc *host)
 	if (!node)
 		goto err;
 
-	node = debugfs_create_file("status", S_IRUSR, root, host, &rk29_sdmmc_status_fops);
+	node = debugfs_create_u32("state", S_IRUSR, root, (u32 *)&host->state);
+	if (!node)
+		goto err;
+
+	node = debugfs_create_x32("pending_events", S_IRUSR, root,
+				     (u32 *)&host->pending_events);
+	if (!node)
+		goto err;
+
+	node = debugfs_create_x32("completed_events", S_IRUSR, root,
+				     (u32 *)&host->completed_events);
 	if (!node)
 		goto err;
 
@@ -349,502 +573,1429 @@ err:
 	dev_err(&mmc->class_dev, "failed to initialize debugfs for host\n");
 }
 #endif
-static void rk29_sdmmc_show_info(struct rk29_sdmmc *host)
-{
-	dev_info(host->dev, "state:   \t\t0x%08x\n", host->state);
-	dev_info(host->dev, "pending_events:   \t0x%08lx\n", host->pending_events);
-	dev_info(host->dev, "completed_events:   \t0x%08lx\n", host->completed_events);
-	dev_info(host->dev, "mrq_status:   \t\t0x%08lx\n\n", host->mrq_status);
-	dev_info(host->dev, "old_mrq_status:   \t0x%08lx\n\n", host->old_mrq_status);
-	dev_info(host->dev, "SDMMC_CTRL:   \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CTRL));
-	dev_info(host->dev, "SDMMC_PWREN:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_PWREN));
-	dev_info(host->dev, "SDMMC_CLKDIV: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CLKDIV));
-	dev_info(host->dev, "SDMMC_CLKSRC: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CLKSRC));
-	dev_info(host->dev, "SDMMC_CLKENA: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CLKENA));
-	dev_info(host->dev, "SDMMC_TMOUT:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_TMOUT));
-	dev_info(host->dev, "SDMMC_CTYPE:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CTYPE));
-	dev_info(host->dev, "SDMMC_BLKSIZ: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_BLKSIZ));
-	dev_info(host->dev, "SDMMC_BYTCNT: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_BYTCNT));
-	dev_info(host->dev, "SDMMC_INTMASK:\t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_INTMASK));
-	dev_info(host->dev, "SDMMC_CMDARG: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CMDARG));
-	dev_info(host->dev, "SDMMC_CMD:    \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CMD));
-	dev_info(host->dev, "SDMMC_RESP0:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RESP0));
-	dev_info(host->dev, "SDMMC_RESP1:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RESP1));
-	dev_info(host->dev, "SDMMC_RESP2:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RESP2));
-	dev_info(host->dev, "SDMMC_RESP3:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RESP3));
-	dev_info(host->dev, "SDMMC_MINTSTS:\t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_MINTSTS));
-	dev_info(host->dev, "SDMMC_RINTSTS:\t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RINTSTS));
-	dev_info(host->dev, "SDMMC_STATUS: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_STATUS));
-	dev_info(host->dev, "SDMMC_FIFOTH: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_FIFOTH));
-	dev_info(host->dev, "SDMMC_CDETECT:\t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CDETECT));
-	dev_info(host->dev, "SDMMC_WRTPRT: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_WRTPRT));
-	dev_info(host->dev, "SDMMC_TCBCNT: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_TCBCNT));
-	dev_info(host->dev, "SDMMC_TBBCNT: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_TBBCNT));
-	dev_info(host->dev, "SDMMC_DEBNCE: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_DEBNCE));
-}
-static int rk29_sdmmc_reset_fifo(struct rk29_sdmmc *host)
+
+
+static u32 rk29_sdmmc_prepare_command(struct mmc_command *cmd)
 {
-	int tmo;
-	int retry = RK29_SDMMC_TMO_COUNT;
-	if(!(rk29_sdmmc_read(host->regs, SDMMC_STATUS) & (SDMMC_STAUTS_MC_BUSY|SDMMC_STAUTS_DATA_BUSY)) &&
-		(rk29_sdmmc_read(host->regs, SDMMC_STATUS) & SDMMC_STAUTS_FIFO_EMPTY))
-		return 0;
+	u32		cmdr = cmd->opcode;
 
-	while(retry--) 
+	switch(cmdr)
 	{
-		tmo = RK29_SDMMC_TMO_COUNT;
-		rk29_sdmmc_write(host->regs, SDMMC_CTRL, rk29_sdmmc_read(host->regs, SDMMC_CTRL) | SDMMC_CTRL_FIFO_RESET);
-		while (--tmo && rk29_sdmmc_read(host->regs, SDMMC_CTRL) & SDMMC_CTRL_FIFO_RESET);
-		if(rk29_sdmmc_read(host->regs, SDMMC_STATUS) & (SDMMC_STAUTS_MC_BUSY|SDMMC_STAUTS_DATA_BUSY))
-			udelay(5);
-		else
-			break;
-	}
-	if(retry <= 0){
-		dev_dbg(host->dev, "%s error\n", __func__);
-		return -1;
-	}
-	else
-		return 0;
-}
-static int rk29_sdmmc_reset_ctrl(struct rk29_sdmmc *host)
-{
-	int tmo = RK29_SDMMC_TMO_COUNT;
-	/*
-	if(!(rk29_sdmmc_read(host->regs, SDMMC_STATUS) & (SDMMC_STAUTS_MC_BUSY|SDMMC_STAUTS_DATA_BUSY)))
-		return 0;
-	*/
-	rk29_sdmmc_write(host->regs, SDMMC_CTRL, (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET));
-	while (--tmo && rk29_sdmmc_read(host->regs, SDMMC_CTRL) & (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET));
-	rk29_sdmmc_write(host->regs, SDMMC_CTRL, rk29_sdmmc_read(host->regs, SDMMC_CTRL) | SDMMC_CTRL_INT_ENABLE);
-
-	if(tmo > 0) {
-		rk29_sdmmc_set_mrq_status(host, MRQ_RESET_CTRL_DONE);
-		host->is_init = 1;
-		return 0;
+	    case MMC_GO_IDLE_STATE: 
+            cmdr |= (SDMMC_CMD_INIT | SDMMC_CMD_PRV_DAT_NO_WAIT);
+            break;
+
+        case MMC_STOP_TRANSMISSION:
+            cmdr |= (SDMMC_CMD_STOP | SDMMC_CMD_PRV_DAT_NO_WAIT);
+            break;
+        case MMC_SEND_STATUS:
+        case MMC_GO_INACTIVE_STATE:   
+            cmdr |= SDMMC_CMD_PRV_DAT_NO_WAIT;
+            break;
+
+        default:
+            cmdr |= SDMMC_CMD_PRV_DAT_WAIT;
+            break;
 	}
-	else {
-		rk29_sdmmc_set_mrq_status(host, MRQ_RESET_CTRL_ERR);
-		dev_err(host->dev, "%s error\n", __func__);
-		return -1;
+
+    /* response type */
+	switch(mmc_resp_type(cmd))
+	{
+	    case MMC_RSP_R1:
+        case MMC_RSP_R1B:
+            // case MMC_RSP_R5:  //R5,R6,R7 is same with the R1
+            //case MMC_RSP_R6:
+            // case R6m_TYPE:
+            // case MMC_RSP_R7:
+            cmdr |= (SDMMC_CMD_RESP_CRC | SDMMC_CMD_RESP_SHORT | SDMMC_CMD_RESP_EXP);
+            break;
+        case MMC_RSP_R3:
+            //case MMC_RSP_R4:
+            /* these response not contain crc7, so don't care crc error and response error */
+            cmdr |= (SDMMC_CMD_RESP_NO_CRC | SDMMC_CMD_RESP_SHORT | SDMMC_CMD_RESP_EXP); 
+            break;
+        case MMC_RSP_R2:
+            cmdr |= (SDMMC_CMD_RESP_CRC | SDMMC_CMD_RESP_LONG | SDMMC_CMD_RESP_EXP);
+            break;
+        case MMC_RSP_NONE:
+            cmdr |= (SDMMC_CMD_RESP_CRC_NOCARE | SDMMC_CMD_RESP_NOCARE | SDMMC_CMD_RESP_NO_EXP);  
+            break;
+        default:
+            cmdr |= (SDMMC_CMD_RESP_CRC_NOCARE | SDMMC_CMD_RESP_NOCARE | SDMMC_CMD_RESP_NO_EXP); 
+            break;
 	}
+
+	return cmdr;
 }
 
-static int rk29_sdmmc_start_command(struct rk29_sdmmc *host,
-		struct mmc_command *cmd, u32 cmd_flags)
-{
-	int tmo = RK29_SDMMC_TMO_COUNT;
-	unsigned long flags;
 
-	local_irq_save(flags);
+static int rk29_sdmmc_start_command(struct rk29_sdmmc *host, struct mmc_command *cmd, u32 cmd_flags)
+{
+ 	int tmo = RK29_SDMMC_SEND_START_TIMEOUT;
 	
-	rk29_sdmmc_write(host->regs, SDMMC_CMDARG, cmd->arg); 
-	rk29_sdmmc_write(host->regs, SDMMC_CMD, cmd_flags | SDMMC_CMD_START); 
-	local_irq_restore(flags);
+ 	host->cmd = cmd;
+ 	host->old_cmd = cmd->opcode;
+ 		
+	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
 
-	while (--tmo && rk29_sdmmc_read(host->regs, SDMMC_CMD) & SDMMC_CMD_START)
-		cpu_relax();
-	if(tmo > 0)
-		return 0;
-	else
-		return -1;
-}
 
-static int send_stop_cmd(struct rk29_sdmmc *host)
-{
-	dev_dbg(host->dev,"start cmd:%d ARGR=0x%08x CMDR=0x%08x\n",
-						host->mrq->data->stop->opcode, host->mrq->data->stop->arg, host->stop_cmdr);
-	if(rk29_sdmmc_start_command(host, host->mrq->data->stop, host->stop_cmdr)) {
-		rk29_sdmmc_set_mrq_status(host, MRQ_STOP_START_TMO);
-		return -1;
+    xbwprintk(5, "\n%s..%d..************.start cmd=%d, arg=0x%x ********=====xbw[%s]=======\n", \
+			__FUNCTION__, __LINE__, cmd->opcode, cmd->arg, host->dma_name);
+
+	/* wait until CIU accepts the command */
+	while (--tmo && (rk29_sdmmc_read(host->regs, SDMMC_CMD) & SDMMC_CMD_START))
+	{
+		cpu_relax();
 	}
-	else {
-		rk29_sdmmc_set_mrq_status(host, MRQ_STOP_START_DONE);
-		return 0;
+	
+	if(!tmo)
+	{
+		printk("%s..%d..  wait for CMD_START timeout!!!!!======xbw[%s]======\n",\
+				__FUNCTION__,__LINE__, host->dma_name);
+
+		cmd->error = -ETIMEDOUT;
+		host->mrq->cmd->error = -ETIMEDOUT;
+		del_timer_sync(&host->request_timer);
+		
+		host->errorstep = 0x1;
+		return SDM_WAIT_FOR_CMDSTART_TIMEOUT;
 	}
-}
-static void rk29_sdmmc_dma_cleanup(struct rk29_sdmmc *host)
-{
-	struct mmc_data	*data = host->mrq->data;
-	if (data) 
-		dma_unmap_sg(host->dev, data->sg, data->sg_len,
-		     ((data->flags & MMC_DATA_WRITE)
-		      ? DMA_TO_DEVICE : DMA_FROM_DEVICE));		      	
+
+	return SDM_SUCCESS;
 }
 
-static void rk29_sdmmc_stop_dma(struct rk29_sdmmc *host)
+static int rk29_sdmmc_reset_fifo(struct rk29_sdmmc *host)
 {
-	int ret = 0;
-	rk29_sdmmc_set_mrq_status(host, MRQ_STOP_DMA);
-	rk29_sdmmc_dma_cleanup(host);
-	ret = rk29_dma_ctrl(host->dma_info.chn,RK29_DMAOP_STOP);
-	if(ret < 0)
-			dev_err(host->dev, "stop dma:rk29_dma_ctrl stop error\n");
-	ret = rk29_dma_ctrl(host->dma_info.chn,RK29_DMAOP_FLUSH);
-	if(ret < 0)
-			dev_err(host->dev, "stop dma:rk29_dma_ctrl flush error\n");
-	rk29_sdmmc_write(host->regs, SDMMC_CTRL, 
-			(rk29_sdmmc_read(host->regs, SDMMC_CTRL))&(~SDMMC_CTRL_DMA_ENABLE));
+    u32     value;
+	int     timeout;
+	int     ret = SDM_SUCCESS;
+	
+    value = rk29_sdmmc_read(host->regs, SDMMC_STATUS);
+    if (!(value & SDMMC_STAUTS_FIFO_EMPTY))
+    {
+        value = rk29_sdmmc_read(host->regs, SDMMC_CTRL);
+        value |= SDMMC_CTRL_FIFO_RESET;
+        rk29_sdmmc_write(host->regs, SDMMC_CTRL, value);
+
+        timeout = 1000;
+        while (((value = rk29_sdmmc_read(host->regs, SDMMC_CTRL)) & (SDMMC_CTRL_FIFO_RESET)) && (timeout > 0))
+        {
+            udelay(1);
+            timeout--;
+        }
+        if (timeout == 0)
+        {
+            host->errorstep = 0x2;
+            ret = SDM_WAIT_FOR_FIFORESET_TIMEOUT;
+        }
+    }
+    
+	return ret;
+	
 }
 
-static void rk29_sdmmc_request_done(struct rk29_sdmmc *host,struct mmc_request	*mrq)
+static int rk29_sdmmc_wait_unbusy(struct rk29_sdmmc *host)
 {
-	int tmo = RK29_SDMMC_TMO_COUNT;
+	int time_out = 250000; //max is 250ms
 
-	spin_unlock(&host->lock);
-	rk29_sdmmc_write(host->regs, SDMMC_RINTSTS, ~SDMMC_INT_SDIO);
-	rk29_sdmmc_write(host->regs, SDMMC_INTMASK,
-		rk29_sdmmc_read(host->regs, SDMMC_INTMASK) & 
-		~(SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | RK29_SDMMC_ERROR_FLAGS));
-
-	if(!rk29_sdmmc_test_mrq_status(host, MRQ_STOP_DMA) && 
-		rk29_sdmmc_test_mrq_status(host, MRQ_START_DMA))
-		rk29_sdmmc_stop_dma(host);
-	if(mrq->stop && !rk29_sdmmc_test_mrq_status(host, MRQ_STOP_START_DONE))
-		send_stop_cmd(host);
-	if(mrq->cmd->opcode == 17 && (host->data_intsts & SDMMC_INT_SBE)){
-		rk29_sdmmc_write(host->regs, SDMMC_CMD, 12|SDMMC_CMD_STOP | SDMMC_CMD_START); 
-		while (--tmo && rk29_sdmmc_read(host->regs, SDMMC_CMD) & SDMMC_CMD_START);
-	}
-	if(rk29_sdmmc_read(host->regs, SDMMC_STATUS) & SDMMC_STAUTS_FIFO_FULL ){
-		rk29_sdmmc_read(host->regs, SDMMC_DATA);
-		rk29_sdmmc_read(host->regs, SDMMC_DATA);
+	while (rk29_sdmmc_read(host->regs, SDMMC_STATUS) & SDMMC_STAUTS_DATA_BUSY) 
+	{
+		udelay(1);
+		time_out--;
+
+		if(time_out == 0)
+		{
+		    host->errorstep = 0x3;
+		    return SDM_BUSY_TIMEOUT;
+		}
 	}
-	//if(mrq->data && mrq->data->error)
-		rk29_sdmmc_reset_fifo(host);
-	
-	host->mrq = NULL;
-	host->state = STATE_IDLE;
-	rk29_sdmmc_set_mrq_status(host, MRQ_REQUEST_DONE);
-	mmc_request_done(host->mmc, mrq);
-	del_timer(&host->monitor_timer);
-	
-	spin_lock(&host->lock);
+
+	return SDM_SUCCESS;
 }
 
-static int sdmmc_send_cmd(struct rk29_sdmmc *host, unsigned int cmd, int arg)
+static void send_stop_cmd(struct rk29_sdmmc *host)
 {
-	int tmo = RK29_SDMMC_TMO_COUNT;
-	rk29_sdmmc_write(host->regs, SDMMC_CMDARG, arg);
-	rk29_sdmmc_write(host->regs, SDMMC_CMD, SDMMC_CMD_START | cmd);		
-	while (--tmo && readl(host->regs + SDMMC_CMD) & SDMMC_CMD_START);
-	if(tmo > 0)
-		return 0;
-	else
-		return -1;
+    mod_timer(&host->request_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_SEND_START_TIMEOUT+2500));
+		
+    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 = host->cmd->retries;
+    
+    host->cmdr = rk29_sdmmc_prepare_command(&host->stopcmd);
+    rk29_sdmmc_start_command(host, &host->stopcmd, host->cmdr);    
 }
 
-int rk29_sdmmc_set_clock(struct rk29_sdmmc *host)
+static void rk29_sdmmc_dma_cleanup(struct rk29_sdmmc *host)
 {
-	unsigned int div;
-	if(!host->ios_clock)
-		return 0;
-	div  = (((host->bus_hz + (host->bus_hz / 5)) / host->ios_clock)) >> 1;
-/*
-	if(div == 0)
-		div = 1;
-*/
-	if(host->div == div)
-		return 0;
-	
-	rk29_sdmmc_write(host->regs, SDMMC_CLKENA, 0);
-	rk29_sdmmc_write(host->regs, SDMMC_CLKSRC,0);
-	if(sdmmc_send_cmd(host, SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0))
-		goto send_cmd_err;
-	rk29_sdmmc_write(host->regs, SDMMC_CLKDIV, div);
-	host->div = div;
-	host->clock = (div == 0)? host->bus_hz :(host->bus_hz / div) >> 1;
-	if(sdmmc_send_cmd(host, SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0))
-		goto send_cmd_err;
-	rk29_sdmmc_write(host->regs, SDMMC_CLKENA, SDMMC_CLKEN_ENABLE);
-	if(sdmmc_send_cmd(host, SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0))
-		goto send_cmd_err;
-
-	rk29_sdmmc_set_mrq_status(host, MRQ_CLK_START_DONE);
-	return 0;
-send_cmd_err:
-	rk29_sdmmc_set_mrq_status(host, MRQ_CLK_START_TMO);
-	return -1;	
+	if (host->data) 
+	{
+		dma_unmap_sg(&host->pdev->dev, host->data->sg, host->data->sg_len,
+		     ((host->data->flags & MMC_DATA_WRITE)
+		      ? DMA_TO_DEVICE : DMA_FROM_DEVICE));		
+    }
 }
 
-static void rk29_sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+static void rk29_sdmmc_stop_dma(struct rk29_sdmmc *host)
 {
-	struct rk29_sdmmc *host = mmc_priv(mmc);;
-
+    int ret = 0;
+    
+	if(host->use_dma == 0)
+		return;
+		
+	if (host->dma_info.chn> 0) 
+	{
+		rk29_sdmmc_dma_cleanup(host); 
+		
+		ret = rk29_dma_ctrl(host->dma_info.chn,RK29_DMAOP_STOP);
+		if(ret < 0)
+		{
+            printk("%s..%d...rk29_dma_ctrl STOP error!===xbw[%s]====\n", __FUNCTION__, __LINE__, host->dma_name);
+            host->errorstep = 0x95;
+            return;
+		}
 
-	switch (ios->bus_width) {
-	case MMC_BUS_WIDTH_1:
-		rk29_sdmmc_write(host->regs, SDMMC_CTYPE, 0);
-		break;
-	case MMC_BUS_WIDTH_4:
-		rk29_sdmmc_write(host->regs, SDMMC_CTYPE, SDMMC_CTYPE_4BIT);
-		break;
-	}
-	host->ios_clock = ios->clock;
-	
-	switch (ios->power_mode) {
-	case MMC_POWER_UP:
-		host->is_init = 1;
-		rk29_sdmmc_write(host->regs, SDMMC_PWREN, 1);
-		break;
-	default:
-		break;
+		ret = rk29_dma_ctrl(host->dma_info.chn,RK29_DMAOP_FLUSH);
+		if(ret < 0)
+		{
+            printk("%s..%d...rk29_dma_ctrl FLUSH error!===xbw[%s]====\n", __FUNCTION__, __LINE__, host->dma_name);
+            host->errorstep = 0x96;
+            return;
+		}
+		
+	} 
+	else 
+	{
+		/* Data transfer was stopped by the interrupt handler */
+		rk29_sdmmc_set_pending(host, EVENT_DATA_COMPLETE);
 	}
 }
 
-static int rk29_sdmmc_get_ro(struct mmc_host *mmc)
+static void rk29_sdmmc_control_host_dma(struct rk29_sdmmc *host, bool enable)
 {
-	struct rk29_sdmmc *host = mmc_priv(mmc);
-	u32 wrtprt = rk29_sdmmc_read(host->regs, SDMMC_WRTPRT);
+    u32 value = rk29_sdmmc_read(host->regs, SDMMC_CTRL);
 
-	return (wrtprt & SDMMC_WRITE_PROTECT)?1:0;
+    if (enable)
+    {
+        value |= SDMMC_CTRL_DMA_ENABLE;
+    }
+    else
+    {
+        value &= ~(SDMMC_CTRL_DMA_ENABLE);
+    }
+
+    rk29_sdmmc_write(host->regs, SDMMC_CTRL, value);
 }
 
 
-static int rk29_sdmmc_get_cd(struct mmc_host *mmc)
+/* 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) 
 {
-	struct rk29_sdmmc *host = mmc_priv(mmc);
+	struct rk29_sdmmc	*host = arg;
 
-	if(host->is_sdio)
-		return host->get_wifi_cd(mmc_dev(host->mmc));
-	else if(host->gpio_det == INVALID_GPIO)
-		return 1;
-	else
-		return gpio_get_value(host->gpio_det)?0:1;
+	if(host->use_dma == 0)
+		return;
+
+	host->intInfo.transLen = host->intInfo.desLen;	
 }
 
-static inline unsigned ns_to_clocks(unsigned clkrate, unsigned ns)
+static int rk29_sdmmc_submit_data_dma(struct rk29_sdmmc *host, struct mmc_data *data)
 {
-	u32 clks;
-	if (clkrate > 1000000)
-		clks =  (ns * (clkrate / 1000000) + 999) / 1000;
+	struct scatterlist		*sg;
+	unsigned int			i,direction, sgDirection;
+	int ret, dma_len=0;
+	
+	if(host->use_dma == 0)
+	{
+	    printk("%s..%d...setup DMA fail!!!!!!. host->use_dma=0 ===xbw=[%s]====\n", __FUNCTION__, __LINE__, host->dma_name);
+	    host->errorstep = 0x4;
+		return -ENOSYS;
+	}
+	/* If we don't have a channel, we can't do DMA */
+	if (host->dma_info.chn < 0)
+	{
+	    printk("%s..%d...setup DMA fail!!!!!!!. dma_info.chn < 0  ===xbw[%s]====\n", __FUNCTION__, __LINE__, host->dma_name);
+	    host->errorstep = 0x5;
+		return -ENODEV;
+	}
+
+	if (data->blksz & 3)
+		return -EINVAL;
+	for_each_sg(data->sg, sg, data->sg_len, i) 
+	{
+		if (sg->offset & 3 || sg->length & 3)
+		{
+		    printk("%s..%d...call for_each_sg() fail !!===xbw[%s]====\n", __FUNCTION__, __LINE__, host->dma_name);
+		    host->errorstep = 0x7;
+			return -EINVAL;
+		}
+	}
+	if (data->flags & MMC_DATA_READ)
+	{
+		direction = RK29_DMASRC_HW;  
+		sgDirection = DMA_FROM_DEVICE; 
+	}
 	else
-		clks =  ((ns/1000) * (clkrate / 1000) + 999) / 1000;
+	{
+		direction = RK29_DMASRC_MEM;
+		sgDirection = DMA_TO_DEVICE;
+	}
+
+	ret = rk29_dma_ctrl(host->dma_info.chn,RK29_DMAOP_STOP);
+	if(ret < 0)
+	{
+	    printk("%s..%d...rk29_dma_ctrl stop error!===xbw[%s]====\n", __FUNCTION__, __LINE__, host->dma_name);
+	    host->errorstep = 0x91;
+		return -ENOSYS;
+	}
+	
+	ret = rk29_dma_ctrl(host->dma_info.chn,RK29_DMAOP_FLUSH);	
+	if(ret < 0)
+	{
+        printk("%s..%d...rk29_dma_ctrl flush error!===xbw[%s]====\n", __FUNCTION__, __LINE__, host->dma_name);
+        host->errorstep = 0x91;
+        return -ENOSYS;
+	}
+
+	
+    ret = rk29_dma_devconfig(host->dma_info.chn, direction, (unsigned long )(host->dma_addr));
+    if(0 != ret)
+    {
+        printk("%s..%d...call rk29_dma_devconfig() fail !!!!===xbw=[%s]====\n", __FUNCTION__, __LINE__, host->dma_name);
+        host->errorstep = 0x8;
+        return -ENOSYS;
+    }
+    
+	dma_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, sgDirection);						                	   
+	for (i = 0; i < dma_len; i++)
+	{
+    	ret = rk29_dma_enqueue(host->dma_info.chn, host, sg_dma_address(&data->sg[i]),sg_dma_len(&data->sg[i]));
+    	if(ret < 0)
+    	{
+            printk("%s..%d...call rk29_dma_devconfig() fail !!!!===xbw=[%s]====\n", __FUNCTION__, __LINE__, host->dma_name);
+            host->errorstep = 0x93;
+            return -ENOSYS;
+    	}
+    }
+    	
+	rk29_sdmmc_control_host_dma(host, TRUE);// enable dma
+	ret = rk29_dma_ctrl(host->dma_info.chn, RK29_DMAOP_START);
+	if(ret < 0)
+	{
+        printk("%s..%d...rk29_dma_ctrl start error!===xbw[%s]====\n", __FUNCTION__, __LINE__, host->dma_name);
+        host->errorstep = 0x94;
+        return -ENOSYS;
+	}
+	
+	return 0;
+}
 
-	return clks;
+
+static int rk29_sdmmc_prepare_write_data(struct rk29_sdmmc *host, struct mmc_data *data)
+{
+    //uint32 value;
+    int     output;
+    u32    i = 0;
+    u32     dataLen;
+    u32     count, *pBuf = (u32 *)host->pbuf;
+
+    output = SDM_SUCCESS;
+    dataLen = data->blocks*data->blksz;
+    
+    host->dodma = 0; //DMA still no request;
+ 
+    //SDMMC controller request the data is multiple of 4.
+    count = (dataLen >> 2) + ((dataLen & 0x3) ? 1:0);
+
+    if (count <= FIFO_DEPTH)
+    {
+        for (i=0; i<count; i++)
+        {
+            rk29_sdmmc_write(host->regs, SDMMC_DATA, pBuf[i]);
+        }
+    }
+    else
+    {
+        host->intInfo.desLen = count;
+        host->intInfo.transLen = 0;
+        host->intInfo.pBuf = (u32 *)pBuf;
+        
+        if(0)//(host->intInfo.desLen <= 512 ) 
+        {  
+            //ʹÓÃpioģʽ           
+            return SDM_SUCCESS;
+        } 
+        else 
+        {
+            xbwprintk(3, "%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);
+        	    
+				host->errorstep = 0x81;
+
+        		rk29_sdmmc_control_host_dma(host, FALSE); 
+    		}
+    		else
+    		{
+    		    host->dodma = 1;
+    		}
+        }
+       
+    }
+
+    return output;
 }
 
-static void rk29_sdmmc_set_timeout(struct rk29_sdmmc *host,struct mmc_data *data)
+
+
+
+static int rk29_sdmmc_prepare_read_data(struct rk29_sdmmc *host, struct mmc_data *data)
 {
-	unsigned timeout;
-	unsigned int clock;
-	
-	if(host->div == -1)
-		return;
-	else if(host->div == 0)
-		clock = host->bus_hz;
-	else
-		clock = (host->bus_hz / host->div) >> 1;
-	timeout = ns_to_clocks(clock, data->timeout_ns) + data->timeout_clks;
-	rk29_sdmmc_write(host->regs, SDMMC_TMOUT, 0xffffffff);
-	//rk29_sdmmc_write(host->regs, SDMMC_TMOUT, (timeout << 8) | (70));
+    u32  count = 0;
+    u32  dataLen;
+    int   output;
+
+    output = SDM_SUCCESS;
+    dataLen = data->blocks*data->blksz;
+    
+    host->dodma = 0;//DMA still no request;
+
+    //SDMMC controller request the data is multiple of 4.
+    count = (dataLen >> 2) ;//+ ((dataLen & 0x3) ? 1:0);
+
+    host->intInfo.desLen = (dataLen >> 2);
+    host->intInfo.transLen = 0;
+    host->intInfo.pBuf = (u32 *)host->pbuf;
+       
+    if (count > (RX_WMARK+1))  //datasheet error.actually, it can nont waken the interrupt when less and equal than RX_WMARK+1
+    {
+        if(0) //(host->intInfo.desLen <= 512 )
+        {
+            //ʹÓÃpioģʽ
+            return SDM_SUCCESS;
+        }        
+        else 
+        {
+            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);
+
+        	    host->errorstep = 0x82;
+
+        		rk29_sdmmc_control_host_dma(host, FALSE); 
+    		}
+    		else
+    		{
+    		    host->dodma = 1;
+    		}
+        }
+    }
+
+    return output;
 }
-static u32 rk29_sdmmc_prepare_command(struct mmc_host *mmc,
-				 struct mmc_command *cmd)
+
+
+
+static int rk29_sdmmc_read_remain_data(struct rk29_sdmmc *host, u32 originalLen, void *pDataBuf)
 {
-	struct mmc_data	*data;
-	u32		cmdr;
-	
-	cmd->error = -EINPROGRESS;
-	cmdr = cmd->opcode;
+    u32  value = 0;
+
+    u32     i = 0;
+    u32     *pBuf = (u32 *)pDataBuf;
+    u8      *pByteBuf = (u8 *)pDataBuf;
+    u32     lastData = 0;
+
+    //SDMMC controller must be multiple of 32. so if transfer 13, then actuall we should write or read 16 byte.
+    u32  count = (originalLen >> 2) + ((originalLen & 0x3) ? 1:0);
+
+    if(1 == host->dodma)
+    {
+        //when use DMA, there are remain data only when datalen/4 less than  RX_WMARK+1 same as equaltion. or not multiple of 4
+        if (!((value = rk29_sdmmc_read(host->regs, SDMMC_STATUS)) & SDMMC_STAUTS_FIFO_EMPTY))
+        {
+            if (count <= (RX_WMARK+1))
+            {
+                i = 0;
+                while ((i<(originalLen >> 2))&&(!(value & SDMMC_STAUTS_FIFO_EMPTY)))
+                {
+                    pBuf[i++] = rk29_sdmmc_read(host->regs, SDMMC_DATA);
+                    value = rk29_sdmmc_read(host->regs, SDMMC_STATUS);
+                }
+            }
+
+            if (count > (originalLen >> 2))
+            {
+                lastData = rk29_sdmmc_read(host->regs, SDMMC_DATA);
+
+                //fill the 1 to 3 byte.
+                for (i=0; i<(originalLen & 0x3); i++)
+                {
+                    pByteBuf[(originalLen & 0xFFFFFFFC) + i] = (u8)((lastData >> (i << 3)) & 0xFF); //default little-endian
+                }
+            }
+        }
+    }
+    else
+    {
+        if (!((value = rk29_sdmmc_read(host->regs, SDMMC_STATUS)) & SDMMC_STAUTS_FIFO_EMPTY))
+        {
+             while ( (host->intInfo.transLen < host->intInfo.desLen)  && (!(value & SDMMC_STAUTS_FIFO_EMPTY)) )
+            {
+                pBuf[host->intInfo.transLen++] = rk29_sdmmc_read(host->regs, SDMMC_DATA);  
+                value = rk29_sdmmc_read(host->regs, SDMMC_STATUS);  
+            }
+
+            if (count > (originalLen >> 2))
+            {
+                lastData = rk29_sdmmc_read(host->regs, SDMMC_DATA); 
+
+                //fill the 1 to 3 byte.
+                for (i=0; i<(originalLen & 0x3); i++)
+                {
+                    pByteBuf[(originalLen & 0xFFFFFFFC) + i] = (u8)((lastData >> (i << 3)) & 0xFF);  //default little-endian
+                }
+            }
+        }
+    }
+    
+    return SDM_SUCCESS;
+}
 
-	if(cmdr == 12) 
-		cmdr |= SDMMC_CMD_STOP;
-	else if(cmdr == 13) 
-		cmdr &= ~SDMMC_CMD_PRV_DAT_WAIT;
-	else 
-		cmdr |= SDMMC_CMD_PRV_DAT_WAIT;
 
-	if (cmd->flags & MMC_RSP_PRESENT) {
-		cmdr |= SDMMC_CMD_RESP_EXP; // expect the respond, need to set this bit
-		if (cmd->flags & MMC_RSP_136) 
-			cmdr |= SDMMC_CMD_RESP_LONG; // expect long respond
+static void rk29_sdmmc_do_pio_read(struct rk29_sdmmc *host)
+{
+    int i;
+    for (i=0; i<(RX_WMARK+1); i++)
+    {
+        host->intInfo.pBuf[host->intInfo.transLen + i] = rk29_sdmmc_read(host->regs, SDMMC_DATA);
+    }
+    host->intInfo.transLen += (RX_WMARK+1);
+}
+
+static void rk29_sdmmc_do_pio_write(struct rk29_sdmmc *host)
+{
+    int i;
+    if ( (host->intInfo.desLen - host->intInfo.transLen) > (FIFO_DEPTH - TX_WMARK) )
+    {
+        for (i=0; i<(FIFO_DEPTH - TX_WMARK); i++)
+        {
+            rk29_sdmmc_write(host->regs, SDMMC_DATA, host->intInfo.pBuf[host->intInfo.transLen + i]);
+        }
+        host->intInfo.transLen += (FIFO_DEPTH - TX_WMARK);
+    }
+    else
+    {
+        for (i=0; i<(host->intInfo.desLen - host->intInfo.transLen); i++)
+        {
+            rk29_sdmmc_write(host->regs, SDMMC_DATA, host->intInfo.pBuf[host->intInfo.transLen + i]);
+        }
+        host->intInfo.transLen =  host->intInfo.desLen;
+    }
+      
+}
+
+
+static void rk29_sdmmc_submit_data(struct rk29_sdmmc *host, struct mmc_data *data)
+{
+    int ret;
+    
+    if(data)
+    {
+        host->data = data;
+        data->error = 0;
+
+        data->bytes_xfered = 0;
+        host->pbuf = (u32*)sg_virt(data->sg);
+
+        if (data->flags & MMC_DATA_STREAM)
+		{
+			host->cmdr |= SDMMC_CMD_STRM_MODE;    //set stream mode
+		}
+		else
+		{
+		    host->cmdr |= SDMMC_CMD_BLOCK_MODE;   //set block mode
+		}
 		
-		if(cmd->flags & MMC_RSP_CRC) 
-			cmdr |= SDMMC_CMD_RESP_CRC;
+        //set the blocks and blocksize
+		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);
+            
+		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", \
+					__FUNCTION__, __LINE__, data->blksz*data->blocks, host->dma_name);
+		    
+			ret = rk29_sdmmc_prepare_write_data(host, data);
+	    }
+	    else
+	    {
+	        host->cmdr |= (SDMMC_CMD_DAT_READ | SDMMC_CMD_DAT_EXP);
+            xbwprintk(3, "%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);
+	    }
+
+    }
+    else
+    {
+        rk29_sdmmc_write(host->regs, SDMMC_BLKSIZ, 0);
+        rk29_sdmmc_write(host->regs, SDMMC_BYTCNT, 0);
+    }
+}
+
+
+static int sdmmc_send_cmd_start(struct rk29_sdmmc *host, unsigned int cmd)
+{
+	int tmo = 1000;
+	
+	rk29_sdmmc_write(host->regs, SDMMC_CMD, SDMMC_CMD_START | cmd);		
+	while (--tmo && readl(host->regs + SDMMC_CMD) & SDMMC_CMD_START)
+	{
+	    cpu_relax();
 	}
+	
+	if(!tmo) 
+	{
+		printk("%s.. %d   set cmd(value=0x%x) register timeout error !   ====xbw[%s]====\n",\
+				__FUNCTION__,__LINE__, cmd, host->dma_name);
 
-	data = cmd->data;
-	if (data) {
-		cmdr |= SDMMC_CMD_DAT_EXP;
-		if (data->flags & MMC_DATA_STREAM) 
-			cmdr |= SDMMC_CMD_STRM_MODE; //  set stream mode
-		if (data->flags & MMC_DATA_WRITE) 
-		    cmdr |= SDMMC_CMD_DAT_WR;
+		host->errorstep = 0x9;
+		return SDM_START_CMD_FAIL;
 	}
-	return cmdr;
+
+	return SDM_SUCCESS;
 }
-static int rk29_sdmmc_submit_data(struct rk29_sdmmc *host, struct mmc_data *data)
+
+static int rk29_sdmmc_get_cd(struct mmc_host *mmc)
 {
-	struct scatterlist		*sg;
-	unsigned int			i,direction;
-	int dma_len=0, ret = 0;
+	struct rk29_sdmmc *host = mmc_priv(mmc);
+	u32 cdetect;
 
-	if (data->blksz & 3){
-		dev_info(host->dev, "data->blksz = %d\n", data->blksz);
-		return -EINVAL;
-	}
-	for_each_sg(data->sg, sg, data->sg_len, i) {
-		if (sg->offset & 3 || sg->length & 3){
-			dev_info(host->dev, "sg->offset = %d, sg->length = %d\n",
-				sg->offset, sg->length);
-			return -EINVAL;
+#ifdef CONFIG_PM
+	if(host->gpio_det == INVALID_GPIO)
+		return 1;
+#endif
+
+	cdetect = rk29_sdmmc_read(host->regs, SDMMC_CDETECT);
+
+	return (cdetect & SDMMC_CARD_DETECT_N)?0:1;
+}
+
+
+/****************************************************************/
+//reset the SDMMC controller of the current host
+/****************************************************************/
+int rk29_sdmmc_reset_controller(struct rk29_sdmmc *host)
+{
+    u32  value = 0;
+    int  timeOut = 0;
+
+    rk29_sdmmc_write(host->regs, SDMMC_PWREN, POWER_ENABLE);
+
+    /* reset SDMMC IP */
+    //SDPAM_SDCClkEnable(host, TRUE);
+
+    //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 */
+    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))
+    {
+        udelay(1);
+        timeOut--;
+        value = rk29_sdmmc_read(host->regs, SDMMC_CTRL);
+    }
+
+    if (timeOut == 0)
+    {
+        printk("%s..%s..%d..  reset controller fail!!! =====xbw[%s]=====\n",\
+				__FILE__, __FUNCTION__,__LINE__, host->dma_name);
+
+        host->errorstep = 0x0A;
+        return SDM_WAIT_FOR_FIFORESET_TIMEOUT;
+    }
+
+     /* FIFO threshold settings  */
+  	rk29_sdmmc_write(host->regs, SDMMC_FIFOTH, (SD_MSIZE_16 | (RX_WMARK << RX_WMARK_SHIFT) | (TX_WMARK << TX_WMARK_SHIFT)));
+  	
+    rk29_sdmmc_write(host->regs, SDMMC_CTYPE, SDMMC_CTYPE_1BIT);
+    rk29_sdmmc_write(host->regs, SDMMC_CLKSRC, CLK_DIV_SRC_0);
+    /* config debounce */
+    host->bus_hz = clk_get_rate(host->clk);
+    if((host->bus_hz > 52000000) || (host->bus_hz <= 0))
+    {
+        printk("%s..%s..%d..****Error!!!!!!  Bus clock %d hz is beyond the prescribed limits ====xbw[%s]===\n",\
+            __FILE__, __FUNCTION__,__LINE__,host->bus_hz, host->dma_name);
+        
+		host->errorstep = 0x0B;            
+        return SDM_PARAM_ERROR;            
+    }
+
+    rk29_sdmmc_write(host->regs, SDMMC_DEBNCE, (DEBOUNCE_TIME*host->bus_hz)&0xFFFFFF);
+
+    /* config interrupt */
+    rk29_sdmmc_write(host->regs, SDMMC_RINTSTS, 0xFFFFFFFF);
+
+    if(host->use_dma)
+    {
+        if(0 == host->pdev->id)
+        {
+		    rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEDMA);
+		}
+		else
+		{
+		    rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEDMA | SDMMC_INT_SDIO);
 		}
 	}
-	if (data->flags & MMC_DATA_READ)
-		direction = RK29_DMASRC_HW;  
 	else
-		direction = RK29_DMASRC_MEM;  
+	{
+		if(0 == host->pdev->id)
+        {
+		    rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEIO);
+		}
+		else
+		{
+		    rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEIO | SDMMC_INT_SDIO);
+		}		
+    }
+
+	rk29_sdmmc_write(host->regs, SDMMC_PWREN, POWER_ENABLE);
 	
-	ret = rk29_dma_ctrl(host->dma_info.chn,RK29_DMAOP_STOP);
-	if(ret < 0)
-			dev_err(host->dev, "rk29_dma_ctrl stop error\n");
-	ret = rk29_dma_ctrl(host->dma_info.chn,RK29_DMAOP_FLUSH);	
-	if(ret < 0)
-			dev_err(host->dev, "rk29_dma_ctrl flush error\n");
-    ret = rk29_dma_devconfig(host->dma_info.chn, direction, (unsigned long )(host->dma_addr));
-	if(ret < 0)
-			dev_err(host->dev, "rk29_dma_devconfig error\n");
-	dma_len = dma_map_sg(host->dev, data->sg, data->sg_len, 
-			(data->flags & MMC_DATA_READ)? DMA_FROM_DEVICE : DMA_TO_DEVICE);						                	   
-	for (i = 0; i < dma_len; i++) {                             
-    	ret = rk29_dma_enqueue(host->dma_info.chn, host, sg_dma_address(&data->sg[i]),sg_dma_len(&data->sg[i]));  // data->sg->dma_address, data->sg->length);	    	
-		if(ret < 0)
-			dev_err(host->dev, "rk29 dma enqueue error\n");
+   	rk29_sdmmc_write(host->regs, SDMMC_CTRL,SDMMC_CTRL_INT_ENABLE); // enable mci interrupt
+
+    return SDM_SUCCESS;
+}
+
+
+
+
+//enable/disnable the clk.
+static int rk29_sdmmc_control_clock(struct rk29_sdmmc *host, bool enable)
+{
+    u32           value = 0;
+    int           tmo = 0;
+    int           ret = SDM_SUCCESS;
+
+    //wait previous start to clear
+    tmo = 1000;
+	while (--tmo && (rk29_sdmmc_read(host->regs, SDMMC_CMD) & SDMMC_CMD_START))
+	{
+		cpu_relax();
 	}
-	rk29_sdmmc_write(host->regs, SDMMC_CTRL, (rk29_sdmmc_read(host->regs, SDMMC_CTRL))|SDMMC_CTRL_DMA_ENABLE);// enable dma
-	ret = rk29_dma_ctrl(host->dma_info.chn, RK29_DMAOP_START);
-	if(ret < 0)
-			dev_err(host->dev, "rk29_dma_ctrl start error\n");
-	rk29_sdmmc_set_mrq_status(host, MRQ_START_DMA);
+	if(!tmo)
+	{
+	    host->errorstep = 0x0C;
+	    ret = SDM_START_CMD_FAIL;
+		goto Error_exit;	
+    }
+
+    if(RK29_CTRL_SDMMC_ID == host->pdev->id)
+    { 
+        //SDMMC use low-power mode
+        if (enable)
+        {
+            value = (SDMMC_CLKEN_LOW_PWR | SDMMC_CLKEN_ENABLE);
+        }
+        else
+        {
+            value = (SDMMC_CLKEN_LOW_PWR | SDMMC_CLKEN_DISABLE);
+        }
+    }
+    else
+    {
+        //SDIO-card use non-low-power mode
+        if (enable)
+        {
+            value = (SDMMC_CLKEN_ENABLE);
+        }
+        else
+        {
+            value = (SDMMC_CLKEN_DISABLE);
+        }
+    }
+  
+    rk29_sdmmc_write(host->regs, SDMMC_CLKENA, value);
+
+	/* inform CIU */
+	ret = sdmmc_send_cmd_start(host, SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT);
+    if(ret != SDM_SUCCESS)
+    {
+        goto Error_exit;
+    }
+
+    return SDM_SUCCESS;
+
+Error_exit:
+    printk("\n%s....%d..  control clock fail!!! Enable=%d, ret=%d ===xbw[%s]====\n",\
+			__FILE__,__LINE__,enable,ret, host->dma_name);
+
+    return ret;
+    
+}
+
+
+//adjust the frequency.ie, to set the frequency division control
+int rk29_sdmmc_change_clk_div(struct rk29_sdmmc *host, u32 freqHz)
+{
+    u32 div;
+    u32 tmo;
+    int ret = SDM_SUCCESS;
+
+    if(0 == freqHz)
+    {
+        ret =  SDM_PARAM_ERROR;
+        goto  SetFreq_error;
+    }
+
+    ret = rk29_sdmmc_control_clock(host, FALSE);
+    if (ret != SDM_SUCCESS)
+    {
+        goto SetFreq_error;
+    }
+
+     
+    host->bus_hz = clk_get_rate(host->clk);
+    if((host->bus_hz > 52000000) || (host->bus_hz <= 0))
+    {
+        printk("%s..%s..%d..****Error!!!!!!  Bus clock %d hz is beyond the prescribed limits ====xbw[%s]===\n",\
+            __FILE__, __FUNCTION__,__LINE__,host->bus_hz, host->dma_name);
+            
+        host->errorstep = 0x0D;    
+        ret = SDM_PARAM_ERROR;   
+        goto SetFreq_error;
+    }
+
+    //calculate the divider
+    div = host->bus_hz/freqHz + ((( host->bus_hz%freqHz ) > 0) ? 1:0 );
+    if( (div & 0x01) && (1 != div) )
+    {
+        //It is sure that the value of div is even. 
+        ++div;
+    }
+
+    if(div > 1)
+    {
+        host->clock = host->bus_hz/div;
+    }
+    else
+    {
+        host->clock = host->bus_hz;
+    }
+    div = (div >> 1);
+
+    //wait previous start to clear
+    tmo = 1000;
+	while (--tmo && (rk29_sdmmc_read(host->regs, SDMMC_CMD) & SDMMC_CMD_START))
+	{
+		cpu_relax();
+	}
+	if(!tmo)
+	{
+	    host->errorstep = 0x0E; 
+	    ret = SDM_START_CMD_FAIL;
+		goto SetFreq_error;
+    }
+           
+    /* set clock to desired speed */
+    rk29_sdmmc_write(host->regs, SDMMC_CLKDIV, div);
+
+    /* inform CIU */
+    ret = sdmmc_send_cmd_start(host, SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT);
+    if(ret != SDM_SUCCESS)
+    {
+        host->errorstep = 0x0E1; 
+        goto SetFreq_error;
+    }
+    
+    if(host->old_div != div)
+    {
+        printk("%s..%d..  newDiv=%u, newCLK=%uKhz====xbw[%s]=====\n", \
+            __FUNCTION__, __LINE__,div, host->clock/1000, host->dma_name);
+    }
+
+    ret = rk29_sdmmc_control_clock(host, TRUE);
+    if(ret != SDM_SUCCESS)
+    {
+        goto SetFreq_error;
+    }
+    host->old_div = div;
+
+    return SDM_SUCCESS;
+    
+SetFreq_error:
+
+    printk("%s..%s..%d..  change division fail, ret=%d  !!! ====xbw[%s]====\n",\
+        __FILE__, __FUNCTION__,__LINE__,ret, host->dma_name);
+        
+    return ret;
+    
+}
+
+
+
+static int rk29_sdmmc_hw_init(struct rk29_sdmmc *host)
+{
+    /* reset controller */
+    rk29_sdmmc_reset_controller(host);
+    rk29_sdmmc_change_clk_div(host, FOD_FREQ);
+    
+    return SDM_SUCCESS;    
+}
+
+
+
+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;
 }
-static int rk29_sdmmc_test_cmd_start(struct rk29_sdmmc *host)
+
+int rk29_sdmmc_set_buswidth(struct rk29_sdmmc *host)
 {
-	return rk29_sdmmc_read(host->regs, SDMMC_CMD) & SDMMC_CMD_START;
+    //int ret;
+    switch (host->ctype)
+    {
+        case SDMMC_CTYPE_1BIT:
+        case SDMMC_CTYPE_4BIT:
+            break;
+        case SDMMC_CTYPE_8BIT:
+            return SDM_PARAM_ERROR; //Now, not support 8 bit width
+        default:
+            return SDM_PARAM_ERROR;
+    }
+    rk29_sdmmc_set_iomux(host);
+
+    /* Set the current  bus width */
+	rk29_sdmmc_write(host->regs, SDMMC_CTYPE, host->ctype);
+
+    return SDM_SUCCESS;
 }
-static int rk29_sdmmc_start_request(struct rk29_sdmmc *host,struct mmc_request *mrq)
+
+
+void  rk29_sdmmc_set_frq(struct rk29_sdmmc *host)
 {
-	int ret = 0;
-	struct mmc_command	*cmd;
-	u32	cmdflags;
+    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)
+{ 
+    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    			    
+    	}
+    	    
+    	case STATE_SENDING_CMD:
+    	    host->cmd_status |= SDMMC_INT_RTO;
+    	    host->cmd->error = -ETIME;
+    	    rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,(SDMMC_INT_CMD_DONE | SDMMC_INT_RTO));  //  clear interrupt
+    	    rk29_sdmmc_set_pending(host, EVENT_CMD_COMPLETE);
+    	    tasklet_schedule(&host->tasklet);
+    	    break;
+    	 case STATE_DATA_BUSY:
+    	    host->data_status |= (SDMMC_INT_DCRC|SDMMC_INT_EBE);
+    	    host->cmd->data->error = -EILSEQ;
+    	    rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_DTO);  // clear interrupt
+    	    rk29_sdmmc_set_pending(host, EVENT_DATA_COMPLETE);
+    	    tasklet_schedule(&host->tasklet);
+    	    break;
+    	 case STATE_SENDING_STOP: 
+    	    host->cmd_status |= SDMMC_INT_RTO;
+    	    host->cmd->error = -ETIME;
+    	    rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,(SDMMC_INT_CMD_DONE | SDMMC_INT_RTO));  //  clear interrupt
+    	    rk29_sdmmc_set_pending(host, EVENT_CMD_COMPLETE);
+    	    tasklet_schedule(&host->tasklet);
+    	    break;
+    }
+}
+
+
+static void rk29_sdmmc_INT_CMD_DONE_timeout(unsigned long host_data)
+{
+	struct rk29_sdmmc *host = (struct rk29_sdmmc *) host_data;
 	
-	BUG_ON(host->state != STATE_IDLE);
+	if(STATE_SENDING_CMD == host->state)
+	{
+	    if(0==host->cmd->retries)
+	    {
+    	    printk("%s..%d... cmd=%d, INT_CMD_DONE timeout, errorStep=0x%x, host->state=%x ===xbw[%s]===\n",\
+                __FUNCTION__, __LINE__,host->cmd->opcode, host->errorstep,host->state,host->dma_name);
+        }
+            
+        rk29_sdmmc_dealwith_timeout(host);        
+	}
 	
-	spin_lock(&host->lock);
+}
+
 
-	if(rk29_sdmmc_test_cmd_start(host)){
-		dev_info(host->dev, "cmd_start bit is set ,reset ctroller\n");
-		ret = rk29_sdmmc_reset_ctrl(host);
+static void rk29_sdmmc_INT_DTO_timeout(unsigned long host_data)
+{
+	struct rk29_sdmmc *host = (struct rk29_sdmmc *) host_data;
+
+
+	if( (host->cmdr & SDMMC_CMD_DAT_EXP) && (STATE_DATA_BUSY == host->state))
+	{
+	    if(0==host->cmd->retries)
+	    {
+    	   printk("%s..%d... cmd=%d INT_DTO timeout,cmdr=0x%x,  host->errorStep=0x%x, Hoststate=%x===xbw[%s]===\n", \
+    	        __FUNCTION__, __LINE__,host->cmd->opcode,host->cmdr ,host->errorstep,host->state,host->dma_name);
+	    }
+
+	    rk29_sdmmc_dealwith_timeout(host);  
 	}
-	if(ret < 0)
-		goto start_err;
+ 
+}
+
+
+//to excute a  request 
+static int rk29_sdmmc_start_request(struct mmc_host *mmc )
+{
+    struct rk29_sdmmc *host = mmc_priv(mmc);
+	struct mmc_request	*mrq;
+	struct mmc_command	*cmd;
 	
-	host->state = STATE_SENDING_CMD;
+	u32		cmdr, ret;
+	unsigned long iflags;
+
+	spin_lock_irqsave(&host->lock, iflags);
 	
-	if (mrq->data) {
-		rk29_sdmmc_set_timeout(host,mrq->data);
-		rk29_sdmmc_write(host->regs, SDMMC_BYTCNT,mrq->data->blksz*mrq->data->blocks);
-		rk29_sdmmc_write(host->regs, SDMMC_BLKSIZ,mrq->data->blksz);
-	}
+	//host->mrq = host->new_mrq;
+	mrq = host->new_mrq;//mrq = host->mrq;	
 	cmd = mrq->cmd;
-	cmdflags = rk29_sdmmc_prepare_command(host->mmc, cmd);
-	if (host->is_init) {
-		host->is_init = 0;
-	    cmdflags |= SDMMC_CMD_INIT; 
-	}
+	cmd->error = 0;
+	
+	cmdr = rk29_sdmmc_prepare_command(cmd);
+	ret = SDM_SUCCESS;
+	
 
-	if (mrq->data) {
-		rk29_sdmmc_set_mrq_status(host, MRQ_HAS_DATA);
-		ret = rk29_sdmmc_submit_data(host, mrq->data);
-	}
-	if(ret < 0) {
-		rk29_sdmmc_set_mrq_status(host, MRQ_DMA_SET_ERR);
-		goto start_err;
+	/*clean FIFO if it is a new request*/
+    if((RK29_CTRL_SDMMC_ID == host->pdev->id) && ( !(cmdr & SDMMC_CMD_STOP)))
+    {
+        ret = rk29_sdmmc_reset_fifo(host);
+        if(SDM_SUCCESS != ret)
+        {
+        		host->mrq = host->new_mrq;///
+            cmd->error = -ENOMEDIUM;
+            host->errorstep = 0x0F; 
+            ret = SDM_FALSE;
+            goto start_request_Err; 
+        }
+    }
+
+    //check data-busy if the current command has the bit13 in command register.
+    if( cmdr & SDMMC_CMD_PRV_DAT_WAIT )
+    {
+        if(rk29_sdmmc_read(host->regs, SDMMC_STATUS) & SDMMC_STAUTS_DATA_BUSY)
+        {
+        	host->mrq = host->new_mrq;///
+            cmd->error = -ETIMEDOUT;
+            ret = SDM_BUSY_TIMEOUT;
+            host->errorstep = 0x10; 
+            goto start_request_Err; 
+        }
+    }
+    
+    host->state = STATE_SENDING_CMD;
+    host->mrq = host->new_mrq;
+	mrq = host->mrq;
+	cmd = mrq->cmd;
+	cmd->error = 0;
+
+    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);
+
+
+	xbwprintk(7, "%s..%d...    CMD%d  begin to call rk29_sdmmc_start_command() ===xbw[%s]===\n", \
+			__FUNCTION__, __LINE__ , cmd->opcode,host->dma_name);
+
+	if(RK29_CTRL_SDMMC_ID == host->pdev->id)
+	{
+	    mod_timer(&host->request_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_SEND_START_TIMEOUT+700));
 	}
-	dev_dbg(host->dev,"start cmd:%d ARGR=0x%08x CMDR=0x%08x\n",
-						cmd->opcode, cmd->arg, cmdflags);
-
-	rk29_sdmmc_write(host->regs, SDMMC_RINTSTS, ~SDMMC_INT_SDIO);
-	rk29_sdmmc_write(host->regs, SDMMC_INTMASK,
-		rk29_sdmmc_read(host->regs, SDMMC_INTMASK) | 
-		(SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | RK29_SDMMC_ERROR_FLAGS));
-	ret = rk29_sdmmc_start_command(host, cmd, cmdflags);
-	if(ret < 0) {
-		rk29_sdmmc_set_mrq_status(host, MRQ_CMD_START_TMO);
-		goto start_err;
+	else
+	{
+	    mod_timer(&host->request_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_SEND_START_TIMEOUT+500));
 	}
-	rk29_sdmmc_set_mrq_status(host, MRQ_CMD_START_DONE);
-	if (mrq->stop) {
-		rk29_sdmmc_set_mrq_status(host, MRQ_HAS_STOP);
-		host->stop_cmdr = rk29_sdmmc_prepare_command(host->mmc, mrq->stop);
-		if(mrq->cmd->opcode == 25)
-			host->stop_cmdr |= SDMMC_CMD_DAT_WR;
+
+
+	ret = rk29_sdmmc_start_command(host, cmd, host->cmdr);
+	if(SDM_SUCCESS != ret)
+	{
+        cmd->error = -ETIMEDOUT;
+        printk("%s..%d...   start_command(CMD%d, arg=%x)  fail !!!!!!! ret=%d  =========xbw=[%s]===\n",\
+            __FUNCTION__, __LINE__ , cmd->opcode,cmd->arg,ret, host->dma_name);
+        host->errorstep = 0x11; 
+        del_timer_sync(&host->request_timer);
+        
+        goto start_request_Err; 
 	}
-	spin_unlock(&host->lock);
-	return 0;
-start_err:
-	spin_unlock(&host->lock);
-	return ret;
+
+    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",\
+        __FUNCTION__, __LINE__, host->cmd->opcode,ret, \
+        host->state,host->cmd_status, host->pending_events,host->completed_events,host->dma_name);
+
+    spin_unlock_irqrestore(&host->lock, iflags);
+	return SDM_SUCCESS;
+	
+start_request_Err:
+    rk29_sdmmc_start_error(host);
+    
+    printk("%s: CMD%d  fail to call sdmmc_start_command()  err=%d, Errorstep=0x%x ====xbw[%s]===\n\n",\
+        __FUNCTION__,  cmd->opcode,ret,host->errorstep,host->dma_name);
+
+    spin_unlock_irqrestore(&host->lock, iflags);
+    
+    host->state = STATE_IDLE;      
+    mmc_request_done(host->mmc, host->mrq);
+    
+    return ret; 
+	
 }
 
+ 
 static void rk29_sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
-	int timeout;
 	struct rk29_sdmmc *host = mmc_priv(mmc);
+	
+	#if 0
+	//set 1 to close the controller for Debug.
+	if(RK29_CTRL_SDMMC_ID==host->pdev->id)//if(RK29_CTRL_SDIO_ID==host->pdev->id)
+	{
+	    mrq->cmd->error = -ENOMEDIUM;
+	    printk("%s..%d..  ==== The %s had been closed by myself for the experiment. ====xbw[%s]===\n",\
+				__FUNCTION__, __LINE__, host->dma_name, host->dma_name);
 
-	if(!mrq)
-		dev_info(host->dev, "mrq = NULL!!!!!\n");
-	if(host->mrq){
-				dev_info(host->dev, "%s-> host->mrq = NULL\n", __func__);
-				rk29_sdmmc_show_info(host);
+	    mmc_request_done(mmc, mrq);
+		return;
+	}
+	#endif
+
+    xbwprintk(5, "\n\n%s..%d...Begin a new cmd=%2d. ====@@@@@@@@==== host->flags=0x%lu, state=0x%x ===xbw[%s]====\n", \
+        __FUNCTION__, __LINE__,mrq->cmd->opcode, host->flags,host->state, host->dma_name);
+
+    if(RK29_CTRL_SDMMC_ID == host->pdev->id)
+    {
+        if(!rk29_sdmmc_get_cd(mmc) || ((0==mmc->re_initialized_flags)&&(MMC_GO_IDLE_STATE != mrq->cmd->opcode)))
+        {
+    		mrq->cmd->error = -ENOMEDIUM;
+
+    		if((RK29_CTRL_SDMMC_ID == host->pdev->id)&&(0==mrq->cmd->retries))
+    		{
+    	    	if(host->old_cmd != mrq->cmd->opcode)
+    	    	{
+    	    	    if( ((17==host->old_cmd)&&(18==mrq->cmd->opcode)) || ((18==host->old_cmd)&&(17==mrq->cmd->opcode)) ||\
+    	    	         ((24==host->old_cmd)&&(25==mrq->cmd->opcode)) || ((25==host->old_cmd)&&(24==mrq->cmd->opcode)))
+    	    	    {
+    	    	        host->old_cmd = mrq->cmd->opcode;
+    	    	        if(host->error_times++ %RK29_ERROR_PRINTK_INTERVAL ==0)
+            	        {
+                    		printk("%s: Refuse to run CMD%2d(arg=0x%8x) due to the removal of card.  1==xbw[%s]==\n", \
+                    		    __FUNCTION__, mrq->cmd->opcode, mrq->cmd->arg, host->dma_name);
+                		}
+    	    	    }
+    	    	    else
+    	    	    {
+            	        host->old_cmd = mrq->cmd->opcode;
+            	        host->error_times = 0;
+            	        printk("%s: Refuse to run CMD%2d(arg=0x%8x) due to the removal of card.  2==xbw[%s]==\n", \
+                    		    __FUNCTION__, mrq->cmd->opcode, mrq->cmd->arg, host->dma_name);
+                	}
+        	    }
+        	    else
+        	    {
+        	        if(host->error_times++ %RK29_ERROR_PRINTK_INTERVAL ==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);
+            		}
+        	    }	    
+    		}
+
+    		mmc_request_done(mmc, mrq);
+    		return;
+    	}
+    	else
+    	{
+    		if(host->old_cmd != mrq->cmd->opcode)
+    		{	
+    			host->old_cmd = mrq->cmd->opcode;
+				host->error_times = 0;
 			}
-	if((!rk29_sdmmc_test_mrq_status(host, MRQ_STOP_DMA) && 
-		rk29_sdmmc_test_mrq_status(host, MRQ_START_DMA)) ||
-		(rk29_sdmmc_test_mrq_status(host, MRQ_STOP_DMA) && 
-		!rk29_sdmmc_test_mrq_status(host, MRQ_START_DMA)))
-		dev_warn(host->dev, "start_dma but no stop_dma, or no start_dma but stop_dma\n");
-	WARN_ON(host->mrq);
-	host->old_mrq_status = host->mrq_status;
-	host->mrq_status = 0;
-	host->pending_events = 0;
-	host->completed_events= 0;
-	host->cmd_intsts = 0;
-	host->data_intsts = 0;
-	host->mrq = mrq;
-
-	if(!mrq->data)
-		timeout = 5000;
+    	}
+	}
 	else
-		timeout = 5000 + mrq->data->timeout_ns/1000000;
-	mod_timer(&host->monitor_timer, jiffies + msecs_to_jiffies(timeout));
+	{
+        host->old_cmd = mrq->cmd->opcode;
+        host->error_times = 0;
+	}
 	
-	if (!rk29_sdmmc_get_cd(mmc)) {
+	//host->mrq = mrq; //replaced by xbw
+	host->new_mrq = mrq;
+	if (host->state == STATE_IDLE) 
+	{
+        //host->state = STATE_SENDING_CMD; //replaced by xbw
+        rk29_sdmmc_start_request(mmc);
+	} 
+	else 
+	{
+        #ifdef RK29_SDMMC_LIST_QUEUE	
+        
+        printk("%s..%d...Danger! Danger! New request was added to queue. ===xbw[%s]===\n", \
+				__FUNCTION__, __LINE__,host->dma_name);
+        list_add_tail(&host->queue_node, &host->queue);
+        
+        #else
+        
+        printk("%s..%d...host state Error! old_state=%d, NewCMD%2d,arg=0x%x ====xbw[%s]======\n", \
+				__FUNCTION__, __LINE__, host->state, mrq->cmd->opcode,mrq->cmd->arg, host->dma_name);
+				
 		mrq->cmd->error = -ENOMEDIUM;
-		rk29_sdmmc_request_done(host, mrq);
-		dev_dbg(host->dev, "mrq_status = 0x%08lx\n", host->mrq_status);
+		mmc_request_done(mmc, mrq);
 		return;
+				
+        #endif	
+	}	
+}
+
+
+
+static void rk29_sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+    int timeout = 100;
+    unsigned int value;
+    unsigned long iflags;
+	struct rk29_sdmmc *host = mmc_priv(mmc);
+
+    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 SDIO controller to be IDLE timeout.==xbw[%s]===\n", \
+				__FUNCTION__, __LINE__, host->dma_name);
 
-	if(rk29_sdmmc_set_clock(host)) {
-		mrq->cmd->error = -EINPROGRESS;
-		dev_info(host->dev, "rk29_sdmmc_set_clock timeout, ios_clock = %d, clock = %d\n", host->ios_clock, host->clock);
-		rk29_sdmmc_request_done(host, mrq);
-		rk29_sdmmc_reset_ctrl(host);
-		rk29_sdmmc_show_info(host);
-		return;
+		goto out;
 	}
-		
-	if(rk29_sdmmc_start_request(host,mrq)) {
-		dev_info(host->dev, "rk29_sdmmc_start_request timeout\n");
-		mrq->cmd->error = -EINPROGRESS;
-		rk29_sdmmc_request_done(host, mrq);
-		rk29_sdmmc_reset_ctrl(host);
-		rk29_sdmmc_show_info(host);
+
+    //if(host->bus_mode != ios->power_mode)
+    {
+        switch (ios->power_mode) 
+        {
+            case MMC_POWER_UP:
+            	rk29_sdmmc_write(host->regs, SDMMC_PWREN, POWER_ENABLE);
+            	
+            	//reset the controller if it is SDMMC0
+            	if(RK29_CTRL_SDMMC_ID == host->pdev->id)
+            	{
+            	    xbwprintk(7, "%s..%d..POWER_UP, call reset_controller, initialized_flags=%d ====xbw[%s]=====\n",\
+            	        __FUNCTION__, __LINE__, host->mmc->re_initialized_flags,host->dma_name);
+            	        
+            	    mdelay(5);
+            	        
+            	    rk29_sdmmc_hw_init(host);
+            	}
+               	
+            	break;
+            case MMC_POWER_OFF:
+              
+                if(RK29_CTRL_SDMMC_ID == host->pdev->id)
+                {
+                	rk29_sdmmc_control_clock(host, FALSE);
+                	rk29_sdmmc_write(host->regs, SDMMC_PWREN, POWER_DISABLE);
+                
+                	if(5 == host->bus_mode)
+                	{
+                        mdelay(5);
+                        xbwprintk(7, "%s..%d..Fisrt powerOFF, call reset_controller ======xbw[%s]====\n", \
+                            __FUNCTION__, __LINE__,host->dma_name);
+                            
+                        rk29_sdmmc_reset_controller(host);
+                	}
+              
+            	}
+
+            	break;        	
+            default:
+            	break;
+    	}
+    	
+    	host->bus_mode = ios->power_mode;
+    	
 	}
-	return;
+
+    
+	if(host->ctype != ios->bus_width)
+	{
+    	switch (ios->bus_width) 
+    	{
+            case MMC_BUS_WIDTH_1:
+                host->ctype = SDMMC_CTYPE_1BIT;
+                break;
+            case MMC_BUS_WIDTH_4:
+                host->ctype = SDMMC_CTYPE_4BIT;
+                break;
+            case MMC_BUS_WIDTH_8:
+                host->ctype = SDMMC_CTYPE_8BIT;
+                break;
+            default:
+                host->ctype = 0;
+                break;
+    	}
+
+	    rk29_sdmmc_set_buswidth(host);
+	    
+	}
+	
+	if (ios->clock && (ios->clock != host->clock)) 
+	{	
+		/*
+		 * Use mirror of ios->clock to prevent race with mmc
+		 * core ios update when finding the minimum.
+		 */
+		//host->clock = ios->clock;	
+		rk29_sdmmc_change_clk_div(host, ios->clock);
+	}
+out:	
+
+    spin_unlock_irqrestore(&host->lock, iflags);
 }
 
+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);
+
+	return (wrtprt & SDMMC_WRITE_PROTECT)?1:0;
+}
+
+
 static void rk29_sdmmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
 {
 	u32 intmask;
@@ -853,6 +2004,7 @@ static void rk29_sdmmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
 	
 	spin_lock_irqsave(&host->lock, flags);
 	intmask = rk29_sdmmc_read(host->regs, SDMMC_INTMASK);
+	
 	if(enable)
 		rk29_sdmmc_write(host->regs, SDMMC_INTMASK, intmask | SDMMC_INT_SDIO);
 	else
@@ -865,6 +2017,8 @@ static void  rk29_sdmmc_init_card(struct mmc_host *mmc, struct mmc_card *card)
         card->quirks = MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
 
 }
+
+
 static const struct mmc_host_ops rk29_sdmmc_ops[] = {
 	{
 		.request	= rk29_sdmmc_request,
@@ -876,388 +2030,657 @@ static const struct mmc_host_ops rk29_sdmmc_ops[] = {
 		.request	= rk29_sdmmc_request,
 		.set_ios	= rk29_sdmmc_set_ios,
 		.enable_sdio_irq = rk29_sdmmc_enable_sdio_irq,
-        .init_card       = rk29_sdmmc_init_card,
+		.init_card       = rk29_sdmmc_init_card,
 	},
 };
 
-static void rk29_sdmmc_request_end(struct rk29_sdmmc *host)
-	__releases(&host->lock)
-	__acquires(&host->lock)
+static void rk29_sdmmc_request_end(struct rk29_sdmmc *host, struct mmc_command *cmd)
+{
+	u32 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",\
+        __FUNCTION__, __LINE__,cmd->opcode,host->state, host->pending_events,host->completed_events,host->dma_name);
+
+    del_timer_sync(&host->DTO_timer);
+
+    //stop DMA
+    if(host->dodma)
+    {
+        rk29_sdmmc_stop_dma(host);
+        rk29_sdmmc_control_host_dma(host, FALSE);
+        host->dodma = 0;
+    }
+
+    if(cmd->error)
+    {
+        goto exit;//It need not to wait-for-busy if the CMD-ERROR happen.
+    }
+
+    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;                
+                output = SDM_DATA_CRC_ERROR;
+                host->errorstep = 0x16; 
+            }
+            else
+            {
+                output = rk29_sdmmc_wait_unbusy(host);
+                if(SDM_SUCCESS != output)
+                {
+                    host->errorstep = 0x17;
+                    cmd->data->error = -ETIMEDOUT;
+                }
+
+                host->data->bytes_xfered = host->data->blocks * host->data->blksz;
+            }
+        }
+        else
+        {
+            if( status  & SDMMC_INT_SBE)
+            {
+                cmd->data->error = -EIO;
+                host->errorstep = 0x18;
+                output = SDM_START_BIT_ERROR;
+            }
+            else if((status  & SDMMC_INT_EBE) && (cmd->opcode != 14)) //MMC4.0, BUSTEST_R, A host read the reserved bus testing data parttern from a card.
+            {
+                cmd->data->error = -EILSEQ;
+                host->errorstep = 0x19;
+                output = SDM_END_BIT_ERROR;
+            }
+            else if(status  & SDMMC_INT_DRTO)
+            {
+                cmd->data->error = -ETIMEDOUT;
+                host->errorstep = 0x1A;
+                output = SDM_DATA_READ_TIMEOUT;
+            }
+            else if(status  & SDMMC_INT_DCRC)
+            {
+                host->errorstep = 0x1B;
+                cmd->data->error = -EILSEQ;
+                output = SDM_DATA_CRC_ERROR;
+            }
+            else
+            {
+                output = rk29_sdmmc_read_remain_data(host, (host->data->blocks * host->data->blksz), host->pbuf);
+                if(SDM_SUCCESS == output)
+                {
+                    host->data->bytes_xfered = host->data->blocks * host->data->blksz;
+                }
+            }       
+        }
+    }
+
+    if(SDM_SUCCESS == output)
+    {
+        if ((mmc_resp_type(cmd) == MMC_RSP_R1B) || (MMC_STOP_TRANSMISSION == cmd->opcode))
+        {
+            output = rk29_sdmmc_wait_unbusy(host);
+            if(SDM_SUCCESS != output)
+            {
+                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);
+            }
+        }
+    }
+
+    //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);
+        }
+    }
+
+exit:
+
+#ifdef RK29_SDMMC_LIST_QUEUE
+	if (!list_empty(&host->queue)) 
+	{
+		printk("%s..%d..  Danger!Danger!. continue the next request in the queue.  ====xbw[%s]====\n",\
+		        __FUNCTION__, __LINE__, host->dma_name);
+
+		host = list_entry(host->queue.next,
+				struct rk29_sdmmc, queue_node);
+		list_del(&host->queue_node);
+		host->state = STATE_SENDING_CMD;
+		rk29_sdmmc_start_request(host->mmc);
+	} 
+	else 
+	{	
+		dev_vdbg(&host->pdev->dev, "list empty\n");
+		host->state = STATE_IDLE;
+	}
+#else
+    dev_vdbg(&host->pdev->dev, "list empty\n");
+	host->state = STATE_IDLE;
+#endif
+	
+}
+
+static int rk29_sdmmc_command_complete(struct rk29_sdmmc *host,
+			struct mmc_command *cmd)
+{
+	u32	 value, status = host->cmd_status;
+	int  timeout, output= SDM_SUCCESS;
+
+    xbwprintk(7, "%s..%d.  cmd=%d, host->state=0x%x, cmdINT=0x%x\n,pendingEvent=0x%lu,completeEvents=0x%lu ===xbw[%s]===\n\n",\
+        __FUNCTION__, __LINE__,cmd->opcode,host->state,status, host->pending_events,host->completed_events,host->dma_name);
+
+
+    del_timer_sync(&host->request_timer);
+    
+    host->cmd_status = 0;
+
+	if((RK29_CTRL_SDMMC_ID == host->pdev->id) && (host->cmdr & SDMMC_CMD_STOP))
+    {
+        output = rk29_sdmmc_reset_fifo(host);
+        if (SDM_SUCCESS != output)
+        {
+            printk("%s..%d......reset fifo fail!!! =======xbw[%s]=====\n",__FUNCTION__, __LINE__, host->dma_name);
+            cmd->error = -ETIMEDOUT;
+            host->mrq->cmd->error = cmd->error;
+            output = SDM_ERROR;
+            host->errorstep = 0x1C;
+            goto CMD_Errror;
+        }
+    }
+
+    //status = rk29_sdmmc_read(host->regs, SDMMC_RINTSTS);
+    if(status & SDMMC_INT_RTO)
+	{
+	    cmd->error = -ENOMEM;
+	    host->mrq->cmd->error = cmd->error;
+        output = SDM_BUSY_TIMEOUT;
+
+        rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_RTO);
+        
+        if(host->use_dma)//if(host->dodma)
+        {
+           if(host->dodma) 
+           {
+                rk29_sdmmc_stop_dma(host);
+                rk29_sdmmc_control_host_dma(host, FALSE);
+                host->dodma = 0;
+           }
+            
+            value = rk29_sdmmc_read(host->regs, SDMMC_CTRL);
+            value |= SDMMC_CTRL_FIFO_RESET;
+            rk29_sdmmc_write(host->regs, SDMMC_CTRL, value);
+
+            timeout = 1000;
+            while (((value = rk29_sdmmc_read(host->regs, SDMMC_CTRL)) & (SDMMC_CTRL_FIFO_RESET)) && (timeout > 0))
+            {
+                udelay(1);
+                timeout--;
+            }
+            if (timeout == 0)
+            {   
+                output = SDM_FALSE;
+                host->errorstep = 0x1D;
+                printk("%s..%d......reset CTRL fail!!! =======xbw[%s]=====\n",__FUNCTION__, __LINE__, host->dma_name);
+                
+               goto CMD_Errror;
+            }
+        }
+
+	}	
+
+	if(cmd->flags & MMC_RSP_PRESENT) 
+	{
+	    if(cmd->flags & MMC_RSP_136) 
+	    {
+            cmd->resp[3] = rk29_sdmmc_read(host->regs, SDMMC_RESP0);
+            cmd->resp[2] = rk29_sdmmc_read(host->regs, SDMMC_RESP1);
+            cmd->resp[1] = rk29_sdmmc_read(host->regs, SDMMC_RESP2);
+            cmd->resp[0] = rk29_sdmmc_read(host->regs, SDMMC_RESP3);
+	    } 
+	    else 
+	    {
+	        cmd->resp[0] = rk29_sdmmc_read(host->regs, SDMMC_RESP0);
+	    }
+	}
+	
+	if(cmd->error)
+	{
+	    del_timer_sync(&host->DTO_timer);
+
+        //trace error
+	    if((0==cmd->retries) && (host->error_times++%RK29_ERROR_PRINTK_INTERVAL == 0))
+	    {
+	        if( ((RK29_CTRL_SDMMC_ID==host->pdev->id)&&(MMC_SLEEP_AWAKE!=cmd->opcode)) || 
+	             ((RK29_CTRL_SDMMC_ID!=host->pdev->id)&&(MMC_SEND_EXT_CSD!=cmd->opcode))  )
+	        {
+	            printk("%s..%d...CMD=%d, arg=%x, errorTimes=%d, errorStep=0x%x !!!!!! =======xbw[%s]=====\n",\
+                    __FUNCTION__, __LINE__, cmd->opcode, cmd->arg,host->error_times,host->errorstep, host->dma_name);
+	        }
+	    }
+
+	}
+    del_timer_sync(&host->request_timer);
+
+
+	return SDM_SUCCESS;
+   
+CMD_Errror:
+    del_timer_sync(&host->request_timer);
+	del_timer_sync(&host->DTO_timer);
+
+	if((0==cmd->retries) && (host->error_times++%RK29_ERROR_PRINTK_INTERVAL == 0))
+    {
+        printk("%s..%d......command_complete(CMD=%d, arg=%x) error=%d =======xbw[%s]=====\n",\
+            __FUNCTION__, __LINE__, host->cmd->opcode,host->cmd->arg, output, host->dma_name);
+    }
+        
+    return output;
+    
+}
+
+
+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;
+
+    del_timer_sync(&host->request_timer);
+
+    rk29_sdmmc_command_complete(host, host->mrq->cmd);    
+    rk29_sdmmc_request_end(host, host->mrq->cmd);
+
+}
+
+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;
+	int done_flag=0;
+
+	spin_lock(&host->lock);
+
+	state = host->state;
+	done_flag = 0;
+	
+	do 
+	{
+        switch (state) 
+        {
+            case STATE_IDLE:
+            {
+                xbwprintk(7, "%s..%d..   prev_state=  STATE_IDLE  ====xbw[%s]====\n", \
+						__FUNCTION__, __LINE__, host->dma_name);
+            	break;
+            }
+
+            case STATE_SENDING_CMD:
+            {
+                xbwprintk(7, "%s..%d..   prev_state=  STATE_SENDING_CMD, pendingEvernt=0x%lu  ====xbw[%s]====\n",\
+                    __FUNCTION__, __LINE__,host->completed_events, host->dma_name);
+
+                if (!rk29_sdmmc_test_and_clear_pending(host, EVENT_CMD_COMPLETE))
+                	break;
+
+                del_timer_sync(&host->request_timer); //delete the timer for INT_COME_DONE
+
+                rk29_sdmmc_set_completed(host, EVENT_CMD_COMPLETE);
+                rk29_sdmmc_command_complete(host, host->cmd);
+
+                
+                if (!data) 
+                {
+                    rk29_sdmmc_request_end(host, host->cmd);
+
+                    xbwprintk(7, "%s..%d..  CMD%d call mmc_request_done()====xbw[%s]====\n", \
+							__FUNCTION__, __LINE__,host->cmd->opcode,host->dma_name);
+                    
+                    done_flag = 1;
+                    goto unlock;
+                }
+
+                if(host->cmd->error)
+                {
+                    del_timer_sync(&host->DTO_timer); //delete the timer for INT_DTO
+                    
+                    if(data->stop)
+                    {
+                        xbwprintk(7, "%s..%d..  cmderr, so call send_stop_cmd() ====xbw[%s]====\n", \
+								__FUNCTION__, __LINE__, host->dma_name);
+
+                        state = STATE_SENDING_CMD;//STATE_SENDING_STOP; 
+                        send_stop_cmd(host);                        
+                        break;
+                    }
+
+                    rk29_sdmmc_set_pending(host, EVENT_DATA_COMPLETE);
+                }
+
+
+                state = STATE_DATA_BUSY; 
+                /* fall through */
+            }
+
+            case STATE_DATA_BUSY:
+            {
+                xbwprintk(7, "%s..%d..   prev_state= STATE_DATA_BUSY, pendingEvernt=0x%lu ====xbw[%s]====\n", \
+						__FUNCTION__, __LINE__,host->pending_events, host->dma_name);
+
+                if (!rk29_sdmmc_test_and_clear_pending(host, EVENT_DATA_COMPLETE))
+                	break;	
+
+                rk29_sdmmc_set_completed(host, EVENT_DATA_COMPLETE);
+                del_timer_sync(&host->DTO_timer); //delete the timer for INT_DTO
+
+                rk29_sdmmc_request_end(host, host->cmd);
+
+                if (data && !data->stop) 
+                {
+                    xbwprintk(7, "%s..%d..  CMD%d call mmc_request_done()====xbw[%s]====\n", \
+							__FUNCTION__, __LINE__,host->cmd->opcode,host->dma_name);
+
+                    if(!( (MMC_READ_SINGLE_BLOCK == host->cmd->opcode)&&( -EIO == data->error))) //deal with START_BIT_ERROR
+                    {
+                    	done_flag = 1;
+                    	goto unlock;
+                    }
+
+                }
+
+                xbwprintk(7, "%s..%d..  after DATA_COMPLETE, so call send_stop_cmd() ====xbw[%s]====\n", \
+						__FUNCTION__, __LINE__, host->dma_name);
+                
+                state = STATE_SENDING_CMD;
+                send_stop_cmd(host);
+                break;
+            }
+
+            case STATE_SENDING_STOP:
+            {
+                xbwprintk(7, "%s..%d..   prev_state=  STATE_SENDING_STOP, pendingEvernt=0x%lu  ====xbw[%s]====\n", \
+						__FUNCTION__, __LINE__, host->pending_events, host->dma_name);
+
+                if (!rk29_sdmmc_test_and_clear_pending(host, EVENT_CMD_COMPLETE))
+                	break;
+
+                rk29_sdmmc_command_complete(host, host->cmd);
+                del_timer_sync(&host->request_timer); //delete the timer for INT_CMD_DONE int CMD12
+                rk29_sdmmc_request_end(host, host->cmd);
+                
+                done_flag = 1;
+                goto unlock;
+            }
+        	
+        }
+	} while(0);
+
+	host->state = state;
+		
+unlock:	
+    if(0==done_flag)
+    {
+        spin_unlock(&host->lock);
+        return;
+    }
+    
+	 host->state = STATE_IDLE;
+	 spin_unlock(&host->lock);
+	 
+	 mmc_request_done(host->mmc, host->mrq);
+}
+
+
+static inline void rk29_sdmmc_cmd_interrupt(struct rk29_sdmmc *host, u32 status)
 {
-	if(host->mrq)
-		rk29_sdmmc_request_done(host, host->mrq);
+	if(!host->cmd_status) 
+		host->cmd_status = status;
+
+    if((MMC_STOP_TRANSMISSION != host->cmd->opcode) && (host->cmdr & SDMMC_CMD_DAT_EXP))
+    {
+	    mod_timer(&host->DTO_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_WAIT_DTO_INTERNVAL));
+	}
+	
+	smp_wmb();
+	rk29_sdmmc_set_pending(host, EVENT_CMD_COMPLETE);
+	tasklet_schedule(&host->tasklet);
 }
 
-static void rk29_sdmmc_command_complete(struct rk29_sdmmc *host,
-	struct mmc_command *cmd)
+static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id)
 {
-	unsigned int intsts = host->cmd_intsts;
+	struct rk29_sdmmc	*host = dev_id;
+	u32			status,  pending;
+	bool present;
+	bool present_old;
+	unsigned long iflags;
+
+	spin_lock_irqsave(&host->lock, iflags);
+
+    status = rk29_sdmmc_read(host->regs, SDMMC_RINTSTS);
+    pending = rk29_sdmmc_read(host->regs, SDMMC_MINTSTS);// read only mask reg
+    if (!pending)
+    {
+    	spin_unlock_irqrestore(&host->lock, iflags);
+        return IRQ_HANDLED;
+    }
 
-	host->cmd_intsts = 0;
-	if(cmd->flags & MMC_RSP_PRESENT) {
 
-	    if(cmd->flags & MMC_RSP_136) {
-		cmd->resp[3] = rk29_sdmmc_read(host->regs, SDMMC_RESP0);
-		cmd->resp[2] = rk29_sdmmc_read(host->regs, SDMMC_RESP1);
-		cmd->resp[1] = rk29_sdmmc_read(host->regs, SDMMC_RESP2);
-		cmd->resp[0] = rk29_sdmmc_read(host->regs, SDMMC_RESP3);
-	    } else {
-	        cmd->resp[0] = rk29_sdmmc_read(host->regs, SDMMC_RESP0);
-			cmd->resp[1] = 0;
-			cmd->resp[2] = 0;
-			cmd->resp[3] = 0;
-	    }
-	}
+    if(pending & SDMMC_INT_CD) 
+    {
+        rk29_sdmmc_write(host->regs, SDMMC_RINTSTS, SDMMC_INT_CD); // clear sd detect int
+    	present = rk29_sdmmc_get_cd(host->mmc);
+    	present_old = test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+  	
+    	if(present != present_old)
+    	{    	    
+        	printk("\n******************\n%s:INT_CD=0x%x,INT-En=%d,hostState=%d,  present Old=%d ==> New=%d ==xbw[%s]==\n",\
+                    __FUNCTION__, pending, host->mmc->re_initialized_flags, host->state, present_old, present,  host->dma_name);
 
-	if (intsts & SDMMC_INT_RTO)
-		cmd->error = -ETIMEDOUT;
-	else if ((cmd->flags & MMC_RSP_CRC) && (intsts & SDMMC_INT_RCRC))
-		cmd->error = -EILSEQ;
-	else if (intsts & SDMMC_INT_RE)
-		cmd->error = -EIO;
-	else if(intsts & SDMMC_INT_HLE)
-		cmd->error = -EIO;
-	else
-		cmd->error = 0;
+    	    rk28_send_wakeup_key(); //wake up backlight
+    	    host->error_times = 0;
 
-	if (cmd->error) {
-		dev_dbg(host->dev,
-			"command error: status=0x%08x resp=0x%08x\n"
-			"cmd=0x%08x arg=0x%08x flg=0x%08x err=%d\n", 
-			intsts, cmd->resp[0], 
-			cmd->opcode, cmd->arg, cmd->flags, cmd->error);
+    	    #if 1
+    	    rk29_sdmmc_dealwith_timeout(host);       	    
+            #endif
+        	            
+    	    if(present)
+    	    {
+    	        set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
 
-		if (cmd->data) {
-			rk29_sdmmc_stop_dma(host);
-		}
-	} 
-}
+    	        if(host->mmc->re_initialized_flags)
+        	    {
+        	        mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_REMOVAL_DELAY/2));
+        	    }
+        	    else
+        	    {
+        	        mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_REMOVAL_DELAY*2));
+        	    }
+    	    }
+    	    else
+    	    {
+    	        clear_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+    	        host->mmc->re_initialized_flags = 0;
 
-static void rk29_sdmmc_tasklet_func(unsigned long priv)
-{
-	struct rk29_sdmmc	*host = (struct rk29_sdmmc *)priv;
-	enum rk29_sdmmc_state	state;
-	enum rk29_sdmmc_state	prev_state;
-	unsigned int			intsts;
+    	        mmc_detect_change(host->mmc, 200);
+    	    }
 
-	spin_lock(&host->lock);
-	state = host->state;
+    	}
 
-	do {
-		prev_state = state;
-		switch (state) {
-		case STATE_IDLE:
-			break;
+        spin_unlock_irqrestore(&host->lock, iflags);
+        return IRQ_HANDLED;
 
-		case STATE_SENDING_CMD:			
-			if (!rk29_sdmmc_test_and_clear_pending(host,
-						EVENT_CMD_COMPLETE))
-				break;
-			rk29_sdmmc_set_completed(host, EVENT_CMD_COMPLETE);
-			if(!host->mrq){
-				dev_info(host->dev, "sending cmd, host->mrq = NULL\n");
-				rk29_sdmmc_show_info(host);
-			}else{
-				rk29_sdmmc_command_complete(host, host->mrq->cmd);
-				if (!host->mrq->data || (host->mrq->cmd->error)) {
-					rk29_sdmmc_request_end(host);
-					goto unlock;
-				}
-			prev_state = state = STATE_SENDING_DATA;
-			}
-		case STATE_SENDING_DATA:
-			if (rk29_sdmmc_test_and_clear_pending(host,
-						EVENT_DATA_ERROR)) {
-				if(!host->mrq){
-					dev_info(host->dev, "sending data, host->mrq = NULL\n");
-					rk29_sdmmc_show_info(host);
-				}
-				if(!rk29_sdmmc_test_mrq_status(host, MRQ_DMA_DONE) && 
-		rk29_sdmmc_test_mrq_status(host, MRQ_START_DMA))
-			dev_info(host->dev, "dma is running...\n");
-				rk29_sdmmc_stop_dma(host);
-				if (host->mrq->data->stop)
-					send_stop_cmd(host);
-				state = STATE_DATA_ERROR;
-				break;
-			}
-			prev_state = state = STATE_DATA_BUSY;
-
-		case STATE_DATA_BUSY:
-			if (!rk29_sdmmc_test_and_clear_pending(host,EVENT_DATA_COMPLETE) &&
-				!(host->data_intsts & SDMMC_INT_SBE))
-				break;	
-			
-			rk29_sdmmc_set_completed(host, EVENT_DATA_COMPLETE);
-			intsts = host->data_intsts;
-			if(!host->mrq){
-				dev_info(host->dev, "%s-> host->mrq = NULL\n", __func__);
-				rk29_sdmmc_show_info(host);
-			}
-			if(host->mrq->data) {
-				if (unlikely(intsts & RK29_SDMMC_DATA_ERROR_FLAGS)) {
-					if (intsts & SDMMC_INT_DRTO) {
-						dev_err(host->dev,"data timeout error\n");
-						host->mrq->data->error = -ETIMEDOUT;
-					} else if (intsts & SDMMC_INT_DCRC) {
-						dev_err(host->dev,"data CRC error\n");
-						host->mrq->data->error = -EILSEQ;
-					} else if (intsts & SDMMC_INT_SBE) {
-						dev_err(host->dev,"data start bit error\n");
-						host->mrq->data->error = -EILSEQ;
-					}else {
-						dev_err(host->dev,"data FIFO error (status=%08x)\n",intsts);
-						host->mrq->data->error = -EIO;
-					}
-					rk29_sdmmc_show_info(host);
-				}else {
-					host->mrq->data->bytes_xfered = host->mrq->data->blocks * host->mrq->data->blksz;
-					host->mrq->data->error = 0;
-				}
-			}
-			if (!host->mrq->data->stop) {
-				rk29_sdmmc_request_end(host);
-				goto unlock;
-			}
+    }	
 
-			prev_state = state = STATE_SENDING_STOP;
-			if (host->mrq->data && !host->mrq->data->error)
-				send_stop_cmd(host);
-			/* fall through */
-
-		case STATE_SENDING_STOP:
-			if (!rk29_sdmmc_test_and_clear_pending(host,
-						EVENT_CMD_COMPLETE))
-				break;
-			if(!host->mrq){
-				dev_info(host->dev, "%s-> host->mrq = NULL\n", __func__);
-				rk29_sdmmc_show_info(host);
-			}
-			if(host->mrq->stop)
-				rk29_sdmmc_command_complete(host, host->mrq->stop);
-			rk29_sdmmc_request_end(host);
-			goto unlock;
-		case STATE_DATA_ERROR:
-			state = STATE_DATA_BUSY;
-			break;
-		}
-	} while (state != prev_state);
 
-	host->state = state;
+    if (pending & SDMMC_INT_CMD_DONE) {
 
-unlock:
-	spin_unlock(&host->lock);
+        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);
+    }
 
+    if(pending & SDMMC_INT_SDIO) 
+    {	
+        xbwprintk(7, "%s..%d..  INT_SDIO  INT=0x%x   ====xbw[%s]====\n", \
+				__FUNCTION__, __LINE__, pending, host->dma_name);
 
-static irqreturn_t rk29_sdmmc_isr(int irq, void *dev_id)
-{
-	struct rk29_sdmmc *host = dev_id;
-	unsigned int intsts;
+        rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_SDIO);
+        mmc_signal_sdio_irq(host->mmc);
+    }
 
-	intsts = rk29_sdmmc_read(host->regs, SDMMC_MINTSTS);
 
-	spin_lock(&host->lock);
-	if(intsts & RK29_SDMMC_CMD_ERROR_FLAGS) {
-		rk29_sdmmc_set_mrq_status(host, MRQ_INT_CMD_ERR);
-	    rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,RK29_SDMMC_CMD_ERROR_FLAGS); 
-	    host->cmd_intsts = intsts;
-	    smp_wmb();
-	    rk29_sdmmc_set_pending(host, EVENT_CMD_COMPLETE);
-		if(!host->mrq){
-				dev_info(host->dev, "%s-> host->mrq = NULL\n", __func__);
-				rk29_sdmmc_show_info(host);
-			}
-		else
-			dev_info(host->dev, "[cmd%d] cmd error(intsts 0x%x, host->state %d, pending_events %ld)\n", 
-				host->mrq->cmd->opcode,intsts,host->state,host->pending_events);
-		tasklet_schedule(&host->tasklet);
-	}
+    if(pending & SDMMC_INT_RTO) 
+    {
+    	xbwprintk(7, "%s..%d..  CMD%d CMD_ERROR_FLAGS  INT=0x%x   ====xbw[%s]====\n", \
+				__FUNCTION__, __LINE__, host->cmd->opcode,pending, host->dma_name);
 
-	if (intsts & RK29_SDMMC_DATA_ERROR_FLAGS) {
-		rk29_sdmmc_set_mrq_status(host, MRQ_INT_DATA_ERR);
-		rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,RK29_SDMMC_DATA_ERROR_FLAGS);
-		host->data_intsts = intsts;
-		smp_wmb();
-		rk29_sdmmc_set_pending(host, EVENT_DATA_ERROR);
-		if(!host->mrq){
-				dev_info(host->dev, "%s-> host->mrq = NULL\n", __func__);
-				rk29_sdmmc_show_info(host);
-			}
-		else
-			dev_info(host->dev, "[cmd%d] data error(intsts 0x%x, host->state %d, pending_events %ld)\n", 
-				host->mrq->cmd->opcode, intsts,host->state,host->pending_events);
-		tasklet_schedule(&host->tasklet);
-	}
+        rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_RTO); 
+        host->cmd_status = status;
+        smp_wmb();
+        rk29_sdmmc_set_pending(host, EVENT_CMD_COMPLETE);
 
-	if(intsts & SDMMC_INT_DTO) {
-		rk29_sdmmc_set_mrq_status(host, MRQ_INT_DATA_DONE);
-	    rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_DTO); 
-	    if (!host->data_intsts)
-			host->data_intsts = intsts;
-	    smp_wmb();
-	    rk29_sdmmc_set_pending(host, EVENT_DATA_COMPLETE);
-	    tasklet_schedule(&host->tasklet);
-	}
-	if (intsts & SDMMC_INT_CMD_DONE) {
-		rk29_sdmmc_set_mrq_status(host, MRQ_INT_CMD_DONE);
-	    rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_CMD_DONE);
-	    if(!host->cmd_intsts) 
-			host->cmd_intsts = intsts;
-
-		smp_wmb();
-		rk29_sdmmc_set_pending(host, EVENT_CMD_COMPLETE);
-		tasklet_schedule(&host->tasklet);
-	}
-	if(host->is_sdio && (intsts & SDMMC_INT_SDIO)) {
-		rk29_sdmmc_set_mrq_status(host, MRQ_INT_SDIO);
-		rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_SDIO);
-		mmc_signal_sdio_irq(host->mmc);
-	}
-	spin_unlock(&host->lock);
-	return IRQ_HANDLED;
-}
+        if(!(pending & SDMMC_INT_CMD_DONE))
+            tasklet_schedule(&host->tasklet);
 
-static void rk29_sdmmc_dma_complete(void *arg, int size, enum rk29_dma_buffresult result)
-{
-	struct rk29_sdmmc	*host = arg;
-	
-	dev_dbg(host->dev, "DMA complete\n");
-	rk29_sdmmc_set_mrq_status(host, MRQ_DMA_DONE);
-}
+        spin_unlock_irqrestore(&host->lock, iflags);
+        return IRQ_HANDLED;
+    }
 
-static void rk29_sdmmc_detect_change(struct rk29_sdmmc *host)
-{
-	spin_lock(&host->lock);	
 
-	del_timer(&host->monitor_timer);
-	rk29_sdmmc_write(host->regs, SDMMC_RINTSTS, ~SDMMC_INT_SDIO);
-	rk29_sdmmc_write(host->regs, SDMMC_INTMASK,
-		rk29_sdmmc_read(host->regs, SDMMC_INTMASK) & 
-		~(SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | RK29_SDMMC_ERROR_FLAGS));
-	if (host->mrq) {
-		switch (host->state) {
-		case STATE_IDLE:
-			break;
-		case STATE_SENDING_CMD:
-			if(host->mrq->cmd)
-				host->mrq->cmd->error = -ENOMEDIUM;
-			if (!host->mrq->data)
-				break;
-			/* fall through */
-		case STATE_SENDING_DATA:
-			if(host->mrq->data)
-				host->mrq->data->error = -ENOMEDIUM;
-			rk29_sdmmc_stop_dma(host);
-			break;
-		case STATE_DATA_BUSY:
-		case STATE_DATA_ERROR:
-			if (host->mrq->data && host->mrq->data->error == -EINPROGRESS)
-				host->mrq->data->error = -ENOMEDIUM;
-			if (!host->mrq->stop)
-				break;
-			/* fall through */
-		case STATE_SENDING_STOP:
-			if(host->mrq->stop) {
-				host->mrq->stop->error = -ENOMEDIUM;
-			}
-			break;
-		}
-		rk29_sdmmc_request_end(host);
-	}
-	rk29_sdmmc_reset_fifo(host);
-	spin_unlock(&host->lock);
-	mmc_detect_change(host->mmc, 0);
-}
+    if(pending & SDMMC_INT_HLE)
+    {
+        printk("%s:  write error due to hardware locked. Please check your hardware. ==xbw[%s]==\n",\
+				__FUNCTION__, host->dma_name);  	      
+    
+        rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_HLE); 
+        spin_unlock_irqrestore(&host->lock, iflags);
+        return IRQ_HANDLED;
+    }
 
-static void rk29_sdmmc1_status_notify_cb(int card_present, void *dev_id)
-{
-    struct rk29_sdmmc *host = dev_id;
 
-    card_present = rk29_sdmmc_get_cd(host->mmc);
-    dev_info(host->dev, "sdio change detected,status is %d\n",card_present);
-	
-    rk29_sdmmc_detect_change(host);
-}
+    if(pending & SDMMC_INT_DTO) 
+    {	
+        xbwprintk(7, "%s..%d..  CMD%d  INT_DTO  INT=0x%x   ==xbw[%s]==\n", \
+				__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
 
-static void rk29_sdmmc_get_dma_dma_info(struct rk29_sdmmc *host)
-{
-	if(host->is_sdio)
-		host->dma_info = dma_infos[1];
-	else
-		host->dma_info = dma_infos[0];
-}
+        if (!host->data_status)
+    		host->data_status = status;
 
-static irqreturn_t rk29_sdmmc_detect_change_isr(int irq, void *dev_id);
-static void rk29_sdmmc_detect_change_work(struct work_struct *work)
-{
-	int ret;
-    struct rk29_sdmmc *host =  container_of(work, struct rk29_sdmmc, work.work);
+        smp_wmb();
 
-	dev_info(host->dev, "sd detect change, card is %s\n", 
-		rk29_sdmmc_get_cd(host->mmc)?"inserted":"removed");
-	if(host->enable_sd_warkup && rk29_sdmmc_get_cd(host->mmc))
-		rk28_send_wakeup_key();
-	rk29_sdmmc_detect_change(host);
+        rk29_sdmmc_set_pending(host, EVENT_DATA_COMPLETE);
+        tasklet_schedule(&host->tasklet);
 
-	free_irq(host->gpio_irq, host);
-	ret = request_irq(host->gpio_irq,
-    				 rk29_sdmmc_detect_change_isr,
-                	 rk29_sdmmc_get_cd(host->mmc)?IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING,
-                	 "sd_detect",
-                	 host);
-	if(ret < 0)
-		dev_err(host->dev, "gpio request_irq error\n");
-}
-static irqreturn_t rk29_sdmmc_detect_change_isr(int irq, void *dev_id)
-{
-	struct rk29_sdmmc *host = dev_id;
+        spin_unlock_irqrestore(&host->lock, iflags);
+        return IRQ_HANDLED;
+    }
 
-	disable_irq_nosync(host->gpio_irq);
-	if(rk29_sdmmc_get_cd(host->mmc))
-		schedule_delayed_work(&host->work, msecs_to_jiffies(500));
-	else
-		schedule_delayed_work(&host->work, 0);
-	
+
+    if (pending & SDMMC_INT_FRUN) 
+    { 
+    	printk("%s: INT=0x%x Oh!My God,let me see!What happened?Why?Where?  ==xbw[%s]==\n", \
+				__FUNCTION__, pending,host->dma_name);
+    	
+        rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_FRUN); 
+        spin_unlock_irqrestore(&host->lock, iflags);
+        return IRQ_HANDLED;
+    }
+
+    if (pending & SDMMC_INT_RXDR) 
+    {	
+        xbwprintk(6, "%s..%d..  SDMMC_INT_RXDR  INT=0x%x   ====xbw[%s]====\n", \
+				__FUNCTION__, __LINE__, pending, host->dma_name);
+
+        rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_RXDR);  //  clear interrupt
+        rk29_sdmmc_do_pio_read(host);
+    }
+
+    if (pending & SDMMC_INT_TXDR) 
+    {
+        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
+    }
+
+	spin_unlock_irqrestore(&host->lock, iflags);
 	return IRQ_HANDLED;
 }
-static void rk29_sdmmc_monitor_timer(unsigned long data)
+
+/*
+ *
+ * MMC card detect thread, kicked off from detect interrupt, 1 timer 
+ *
+ */
+static void rk29_sdmmc_detect_change(unsigned long data)
 {
 	struct rk29_sdmmc *host = (struct rk29_sdmmc *)data;
-	
-	if(!rk29_sdmmc_test_mrq_status(host, MRQ_REQUEST_DONE)){
-		dev_info(host->dev, "no dto interrupt\n");
-		rk29_sdmmc_show_info(host);
-		host->mrq->cmd->error = -ETIMEDOUT;
-		if(host->mrq->data)
-			host->mrq->data->error = -ETIMEDOUT;
-		rk29_sdmmc_request_end(host);
-		//rk29_sdmmc_reset_ctrl(host);
-	}
-	
+
+	if(!host->mmc)
+	    return;
+   
+	smp_rmb();
+
+    if(RK29_CTRL_SDMMC_ID == host->pdev->id)
+    {
+        host->mmc->re_initialized_flags =1;
+    }
+    
+	mmc_detect_change(host->mmc, 0);	
+
 }
 
-#ifdef CONFIG_HAS_EARLYSUSPEND
-static void rk29_sdmmc_early_suspend(struct early_suspend *h)
+static void rk29_sdmmc1_check_status(unsigned long data)
 {
-	struct rk29_sdmmc *host = container_of(h,
-							struct rk29_sdmmc,
-							early_suspend);
+        struct rk29_sdmmc *host = (struct rk29_sdmmc *)data;
+        struct rk29_sdmmc_platform_data *pdata = host->pdev->dev.platform_data;
+        unsigned int status;
+
+    status = pdata->status(mmc_dev(host->mmc));
+
+    if (status ^ host->oldstatus)
+    {
+        pr_info("%s: slot status change detected(%d-%d)\n",mmc_hostname(host->mmc), host->oldstatus, status);
+        if (status) 
+        {
+            set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+            mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(200));
+        }
+        else 
+        {
+            clear_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+            rk29_sdmmc_detect_change((unsigned long)host);
+        }
+    }
 
-	dev_dbg(host->dev, "Enter rk29_sdmmc_early_suspend\n");
+    host->oldstatus = status;
 }
 
-static void rk29_sdmmc_early_resume(struct early_suspend *h)
+static void rk29_sdmmc1_status_notify_cb(int card_present, void *dev_id)
 {
-	struct rk29_sdmmc *host = container_of(h,
-							struct rk29_sdmmc,
-							early_suspend);
-
-	dev_dbg(host->dev, "Exit rk29_sdmmc_early_resume\n");
+        struct rk29_sdmmc *host = dev_id;
+        printk(KERN_INFO "%s, card_present %d\n", mmc_hostname(host->mmc), card_present);
+        rk29_sdmmc1_check_status((unsigned long)host);
 }
-#endif
 
 
 static int rk29_sdmmc_probe(struct platform_device *pdev)
@@ -1266,270 +2689,365 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
 	struct rk29_sdmmc		*host;
 	struct resource			*regs;
 	struct rk29_sdmmc_platform_data *pdata;
+	int				irq;
 	int				ret = 0;
 
+    /* must have platform data */
 	pdata = pdev->dev.platform_data;
 	if (!pdata) {
 		dev_err(&pdev->dev, "Platform data missing\n");
-		return -ENODEV;
+		ret = -ENODEV;
+		host->errorstep = 0x87;
+		goto out;
+	}
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs)
+	{
+	    host->errorstep = 0x88;
+		return -ENXIO;
 	}
-	if(pdata->io_init)
-		pdata->io_init();
 
 	mmc = mmc_alloc_host(sizeof(struct rk29_sdmmc), &pdev->dev);
 	if (!mmc)
-		return -ENOMEM;	
+	{
+	    host->errorstep = 0x89;
+		ret = -ENOMEM;
+		goto rel_regions;
+	}	
 
 	host = mmc_priv(mmc);
 	host->mmc = mmc;
-	host->dev = &pdev->dev;
-	host->mrq = NULL;
-	host->state = STATE_IDLE;
-	host->div = -1;
-	host->is_init = 1;
-	host->is_sdio = rk29_sdmmc_is_sdio(pdata);
-
-	if(host->is_sdio)
-		sdio_host = host;
-	host->get_wifi_cd = pdata->status;
-
-	host->irq = platform_get_irq(pdev, 0);
-	if (host->irq < 0) {
-		dev_err(&pdev->dev, "platform_get_irq error\n");
-		ret = host->irq;
-		goto err_mmc_free_host;
-	}
-	
-	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!regs) {
-		dev_err(&pdev->dev, "platform_get_resource error\n");
-		ret = -ENXIO;
-		goto err_mmc_free_host;
-	}
+	host->pdev = pdev;	
+
+	host->ctype = 0; // set default 1 bit mode
+	host->errorstep = 0;
+	host->bus_mode = 5;
+	host->old_cmd = 100;
+	host->clock =0;
+	host->old_div = 0xFF;
+	host->error_times = 0;
 	
-	host->regs = ioremap(regs->start, regs->end - regs->start);
-	if (!host->regs){
-		dev_err(&pdev->dev, "ioremap error\n");
-		ret = ENXIO;
-	    goto err_mmc_free_host; 
-	}
-	spin_lock_init(&host->lock);
+#ifdef CONFIG_PM
+    host->gpio_det = pdata->detect_irq;
+#endif
 
-	/* dma init */
-	rk29_sdmmc_get_dma_dma_info(host);
-	ret = rk29_dma_request(host->dma_info.chn, &(host->dma_info.client), NULL); 
-	if (ret < 0){
-		dev_err(&pdev->dev, "rk29_dma_request error\n");
-	    goto err_iounmap; 
-	}
-	ret = rk29_dma_config(host->dma_info.chn, 4, 1);
+	if(pdata->io_init)
+		pdata->io_init();
+		
+	spin_lock_init(&host->lock);
 
-	if (ret < 0){
-		dev_err(&pdev->dev, "rk29_dma_config error\n");
-	    //goto err_rk29_dma_free; 
-	}
-	ret = rk29_dma_set_buffdone_fn(host->dma_info.chn, rk29_sdmmc_dma_complete);
-	if (ret < 0){
-		dev_err(&pdev->dev, "rk29_dma_set_buffdone_fn error\n");
-	    goto err_rk29_dma_free; 
-	}
-	host->dma_addr = regs->start + SDMMC_DATA;
+#ifdef RK29_SDMMC_LIST_QUEUE	
+	INIT_LIST_HEAD(&host->queue);
+#endif	
 
-	/* clk init */
 	host->clk = clk_get(&pdev->dev, "mmc");
-	if(host->is_sdio)
-		clk_set_rate(host->clk,RK29_SDIO_CLK * 1000000);
-	else
-		clk_set_rate(host->clk,RK29_SDCARD_CLK * 1000000);
+	clk_set_rate(host->clk,SDHC_FPP_FREQ);
 	clk_enable(host->clk);
 	clk_enable(clk_get(&pdev->dev, "hclk_mmc"));
-	host->bus_hz = clk_get_rate(host->clk); 
-
-	/* reset all blocks */
-  	rk29_sdmmc_write(host->regs, SDMMC_CTRL,(SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET));
-  	/* wait till resets clear */
-  	while (rk29_sdmmc_read(host->regs, SDMMC_CTRL) & (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET));
-	 /* Clear the interrupts for the host controller */
-	rk29_sdmmc_write(host->regs, SDMMC_RINTSTS, 0xFFFFFFFF);
-	rk29_sdmmc_write(host->regs, SDMMC_INTMASK, 0); // disable all mmc interrupt first
-  	/* Put in max timeout */
-  	rk29_sdmmc_write(host->regs, SDMMC_TMOUT, 0xFFFFFFFF);
-
-  	/* FIFO threshold settings  */
-  	rk29_sdmmc_write(host->regs, SDMMC_FIFOTH, ((0x3 << 28) | (0x0f << 16) | (0x10 << 0))); // RXMark = 15, TXMark = 16, DMA Size = 16
-	/* disable clock to CIU */
-	rk29_sdmmc_write(host->regs, SDMMC_CLKENA,0);
-	rk29_sdmmc_write(host->regs, SDMMC_CLKSRC,0);
-	rk29_sdmmc_write(host->regs, SDMMC_PWREN, 1);
-
-	ret = request_irq(host->irq, rk29_sdmmc_isr, 0, dev_name(&pdev->dev), host);
-	if (ret < 0){
-		dev_err(&pdev->dev, "request_irq error\n");
-	    goto err_rk29_dma_free; 
+
+	ret = -ENOMEM;
+	host->regs = ioremap(regs->start, regs->end - regs->start);
+	if (!host->regs)
+	{
+	    host->errorstep = 0x8A;
+	    goto err_freemap; 
 	}
 
-	/* card insert flags init*/  
-    if (pdata->register_status_notify) {
-        pdata->register_status_notify(rk29_sdmmc1_status_notify_cb, host);
+    mmc->ops = &rk29_sdmmc_ops[pdev->id];
+	mmc->f_min = FOD_FREQ;
+#if 0
+    mmc->f_max = SDHC_FPP_FREQ;
+#else
+    if(RK29_CTRL_SDMMC_ID== host->pdev->id)
+    {
+        mmc->f_max = SDHC_FPP_FREQ;
+    }
+    else
+    {
+        mmc->f_max = SDHC_FPP_FREQ / 2;
     }
 
-	/* add host */
-	if(host->is_sdio)
-		mmc->ops = &rk29_sdmmc_ops[1];
-	else
-		mmc->ops = &rk29_sdmmc_ops[0];
-  
-        if (host->is_sdio) 
-           mmc->pm_flags = MMC_PM_IGNORE_PM_NOTIFY;   //ignore pm notify    
-	
-	mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510);
-	mmc->f_max = host->bus_hz; 
-	mmc->ocr_avail = pdata->host_ocr_avail;
+#endif 
+	//mmc->ocr_avail = pdata->host_ocr_avail;
+	mmc->ocr_avail = MMC_VDD_27_28|MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31
+                     | 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;
+
+    /*
+	 * We can do SGIO
+	*/
 	mmc->max_phys_segs = 64;
-	mmc->max_hw_segs = 64;
-	mmc->max_blk_size = 4095; 
-	mmc->max_blk_count = 65535; 
-	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
-	mmc->max_seg_size = mmc->max_req_size;	
-	
-	ret = mmc_add_host(mmc);
-	if (ret < 0){
-		dev_err(&pdev->dev, "mmc_add_host error\n");
-	    goto err_free_irq; 
-	}
-	
-#if defined (CONFIG_DEBUG_FS)
-	rk29_sdmmc_init_debugfs(host);
-#endif
+	mmc->max_hw_segs = 64; 
+
+	/*
+	 * Block size can be up to 2048 bytes, but must be a power of two.
+	*/
+	mmc->max_blk_size = 4095;
+
+	/*
+	 * No limit on the number of blocks transferred.
+	*/
+	mmc->max_blk_count = 4096; 
+
+	/*
+	 * Since we only have a 16-bit data length register, we must
+	 * ensure that we don't exceed 2^16-1 bytes in a single request.
+	*/
+	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; //8M bytes(2K*4K)
+
+    /*
+	 * Set the maximum segment size.  Since we aren't doing DMA
+	 * (yet) we are only limited by the data length register.
+	*/
+	mmc->max_seg_size = mmc->max_req_size;
+
 	tasklet_init(&host->tasklet, rk29_sdmmc_tasklet_func, (unsigned long)host);
-	setup_timer(&host->monitor_timer, rk29_sdmmc_monitor_timer,(unsigned long)host);
-	
-	host->gpio_det = pdata->detect_irq;
-	if(!host->is_sdio && host->gpio_det != INVALID_GPIO) {
-		INIT_DELAYED_WORK(&host->work, rk29_sdmmc_detect_change_work);
-		ret = gpio_request(host->gpio_det, "sd_detect");
-		if(ret < 0) {
-			dev_err(&pdev->dev, "gpio_request error\n");
-			goto err_mmc_remove_host;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+	{
+	    host->errorstep = 0x8B;
+		ret = -EINVAL;
+		goto err_freemap;
+	}
+
+    memcpy(host->dma_name, pdata->dma_name, 8);    
+	host->use_dma = pdata->use_dma;
+
+	/*DMA init*/
+	if(host->use_dma)
+	{
+        host->dma_info = rk29_sdmmc_dma_infos[host->pdev->id];
+        ret = rk29_dma_request(host->dma_info.chn, &(host->dma_info.client), NULL); 
+        if (ret < 0)
+        {
+        	printk("%s..%d...rk29_dma_request error=%d.===xbw[%s]====\n", \
+					__FUNCTION__, __LINE__,ret, host->dma_name);
+        	host->errorstep = 0x97;
+            goto err_freemap; 
+        }
+
+        ret = rk29_dma_config(host->dma_info.chn, 4);
+        if(ret < 0)
+		{
+            printk("%s..%d..  rk29_dma_config error=%d ====xbw[%s]====\n", \
+					__FUNCTION__, __LINE__, ret, host->dma_name);
+            host->errorstep = 0x98;
+            goto err_dmaunmap;
 		}
-		gpio_direction_input(host->gpio_det);
-		host->gpio_irq = gpio_to_irq(host->gpio_det);
-
-		ret = request_irq(host->gpio_irq,
-                		  rk29_sdmmc_detect_change_isr,
-                		  rk29_sdmmc_get_cd(host->mmc)?IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING,
-                		  "sd_detect",
-                		  host);
-		if(ret < 0) {
-			dev_err(&pdev->dev, "gpio request_irq error\n");
-			goto err_gpio_free;
+
+        ret = rk29_dma_set_buffdone_fn(host->dma_info.chn, rk29_sdmmc_dma_complete);	
+		if(ret < 0)
+		{
+            printk("%s..%d..  dma_set_buffdone_fn error=%d ====xbw[%s]====\n", \
+					__FUNCTION__, __LINE__, ret, host->dma_name);
+            host->errorstep = 0x99;
+            goto err_dmaunmap;
 		}
-		host->enable_sd_warkup = pdata->enable_sd_wakeup;
-		if(host->enable_sd_warkup)
-			enable_irq_wake(host->gpio_irq);
+		
+		host->dma_addr = regs->start + SDMMC_DATA;
+	}
+
+    rk29_sdmmc_hw_init(host);
+
+    ret = request_irq(irq, rk29_sdmmc_interrupt, 0, dev_name(&pdev->dev), host);
+	if (ret)
+	{	
+
+	    printk("%s..%d..  request_irq error=%d ====xbw[%s]====\n", \
+				__FUNCTION__, __LINE__, ret, host->dma_name);
+	    host->errorstep = 0x8C;
+	    goto err_dmaunmap;
 	}
-	platform_set_drvdata(pdev, host);
-	rk29_sdmmc_write(host->regs, SDMMC_CTYPE, 0);
-	rk29_sdmmc_write(host->regs, SDMMC_RINTSTS, 0xFFFFFFFF);
-	rk29_sdmmc_write(host->regs, SDMMC_INTMASK,SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | RK29_SDMMC_ERROR_FLAGS);
-	rk29_sdmmc_write(host->regs, SDMMC_CTRL,SDMMC_CTRL_INT_ENABLE);
-	rk29_sdmmc_write(host->regs, SDMMC_CLKENA,1);
-#ifdef CONFIG_HAS_EARLYSUSPEND
-	host->early_suspend.suspend = rk29_sdmmc_early_suspend;
-	host->early_suspend.resume = rk29_sdmmc_early_resume;
-	host->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
-	register_early_suspend(&host->early_suspend);
+
+    /* setup sdmmc1 wifi card detect change */
+    if (pdata->register_status_notify) {
+        pdata->register_status_notify(rk29_sdmmc1_status_notify_cb, host);
+    }
+
+    if(RK29_CTRL_SDMMC_ID== host->pdev->id)
+    {
+        clear_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+    }
+
+
+    /* sdmmc1 wifi card slot status initially */
+    if (pdata->status) {
+        host->oldstatus = pdata->status(mmc_dev(host->mmc));
+        if (host->oldstatus)  {
+            set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+        }else {
+            clear_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+        }
+    }
+
+    /* 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); 	
+
+	mmc_add_host(mmc);
+
+#ifdef RK29_SDMMC_NOTIFY_REMOVE_INSERTION
+    
+    globalSDhost[pdev->id] = (struct rk29_sdmmc	*)host;
+    if(RK29_CTRL_SDMMC_ID== host->pdev->id)
+    {
+        rk29_sdmmc_progress_add_attr(pdev);
+    }
 #endif	
-	dev_info(host->dev, "RK29 SDMMC controller at irq %d\n", host->irq);
+	
+#if defined (CONFIG_DEBUG_FS)
+	rk29_sdmmc_init_debugfs(host);
+#endif
+
+    printk("..Line%d..The End of the SDMMC probe %s ===xbw[%s]===\n\n", __LINE__, RK29_SDMMC_VERSION,host->dma_name);
 	return 0;
-	free_irq(host->gpio_irq, host);
-err_gpio_free:
-	gpio_free(host->gpio_det);
-err_mmc_remove_host:
-	mmc_remove_host(host->mmc);
-err_free_irq:
-	free_irq(host->irq, host);
-err_rk29_dma_free:
-	rk29_dma_free(host->dma_info.chn, &host->dma_info.client);
-err_iounmap:	
+
+
+err_dmaunmap:
+	if(host->use_dma)
+	{
+	    rk29_dma_free(host->dma_info.chn, &host->dma_info.client);
+	}
+
+err_freemap:
 	iounmap(host->regs);
-err_mmc_free_host:
-	mmc_free_host(host->mmc);
 
-	while(1);
-	return ret;
+rel_regions:
+    mmc_free_host(mmc);
 
+out:
+	
+	return ret;
 }
 
 
 
 static int __exit rk29_sdmmc_remove(struct platform_device *pdev)
 {
-	struct rk29_sdmmc *host = platform_get_drvdata(pdev);
 
-	rk29_sdmmc_write(host->regs, SDMMC_RINTSTS, 0xFFFFFFFF);
-	rk29_sdmmc_write(host->regs, SDMMC_INTMASK, 0); // disable all mmc interrupt first
-	
+    struct mmc_host *mmc = platform_get_drvdata(pdev);
+    struct rk29_sdmmc *host;
+    struct resource		*regs;
+
+    if (!mmc)
+        return -1;
+
+    host = mmc_priv(mmc); 
+    
 	smp_wmb();
-	free_irq(host->gpio_irq, host);
-	gpio_free(host->gpio_det);
-	mmc_remove_host(host->mmc);
-	free_irq(host->irq, host);
-	rk29_dma_free(host->dma_info.chn, &host->dma_info.client);
-	
-	/* disable clock to CIU */
-	rk29_sdmmc_write(host->regs, SDMMC_CLKENA,0);
-	rk29_sdmmc_write(host->regs, SDMMC_CLKSRC,0);
-	
+    rk29_sdmmc_control_clock(host, 0);
+
+    /* Shutdown detect IRQ and kill detect thread */
+	del_timer_sync(&host->detect_timer);
+	del_timer_sync(&host->request_timer);
+	del_timer_sync(&host->DTO_timer);
+
+	tasklet_disable(&host->tasklet);
+	free_irq(platform_get_irq(pdev, 0), host);
+	if(host->use_dma)
+	{
+		rk29_dma_free(host->dma_info.chn, &host->dma_info.client);
+	}
+
+	mmc_remove_host(mmc);
+
 	iounmap(host->regs);
-	mmc_free_host(host->mmc);
+	
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(regs->start,resource_size(regs));  
+
+    mmc_free_host(mmc);
+    platform_set_drvdata(pdev, NULL);
+
 	return 0;
 }
-static int rk29_sdmmc_suspend(struct platform_device *pdev, pm_message_t state)
+
+
+#ifdef CONFIG_PM
+
+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(RK29_PIN2_PA2)?"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;
-#ifdef CONFIG_PM
-	struct rk29_sdmmc *host = platform_get_drvdata(pdev);
+	rk29_mux_api_set(GPIO2A2_SDMMC0DETECTN_NAME, GPIO2L_GPIO2A2);
+	gpio_request(RK29_PIN2_PA2, "sd_detect");
+	gpio_direction_input(RK29_PIN2_PA2);
+
+	host->gpio_irq = gpio_to_irq(RK29_PIN2_PA2);
+	ret = request_irq(host->gpio_irq, det_keys_isr,
+					    (gpio_get_value(RK29_PIN2_PA2))?IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING,
+					    "sd_detect",
+					    host);
+	
+	enable_irq_wake(host->gpio_irq);
 
-	dev_info(host->dev, "Enter rk29_sdmmc_suspend\n");
-	if(host->mmc && !host->is_sdio && host->gpio_det != INVALID_GPIO){
-		ret = mmc_suspend_host(host->mmc,state);
-		if(!host->enable_sd_warkup)
-			free_irq(host->gpio_irq, host);
-	}
-	rk29_sdmmc_write(host->regs, SDMMC_CLKENA, 0);
-	clk_disable(host->clk);
-#endif
 	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(RK29_PIN2_PA2);
+	rk29_mux_api_set(GPIO2A2_SDMMC0DETECTN_NAME, GPIO2L_SDMMC0_DETECT_N);
+}
 
-static int rk29_sdmmc_resume(struct platform_device *pdev)
+
+
+static int rk29_sdmmc_suspend(struct platform_device *pdev, pm_message_t state)
 {
-	int ret = 0;
-#ifdef CONFIG_PM
-	struct rk29_sdmmc *host = platform_get_drvdata(pdev);
+    struct mmc_host *mmc = platform_get_drvdata(pdev);
+    struct rk29_sdmmc *host = mmc_priv(mmc);
+    int ret = 0;
 
-	dev_info(host->dev, "Exit rk29_sdmmc_suspend\n");
-	clk_enable(host->clk);
-    rk29_sdmmc_write(host->regs, SDMMC_CLKENA, 1);
-	if(host->mmc && !host->is_sdio && host->gpio_det != INVALID_GPIO){
-		if(!host->enable_sd_warkup){
-			ret = request_irq(host->gpio_irq,
-                		  rk29_sdmmc_detect_change_isr,
-                		  rk29_sdmmc_get_cd(host->mmc)?IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING,
-                		  "sd_detect",
-                		  host);
-			if(ret < 0)
-			dev_err(host->dev, "gpio request_irq error\n");
-		}
-		host->is_init = 1;
-		ret = mmc_resume_host(host->mmc);
-		mmc_detect_change(host->mmc, 0);
+    if(host && host->pdev && (RK29_CTRL_SDMMC_ID == host->pdev->id)) //only the SDMMC0 have suspend-resume; noted by xbw
+    {
+        if (mmc)
+            ret = mmc_suspend_host(mmc, state);
+
+        if(rk29_sdmmc_sdcard_suspend(host) < 0)
+			dev_info(&host->pdev->dev, "rk29_sdmmc_sdcard_suspend error\n");
+    }
+
+    return ret;
+}
+
+static int rk29_sdmmc_resume(struct platform_device *pdev)
+{
+    struct mmc_host *mmc = platform_get_drvdata(pdev);
+    struct rk29_sdmmc *host = mmc_priv(mmc);
+    int ret = 0;
+
+    if(host && host->pdev && (RK29_CTRL_SDMMC_ID == host->pdev->id)) //only the SDMMC0 have suspend-resume; noted by xbw
+    {
+        if (mmc)
+        {
+            rk29_sdmmc_sdcard_resume(host);	
+    		ret = mmc_resume_host(mmc);
+    	}
 	}
-#endif
+
 	return ret;
 }
+#else
+#define rk29_sdmmc_suspend	NULL
+#define rk29_sdmmc_resume	NULL
+#endif
+
 static struct platform_driver rk29_sdmmc_driver = {
 	.suspend    = rk29_sdmmc_suspend,
 	.resume     = rk29_sdmmc_resume,
@@ -1553,6 +3071,6 @@ module_init(rk29_sdmmc_init);
 module_exit(rk29_sdmmc_exit);
 
 MODULE_DESCRIPTION("Rk29 Multimedia Card Interface driver");
-MODULE_AUTHOR("Rockchips");
+MODULE_AUTHOR("xbw@rock-chips.com");
 MODULE_LICENSE("GPL v2");
  
diff --git a/drivers/mmc/host/rk29_sdmmc.h b/drivers/mmc/host/rk29_sdmmc.h
new file mode 100755
index 000000000000..1f6ef4a8f89e
--- /dev/null
+++ b/drivers/mmc/host/rk29_sdmmc.h
@@ -0,0 +1,202 @@
+/* drivers/mmc/host/rk29_sdmmc.h
+ *
+ * Copyright (C) 2011 ROCKCHIP, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __RK2918_SDMMC_H
+#define __RK2918_SDMMC_H
+
+#define MAX_SG_CHN	2
+
+
+#define SDMMC_CTRL            (0x000)   //SDMMC Control register
+#define SDMMC_PWREN           (0x004)   //Power enable register
+#define SDMMC_CLKDIV          (0x008)   //Clock divider register
+#define SDMMC_CLKSRC          (0x00c)   //Clock source register
+#define SDMMC_CLKENA          (0x010)   //Clock enable register
+#define SDMMC_TMOUT           (0x014)   //Time out register
+#define SDMMC_CTYPE           (0x018)   //Card type register
+#define SDMMC_BLKSIZ          (0x01c)   //Block size register
+#define SDMMC_BYTCNT          (0x020)   //Byte count register
+#define SDMMC_INTMASK         (0x024)   //Interrupt mask register
+#define SDMMC_CMDARG          (0x028)   //Command argument register
+#define SDMMC_CMD             (0x02c)   //Command register
+#define SDMMC_RESP0           (0x030)   //Response 0 register
+#define SDMMC_RESP1           (0x034)   //Response 1 register
+#define SDMMC_RESP2           (0x038)   //Response 2 register
+#define SDMMC_RESP3           (0x03c)   //Response 3 register
+#define SDMMC_MINTSTS         (0x040)   //Masked interrupt status register
+#define SDMMC_RINTSTS         (0x044)   //Raw interrupt status register
+#define SDMMC_STATUS          (0x048)   //Status register
+#define SDMMC_FIFOTH          (0x04c)   //FIFO threshold register
+#define SDMMC_CDETECT         (0x050)   //Card detect register
+#define SDMMC_WRTPRT          (0x054)   //Write protect register
+#define SDMMC_TCBCNT          (0x05c)   //Transferred CIU card byte count
+#define SDMMC_TBBCNT          (0x060)   //Transferred host/DMA to/from BIU_FIFO byte count
+#define SDMMC_DEBNCE          (0x064)   //Card detect debounce register
+#define SDMMC_DATA            (0x100)
+
+#define RK2818_BIT(n)				(1<<(n))
+#define RK_CLEAR_BIT(n)		        (0<<(n))
+
+
+/* Control register defines (base+ 0x00)*/
+#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_FIFO_RESET     RK2818_BIT(1)
+#define SDMMC_CTRL_RESET          RK2818_BIT(0)
+
+/* Power Enable Register(base+ 0x04) */
+#define POWER_ENABLE             RK2818_BIT(0)      //Power enable
+#define POWER_DISABLE            RK_CLEAR_BIT(0)    //Power off
+
+/* SDMMC Clock source Register(base+ 0x0C) */
+#define CLK_DIV_SRC_0         (0x0)    //clock divider 0 selected
+#define CLK_DIV_SRC_1         (0x1)    //clock divider 1 selected
+#define CLK_DIV_SRC_2         (0x2)    //clock divider 2 selected
+#define CLK_DIV_SRC_3         (0x3)    //clock divider 3 selected
+
+
+/* Clock Enable register defines(base+0x10) */
+#define SDMMC_CLKEN_LOW_PWR      RK2818_BIT(16)
+#define SDMMC_CLKEN_NO_LOW_PWR   RK_CLEAR_BIT(16)   //low-power mode disabled
+#define SDMMC_CLKEN_ENABLE       RK2818_BIT(0)
+#define SDMMC_CLKEN_DISABLE      RK_CLEAR_BIT(16)   //clock disabled
+
+/* time-out register defines(base+0x14) */
+#define SDMMC_TMOUT_DATA(n)      _SBF(8, (n))
+#define SDMMC_TMOUT_DATA_MSK     0xFFFFFF00
+#define SDMMC_TMOUT_RESP(n)      ((n) & 0xFF)
+#define SDMMC_TMOUT_RESP_MSK     0xFF
+
+/* card-type register defines(base+0x18) */
+#define SDMMC_CTYPE_8BIT         RK2818_BIT(16)
+#define SDMMC_CTYPE_4BIT         RK2818_BIT(0)
+#define SDMMC_CTYPE_1BIT         RK_CLEAR_BIT(0)
+
+/* Interrupt status & mask register defines(base+0x24) */
+#define SDMMC_INT_SDIO          RK2818_BIT(16)      //SDIO interrupt
+#define SDMMC_INT_EBE           RK2818_BIT(15)      //End Bit Error(read)/Write no CRC
+#define SDMMC_INT_ACD           RK2818_BIT(14)      //Auto Command Done
+#define SDMMC_INT_SBE           RK2818_BIT(13)      //Start Bit Error
+#define SDMMC_INT_HLE           RK2818_BIT(12)      //Hardware Locked Write Error
+#define SDMMC_INT_FRUN          RK2818_BIT(11)      //FIFO Underrun/Overrun Error
+#define SDMMC_INT_HTO           RK2818_BIT(10)      //Data Starvation by Host Timeout
+#define SDMMC_INT_DRTO          RK2818_BIT(9)       //Data Read TimeOut
+#define SDMMC_INT_RTO           RK2818_BIT(8)       //Response TimeOut
+#define SDMMC_INT_DCRC          RK2818_BIT(7)       //Data CRC Error
+#define SDMMC_INT_RCRC          RK2818_BIT(6)       //Response CRC Error
+#define SDMMC_INT_RXDR          RK2818_BIT(5)       //Receive FIFO Data Request
+#define SDMMC_INT_TXDR          RK2818_BIT(4)       //Transmit FIFO Data Request
+#define SDMMC_INT_DTO			RK2818_BIT(3)       //Data Transfer Over
+#define SDMMC_INT_CMD_DONE		RK2818_BIT(2)       //Command Done
+#define SDMMC_INT_RE	        RK2818_BIT(1)       //Response Error
+#define SDMMC_INT_CD            RK2818_BIT(0)       //Card Detect
+
+/* Command register defines(base+0x2C) */
+#define SDMMC_CMD_START         RK2818_BIT(31)      //start command
+#define SDMMC_CMD_UPD_CLK       RK2818_BIT(21)      //update clock register only
+#define SDMMC_CMD_INIT          RK2818_BIT(15)      //send initialization sequence
+#define SDMMC_CMD_STOP          RK2818_BIT(14)      //stop abort command
+#define SDMMC_CMD_PRV_DAT_NO_WAIT  RK_CLEAR_BIT(13) //not wait previous data transfer complete, send command at once
+#define SDMMC_CMD_PRV_DAT_WAIT  RK2818_BIT(13)      //wait previous data transfer complete
+#define SDMMC_CMD_SEND_STOP     RK2818_BIT(12)      //send auto stop command at end of data transfer
+#define SDMMC_CMD_BLOCK_MODE    RK_CLEAR_BIT(11)    //block data transfer command
+#define SDMMC_CMD_STRM_MODE     RK2818_BIT(11)      //stream data transfer command
+#define SDMMC_CMD_DAT_READ      RK_CLEAR_BIT(10)    //read from card
+#define SDMMC_CMD_DAT_WRITE     RK2818_BIT(10)      //write to card; 
+#define SDMMC_CMD_DAT_WR        RK2818_BIT(10)      //write to card;
+#define SDMMC_CMD_DAT_NO_EXP    RK_CLEAR_BIT(9)     //no data transfer expected
+#define SDMMC_CMD_DAT_EXP       RK2818_BIT(9)       //data transfer expected
+#define SDMMC_CMD_RESP_NO_CRC   RK_CLEAR_BIT(8)     //do not check response crc
+#define SDMMC_CMD_RESP_CRC      RK2818_BIT(8)       //check response crc
+#define SDMMC_CMD_RESP_CRC_NOCARE   SDMMC_CMD_RESP_CRC  //not care response crc
+#define SDMMC_CMD_RESP_SHORT    RK_CLEAR_BIT(7)     //short response expected from card
+#define SDMMC_CMD_RESP_LONG     RK2818_BIT(7)       //long response expected from card;
+#define SDMMC_CMD_RESP_NOCARE   SDMMC_CMD_RESP_SHORT    //not care response length
+#define SDMMC_CMD_RESP_NO_EXP   RK_CLEAR_BIT(6)     //no response expected from card
+#define SDMMC_CMD_RESP_EXP      RK2818_BIT(6)       //response expected from card
+#define SDMMC_CMD_INDX(n)       ((n) & 0x1F)
+
+
+/* Status register defines (base+0x48)*/
+#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
+#define SDMMC_STAUTS_FIFO_FULL	RK2818_BIT(3)       //FIFO is full status
+#define SDMMC_STAUTS_FIFO_EMPTY	RK2818_BIT(2)       //FIFO is empty status
+
+#define SDMMC_GET_FCNT(x)       (((x)>>17) & 0x1FF)//fifo_count, numbers of filled locations in FIFO
+#define SDMMC_FIFO_SZ           32
+
+
+/* FIFO Register (base + 0x4c)*/
+#define SD_MSIZE_1        (0x0 << 28)  //DW_DMA_Multiple_Transaction_Size
+#define SD_MSIZE_4        (0x1 << 28)
+#define SD_MSIZE_8        (0x1 << 28)
+#define SD_MSIZE_16       (0x3 << 28)
+#define SD_MSIZE_32       (0x4 << 28)
+#define SD_MSIZE_64       (0x5 << 28)
+#define SD_MSIZE_128      (0x6 << 28)
+#define SD_MSIZE_256      (0x7 << 28)
+
+#define FIFO_DEPTH        (0x20)       //FIFO depth = 32 word
+#define RX_WMARK_SHIFT    (16)
+#define TX_WMARK_SHIFT    (0)
+
+/* FIFO watermark */
+#define RX_WMARK          (0xF)        //RX watermark level set to 15
+#define TX_WMARK          (0x10)       //TX watermark level set to 16
+
+
+/* CDETECT register defines (base+0x50)*/
+#define SDMMC_CARD_DETECT_N		RK2818_BIT(0)        //0--represents presence of card.
+
+/* WRIPRT register defines (base+0x54)*/
+#define SDMMC_WRITE_PROTECT		RK2818_BIT(0)       // 1--represents write protect
+
+
+
+/* Specifies how often in millisecs to poll for card removal-insertion changes
+ * when the timer switch is open */
+#define RK_SDMMC0_SWITCH_POLL_DELAY 35
+
+
+
+/* SDMMC progress  return value */
+#define SDM_SUCCESS              (0)                    
+#define SDM_FALSE                (1)             
+#define SDM_PARAM_ERROR          (2)              
+#define SDM_RESP_ERROR           (3)             
+#define SDM_RESP_TIMEOUT         (4)              
+#define SDM_DATA_CRC_ERROR       (5)              
+#define SDM_DATA_READ_TIMEOUT    (6)              
+#define SDM_END_BIT_ERROR        (7)              
+#define SDM_START_BIT_ERROR      (8)              
+#define SDM_BUSY_TIMEOUT         (9)            
+#define SDM_ERROR                (10)             //SDMMC host controller error 
+#define SDM_START_CMD_FAIL       (11)  
+#define SDM_WAIT_FOR_CMDSTART_TIMEOUT   (12)  
+#define SDM_WAIT_FOR_FIFORESET_TIMEOUT  (13)  
+
+
+
+#define FALSE			0
+#define TRUE			1
+
+
+#define DEBOUNCE_TIME         (25)     //uint is ms, recommend 5--25ms
+
+
+#endif
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 6fd20b428344..e0356644d1aa 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -569,7 +569,6 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
 	host->ioaddr = pci_ioremap_bar(pdev, bar);
 	if (!host->ioaddr) {
 		dev_err(&pdev->dev, "failed to remap registers\n");
-		ret = -ENOMEM;
 		goto release;
 	}
 
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index e6c65a78c46c..c279fbc4c2e5 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1266,13 +1266,6 @@ static void sdhci_tasklet_finish(unsigned long param)
 
 	host = (struct sdhci_host*)param;
 
-        /*
-         * If this tasklet gets rescheduled while running, it will
-         * be run again afterwards but without any active request.
-         */
-	if (!host->mrq)
-		return;
-
 	spin_lock_irqsave(&host->lock, flags);
 
 	del_timer(&host->timer);
@@ -1284,7 +1277,7 @@ static void sdhci_tasklet_finish(unsigned long param)
 	 * upon error conditions.
 	 */
 	if (!(host->flags & SDHCI_DEVICE_DEAD) &&
-	    ((mrq->cmd && mrq->cmd->error) ||
+		(mrq->cmd->error ||
 		 (mrq->data && (mrq->data->error ||
 		  (mrq->data->stop && mrq->data->stop->error))) ||
 		   (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) {
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 5689a0a889a9..4c24a7f83291 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -541,7 +541,14 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
 	int p, highest, res;
 
 	if (bdev->bd_part_count)
+	{
+	    if(179 == MAJOR(bdev->bd_dev))
+	    {
+	        printk("%s..%d.. The sdcard partition have been using.So device busy! ====xbw===\n",__FUNCTION__, __LINE__);
+	    }
+	    
 		return -EBUSY;
+	}
 	res = invalidate_partition(disk, 0);
 	if (res)
 		return res;
@@ -556,7 +563,14 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
 	check_disk_size_change(disk, bdev);
 	bdev->bd_invalidated = 0;
 	if (!get_capacity(disk) || !(state = check_partition(disk, bdev)))
+	{
+	    if(179 == MAJOR(bdev->bd_dev))
+	    {
+	        printk("%s..%d... ==== check partition fail. partitionAddr=%x ====xbw===\n",__FUNCTION__, __LINE__, state);
+	    }
+	    
 		return 0;
+	}
 	if (IS_ERR(state))	/* I/O error reading the partition table */
 		return -EIO;
 
diff --git a/fs/partitions/efi.c b/fs/partitions/efi.c
index 2aac7764b7e5..49cfd5f54238 100644
--- a/fs/partitions/efi.c
+++ b/fs/partitions/efi.c
@@ -349,12 +349,6 @@ is_gpt_valid(struct block_device *bdev, u64 lba,
 		goto fail;
 	}
 
-	/* Check that sizeof_partition_entry has the correct value */
-	if (le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) {
-		pr_debug("GUID Partitition Entry Size check failed.\n");
-		goto fail;
-	}
-
 	if (!(*ptes = alloc_read_gpt_entries(bdev, *gpt)))
 		goto fail;
 
diff --git a/fs/partitions/ldm.c b/fs/partitions/ldm.c
index dd6efdba939f..8652fb99e962 100644
--- a/fs/partitions/ldm.c
+++ b/fs/partitions/ldm.c
@@ -251,11 +251,6 @@ static bool ldm_parse_vmdb (const u8 *data, struct vmdb *vm)
 	}
 
 	vm->vblk_size     = get_unaligned_be32(data + 0x08);
-	if (vm->vblk_size == 0) {
-		ldm_error ("Illegal VBLK size");
-		return false;
-	}
-
 	vm->vblk_offset   = get_unaligned_be32(data + 0x0C);
 	vm->last_vblk_seq = get_unaligned_be32(data + 0x04);
 
@@ -1299,11 +1294,6 @@ static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags)
 
 	BUG_ON (!data || !frags);
 
-	if (size < 2 * VBLK_SIZE_HEAD) {
-		ldm_error("Value of size is to small.");
-		return false;
-	}
-
 	group = get_unaligned_be32(data + 0x08);
 	rec   = get_unaligned_be16(data + 0x0C);
 	num   = get_unaligned_be16(data + 0x0E);
@@ -1311,10 +1301,6 @@ static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags)
 		ldm_error ("A VBLK claims to have %d parts.", num);
 		return false;
 	}
-	if (rec >= num) {
-		ldm_error("REC value (%d) exceeds NUM value (%d)", rec, num);
-		return false;
-	}
 
 	list_for_each (item, frags) {
 		f = list_entry (item, struct frag, list);
@@ -1335,11 +1321,6 @@ static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags)
 
 	list_add_tail (&f->list, frags);
 found:
-	if (rec >= f->num) {
-		ldm_error("REC value (%d) exceeds NUM value (%d)", rec, f->num);
-		return false;
-	}
-
 	if (f->map & (1 << rec)) {
 		ldm_error ("Duplicate VBLK, part %d.", rec);
 		f->map &= 0x7F;			/* Mark the group as broken */
@@ -1348,9 +1329,10 @@ found:
 
 	f->map |= (1 << rec);
 
-	data += VBLK_SIZE_HEAD;
-	size -= VBLK_SIZE_HEAD;
-
+	if (num > 0) {
+		data += VBLK_SIZE_HEAD;
+		size -= VBLK_SIZE_HEAD;
+	}
 	memcpy (f->data+rec*(size-VBLK_SIZE_HEAD)+VBLK_SIZE_HEAD, data, size);
 
 	return true;
diff --git a/fs/partitions/mac.c b/fs/partitions/mac.c
index 5765198e9228..d4a0fad3563b 100644
--- a/fs/partitions/mac.c
+++ b/fs/partitions/mac.c
@@ -29,9 +29,10 @@ static inline void mac_fix_string(char *stg, int len)
 
 int mac_partition(struct parsed_partitions *state, struct block_device *bdev)
 {
+	int slot = 1;
 	Sector sect;
 	unsigned char *data;
-	int slot, blocks_in_map;
+	int blk, blocks_in_map;
 	unsigned secsize;
 #ifdef CONFIG_PPC_PMAC
 	int found_root = 0;
@@ -58,14 +59,10 @@ int mac_partition(struct parsed_partitions *state, struct block_device *bdev)
 		put_dev_sector(sect);
 		return 0;		/* not a MacOS disk */
 	}
-	blocks_in_map = be32_to_cpu(part->map_count);
-	if (blocks_in_map < 0 || blocks_in_map >= DISK_MAX_PARTS) {
-		put_dev_sector(sect);
-		return 0;
-	}
 	printk(" [mac]");
-	for (slot = 1; slot <= blocks_in_map; ++slot) {
-		int pos = slot * secsize;
+	blocks_in_map = be32_to_cpu(part->map_count);
+	for (blk = 1; blk <= blocks_in_map; ++blk) {
+		int pos = blk * secsize;
 		put_dev_sector(sect);
 		data = read_dev_sector(bdev, pos/512, &sect);
 		if (!data)
@@ -116,11 +113,13 @@ int mac_partition(struct parsed_partitions *state, struct block_device *bdev)
 			}
 
 			if (goodness > found_root_goodness) {
-				found_root = slot;
+				found_root = blk;
 				found_root_goodness = goodness;
 			}
 		}
 #endif /* CONFIG_PPC_PMAC */
+
+		++slot;
 	}
 #ifdef CONFIG_PPC_PMAC
 	if (found_root_goodness)
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
index 90be97f1f5a8..c79407ee4bbc 100644
--- a/fs/partitions/msdos.c
+++ b/fs/partitions/msdos.c
@@ -440,6 +440,11 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
 		return 0;
 	}
 
+    if(179 == MAJOR(bdev->bd_dev))
+    {
+	    printk("\n%s..%d... ==== Begin to parse sdcard-partition.  ====xbw[mmc0]===\n",__FUNCTION__, __LINE__);
+	}
+
 	/*
 	 * Now that the 55aa signature is present, this is probably
 	 * either the boot sector of a FAT filesystem or a DOS-type
@@ -449,6 +454,12 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
 	p = (struct partition *) (data + 0x1be);
 	for (slot = 1; slot <= 4; slot++, p++) {
 		if (p->boot_ind != 0 && p->boot_ind != 0x80) {
+
+		    if(179 == MAJOR(bdev->bd_dev))
+		    {
+			    printk("%s..%d... ==== The sdcard has not MBR.  ====xbw[mmc0]===\n",__FUNCTION__, __LINE__);
+			}
+
 			/*
 			 * Even without a valid boot inidicator value
 			 * its still possible this is valid FAT filesystem
@@ -459,9 +470,21 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
 				&& fat_valid_media(fb->media)) {
 				printk("\n");
 				put_dev_sector(sect);
+
+				if(179 == MAJOR(bdev->bd_dev))
+				{
+				    printk("%s..%d... ==== The DBR(slot=%d) is valid. ====xbw[mmc0]===\n",__FUNCTION__, __LINE__, slot);
+				}
+
 				return 1;
 			} else {
 				put_dev_sector(sect);
+
+				if(179 == MAJOR(bdev->bd_dev))
+				{
+				    printk("%s..%d... ==== The DBR is invalid. ====xbw[mmc0]===\n",__FUNCTION__, __LINE__);
+				}
+
 				return 0;
 			}
 		}
@@ -473,6 +496,7 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
 		/* If this is an EFI GPT disk, msdos should ignore it. */
 		if (SYS_IND(p) == EFI_PMBR_OSTYPE_EFI_GPT) {
 			put_dev_sector(sect);
+
 			return 0;
 		}
 	}
@@ -485,12 +509,24 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
 	 * On the second pass look inside *BSD, Unixware and Solaris partitions.
 	 */
 
+    if(179 == MAJOR(bdev->bd_dev))
+    {
+        printk("%s..%d... ==== The sdcard has MBR. ====xbw[mmc0]===\n", __FUNCTION__, __LINE__);
+    }
 	state->next = 5;
 	for (slot = 1 ; slot <= 4 ; slot++, p++) {
 		sector_t start = start_sect(p)*sector_size;
 		sector_t size = nr_sects(p)*sector_size;
+
 		if (!size)
 			continue;
+
+	    if(179 == MAJOR(bdev->bd_dev))
+	    {
+		    printk("%s..%d... ==== partition-%d, size=%luKB  ====xbw[mmc0]===\n",\
+		        __FUNCTION__, __LINE__, slot, size/2);
+		}
+	
 		if (is_extended_partition(p)) {
 			/*
 			 * prevent someone doing mkfs or mkswap on an
@@ -500,6 +536,11 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
 			 */
 			sector_t n = 2;
 			n = min(size, max(sector_size, n));
+			
+            if(179 == MAJOR(bdev->bd_dev))
+            {
+			    printk("%s...%d... ==== extend partition-%d....====xbw[mmc0]===\n",__FUNCTION__, __LINE__, slot);
+			}
 			put_partition(state, slot, start, n);
 
 			printk(" <");
@@ -507,6 +548,12 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
 			printk(" >");
 			continue;
 		}
+
+		if(179 == MAJOR(bdev->bd_dev))
+		{
+		    printk("%s..%d... ==== main partition-%d....====xbw[mmc0]===\n",__FUNCTION__, __LINE__, slot);
+		}
+		
 		put_partition(state, slot, start, size);
 		if (SYS_IND(p) == LINUX_RAID_PARTITION)
 			state->parts[slot].flags = 1;
diff --git a/fs/partitions/osf.c b/fs/partitions/osf.c
index 9ddca5891278..c05c17bc5df3 100644
--- a/fs/partitions/osf.c
+++ b/fs/partitions/osf.c
@@ -10,13 +10,10 @@
 #include "check.h"
 #include "osf.h"
 
-#define MAX_OSF_PARTITIONS 18
-
 int osf_partition(struct parsed_partitions *state, struct block_device *bdev)
 {
 	int i;
 	int slot = 1;
-	unsigned int npartitions;
 	Sector sect;
 	unsigned char *data;
 	struct disklabel {
@@ -48,7 +45,7 @@ int osf_partition(struct parsed_partitions *state, struct block_device *bdev)
 			u8  p_fstype;
 			u8  p_frag;
 			__le16 p_cpg;
-		} d_partitions[MAX_OSF_PARTITIONS];
+		} d_partitions[8];
 	} * label;
 	struct d_partition * partition;
 
@@ -66,12 +63,7 @@ int osf_partition(struct parsed_partitions *state, struct block_device *bdev)
 		put_dev_sector(sect);
 		return 0;
 	}
-	npartitions = le16_to_cpu(label->d_npartitions);
-	if (npartitions > MAX_OSF_PARTITIONS) {
-		put_dev_sector(sect);
-		return 0;
-	}
-	for (i = 0 ; i < npartitions; i++, partition++) {
+	for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) {
 		if (slot == state->limit)
 		        break;
 		if (le32_to_cpu(partition->p_size))
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 01f21a50a2bf..00a015a19412 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -14,7 +14,6 @@
 #include <linux/sched.h>
 
 #include <linux/mmc/core.h>
-#include <linux/mmc/pm.h>
 
 struct mmc_ios {
 	unsigned int	clock;			/* clock rate */
@@ -124,7 +123,6 @@ struct mmc_host {
 	unsigned int		f_min;
 	unsigned int		f_max;
 	u32			ocr_avail;
-	struct notifier_block	pm_notify;
 
 #define MMC_VDD_165_195		0x00000080	/* VDD voltage 1.65 - 1.95 */
 #define MMC_VDD_20_21		0x00000100	/* VDD voltage 2.0 ~ 2.1 */
@@ -182,7 +180,6 @@ struct mmc_host {
 
 	/* Only used with MMC_CAP_DISABLE */
 	int			enabled;	/* host is enabled */
-	int			rescan_disable;	/* disable card detection */
 	int			nesting_cnt;	/* "enable" nesting count */
 	int			en_dis_recurs;	/* detect recursion */
 	unsigned int		disable_delay;	/* disable delay in msecs */
@@ -203,12 +200,12 @@ struct mmc_host {
 #define MMC_BUSRESUME_MANUAL_RESUME	(1 << 0)
 #define MMC_BUSRESUME_NEEDS_RESUME	(1 << 1)
 
+    unsigned int		re_initialized_flags; //in order to begin the rescan ;  added by xbw@2011-04-07
+
 	unsigned int		sdio_irqs;
 	struct task_struct	*sdio_irq_thread;
 	atomic_t		sdio_irq_thread_abort;
 
-        mmc_pm_flag_t           pm_flags;       /* requested pm features */
-
 #ifdef CONFIG_LEDS_TRIGGERS
 	struct led_trigger	*led;		/* activity led */
 #endif
@@ -289,7 +286,6 @@ int mmc_card_can_sleep(struct mmc_host *host);
 int mmc_host_enable(struct mmc_host *host);
 int mmc_host_disable(struct mmc_host *host);
 int mmc_host_lazy_disable(struct mmc_host *host);
-int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *);
 
 static inline void mmc_set_disable_delay(struct mmc_host *host,
 					 unsigned int disable_delay)
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index c02c8db73701..b96f110efbb4 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -282,5 +282,18 @@ struct _mmc_csd {
 #define MMC_SWITCH_MODE_CLEAR_BITS	0x02	/* Clear bits which are 1 in value */
 #define MMC_SWITCH_MODE_WRITE_BYTE	0x03	/* Set target to value */
 
+
+/*
+* some limit value of SDMMC about protocol  ; Added by xbw at 2011-03-21
+*/
+#define FOD_FREQ              (300000)    //  in the identify stage, unit: hz,  max is 400Khz,
+                                       //  the least frequency is FREQ_HCLK_MAX/8
+#define SD_FPP_FREQ           (24000000)  //   normal sd freq,  25Mhz
+#define SDHC_FPP_FREQ         (49000000)  // SDHC in the highspeed. unit is hz,  max is 50Mhz.
+#define MMC_FPP_FREQ          (19000000)  // MMC freq, unit is hz,   max is 20MHz
+#define MMCHS_26_FPP_FREQ     (24000000)  //  highspeed mode support 26M  HS-MMC, unit is hz, max is 26Mhz, 
+#define MMCHS_52_FPP_FREQ     (49000000)  //  highspeed support 52M HS-MMC,   unit is hz,   max is 52Mhz,
+
+
 #endif  /* MMC_MMC_PROTOCOL_H */