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

mmc: mmc: Relax checking for switch errors after HS200 switch

The JEDEC specification indicates CMD13 can be used after a HS200 switch
to check for errors. However in practice some boards experience CRC errors
in the CMD13 response. Consequently, for HS200, CRC errors are not a
reliable way to know the switch failed. If there really is a problem, we
would expect tuning will fail and the result ends up the same. So change
the error condition to ignore CRC errors in that case.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>

authored by

Adrian Hunter and committed by
Ulf Hansson
ef3d2322 db52d4f8

+22 -3
+13 -2
drivers/mmc/core/mmc.c
··· 1240 1240 1241 1241 mmc_set_timing(host, MMC_TIMING_MMC_HS200); 1242 1242 1243 - err = mmc_switch_status(card); 1243 + /* 1244 + * For HS200, CRC errors are not a reliable way to know the switch 1245 + * failed. If there really is a problem, we would expect tuning will 1246 + * fail and the result ends up the same. 1247 + */ 1248 + err = __mmc_switch_status(card, false); 1244 1249 if (err) 1245 1250 goto out_err; 1246 1251 ··· 1408 1403 old_timing = host->ios.timing; 1409 1404 mmc_set_timing(host, MMC_TIMING_MMC_HS200); 1410 1405 1411 - err = mmc_switch_status(card); 1406 + /* 1407 + * For HS200, CRC errors are not a reliable way to know the 1408 + * switch failed. If there really is a problem, we would expect 1409 + * tuning will fail and the result ends up the same. 1410 + */ 1411 + err = __mmc_switch_status(card, false); 1412 + 1412 1413 /* 1413 1414 * mmc_select_timing() assumes timing has not changed if 1414 1415 * it is a switch error.
+8 -1
drivers/mmc/core/mmc_ops.c
··· 431 431 } 432 432 433 433 /* Caller must hold re-tuning */ 434 - int mmc_switch_status(struct mmc_card *card) 434 + int __mmc_switch_status(struct mmc_card *card, bool crc_err_fatal) 435 435 { 436 436 u32 status; 437 437 int err; 438 438 439 439 err = mmc_send_status(card, &status); 440 + if (!crc_err_fatal && err == -EILSEQ) 441 + return 0; 440 442 if (err) 441 443 return err; 442 444 443 445 return mmc_switch_status_error(card->host, status); 446 + } 447 + 448 + int mmc_switch_status(struct mmc_card *card) 449 + { 450 + return __mmc_switch_status(card, true); 444 451 } 445 452 446 453 static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
+1
drivers/mmc/core/mmc_ops.h
··· 28 28 int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status); 29 29 int mmc_can_ext_csd(struct mmc_card *card); 30 30 int mmc_switch_status(struct mmc_card *card); 31 + int __mmc_switch_status(struct mmc_card *card, bool crc_err_fatal); 31 32 int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, 32 33 unsigned int timeout_ms, unsigned char timing, 33 34 bool use_busy_signal, bool send_status, bool retry_crc_err);