summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDov Levenglick <dovl@codeaurora.org>2015-06-24 19:51:58 +0300
committerSubhash Jadavani <subhashj@codeaurora.org>2016-05-31 15:26:49 -0700
commitfda56078bbf3b05a9bb1c2ffe3d3616dd15714d5 (patch)
tree1baf3fcd0d9f512dc5dc6b7b889cc3cabd935c2b
parent37927a22fe1c03a9ec3f410af4ffae1707330918 (diff)
mmc: add support for bkops
Add support for manual and auto bkops for legacy (not command-queue) mode. Change-Id: I1333e1d4330393e446ba48a9474c83295744c050 Signed-off-by: Dov Levenglick <dovl@codeaurora.org> [subhashj@codeaurora.org: fixed merge conflicts and compilation errors] Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
-rw-r--r--drivers/mmc/card/block.c20
-rw-r--r--drivers/mmc/core/bus.c12
-rw-r--r--drivers/mmc/core/core.c156
-rw-r--r--drivers/mmc/core/core.h16
-rw-r--r--drivers/mmc/core/mmc.c54
-rw-r--r--include/linux/mmc/card.h29
-rw-r--r--include/linux/mmc/core.h21
-rw-r--r--include/linux/mmc/host.h2
-rw-r--r--include/linux/mmc/mmc.h3
9 files changed, 247 insertions, 66 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 5d95402c5fb2..006d112f11db 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -43,6 +43,7 @@
#include <linux/mmc/ioctl.h>
#include <linux/mmc/card.h>
+#include <linux/mmc/core.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/sd.h>
@@ -3405,10 +3406,17 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
unsigned long flags;
unsigned int cmd_flags = req ? req->cmd_flags : 0;
- if (req && !mq->mqrq_prev->req)
+ if (req && !mq->mqrq_prev->req) {
/* claim host only for the first request */
mmc_get_card(card);
+ if (mmc_card_doing_bkops(host->card)) {
+ ret = mmc_stop_bkops(host->card);
+ if (ret)
+ goto out;
+ }
+ }
+
ret = mmc_blk_part_switch(card, md);
if (ret) {
if (req) {
@@ -3951,8 +3959,16 @@ static int mmc_blk_probe(struct mmc_card *card)
goto out;
}
- pm_runtime_set_autosuspend_delay(&card->dev, 3000);
pm_runtime_use_autosuspend(&card->dev);
+ pm_runtime_set_autosuspend_delay(&card->dev, MMC_AUTOSUSPEND_DELAY_MS);
+ /*
+ * If there is a runtime_idle function, it should take care of
+ * suspending the card
+ */
+ if (card->host->bus_ops->runtime_idle)
+ pm_runtime_dont_use_autosuspend(&card->dev);
+ else
+ pm_runtime_use_autosuspend(&card->dev);
/*
* Don't enable runtime PM for SD-combo cards here. Leave that
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index af884a552d5e..be7773f40a90 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -200,10 +200,20 @@ static int mmc_runtime_resume(struct device *dev)
return host->bus_ops->runtime_resume(host);
}
+
+static int mmc_runtime_idle(struct device *dev)
+{
+ struct mmc_card *card = mmc_dev_to_card(dev);
+ struct mmc_host *host = card->host;
+
+ return host->bus_ops->runtime_idle(host);
+}
+
#endif /* !CONFIG_PM */
static const struct dev_pm_ops mmc_bus_pm_ops = {
- SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume, NULL)
+ SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume,
+ mmc_runtime_idle)
SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume)
};
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index ed4e383c0482..8db21b61a2ae 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -913,24 +913,70 @@ static void mmc_start_cmdq_request(struct mmc_host *host,
}
/**
- * mmc_start_bkops - start BKOPS for supported cards
+ * mmc_set_auto_bkops - set auto BKOPS for supported cards
* @card: MMC card to start BKOPS
- * @form_exception: A flag to indicate if this function was
- * called due to an exception raised by the card
+ * @enable: enable/disable flag
+ * Configure the card to run automatic BKOPS.
*
- * Start background operations whenever requested.
- * When the urgent BKOPS bit is set in a R1 command response
- * then background operations should be started immediately.
+ * Should be called when host is claimed.
*/
-void mmc_start_bkops(struct mmc_card *card, bool from_exception)
+int mmc_set_auto_bkops(struct mmc_card *card, bool enable)
+{
+ int ret = 0;
+ u8 bkops_en;
+
+ BUG_ON(!card);
+ enable = !!enable;
+
+ if (unlikely(!mmc_card_support_auto_bkops(card))) {
+ pr_err("%s: %s: card doesn't support auto bkops\n",
+ mmc_hostname(card->host), __func__);
+ return -EPERM;
+ }
+
+ if (enable) {
+ if (mmc_card_doing_auto_bkops(card))
+ goto out;
+ bkops_en = card->ext_csd.man_bkops_en | EXT_CSD_BKOPS_AUTO_EN;
+ } else {
+ if (!mmc_card_doing_auto_bkops(card))
+ goto out;
+ bkops_en = card->ext_csd.man_bkops_en & ~EXT_CSD_BKOPS_AUTO_EN;
+ }
+
+ ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BKOPS_EN,
+ bkops_en, 0);
+ if (ret) {
+ pr_err("%s: %s: error in setting auto bkops to %d (%d)\n",
+ mmc_hostname(card->host), __func__, enable, ret);
+ } else {
+ if (enable)
+ mmc_card_set_auto_bkops(card);
+ else
+ mmc_card_clr_auto_bkops(card);
+ card->ext_csd.man_bkops_en = bkops_en;
+ }
+out:
+ return ret;
+}
+EXPORT_SYMBOL(mmc_set_auto_bkops);
+
+/**
+ * mmc_check_bkops - check BKOPS for supported cards
+ * @card: MMC card to check BKOPS
+ *
+ * Read the BKOPS status in order to determine whether the
+ * card requires bkops to be started.
+*/
+void mmc_check_bkops(struct mmc_card *card)
{
int err;
- int timeout;
- bool use_busy_signal;
BUG_ON(!card);
- if (!card->ext_csd.man_bkops_en || mmc_card_doing_bkops(card))
+ if (unlikely(!mmc_card_configured_manual_bkops(card)))
+ return;
+ if (mmc_card_doing_bkops(card) || mmc_card_doing_auto_bkops(card))
return;
err = mmc_read_bkops_status(card);
@@ -940,47 +986,48 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception)
return;
}
- if (!card->ext_csd.raw_bkops_status)
+ if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2)
+ return;
+
+ card->bkops.needs_manual = true;
+}
+EXPORT_SYMBOL(mmc_check_bkops);
+
+/**
+ * mmc_start_manual_bkops - start BKOPS for supported cards
+ * @card: MMC card to start BKOPS
+ *
+ * Send START_BKOPS to the card.
+*/
+void mmc_start_manual_bkops(struct mmc_card *card)
+{
+ int err;
+
+ BUG_ON(!card);
+
+ if (unlikely(!mmc_card_configured_manual_bkops(card)))
return;
- if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2 &&
- from_exception)
+ if (mmc_card_doing_bkops(card))
return;
mmc_claim_host(card->host);
- if (card->ext_csd.raw_bkops_status >= EXT_CSD_BKOPS_LEVEL_2) {
- timeout = MMC_BKOPS_MAX_TIMEOUT;
- use_busy_signal = true;
- } else {
- timeout = 0;
- use_busy_signal = false;
- }
-
mmc_retune_hold(card->host);
- err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_BKOPS_START, 1, timeout,
- use_busy_signal, true, false);
+ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BKOPS_START,
+ 1, 0, false, true, false);
if (err) {
- pr_warn("%s: Error %d starting bkops\n",
- mmc_hostname(card->host), err);
- mmc_retune_release(card->host);
- goto out;
+ pr_err("%s: Error %d starting manual bkops\n",
+ mmc_hostname(card->host), err);
+ } else {
+ mmc_card_set_doing_bkops(card);
+ card->bkops.needs_manual = false;
}
- /*
- * For urgent bkops status (LEVEL_2 and more)
- * bkops executed synchronously, otherwise
- * the operation is in progress
- */
- if (!use_busy_signal)
- mmc_card_set_doing_bkops(card);
- else
- mmc_retune_release(card->host);
-out:
+ mmc_retune_release(card->host);
mmc_release_host(card->host);
}
-EXPORT_SYMBOL(mmc_start_bkops);
+EXPORT_SYMBOL(mmc_start_manual_bkops);
/*
* mmc_wait_data_done() - done callback for data request
@@ -1347,7 +1394,7 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
if (areq)
mmc_post_req(host, areq->mrq, -EINVAL);
- mmc_start_bkops(host->card, true);
+ mmc_check_bkops(host->card);
/* prepare the request again */
if (areq)
@@ -1509,6 +1556,11 @@ int mmc_stop_bkops(struct mmc_card *card)
int err = 0;
BUG_ON(!card);
+ if (unlikely(!mmc_card_configured_manual_bkops(card)))
+ goto out;
+ if (!mmc_card_doing_bkops(card))
+ goto out;
+
err = mmc_interrupt_hpi(card);
/*
@@ -1520,7 +1572,7 @@ int mmc_stop_bkops(struct mmc_card *card)
mmc_retune_release(card->host);
err = 0;
}
-
+out:
return err;
}
EXPORT_SYMBOL(mmc_stop_bkops);
@@ -1777,6 +1829,19 @@ void mmc_get_card(struct mmc_card *card)
EXPORT_SYMBOL(mmc_get_card);
/*
+ * This is a helper function, which drops the runtime
+ * pm reference for the card device.
+ */
+static void __mmc_put_card(struct mmc_card *card)
+{
+ /* In case of runtime_idle, it will handle the suspend */
+ if (card->host->bus_ops->runtime_idle)
+ pm_runtime_put(&card->dev);
+ else
+ pm_runtime_put_autosuspend(&card->dev);
+}
+
+/*
* This is a helper function, which releases the host and drops the runtime
* pm reference for the card device.
*/
@@ -1784,7 +1849,7 @@ void mmc_put_card(struct mmc_card *card)
{
mmc_release_host(card->host);
pm_runtime_mark_last_busy(&card->dev);
- pm_runtime_put_autosuspend(&card->dev);
+ __mmc_put_card(card);
}
EXPORT_SYMBOL(mmc_put_card);
@@ -1796,6 +1861,13 @@ void mmc_set_ios(struct mmc_host *host)
{
struct mmc_ios *ios = &host->ios;
+ if (unlikely(ios->power_mode == MMC_POWER_OFF &&
+ host->card && mmc_card_doing_auto_bkops(host->card))) {
+ pr_err("%s: %s: illegal to disable power to card when running auto bkops\n",
+ mmc_hostname(host), __func__);
+ return;
+ }
+
pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u "
"width %u timing %u\n",
mmc_hostname(host), ios->clock, ios->bus_mode,
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index c4ab8ce9fd90..af0b13a492a5 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -15,22 +15,6 @@
#define MMC_CMD_RETRIES 3
-struct mmc_bus_ops {
- void (*remove)(struct mmc_host *);
- void (*detect)(struct mmc_host *);
- int (*pre_suspend)(struct mmc_host *);
- int (*suspend)(struct mmc_host *);
- int (*resume)(struct mmc_host *);
- int (*runtime_suspend)(struct mmc_host *);
- int (*runtime_resume)(struct mmc_host *);
- int (*power_save)(struct mmc_host *);
- int (*power_restore)(struct mmc_host *);
- int (*alive)(struct mmc_host *);
- int (*shutdown)(struct mmc_host *);
- int (*reset)(struct mmc_host *);
- int (*change_bus_speed)(struct mmc_host *, unsigned long *);
-};
-
void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
void mmc_detach_bus(struct mmc_host *host);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index fe96eda51d72..3f68765323ea 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -518,6 +518,9 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
*/
card->ext_csd.out_of_int_time =
ext_csd[EXT_CSD_OUT_OF_INTERRUPT_TIME] * 10;
+ pr_info("%s: Out-of-interrupt timeout is %d[ms]\n",
+ mmc_hostname(card->host),
+ card->ext_csd.out_of_int_time);
}
if (card->ext_csd.rev >= 5) {
@@ -535,8 +538,11 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
card->ext_csd.raw_bkops_status =
ext_csd[EXT_CSD_BKOPS_STATUS];
if (!card->ext_csd.man_bkops_en)
- pr_info("%s: MAN_BKOPS_EN bit is not set\n",
- mmc_hostname(card->host));
+ pr_info("%s: BKOPS_EN equals 0x%x\n",
+ mmc_hostname(card->host),
+ card->ext_csd.man_bkops_en);
+
+
}
/* check whether the eMMC card supports HPI */
@@ -2132,6 +2138,23 @@ reinit:
}
}
+ /*
+ * Start auto bkops, if supported.
+ *
+ * Note: This leaves the possibility of having both manual and
+ * auto bkops running in parallel. The runtime implementation
+ * will allow this, but ignore bkops exceptions on the premises
+ * that auto bkops will eventually kick in and the device will
+ * handle bkops without START_BKOPS from the host.
+ */
+ if (mmc_card_support_auto_bkops(card)) {
+ /*
+ * Ignore the return value of setting auto bkops.
+ * If it failed, will run in backward compatible mode.
+ */
+ (void)mmc_set_auto_bkops(card, true);
+ }
+
return 0;
free_card:
@@ -2335,6 +2358,12 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
goto out;
}
+ if (mmc_card_doing_auto_bkops(host->card)) {
+ err = mmc_set_auto_bkops(host->card, false);
+ if (err)
+ goto out;
+ }
+
err = mmc_flush_cache(host->card);
if (err)
goto out;
@@ -2547,6 +2576,26 @@ static int mmc_reset(struct mmc_host *host)
return mmc_init_card(host, card->ocr, card);
}
+#define NO_AUTOSUSPEND (-1)
+static int mmc_runtime_idle(struct mmc_host *host)
+{
+ BUG_ON(!host->card);
+
+ if (host->card->bkops.needs_manual)
+ mmc_start_manual_bkops(host->card);
+
+ pm_runtime_mark_last_busy(&host->card->dev);
+ /*
+ * TODO: consider prolonging suspend when bkops
+ * is running in order to allow a longer time for
+ * bkops to complete
+ * */
+ pm_schedule_suspend(&host->card->dev, MMC_AUTOSUSPEND_DELAY_MS);
+
+ /* return negative value in order to avoid autosuspend */
+ return NO_AUTOSUSPEND;
+}
+
static const struct mmc_bus_ops mmc_ops = {
.remove = mmc_remove,
.detect = mmc_detect,
@@ -2554,6 +2603,7 @@ static const struct mmc_bus_ops mmc_ops = {
.resume = mmc_resume,
.runtime_suspend = mmc_runtime_suspend,
.runtime_resume = mmc_runtime_resume,
+ .runtime_idle = mmc_runtime_idle,
.alive = mmc_alive,
.shutdown = mmc_shutdown,
.change_bus_speed = mmc_change_bus_speed,
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 8289add95151..80ce6cc36b88 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -12,6 +12,7 @@
#include <linux/device.h>
#include <linux/mmc/core.h>
+#include <linux/mmc/mmc.h>
#include <linux/mod_devicetable.h>
#include <linux/notifier.h>
@@ -86,7 +87,7 @@ struct mmc_ext_csd {
bool hpi; /* HPI support bit */
unsigned int hpi_cmd; /* cmd used as HPI */
bool bkops; /* background support bit */
- bool man_bkops_en; /* manual bkops enable bit */
+ u8 man_bkops_en; /* manual bkops enable */
unsigned int data_sector_size; /* 512 bytes or 4KB */
unsigned int data_tag_unit_size; /* DATA TAG UNIT size */
unsigned int boot_ro_lock; /* ro lock support */
@@ -274,6 +275,15 @@ struct mmc_part {
#define MMC_BLK_DATA_AREA_RPMB (1<<3)
};
+/**
+ * struct mmc_bkops_info - BKOPS data
+ * @need_manual: indication whether have to send START_BKOPS
+ * to the device
+ */
+struct mmc_bkops_info {
+ bool needs_manual;
+};
+
/*
* MMC device
*/
@@ -297,9 +307,10 @@ struct mmc_card {
#define MMC_STATE_BLOCKADDR (1<<2) /* card uses block-addressing */
#define MMC_CARD_SDXC (1<<3) /* card is SDXC */
#define MMC_CARD_REMOVED (1<<4) /* card has been removed */
-#define MMC_STATE_DOING_BKOPS (1<<5) /* card is doing BKOPS */
+#define MMC_STATE_DOING_BKOPS (1<<5) /* card is doing manual BKOPS */
#define MMC_STATE_SUSPENDED (1<<6) /* card is suspended */
#define MMC_STATE_CMDQ (1<<12) /* card is in cmd queue mode */
+#define MMC_STATE_AUTO_BKOPS (1<<13) /* card is doing auto BKOPS */
unsigned int quirks; /* card quirks */
#define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */
#define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */
@@ -363,6 +374,7 @@ struct mmc_card {
bool issue_long_pon;
u8 *cached_ext_csd;
bool cmdq_init;
+ struct mmc_bkops_info bkops;
};
/*
@@ -512,6 +524,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
#define mmc_card_doing_bkops(c) ((c)->state & MMC_STATE_DOING_BKOPS)
#define mmc_card_suspended(c) ((c)->state & MMC_STATE_SUSPENDED)
#define mmc_card_cmdq(c) ((c)->state & MMC_STATE_CMDQ)
+#define mmc_card_doing_auto_bkops(c) ((c)->state & MMC_STATE_AUTO_BKOPS)
#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
@@ -524,6 +537,8 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
#define mmc_card_clr_suspended(c) ((c)->state &= ~MMC_STATE_SUSPENDED)
#define mmc_card_set_cmdq(c) ((c)->state |= MMC_STATE_CMDQ)
#define mmc_card_clr_cmdq(c) ((c)->state &= ~MMC_STATE_CMDQ)
+#define mmc_card_set_auto_bkops(c) ((c)->state |= MMC_STATE_AUTO_BKOPS)
+#define mmc_card_clr_auto_bkops(c) ((c)->state &= ~MMC_STATE_AUTO_BKOPS)
/*
* Quirk add/remove for MMC products.
@@ -594,6 +609,16 @@ static inline int mmc_card_broken_irq_polling(const struct mmc_card *c)
return c->quirks & MMC_QUIRK_BROKEN_IRQ_POLLING;
}
+static inline bool mmc_card_support_auto_bkops(const struct mmc_card *c)
+{
+ return c->ext_csd.rev >= MMC_V5_1;
+}
+
+static inline bool mmc_card_configured_manual_bkops(const struct mmc_card *c)
+{
+ return c->ext_csd.man_bkops_en & EXT_CSD_BKOPS_MANUAL_EN;
+}
+
#define mmc_card_name(c) ((c)->cid.prod_name)
#define mmc_card_id(c) (dev_name(&(c)->dev))
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 22c610609a25..446b56765dbb 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -112,6 +112,23 @@ struct mmc_request {
struct request *req;
};
+struct mmc_bus_ops {
+ void (*remove)(struct mmc_host *);
+ void (*detect)(struct mmc_host *);
+ int (*pre_suspend)(struct mmc_host *);
+ int (*suspend)(struct mmc_host *);
+ int (*resume)(struct mmc_host *);
+ int (*runtime_suspend)(struct mmc_host *);
+ int (*runtime_resume)(struct mmc_host *);
+ int (*runtime_idle)(struct mmc_host *);
+ int (*power_save)(struct mmc_host *);
+ int (*power_restore)(struct mmc_host *);
+ int (*alive)(struct mmc_host *);
+ int (*shutdown)(struct mmc_host *);
+ int (*reset)(struct mmc_host *);
+ int (*change_bus_speed)(struct mmc_host *, unsigned long *);
+};
+
struct mmc_card;
struct mmc_async_req;
struct mmc_cmdq_req;
@@ -139,13 +156,15 @@ extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
extern int mmc_app_cmd(struct mmc_host *, struct mmc_card *);
extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
struct mmc_command *, int);
-extern void mmc_start_bkops(struct mmc_card *card, bool from_exception);
+extern void mmc_check_bkops(struct mmc_card *card);
+extern void mmc_start_manual_bkops(struct mmc_card *card);
extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int);
extern int __mmc_switch_cmdq_mode(struct mmc_command *cmd, u8 set, u8 index,
u8 value, unsigned int timeout_ms,
bool use_busy_signal, bool ignore_timeout);
extern int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error);
extern int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd);
+extern int mmc_set_auto_bkops(struct mmc_card *card, bool enable);
#define MMC_ERASE_ARG 0x00000000
#define MMC_SECURE_ERASE_ARG 0x80000000
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 42e7b412e6f1..cb46cdf8dcf3 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -22,6 +22,8 @@
#include <linux/mmc/card.h>
#include <linux/mmc/pm.h>
+#define MMC_AUTOSUSPEND_DELAY_MS 3000
+
struct mmc_ios {
unsigned int clock; /* clock rate */
unsigned int old_rate; /* saved clock rate */
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index aa1db902745f..1cde2e5eb283 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -370,6 +370,9 @@ struct _mmc_csd {
#define EXT_CSD_PACKED_EVENT_EN BIT(3)
+#define EXT_CSD_BKOPS_MANUAL_EN BIT(0)
+#define EXT_CSD_BKOPS_AUTO_EN BIT(1)
+
/*
* EXCEPTION_EVENT_STATUS field
*/