aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArindam Nath <arindam.nath@amd.com>2011-05-05 02:49:03 -0400
committerChris Ball <cjb@laptop.org>2011-05-24 23:53:46 -0400
commit3a3035114307cd55e024662bb295a87b849f0bd4 (patch)
tree764f881c7a677641abaa211128f27a37c9613d90
parent5371c927bcd06a5c9dd6785bab2d452b87d9abc6 (diff)
mmc: sd: report correct speed and capacity of uhs cards
Since only UHS-I cards respond with S18A set in response to ACMD41, we set the card as ultra-high-speed after successfull initialization. We need to decide whether a card is SDXC based on the C_SIZE field of CSDv2.0 register. According to Physical Layer spec v3.01, the minimum value of C_SIZE for SDXC card is 00FFFFh. Tested by Zhangfei Gao with a Toshiba uhs card and general hs card, on mmp2 in SDMA mode. Signed-off-by: Arindam Nath <arindam.nath@amd.com> Reviewed-by: Philip Rakity <prakity@marvell.com> Tested-by: Philip Rakity <prakity@marvell.com> Acked-by: Zhangfei Gao <zhangfei.gao@marvell.com> Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r--drivers/mmc/core/bus.c11
-rw-r--r--drivers/mmc/core/sd.c10
-rw-r--r--include/linux/mmc/card.h7
3 files changed, 24 insertions, 4 deletions
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index d6d62fd07ee9..393d817ed040 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -274,8 +274,12 @@ int mmc_add_card(struct mmc_card *card)
274 break; 274 break;
275 case MMC_TYPE_SD: 275 case MMC_TYPE_SD:
276 type = "SD"; 276 type = "SD";
277 if (mmc_card_blockaddr(card)) 277 if (mmc_card_blockaddr(card)) {
278 type = "SDHC"; 278 if (mmc_card_ext_capacity(card))
279 type = "SDXC";
280 else
281 type = "SDHC";
282 }
279 break; 283 break;
280 case MMC_TYPE_SDIO: 284 case MMC_TYPE_SDIO:
281 type = "SDIO"; 285 type = "SDIO";
@@ -299,7 +303,8 @@ int mmc_add_card(struct mmc_card *card)
299 } else { 303 } else {
300 printk(KERN_INFO "%s: new %s%s%s card at address %04x\n", 304 printk(KERN_INFO "%s: new %s%s%s card at address %04x\n",
301 mmc_hostname(card->host), 305 mmc_hostname(card->host),
302 mmc_card_highspeed(card) ? "high speed " : "", 306 mmc_sd_card_uhs(card) ? "ultra high speed " :
307 (mmc_card_highspeed(card) ? "high speed " : ""),
303 mmc_card_ddr_mode(card) ? "DDR " : "", 308 mmc_card_ddr_mode(card) ? "DDR " : "",
304 type, card->rca); 309 type, card->rca);
305 } 310 }
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 8e2d8012e4cb..732c3171ceca 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -130,7 +130,7 @@ static int mmc_decode_csd(struct mmc_card *card)
130 break; 130 break;
131 case 1: 131 case 1:
132 /* 132 /*
133 * This is a block-addressed SDHC card. Most 133 * This is a block-addressed SDHC or SDXC card. Most
134 * interesting fields are unused and have fixed 134 * interesting fields are unused and have fixed
135 * values. To avoid getting tripped by buggy cards, 135 * values. To avoid getting tripped by buggy cards,
136 * we assume those fixed values ourselves. 136 * we assume those fixed values ourselves.
@@ -144,6 +144,11 @@ static int mmc_decode_csd(struct mmc_card *card)
144 e = UNSTUFF_BITS(resp, 96, 3); 144 e = UNSTUFF_BITS(resp, 96, 3);
145 csd->max_dtr = tran_exp[e] * tran_mant[m]; 145 csd->max_dtr = tran_exp[e] * tran_mant[m];
146 csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); 146 csd->cmdclass = UNSTUFF_BITS(resp, 84, 12);
147 csd->c_size = UNSTUFF_BITS(resp, 48, 22);
148
149 /* SDXC cards have a minimum C_SIZE of 0x00FFFF */
150 if (csd->c_size >= 0xFFFF)
151 mmc_card_set_ext_capacity(card);
147 152
148 m = UNSTUFF_BITS(resp, 48, 22); 153 m = UNSTUFF_BITS(resp, 48, 22);
149 csd->capacity = (1 + m) << 10; 154 csd->capacity = (1 + m) << 10;
@@ -911,6 +916,9 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
911 err = mmc_sd_init_uhs_card(card); 916 err = mmc_sd_init_uhs_card(card);
912 if (err) 917 if (err)
913 goto free_card; 918 goto free_card;
919
920 /* Card is an ultra-high-speed card */
921 mmc_sd_card_set_uhs(card);
914 } else { 922 } else {
915 /* 923 /*
916 * Attempt to change to high-speed (if supported) 924 * Attempt to change to high-speed (if supported)
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 47b5ad3960b7..d8dffc992ce2 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -30,6 +30,7 @@ struct mmc_csd {
30 unsigned short cmdclass; 30 unsigned short cmdclass;
31 unsigned short tacc_clks; 31 unsigned short tacc_clks;
32 unsigned int tacc_ns; 32 unsigned int tacc_ns;
33 unsigned int c_size;
33 unsigned int r2w_factor; 34 unsigned int r2w_factor;
34 unsigned int max_dtr; 35 unsigned int max_dtr;
35 unsigned int erase_size; /* In sectors */ 36 unsigned int erase_size; /* In sectors */
@@ -158,6 +159,8 @@ struct mmc_card {
158#define MMC_STATE_HIGHSPEED (1<<2) /* card is in high speed mode */ 159#define MMC_STATE_HIGHSPEED (1<<2) /* card is in high speed mode */
159#define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */ 160#define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */
160#define MMC_STATE_HIGHSPEED_DDR (1<<4) /* card is in high speed mode */ 161#define MMC_STATE_HIGHSPEED_DDR (1<<4) /* card is in high speed mode */
162#define MMC_STATE_ULTRAHIGHSPEED (1<<5) /* card is in ultra high speed mode */
163#define MMC_CARD_SDXC (1<<6) /* card is SDXC */
161 unsigned int quirks; /* card quirks */ 164 unsigned int quirks; /* card quirks */
162#define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ 165#define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */
163#define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ 166#define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */
@@ -293,12 +296,16 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
293#define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED) 296#define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED)
294#define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) 297#define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR)
295#define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR) 298#define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR)
299#define mmc_sd_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED)
300#define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
296 301
297#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) 302#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
298#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) 303#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
299#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED) 304#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
300#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR) 305#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
301#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR) 306#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
307#define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
308#define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
302 309
303static inline int mmc_card_lenient_fn0(const struct mmc_card *c) 310static inline int mmc_card_lenient_fn0(const struct mmc_card *c)
304{ 311{