|
@@ -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;
|
|
|
}
|