mmc: sdhci: Add support for HOST_CONTROL2 and setting UHS timings
authorFaiz Abbas <faiz_abbas@ti.com>
Mon, 10 Jun 2019 19:13:40 +0000 (00:43 +0530)
committerTom Rini <trini@konsulko.com>
Wed, 17 Jul 2019 15:12:08 +0000 (11:12 -0400)
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@ti.com>
Reviewed-by: Tom Rini <trini@konsulko.com>
drivers/mmc/sdhci.c
drivers/mmc/zynq_sdhci.c
include/sdhci.h

index 61cf216e127b2b3460e311496e69a4601654455a..0a0770cc2035ca609896e8b10a267c5312e24786 100644 (file)
@@ -534,6 +534,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)
 {
index 08023783de48d78dc1c8a2735646e3de12ce6801..c525084250c6ca2669e192d1bf7c2fd76349b4bc 100644 (file)
@@ -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
 
index 3dcbc1496595325fd849572e0aaf4939c8571378..01addb7a6036585606179a2257dca0233475b67d 100644 (file)
 
 #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);