634 lines
23 KiB
Diff
634 lines
23 KiB
Diff
From 38396ba52ab85ea1eabea3c92fd7532f8732f92e Mon Sep 17 00:00:00 2001
|
|
From: Jonas Karlman <jonas@kwiboo.se>
|
|
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 <haibo.chen@nxp.com>
|
|
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: <stable@vger.kernel.org>
|
|
Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
|
|
Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
|
|
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
|
|
(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 <ulf.hansson@linaro.org>
|
|
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 <ulf.hansson@linaro.org>
|
|
Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
|
|
Tested-by: Jan Glauber <jglauber@cavium.com>
|
|
Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
|
|
(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 <ulf.hansson@linaro.org>
|
|
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 <ulf.hansson@linaro.org>
|
|
Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
|
|
Tested-by: Jan Glauber <jglauber@cavium.com>
|
|
Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
|
|
(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 <ulf.hansson@linaro.org>
|
|
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 <ulf.hansson@linaro.org>
|
|
Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
|
|
Tested-by: Jan Glauber <jglauber@cavium.com>
|
|
Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
|
|
(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 <adrian.hunter@intel.com>
|
|
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 <adrian.hunter@intel.com>
|
|
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
|
|
(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 <adrian.hunter@intel.com>
|
|
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 <adrian.hunter@intel.com>
|
|
Tested-by: Zhoujie Wu <zjwu@marvell.com>
|
|
Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
|
|
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
|
|
(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 <ulf.hansson@linaro.org>
|
|
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 <ulf.hansson@linaro.org>
|
|
Tested-by: Quentin Schulz <quentin.schulz@bootlin.com>
|
|
Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
|
|
(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 <jonas@kwiboo.se>
|
|
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;
|