Commit fce2ce78 authored by Avri Altman's avatar Avri Altman Committed by Ulf Hansson
Browse files

mmc: sd: SDUC Support Recognition



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: default avatarRicky WU <ricky_wu@realtek.com>
Reviewed-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Signed-off-by: default avatarAvri Altman <avri.altman@wdc.com>
Link: https://lore.kernel.org/r/20241006051148.160278-2-avri.altman@wdc.com


Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 078e548a
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -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";
+3 −0
Original line number Diff line number Diff line
@@ -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)
+17 −11
Original line number Diff line number Diff line
@@ -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 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
	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 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
	}

	if (!oldcard) {
		err = mmc_sd_get_csd(card);
		err = mmc_sd_get_csd(card, false);
		if (err)
			goto free_card;

+1 −1
Original line number Diff line number Diff line
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -769,7 +769,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
	 * 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;

Loading