From 38396ba52ab85ea1eabea3c92fd7532f8732f92e Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 24 Jul 2018 15:49:29 +0200 Subject: [PATCH] mmc: core: use hs400es voltage flags --- drivers/mmc/core/mmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index a814eb6882aa..1d950f0b3aa6 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1259,10 +1259,10 @@ static int mmc_select_hs400es(struct mmc_card *card) goto out_err; } - if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V) + if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400_1_2V) err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); - if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V) + if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400_1_8V) err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); /* If fails try again during next card power cycle */ From 92a57737adc14e15e80b6913932bb5d2d3478068 Mon Sep 17 00:00:00 2001 From: Haibo Chen Date: Tue, 8 Aug 2017 18:54:01 +0800 Subject: [PATCH] UPSTREAM: mmc: mmc: correct the logic for setting HS400ES signal voltage Change the default err value to -EINVAL, make sure the card only has type EXT_CSD_CARD_TYPE_HS400_1_8V also do the signal voltage setting when select hs400es mode. Fixes: commit 1720d3545b77 ("mmc: core: switch to 1V8 or 1V2 for hs400es mode") Cc: Signed-off-by: Haibo Chen Reviewed-by: Shawn Lin Signed-off-by: Ulf Hansson (cherry picked from commit 92ddd95919466de5d34f3cb43635da9a7f9ab814) --- drivers/mmc/core/mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 1d950f0b3aa6..70de514dd061 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1251,7 +1251,7 @@ out_err: static int mmc_select_hs400es(struct mmc_card *card) { struct mmc_host *host = card->host; - int err = 0; + int err = -EINVAL; u8 val; if (!(host->caps & MMC_CAP_8_BIT_DATA)) { From 108a045df9dc1cee2127aec0bdd327ba7f2fdb81 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Wed, 25 Jan 2017 10:12:10 +0100 Subject: [PATCH] UPSTREAM: mmc: core: Remove redundant code in mmc_set_signal_voltage() The mmc_set_signal_voltage() function is used for SD/SDIO when switching to 1.8V for UHS mode. Therefore let's remove the redundant code dealing with MMC_SIGNAL_VOLTAGE_330. Signed-off-by: Ulf Hansson Reviewed-by: Shawn Lin Tested-by: Jan Glauber Tested-by: Stefan Wahren (cherry picked from commit a44efa4796249c6d4341935e90e9105d6e1a5f15) --- drivers/mmc/core/core.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 3e3c79feb07b..b69c96ad9486 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1598,13 +1598,6 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr) BUG_ON(!host); - /* - * Send CMD11 only if the request is to switch the card to - * 1.8V signalling. - */ - if (signal_voltage == MMC_SIGNAL_VOLTAGE_330) - return __mmc_set_signal_voltage(host, signal_voltage); - /* * If we cannot switch voltages, return failure so the caller * can continue without UHS mode From d28c1bfff6556db2c4ce1093091293cf20542202 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Wed, 25 Jan 2017 10:25:01 +0100 Subject: [PATCH] UPSTREAM: mmc: core: Clarify usage of mmc_set_signal_voltage() The mmc_set_signal_voltage() function is used for SD/SDIO when switching to 1.8V for UHS mode. To clarify this let's do the following changes. - We are always providing MMC_SIGNAL_VOLTAGE_180 as the signal_voltage parameter to the function. Then, let's just remove the parameter as it serves no purpose. - Rename the function to mmc_set_uhs_voltage(). Signed-off-by: Ulf Hansson Reviewed-by: Shawn Lin Tested-by: Jan Glauber Tested-by: Stefan Wahren (cherry picked from commit 2ed573b603f78289dd1435c94597aa25a97e2b76) --- drivers/mmc/core/core.c | 4 ++-- drivers/mmc/core/core.h | 2 +- drivers/mmc/core/sd.c | 3 +-- drivers/mmc/core/sdio.c | 3 +-- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index b69c96ad9486..35d19d57d2c5 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1590,7 +1590,7 @@ int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) } -int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr) +int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr) { struct mmc_command cmd = {0}; int err = 0; @@ -1636,7 +1636,7 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr) host->ios.clock = 0; mmc_set_ios(host); - if (__mmc_set_signal_voltage(host, signal_voltage)) { + if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) { /* * Voltages may not have been switched, but we've already * sent CMD11, so a power cycle is required anyway diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index ed7c3167763a..88ef50b2e0be 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -43,7 +43,7 @@ void mmc_set_clock(struct mmc_host *host, unsigned int hz); void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); void mmc_set_bus_width(struct mmc_host *host, unsigned int width); u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); -int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr); +int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr); int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); void mmc_set_timing(struct mmc_host *host, unsigned int timing); void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index cd437d6b1843..d9943d82db95 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -742,8 +742,7 @@ try_again: */ if (!mmc_host_is_spi(host) && rocr && ((*rocr & 0x41000000) == 0x41000000)) { - err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, - pocr); + err = mmc_set_uhs_voltage(host, pocr); if (err == -EAGAIN) { retries--; goto try_again; diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index c586b11a40b5..f221418542e2 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -648,8 +648,7 @@ try_again: * to make sure which speed mode should work. */ if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) { - err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, - ocr_card); + err = mmc_set_uhs_voltage(host, ocr_card); if (err == -EAGAIN) { mmc_sdio_resend_if_cond(host, card); retries--; From 0f61c64862ed54163c5f88389170c95055a74f68 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Wed, 25 Jan 2017 11:12:34 +0100 Subject: [PATCH] UPSTREAM: mmc: core: Rename __mmc_set_signal_voltage() to mmc_set_signal_voltage() Earlier the mmc_set_signal_voltage() existed, but since it has been renamed to mmc_set_uhs_voltage(), we can now use that name instead. Signed-off-by: Ulf Hansson Reviewed-by: Shawn Lin Tested-by: Jan Glauber Tested-by: Stefan Wahren (cherry picked from commit 4e74b6b3c6e9adfe6a8fdebfc56a6416a996d905) --- drivers/mmc/core/core.c | 10 +++++----- drivers/mmc/core/core.h | 2 +- drivers/mmc/core/mmc.c | 16 ++++++++-------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 35d19d57d2c5..ba285431c2d0 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1574,7 +1574,7 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr) return ocr; } -int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) +int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) { int err = 0; int old_signal_voltage = host->ios.signal_voltage; @@ -1636,7 +1636,7 @@ int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr) host->ios.clock = 0; mmc_set_ios(host); - if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) { + if (mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) { /* * Voltages may not have been switched, but we've already * sent CMD11, so a power cycle is required anyway @@ -1745,11 +1745,11 @@ void mmc_power_up(struct mmc_host *host, u32 ocr) mmc_set_initial_state(host); /* Try to set signal voltage to 3.3V but fall back to 1.8v or 1.2v */ - if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330) == 0) + if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330)) dev_dbg(mmc_dev(host), "Initial signal voltage of 3.3v\n"); - else if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180) == 0) + else if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) dev_dbg(mmc_dev(host), "Initial signal voltage of 1.8v\n"); - else if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120) == 0) + else if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120)) dev_dbg(mmc_dev(host), "Initial signal voltage of 1.2v\n"); /* diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 88ef50b2e0be..0e4bc1c7a773 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -44,7 +44,7 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); void mmc_set_bus_width(struct mmc_host *host, unsigned int width); u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr); -int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); +int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); void mmc_set_timing(struct mmc_host *host, unsigned int timing); void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); int mmc_select_drive_strength(struct mmc_card *card, unsigned int max_dtr, diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 70de514dd061..dd0040a10c0b 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1088,14 +1088,14 @@ static int mmc_select_hs_ddr(struct mmc_card *card) */ err = -EINVAL; if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_1_2V) - err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); + err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); if (err && (card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_1_8V)) - err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); + err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); /* make sure vccq is 3.3v after switching disaster */ if (err) - err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330); + err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330); if (!err) mmc_set_timing(host, MMC_TIMING_MMC_DDR52); @@ -1260,10 +1260,10 @@ static int mmc_select_hs400es(struct mmc_card *card) } if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400_1_2V) - err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); + err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400_1_8V) - err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); + err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); /* If fails try again during next card power cycle */ if (err) @@ -1362,10 +1362,10 @@ static int mmc_select_hs200(struct mmc_card *card) old_signal_voltage = host->ios.signal_voltage; if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V) - err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); + err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V) - err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); + err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180); /* If fails try again during next card power cycle */ if (err) @@ -1393,7 +1393,7 @@ static int mmc_select_hs200(struct mmc_card *card) err: if (err) { /* fall back to the old signal voltage, if fails report error */ - if (__mmc_set_signal_voltage(host, old_signal_voltage)) + if (mmc_set_signal_voltage(host, old_signal_voltage)) err = -EIO; pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host), From db9fd591980256d95de5675ebd84759b9cc9831c Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 25 Sep 2017 11:29:03 +0300 Subject: [PATCH] UPSTREAM: mmc: core: Factor out mmc_host_set_uhs_voltage() Factor out mmc_host_set_uhs_voltage() so it can be reused. Signed-off-by: Adrian Hunter Signed-off-by: Ulf Hansson (cherry picked from commit 3f496afb6fb361b282f37968ff7d3d80b0f1b5cb) --- drivers/mmc/core/core.c | 38 ++++++++++++++++++++++++-------------- drivers/mmc/core/core.h | 1 + 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index ba285431c2d0..dae82afcbc99 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1590,11 +1590,33 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) } +int mmc_host_set_uhs_voltage(struct mmc_host *host) +{ + u32 clock; + + /* + * During a signal voltage level switch, the clock must be gated + * for 5 ms according to the SD spec + */ + clock = host->ios.clock; + host->ios.clock = 0; + mmc_set_ios(host); + + if (mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) + return -EAGAIN; + + /* Keep clock gated for at least 10 ms, though spec only says 5 ms */ + mmc_delay(10); + host->ios.clock = clock; + mmc_set_ios(host); + + return 0; +} + int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr) { struct mmc_command cmd = {0}; int err = 0; - u32 clock; BUG_ON(!host); @@ -1628,15 +1650,8 @@ int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr) err = -EAGAIN; goto power_cycle; } - /* - * During a signal voltage level switch, the clock must be gated - * for 5 ms according to the SD spec - */ - clock = host->ios.clock; - host->ios.clock = 0; - mmc_set_ios(host); - if (mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) { + if (mmc_host_set_uhs_voltage(host)) { /* * Voltages may not have been switched, but we've already * sent CMD11, so a power cycle is required anyway @@ -1645,11 +1660,6 @@ int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr) goto power_cycle; } - /* Keep clock gated for at least 10 ms, though spec only says 5 ms */ - mmc_delay(10); - host->ios.clock = clock; - mmc_set_ios(host); - /* Wait for at least 1 ms according to spec */ mmc_delay(1); diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 0e4bc1c7a773..11f3d2c22ecb 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -44,6 +44,7 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); void mmc_set_bus_width(struct mmc_host *host, unsigned int width); u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr); +int mmc_host_set_uhs_voltage(struct mmc_host *host); int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); void mmc_set_timing(struct mmc_host *host, unsigned int timing); void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); From 9c2d593200bd835b8e55eb6e0ba188e4dd9c744e Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 25 Sep 2017 11:29:04 +0300 Subject: [PATCH] UPSTREAM: mmc: sd: Fix signal voltage when there is no power cycle Some boards have SD card connectors where the power rail cannot be switched off by the driver. However there are various circumstances when a card might be re-initialized, such as after system resume, warm re-boot, or error handling. However, a UHS card will continue to use 1.8V signaling unless it is power cycled. If the card has not been power cycled, it may still be using 1.8V signaling. According to the SD spec., the Bus Speed Mode (function group 1) bits 2 to 4 are zero if the card is initialized at 3.3V signal level. Thus they can be used to determine if the card has already switched to 1.8V signaling. Detect that situation and try to initialize a UHS-I (1.8V) transfer mode. Tested with the following cards: Transcend 4GB High Speed Kingston 64GB SDR104 Lexar by Micron HIGH-PERFORMANCE 300x 16GB DDR50 SanDisk Ultra 8GB DDR50 Transcend Ultimate 600x 16GB SDR104 Transcend Premium 300x 64GB SDR104 Lexar by Micron Professional 1000x 32GB UHS-II SDR104 SanDisk Extreme Pro 16GB SDR104 Signed-off-by: Adrian Hunter Tested-by: Zhoujie Wu Reviewed-by: Shawn Lin Signed-off-by: Ulf Hansson (cherry picked from commit 6a11fc47f175c8d87018e89cb58e2d36c66534cb) --- drivers/mmc/core/sd.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index d9943d82db95..2808a281d094 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -898,6 +898,18 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card) return max_dtr; } +static bool mmc_sd_card_using_v18(struct mmc_card *card) +{ + /* + * According to the SD spec., the Bus Speed Mode (function group 1) bits + * 2 to 4 are zero if the card is initialized at 3.3V signal level. Thus + * they can be used to determine if the card has already switched to + * 1.8V signaling. + */ + return card->sw_caps.sd3_bus_mode & + (SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | SD_MODE_UHS_DDR50); +} + /* * Handle the detection and initialisation of a card. * @@ -911,10 +923,11 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, int err; u32 cid[4]; u32 rocr = 0; + bool v18_fixup_failed = false; BUG_ON(!host); WARN_ON(!host->claimed); - +retry: err = mmc_sd_get_cid(host, ocr, cid, &rocr); if (err) return err; @@ -980,6 +993,36 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, if (err) goto free_card; + /* + * If the card has not been power cycled, it may still be using 1.8V + * signaling. Detect that situation and try to initialize a UHS-I (1.8V) + * transfer mode. + */ + if (!v18_fixup_failed && !mmc_host_is_spi(host) && mmc_host_uhs(host) && + mmc_sd_card_using_v18(card) && + host->ios.signal_voltage != MMC_SIGNAL_VOLTAGE_180) { + /* + * Re-read switch information in case it has changed since + * oldcard was initialized. + */ + if (oldcard) { + err = mmc_read_switch(card); + if (err) + goto free_card; + } + if (mmc_sd_card_using_v18(card)) { + if (mmc_host_set_uhs_voltage(host) || + mmc_sd_init_uhs_card(card)) { + v18_fixup_failed = true; + mmc_power_cycle(host, ocr); + if (!oldcard) + mmc_remove_card(card); + goto retry; + } + goto done; + } + } + /* Initialization sequence for UHS-I cards */ if (rocr & SD_ROCR_S18A && mmc_host_uhs(host)) { err = mmc_sd_init_uhs_card(card); @@ -1012,7 +1055,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, mmc_set_bus_width(host, MMC_BUS_WIDTH_4); } } - +done: host->card = card; return 0; From 6ee3035196c307a77f95b1c1f3cc537e467fb838 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 5 Apr 2018 21:24:15 +0200 Subject: [PATCH] UPSTREAM: mmc: core: Share internal function to set initial signal voltage Move the corresponding code for setting the initial signal voltage, from mmc_power_up() into a new function, mmc_set_initial_signal_voltage(). Make the function internally available to the mmc core, as to allow the following changes to make use of it. Signed-off-by: Ulf Hansson Tested-by: Quentin Schulz Reviewed-by: Shawn Lin (cherry picked from commit 508c9864ccede5dd4b8a7220b3fe6998763e4407) --- drivers/mmc/core/core.c | 19 ++++++++++++------- drivers/mmc/core/core.h | 1 + 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index dae82afcbc99..7aa83beea957 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1590,6 +1590,17 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) } +void mmc_set_initial_signal_voltage(struct mmc_host *host) +{ + /* Try to set signal voltage to 3.3V but fall back to 1.8v or 1.2v */ + if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330)) + dev_dbg(mmc_dev(host), "Initial signal voltage of 3.3v\n"); + else if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) + dev_dbg(mmc_dev(host), "Initial signal voltage of 1.8v\n"); + else if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120)) + dev_dbg(mmc_dev(host), "Initial signal voltage of 1.2v\n"); +} + int mmc_host_set_uhs_voltage(struct mmc_host *host) { u32 clock; @@ -1754,13 +1765,7 @@ void mmc_power_up(struct mmc_host *host, u32 ocr) /* Set initial state and call mmc_set_ios */ mmc_set_initial_state(host); - /* Try to set signal voltage to 3.3V but fall back to 1.8v or 1.2v */ - if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330)) - dev_dbg(mmc_dev(host), "Initial signal voltage of 3.3v\n"); - else if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180)) - dev_dbg(mmc_dev(host), "Initial signal voltage of 1.8v\n"); - else if (!mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120)) - dev_dbg(mmc_dev(host), "Initial signal voltage of 1.2v\n"); + mmc_set_initial_signal_voltage(host); /* * This delay should be sufficient to allow the power supply diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 11f3d2c22ecb..2634722265ad 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -46,6 +46,7 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr); int mmc_host_set_uhs_voltage(struct mmc_host *host); int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); +void mmc_set_initial_signal_voltage(struct mmc_host *host); void mmc_set_timing(struct mmc_host *host, unsigned int timing); void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); int mmc_select_drive_strength(struct mmc_card *card, unsigned int max_dtr, From adadab9687a3e07be7557e4272fdf5a007b4c604 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 24 Jul 2018 15:50:06 +0200 Subject: [PATCH] mmc: core: set initial signal voltage on power off --- drivers/mmc/core/core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 7aa83beea957..d2c59b5e04ab 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1792,6 +1792,14 @@ void mmc_power_off(struct mmc_host *host) if (host->ios.power_mode == MMC_POWER_OFF) return; + mmc_set_initial_signal_voltage(host); + + /* + * This delay should be sufficient to allow the power supply + * to reach the minimum voltage. + */ + mmc_delay(10); + mmc_pwrseq_power_off(host); host->ios.clock = 0;