Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / drivers / mmc / core / sd.c
index ff27741..633975f 100644 (file)
@@ -409,52 +409,62 @@ out:
 
 static int sd_select_driver_type(struct mmc_card *card, u8 *status)
 {
-       int host_drv_type = 0, card_drv_type = 0;
+       int host_drv_type = SD_DRIVER_TYPE_B;
+       int card_drv_type = SD_DRIVER_TYPE_B;
+       int drive_strength;
        int err;
 
        /*
         * If the host doesn't support any of the Driver Types A,C or D,
-        * default Driver Type B is used.
+        * or there is no board specific handler then default Driver
+        * Type B is used.
         */
        if (!(card->host->caps & (MMC_CAP_DRIVER_TYPE_A | MMC_CAP_DRIVER_TYPE_C
            | MMC_CAP_DRIVER_TYPE_D)))
                return 0;
 
-       if (card->host->caps & MMC_CAP_DRIVER_TYPE_A) {
-               host_drv_type = MMC_SET_DRIVER_TYPE_A;
-               if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A)
-                       card_drv_type = MMC_SET_DRIVER_TYPE_A;
-               else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_B)
-                       card_drv_type = MMC_SET_DRIVER_TYPE_B;
-               else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
-                       card_drv_type = MMC_SET_DRIVER_TYPE_C;
-       } else if (card->host->caps & MMC_CAP_DRIVER_TYPE_C) {
-               host_drv_type = MMC_SET_DRIVER_TYPE_C;
-               if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
-                       card_drv_type = MMC_SET_DRIVER_TYPE_C;
-       } else if (!(card->host->caps & MMC_CAP_DRIVER_TYPE_D)) {
-               /*
-                * If we are here, that means only the default driver type
-                * B is supported by the host.
-                */
-               host_drv_type = MMC_SET_DRIVER_TYPE_B;
-               if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_B)
-                       card_drv_type = MMC_SET_DRIVER_TYPE_B;
-               else if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
-                       card_drv_type = MMC_SET_DRIVER_TYPE_C;
-       }
+       if (!card->host->ops->select_drive_strength)
+               return 0;
+
+       if (card->host->caps & MMC_CAP_DRIVER_TYPE_A)
+               host_drv_type |= SD_DRIVER_TYPE_A;
+
+       if (card->host->caps & MMC_CAP_DRIVER_TYPE_C)
+               host_drv_type |= SD_DRIVER_TYPE_C;
+
+       if (card->host->caps & MMC_CAP_DRIVER_TYPE_D)
+               host_drv_type |= SD_DRIVER_TYPE_D;
+
+       if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A)
+               card_drv_type |= SD_DRIVER_TYPE_A;
+
+       if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C)
+               card_drv_type |= SD_DRIVER_TYPE_C;
+
+       if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_D)
+               card_drv_type |= SD_DRIVER_TYPE_D;
+
+       /*
+        * The drive strength that the hardware can support
+        * depends on the board design.  Pass the appropriate
+        * information and let the hardware specific code
+        * return what is possible given the options
+        */
+       drive_strength = card->host->ops->select_drive_strength(
+               card->sw_caps.uhs_max_dtr,
+               host_drv_type, card_drv_type);
 
-       err = mmc_sd_switch(card, 1, 2, card_drv_type, status);
+       err = mmc_sd_switch(card, 1, 2, drive_strength, status);
        if (err)
                return err;
 
-       if ((status[15] & 0xF) != card_drv_type) {
-               printk(KERN_WARNING "%s: Problem setting driver strength!\n",
+       if ((status[15] & 0xF) != drive_strength) {
+               printk(KERN_WARNING "%s: Problem setting drive strength!\n",
                        mmc_hostname(card->host));
                return 0;
        }
 
-       mmc_set_driver_type(card->host, host_drv_type);
+       mmc_set_driver_type(card->host, drive_strength);
 
        return 0;
 }