diff options
author | Peter Griffin <peter.griffin@linaro.org> | 2015-04-10 05:40:27 -0400 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2015-04-10 06:55:40 -0400 |
commit | cf48d32efb4b9e70ca1e17f2c38f77756e9aae58 (patch) | |
tree | aa07dabb5c9a7c6626cd58dab244fa39c19da10e | |
parent | 2053812f6e1af0b8c3d18d4d6d9f356b0c0d0039 (diff) |
mmc: sdhci-st: Add sdhci_st_set_uhs_signaling function.
To allow UHS modes to work properly we need to provide the st specific
set_uhs_signaling callback function. This function differs from the
generic sdhci_set_uhs_signaling callback in that we need to configure
the correct delay depending on the UHS mode, and also set the V18_EN
bit.
Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Acked-by: Maxime Coquelin <maxime.coquelin@st.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r-- | drivers/mmc/host/sdhci-st.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index 10989edb5100..42a361c14f52 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c | |||
@@ -261,6 +261,56 @@ static int sdhci_st_set_dll_for_clock(struct sdhci_host *host) | |||
261 | return ret; | 261 | return ret; |
262 | } | 262 | } |
263 | 263 | ||
264 | static void sdhci_st_set_uhs_signaling(struct sdhci_host *host, | ||
265 | unsigned int uhs) | ||
266 | { | ||
267 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
268 | struct st_mmc_platform_data *pdata = pltfm_host->priv; | ||
269 | u16 ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); | ||
270 | int ret = 0; | ||
271 | |||
272 | /* Select Bus Speed Mode for host */ | ||
273 | ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; | ||
274 | switch (uhs) { | ||
275 | /* | ||
276 | * Set V18_EN -- UHS modes do not work without this. | ||
277 | * does not change signaling voltage | ||
278 | */ | ||
279 | |||
280 | case MMC_TIMING_UHS_SDR12: | ||
281 | st_mmcss_set_static_delay(pdata->top_ioaddr); | ||
282 | ctrl_2 |= SDHCI_CTRL_UHS_SDR12 | SDHCI_CTRL_VDD_180; | ||
283 | break; | ||
284 | case MMC_TIMING_UHS_SDR25: | ||
285 | st_mmcss_set_static_delay(pdata->top_ioaddr); | ||
286 | ctrl_2 |= SDHCI_CTRL_UHS_SDR25 | SDHCI_CTRL_VDD_180; | ||
287 | break; | ||
288 | case MMC_TIMING_UHS_SDR50: | ||
289 | st_mmcss_set_static_delay(pdata->top_ioaddr); | ||
290 | ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180; | ||
291 | ret = sdhci_st_set_dll_for_clock(host); | ||
292 | break; | ||
293 | case MMC_TIMING_UHS_SDR104: | ||
294 | case MMC_TIMING_MMC_HS200: | ||
295 | st_mmcss_set_static_delay(pdata->top_ioaddr); | ||
296 | ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180; | ||
297 | ret = sdhci_st_set_dll_for_clock(host); | ||
298 | break; | ||
299 | case MMC_TIMING_UHS_DDR50: | ||
300 | case MMC_TIMING_MMC_DDR52: | ||
301 | st_mmcss_set_static_delay(pdata->top_ioaddr); | ||
302 | ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180; | ||
303 | break; | ||
304 | } | ||
305 | |||
306 | if (ret) | ||
307 | dev_warn(mmc_dev(host->mmc), "Error setting dll for clock " | ||
308 | "(uhs %d)\n", uhs); | ||
309 | |||
310 | dev_dbg(mmc_dev(host->mmc), "uhs %d, ctrl_2 %04X\n", uhs, ctrl_2); | ||
311 | |||
312 | sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); | ||
313 | } | ||
264 | 314 | ||
265 | static u32 sdhci_st_readl(struct sdhci_host *host, int reg) | 315 | static u32 sdhci_st_readl(struct sdhci_host *host, int reg) |
266 | { | 316 | { |
@@ -284,6 +334,7 @@ static const struct sdhci_ops sdhci_st_ops = { | |||
284 | .set_bus_width = sdhci_set_bus_width, | 334 | .set_bus_width = sdhci_set_bus_width, |
285 | .read_l = sdhci_st_readl, | 335 | .read_l = sdhci_st_readl, |
286 | .reset = sdhci_reset, | 336 | .reset = sdhci_reset, |
337 | .set_uhs_signaling = sdhci_st_set_uhs_signaling, | ||
287 | }; | 338 | }; |
288 | 339 | ||
289 | static const struct sdhci_pltfm_data sdhci_st_pdata = { | 340 | static const struct sdhci_pltfm_data sdhci_st_pdata = { |