UPSTREAM: mmc: core: update mmc.c upstream version
authorxiaoyao <xiaoyao@rock-chips.com>
Thu, 22 Sep 2016 09:29:19 +0000 (17:29 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Fri, 23 Sep 2016 09:04:06 +0000 (17:04 +0800)
Change-Id: Ie67d23ca74708467d5af01b4ca801efa5dcd2f51
Signed-off-by: xiaoyao <xiaoyao@rock-chips.com>
drivers/mmc/core/mmc.c

index c6cf371a3e202819eb52e02cfee20152a8eedf8e..4fb06dd188c766e422ac0adfd13f4c6d8b8944eb 100644 (file)
@@ -236,8 +236,8 @@ static void mmc_select_card_type(struct mmc_card *card)
        }
 
        if ((caps2 & MMC_CAP2_HS400_ES) &&
-               card->ext_csd.strobe_support &&
-               (avail_type & EXT_CSD_CARD_TYPE_HS400))
+           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;
@@ -391,13 +391,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
                        mmc_card_set_blockaddr(card);
        }
 
-       /*
-        * Enhance Strobe is supported since v5.1 which rev should be
-        * 8 but some eMMC devices can support it with rev 7. So handle
-        * Enhance Strobe here.
-        */
        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);
 
@@ -739,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,
@@ -756,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,
@@ -774,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);
@@ -964,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
  */
@@ -981,9 +1007,15 @@ 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);
-       if (!err)
+                          true, false, true);
+       if (!err) {
                mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+               err = mmc_switch_status(card);
+       }
+
+       if (err)
+               pr_warn("%s: switch to high-speed failed, err:%d\n",
+                       mmc_hostname(card->host), err);
 
        return err;
 }
@@ -1059,23 +1091,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;
@@ -1087,9 +1105,6 @@ 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;
-
        /* Switch card to HS mode */
        val = EXT_CSD_TIMING_HS;
        err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -1109,11 +1124,9 @@ static int mmc_select_hs400(struct mmc_card *card)
        max_dtr = card->ext_csd.hs_max_dtr;
        mmc_set_clock(host, max_dtr);
 
-       if (!send_status) {
-               err = mmc_switch_status(card);
-               if (err)
-                       goto out_err;
-       }
+       err = mmc_switch_status(card);
+       if (err)
+               goto out_err;
 
        /* Switch card to DDR */
        err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -1132,7 +1145,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);
@@ -1143,11 +1156,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;
 
@@ -1165,14 +1176,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);
@@ -1187,43 +1194,37 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
 
        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);
 
@@ -1235,86 +1236,6 @@ out_err:
        return err;
 }
 
-static void mmc_select_driver_type(struct mmc_card *card)
-{
-       int card_drv_type, drive_strength, drv_type;
-
-       card_drv_type = card->ext_csd.raw_driver_strength |
-                       mmc_driver_type_mask(0);
-
-       drive_strength = mmc_select_drive_strength(card,
-                                                  card->ext_csd.hs200_max_dtr,
-                                                  card_drv_type, &drv_type);
-
-       card->drive_strength = drive_strength;
-
-       if (drv_type)
-               mmc_set_driver_type(card->host, drv_type);
-}
-
-/*
- * For device supporting HS200 mode, the following sequence
- * should be done before executing the tuning process.
- * 1. set the desired bus width(4-bit or 8-bit, 1-bit is not supported)
- * 2. switch to HS200 mode
- * 3. set the clock to > 52Mhz and <=200MHz
- */
-static int mmc_select_hs200(struct mmc_card *card)
-{
-       struct mmc_host *host = card->host;
-       bool send_status = true;
-       unsigned int old_timing;
-       int err = -EINVAL;
-       u8 val;
-
-       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 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)) {
-               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, 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)
-               pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host),
-                      __func__, err);
-       return err;
-}
-
 static int mmc_select_hs400es(struct mmc_card *card)
 {
        struct mmc_host *host = card->host;
@@ -1327,16 +1248,13 @@ static int mmc_select_hs400es(struct mmc_card *card)
        }
 
        err = mmc_select_bus_width(card);
-       if (IS_ERR_VALUE(err))
+       if (err < 0)
                goto out_err;
 
        /* Switch card to HS mode */
        err = mmc_select_hs(card);
-       if (err) {
-               pr_err("%s: switch to high-speed failed, err:%d\n",
-                       mmc_hostname(host), err);
+       if (err)
                goto out_err;
-       }
 
        err = mmc_switch_status(card);
        if (err)
@@ -1344,7 +1262,6 @@ static int mmc_select_hs400es(struct mmc_card *card)
 
        /* 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,
@@ -1364,7 +1281,7 @@ static int mmc_select_hs400es(struct mmc_card *card)
                           true, false, true);
        if (err) {
                pr_err("%s: switch to hs400es failed, err:%d\n",
-                        mmc_hostname(host), err);
+                       mmc_hostname(host), err);
                goto out_err;
        }
 
@@ -1388,8 +1305,89 @@ out_err:
        return err;
 }
 
+static void mmc_select_driver_type(struct mmc_card *card)
+{
+       int card_drv_type, drive_strength, drv_type;
+
+       card_drv_type = card->ext_csd.raw_driver_strength |
+                       mmc_driver_type_mask(0);
+
+       drive_strength = mmc_select_drive_strength(card,
+                                                  card->ext_csd.hs200_max_dtr,
+                                                  card_drv_type, &drv_type);
+
+       card->drive_strength = drive_strength;
+
+       if (drv_type)
+               mmc_set_driver_type(card->host, drv_type);
+}
+
+/*
+ * For device supporting HS200 mode, the following sequence
+ * should be done before executing the tuning process.
+ * 1. set the desired bus width(4-bit or 8-bit, 1-bit is not supported)
+ * 2. switch to HS200 mode
+ * 3. set the clock to > 52Mhz and <=200MHz
+ */
+static int mmc_select_hs200(struct mmc_card *card)
+{
+       struct mmc_host *host = card->host;
+       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);
+
+       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)
+               return err;
+
+       mmc_select_driver_type(card);
+
+       /*
+        * 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 (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, false, true);
+               if (err)
+                       goto err;
+               old_timing = host->ios.timing;
+               mmc_set_timing(host, MMC_TIMING_MMC_HS200);
+
+               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) {
+               /* 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 or HS400ES mode if supported.
+ * Activate High Speed, HS200 or HS400ES mode if supported.
  */
 static int mmc_select_timing(struct mmc_card *card)
 {
@@ -1408,21 +1406,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;
 }
 
 /*
@@ -1577,12 +1567,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 */
@@ -1671,7 +1662,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        } else if (mmc_card_hs(card)) {
                /* Select the desired bus width optionally */
                err = mmc_select_bus_width(card);
-               if (!IS_ERR_VALUE(err)) {
+               if (err > 0) {
                        err = mmc_select_hs_ddr(card);
                        if (err)
                                goto free_card;
@@ -2014,16 +2005,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;
 }
 
 /*
@@ -2051,12 +2034,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;