storage/mmc: support early init in coreboot

If the eMMC has been already initialized in coreboot
(lib_sysinfo.mmc_early_wake_status), we should skip
sending CMD0 or CMD1 (or both).

BUG=b:177389446
TEST=none
BRANCH=asurada

Signed-off-by: Wenbin Mei <wenbin.mei@mediatek.com>
Change-Id: I63a8366bba30e8e08892f29c60a3e472166808b6
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/depthcharge/+/2785738
Reviewed-by: Yu-Ping Wu <yupingso@chromium.org>
Reviewed-by: Hung-Te Lin <hungte@chromium.org>
Commit-Queue: Hung-Te Lin <hungte@chromium.org>
Tested-by: Hung-Te Lin <hungte@chromium.org>
diff --git a/src/drivers/storage/mmc.c b/src/drivers/storage/mmc.c
index 4c98edc..3cb2bf9 100644
--- a/src/drivers/storage/mmc.c
+++ b/src/drivers/storage/mmc.c
@@ -1265,6 +1265,40 @@
 	return 0;
 }
 
+static int mmc_early_init(MmcMedia *media)
+{
+	int err;
+
+	/* Reset the Card */
+	err = mmc_go_idle(media);
+	if (err)
+		return err;
+
+	/* If the slot_type is unknown or removable we try SD first then MMC. */
+	if (media->ctrlr->slot_type == MMC_SLOT_TYPE_UNKNOWN ||
+	    media->ctrlr->slot_type == MMC_SLOT_TYPE_REMOVABLE) {
+		/* Test for SD version 2 */
+		err = mmc_send_if_cond(media);
+
+		/* Get SD card operating condition */
+		err = sd_send_op_cond(media);
+	}
+
+	/* If the slot is embedded or the SD command timed out, we check for an
+	 * MMC card */
+	if (media->ctrlr->slot_type == MMC_SLOT_TYPE_EMBEDDED ||
+	    err == MMC_TIMEOUT) {
+		err = mmc_send_op_cond(media);
+
+		if (err && err != MMC_IN_PROGRESS) {
+			printf("MMC did not respond to voltage select!\n");
+			return MMC_UNUSABLE_ERR;
+		}
+	}
+
+	return err;
+}
+
 int mmc_setup_media(MmcCtrlr *ctrlr)
 {
 	int err;
@@ -1275,33 +1309,21 @@
 	mmc_set_timing(ctrlr, MMC_TIMING_INITIALIZATION);
 	mmc_set_bus_width(ctrlr, 1);
 
-	/* Reset the Card */
-	err = mmc_go_idle(media);
-	if (err) {
-		free(media);
-		return err;
-	}
-
-	/* If the slot_type is unknown or removable we try SD first then MMC. */
-	if (ctrlr->slot_type == MMC_SLOT_TYPE_UNKNOWN ||
-	    ctrlr->slot_type == MMC_SLOT_TYPE_REMOVABLE) {
-		/* Test for SD version 2 */
-		err = mmc_send_if_cond(media);
-
-		/* Get SD card operating condition */
-		err = sd_send_op_cond(media);
-	}
-
-	/* If the slot is embedded or the SD command timed out, we check for an
-	 * MMC card */
-	if (ctrlr->slot_type == MMC_SLOT_TYPE_EMBEDDED || err == MMC_TIMEOUT) {
-		err = mmc_send_op_cond(media);
-
-		if (err && err != MMC_IN_PROGRESS) {
-			printf("MMC did not respond to voltage select!\n");
-			free(media);
-			return MMC_UNUSABLE_ERR;
+	if (ctrlr->slot_type == MMC_SLOT_TYPE_EMBEDDED &&
+	    lib_sysinfo.mmc_early_wake_status) {
+		switch (lib_sysinfo.mmc_early_wake_status) {
+		case MMC_STATUS_CMD1_READY:
+			err = 0;
+			break;
+		case MMC_STATUS_CMD1_IN_PROGRESS:
+			err = MMC_IN_PROGRESS;
+			break;
+		default:
+			err = mmc_early_init(media);
+			break;
 		}
+	} else {
+		err = mmc_early_init(media);
 	}
 
 	if (err && err != MMC_IN_PROGRESS) {
diff --git a/src/drivers/storage/mmc.h b/src/drivers/storage/mmc.h
index 5c1fca2..f05b005 100644
--- a/src/drivers/storage/mmc.h
+++ b/src/drivers/storage/mmc.h
@@ -66,6 +66,14 @@
 #define MMC_IN_PROGRESS		-20 /* operation is in progress */
 #define MMC_INVALID_ERR		-21 /* A catch all case. */
 
+/* MMC status in CBMEM_ID_MMC_STATUS */
+enum {
+	MMC_STATUS_NEED_RESET = 0,
+	MMC_STATUS_CMD1_READY_OR_IN_PROGRESS,
+	MMC_STATUS_CMD1_READY,
+	MMC_STATUS_CMD1_IN_PROGRESS,
+};
+
 #define MMC_CMD_GO_IDLE_STATE		0
 #define MMC_CMD_SEND_OP_COND		1
 #define MMC_CMD_ALL_SEND_CID		2