mmc: sd: SDUC Support Recognition
authorAvri Altman <avri.altman@wdc.com>
Sun, 6 Oct 2024 05:11:39 +0000 (08:11 +0300)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 14 Oct 2024 10:29:01 +0000 (12:29 +0200)
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>
drivers/mmc/core/bus.c
drivers/mmc/core/card.h
drivers/mmc/core/sd.c
drivers/mmc/core/sd.h
drivers/mmc/core/sdio.c
include/linux/mmc/card.h
include/linux/mmc/sd.h

index 0ddaee0eae54f0ccb5042fefd9ec8f5f87bc03ec..30763b342bd3615d37c5116b56613885173f173a 100644 (file)
@@ -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";
index 8476754b1b170c5698ea7da3d4e1008a70ead1c6..3205feb1e8ff6ac7296e81075c105798a5bbac68 100644 (file)
@@ -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)
 #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)
index 9e62cb7055fef96e041410ebe1ce8e1d93ee92bf..63915541c0e494388e4749b6efca57df5a653aaf 100644 (file)
@@ -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;
 
index fe6dd46927a423e9746c0a8b414d8c6a33c1d9c5..7e8beface2ca61490991efefb8f68626e42f4fe8 100644 (file)
@@ -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);
index 4fb247fde5c0801a4b9bdf5503737d36841e0fe8..9566837c9848e6e62a3a3bdd582328e6a1b2ed67 100644 (file)
@@ -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;
 
index 543446392776fa28f8eb3a9c6be721b9a41b7be0..eb67d3d5ff5b22784bfa7032da13773cc68ec60b 100644 (file)
@@ -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,
index 6727576a875559bebafda0c764432851708981b1..865cc0ca8543d1152031613119e03b566813a096 100644 (file)
@@ -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 */