|
|
@@ -1056,6 +1056,7 @@ static int mmc_switch_status(struct mmc_card *card)
|
|
|
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;
|
|
|
@@ -1067,6 +1068,9 @@ 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);
|
|
|
@@ -1077,7 +1081,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, true, true);
|
|
|
+ true, send_status, true);
|
|
|
if (err) {
|
|
|
pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
|
|
|
mmc_hostname(host), err);
|
|
|
@@ -1087,6 +1091,13 @@ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Switch card to DDR */
|
|
|
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
|
|
EXT_CSD_BUS_WIDTH,
|
|
|
EXT_CSD_DDR_BUS_WIDTH_8,
|
|
|
@@ -1097,22 +1108,35 @@ static int mmc_select_hs400(struct mmc_card *card)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+ /* Switch card to HS400 */
|
|
|
val = EXT_CSD_TIMING_HS400 |
|
|
|
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, true, true);
|
|
|
+ true, send_status, true);
|
|
|
if (err) {
|
|
|
pr_err("%s: switch to hs400 failed, err:%d\n",
|
|
|
mmc_hostname(host), err);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+ /* Set host controller to HS400 timing and frequency */
|
|
|
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;
|
|
|
+ }
|
|
|
+
|
|
|
return 0;
|
|
|
+
|
|
|
+out_err:
|
|
|
+ pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host),
|
|
|
+ __func__, err);
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
int mmc_hs200_to_hs400(struct mmc_card *card)
|