diff mbox series

[v3,02/10] mmc: sd: Add SD CSD version 3.0

Message ID 20240814072934.2559911-3-avri.altman@wdc.com (mailing list archive)
State New
Headers show
Series Add SDUC Support | expand

Commit Message

Avri Altman Aug. 14, 2024, 7:29 a.m. UTC
Ultra Capacity SD cards (SDUC) was already introduced in SD7.0.  Those
cards support capacity larger than 2TB and up to including 128TB.
Properly parse the csd register as the c_size field got expanded to 28
bits.

Tested-by: Ricky WU <ricky_wu@realtek.com>
Signed-off-by: Avri Altman <avri.altman@wdc.com>
---
 drivers/mmc/core/bus.c   |  4 +++-
 drivers/mmc/core/card.h  |  3 +++
 drivers/mmc/core/sd.c    | 16 +++++++++++-----
 include/linux/mmc/card.h |  2 +-
 4 files changed, 18 insertions(+), 7 deletions(-)

Comments

Ulf Hansson Aug. 22, 2024, 11:47 a.m. UTC | #1
On Wed, 14 Aug 2024 at 09:31, Avri Altman <avri.altman@wdc.com> wrote:
>
> Ultra Capacity SD cards (SDUC) was already introduced in SD7.0.  Those
> cards support capacity larger than 2TB and up to including 128TB.
> Properly parse the csd register as the c_size field got expanded to 28
> bits.
>
> Tested-by: Ricky WU <ricky_wu@realtek.com>
> Signed-off-by: Avri Altman <avri.altman@wdc.com>

This is more what I expected from patch1. Perhaps we should simply
squash patch1 and patch2?

Kind regards
Uffe

> ---
>  drivers/mmc/core/bus.c   |  4 +++-
>  drivers/mmc/core/card.h  |  3 +++
>  drivers/mmc/core/sd.c    | 16 +++++++++++-----
>  include/linux/mmc/card.h |  2 +-
>  4 files changed, 18 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
> index 0ddaee0eae54..30763b342bd3 100644
> --- a/drivers/mmc/core/bus.c
> +++ b/drivers/mmc/core/bus.c
> @@ -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";
> diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h
> index b7754a1b8d97..64dcb463a4f4 100644
> --- a/drivers/mmc/core/card.h
> +++ b/drivers/mmc/core/card.h
> @@ -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)
> diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
> index 1c8148cdda50..28193a9b31c9 100644
> --- a/drivers/mmc/core/sd.c
> +++ b/drivers/mmc/core/sd.c
> @@ -157,6 +157,7 @@ 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
> @@ -172,14 +173,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 && mmc_card_is_sduc(card->host))
> +                       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;
> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
> index f34407cc2788..f39bce322365 100644
> --- a/include/linux/mmc/card.h
> +++ b/include/linux/mmc/card.h
> @@ -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,
> --
> 2.25.1
>
Avri Altman Aug. 22, 2024, 1:17 p.m. UTC | #2
> On Wed, 14 Aug 2024 at 09:31, Avri Altman <avri.altman@wdc.com> wrote:
> >
> > Ultra Capacity SD cards (SDUC) was already introduced in SD7.0.  Those
> > cards support capacity larger than 2TB and up to including 128TB.
> > Properly parse the csd register as the c_size field got expanded to 28
> > bits.
> >
> > Tested-by: Ricky WU <ricky_wu@realtek.com>
> > Signed-off-by: Avri Altman <avri.altman@wdc.com>
> 
> This is more what I expected from patch1. Perhaps we should simply squash
> patch1 and patch2?
Done.

Thanks,
Avri

> 
> Kind regards
> Uffe
> 
> > ---
> >  drivers/mmc/core/bus.c   |  4 +++-
> >  drivers/mmc/core/card.h  |  3 +++
> >  drivers/mmc/core/sd.c    | 16 +++++++++++-----
> >  include/linux/mmc/card.h |  2 +-
> >  4 files changed, 18 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index
> > 0ddaee0eae54..30763b342bd3 100644
> > --- a/drivers/mmc/core/bus.c
> > +++ b/drivers/mmc/core/bus.c
> > @@ -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"; diff --git
> > a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h index
> > b7754a1b8d97..64dcb463a4f4 100644
> > --- a/drivers/mmc/core/card.h
> > +++ b/drivers/mmc/core/card.h
> > @@ -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)
> > diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index
> > 1c8148cdda50..28193a9b31c9 100644
> > --- a/drivers/mmc/core/sd.c
> > +++ b/drivers/mmc/core/sd.c
> > @@ -157,6 +157,7 @@ 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 @@
> > -172,14 +173,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 && mmc_card_is_sduc(card->host))
> > +                       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; diff --git
> > a/include/linux/mmc/card.h b/include/linux/mmc/card.h index
> > f34407cc2788..f39bce322365 100644
> > --- a/include/linux/mmc/card.h
> > +++ b/include/linux/mmc/card.h
> > @@ -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,
> > --
> > 2.25.1
> >
diff mbox series

Patch

diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 0ddaee0eae54..30763b342bd3 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -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";
diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h
index b7754a1b8d97..64dcb463a4f4 100644
--- a/drivers/mmc/core/card.h
+++ b/drivers/mmc/core/card.h
@@ -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)
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 1c8148cdda50..28193a9b31c9 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -157,6 +157,7 @@  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
@@ -172,14 +173,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 && mmc_card_is_sduc(card->host))
+			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;
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index f34407cc2788..f39bce322365 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -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,