Merge remote-tracking branch 'remotes/kernel-2.6.32/develop' into develop-2.6.36
[firefly-linux-kernel-4.4.55.git] / drivers / mmc / core / core.c
index 73e56f2da61f703a3207fdc915b64bc950091a94..3c7e63b416ef96c0b1bc3ee8fb62733fbac52ff8 100644 (file)
@@ -218,7 +218,11 @@ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
 
        mmc_start_request(host, mrq);
 
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+    wait_for_completion_timeout(&complete,HZ*3); //for cmd dead. Modifyed by xbw at 2011-06-02
+#else    
        wait_for_completion(&complete);
+#endif
 }
 
 EXPORT_SYMBOL(mmc_wait_for_req);
@@ -1428,6 +1432,155 @@ int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
 }
 EXPORT_SYMBOL(mmc_erase_group_aligned);
 
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)  
+void mmc_rescan(struct work_struct *work)
+{
+       struct mmc_host *host =
+               container_of(work, struct mmc_host, detect.work);
+       u32 ocr;
+       int err;
+       int extend_wakelock = 0;
+
+    
+       mmc_bus_get(host);
+
+       /* if there is a card registered, check whether it is still present */
+       if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead)
+               host->bus_ops->detect(host);
+
+       /* If the card was removed the bus will be marked
+        * as dead - extend the wakelock so userspace
+        * can respond */
+       if (host->bus_dead)
+               extend_wakelock = 1;
+
+       mmc_bus_put(host);
+
+
+       mmc_bus_get(host);
+
+       /* if there still is a card present, stop here */
+       if (host->bus_ops != NULL) {
+               mmc_bus_put(host);
+               goto out;
+       }
+
+       /* detect a newly inserted card */
+
+       /*
+        * Only we can add a new handler, so it's safe to
+        * 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);
+
+    /*
+        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
+               wake_unlock(&mmc_delayed_work_wake_lock);
+
+       if (host->caps & MMC_CAP_NEEDS_POLL)
+               mmc_schedule_delayed_work(&host->detect, HZ);
+}
+
+#else
 void mmc_rescan(struct work_struct *work)
 {
        struct mmc_host *host =
@@ -1436,6 +1589,20 @@ void mmc_rescan(struct work_struct *work)
        int err;
        unsigned long flags;
        int extend_wakelock = 0;
+       
+#if defined(CONFIG_SDMMC_RK29) && defined(CONFIG_SDMMC_RK29_OLD)       
+       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);
+#endif
+
 
        spin_lock_irqsave(&host->lock, flags);
 
@@ -1542,6 +1709,7 @@ out:
        if (host->caps & MMC_CAP_NEEDS_POLL)
                mmc_schedule_delayed_work(&host->detect, HZ);
 }
+#endif
 
 void mmc_start_host(struct mmc_host *host)
 {
@@ -1680,6 +1848,10 @@ int mmc_suspend_host(struct mmc_host *host)
        if (host->bus_ops && !host->bus_dead) {
                if (host->bus_ops->suspend)
                        err = host->bus_ops->suspend(host);
+                       
+#if defined(CONFIG_SDMMC_RK29) && defined(CONFIG_SDMMC_RK29_OLD)
+        //deleted all detail code.
+#else
                if (err == -ENOSYS || !host->bus_ops->resume) {
                        /*
                         * We simply "remove" the card in this case.
@@ -1693,6 +1865,7 @@ int mmc_suspend_host(struct mmc_host *host)
                        host->pm_flags = 0;
                        err = 0;
                }
+#endif         
        }
        mmc_bus_put(host);
 
@@ -1725,6 +1898,8 @@ int mmc_resume_host(struct mmc_host *host)
                        mmc_select_voltage(host, host->ocr);
                }
                BUG_ON(!host->bus_ops->resume);
+               
+#if defined(CONFIG_SDMMC_RK29) && defined(CONFIG_SDMMC_RK29_OLD)
                err = host->bus_ops->resume(host);
                if (err) {
                        printk(KERN_WARNING "%s: error %d during resume "
@@ -1732,6 +1907,20 @@ int mmc_resume_host(struct mmc_host *host)
                                            mmc_hostname(host), err);
                        err = 0;
                }
+
+#elif defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)  
+        //panic if the card is being removed during the resume, deleted by xbw at 2011-06-20
+               host->bus_ops->resume(host);
+
+#else
+               err = host->bus_ops->resume(host);
+               if (err) {
+                       printk(KERN_WARNING "%s: error %d during resume "
+                                           "(card was removed?)\n",
+                                           mmc_hostname(host), err);
+                       err = 0;
+               }               
+#endif
        }
        mmc_bus_put(host);
 
@@ -1779,6 +1968,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
 
        case PM_POST_SUSPEND:
        case PM_POST_HIBERNATION:
+       case PM_POST_RESTORE:
 
                spin_lock_irqsave(&host->lock, flags);
                if (mmc_bus_manual_resume(host)) {