diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2016-12-02 06:16:35 -0500 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2016-12-05 08:15:46 -0500 |
commit | ef3d232245ab7a1bf361c52449e612e4c8b7c5ab (patch) | |
tree | 0e6d579644349f6efa511681faadaba24b9e9b58 | |
parent | db52d4f8a4bde36263a7cc9d46ff20b243562ac9 (diff) |
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>
-rw-r--r-- | drivers/mmc/core/mmc.c | 15 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.c | 9 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.h | 1 |
3 files changed, 22 insertions, 3 deletions
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 033e00abe93f..b61b52f9da3d 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -1240,7 +1240,12 @@ int mmc_hs400_to_hs200(struct mmc_card *card) | |||
1240 | 1240 | ||
1241 | mmc_set_timing(host, MMC_TIMING_MMC_HS200); | 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 | if (err) | 1249 | if (err) |
1245 | goto out_err; | 1250 | goto out_err; |
1246 | 1251 | ||
@@ -1403,7 +1408,13 @@ static int mmc_select_hs200(struct mmc_card *card) | |||
1403 | old_timing = host->ios.timing; | 1408 | old_timing = host->ios.timing; |
1404 | mmc_set_timing(host, MMC_TIMING_MMC_HS200); | 1409 | mmc_set_timing(host, MMC_TIMING_MMC_HS200); |
1405 | 1410 | ||
1406 | err = mmc_switch_status(card); | 1411 | /* |
1412 | * For HS200, CRC errors are not a reliable way to know the | ||
1413 | * switch failed. If there really is a problem, we would expect | ||
1414 | * tuning will fail and the result ends up the same. | ||
1415 | */ | ||
1416 | err = __mmc_switch_status(card, false); | ||
1417 | |||
1407 | /* | 1418 | /* |
1408 | * mmc_select_timing() assumes timing has not changed if | 1419 | * mmc_select_timing() assumes timing has not changed if |
1409 | * it is a switch error. | 1420 | * it is a switch error. |
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index cb7006feb5c4..81ce63bb0773 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c | |||
@@ -431,18 +431,25 @@ static int mmc_switch_status_error(struct mmc_host *host, u32 status) | |||
431 | } | 431 | } |
432 | 432 | ||
433 | /* Caller must hold re-tuning */ | 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 | u32 status; | 436 | u32 status; |
437 | int err; | 437 | int err; |
438 | 438 | ||
439 | err = mmc_send_status(card, &status); | 439 | err = mmc_send_status(card, &status); |
440 | if (!crc_err_fatal && err == -EILSEQ) | ||
441 | return 0; | ||
440 | if (err) | 442 | if (err) |
441 | return err; | 443 | return err; |
442 | 444 | ||
443 | return mmc_switch_status_error(card->host, status); | 445 | return mmc_switch_status_error(card->host, status); |
444 | } | 446 | } |
445 | 447 | ||
448 | int mmc_switch_status(struct mmc_card *card) | ||
449 | { | ||
450 | return __mmc_switch_status(card, true); | ||
451 | } | ||
452 | |||
446 | static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, | 453 | static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, |
447 | bool send_status, bool retry_crc_err) | 454 | bool send_status, bool retry_crc_err) |
448 | { | 455 | { |
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index 761cb69c46af..abd525ed74be 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h | |||
@@ -28,6 +28,7 @@ int mmc_bus_test(struct mmc_card *card, u8 bus_width); | |||
28 | int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status); | 28 | int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status); |
29 | int mmc_can_ext_csd(struct mmc_card *card); | 29 | int mmc_can_ext_csd(struct mmc_card *card); |
30 | int mmc_switch_status(struct mmc_card *card); | 30 | int mmc_switch_status(struct mmc_card *card); |
31 | int __mmc_switch_status(struct mmc_card *card, bool crc_err_fatal); | ||
31 | int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, | 32 | int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, |
32 | unsigned int timeout_ms, unsigned char timing, | 33 | unsigned int timeout_ms, unsigned char timing, |
33 | bool use_busy_signal, bool send_status, bool retry_crc_err); | 34 | bool use_busy_signal, bool send_status, bool retry_crc_err); |