Merge branch 'linux-linaro-lsk-v4.4-android' of git://git.linaro.org/kernel/linux...
[firefly-linux-kernel-4.4.55.git] / drivers / mmc / core / mmc.c
index 79a0c26e14190077d707f9e0141ca230e6d13d2d..7a20989adabb5a08c119aee70e32fb277c692615 100644 (file)
@@ -235,6 +235,11 @@ static void mmc_select_card_type(struct mmc_card *card)
                avail_type |= EXT_CSD_CARD_TYPE_HS400_1_2V;
        }
 
+       if ((caps2 & MMC_CAP2_HS400_ES) &&
+           card->ext_csd.strobe_support &&
+           (avail_type & EXT_CSD_CARD_TYPE_HS400))
+               avail_type |= EXT_CSD_CARD_TYPE_HS400ES;
+
        card->ext_csd.hs_max_dtr = hs_max_dtr;
        card->ext_csd.hs200_max_dtr = hs200_max_dtr;
        card->mmc_avail_type = avail_type;
@@ -386,6 +391,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
                        mmc_card_set_blockaddr(card);
        }
 
+       card->ext_csd.strobe_support = ext_csd[EXT_CSD_STROBE_SUPPORT];
        card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE];
        mmc_select_card_type(card);
 
@@ -727,6 +733,7 @@ MMC_DEV_ATTR(enhanced_area_offset, "%llu\n",
 MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size);
 MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult);
 MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors);
+MMC_DEV_ATTR(ocr, "%08x\n", card->ocr);
 
 static ssize_t mmc_fwrev_show(struct device *dev,
                              struct device_attribute *attr,
@@ -744,6 +751,22 @@ static ssize_t mmc_fwrev_show(struct device *dev,
 
 static DEVICE_ATTR(fwrev, S_IRUGO, mmc_fwrev_show, NULL);
 
+static ssize_t mmc_dsr_show(struct device *dev,
+                           struct device_attribute *attr,
+                           char *buf)
+{
+       struct mmc_card *card = mmc_dev_to_card(dev);
+       struct mmc_host *host = card->host;
+
+       if (card->csd.dsr_imp && host->dsr_req)
+               return sprintf(buf, "0x%x\n", host->dsr);
+       else
+               /* return default DSR value */
+               return sprintf(buf, "0x%x\n", 0x404);
+}
+
+static DEVICE_ATTR(dsr, S_IRUGO, mmc_dsr_show, NULL);
+
 static struct attribute *mmc_std_attrs[] = {
        &dev_attr_cid.attr,
        &dev_attr_csd.attr,
@@ -762,6 +785,8 @@ static struct attribute *mmc_std_attrs[] = {
        &dev_attr_enhanced_area_size.attr,
        &dev_attr_raw_rpmb_size_mult.attr,
        &dev_attr_rel_sectors.attr,
+       &dev_attr_ocr.attr,
+       &dev_attr_dsr.attr,
        NULL,
 };
 ATTRIBUTE_GROUPS(mmc_std);
@@ -952,13 +977,26 @@ static int mmc_select_bus_width(struct mmc_card *card)
                        break;
                } else {
                        pr_warn("%s: switch to bus width %d failed\n",
-                               mmc_hostname(host), ext_csd_bits[idx]);
+                               mmc_hostname(host), 1 << bus_width);
                }
        }
 
        return err;
 }
 
+/* Caller must hold re-tuning */
+static int mmc_switch_status(struct mmc_card *card)
+{
+       u32 status;
+       int err;
+
+       err = mmc_send_status(card, &status);
+       if (err)
+               return err;
+
+       return mmc_switch_status_error(card->host, status);
+}
+
 /*
  * Switch to the high-speed mode
  */
@@ -969,10 +1007,14 @@ static int mmc_select_hs(struct mmc_card *card)
        err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                           EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
                           card->ext_csd.generic_cmd6_time,
-                          true, true, true);
+                          true, false, true);
        if (!err)
                mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
 
+       if (err)
+               pr_warn("%s: switch to high-speed failed, err:%d\n",
+                       mmc_hostname(card->host), err);
+
        return err;
 }
 
@@ -1047,23 +1089,9 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
        return err;
 }
 
-/* Caller must hold re-tuning */
-static int mmc_switch_status(struct mmc_card *card)
-{
-       u32 status;
-       int err;
-
-       err = mmc_send_status(card, &status);
-       if (err)
-               return err;
-
-       return mmc_switch_status_error(card->host, status);
-}
-
 static int mmc_select_hs400(struct mmc_card *card)
 {
        struct mmc_host *host = card->host;
-       bool send_status = true;
        unsigned int max_dtr;
        int err = 0;
        u8 val;
@@ -1075,19 +1103,12 @@ static int mmc_select_hs400(struct mmc_card *card)
              host->ios.bus_width == MMC_BUS_WIDTH_8))
                return 0;
 
-       if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
-               send_status = false;
-
-       /* Reduce frequency to HS frequency */
-       max_dtr = card->ext_csd.hs_max_dtr;
-       mmc_set_clock(host, max_dtr);
-
        /* Switch card to HS mode */
        val = EXT_CSD_TIMING_HS;
        err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                           EXT_CSD_HS_TIMING, val,
                           card->ext_csd.generic_cmd6_time,
-                          true, send_status, true);
+                          true, false, true);
        if (err) {
                pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
                        mmc_hostname(host), err);
@@ -1097,11 +1118,13 @@ static int mmc_select_hs400(struct mmc_card *card)
        /* Set host controller to HS timing */
        mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
 
-       if (!send_status) {
-               err = mmc_switch_status(card);
-               if (err)
-                       goto out_err;
-       }
+       /* Reduce frequency to HS frequency */
+       max_dtr = card->ext_csd.hs_max_dtr;
+       mmc_set_clock(host, max_dtr);
+
+       err = mmc_switch_status(card);
+       if (err)
+               goto out_err;
 
        /* Switch card to DDR */
        err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -1120,7 +1143,7 @@ static int mmc_select_hs400(struct mmc_card *card)
        err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                           EXT_CSD_HS_TIMING, val,
                           card->ext_csd.generic_cmd6_time,
-                          true, send_status, true);
+                          true, false, true);
        if (err) {
                pr_err("%s: switch to hs400 failed, err:%d\n",
                         mmc_hostname(host), err);
@@ -1131,11 +1154,9 @@ static int mmc_select_hs400(struct mmc_card *card)
        mmc_set_timing(host, MMC_TIMING_MMC_HS400);
        mmc_set_bus_speed(card);
 
-       if (!send_status) {
-               err = mmc_switch_status(card);
-               if (err)
-                       goto out_err;
-       }
+       err = mmc_switch_status(card);
+       if (err)
+               goto out_err;
 
        return 0;
 
@@ -1153,14 +1174,10 @@ int mmc_hs200_to_hs400(struct mmc_card *card)
 int mmc_hs400_to_hs200(struct mmc_card *card)
 {
        struct mmc_host *host = card->host;
-       bool send_status = true;
        unsigned int max_dtr;
        int err;
        u8 val;
 
-       if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
-               send_status = false;
-
        /* Reduce frequency to HS */
        max_dtr = card->ext_csd.hs_max_dtr;
        mmc_set_clock(host, max_dtr);
@@ -1169,49 +1186,43 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
        val = EXT_CSD_TIMING_HS;
        err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
                           val, card->ext_csd.generic_cmd6_time,
-                          true, send_status, true);
+                          true, false, true);
        if (err)
                goto out_err;
 
        mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
 
-       if (!send_status) {
-               err = mmc_switch_status(card);
-               if (err)
-                       goto out_err;
-       }
+       err = mmc_switch_status(card);
+       if (err)
+               goto out_err;
 
        /* Switch HS DDR to HS */
        err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
                           EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time,
-                          true, send_status, true);
+                          true, false, true);
        if (err)
                goto out_err;
 
        mmc_set_timing(host, MMC_TIMING_MMC_HS);
 
-       if (!send_status) {
-               err = mmc_switch_status(card);
-               if (err)
-                       goto out_err;
-       }
+       err = mmc_switch_status(card);
+       if (err)
+               goto out_err;
 
        /* Switch HS to HS200 */
        val = EXT_CSD_TIMING_HS200 |
              card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
        err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
-                          val, card->ext_csd.generic_cmd6_time, true,
-                          send_status, true);
+                          val, card->ext_csd.generic_cmd6_time,
+                          true, false, true);
        if (err)
                goto out_err;
 
        mmc_set_timing(host, MMC_TIMING_MMC_HS200);
 
-       if (!send_status) {
-               err = mmc_switch_status(card);
-               if (err)
-                       goto out_err;
-       }
+       err = mmc_switch_status(card);
+       if (err)
+               goto out_err;
 
        mmc_set_bus_speed(card);
 
@@ -1223,6 +1234,87 @@ out_err:
        return err;
 }
 
+static int mmc_select_hs400es(struct mmc_card *card)
+{
+       struct mmc_host *host = card->host;
+       int err = 0;
+       u8 val;
+
+       if (!(host->caps & MMC_CAP_8_BIT_DATA)) {
+               err = -ENOTSUPP;
+               goto out_err;
+       }
+
+       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
+               err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
+
+       if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
+               err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
+
+       /* If fails try again during next card power cycle */
+       if (err)
+               goto out_err;
+
+       err = mmc_select_bus_width(card);
+       if (err < 0)
+               goto out_err;
+
+       /* Switch card to HS mode */
+       err = mmc_select_hs(card);
+       if (err)
+               goto out_err;
+
+       mmc_set_clock(host, card->ext_csd.hs_max_dtr);
+
+       err = mmc_switch_status(card);
+       if (err)
+               goto out_err;
+
+       /* Switch card to DDR with strobe bit */
+       val = EXT_CSD_DDR_BUS_WIDTH_8 | EXT_CSD_BUS_WIDTH_STROBE;
+       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                        EXT_CSD_BUS_WIDTH,
+                        val,
+                        card->ext_csd.generic_cmd6_time);
+       if (err) {
+               pr_err("%s: switch to bus width for hs400es failed, err:%d\n",
+                       mmc_hostname(host), err);
+               goto out_err;
+       }
+
+       /* Switch card to HS400 */
+       val = EXT_CSD_TIMING_HS400 |
+             card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
+       err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                          EXT_CSD_HS_TIMING, val,
+                          card->ext_csd.generic_cmd6_time,
+                          true, false, true);
+       if (err) {
+               pr_err("%s: switch to hs400es failed, err:%d\n",
+                       mmc_hostname(host), err);
+               goto out_err;
+       }
+
+       /* Set host controller to HS400 timing and frequency */
+       mmc_set_timing(host, MMC_TIMING_MMC_HS400);
+
+       /* Controller enable enhanced strobe function */
+       host->ios.enhanced_strobe = true;
+       if (host->ops->hs400_enhanced_strobe)
+               host->ops->hs400_enhanced_strobe(host, &host->ios);
+
+       err = mmc_switch_status(card);
+       if (err)
+               goto out_err;
+
+       return 0;
+
+out_err:
+       pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host),
+              __func__, err);
+       return err;
+}
+
 static void mmc_select_driver_type(struct mmc_card *card)
 {
        int card_drv_type, drive_strength, drv_type;
@@ -1250,11 +1342,11 @@ static void mmc_select_driver_type(struct mmc_card *card)
 static int mmc_select_hs200(struct mmc_card *card)
 {
        struct mmc_host *host = card->host;
-       bool send_status = true;
-       unsigned int old_timing;
+       unsigned int old_timing, old_signal_voltage;
        int err = -EINVAL;
        u8 val;
 
+       old_signal_voltage = host->ios.signal_voltage;
        if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
                err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
@@ -1263,48 +1355,41 @@ static int mmc_select_hs200(struct mmc_card *card)
 
        /* If fails try again during next card power cycle */
        if (err)
-               goto err;
+               return err;
 
        mmc_select_driver_type(card);
 
-       if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
-               send_status = false;
-
        /*
         * Set the bus width(4 or 8) with host's support and
         * switch to HS200 mode if bus width is set successfully.
         */
        err = mmc_select_bus_width(card);
-       if (!IS_ERR_VALUE(err)) {
+       if (err > 0) {
                val = EXT_CSD_TIMING_HS200 |
                      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
                err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                   EXT_CSD_HS_TIMING, val,
                                   card->ext_csd.generic_cmd6_time,
-                                  true, send_status, true);
+                                  true, false, true);
                if (err)
                        goto err;
                old_timing = host->ios.timing;
                mmc_set_timing(host, MMC_TIMING_MMC_HS200);
-               if (!send_status) {
-                       err = mmc_switch_status(card);
-                       /*
-                        * mmc_select_timing() assumes timing has not changed if
-                        * it is a switch error.
-                        */
-                       if (err == -EBADMSG)
-                               mmc_set_timing(host, old_timing);
-               }
        }
 err:
-       if (err)
+       if (err) {
+               /* fall back to the old signal voltage, if fails report error */
+               if (__mmc_set_signal_voltage(host, old_signal_voltage))
+                       err = -EIO;
+
                pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host),
                       __func__, err);
+       }
        return err;
 }
 
 /*
- * Activate High Speed or HS200 mode if supported.
+ * Activate High Speed, HS200 or HS400ES mode if supported.
  */
 static int mmc_select_timing(struct mmc_card *card)
 {
@@ -1313,7 +1398,9 @@ static int mmc_select_timing(struct mmc_card *card)
        if (!mmc_can_ext_csd(card))
                goto bus_speed;
 
-       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
+       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400ES)
+               err = mmc_select_hs400es(card);
+       else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
                err = mmc_select_hs200(card);
        else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
                err = mmc_select_hs(card);
@@ -1321,21 +1408,13 @@ static int mmc_select_timing(struct mmc_card *card)
        if (err && err != -EBADMSG)
                return err;
 
-       if (err) {
-               pr_warn("%s: switch to %s failed\n",
-                       mmc_card_hs(card) ? "high-speed" :
-                       (mmc_card_hs200(card) ? "hs200" : ""),
-                       mmc_hostname(card->host));
-               err = 0;
-       }
-
 bus_speed:
        /*
         * Set the bus speed to the selected bus timing.
         * If timing is not selected, backward compatible is the default.
         */
        mmc_set_bus_speed(card);
-       return err;
+       return 0;
 }
 
 /*
@@ -1490,12 +1569,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                if (err)
                        goto free_card;
 
-               /* If doing byte addressing, check if required to do sector
+               /*
+                * If doing byte addressing, check if required to do sector
                 * addressing.  Handle the case of <2GB cards needing sector
                 * addressing.  See section 8.1 JEDEC Standard JED84-A441;
                 * ocr register has bit 30 set for sector addressing.
                 */
-               if (!(mmc_card_blockaddr(card)) && (rocr & (1<<30)))
+               if (rocr & BIT(30))
                        mmc_card_set_blockaddr(card);
 
                /* Erase size depends on CSD and Extended CSD */
@@ -1584,7 +1664,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        } else {
                /* Select the desired bus width optionally */
                err = mmc_select_bus_width(card);
-               if (!IS_ERR_VALUE(err) && mmc_card_hs(card)) {
+               if (err > 0 && mmc_card_hs(card)) {
                        err = mmc_select_hs_ddr(card);
                        if (err)
                                goto free_card;
@@ -1868,6 +1948,7 @@ static int mmc_suspend(struct mmc_host *host)
 static int _mmc_resume(struct mmc_host *host)
 {
        int err = 0;
+       int i;
 
        BUG_ON(!host);
        BUG_ON(!host->card);
@@ -1877,8 +1958,22 @@ static int _mmc_resume(struct mmc_host *host)
        if (!mmc_card_suspended(host->card))
                goto out;
 
-       mmc_power_up(host, host->card->ocr);
-       err = mmc_init_card(host, host->card->ocr, host->card);
+       /*
+        * Let's try to fallback the host->f_init
+        * if failing to init mmc card after resume.
+        */
+       for (i = 0; i < ARRAY_SIZE(freqs); i++) {
+               if (host->f_init < max(freqs[i], host->f_min))
+                       continue;
+               else
+                       host->f_init = max(freqs[i], host->f_min);
+
+               mmc_power_up(host, host->card->ocr);
+               err = mmc_init_card(host, host->card->ocr, host->card);
+               if (!err)
+                       break;
+       }
+
        mmc_card_clr_suspended(host->card);
 
 out:
@@ -1912,16 +2007,8 @@ static int mmc_shutdown(struct mmc_host *host)
  */
 static int mmc_resume(struct mmc_host *host)
 {
-       int err = 0;
-
-       if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) {
-               err = _mmc_resume(host);
-               pm_runtime_set_active(&host->card->dev);
-               pm_runtime_mark_last_busy(&host->card->dev);
-       }
        pm_runtime_enable(&host->card->dev);
-
-       return err;
+       return 0;
 }
 
 /*
@@ -1949,12 +2036,9 @@ static int mmc_runtime_resume(struct mmc_host *host)
 {
        int err;
 
-       if (!(host->caps & (MMC_CAP_AGGRESSIVE_PM | MMC_CAP_RUNTIME_RESUME)))
-               return 0;
-
        err = _mmc_resume(host);
-       if (err)
-               pr_err("%s: error %d doing aggressive resume\n",
+       if (err && err != -ENOMEDIUM)
+               pr_err("%s: error %d doing runtime resume\n",
                        mmc_hostname(host), err);
 
        return 0;