msm_shared: mmc_sdhci: Add support for sleep function

Add function to put mmc card to sleep mode.

Change-Id: Iba1bd1667a9e897fc423eac5624f59b44ac749b0
diff --git a/platform/msm_shared/include/mmc_sdhci.h b/platform/msm_shared/include/mmc_sdhci.h
index 0c6c3eb..6aa323d 100644
--- a/platform/msm_shared/include/mmc_sdhci.h
+++ b/platform/msm_shared/include/mmc_sdhci.h
@@ -37,6 +37,7 @@
 #define CMD2_ALL_SEND_CID                         2
 #define CMD3_SEND_RELATIVE_ADDR                   3
 #define CMD4_SET_DSR                              4
+#define CMD5_SLEEP_AWAKE                          5
 #define CMD6_SWITCH_FUNC                          6
 #define CMD7_SELECT_DESELECT_CARD                 7
 #define CMD8_SEND_EXT_CSD                         8
@@ -124,9 +125,11 @@
 
 /* RCA of the card */
 #define MMC_RCA                                   2
+#define MMC_CARD_RCA_BIT                          16
 
 /* Misc card macros */
 #define MMC_BLK_SZ                                512
+#define MMC_CARD_SLEEP                            (1 << 15)
 
 /* Clock rates */
 #define MMC_CLK_400KHZ                            400000
@@ -236,4 +239,6 @@
 uint32_t mmc_set_clr_power_on_wp_user(struct mmc_device *dev, uint32_t addr, uint64_t len, uint8_t set_clr);
 /* API: Get the WP status of write protect groups starting at addr */
 uint32_t mmc_get_wp_status(struct mmc_device *dev, uint32_t addr, uint8_t *wp_status);
+/* API: Put the mmc card in sleep mode */
+void mmc_put_card_to_sleep(struct mmc_device *dev);
 #endif
diff --git a/platform/msm_shared/mmc_sdhci.c b/platform/msm_shared/mmc_sdhci.c
index bfdeeef..1e6aaa8 100644
--- a/platform/msm_shared/mmc_sdhci.c
+++ b/platform/msm_shared/mmc_sdhci.c
@@ -1641,3 +1641,31 @@
 
 	return 0;
 }
+
+/* Function to put the mmc card to sleep */
+void mmc_put_card_to_sleep(struct mmc_device *dev)
+{
+	struct mmc_command cmd = {0};
+	struct mmc_card *card = &dev->card;
+
+	cmd.cmd_index = CMD7_SELECT_DESELECT_CARD;
+	cmd.argument = 0x00000000;
+	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd.resp_type = SDHCI_CMD_RESP_NONE;
+
+	/* send command */
+	if(sdhci_send_command(&dev->host, &cmd))
+	{
+		dprintf(CRITICAL, "card deselect error: %s\n", __func__);
+		return;
+	}
+
+	cmd.cmd_index = CMD5_SLEEP_AWAKE;
+	cmd.argument = (card->rca << MMC_CARD_RCA_BIT) | MMC_CARD_SLEEP;
+	cmd.cmd_type = SDHCI_CMD_TYPE_NORMAL;
+	cmd.resp_type = SDHCI_CMD_RESP_R1B;
+
+	/* send command */
+	if(sdhci_send_command(&dev->host, &cmd))
+		dprintf(CRITICAL, "card sleep error: %s\n", __func__);
+}