drivers: mmc: Add wait_dat0 support for sdhci driver

Adds an implementation of the wait_dat0 MMC operation for the DM SDHCI
driver, allowing the driver to continue when the card is ready rather
than waiting for the worst case time on each MMC switch operation.

Signed-off-by: Stephen Carlson <stcarlso@linux.microsoft.com>
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 03bfd9d..766e4a6 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -780,6 +780,25 @@
 		return value;
 }
 
+static int sdhci_wait_dat0(struct udevice *dev, int state,
+			   int timeout_us)
+{
+	int tmp;
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+	struct sdhci_host *host = mmc->priv;
+	unsigned long timeout = timer_get_us() + timeout_us;
+
+	// readx_poll_timeout is unsuitable because sdhci_readl accepts
+	// two arguments
+	do {
+		tmp = sdhci_readl(host, SDHCI_PRESENT_STATE);
+		if (!!(tmp & SDHCI_DATA_0_LVL_MASK) == !!state)
+			return 0;
+	} while (!timeout_us || !time_after(timer_get_us(), timeout));
+
+	return -ETIMEDOUT;
+}
+
 const struct dm_mmc_ops sdhci_ops = {
 	.send_cmd	= sdhci_send_command,
 	.set_ios	= sdhci_set_ios,
@@ -788,6 +807,7 @@
 #ifdef MMC_SUPPORTS_TUNING
 	.execute_tuning	= sdhci_execute_tuning,
 #endif
+	.wait_dat0	= sdhci_wait_dat0,
 };
 #else
 static const struct mmc_ops sdhci_ops = {