.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_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,
+                                0);
+       }
+
+       return err;
+}
+
 /*
  * Handle the detection and initialisation of a card.
  *
                        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_err("%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],
                }
 
                if (!err && ddr) {
+                       err = mmc_select_powerclass(card, ext_csd_bits[idx][1],
+                                                   ext_csd);
+                       if (err)
+                               pr_err("%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],
 
 #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_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 */
 #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_POWER_OFF_LONG_TIME    247     /* RO */
 
 /*
  * EXT_CSD field definitions
 #define EXT_CSD_RST_N_EN_MASK  0x3
 #define EXT_CSD_RST_N_ENABLED  1       /* RST_n is enabled on card */
 
+#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
 /*
  * MMC_SWITCH access modes
  */