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 ++- include/linux/mmc/host.h | 3 +++ include/linux/mmc/sd.h | 13 +++++++++++++ 5 files changed, 64 insertions(+), 1 deletion(-) 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 diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 8c0bf3f2a36f..0e56f1ae7602 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -401,6 +401,9 @@ int mmc_host_enable(struct mmc_host *host); int mmc_host_disable(struct mmc_host *host); int mmc_host_lazy_disable(struct mmc_host *host); int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *); +int mmc_speed_class_control(struct mmc_host *host, + unsigned int speed_class_ctrl_arg); + static inline void mmc_set_disable_delay(struct mmc_host *host, unsigned int disable_delay) diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h index 1ebcf9ba1256..e65bf7c9dab0 100644 --- a/include/linux/mmc/sd.h +++ b/include/linux/mmc/sd.h @@ -19,6 +19,10 @@ #define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */ #define SD_SWITCH_VOLTAGE 11 /* ac R1 */ + /* class 2 */ +#define SD_SEND_TUNING_PATTERN 19 /* adtc R1 */ +#define SD_SPEED_CLASS_CONTROL 20 /* ac R1b */ + /* class 10 */ #define SD_SWITCH 6 /* adtc [31:0] See below R1 */ @@ -91,4 +95,13 @@ #define SD_SWITCH_ACCESS_DEF 0 #define SD_SWITCH_ACCESS_HS 1 +/* + * SD_SPEED_CLASS_CONTROL definitions + */ +#define SD_SPEED_CLASS_CONTROL_START_REC 0x0 +#define SD_SPEED_CLASS_CONTROL_CREATE_DIR 0x1 +#define SD_SPEED_CLASS_CONTROL_UPDATE_CI 0x4 + + #endif /* LINUX_MMC_SD_H */ + -- cgit v1.2.3