diff mbox series

[v3,09/20] mmc: am654_sdhci: Fix HISPD bit configuration in some lower speed modes

Message ID 20210121124052.3454-10-a-govindraju@ti.com
State Changes Requested
Delegated to: Lokesh Vutla
Headers show
Series Add support for MMC higher speed modes for TI's am65x, j721e and j7200 platforms | expand

Commit Message

Aswath Govindraju Jan. 21, 2021, 12:40 p.m. UTC
From: Faiz Abbas <faiz_abbas@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_abbas@ti.com>
Signed-off-by: Aswath Govindraju <a-govindraju@ti.com>
---
 drivers/mmc/Kconfig       |  1 +
 drivers/mmc/am654_sdhci.c | 25 +++++++++++++++++++++++--
 2 files changed, 24 insertions(+), 2 deletions(-)

Comments

Jaehoon Chung Jan. 25, 2021, 10:43 p.m. UTC | #1
On 1/21/21 9:40 PM, Aswath Govindraju wrote:
> From: Faiz Abbas <faiz_abbas@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_abbas@ti.com>
> Signed-off-by: Aswath Govindraju <a-govindraju@ti.com>

Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>

Best Regards,
Jaehoon Chung

> ---
>  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) {
>
diff mbox series

Patch

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) {