[U-Boot,RFC] mmc: sdhci: add support for switching to UHS-I modes on ZynqMP Platform
diff mbox series

Message ID 2eabee23243f240ed0999311e4cc50e5b0154fb6.1568209763.git.michal.simek@xilinx.com
State New
Delegated to: Michal Simek
Headers show
Series
  • [U-Boot,RFC] mmc: sdhci: add support for switching to UHS-I modes on ZynqMP Platform
Related show

Commit Message

Michal Simek Sept. 11, 2019, 1:49 p.m. UTC
From: T Karthik Reddy <t.karthik.reddy@xilinx.com>

This patch adds support for switching to UHS-I modes on ZynqMP platform.
There is one issue with the ZynqMP ZCU102 where it is not able to power
cycle the SD card. Due to this once the card is initialized in UHS-I
mode it cannot be reinitialized in UHS-I mode again. So to solve this
issue there are some of the checks are made in place to ensure that the
card operates in UHS-I mode even on reinitialization. This will enable
the SD host controller to run SD at UHS-I mode in u-boot if it was
running at UHS-I mode already.

Signed-off-by: T Karthik Reddy <t.karthik.reddy@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
---

 drivers/mmc/mmc.c | 20 ++++++++++++++++++++
 include/mmc.h     |  2 ++
 2 files changed, 22 insertions(+)

Patch
diff mbox series

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index c8f71cd0c1b6..3d25f11942ff 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1711,6 +1711,26 @@  static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
 	/* Restrict card's capabilities by what the host can do */
 	caps = card_caps & mmc->host_caps;
 
+	/*
+	 * If the card is already in 1.8V and the system doesn't have
+	 * mechanism to power cycle the SD card, it will respond with no 1.8V
+	 * supported in OCR response. Below check will confirm if the above
+	 * condition has occurred.
+	 *
+	 * If the host is supporting UHS modes and the card is supporting SD
+	 * specification 3.0 and above, it can operate at UHS modes.
+	 */
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
+	if (!uhs_en && !(mmc_host_is_spi(mmc)) &&
+	    mmc->scr[0] & SD_SCR0_SPEC3 &&
+	    (mmc->card_caps & MMC_MODE_MASK) >= MMC_CAP(UHS_SDR50) &&
+	    (mmc->host_caps & MMC_MODE_MASK) >= MMC_CAP(UHS_SDR50)) {
+		uhs_en = true;
+		err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
+		if (err)
+			return err;
+	}
+#endif
 	if (!uhs_en)
 		caps &= ~UHS_CAPS;
 
diff --git a/include/mmc.h b/include/mmc.h
index 686ba0065654..e959ffef2948 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -66,6 +66,7 @@ 
 #define MMC_MODE_HS200		MMC_CAP(MMC_HS_200)
 #define MMC_MODE_HS400		MMC_CAP(MMC_HS_400)
 #define MMC_MODE_HS400_ES	MMC_CAP(MMC_HS_400_ES)
+#define MMC_MODE_MASK		(MMC_CAP(MMC_MODES_END) - 1)
 
 #define MMC_CAP_NONREMOVABLE	BIT(14)
 #define MMC_CAP_NEEDS_POLL	BIT(15)
@@ -140,6 +141,7 @@  static inline bool mmc_is_tuning_cmd(uint cmdidx)
 /* SCR definitions in different words */
 #define SD_HIGHSPEED_BUSY	0x00020000
 #define SD_HIGHSPEED_SUPPORTED	0x00020000
+#define SD_SCR0_SPEC3		BIT(15)
 
 #define UHS_SDR12_BUS_SPEED	0
 #define HIGH_SPEED_BUS_SPEED	1