From f2119df6b764609af4baceb68caf1e848c1c8aa7 Mon Sep 17 00:00:00 2001 From: Arindam Nath Date: Thu, 5 May 2011 12:18:57 +0530 Subject: mmc: sd: add support for signal voltage switch procedure Host Controller v3.00 adds another Capabilities register. Apart from other things, this new register indicates whether the Host Controller supports SDR50, SDR104, and DDR50 UHS-I modes. The spec doesn't mention about explicit support for SDR12 and SDR25 UHS-I modes, so the Host Controller v3.00 should support them by default. Also if the controller supports SDR104 mode, it will also support SDR50 mode as well. So depending on the host support, we set the corresponding MMC_CAP_* flags. One more new register. Host Control2 is added in v3.00, which is used during Signal Voltage Switch procedure described below. Since as per v3.00 spec, UHS-I supported hosts should set S18R to 1, we set S18R (bit 24) of OCR before sending ACMD41. We also need to set XPC (bit 28) of OCR in case the host can supply >150mA. This support is indicated by the Maximum Current Capabilities register of the Host Controller. If the response of ACMD41 has both CCS and S18A set, we start the signal voltage switch procedure, which if successfull, will switch the card from 3.3V signalling to 1.8V signalling. Signal voltage switch procedure adds support for a new command CMD11 in the Physical Layer Spec v3.01. As part of this procedure, we need to set 1.8V Signalling Enable (bit 3) of Host Control2 register, which if remains set after 5ms, means the switch to 1.8V signalling is successfull. Otherwise, we clear bit 24 of OCR and retry the initialization sequence. When we remove the card, and insert the same or another card, we need to make sure that we start with 3.3V signalling voltage. So we call mmc_set_signal_voltage() with MMC_SIGNAL_VOLTAGE_330 set so that we are back to 3.3V signalling voltage before we actually start initializing the card. Tested by Zhangfei Gao with a Toshiba uhs card and general hs card, on mmp2 in SDMA mode. Signed-off-by: Arindam Nath Reviewed-by: Philip Rakity Tested-by: Philip Rakity Acked-by: Zhangfei Gao Signed-off-by: Chris Ball --- include/linux/mmc/sd.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/linux/mmc/sd.h') diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h index 3fd85e088cc..c648878f673 100644 --- a/include/linux/mmc/sd.h +++ b/include/linux/mmc/sd.h @@ -17,6 +17,7 @@ /* This is basically the same command as for MMC with some quirks. */ #define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */ #define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */ +#define SD_SWITCH_VOLTAGE 11 /* ac R1 */ /* class 10 */ #define SD_SWITCH 6 /* adtc [31:0] See below R1 */ @@ -32,6 +33,12 @@ #define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ #define SD_APP_SEND_SCR 51 /* adtc R1 */ +/* OCR bit definitions */ +#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */ +#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */ +#define SD_OCR_XPC (1 << 28) /* SDXC power control */ +#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */ + /* * SD_SWITCH argument format: * -- cgit v1.2.3-70-g09d2 From f0d89972b01798cf9d245dfa1cacfa0ee78a3593 Mon Sep 17 00:00:00 2001 From: Andrei Warkentin Date: Mon, 23 May 2011 15:06:38 -0500 Subject: mmc: core: Block CMD23 support for UHS104/SDXC cards. SD cards operating at UHS104 or better support SET_BLOCK_COUNT. Signed-off-by: Andrei Warkentin Reviewed-by: Arindam Nath Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 9 ++++++--- drivers/mmc/core/sd.c | 2 ++ include/linux/mmc/card.h | 3 +++ include/linux/mmc/sd.h | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) (limited to 'include/linux/mmc/sd.h') diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index a380accaba9..71da5641e25 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1057,9 +1057,12 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, blk_queue_logical_block_size(md->queue.queue, 512); set_capacity(md->disk, size); - if (mmc_host_cmd23(card->host) && - mmc_card_mmc(card)) - md->flags |= MMC_BLK_CMD23; + if (mmc_host_cmd23(card->host)) { + if (mmc_card_mmc(card) || + (mmc_card_sd(card) && + card->scr.cmds & SD_SCR_CMD23_SUPPORT)) + md->flags |= MMC_BLK_CMD23; + } if (mmc_card_mmc(card) && md->flags & MMC_BLK_CMD23 && diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 596d0b9d30b..ff2774128aa 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -203,6 +203,8 @@ static int mmc_decode_scr(struct mmc_card *card) else card->erased_byte = 0x0; + if (scr->sda_spec3) + scr->cmds = UNSTUFF_BITS(resp, 32, 2); return 0; } diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 4a0e27baaea..c6927a4d157 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -72,6 +72,9 @@ struct sd_scr { unsigned char bus_widths; #define SD_SCR_BUS_WIDTH_1 (1<<0) #define SD_SCR_BUS_WIDTH_4 (1<<2) + unsigned char cmds; +#define SD_SCR_CMD20_SUPPORT (1<<0) +#define SD_SCR_CMD23_SUPPORT (1<<1) }; struct sd_ssr { diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h index c648878f673..7d35d52c3df 100644 --- a/include/linux/mmc/sd.h +++ b/include/linux/mmc/sd.h @@ -66,7 +66,7 @@ #define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */ #define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */ -#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00 */ +#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */ /* * SD bus widths -- cgit v1.2.3-70-g09d2