Commit 3a303511 authored by Arindam Nath's avatar Arindam Nath Committed by Chris Ball

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: default avatarArindam Nath <arindam.nath@amd.com>
Reviewed-by: default avatarPhilip Rakity <prakity@marvell.com>
Tested-by: default avatarPhilip Rakity <prakity@marvell.com>
Acked-by: default avatarZhangfei Gao <zhangfei.gao@marvell.com>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent 5371c927
...@@ -274,8 +274,12 @@ int mmc_add_card(struct mmc_card *card) ...@@ -274,8 +274,12 @@ int mmc_add_card(struct mmc_card *card)
break; break;
case MMC_TYPE_SD: case MMC_TYPE_SD:
type = "SD"; type = "SD";
if (mmc_card_blockaddr(card)) if (mmc_card_blockaddr(card)) {
type = "SDHC"; if (mmc_card_ext_capacity(card))
type = "SDXC";
else
type = "SDHC";
}
break; break;
case MMC_TYPE_SDIO: case MMC_TYPE_SDIO:
type = "SDIO"; type = "SDIO";
...@@ -299,7 +303,8 @@ int mmc_add_card(struct mmc_card *card) ...@@ -299,7 +303,8 @@ int mmc_add_card(struct mmc_card *card)
} else { } else {
printk(KERN_INFO "%s: new %s%s%s card at address %04x\n", printk(KERN_INFO "%s: new %s%s%s card at address %04x\n",
mmc_hostname(card->host), mmc_hostname(card->host),
mmc_card_highspeed(card) ? "high speed " : "", mmc_sd_card_uhs(card) ? "ultra high speed " :
(mmc_card_highspeed(card) ? "high speed " : ""),
mmc_card_ddr_mode(card) ? "DDR " : "", mmc_card_ddr_mode(card) ? "DDR " : "",
type, card->rca); type, card->rca);
} }
......
...@@ -130,7 +130,7 @@ static int mmc_decode_csd(struct mmc_card *card) ...@@ -130,7 +130,7 @@ static int mmc_decode_csd(struct mmc_card *card)
break; break;
case 1: case 1:
/* /*
* This is a block-addressed SDHC card. Most * This is a block-addressed SDHC or SDXC card. Most
* interesting fields are unused and have fixed * interesting fields are unused and have fixed
* values. To avoid getting tripped by buggy cards, * values. To avoid getting tripped by buggy cards,
* we assume those fixed values ourselves. * we assume those fixed values ourselves.
...@@ -144,6 +144,11 @@ static int mmc_decode_csd(struct mmc_card *card) ...@@ -144,6 +144,11 @@ static int mmc_decode_csd(struct mmc_card *card)
e = UNSTUFF_BITS(resp, 96, 3); e = UNSTUFF_BITS(resp, 96, 3);
csd->max_dtr = tran_exp[e] * tran_mant[m]; csd->max_dtr = tran_exp[e] * tran_mant[m];
csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); csd->cmdclass = UNSTUFF_BITS(resp, 84, 12);
csd->c_size = UNSTUFF_BITS(resp, 48, 22);
/* SDXC cards have a minimum C_SIZE of 0x00FFFF */
if (csd->c_size >= 0xFFFF)
mmc_card_set_ext_capacity(card);
m = UNSTUFF_BITS(resp, 48, 22); m = UNSTUFF_BITS(resp, 48, 22);
csd->capacity = (1 + m) << 10; csd->capacity = (1 + m) << 10;
...@@ -911,6 +916,9 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, ...@@ -911,6 +916,9 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
err = mmc_sd_init_uhs_card(card); err = mmc_sd_init_uhs_card(card);
if (err) if (err)
goto free_card; goto free_card;
/* Card is an ultra-high-speed card */
mmc_sd_card_set_uhs(card);
} else { } else {
/* /*
* Attempt to change to high-speed (if supported) * Attempt to change to high-speed (if supported)
......
...@@ -30,6 +30,7 @@ struct mmc_csd { ...@@ -30,6 +30,7 @@ struct mmc_csd {
unsigned short cmdclass; unsigned short cmdclass;
unsigned short tacc_clks; unsigned short tacc_clks;
unsigned int tacc_ns; unsigned int tacc_ns;
unsigned int c_size;
unsigned int r2w_factor; unsigned int r2w_factor;
unsigned int max_dtr; unsigned int max_dtr;
unsigned int erase_size; /* In sectors */ unsigned int erase_size; /* In sectors */
...@@ -158,6 +159,8 @@ struct mmc_card { ...@@ -158,6 +159,8 @@ struct mmc_card {
#define MMC_STATE_HIGHSPEED (1<<2) /* card is in high speed mode */ #define MMC_STATE_HIGHSPEED (1<<2) /* card is in high speed mode */
#define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */ #define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */
#define MMC_STATE_HIGHSPEED_DDR (1<<4) /* card is in high speed mode */ #define MMC_STATE_HIGHSPEED_DDR (1<<4) /* card is in high speed mode */
#define MMC_STATE_ULTRAHIGHSPEED (1<<5) /* card is in ultra high speed mode */
#define MMC_CARD_SDXC (1<<6) /* card is SDXC */
unsigned int quirks; /* card quirks */ unsigned int quirks; /* card quirks */
#define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */
#define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ #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,12 +296,16 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
#define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED) #define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED)
#define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR)
#define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR) #define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR)
#define mmc_sd_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED)
#define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED) #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR) #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR) #define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
#define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
#define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
static inline int mmc_card_lenient_fn0(const struct mmc_card *c) static inline int mmc_card_lenient_fn0(const struct mmc_card *c)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment