| From 3941b8cb84ce2c027633a67fab7b4df654fa0009 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 3 Sep 2019 07:51:14 -0400 |
| Subject: mmc: sdhci: Fix incorrect switch to HS mode |
| |
| From: Al Cooper <alcooperx@gmail.com> |
| |
| [ Upstream commit c894e33ddc1910e14d6f2a2016f60ab613fd8b37 ] |
| |
| When switching from any MMC speed mode that requires 1.8v |
| (HS200, HS400 and HS400ES) to High Speed (HS) mode, the system |
| ends up configured for SDR12 with a 50MHz clock which is an illegal |
| mode. |
| |
| This happens because the SDHCI_CTRL_VDD_180 bit in the |
| SDHCI_HOST_CONTROL2 register is left set and when this bit is |
| set, the speed mode is controlled by the SDHCI_CTRL_UHS field |
| in the SDHCI_HOST_CONTROL2 register. The SDHCI_CTRL_UHS field |
| will end up being set to 0 (SDR12) by sdhci_set_uhs_signaling() |
| because there is no UHS mode being set. |
| |
| The fix is to change sdhci_set_uhs_signaling() to set the |
| SDHCI_CTRL_UHS field to SDR25 (which is the same as HS) for |
| any switch to HS mode. |
| |
| This was found on a new eMMC controller that does strict checking |
| of the speed mode and the corresponding clock rate. It caused the |
| switch to HS400 mode to fail because part of the sequence to switch |
| to HS400 requires a switch from HS200 to HS before going to HS400. |
| |
| Suggested-by: Adrian Hunter <adrian.hunter@intel.com> |
| Signed-off-by: Al Cooper <alcooperx@gmail.com> |
| Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/mmc/host/sdhci.c | 4 +++- |
| 1 file changed, 3 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c |
| index df306caba296a..0347742a495a6 100644 |
| --- a/drivers/mmc/host/sdhci.c |
| +++ b/drivers/mmc/host/sdhci.c |
| @@ -1557,7 +1557,9 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing) |
| ctrl_2 |= SDHCI_CTRL_UHS_SDR104; |
| else if (timing == MMC_TIMING_UHS_SDR12) |
| ctrl_2 |= SDHCI_CTRL_UHS_SDR12; |
| - else if (timing == MMC_TIMING_UHS_SDR25) |
| + else if (timing == MMC_TIMING_SD_HS || |
| + timing == MMC_TIMING_MMC_HS || |
| + timing == MMC_TIMING_UHS_SDR25) |
| ctrl_2 |= SDHCI_CTRL_UHS_SDR25; |
| else if (timing == MMC_TIMING_UHS_SDR50) |
| ctrl_2 |= SDHCI_CTRL_UHS_SDR50; |
| -- |
| 2.20.1 |
| |