Merge tag 'gfs2-merge-window' of git://git.kernel.org:/pub/scm/linux/kernel/git/gfs2...
[firefly-linux-kernel-4.4.55.git] / drivers / mmc / host / sdhci.c
index 58c1770e879d6b73bc9edafa634e0af849f818a8..bc1445238fb3053b8d2a03a7bb35a25ddfff4b61 100644 (file)
@@ -834,7 +834,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
                        int sg_cnt;
 
                        sg_cnt = sdhci_pre_dma_transfer(host, data, NULL);
-                       if (sg_cnt == 0) {
+                       if (sg_cnt <= 0) {
                                /*
                                 * This only happens when someone fed
                                 * us an invalid request.
@@ -1514,8 +1514,17 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
                        ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK;
                        if (ios->drv_type == MMC_SET_DRIVER_TYPE_A)
                                ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A;
+                       else if (ios->drv_type == MMC_SET_DRIVER_TYPE_B)
+                               ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B;
                        else if (ios->drv_type == MMC_SET_DRIVER_TYPE_C)
                                ctrl_2 |= SDHCI_CTRL_DRV_TYPE_C;
+                       else if (ios->drv_type == MMC_SET_DRIVER_TYPE_D)
+                               ctrl_2 |= SDHCI_CTRL_DRV_TYPE_D;
+                       else {
+                               pr_warn("%s: invalid driver type, default to "
+                                       "driver type B\n", mmc_hostname(mmc));
+                               ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B;
+                       }
 
                        sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
                } else {
@@ -2039,6 +2048,18 @@ out_unlock:
        return err;
 }
 
+static int sdhci_select_drive_strength(struct mmc_card *card,
+                                      unsigned int max_dtr, int host_drv,
+                                      int card_drv, int *drv_type)
+{
+       struct sdhci_host *host = mmc_priv(card->host);
+
+       if (!host->ops->select_drive_strength)
+               return 0;
+
+       return host->ops->select_drive_strength(host, card, max_dtr, host_drv,
+                                               card_drv, drv_type);
+}
 
 static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)
 {
@@ -2183,6 +2204,7 @@ static const struct mmc_host_ops sdhci_ops = {
        .start_signal_voltage_switch    = sdhci_start_signal_voltage_switch,
        .prepare_hs400_tuning           = sdhci_prepare_hs400_tuning,
        .execute_tuning                 = sdhci_execute_tuning,
+       .select_drive_strength          = sdhci_select_drive_strength,
        .card_event                     = sdhci_card_event,
        .card_busy      = sdhci_card_busy,
 };
@@ -3234,13 +3256,14 @@ int sdhci_add_host(struct sdhci_host *host)
                                   SDHCI_MAX_CURRENT_MULTIPLIER;
        }
 
-       /* If OCR set by external regulators, use it instead */
+       /* If OCR set by host, use it instead. */
+       if (host->ocr_mask)
+               ocr_avail = host->ocr_mask;
+
+       /* If OCR set by external regulators, give it highest prio. */
        if (mmc->ocr_avail)
                ocr_avail = mmc->ocr_avail;
 
-       if (host->ocr_mask)
-               ocr_avail &= host->ocr_mask;
-
        mmc->ocr_avail = ocr_avail;
        mmc->ocr_avail_sdio = ocr_avail;
        if (host->ocr_avail_sdio)