diff options
| author | Arindam Nath <arindam.nath@amd.com> | 2011-05-05 02:49:03 -0400 |
|---|---|---|
| committer | Chris Ball <cjb@laptop.org> | 2011-05-24 23:53:46 -0400 |
| commit | 3a3035114307cd55e024662bb295a87b849f0bd4 (patch) | |
| tree | 764f881c7a677641abaa211128f27a37c9613d90 | |
| parent | 5371c927bcd06a5c9dd6785bab2d452b87d9abc6 (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.c | 11 | ||||
| -rw-r--r-- | drivers/mmc/core/sd.c | 10 | ||||
| -rw-r--r-- | include/linux/mmc/card.h | 7 |
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 | ||
| 303 | static inline int mmc_card_lenient_fn0(const struct mmc_card *c) | 310 | static inline int mmc_card_lenient_fn0(const struct mmc_card *c) |
| 304 | { | 311 | { |
