]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/mmc/core/sdio.c
Merge branch 'fix/asoc' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[mv-sheeva.git] / drivers / mmc / core / sdio.c
index c3ad1058cd318627b8290c756c6a2f2e0d2d8027..ebc62ad4cc567b7aee3313835050770dd1ff14f0 100644 (file)
@@ -547,9 +547,11 @@ static void mmc_sdio_detect(struct mmc_host *host)
        BUG_ON(!host->card);
 
        /* Make sure card is powered before detecting it */
-       err = pm_runtime_get_sync(&host->card->dev);
-       if (err < 0)
-               goto out;
+       if (host->caps & MMC_CAP_POWER_OFF_CARD) {
+               err = pm_runtime_get_sync(&host->card->dev);
+               if (err < 0)
+                       goto out;
+       }
 
        mmc_claim_host(host);
 
@@ -560,6 +562,20 @@ static void mmc_sdio_detect(struct mmc_host *host)
 
        mmc_release_host(host);
 
+       /*
+        * Tell PM core it's OK to power off the card now.
+        *
+        * The _sync variant is used in order to ensure that the card
+        * is left powered off in case an error occurred, and the card
+        * is going to be removed.
+        *
+        * Since there is no specific reason to believe a new user
+        * is about to show up at this point, the _sync variant is
+        * desirable anyway.
+        */
+       if (host->caps & MMC_CAP_POWER_OFF_CARD)
+               pm_runtime_put_sync(&host->card->dev);
+
 out:
        if (err) {
                mmc_sdio_remove(host);
@@ -568,9 +584,6 @@ out:
                mmc_detach_bus(host);
                mmc_release_host(host);
        }
-
-       /* Tell PM core that we're done */
-       pm_runtime_put(&host->card->dev);
 }
 
 /*
@@ -614,15 +627,27 @@ static int mmc_sdio_suspend(struct mmc_host *host)
 
 static int mmc_sdio_resume(struct mmc_host *host)
 {
-       int i, err;
+       int i, err = 0;
 
        BUG_ON(!host);
        BUG_ON(!host->card);
 
        /* Basic card reinitialization. */
        mmc_claim_host(host);
-       err = mmc_sdio_init_card(host, host->ocr, host->card,
+
+       /* No need to reinitialize powered-resumed nonremovable cards */
+       if (mmc_card_is_removable(host) || !mmc_card_is_powered_resumed(host))
+               err = mmc_sdio_init_card(host, host->ocr, host->card,
                                 (host->pm_flags & MMC_PM_KEEP_POWER));
+       else if (mmc_card_is_powered_resumed(host)) {
+               /* We may have switched to 1-bit mode during suspend */
+               err = sdio_enable_4bit_bus(host->card);
+               if (err > 0) {
+                       mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
+                       err = 0;
+               }
+       }
+
        if (!err && host->sdio_irqs)
                mmc_signal_sdio_irq(host);
        mmc_release_host(host);
@@ -677,16 +702,22 @@ static const struct mmc_bus_ops mmc_sdio_ops = {
 /*
  * Starting point for SDIO card init.
  */
-int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
+int mmc_attach_sdio(struct mmc_host *host)
 {
-       int err;
-       int i, funcs;
+       int err, i, funcs;
+       u32 ocr;
        struct mmc_card *card;
 
        BUG_ON(!host);
        WARN_ON(!host->claimed);
 
+       err = mmc_send_io_op_cond(host, 0, &ocr);
+       if (err)
+               return err;
+
        mmc_attach_bus(host, &mmc_sdio_ops);
+       if (host->ocr_avail_sdio)
+               host->ocr_avail = host->ocr_avail_sdio;
 
        /*
         * Sanity check the voltages that the card claims to
@@ -718,16 +749,21 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
        card = host->card;
 
        /*
-        * Let runtime PM core know our card is active
+        * Enable runtime PM only if supported by host+card+board
         */
-       err = pm_runtime_set_active(&card->dev);
-       if (err)
-               goto remove;
+       if (host->caps & MMC_CAP_POWER_OFF_CARD) {
+               /*
+                * Let runtime PM core know our card is active
+                */
+               err = pm_runtime_set_active(&card->dev);
+               if (err)
+                       goto remove;
 
-       /*
-        * Enable runtime PM for this card
-        */
-       pm_runtime_enable(&card->dev);
+               /*
+                * Enable runtime PM for this card
+                */
+               pm_runtime_enable(&card->dev);
+       }
 
        /*
         * The number of functions on the card is encoded inside
@@ -745,16 +781,16 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
                        goto remove;
 
                /*
-                * Enable Runtime PM for this func
+                * Enable Runtime PM for this func (if supported)
                 */
-               pm_runtime_enable(&card->sdio_func[i]->dev);
+               if (host->caps & MMC_CAP_POWER_OFF_CARD)
+                       pm_runtime_enable(&card->sdio_func[i]->dev);
        }
 
-       mmc_release_host(host);
-
        /*
         * First add the card to the driver model...
         */
+       mmc_release_host(host);
        err = mmc_add_card(host->card);
        if (err)
                goto remove_added;
@@ -768,6 +804,7 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
                        goto remove_added;
        }
 
+       mmc_claim_host(host);
        return 0;
 
 
@@ -777,11 +814,12 @@ remove_added:
        mmc_claim_host(host);
 remove:
        /* And with lock if it hasn't been added. */
+       mmc_release_host(host);
        if (host->card)
                mmc_sdio_remove(host);
+       mmc_claim_host(host);
 err:
        mmc_detach_bus(host);
-       mmc_release_host(host);
 
        printk(KERN_ERR "%s: error %d whilst initialising SDIO card\n",
                mmc_hostname(host), err);