From 503103dabe8b55358379d4cd3ecd5acac45ebd3d Mon Sep 17 00:00:00 2001 From: Pavan Kunapuli Date: Mon, 16 Jul 2012 14:57:35 +0530 Subject: mmc: core: SDXC speed class support Unlike SDSC and SDHC, for SDXC cards CMD20 needs to be issued to meet the class performance for speed class recording. Adding mmc_speed_class_control() which should be used by an AV recording app/utility before starting recording on an SDXC card. Bug 969360 Reviewed-on: http://git-master/r/39394 Signed-off-by: Pavan Kunapuli Reviewed-on: http://git-master/r/115685 (cherry picked from commit 04b8d1287a95e1882d956cdf7997015350408a3c) Change-Id: Id567effb476ee580de3d49b70201ebae5a13360a Reviewed-on: http://git-master/r/118038 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Naveen Kumar Arepalli Reviewed-by: Bitan Biswas --- drivers/mmc/core/core.c | 20 ++++++++++++++++++++ drivers/mmc/core/sd_ops.c | 26 ++++++++++++++++++++++++++ drivers/mmc/core/sd_ops.h | 3 ++- 3 files changed, 48 insertions(+), 1 deletion(-) (limited to 'drivers/mmc') diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 35f3df8810e0..3fe73a7c1e99 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2109,6 +2109,26 @@ void mmc_stop_host(struct mmc_host *host) mmc_power_off(host); } +int mmc_speed_class_control(struct mmc_host *host, + unsigned int speed_class_ctrl_arg) +{ + int err = -ENOSYS; + u32 status; + + err = mmc_send_speed_class_ctrl(host, speed_class_ctrl_arg); + if (err) + return err; + + /* Issue CMD13 to check for any errors during the busy period of CMD20 */ + err = mmc_send_status(host->card, &status); + if (!err) { + if (status & R1_ERROR) + err = -EINVAL; + } + return err; +} +EXPORT_SYMBOL(mmc_speed_class_control); + int mmc_power_save_host(struct mmc_host *host) { int ret = 0; diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index 021fed153804..b06781e69ce3 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c @@ -389,3 +389,29 @@ int mmc_app_sd_status(struct mmc_card *card, void *ssr) return 0; } + +int mmc_send_speed_class_ctrl(struct mmc_host *host, + unsigned int speed_class_ctrl_arg) +{ + int err = 0; + struct mmc_command cmd = { + .opcode = SD_SPEED_CLASS_CONTROL, + .arg = (speed_class_ctrl_arg << 28), + .flags = MMC_RSP_R1B | MMC_CMD_AC | MMC_RSP_BUSY, + }; + + BUG_ON(!host); + BUG_ON(speed_class_ctrl_arg > 3); + err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); + if (err) + return err; + + /* + * If the host does not wait while the card signals busy, then we will + * will have to wait the max busy indication timeout. + */ + if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) + mmc_delay(1000); + return err; +} + diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h index ffc2305d905f..a77b8facceb4 100644 --- a/drivers/mmc/core/sd_ops.h +++ b/drivers/mmc/core/sd_ops.h @@ -20,6 +20,7 @@ int mmc_app_send_scr(struct mmc_card *card, u32 *scr); int mmc_sd_switch(struct mmc_card *card, int mode, int group, u8 value, u8 *resp); int mmc_app_sd_status(struct mmc_card *card, void *ssr); - +int mmc_send_speed_class_ctrl(struct mmc_host *host, + unsigned int speed_class_ctrl_arg); #endif -- cgit v1.2.3