Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mmc: core: Allow CMD13 polling when switching to HS mode for mmc

In cases when the mmc host doesn't support HW busy detection, polling for a
card being busy by using CMD13 is beneficial. That is because, instead of
waiting a fixed amount of time, 500ms or the generic CMD6 time from
EXT_CSD, we find out a lot sooner when the card stops signaling busy. This
leads to a significant decreased total initialization time for the mmc
card.

However, to allow polling with CMD13 during a bus timing change operation,
such as switching to HS mode, we first need to update the mmc host's bus
timing before starting to poll. Deal with that, simply by providing
MMC_TIMING_MMC_HS as the timing parameter to __mmc_switch() from
mmc_select_hs().

By telling __mmc_switch() to allow polling with CMD13, also makes it
validate the CMD6 status, thus we can remove the corresponding checks.

When switching to HS400ES, the mmc_select_hs() function is called in one of
the intermediate steps. To still prevent CMD13 polling for HS400ES, let's
call the __mmc_switch() function in this path as it enables us to keep
using the existing method.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Tested-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>

+14 -12
+14 -12
drivers/mmc/core/mmc.c
··· 1012 1012 1013 1013 err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 1014 1014 EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS, 1015 - card->ext_csd.generic_cmd6_time, 0, 1016 - true, false, true); 1017 - if (!err) { 1018 - mmc_set_timing(card->host, MMC_TIMING_MMC_HS); 1019 - err = mmc_switch_status(card); 1020 - } 1021 - 1015 + card->ext_csd.generic_cmd6_time, MMC_TIMING_MMC_HS, 1016 + true, true, true); 1022 1017 if (err) 1023 1018 pr_warn("%s: switch to high-speed failed, err:%d\n", 1024 1019 mmc_hostname(card->host), err); ··· 1263 1268 goto out_err; 1264 1269 1265 1270 /* Switch card to HS mode */ 1266 - err = mmc_select_hs(card); 1271 + err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 1272 + EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS, 1273 + card->ext_csd.generic_cmd6_time, 0, 1274 + true, false, true); 1275 + if (err) { 1276 + pr_err("%s: switch to hs for hs400es failed, err:%d\n", 1277 + mmc_hostname(host), err); 1278 + goto out_err; 1279 + } 1280 + 1281 + mmc_set_timing(host, MMC_TIMING_MMC_HS); 1282 + err = mmc_switch_status(card); 1267 1283 if (err) 1268 1284 goto out_err; 1269 1285 1270 1286 mmc_set_clock(host, card->ext_csd.hs_max_dtr); 1271 - 1272 - err = mmc_switch_status(card); 1273 - if (err) 1274 - goto out_err; 1275 1287 1276 1288 /* Switch card to DDR with strobe bit */ 1277 1289 val = EXT_CSD_DDR_BUS_WIDTH_8 | EXT_CSD_BUS_WIDTH_STROBE;