aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2014-01-28 08:15:34 -0500
committerChris Ball <chris@printf.net>2014-02-23 10:40:38 -0500
commitb9ec26160f998493509b782be999ff59e4372971 (patch)
tree06c0af48fe14643e4252a50d153eef81461c5a25 /drivers/mmc/core
parent636bd13c12d2331ad835b89681428eccb4cf102e (diff)
mmc: core: Fixup busy detection for mmc switch operations
If the host controller supports busy detection in HW, we expect the MMC_CAP_WAIT_WHILE_BUSY to be set. Likewise the corresponding host->max_busy_timeout should reflect the maximum busy detection timeout supported by the host. Previously we expected a host that supported MMC_CAP_WAIT_WHILE_BUSY to cope with any timeout, which just isn't feasible due to HW limitations. For most switch operations, R1B responses are expected and thus we need to check for busy detection completion. To cope with cases where the requested busy detection timeout is greater than what the host are able to support, we fallback to use a R1 response instead. This will prevent the host from doing HW busy detection. In those cases, busy detection completion is handled by polling the for the card's status using CMD13. This is the same mechanism used when the host doesn't support MMC_CAP_WAIT_WHILE_BUSY. Do note, a host->max_busy_timeout set to zero, is interpreted by the mmc core as it don't know what the host supports. It will then provide the host with whatever timeout the mmc core finds suitable. For some cases the mmc core has unfurtunate no clue of what timeout to use. In these cases we provide the host with a timeout value of zero, which the host may interpret as use whatever timeout it finds suitable. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Chris Ball <chris@printf.net>
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r--drivers/mmc/core/mmc_ops.c33
1 files changed, 26 insertions, 7 deletions
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 04ecdb913aa0..f51b5ba3bbea 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -418,6 +418,17 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
418 struct mmc_command cmd = {0}; 418 struct mmc_command cmd = {0};
419 unsigned long timeout; 419 unsigned long timeout;
420 u32 status = 0; 420 u32 status = 0;
421 bool use_r1b_resp = use_busy_signal;
422
423 /*
424 * If the cmd timeout and the max_busy_timeout of the host are both
425 * specified, let's validate them. A failure means we need to prevent
426 * the host from doing hw busy detection, which is done by converting
427 * to a R1 response instead of a R1B.
428 */
429 if (timeout_ms && host->max_busy_timeout &&
430 (timeout_ms > host->max_busy_timeout))
431 use_r1b_resp = false;
421 432
422 cmd.opcode = MMC_SWITCH; 433 cmd.opcode = MMC_SWITCH;
423 cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | 434 cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
@@ -425,13 +436,17 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
425 (value << 8) | 436 (value << 8) |
426 set; 437 set;
427 cmd.flags = MMC_CMD_AC; 438 cmd.flags = MMC_CMD_AC;
428 if (use_busy_signal) 439 if (use_r1b_resp) {
429 cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B; 440 cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B;
430 else 441 /*
442 * A busy_timeout of zero means the host can decide to use
443 * whatever value it finds suitable.
444 */
445 cmd.busy_timeout = timeout_ms;
446 } else {
431 cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1; 447 cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1;
448 }
432 449
433
434 cmd.busy_timeout = timeout_ms;
435 if (index == EXT_CSD_SANITIZE_START) 450 if (index == EXT_CSD_SANITIZE_START)
436 cmd.sanitize_busy = true; 451 cmd.sanitize_busy = true;
437 452
@@ -447,18 +462,22 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
447 * CRC errors shall only be ignored in cases were CMD13 is used to poll 462 * CRC errors shall only be ignored in cases were CMD13 is used to poll
448 * to detect busy completion. 463 * to detect busy completion.
449 */ 464 */
450 if (host->caps & MMC_CAP_WAIT_WHILE_BUSY) 465 if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
451 ignore_crc = false; 466 ignore_crc = false;
452 467
468 /* We have an unspecified cmd timeout, use the fallback value. */
469 if (!timeout_ms)
470 timeout_ms = MMC_OPS_TIMEOUT_MS;
471
453 /* Must check status to be sure of no errors. */ 472 /* Must check status to be sure of no errors. */
454 timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS); 473 timeout = jiffies + msecs_to_jiffies(timeout_ms);
455 do { 474 do {
456 if (send_status) { 475 if (send_status) {
457 err = __mmc_send_status(card, &status, ignore_crc); 476 err = __mmc_send_status(card, &status, ignore_crc);
458 if (err) 477 if (err)
459 return err; 478 return err;
460 } 479 }
461 if (host->caps & MMC_CAP_WAIT_WHILE_BUSY) 480 if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
462 break; 481 break;
463 if (mmc_host_is_spi(host)) 482 if (mmc_host_is_spi(host))
464 break; 483 break;