From: Faiz Abbas <faiz_ab...@ti.com>

According to the AM654x Data Manual[1], the setup timing in lower speed
modes can only be met if the controller uses a falling edge data launch.

To ensure this, the HIGH_SPEED_ENA (HOST_CONTROL[2]) bit should be
cleared in default speed, SD high speed, MMC high speed, SDR12 and SDR25
speed modes.

Use the sdhci writeb callback to implement this condition.

[1] http://www.ti.com/lit/gpn/am6546 Section 5.10.5.16.1

Signed-off-by: Faiz Abbas <faiz_ab...@ti.com>
Signed-off-by: Aswath Govindraju <a-govindr...@ti.com>
Reviewed-by: Jaehoon Chung <jh80.ch...@samsung.com>
---
 drivers/mmc/Kconfig       |  1 +
 drivers/mmc/am654_sdhci.c | 25 +++++++++++++++++++++++--
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 14d79139864a..f8ea92172e44 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -526,6 +526,7 @@ config MMC_SDHCI_AM654
        depends on MMC_SDHCI
        depends on DM_MMC && OF_CONTROL && BLK
        depends on REGMAP
+       select MMC_SDHCI_IO_ACCESSORS
        help
          Support for Secure Digital Host Controller Interface (SDHCI)
          controllers present on TI's AM654 SOCs.
diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index 9549420c6582..5dea3eb1be4e 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -369,6 +369,26 @@ static int am654_sdhci_deferred_probe(struct sdhci_host 
*host)
        return sdhci_probe(dev);
 }
 
+static void am654_sdhci_write_b(struct sdhci_host *host, u8 val, int reg)
+{
+       if (reg == SDHCI_HOST_CONTROL) {
+               switch (host->mmc->selected_mode) {
+               /*
+                * According to the data manual, HISPD bit
+                * should not be set in these speed modes.
+                */
+               case SD_HS:
+               case MMC_HS:
+               case UHS_SDR12:
+               case UHS_SDR25:
+                       val &= ~SDHCI_CTRL_HISPD;
+               default:
+                       break;
+               }
+       }
+
+       writeb(val, host->ioaddr + reg);
+}
 #ifdef MMC_SUPPORTS_TUNING
 #define ITAP_MAX       32
 static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
@@ -414,6 +434,7 @@ const struct sdhci_ops am654_sdhci_ops = {
        .deferred_probe         = am654_sdhci_deferred_probe,
        .set_ios_post           = &am654_sdhci_set_ios_post,
        .set_control_reg        = &am654_sdhci_set_control_reg,
+       .write_b                = am654_sdhci_write_b,
 };
 
 const struct am654_driver_data am654_drv_data = {
@@ -455,6 +476,7 @@ const struct sdhci_ops j721e_4bit_sdhci_ops = {
 #endif
        .deferred_probe         = am654_sdhci_deferred_probe,
        .set_ios_post           = &j721e_4bit_sdhci_set_ios_post,
+       .write_b                = am654_sdhci_write_b,
 };
 
 const struct am654_driver_data j721e_4bit_drv_data = {
@@ -532,6 +554,7 @@ static int am654_sdhci_probe(struct udevice *dev)
        host->max_clk = clock;
        host->mmc = &plat->mmc;
        host->mmc->dev = dev;
+       host->ops = drv_data->ops;
        ret = sdhci_setup_cfg(cfg, host, cfg->f_max,
                              AM654_SDHCI_MIN_FREQ);
        if (ret)
@@ -541,8 +564,6 @@ static int am654_sdhci_probe(struct udevice *dev)
        if (ret)
                return ret;
 
-       host->ops = drv_data->ops;
-
        /* Update ops based on SoC revision */
        soc = soc_device_match(am654_sdhci_soc_attr);
        if (soc && soc->data) {
-- 
2.17.1

Reply via email to