diff options
author | Jaehoon Chung <jh80.chung@samsung.com> | 2012-09-17 12:42:02 +0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2012-10-03 18:05:12 +0400 |
commit | 950d56acce5d401f477b91d0177605b543d63d07 (patch) | |
tree | 205505f3976d02c6ef2fa9d6c911407f0e0f6c80 /drivers/mmc/core/mmc_ops.c | |
parent | bec9d4e5939987053169a9bb48fc58b6a2d3e237 (diff) | |
download | linux-950d56acce5d401f477b91d0177605b543d63d07.tar.xz |
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.c | 26 |
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) } /** - * mmc_switch - modify EXT_CSD register + * __mmc_switch - modify EXT_CSD register * @card: the MMC card associated with the data transfer * @set: cmd set values * @index: EXT_CSD register index * @value: value to program into EXT_CSD register * @timeout_ms: timeout (ms) for operation performed by register write, * timeout of zero implies maximum possible timeout + * @use_busy_signal: use the busy signal as response type * * Modifies the EXT_CSD register for selected card. */ -int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, - unsigned int timeout_ms) +int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, + unsigned int timeout_ms, bool use_busy_signal) { int err; struct mmc_command cmd = {0}; @@ -418,13 +419,23 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, (index << 16) | (value << 8) | set; - cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; + cmd.flags = MMC_CMD_AC; + if (use_busy_signal) + cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B; + else + cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1; + + cmd.cmd_timeout_ms = timeout_ms; err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); if (err) return err; + /* No need to check card status in case of unblocking command */ + if (!use_busy_signal) + return 0; + /* Must check status to be sure of no errors */ do { err = mmc_send_status(card, &status); @@ -449,6 +460,13 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, return 0; } +EXPORT_SYMBOL_GPL(__mmc_switch); + +int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, + unsigned int timeout_ms) +{ + return __mmc_switch(card, set, index, value, timeout_ms, true); +} EXPORT_SYMBOL_GPL(mmc_switch); int mmc_send_status(struct mmc_card *card, u32 *status) |