diff options
-rw-r--r-- | drivers/mmc/host/sdhci.c | 44 | ||||
-rw-r--r-- | include/linux/mmc/sdhci.h | 1 |
2 files changed, 27 insertions, 18 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index effd9e5d1d81..447eef8217c7 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -205,9 +205,14 @@ static void sdhci_do_reset(struct sdhci_host *host, u8 mask) | |||
205 | 205 | ||
206 | host->ops->reset(host, mask); | 206 | host->ops->reset(host, mask); |
207 | 207 | ||
208 | if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { | 208 | if (mask & SDHCI_RESET_ALL) { |
209 | if ((host->ops->enable_dma) && (mask & SDHCI_RESET_ALL)) | 209 | if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { |
210 | host->ops->enable_dma(host); | 210 | if (host->ops->enable_dma) |
211 | host->ops->enable_dma(host); | ||
212 | } | ||
213 | |||
214 | /* Resetting the controller clears many */ | ||
215 | host->preset_enabled = false; | ||
211 | } | 216 | } |
212 | } | 217 | } |
213 | 218 | ||
@@ -1126,8 +1131,7 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) | |||
1126 | return; | 1131 | return; |
1127 | 1132 | ||
1128 | if (host->version >= SDHCI_SPEC_300) { | 1133 | if (host->version >= SDHCI_SPEC_300) { |
1129 | if (sdhci_readw(host, SDHCI_HOST_CONTROL2) & | 1134 | if (host->preset_enabled) { |
1130 | SDHCI_CTRL_PRESET_VAL_ENABLE) { | ||
1131 | u16 pre_val; | 1135 | u16 pre_val; |
1132 | 1136 | ||
1133 | clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); | 1137 | clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); |
@@ -1493,13 +1497,13 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) | |||
1493 | (ios->timing == MMC_TIMING_UHS_SDR25)) | 1497 | (ios->timing == MMC_TIMING_UHS_SDR25)) |
1494 | ctrl |= SDHCI_CTRL_HISPD; | 1498 | ctrl |= SDHCI_CTRL_HISPD; |
1495 | 1499 | ||
1496 | ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1500 | if (!host->preset_enabled) { |
1497 | if (!(ctrl_2 & SDHCI_CTRL_PRESET_VAL_ENABLE)) { | ||
1498 | sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); | 1501 | sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); |
1499 | /* | 1502 | /* |
1500 | * We only need to set Driver Strength if the | 1503 | * We only need to set Driver Strength if the |
1501 | * preset value enable is not set. | 1504 | * preset value enable is not set. |
1502 | */ | 1505 | */ |
1506 | ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); | ||
1503 | ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK; | 1507 | ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK; |
1504 | if (ios->drv_type == MMC_SET_DRIVER_TYPE_A) | 1508 | if (ios->drv_type == MMC_SET_DRIVER_TYPE_A) |
1505 | ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A; | 1509 | ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A; |
@@ -2018,26 +2022,30 @@ out: | |||
2018 | 2022 | ||
2019 | static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable) | 2023 | static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable) |
2020 | { | 2024 | { |
2021 | u16 ctrl; | ||
2022 | |||
2023 | /* Host Controller v3.00 defines preset value registers */ | 2025 | /* Host Controller v3.00 defines preset value registers */ |
2024 | if (host->version < SDHCI_SPEC_300) | 2026 | if (host->version < SDHCI_SPEC_300) |
2025 | return; | 2027 | return; |
2026 | 2028 | ||
2027 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | ||
2028 | |||
2029 | /* | 2029 | /* |
2030 | * We only enable or disable Preset Value if they are not already | 2030 | * We only enable or disable Preset Value if they are not already |
2031 | * enabled or disabled respectively. Otherwise, we bail out. | 2031 | * enabled or disabled respectively. Otherwise, we bail out. |
2032 | */ | 2032 | */ |
2033 | if (enable && !(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) { | 2033 | if (host->preset_enabled != enable) { |
2034 | ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE; | 2034 | u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
2035 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | 2035 | |
2036 | host->flags |= SDHCI_PV_ENABLED; | 2036 | if (enable) |
2037 | } else if (!enable && (ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) { | 2037 | ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE; |
2038 | ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; | 2038 | else |
2039 | ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; | ||
2040 | |||
2039 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | 2041 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); |
2040 | host->flags &= ~SDHCI_PV_ENABLED; | 2042 | |
2043 | if (enable) | ||
2044 | host->flags |= SDHCI_PV_ENABLED; | ||
2045 | else | ||
2046 | host->flags &= ~SDHCI_PV_ENABLED; | ||
2047 | |||
2048 | host->preset_enabled = enable; | ||
2041 | } | 2049 | } |
2042 | } | 2050 | } |
2043 | 2051 | ||
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index 7f3efbab8732..08abe9941884 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h | |||
@@ -143,6 +143,7 @@ struct sdhci_host { | |||
143 | 143 | ||
144 | bool runtime_suspended; /* Host is runtime suspended */ | 144 | bool runtime_suspended; /* Host is runtime suspended */ |
145 | bool bus_on; /* Bus power prevents runtime suspend */ | 145 | bool bus_on; /* Bus power prevents runtime suspend */ |
146 | bool preset_enabled; /* Preset is enabled */ | ||
146 | 147 | ||
147 | struct mmc_request *mrq; /* Current request */ | 148 | struct mmc_request *mrq; /* Current request */ |
148 | struct mmc_command *cmd; /* Current command */ | 149 | struct mmc_command *cmd; /* Current command */ |