mmc: sd: SDUC Support Recognition
[ Upstream commit fce2ce78af1e14dc1316aaddb5b3308be05cf452 ] Ultra Capacity SD cards (SDUC) was already introduced in SD7.0. Those cards support capacity larger than 2TB and up to including 128TB. ACMD41 was extended to support the host-card handshake during initialization. The card expects that the HCS & HO2T bits to be set in the command argument, and sets the applicable bits in the R3 returned response. On the contrary, if a SDUC card is inserted to a non-supporting host, it will never respond to this ACMD41 until eventually, the host will timed out and give up. Also, add SD CSD version 3.0 - designated for SDUC, and properly parse the csd register as the c_size field got expanded to 28 bits. Do not enable SDUC for now - leave it to the last patch in the series. Tested-by: Ricky WU <ricky_wu@realtek.com> Reviewed-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Avri Altman <avri.altman@wdc.com> Link: https://lore.kernel.org/r/20241006051148.160278-2-avri.altman@wdc.com Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Stable-dep-of: 869d37475788 ("mmc: core: Use GFP_NOIO in ACMD22") Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
f42e0656d4
commit
c00372e41b
@@ -321,7 +321,9 @@ int mmc_add_card(struct mmc_card *card)
|
||||
case MMC_TYPE_SD:
|
||||
type = "SD";
|
||||
if (mmc_card_blockaddr(card)) {
|
||||
if (mmc_card_ext_capacity(card))
|
||||
if (mmc_card_ult_capacity(card))
|
||||
type = "SDUC";
|
||||
else if (mmc_card_ext_capacity(card))
|
||||
type = "SDXC";
|
||||
else
|
||||
type = "SDHC";
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#define MMC_CARD_SDXC (1<<3) /* card is SDXC */
|
||||
#define MMC_CARD_REMOVED (1<<4) /* card has been removed */
|
||||
#define MMC_STATE_SUSPENDED (1<<5) /* card is suspended */
|
||||
#define MMC_CARD_SDUC (1<<6) /* card is SDUC */
|
||||
|
||||
#define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT)
|
||||
#define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY)
|
||||
@@ -30,11 +31,13 @@
|
||||
#define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
|
||||
#define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED))
|
||||
#define mmc_card_suspended(c) ((c)->state & MMC_STATE_SUSPENDED)
|
||||
#define mmc_card_ult_capacity(c) ((c)->state & MMC_CARD_SDUC)
|
||||
|
||||
#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_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
|
||||
#define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
|
||||
#define mmc_card_set_ult_capacity(c) ((c)->state |= MMC_CARD_SDUC)
|
||||
#define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
|
||||
#define mmc_card_set_suspended(c) ((c)->state |= MMC_STATE_SUSPENDED)
|
||||
#define mmc_card_clr_suspended(c) ((c)->state &= ~MMC_STATE_SUSPENDED)
|
||||
|
||||
@@ -100,7 +100,7 @@ void mmc_decode_cid(struct mmc_card *card)
|
||||
/*
|
||||
* Given a 128-bit response, decode to our card CSD structure.
|
||||
*/
|
||||
static int mmc_decode_csd(struct mmc_card *card)
|
||||
static int mmc_decode_csd(struct mmc_card *card, bool is_sduc)
|
||||
{
|
||||
struct mmc_csd *csd = &card->csd;
|
||||
unsigned int e, m, csd_struct;
|
||||
@@ -144,9 +144,10 @@ static int mmc_decode_csd(struct mmc_card *card)
|
||||
mmc_card_set_readonly(card);
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
/*
|
||||
* This is a block-addressed SDHC or SDXC card. Most
|
||||
* interesting fields are unused and have fixed
|
||||
* This is a block-addressed SDHC, SDXC or SDUC card.
|
||||
* Most interesting fields are unused and have fixed
|
||||
* values. To avoid getting tripped by buggy cards,
|
||||
* we assume those fixed values ourselves.
|
||||
*/
|
||||
@@ -159,14 +160,19 @@ static int mmc_decode_csd(struct mmc_card *card)
|
||||
e = unstuff_bits(resp, 96, 3);
|
||||
csd->max_dtr = tran_exp[e] * tran_mant[m];
|
||||
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)
|
||||
if (csd_struct == 1)
|
||||
m = unstuff_bits(resp, 48, 22);
|
||||
else
|
||||
m = unstuff_bits(resp, 48, 28);
|
||||
csd->c_size = m;
|
||||
|
||||
if (csd->c_size >= 0x400000 && is_sduc)
|
||||
mmc_card_set_ult_capacity(card);
|
||||
else if (csd->c_size >= 0xFFFF)
|
||||
mmc_card_set_ext_capacity(card);
|
||||
|
||||
m = unstuff_bits(resp, 48, 22);
|
||||
csd->capacity = (1 + m) << 10;
|
||||
csd->capacity = (1 + (typeof(sector_t))m) << 10;
|
||||
|
||||
csd->read_blkbits = 9;
|
||||
csd->read_partial = 0;
|
||||
@@ -876,7 +882,7 @@ try_again:
|
||||
return err;
|
||||
}
|
||||
|
||||
int mmc_sd_get_csd(struct mmc_card *card)
|
||||
int mmc_sd_get_csd(struct mmc_card *card, bool is_sduc)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -887,7 +893,7 @@ int mmc_sd_get_csd(struct mmc_card *card)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mmc_decode_csd(card);
|
||||
err = mmc_decode_csd(card, is_sduc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -1442,7 +1448,7 @@ retry:
|
||||
}
|
||||
|
||||
if (!oldcard) {
|
||||
err = mmc_sd_get_csd(card);
|
||||
err = mmc_sd_get_csd(card, false);
|
||||
if (err)
|
||||
goto free_card;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ struct mmc_host;
|
||||
struct mmc_card;
|
||||
|
||||
int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr);
|
||||
int mmc_sd_get_csd(struct mmc_card *card);
|
||||
int mmc_sd_get_csd(struct mmc_card *card, bool is_sduc);
|
||||
void mmc_decode_cid(struct mmc_card *card);
|
||||
int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
|
||||
bool reinit);
|
||||
|
||||
@@ -769,7 +769,7 @@ try_again:
|
||||
* Read CSD, before selecting the card
|
||||
*/
|
||||
if (!oldcard && mmc_card_sd_combo(card)) {
|
||||
err = mmc_sd_get_csd(card);
|
||||
err = mmc_sd_get_csd(card, false);
|
||||
if (err)
|
||||
goto remove;
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ struct mmc_csd {
|
||||
unsigned int wp_grp_size;
|
||||
unsigned int read_blkbits;
|
||||
unsigned int write_blkbits;
|
||||
unsigned int capacity;
|
||||
sector_t capacity;
|
||||
unsigned int read_partial:1,
|
||||
read_misalign:1,
|
||||
write_partial:1,
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
/* 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_2T (1 << 27) /* HO2T/CO2T - SDUC support */
|
||||
#define SD_OCR_XPC (1 << 28) /* SDXC power control */
|
||||
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user