mmc: core: support HPI send command
[pandora-kernel.git] / drivers / mmc / core / mmc.c
index 5408876..fb5bf01 100644 (file)
@@ -448,6 +448,21 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
        }
 
        if (card->ext_csd.rev >= 5) {
+               /* 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];
        }
@@ -470,6 +485,12 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
        } else
                card->ext_csd.generic_cmd6_time = 0;
 
+       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;
+
 out:
        return err;
 }
@@ -663,7 +684,7 @@ static int mmc_select_powerclass(struct mmc_card *card,
                err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                 EXT_CSD_POWER_CLASS,
                                 pwrclass_val,
-                                0);
+                                card->ext_csd.generic_cmd6_time);
        }
 
        return err;
@@ -889,6 +910,22 @@ 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, 0);
+               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;
+       }
+
        /*
         * Compute bus speed.
         */
@@ -1020,6 +1057,23 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                }
        }
 
+       /*
+        * 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, 0);
+               if (err && err != -EBADMSG)
+                       goto free_card;
+
+               /*
+                * Only if no error, cache is turned on successfully.
+                */
+               card->ext_csd.cache_ctrl = err ? 0 : 1;
+       }
+
        if (!oldcard)
                host->card = card;