[U-Boot] [PATCH v8 10/14] mmc: sdhci: Add support for HOST_CONTROL2 and setting UHS timings

Faiz Abbas faiz_abbas at ti.com
Mon Jun 10 19:13:40 UTC 2019


The HOST_CONTROL2 register is a part of SDHC v3.00 and not just specific
to arasan/zynq controllers. Add the same to sdhci.h.

Also create a common API to set UHS timings in HOST_CONTROL2.

Signed-off-by: Faiz Abbas <faiz_abbas at ti.com>
Reviewed-by: Tom Rini <trini at konsulko.com>
---
 drivers/mmc/sdhci.c      | 28 +++++++++++++++++++++++++
 drivers/mmc/zynq_sdhci.c | 45 ++++++++--------------------------------
 include/sdhci.h          | 19 ++++++++++++++++-
 3 files changed, 55 insertions(+), 37 deletions(-)

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 7665441204..a6b95a4cb5 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -533,6 +533,34 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
 	sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
 }
 
+void sdhci_set_uhs_timing(struct sdhci_host *host)
+{
+	struct mmc *mmc = (struct mmc *)host->mmc;
+	u32 reg;
+
+	reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+	reg &= ~SDHCI_CTRL_UHS_MASK;
+
+	switch (mmc->selected_mode) {
+	case UHS_SDR50:
+	case MMC_HS_52:
+		reg |= SDHCI_CTRL_UHS_SDR50;
+		break;
+	case UHS_DDR50:
+	case MMC_DDR_52:
+		reg |= SDHCI_CTRL_UHS_DDR50;
+		break;
+	case UHS_SDR104:
+	case MMC_HS_200:
+		reg |= SDHCI_CTRL_UHS_SDR104;
+		break;
+	default:
+		reg |= SDHCI_CTRL_UHS_SDR12;
+	}
+
+	sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
+}
+
 #ifdef CONFIG_DM_MMC
 static int sdhci_set_ios(struct udevice *dev)
 {
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 08023783de..c525084250 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -48,11 +48,6 @@ static const u8 mode2timing[] = {
 	[MMC_HS_200] = MMC_HS200_BUS_SPEED,
 };
 
-#define SDHCI_HOST_CTRL2	0x3E
-#define SDHCI_CTRL2_MODE_MASK	0x7
-#define SDHCI_18V_SIGNAL	0x8
-#define SDHCI_CTRL_EXEC_TUNING	0x0040
-#define SDHCI_CTRL_TUNED_CLK	0x80
 #define SDHCI_TUNING_LOOP_COUNT	40
 
 static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
@@ -99,9 +94,9 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
 	host = priv->host;
 	deviceid = priv->deviceid;
 
-	ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
+	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 	ctrl |= SDHCI_CTRL_EXEC_TUNING;
-	sdhci_writew(host, ctrl, SDHCI_HOST_CTRL2);
+	sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
 	mdelay(1);
 
@@ -133,7 +128,7 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
 		sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
 
 		mmc_send_cmd(mmc, &cmd, NULL);
-		ctrl = sdhci_readw(host, SDHCI_HOST_CTRL2);
+		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 
 		if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK)
 			udelay(1);
@@ -142,7 +137,7 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
 
 	if (tuning_loop_counter < 0) {
 		ctrl &= ~SDHCI_CTRL_TUNED_CLK;
-		sdhci_writel(host, ctrl, SDHCI_HOST_CTRL2);
+		sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL2);
 	}
 
 	if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
@@ -184,36 +179,14 @@ static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
 		return;
 
 	if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
-		reg = sdhci_readw(host, SDHCI_HOST_CTRL2);
-		reg |= SDHCI_18V_SIGNAL;
-		sdhci_writew(host, reg, SDHCI_HOST_CTRL2);
+		reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+		reg |= SDHCI_CTRL_VDD_180;
+		sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
 	}
 
 	if (mmc->selected_mode > SD_HS &&
-	    mmc->selected_mode <= UHS_DDR50) {
-		reg = sdhci_readw(host, SDHCI_HOST_CTRL2);
-		reg &= ~SDHCI_CTRL2_MODE_MASK;
-		switch (mmc->selected_mode) {
-		case UHS_SDR12:
-			reg |= UHS_SDR12_BUS_SPEED;
-			break;
-		case UHS_SDR25:
-			reg |= UHS_SDR25_BUS_SPEED;
-			break;
-		case UHS_SDR50:
-			reg |= UHS_SDR50_BUS_SPEED;
-			break;
-		case UHS_SDR104:
-			reg |= UHS_SDR104_BUS_SPEED;
-			break;
-		case UHS_DDR50:
-			reg |= UHS_DDR50_BUS_SPEED;
-			break;
-		default:
-			break;
-		}
-		sdhci_writew(host, reg, SDHCI_HOST_CTRL2);
-	}
+	    mmc->selected_mode <= UHS_DDR50)
+		sdhci_set_uhs_timing(host);
 }
 #endif
 
diff --git a/include/sdhci.h b/include/sdhci.h
index 3dcbc14965..01addb7a60 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -144,7 +144,23 @@
 
 #define SDHCI_ACMD12_ERR	0x3C
 
-/* 3E-3F reserved */
+#define SDHCI_HOST_CONTROL2	0x3E
+#define  SDHCI_CTRL_UHS_MASK	0x0007
+#define  SDHCI_CTRL_UHS_SDR12	0x0000
+#define  SDHCI_CTRL_UHS_SDR25	0x0001
+#define  SDHCI_CTRL_UHS_SDR50	0x0002
+#define  SDHCI_CTRL_UHS_SDR104	0x0003
+#define  SDHCI_CTRL_UHS_DDR50	0x0004
+#define  SDHCI_CTRL_HS400	0x0005 /* Non-standard */
+#define  SDHCI_CTRL_VDD_180	0x0008
+#define  SDHCI_CTRL_DRV_TYPE_MASK	0x0030
+#define  SDHCI_CTRL_DRV_TYPE_B	0x0000
+#define  SDHCI_CTRL_DRV_TYPE_A	0x0010
+#define  SDHCI_CTRL_DRV_TYPE_C	0x0020
+#define  SDHCI_CTRL_DRV_TYPE_D	0x0030
+#define  SDHCI_CTRL_EXEC_TUNING	0x0040
+#define  SDHCI_CTRL_TUNED_CLK	0x0080
+#define  SDHCI_CTRL_PRESET_VAL_ENABLE	0x8000
 
 #define SDHCI_CAPABILITIES	0x40
 #define  SDHCI_TIMEOUT_CLK_MASK	0x0000003F
@@ -467,6 +483,7 @@ int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg);
 int add_sdhci(struct sdhci_host *host, u32 f_max, u32 f_min);
 #endif /* !CONFIG_BLK */
 
+void sdhci_set_uhs_timing(struct sdhci_host *host);
 #ifdef CONFIG_DM_MMC
 /* Export the operations to drivers */
 int sdhci_probe(struct udevice *dev);
-- 
2.19.2



More information about the U-Boot mailing list