aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2014-12-05 12:25:31 -0500
committerUlf Hansson <ulf.hansson@linaro.org>2015-01-12 04:14:56 -0500
commitb5540ce1512eede3bed68ab1e9949df9ad556091 (patch)
treeb72f27bae81f9273b04769a7168db2b88e86ef8e
parent38e40bf5db9d5b8cbaeca9a78ee17f38473dd78d (diff)
mmc: sdhci: Disable re-tuning for HS400
Re-tuning for HS400 mode must be done in HS200 mode. Currently there is no support for that. That needs to be reflected in the code. Specifically, if tuning is executed in HS400 mode then return an error, and do not start the tuning timer if HS200 tuning is being done prior to switching to HS400. Note that periodic re-tuning is not expected to be needed for HS400 but re-tuning is still needed after the host controller has lost power. In the case of suspend/resume that is not necessary because the card is fully re-initialised. That just leaves runtime suspend/resume with no support for HS400 re-tuning. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/host/sdhci.c29
-rw-r--r--include/linux/mmc/sdhci.h1
2 files changed, 30 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 5c28c19622e6..398e9e496736 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1878,6 +1878,18 @@ static int sdhci_card_busy(struct mmc_host *mmc)
1878 return !(present_state & SDHCI_DATA_LVL_MASK); 1878 return !(present_state & SDHCI_DATA_LVL_MASK);
1879} 1879}
1880 1880
1881static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
1882{
1883 struct sdhci_host *host = mmc_priv(mmc);
1884 unsigned long flags;
1885
1886 spin_lock_irqsave(&host->lock, flags);
1887 host->flags |= SDHCI_HS400_TUNING;
1888 spin_unlock_irqrestore(&host->lock, flags);
1889
1890 return 0;
1891}
1892
1881static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) 1893static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
1882{ 1894{
1883 struct sdhci_host *host = mmc_priv(mmc); 1895 struct sdhci_host *host = mmc_priv(mmc);
@@ -1886,10 +1898,14 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
1886 int err = 0; 1898 int err = 0;
1887 unsigned long flags; 1899 unsigned long flags;
1888 unsigned int tuning_count = 0; 1900 unsigned int tuning_count = 0;
1901 bool hs400_tuning;
1889 1902
1890 sdhci_runtime_pm_get(host); 1903 sdhci_runtime_pm_get(host);
1891 spin_lock_irqsave(&host->lock, flags); 1904 spin_lock_irqsave(&host->lock, flags);
1892 1905
1906 hs400_tuning = host->flags & SDHCI_HS400_TUNING;
1907 host->flags &= ~SDHCI_HS400_TUNING;
1908
1893 if (host->tuning_mode == SDHCI_TUNING_MODE_1) 1909 if (host->tuning_mode == SDHCI_TUNING_MODE_1)
1894 tuning_count = host->tuning_count; 1910 tuning_count = host->tuning_count;
1895 1911
@@ -1901,8 +1917,20 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
1901 * tuning function has to be executed. 1917 * tuning function has to be executed.
1902 */ 1918 */
1903 switch (host->timing) { 1919 switch (host->timing) {
1920 /* HS400 tuning is done in HS200 mode */
1904 case MMC_TIMING_MMC_HS400: 1921 case MMC_TIMING_MMC_HS400:
1922 err = -EINVAL;
1923 goto out_unlock;
1924
1905 case MMC_TIMING_MMC_HS200: 1925 case MMC_TIMING_MMC_HS200:
1926 /*
1927 * Periodic re-tuning for HS400 is not expected to be needed, so
1928 * disable it here.
1929 */
1930 if (hs400_tuning)
1931 tuning_count = 0;
1932 break;
1933
1906 case MMC_TIMING_UHS_SDR104: 1934 case MMC_TIMING_UHS_SDR104:
1907 break; 1935 break;
1908 1936
@@ -2130,6 +2158,7 @@ static const struct mmc_host_ops sdhci_ops = {
2130 .hw_reset = sdhci_hw_reset, 2158 .hw_reset = sdhci_hw_reset,
2131 .enable_sdio_irq = sdhci_enable_sdio_irq, 2159 .enable_sdio_irq = sdhci_enable_sdio_irq,
2132 .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, 2160 .start_signal_voltage_switch = sdhci_start_signal_voltage_switch,
2161 .prepare_hs400_tuning = sdhci_prepare_hs400_tuning,
2133 .execute_tuning = sdhci_execute_tuning, 2162 .execute_tuning = sdhci_execute_tuning,
2134 .card_event = sdhci_card_event, 2163 .card_event = sdhci_card_event,
2135 .card_busy = sdhci_card_busy, 2164 .card_busy = sdhci_card_busy,
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 375af80bde7d..f767a0de611f 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -137,6 +137,7 @@ struct sdhci_host {
137#define SDHCI_SDR104_NEEDS_TUNING (1<<10) /* SDR104/HS200 needs tuning */ 137#define SDHCI_SDR104_NEEDS_TUNING (1<<10) /* SDR104/HS200 needs tuning */
138#define SDHCI_USING_RETUNING_TIMER (1<<11) /* Host is using a retuning timer for the card */ 138#define SDHCI_USING_RETUNING_TIMER (1<<11) /* Host is using a retuning timer for the card */
139#define SDHCI_USE_64_BIT_DMA (1<<12) /* Use 64-bit DMA */ 139#define SDHCI_USE_64_BIT_DMA (1<<12) /* Use 64-bit DMA */
140#define SDHCI_HS400_TUNING (1<<13) /* Tuning for HS400 */
140 141
141 unsigned int version; /* SDHCI spec. version */ 142 unsigned int version; /* SDHCI spec. version */
142 143