|
@@ -965,6 +965,19 @@ static int mmc_select_bus_width(struct mmc_card *card)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+/* Caller must hold re-tuning */
|
|
|
+static int mmc_switch_status(struct mmc_card *card)
|
|
|
+{
|
|
|
+ u32 status;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ err = mmc_send_status(card, &status);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ return mmc_switch_status_error(card->host, status);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Switch to the high-speed mode
|
|
|
*/
|
|
@@ -975,9 +988,11 @@ static int mmc_select_hs(struct mmc_card *card)
|
|
|
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
|
EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
|
|
|
card->ext_csd.generic_cmd6_time,
|
|
|
- true, true, true);
|
|
|
- if (!err)
|
|
|
+ true, false, true);
|
|
|
+ if (!err) {
|
|
|
mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
|
|
|
+ err = mmc_switch_status(card);
|
|
|
+ }
|
|
|
|
|
|
return err;
|
|
|
}
|
|
@@ -1053,23 +1068,9 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-/* Caller must hold re-tuning */
|
|
|
-static int mmc_switch_status(struct mmc_card *card)
|
|
|
-{
|
|
|
- u32 status;
|
|
|
- int err;
|
|
|
-
|
|
|
- err = mmc_send_status(card, &status);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- return mmc_switch_status_error(card->host, status);
|
|
|
-}
|
|
|
-
|
|
|
static int mmc_select_hs400(struct mmc_card *card)
|
|
|
{
|
|
|
struct mmc_host *host = card->host;
|
|
|
- bool send_status = true;
|
|
|
unsigned int max_dtr;
|
|
|
int err = 0;
|
|
|
u8 val;
|
|
@@ -1081,9 +1082,6 @@ static int mmc_select_hs400(struct mmc_card *card)
|
|
|
host->ios.bus_width == MMC_BUS_WIDTH_8))
|
|
|
return 0;
|
|
|
|
|
|
- if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
|
|
|
- send_status = false;
|
|
|
-
|
|
|
/* Reduce frequency to HS frequency */
|
|
|
max_dtr = card->ext_csd.hs_max_dtr;
|
|
|
mmc_set_clock(host, max_dtr);
|
|
@@ -1093,7 +1091,7 @@ static int mmc_select_hs400(struct mmc_card *card)
|
|
|
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
|
EXT_CSD_HS_TIMING, val,
|
|
|
card->ext_csd.generic_cmd6_time,
|
|
|
- true, send_status, true);
|
|
|
+ true, false, true);
|
|
|
if (err) {
|
|
|
pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
|
|
|
mmc_hostname(host), err);
|
|
@@ -1103,11 +1101,9 @@ static int mmc_select_hs400(struct mmc_card *card)
|
|
|
/* Set host controller to HS timing */
|
|
|
mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
|
|
|
|
|
|
- if (!send_status) {
|
|
|
- err = mmc_switch_status(card);
|
|
|
- if (err)
|
|
|
- goto out_err;
|
|
|
- }
|
|
|
+ err = mmc_switch_status(card);
|
|
|
+ if (err)
|
|
|
+ goto out_err;
|
|
|
|
|
|
/* Switch card to DDR */
|
|
|
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
@@ -1126,7 +1122,7 @@ static int mmc_select_hs400(struct mmc_card *card)
|
|
|
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
|
EXT_CSD_HS_TIMING, val,
|
|
|
card->ext_csd.generic_cmd6_time,
|
|
|
- true, send_status, true);
|
|
|
+ true, false, true);
|
|
|
if (err) {
|
|
|
pr_err("%s: switch to hs400 failed, err:%d\n",
|
|
|
mmc_hostname(host), err);
|
|
@@ -1137,11 +1133,9 @@ static int mmc_select_hs400(struct mmc_card *card)
|
|
|
mmc_set_timing(host, MMC_TIMING_MMC_HS400);
|
|
|
mmc_set_bus_speed(card);
|
|
|
|
|
|
- if (!send_status) {
|
|
|
- err = mmc_switch_status(card);
|
|
|
- if (err)
|
|
|
- goto out_err;
|
|
|
- }
|
|
|
+ err = mmc_switch_status(card);
|
|
|
+ if (err)
|
|
|
+ goto out_err;
|
|
|
|
|
|
return 0;
|
|
|
|
|
@@ -1159,14 +1153,10 @@ int mmc_hs200_to_hs400(struct mmc_card *card)
|
|
|
int mmc_hs400_to_hs200(struct mmc_card *card)
|
|
|
{
|
|
|
struct mmc_host *host = card->host;
|
|
|
- bool send_status = true;
|
|
|
unsigned int max_dtr;
|
|
|
int err;
|
|
|
u8 val;
|
|
|
|
|
|
- if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
|
|
|
- send_status = false;
|
|
|
-
|
|
|
/* Reduce frequency to HS */
|
|
|
max_dtr = card->ext_csd.hs_max_dtr;
|
|
|
mmc_set_clock(host, max_dtr);
|
|
@@ -1175,49 +1165,43 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
|
|
|
val = EXT_CSD_TIMING_HS;
|
|
|
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
|
|
|
val, card->ext_csd.generic_cmd6_time,
|
|
|
- true, send_status, true);
|
|
|
+ true, false, true);
|
|
|
if (err)
|
|
|
goto out_err;
|
|
|
|
|
|
mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
|
|
|
|
|
|
- if (!send_status) {
|
|
|
- err = mmc_switch_status(card);
|
|
|
- if (err)
|
|
|
- goto out_err;
|
|
|
- }
|
|
|
+ err = mmc_switch_status(card);
|
|
|
+ if (err)
|
|
|
+ goto out_err;
|
|
|
|
|
|
/* Switch HS DDR to HS */
|
|
|
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
|
|
|
EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time,
|
|
|
- true, send_status, true);
|
|
|
+ true, false, true);
|
|
|
if (err)
|
|
|
goto out_err;
|
|
|
|
|
|
mmc_set_timing(host, MMC_TIMING_MMC_HS);
|
|
|
|
|
|
- if (!send_status) {
|
|
|
- err = mmc_switch_status(card);
|
|
|
- if (err)
|
|
|
- goto out_err;
|
|
|
- }
|
|
|
+ err = mmc_switch_status(card);
|
|
|
+ if (err)
|
|
|
+ goto out_err;
|
|
|
|
|
|
/* Switch HS to HS200 */
|
|
|
val = EXT_CSD_TIMING_HS200 |
|
|
|
card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
|
|
|
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
|
|
|
- val, card->ext_csd.generic_cmd6_time, true,
|
|
|
- send_status, true);
|
|
|
+ val, card->ext_csd.generic_cmd6_time,
|
|
|
+ true, false, true);
|
|
|
if (err)
|
|
|
goto out_err;
|
|
|
|
|
|
mmc_set_timing(host, MMC_TIMING_MMC_HS200);
|
|
|
|
|
|
- if (!send_status) {
|
|
|
- err = mmc_switch_status(card);
|
|
|
- if (err)
|
|
|
- goto out_err;
|
|
|
- }
|
|
|
+ err = mmc_switch_status(card);
|
|
|
+ if (err)
|
|
|
+ goto out_err;
|
|
|
|
|
|
mmc_set_bus_speed(card);
|
|
|
|
|
@@ -1328,7 +1312,6 @@ static void mmc_select_driver_type(struct mmc_card *card)
|
|
|
static int mmc_select_hs200(struct mmc_card *card)
|
|
|
{
|
|
|
struct mmc_host *host = card->host;
|
|
|
- bool send_status = true;
|
|
|
unsigned int old_timing, old_signal_voltage;
|
|
|
int err = -EINVAL;
|
|
|
u8 val;
|
|
@@ -1346,9 +1329,6 @@ static int mmc_select_hs200(struct mmc_card *card)
|
|
|
|
|
|
mmc_select_driver_type(card);
|
|
|
|
|
|
- if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
|
|
|
- send_status = false;
|
|
|
-
|
|
|
/*
|
|
|
* Set the bus width(4 or 8) with host's support and
|
|
|
* switch to HS200 mode if bus width is set successfully.
|
|
@@ -1360,20 +1340,19 @@ static int mmc_select_hs200(struct mmc_card *card)
|
|
|
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
|
EXT_CSD_HS_TIMING, val,
|
|
|
card->ext_csd.generic_cmd6_time,
|
|
|
- true, send_status, true);
|
|
|
+ true, false, true);
|
|
|
if (err)
|
|
|
goto err;
|
|
|
old_timing = host->ios.timing;
|
|
|
mmc_set_timing(host, MMC_TIMING_MMC_HS200);
|
|
|
- if (!send_status) {
|
|
|
- err = mmc_switch_status(card);
|
|
|
- /*
|
|
|
- * mmc_select_timing() assumes timing has not changed if
|
|
|
- * it is a switch error.
|
|
|
- */
|
|
|
- if (err == -EBADMSG)
|
|
|
- mmc_set_timing(host, old_timing);
|
|
|
- }
|
|
|
+
|
|
|
+ err = mmc_switch_status(card);
|
|
|
+ /*
|
|
|
+ * mmc_select_timing() assumes timing has not changed if
|
|
|
+ * it is a switch error.
|
|
|
+ */
|
|
|
+ if (err == -EBADMSG)
|
|
|
+ mmc_set_timing(host, old_timing);
|
|
|
}
|
|
|
err:
|
|
|
if (err) {
|