mmc: am654_sdhci: Fix HISPD bit configuration in some lower speed modes

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_abbas@ti.com>
Signed-off-by: Aswath Govindraju <a-govindraju@ti.com>
Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
This commit is contained in:
Faiz Abbas 2021-02-04 15:10:54 +05:30 committed by Lokesh Vutla
parent a759abf569
commit 27a87c834f
2 changed files with 24 additions and 2 deletions

View file

@ -526,6 +526,7 @@ config MMC_SDHCI_AM654
depends on MMC_SDHCI depends on MMC_SDHCI
depends on DM_MMC && OF_CONTROL && BLK depends on DM_MMC && OF_CONTROL && BLK
depends on REGMAP depends on REGMAP
select MMC_SDHCI_IO_ACCESSORS
help help
Support for Secure Digital Host Controller Interface (SDHCI) Support for Secure Digital Host Controller Interface (SDHCI)
controllers present on TI's AM654 SOCs. controllers present on TI's AM654 SOCs.

View file

@ -369,6 +369,26 @@ static int am654_sdhci_deferred_probe(struct sdhci_host *host)
return sdhci_probe(dev); 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 #ifdef MMC_SUPPORTS_TUNING
#define ITAP_MAX 32 #define ITAP_MAX 32
static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 opcode) 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, .deferred_probe = am654_sdhci_deferred_probe,
.set_ios_post = &am654_sdhci_set_ios_post, .set_ios_post = &am654_sdhci_set_ios_post,
.set_control_reg = &am654_sdhci_set_control_reg, .set_control_reg = &am654_sdhci_set_control_reg,
.write_b = am654_sdhci_write_b,
}; };
const struct am654_driver_data am654_drv_data = { const struct am654_driver_data am654_drv_data = {
@ -455,6 +476,7 @@ const struct sdhci_ops j721e_4bit_sdhci_ops = {
#endif #endif
.deferred_probe = am654_sdhci_deferred_probe, .deferred_probe = am654_sdhci_deferred_probe,
.set_ios_post = &j721e_4bit_sdhci_set_ios_post, .set_ios_post = &j721e_4bit_sdhci_set_ios_post,
.write_b = am654_sdhci_write_b,
}; };
const struct am654_driver_data j721e_4bit_drv_data = { 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->max_clk = clock;
host->mmc = &plat->mmc; host->mmc = &plat->mmc;
host->mmc->dev = dev; host->mmc->dev = dev;
host->ops = drv_data->ops;
ret = sdhci_setup_cfg(cfg, host, cfg->f_max, ret = sdhci_setup_cfg(cfg, host, cfg->f_max,
AM654_SDHCI_MIN_FREQ); AM654_SDHCI_MIN_FREQ);
if (ret) if (ret)
@ -541,8 +564,6 @@ static int am654_sdhci_probe(struct udevice *dev)
if (ret) if (ret)
return ret; return ret;
host->ops = drv_data->ops;
/* Update ops based on SoC revision */ /* Update ops based on SoC revision */
soc = soc_device_match(am654_sdhci_soc_attr); soc = soc_device_match(am654_sdhci_soc_attr);
if (soc && soc->data) { if (soc && soc->data) {