SD(io)/(e)MMC: update mmc flow, continue commit-sha19896ff517b38c2c2db17980a71dca8cd2...
authorlintao <lintao@rock-chips.com>
Mon, 5 Aug 2013 02:38:52 +0000 (10:38 +0800)
committerlintao <lintao@rock-chips.com>
Mon, 5 Aug 2013 02:39:07 +0000 (10:39 +0800)
drivers/mmc/core/core.c
drivers/mmc/core/core.h [changed mode: 0644->0755]
drivers/mmc/core/mmc.c
include/linux/mmc/card.h
include/linux/mmc/host.h
include/linux/mmc/mmc.h [changed mode: 0644->0755]

index 1cbef4174f302ffd33f893e63f48408912f9535e..59509b18d8146c4cf81f266ffdbdda921e6b9c5b 100755 (executable)
@@ -2291,6 +2291,70 @@ int mmc_card_can_sleep(struct mmc_host *host)
 }
 EXPORT_SYMBOL(mmc_card_can_sleep);
 
+/*
+ * Flush the cache to the non-volatile storage.
+ */
+int mmc_flush_cache(struct mmc_card *card)
+{
+       struct mmc_host *host = card->host;
+       int err = 0;
+
+       if (!(host->caps2 & MMC_CAP2_CACHE_CTRL))
+               return err;
+
+       if (mmc_card_mmc(card) &&
+                       (card->ext_csd.cache_size > 0) &&
+                       (card->ext_csd.cache_ctrl & 1)) {
+               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                               EXT_CSD_FLUSH_CACHE, 1, 0);
+               if (err)
+                       pr_err("%s: cache flush error %d\n",
+                                       mmc_hostname(card->host), err);
+       }
+
+       return err;
+}
+EXPORT_SYMBOL(mmc_flush_cache);
+
+/*
+ * Turn the cache ON/OFF.
+ * Turning the cache OFF shall trigger flushing of the data
+ * to the non-volatile storage.
+ * This function should be called with host claimed
+ */
+int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
+{
+       struct mmc_card *card = host->card;
+       unsigned int timeout;
+       int err = 0;
+
+       if (!(host->caps2 & MMC_CAP2_CACHE_CTRL) ||
+                       mmc_card_is_removable(host))
+               return err;
+
+       if (card && mmc_card_mmc(card) &&
+                       (card->ext_csd.cache_size > 0)) {
+               enable = !!enable;
+
+               if (card->ext_csd.cache_ctrl ^ enable) {
+                       timeout = enable ? card->ext_csd.generic_cmd6_time : 0;
+                       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                                       EXT_CSD_CACHE_CTRL, enable, timeout);
+                       if (err)
+                               pr_err("%s: cache %s error %d\n",
+                                               mmc_hostname(card->host),
+                                               enable ? "on" : "off",
+                                               err);
+                       else
+                               card->ext_csd.cache_ctrl = enable;
+               }
+       }
+
+       return err;
+}
+EXPORT_SYMBOL(mmc_cache_ctrl);
+
+
 #ifdef CONFIG_PM
 
 /**
old mode 100644 (file)
new mode 100755 (executable)
index 14664f1..e2f8978
@@ -24,6 +24,7 @@ struct mmc_bus_ops {
        int (*resume)(struct mmc_host *);
        int (*power_save)(struct mmc_host *);
        int (*power_restore)(struct mmc_host *);
+       int (*alive)(struct mmc_host *);
 };
 
 void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
index 403905501f5f8f00e98c36ba090ebd3f5f3d4169..0acf7ebdd1bee6472c9a75c6d5698ce48413b9d7 100755 (executable)
@@ -19,6 +19,7 @@
 
 #include "core.h"
 #include "bus.h"
+#include "host.h"
 #include "mmc_ops.h"
 #include "sd_ops.h"
 
@@ -95,6 +96,7 @@ static int mmc_decode_cid(struct mmc_card *card)
                card->cid.prod_name[3]  = UNSTUFF_BITS(resp, 72, 8);
                card->cid.prod_name[4]  = UNSTUFF_BITS(resp, 64, 8);
                card->cid.prod_name[5]  = UNSTUFF_BITS(resp, 56, 8);
+               card->cid.prv           = UNSTUFF_BITS(resp, 48, 8);
                card->cid.serial        = UNSTUFF_BITS(resp, 16, 32);
                card->cid.month         = UNSTUFF_BITS(resp, 12, 4);
                card->cid.year          = UNSTUFF_BITS(resp, 8, 4) + 1997;
@@ -234,12 +236,44 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
        return err;
 }
 
+static void mmc_select_card_type(struct mmc_card *card)
+{
+       struct mmc_host *host = card->host;
+       u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
+       u32 caps = host->caps, caps2 = host->caps2;
+       unsigned int hs_max_dtr = 0;
+
+       if (card_type & EXT_CSD_CARD_TYPE_26)
+               hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+
+       if (caps & MMC_CAP_MMC_HIGHSPEED &&
+                       card_type & EXT_CSD_CARD_TYPE_52)
+               hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+
+       if ((caps & MMC_CAP_1_8V_DDR &&
+                       card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
+           (caps & MMC_CAP_1_2V_DDR &&
+                       card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+               hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+
+       if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+                       card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
+           (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+                       card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+               hs_max_dtr = MMC_HS200_MAX_DTR;
+
+       card->ext_csd.hs_max_dtr = hs_max_dtr;
+       card->ext_csd.card_type = card_type;
+}
+
 /*
  * Decode extended CSD.
  */
 static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
 {
-       int err = 0;
+       int err = 0, idx;
+       unsigned int part_size;
+       u8 hc_erase_grp_sz = 0, hc_wp_grp_sz = 0;
 
        BUG_ON(!card);
 
@@ -397,6 +431,42 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
                        card->ext_csd.enhanced_area_offset = -EINVAL;
                        card->ext_csd.enhanced_area_size = -EINVAL;
                }
+
+               /*
+                * General purpose partition feature support --
+                * If ext_csd has the size of general purpose partitions,
+                * set size, part_cfg, partition name in mmc_part.
+                */
+               if (ext_csd[EXT_CSD_PARTITION_SUPPORT] &
+                       EXT_CSD_PART_SUPPORT_PART_EN) {
+                       if (card->ext_csd.enhanced_area_en != 1) {
+                               hc_erase_grp_sz =
+                                       ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
+                               hc_wp_grp_sz =
+                                       ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
+
+                               card->ext_csd.enhanced_area_en = 1;
+                       }
+
+                       for (idx = 0; idx < MMC_NUM_GP_PARTITION; idx++) {
+                               if (!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3] &&
+                               !ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1] &&
+                               !ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2])
+                                       continue;
+                               part_size =
+                               (ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2]
+                                       << 16) +
+                               (ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1]
+                                       << 8) +
+                               ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3];
+                               part_size *= (size_t)(hc_erase_grp_sz *
+                                       hc_wp_grp_sz);
+                               mmc_part_add(card, part_size << 19,
+                                       EXT_CSD_PART_CONFIG_ACC_GP0 + idx,
+                                       "gp%d", idx, false,
+                                       MMC_BLK_DATA_AREA_GP);
+                       }
+               }
                card->ext_csd.sec_trim_mult =
                        ext_csd[EXT_CSD_SEC_TRIM_MULT];
                card->ext_csd.sec_erase_mult =
@@ -405,10 +475,57 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
                        ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT];
                card->ext_csd.trim_timeout = 300 *
                        ext_csd[EXT_CSD_TRIM_MULT];
+
+               /*
+                * Note that the call to mmc_part_add above defaults to read
+                * only. If this default assumption is changed, the call must
+                * take into account the value of boot_locked below.
+                */
+               card->ext_csd.boot_ro_lock = ext_csd[EXT_CSD_BOOT_WP];
+               card->ext_csd.boot_ro_lockable = true;
        }
 
-       if (card->ext_csd.rev >= 5)
+       if (card->ext_csd.rev >= 5) {
+               /* check whether the eMMC card supports BKOPS */
+               if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) {
+                       card->ext_csd.bkops = 1;
+                       card->ext_csd.bkops_en = ext_csd[EXT_CSD_BKOPS_EN];
+                       card->ext_csd.raw_bkops_status =
+                               ext_csd[EXT_CSD_BKOPS_STATUS];
+                       if (!card->ext_csd.bkops_en)
+                               pr_info("%s: BKOPS_EN bit is not set\n",
+                                       mmc_hostname(card->host));
+               }
+
+               /* check whether the eMMC card supports HPI */
+               if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) {
+                       card->ext_csd.hpi = 1;
+                       if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2)
+                               card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION;
+                       else
+                               card->ext_csd.hpi_cmd = MMC_SEND_STATUS;
+                       /*
+                        * Indicate the maximum timeout to close
+                        * a command interrupted by HPI
+                        */
+                       card->ext_csd.out_of_int_time =
+                               ext_csd[EXT_CSD_OUT_OF_INTERRUPT_TIME] * 10;
+               }
+
                card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM];
+               card->ext_csd.rst_n_function = ext_csd[EXT_CSD_RST_N_FUNCTION];
+
+               /*
+                * RPMB regions are defined in multiples of 128K.
+                */
+               card->ext_csd.raw_rpmb_size_mult = ext_csd[EXT_CSD_RPMB_MULT];
+               if (ext_csd[EXT_CSD_RPMB_MULT] && mmc_host_cmd23(card->host)) {
+                       mmc_part_add(card, ext_csd[EXT_CSD_RPMB_MULT] << 17,
+                               EXT_CSD_PART_CONFIG_ACC_RPMB,
+                               "rpmb", 0, false,
+                               MMC_BLK_DATA_AREA_RPMB);
+               }
+       }
 
        card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT];
        if (ext_csd[EXT_CSD_ERASED_MEM_CONT])
@@ -416,6 +533,43 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
        else
                card->erased_byte = 0x0;
 
+       /* eMMC v4.5 or later */
+       if (card->ext_csd.rev >= 6) {
+               card->ext_csd.feature_support |= MMC_DISCARD_FEATURE;
+
+               card->ext_csd.generic_cmd6_time = 10 *
+                       ext_csd[EXT_CSD_GENERIC_CMD6_TIME];
+               card->ext_csd.power_off_longtime = 10 *
+                       ext_csd[EXT_CSD_POWER_OFF_LONG_TIME];
+
+               card->ext_csd.cache_size =
+                       ext_csd[EXT_CSD_CACHE_SIZE + 0] << 0 |
+                       ext_csd[EXT_CSD_CACHE_SIZE + 1] << 8 |
+                       ext_csd[EXT_CSD_CACHE_SIZE + 2] << 16 |
+                       ext_csd[EXT_CSD_CACHE_SIZE + 3] << 24;
+
+               if (ext_csd[EXT_CSD_DATA_SECTOR_SIZE] == 1)
+                       card->ext_csd.data_sector_size = 4096;
+               else
+                       card->ext_csd.data_sector_size = 512;
+
+               if ((ext_csd[EXT_CSD_DATA_TAG_SUPPORT] & 1) &&
+                   (ext_csd[EXT_CSD_TAG_UNIT_SIZE] <= 8)) {
+                       card->ext_csd.data_tag_unit_size =
+                       ((unsigned int) 1 << ext_csd[EXT_CSD_TAG_UNIT_SIZE]) *
+                       (card->ext_csd.data_sector_size);
+               } else {
+                       card->ext_csd.data_tag_unit_size = 0;
+               }
+
+               card->ext_csd.max_packed_writes =
+                       ext_csd[EXT_CSD_MAX_PACKED_WRITES];
+               card->ext_csd.max_packed_reads =
+                       ext_csd[EXT_CSD_MAX_PACKED_READS];
+       } else {
+               card->ext_csd.data_sector_size = 512;
+       }
+
 out:
        return err;
 }
@@ -510,10 +664,13 @@ MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
 MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid);
 MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
 MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
+MMC_DEV_ATTR(prv, "0x%x\n", card->cid.prv);
 MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
 MMC_DEV_ATTR(enhanced_area_offset, "%llu\n",
                card->ext_csd.enhanced_area_offset);
 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);
 
 static struct attribute *mmc_std_attrs[] = {
        &dev_attr_cid.attr,
@@ -526,9 +683,12 @@ static struct attribute *mmc_std_attrs[] = {
        &dev_attr_manfid.attr,
        &dev_attr_name.attr,
        &dev_attr_oemid.attr,
+       &dev_attr_prv.attr,
        &dev_attr_serial.attr,
        &dev_attr_enhanced_area_offset.attr,
        &dev_attr_enhanced_area_size.attr,
+       &dev_attr_raw_rpmb_size_mult.attr,
+       &dev_attr_rel_sectors.attr,
        NULL,
 };
 
@@ -545,6 +705,166 @@ static struct device_type mmc_type = {
        .groups = mmc_attr_groups,
 };
 
+/*
+ * Select the PowerClass for the current bus width
+ * If power class is defined for 4/8 bit bus in the
+ * extended CSD register, select it by executing the
+ * mmc_switch command.
+ */
+static int mmc_select_powerclass(struct mmc_card *card,
+               unsigned int bus_width, u8 *ext_csd)
+{
+       int err = 0;
+       unsigned int pwrclass_val;
+       unsigned int index = 0;
+       struct mmc_host *host;
+
+       BUG_ON(!card);
+
+       host = card->host;
+       BUG_ON(!host);
+
+       if (ext_csd == NULL)
+               return 0;
+
+       /* Power class selection is supported for versions >= 4.0 */
+       if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
+               return 0;
+
+       /* Power class values are defined only for 4/8 bit bus */
+       if (bus_width == EXT_CSD_BUS_WIDTH_1)
+               return 0;
+
+       switch (1 << host->ios.vdd) {
+       case MMC_VDD_165_195:
+               if (host->ios.clock <= 26000000)
+                       index = EXT_CSD_PWR_CL_26_195;
+               else if (host->ios.clock <= 52000000)
+                       index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
+                               EXT_CSD_PWR_CL_52_195 :
+                               EXT_CSD_PWR_CL_DDR_52_195;
+               else if (host->ios.clock <= 200000000)
+                       index = EXT_CSD_PWR_CL_200_195;
+               break;
+       case MMC_VDD_27_28:
+       case MMC_VDD_28_29:
+       case MMC_VDD_29_30:
+       case MMC_VDD_30_31:
+       case MMC_VDD_31_32:
+       case MMC_VDD_32_33:
+       case MMC_VDD_33_34:
+       case MMC_VDD_34_35:
+       case MMC_VDD_35_36:
+               if (host->ios.clock <= 26000000)
+                       index = EXT_CSD_PWR_CL_26_360;
+               else if (host->ios.clock <= 52000000)
+                       index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
+                               EXT_CSD_PWR_CL_52_360 :
+                               EXT_CSD_PWR_CL_DDR_52_360;
+               else if (host->ios.clock <= 200000000)
+                       index = EXT_CSD_PWR_CL_200_360;
+               break;
+       default:
+               pr_warning("%s: Voltage range not supported "
+                          "for power class.\n", mmc_hostname(host));
+               return -EINVAL;
+       }
+
+       pwrclass_val = ext_csd[index];
+
+       if (bus_width & (EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_BUS_WIDTH_8))
+               pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_8BIT_MASK) >>
+                               EXT_CSD_PWR_CL_8BIT_SHIFT;
+       else
+               pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_4BIT_MASK) >>
+                               EXT_CSD_PWR_CL_4BIT_SHIFT;
+
+       /* If the power class is different from the default value */
+       if (pwrclass_val > 0) {
+               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                                EXT_CSD_POWER_CLASS,
+                                pwrclass_val,
+                                card->ext_csd.generic_cmd6_time);
+       }
+
+       return err;
+}
+
+/*
+ * Selects the desired buswidth and switch to the HS200 mode
+ * if bus width set without error
+ */
+static int mmc_select_hs200(struct mmc_card *card)
+{
+       int idx, err = -EINVAL;
+       struct mmc_host *host;
+       static unsigned ext_csd_bits[] = {
+               EXT_CSD_BUS_WIDTH_4,
+               EXT_CSD_BUS_WIDTH_8,
+       };
+       static unsigned bus_widths[] = {
+               MMC_BUS_WIDTH_4,
+               MMC_BUS_WIDTH_8,
+       };
+
+       BUG_ON(!card);
+
+       host = card->host;
+
+       if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
+                       host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+               err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120,0);
+
+       if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
+                       host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+               err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180,0);
+
+       /* If fails try again during next card power cycle */
+       if (err)
+               goto err;
+
+       idx = (host->caps & MMC_CAP_8_BIT_DATA) ? 1 : 0;
+
+       /*
+        * Unlike SD, MMC cards dont have a configuration register to notify
+        * supported bus width. So bus test command should be run to identify
+        * the supported bus width or compare the ext csd values of current
+        * bus width and ext csd values of 1 bit mode read earlier.
+        */
+       for (; idx >= 0; idx--) {
+
+               /*
+                * Host is capable of 8bit transfer, then switch
+                * the device to work in 8bit transfer mode. If the
+                * mmc switch command returns error then switch to
+                * 4bit transfer mode. On success set the corresponding
+                * bus width on the host.
+                */
+               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                                EXT_CSD_BUS_WIDTH,
+                                ext_csd_bits[idx],
+                                card->ext_csd.generic_cmd6_time);
+               if (err)
+                       continue;
+
+               mmc_set_bus_width(card->host, bus_widths[idx]);
+
+               if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
+                       err = mmc_compare_ext_csds(card, bus_widths[idx]);
+               else
+                       err = mmc_bus_test(card, bus_widths[idx]);
+               if (!err)
+                       break;
+       }
+
+       /* switch to HS200 mode if bus width set successfully */
+       if (!err)
+               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                                EXT_CSD_HS_TIMING, 2, 0);
+err:
+       return err;
+}
+
 /*
  * Handle the detection and initialisation of a card.
  *
@@ -564,6 +884,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        BUG_ON(!host);
        WARN_ON(!host->claimed);
 
+       /* Set correct bus mode for MMC before attempting init */
+       if (!mmc_host_is_spi(host))
+               mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN);
+
        /*
         * Since we're changing the OCR value, we seem to
         * need to tell some cards to go back to the idle
@@ -687,9 +1011,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
         * If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF
         * bit.  This bit will be lost every time after a reset or power off.
         */
-       if (card->ext_csd.enhanced_area_en) {
+       if (card->ext_csd.enhanced_area_en ||
+           (card->ext_csd.rev >= 3 && (host->caps2 & MMC_CAP2_HC_ERASE_SZ))) {
                err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                                EXT_CSD_ERASE_GROUP_DEF, 1, 0);
+                                EXT_CSD_ERASE_GROUP_DEF, 1,
+                                card->ext_csd.generic_cmd6_time);
 
                if (err && err != -EBADMSG)
                        goto free_card;
@@ -727,12 +1053,39 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        }
 
        /*
-        * Activate high speed (if supported)
+        * If the host supports the power_off_notify capability then
+        * set the notification byte in the ext_csd register of device
         */
-       if ((card->ext_csd.hs_max_dtr != 0) &&
-               (host->caps & MMC_CAP_MMC_HIGHSPEED)) {
+       if ((host->caps2 & MMC_CAP2_POWEROFF_NOTIFY) &&
+           (card->ext_csd.rev >= 6)) {
                err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                                EXT_CSD_HS_TIMING, 1, 0);
+                                EXT_CSD_POWER_OFF_NOTIFICATION,
+                                EXT_CSD_POWER_ON,
+                                card->ext_csd.generic_cmd6_time);
+               if (err && err != -EBADMSG)
+                       goto free_card;
+
+               /*
+                * The err can be -EBADMSG or 0,
+                * so check for success and update the flag
+                */
+               if (!err)
+                       card->ext_csd.power_off_notification = EXT_CSD_POWER_ON;
+       }
+
+       /*
+        * Activate high speed (if supported)
+        */
+       if (card->ext_csd.hs_max_dtr != 0) {
+               err = 0;
+               if (card->ext_csd.hs_max_dtr > 52000000 &&
+                   host->caps2 & MMC_CAP2_HS200)
+                       err = mmc_select_hs200(card);
+               else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
+                       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                                        EXT_CSD_HS_TIMING, 1,
+                                        card->ext_csd.generic_cmd6_time);
+
                if (err && err != -EBADMSG)
                        goto free_card;
 
@@ -741,8 +1094,15 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                               mmc_hostname(card->host));
                        err = 0;
                } else {
-                       mmc_card_set_highspeed(card);
-                       mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+                       if (card->ext_csd.hs_max_dtr > 52000000 &&
+                           host->caps2 & MMC_CAP2_HS200) {
+                               mmc_card_set_hs200(card);
+                               mmc_set_timing(card->host,
+                                              MMC_TIMING_MMC_HS200);
+                       } else {
+                               mmc_card_set_highspeed(card);
+                               mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+                       }
                }
        }
 
@@ -754,6 +1114,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        if (mmc_card_highspeed(card)) {
                if (max_dtr > card->ext_csd.hs_max_dtr)
                        max_dtr = card->ext_csd.hs_max_dtr;
+               if (mmc_card_highspeed(card) && (max_dtr > 52000000))
+                       max_dtr = 52000000;
        } else if (max_dtr > card->csd.max_dtr) {
                if(!HOST_IS_EMMC(host)){
                        //in order to expand the compatibility of card. Added by xbw@2011-03-21
@@ -780,10 +1142,51 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                                ddr = MMC_1_2V_DDR_MODE;
        }
 
+       /*
+        * Indicate HS200 SDR mode (if supported).
+        */
+       if (mmc_card_hs200(card)) {
+               u32 ext_csd_bits;
+               u32 bus_width = card->host->ios.bus_width;
+
+               /*
+                * For devices supporting HS200 mode, the bus width has
+                * to be set before executing the tuning function. If
+                * set before tuning, then device will respond with CRC
+                * errors for responses on CMD line. So for HS200 the
+                * sequence will be
+                * 1. set bus width 4bit / 8 bit (1 bit not supported)
+                * 2. switch to HS200 mode
+                * 3. set the clock to > 52Mhz <=200MHz and
+                * 4. execute tuning for HS200
+                */
+               if ((host->caps2 & MMC_CAP2_HS200) &&
+                   card->host->ops->execute_tuning) {
+                       mmc_host_clk_hold(card->host);
+                       err = card->host->ops->execute_tuning(card->host,
+                               MMC_SEND_TUNING_BLOCK_HS200);
+                       mmc_host_clk_release(card->host);
+               }
+               if (err) {
+                       pr_warning("%s: tuning execution failed\n",
+                                  mmc_hostname(card->host));
+                       goto err;
+               }
+
+               ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
+                               EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4;
+               err = mmc_select_powerclass(card, ext_csd_bits, ext_csd);
+               if (err)
+                       pr_warning("%s: power class selection to bus width %d"
+                                  " failed\n", mmc_hostname(card->host),
+                                  1 << bus_width);
+       }
+
        /*
         * Activate wide bus and DDR (if supported).
         */
-       if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
+       if (!mmc_card_hs200(card) &&
+           (card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
            (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
                static unsigned ext_csd_bits[][2] = {
                        { EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 },
@@ -805,10 +1208,18 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                        bus_width = bus_widths[idx];
                        if (bus_width == MMC_BUS_WIDTH_1)
                                ddr = 0; /* no DDR for 1-bit width */
+                       err = mmc_select_powerclass(card, ext_csd_bits[idx][0],
+                                                   ext_csd);
+                       if (err)
+                               pr_warning("%s: power class selection to "
+                                          "bus width %d failed\n",
+                                          mmc_hostname(card->host),
+                                          1 << bus_width);
+
                        err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                         EXT_CSD_BUS_WIDTH,
                                         ext_csd_bits[idx][0],
-                                        0);
+                                        card->ext_csd.generic_cmd6_time);
                        if (!err) {
                                mmc_set_bus_width(card->host, bus_width);
 
@@ -828,10 +1239,18 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                }
 
                if (!err && ddr) {
+                       err = mmc_select_powerclass(card, ext_csd_bits[idx][1],
+                                                   ext_csd);
+                       if (err)
+                               pr_warning("%s: power class selection to "
+                                          "bus width %d ddr %d failed\n",
+                                          mmc_hostname(card->host),
+                                          1 << bus_width, ddr);
+
                        err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                         EXT_CSD_BUS_WIDTH,
                                         ext_csd_bits[idx][1],
-                                        0);
+                                        card->ext_csd.generic_cmd6_time);
                }
                if (err) {
                        printk(KERN_WARNING "%s: switch to bus width %d ddr %d "
@@ -865,6 +1284,72 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                }
        }
 
+       /*
+        * Enable HPI feature (if supported)
+        */
+       if (card->ext_csd.hpi) {
+               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                               EXT_CSD_HPI_MGMT, 1,
+                               card->ext_csd.generic_cmd6_time);
+               if (err && err != -EBADMSG)
+                       goto free_card;
+               if (err) {
+                       pr_warning("%s: Enabling HPI failed\n",
+                                  mmc_hostname(card->host));
+                       err = 0;
+               } else
+                       card->ext_csd.hpi_en = 1;
+       }
+
+       /*
+        * If cache size is higher than 0, this indicates
+        * the existence of cache and it can be turned on.
+        */
+       if ((host->caps2 & MMC_CAP2_CACHE_CTRL) &&
+                       card->ext_csd.cache_size > 0) {
+               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                               EXT_CSD_CACHE_CTRL, 1,
+                               card->ext_csd.generic_cmd6_time);
+               if (err && err != -EBADMSG)
+                       goto free_card;
+
+               /*
+                * Only if no error, cache is turned on successfully.
+                */
+               if (err) {
+                       pr_warning("%s: Cache is supported, "
+                                       "but failed to turn on (%d)\n",
+                                       mmc_hostname(card->host), err);
+                       card->ext_csd.cache_ctrl = 0;
+                       err = 0;
+               } else {
+                       card->ext_csd.cache_ctrl = 1;
+               }
+       }
+
+       /*
+        * The mandatory minimum values are defined for packed command.
+        * read: 5, write: 3
+        */
+       if (card->ext_csd.max_packed_writes >= 3 &&
+           card->ext_csd.max_packed_reads >= 5 &&
+           host->caps2 & MMC_CAP2_PACKED_CMD) {
+               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                               EXT_CSD_EXP_EVENTS_CTRL,
+                               EXT_CSD_PACKED_EVENT_EN,
+                               card->ext_csd.generic_cmd6_time);
+               if (err && err != -EBADMSG)
+                       goto free_card;
+               if (err) {
+                       pr_warn("%s: Enabling packed event failed\n",
+                               mmc_hostname(card->host));
+                       card->ext_csd.packed_event_en = 0;
+                       err = 0;
+               } else {
+                       card->ext_csd.packed_event_en = 1;
+               }
+       }
+
        if (!oldcard)
                host->card = card;
 
@@ -880,6 +1365,35 @@ err:
        return err;
 }
 
+static int mmc_can_poweroff_notify(const struct mmc_card *card)
+{
+       return card &&
+               mmc_card_mmc(card) &&
+               (card->ext_csd.power_off_notification == EXT_CSD_POWER_ON);
+}
+
+static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type)
+{
+       unsigned int timeout = card->ext_csd.generic_cmd6_time;
+       int err;
+
+       /* Use EXT_CSD_POWER_OFF_SHORT as default notification type. */
+       if (notify_type == EXT_CSD_POWER_OFF_LONG)
+               timeout = card->ext_csd.power_off_longtime;
+
+       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                        EXT_CSD_POWER_OFF_NOTIFICATION,
+                        notify_type, timeout);
+       if (err)
+               pr_err("%s: Power Off Notification timed out, %u\n",
+                      mmc_hostname(card->host), timeout);
+
+       /* Disable the power off notification after the switch operation. */
+       card->ext_csd.power_off_notification = EXT_CSD_NO_POWER_NOTIFICATION;
+
+       return err;
+}
+
 /*
  * Host is being removed. Free up the current card.
  */
@@ -892,6 +1406,14 @@ static void mmc_remove(struct mmc_host *host)
        host->card = NULL;
 }
 
+/*
+ * Card detection - card is alive.
+ */
+static int mmc_alive(struct mmc_host *host)
+{
+       return mmc_send_status(host->card, NULL);
+}
+
 /*
  * Card detection callback from host.
  */
@@ -924,18 +1446,31 @@ static void mmc_detect(struct mmc_host *host)
 /*
  * Suspend callback from host.
  */
+extern int mmc_cache_ctrl(struct mmc_host *host, u8 enable);
 static int mmc_suspend(struct mmc_host *host)
 {
+       int err = 0;
+
        BUG_ON(!host);
        BUG_ON(!host->card);
 
        mmc_claim_host(host);
-       if (!mmc_host_is_spi(host))
-               mmc_deselect_cards(host);
-       host->card->state &= ~MMC_STATE_HIGHSPEED;
-       mmc_release_host(host);
 
-       return 0;
+       err = mmc_cache_ctrl(host, 0);
+       if (err)
+               goto out;
+
+       if (mmc_can_poweroff_notify(host->card))
+               err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT);
+       else if (mmc_card_can_sleep(host))
+               err = mmc_card_sleep(host);
+       else if (!mmc_host_is_spi(host))
+               err = mmc_deselect_cards(host);
+       host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
+
+out:
+       mmc_release_host(host);
+       return err;
 }
 
 /*
@@ -962,7 +1497,7 @@ static int mmc_power_restore(struct mmc_host *host)
 {
        int ret;
 
-       host->card->state &= ~MMC_STATE_HIGHSPEED;
+       host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
        mmc_claim_host(host);
        ret = mmc_init_card(host, host->ocr, host->card);
        mmc_release_host(host);
@@ -1008,6 +1543,7 @@ static const struct mmc_bus_ops mmc_ops = {
        .suspend = NULL,
        .resume = NULL,
        .power_restore = mmc_power_restore,
+       .alive = mmc_alive,
 };
 
 static const struct mmc_bus_ops mmc_ops_unsafe = {
@@ -1018,6 +1554,7 @@ static const struct mmc_bus_ops mmc_ops_unsafe = {
        .suspend = mmc_suspend,
        .resume = mmc_resume,
        .power_restore = mmc_power_restore,
+       .alive = mmc_alive,
 };
 
 static void mmc_attach_bus_ops(struct mmc_host *host)
index 228e7a49720cf6a85f08344ab6d76dfcc5372e02..ca107853d632bfa0422a9a66a6e4cb7d97023aa2 100755 (executable)
@@ -16,6 +16,7 @@
 struct mmc_cid {
        unsigned int            manfid;
        char                    prod_name[8];
+       unsigned char           prv;
        unsigned int            serial;
        unsigned short          oemid;
        unsigned short          year;
@@ -50,9 +51,21 @@ struct mmc_ext_csd {
        u8                      rel_sectors;
        u8                      rel_param;
        u8                      part_config;
+       u8                      cache_ctrl;
+       u8                      rst_n_function;
+       u8                      max_packed_writes;
+       u8                      max_packed_reads;
+       u8                      packed_event_en;
        unsigned int            part_time;              /* Units: ms */
        unsigned int            sa_timeout;             /* Units: 100ns */
+       unsigned int            generic_cmd6_time;      /* Units: 10ms */
+       unsigned int        power_off_longtime;     /* Units: ms */
+       u8                      power_off_notification; /* state */
        unsigned int            hs_max_dtr;
+       #define MMC_HIGH_26_MAX_DTR     26000000
+    #define MMC_HIGH_52_MAX_DTR        52000000
+    #define MMC_HIGH_DDR_MAX_DTR       52000000
+    #define MMC_HS200_MAX_DTR  200000000
        unsigned int            sectors;
        unsigned int            card_type;
        unsigned int            hc_erase_size;          /* In sectors */
@@ -64,10 +77,23 @@ struct mmc_ext_csd {
        unsigned long long      enhanced_area_offset;   /* Units: Byte */
        unsigned int            enhanced_area_size;     /* Units: KB */
        unsigned int            boot_size;              /* in bytes */
+       unsigned int            cache_size;             /* Units: KB */
+       bool                    hpi_en;                 /* HPI enablebit */
+       bool                    hpi;                    /* HPI support bit */
+       unsigned int            hpi_cmd;                /* cmd used as HPI */
+       bool                    bkops;          /* background support bit */
+       bool                    bkops_en;       /* background enable bit */
+       unsigned int            data_sector_size;       /* 512 bytes or 4KB */
+       unsigned int            data_tag_unit_size;     /* DATA TAG UNIT size */
+       unsigned int            boot_ro_lock;           /* ro lock support */
+       bool                    boot_ro_lockable;
+       u8                      raw_exception_status;   /* 54 */
        u8                      raw_partition_support;  /* 160 */
+       u8                      raw_rpmb_size_mult;     /* 168 */
        u8                      raw_erased_mem_count;   /* 181 */
        u8                      raw_ext_csd_structure;  /* 194 */
        u8                      raw_card_type;          /* 196 */
+       u8                      out_of_int_time;        /* 198 */
        u8                      raw_s_a_timeout;                /* 217 */
        u8                      raw_hc_erase_gap_size;  /* 221 */
        u8                      raw_erase_timeout_mult; /* 223 */
@@ -76,7 +102,11 @@ struct mmc_ext_csd {
        u8                      raw_sec_erase_mult;     /* 230 */
        u8                      raw_sec_feature_support;/* 231 */
        u8                      raw_trim_mult;          /* 232 */
+       u8                      raw_bkops_status;       /* 246 */
        u8                      raw_sectors[4];         /* 212 - 4 bytes */
+
+       unsigned int            feature_support;
+    #define MMC_DISCARD_FEATURE        BIT(0)                  /* CMD38 feature */
 };
 
 struct sd_scr {
@@ -126,6 +156,7 @@ struct sd_switch_caps {
 #define SD_SET_CURRENT_LIMIT_400       1
 #define SD_SET_CURRENT_LIMIT_600       2
 #define SD_SET_CURRENT_LIMIT_800       3
+#define SD_SET_CURRENT_NO_CHANGE       (-1)
 
 #define SD_MAX_CURRENT_200     (1 << SD_SET_CURRENT_LIMIT_200)
 #define SD_MAX_CURRENT_400     (1 << SD_SET_CURRENT_LIMIT_400)
@@ -157,6 +188,30 @@ struct sdio_func_tuple;
 
 #define SDIO_MAX_FUNCS         7
 
+/* The number of MMC physical partitions.  These consist of:
+ * boot partitions (2), general purpose partitions (4) in MMC v4.4.
+ */
+#define MMC_NUM_BOOT_PARTITION 2
+#define MMC_NUM_GP_PARTITION   4
+#define MMC_NUM_PHY_PARTITION  6
+#define MAX_MMC_PART_NAME_LEN  20
+
+/*
+ * MMC Physical partitions
+ */
+struct mmc_part {
+       unsigned int    size;   /* partition size (in bytes) */
+       unsigned int    part_cfg;       /* partition type */
+       char    name[MAX_MMC_PART_NAME_LEN];
+       bool    force_ro;       /* to make boot parts RO by default */
+       unsigned int    area_type;
+#define MMC_BLK_DATA_AREA_MAIN (1<<0)
+#define MMC_BLK_DATA_AREA_BOOT (1<<1)
+#define MMC_BLK_DATA_AREA_GP   (1<<2)
+#define MMC_BLK_DATA_AREA_RPMB (1<<3)
+};
+
+
 /*
  * MMC device
  */
@@ -224,8 +279,31 @@ struct mmc_card {
        unsigned int            sd_bus_speed;   /* Bus Speed Mode set for the card */
 
        struct dentry           *debugfs_root;
+       struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
+       unsigned int    nr_parts;
 };
 
+/*
+ * This function fill contents in mmc_part.
+ */
+static inline void mmc_part_add(struct mmc_card *card, unsigned int size,
+                       unsigned int part_cfg, char *name, int idx, bool ro,
+                       int area_type)
+{
+       card->part[card->nr_parts].size = size;
+       card->part[card->nr_parts].part_cfg = part_cfg;
+       sprintf(card->part[card->nr_parts].name, name, idx);
+       card->part[card->nr_parts].force_ro = ro;
+       card->part[card->nr_parts].area_type = area_type;
+       card->nr_parts++;
+}
+
+static inline bool mmc_large_sector(struct mmc_card *card)
+{
+       return card->ext_csd.data_sector_size == 4096;
+}
+
+
 /*
  *  The world is not perfect and supplies us with broken mmc/sdio devices.
  *  For at least some of these bugs we need a work-around.
@@ -319,6 +397,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 #define mmc_card_readonly(c)   ((c)->state & MMC_STATE_READONLY)
 #define mmc_card_highspeed(c)  ((c)->state & MMC_STATE_HIGHSPEED)
 #define mmc_card_hs200(c)      ((c)->state & MMC_STATE_HIGHSPEED_200)
+#define mmc_card_set_hs200(c)  ((c)->state |= MMC_STATE_HIGHSPEED_200)
 #define mmc_card_blockaddr(c)  ((c)->state & MMC_STATE_BLOCKADDR)
 #define mmc_card_ddr_mode(c)   ((c)->state & MMC_STATE_HIGHSPEED_DDR)
 #define mmc_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
index 43e48cab8f433373504ec0f00c3d1dfb86ee4706..4df54d991241b272c6cfea781c99284ee7040cd1 100755 (executable)
@@ -56,6 +56,7 @@ struct mmc_ios {
 #define MMC_TIMING_UHS_SDR50   3
 #define MMC_TIMING_UHS_SDR104  4
 #define MMC_TIMING_UHS_DDR50   5
+#define MMC_TIMING_MMC_HS200   8
 
        unsigned char   ddr;                    /* dual data rate used */
 
@@ -238,6 +239,28 @@ struct mmc_host {
 #define MMC_CAP_MAX_CURRENT_600        (1 << 28)       /* Host max current limit is 600mA */
 #define MMC_CAP_MAX_CURRENT_800        (1 << 29)       /* Host max current limit is 800mA */
 #define MMC_CAP_CMD23          (1 << 30)       /* CMD23 supported. */
+#define MMC_CAP_HW_RESET       (1 << 31)       /* Hardware reset */
+    
+        u32         caps2;      /* More host capabilities */
+#define MMC_CAP2_BOOTPART_NOACC        (1 << 0)        /* Boot partition no access */
+#define MMC_CAP2_CACHE_CTRL    (1 << 1)        /* Allow cache control */
+#define MMC_CAP2_POWEROFF_NOTIFY (1 << 2)      /* Notify poweroff supported */
+#define MMC_CAP2_NO_MULTI_READ (1 << 3)        /* Multiblock reads don't work */
+#define MMC_CAP2_NO_SLEEP_CMD  (1 << 4)        /* Don't allow sleep command */
+#define MMC_CAP2_HS200_1_8V_SDR        (1 << 5)        /* can support */
+#define MMC_CAP2_HS200_1_2V_SDR        (1 << 6)        /* can support */
+#define MMC_CAP2_HS200         (MMC_CAP2_HS200_1_8V_SDR | \
+                     MMC_CAP2_HS200_1_2V_SDR)
+#define MMC_CAP2_BROKEN_VOLTAGE        (1 << 7)        /* Use the broken voltage */
+#define MMC_CAP2_DETECT_ON_ERR (1 << 8)        /* On I/O err check card removal */
+#define MMC_CAP2_HC_ERASE_SZ   (1 << 9)        /* High-capacity erase size */
+#define MMC_CAP2_CD_ACTIVE_HIGH        (1 << 10)       /* Card-detect signal active high */
+#define MMC_CAP2_RO_ACTIVE_HIGH        (1 << 11)       /* Write-protect signal active high */
+#define MMC_CAP2_PACKED_RD     (1 << 12)       /* Allow packed read */
+#define MMC_CAP2_PACKED_WR     (1 << 13)       /* Allow packed write */
+#define MMC_CAP2_PACKED_CMD    (MMC_CAP2_PACKED_RD | \
+                     MMC_CAP2_PACKED_WR)
+#define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)  /* Don't power up before scan */
 
        mmc_pm_flag_t           pm_caps;        /* supported pm features */
 
old mode 100644 (file)
new mode 100755 (executable)
index 54a673e..8209cb5
@@ -51,6 +51,7 @@
 #define MMC_READ_SINGLE_BLOCK    17   /* adtc [31:0] data addr   R1  */
 #define MMC_READ_MULTIPLE_BLOCK  18   /* adtc [31:0] data addr   R1  */
 #define MMC_SEND_TUNING_BLOCK    19   /* adtc                    R1  */
+#define MMC_SEND_TUNING_BLOCK_HS200    21      /* adtc R1  */
 
   /* class 3 */
 #define MMC_WRITE_DAT_UNTIL_STOP 20   /* adtc [31:0] data addr   R1  */
@@ -269,19 +270,40 @@ struct _mmc_csd {
 /*
  * EXT_CSD fields
  */
-
+#define EXT_CSD_FLUSH_CACHE            32      /* W */
+#define EXT_CSD_CACHE_CTRL             33      /* R/W */
+#define EXT_CSD_POWER_OFF_NOTIFICATION 34      /* R/W */
+#define EXT_CSD_PACKED_FAILURE_INDEX   35      /* RO */
+#define EXT_CSD_PACKED_CMD_STATUS      36      /* RO */
+#define EXT_CSD_EXP_EVENTS_STATUS      54      /* RO, 2 bytes */
+#define EXT_CSD_EXP_EVENTS_CTRL                56      /* R/W, 2 bytes */
+#define EXT_CSD_DATA_SECTOR_SIZE       61      /* R */
+#define EXT_CSD_GP_SIZE_MULT           143     /* R/W */
 #define EXT_CSD_PARTITION_ATTRIBUTE    156     /* R/W */
 #define EXT_CSD_PARTITION_SUPPORT      160     /* RO */
+#define EXT_CSD_HPI_MGMT               161     /* R/W */
+#define EXT_CSD_RST_N_FUNCTION         162     /* R/W */
+#define EXT_CSD_BKOPS_EN               163     /* R/W */
+#define EXT_CSD_BKOPS_START            164     /* W */
+#define EXT_CSD_SANITIZE_START         165     /* W */
 #define EXT_CSD_WR_REL_PARAM           166     /* RO */
+#define EXT_CSD_RPMB_MULT              168     /* RO */
+#define EXT_CSD_BOOT_WP                        173     /* R/W */
 #define EXT_CSD_ERASE_GROUP_DEF                175     /* R/W */
 #define EXT_CSD_PART_CONFIG            179     /* R/W */
 #define EXT_CSD_ERASED_MEM_CONT                181     /* RO */
 #define EXT_CSD_BUS_WIDTH              183     /* R/W */
 #define EXT_CSD_HS_TIMING              185     /* R/W */
+#define EXT_CSD_POWER_CLASS            187     /* R/W */
 #define EXT_CSD_REV                    192     /* RO */
 #define EXT_CSD_STRUCTURE              194     /* RO */
 #define EXT_CSD_CARD_TYPE              196     /* RO */
+#define EXT_CSD_OUT_OF_INTERRUPT_TIME  198     /* RO */
 #define EXT_CSD_PART_SWITCH_TIME        199     /* RO */
+#define EXT_CSD_PWR_CL_52_195          200     /* RO */
+#define EXT_CSD_PWR_CL_26_195          201     /* RO */
+#define EXT_CSD_PWR_CL_52_360          202     /* RO */
+#define EXT_CSD_PWR_CL_26_360          203     /* RO */
 #define EXT_CSD_SEC_CNT                        212     /* RO, 4 bytes */
 #define EXT_CSD_S_A_TIMEOUT            217     /* RO */
 #define EXT_CSD_REL_WR_SEC_C           222     /* RO */
@@ -293,6 +315,20 @@ struct _mmc_csd {
 #define EXT_CSD_SEC_ERASE_MULT         230     /* RO */
 #define EXT_CSD_SEC_FEATURE_SUPPORT    231     /* RO */
 #define EXT_CSD_TRIM_MULT              232     /* RO */
+#define EXT_CSD_PWR_CL_200_195         236     /* RO */
+#define EXT_CSD_PWR_CL_200_360         237     /* RO */
+#define EXT_CSD_PWR_CL_DDR_52_195      238     /* RO */
+#define EXT_CSD_PWR_CL_DDR_52_360      239     /* RO */
+#define EXT_CSD_BKOPS_STATUS           246     /* RO */
+#define EXT_CSD_POWER_OFF_LONG_TIME    247     /* RO */
+#define EXT_CSD_GENERIC_CMD6_TIME      248     /* RO */
+#define EXT_CSD_CACHE_SIZE             249     /* RO, 4 bytes */
+#define EXT_CSD_TAG_UNIT_SIZE          498     /* RO */
+#define EXT_CSD_DATA_TAG_SUPPORT       499     /* RO */
+#define EXT_CSD_MAX_PACKED_WRITES      500     /* RO */
+#define EXT_CSD_MAX_PACKED_READS       501     /* RO */
+#define EXT_CSD_BKOPS_SUPPORT          502     /* RO */
+#define EXT_CSD_HPI_FEATURES           503     /* RO */
 
 /*
  * EXT_CSD field definitions
@@ -300,9 +336,18 @@ struct _mmc_csd {
 
 #define EXT_CSD_WR_REL_PARAM_EN                (1<<2)
 
+#define EXT_CSD_BOOT_WP_B_PWR_WP_DIS   (0x40)
+#define EXT_CSD_BOOT_WP_B_PERM_WP_DIS  (0x10)
+#define EXT_CSD_BOOT_WP_B_PERM_WP_EN   (0x04)
+#define EXT_CSD_BOOT_WP_B_PWR_WP_EN    (0x01)
+
 #define EXT_CSD_PART_CONFIG_ACC_MASK   (0x7)
 #define EXT_CSD_PART_CONFIG_ACC_BOOT0  (0x1)
 #define EXT_CSD_PART_CONFIG_ACC_BOOT1  (0x2)
+#define EXT_CSD_PART_CONFIG_ACC_RPMB   (0x3)
+#define EXT_CSD_PART_CONFIG_ACC_GP0    (0x4)
+
+#define EXT_CSD_PART_SUPPORT_PART_EN   (0x1)
 
 #define EXT_CSD_CMD_SET_NORMAL         (1<<0)
 #define EXT_CSD_CMD_SET_SECURE         (1<<1)
@@ -310,13 +355,16 @@ struct _mmc_csd {
 
 #define EXT_CSD_CARD_TYPE_26   (1<<0)  /* Card can run at 26MHz */
 #define EXT_CSD_CARD_TYPE_52   (1<<1)  /* Card can run at 52MHz */
-#define EXT_CSD_CARD_TYPE_MASK 0x    /* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_MASK 0x3F    /* Mask out reserved bits */
 #define EXT_CSD_CARD_TYPE_DDR_1_8V  (1<<2)   /* Card can run at 52MHz */
                                             /* DDR mode @1.8V or 3V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_1_2V  (1<<3)   /* Card can run at 52MHz */
                                             /* DDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_52       (EXT_CSD_CARD_TYPE_DDR_1_8V  \
                                        | EXT_CSD_CARD_TYPE_DDR_1_2V)
+#define EXT_CSD_CARD_TYPE_SDR_1_8V     (1<<4)  /* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_SDR_1_2V     (1<<5)  /* Card can run at 200MHz */
+                            /* SDR mode @1.2V I/O */
 
 #define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
@@ -327,6 +375,22 @@ struct _mmc_csd {
 #define EXT_CSD_SEC_ER_EN      BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN  BIT(2)
 #define EXT_CSD_SEC_GB_CL_EN   BIT(4)
+#define EXT_CSD_SEC_SANITIZE   BIT(6)  /* v4.5 only */
+
+#define EXT_CSD_RST_N_EN_MASK  0x3
+#define EXT_CSD_RST_N_ENABLED  1       /* RST_n is enabled on card */
+
+#define EXT_CSD_NO_POWER_NOTIFICATION  0
+#define EXT_CSD_POWER_ON               1
+#define EXT_CSD_POWER_OFF_SHORT                2
+#define EXT_CSD_POWER_OFF_LONG         3
+
+#define EXT_CSD_PWR_CL_8BIT_MASK       0xF0    /* 8 bit PWR CLS */
+#define EXT_CSD_PWR_CL_4BIT_MASK       0x0F    /* 8 bit PWR CLS */
+#define EXT_CSD_PWR_CL_8BIT_SHIFT      4
+#define EXT_CSD_PWR_CL_4BIT_SHIFT      0
+
+#define EXT_CSD_PACKED_EVENT_EN        BIT(3)
 
 /*
  * MMC_SWITCH access modes