aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core/mmc_ops.c
diff options
context:
space:
mode:
authorJaehoon Chung <jh80.chung@samsung.com>2012-09-17 04:42:02 -0400
committerChris Ball <cjb@laptop.org>2012-10-03 10:05:12 -0400
commit950d56acce5d401f477b91d0177605b543d63d07 (patch)
tree205505f3976d02c6ef2fa9d6c911407f0e0f6c80 /drivers/mmc/core/mmc_ops.c
parentbec9d4e5939987053169a9bb48fc58b6a2d3e237 (diff)
mmc: support BKOPS feature for eMMC
Enable eMMC background operations (BKOPS) feature. If URGENT_BKOPS is set after a response, note that BKOPS are required. Immediately run BKOPS if required. Read/write operations should be requested during BKOPS(LEVEL-1), then issue HPI to interrupt the ongoing BKOPS and service the foreground operation. (This patch only controls the LEVEL2/3.) When repeating the writing 1GB data, at a certain time, performance is decreased. At that time, card triggers the Level-3 or Level-2. After running bkops, performance is recovered. Future considerations: * Check BKOPS_LEVEL=1 and start BKOPS in a preventive manner. * Interrupt ongoing BKOPS before powering off the card. * How do we get BKOPS_STATUS value (periodically send ext_csd command)? * If using periodic bkops, also consider runtime_pm control. Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Konstantin Dorfman <kdorfman@codeaurora.org> Reviewed-by: Maya Erez <merez@codeaurora.org> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/core/mmc_ops.c')
-rw-r--r--drivers/mmc/core/mmc_ops.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 225371a28861..a0e172042e65 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -393,18 +393,19 @@ int mmc_spi_set_crc(struct mmc_host *host, int use_crc)
393} 393}
394 394
395/** 395/**
396 * mmc_switch - modify EXT_CSD register 396 * __mmc_switch - modify EXT_CSD register
397 * @card: the MMC card associated with the data transfer 397 * @card: the MMC card associated with the data transfer
398 * @set: cmd set values 398 * @set: cmd set values
399 * @index: EXT_CSD register index 399 * @index: EXT_CSD register index
400 * @value: value to program into EXT_CSD register 400 * @value: value to program into EXT_CSD register
401 * @timeout_ms: timeout (ms) for operation performed by register write, 401 * @timeout_ms: timeout (ms) for operation performed by register write,
402 * timeout of zero implies maximum possible timeout 402 * timeout of zero implies maximum possible timeout
403 * @use_busy_signal: use the busy signal as response type
403 * 404 *
404 * Modifies the EXT_CSD register for selected card. 405 * Modifies the EXT_CSD register for selected card.
405 */ 406 */
406int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, 407int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
407 unsigned int timeout_ms) 408 unsigned int timeout_ms, bool use_busy_signal)
408{ 409{
409 int err; 410 int err;
410 struct mmc_command cmd = {0}; 411 struct mmc_command cmd = {0};
@@ -418,13 +419,23 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
418 (index << 16) | 419 (index << 16) |
419 (value << 8) | 420 (value << 8) |
420 set; 421 set;
421 cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; 422 cmd.flags = MMC_CMD_AC;
423 if (use_busy_signal)
424 cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B;
425 else
426 cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1;
427
428
422 cmd.cmd_timeout_ms = timeout_ms; 429 cmd.cmd_timeout_ms = timeout_ms;
423 430
424 err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); 431 err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
425 if (err) 432 if (err)
426 return err; 433 return err;
427 434
435 /* No need to check card status in case of unblocking command */
436 if (!use_busy_signal)
437 return 0;
438
428 /* Must check status to be sure of no errors */ 439 /* Must check status to be sure of no errors */
429 do { 440 do {
430 err = mmc_send_status(card, &status); 441 err = mmc_send_status(card, &status);
@@ -449,6 +460,13 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
449 460
450 return 0; 461 return 0;
451} 462}
463EXPORT_SYMBOL_GPL(__mmc_switch);
464
465int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
466 unsigned int timeout_ms)
467{
468 return __mmc_switch(card, set, index, value, timeout_ms, true);
469}
452EXPORT_SYMBOL_GPL(mmc_switch); 470EXPORT_SYMBOL_GPL(mmc_switch);
453 471
454int mmc_send_status(struct mmc_card *card, u32 *status) 472int mmc_send_status(struct mmc_card *card, u32 *status)