diff mbox series

[v2,01/10] mmc: sd: SDUC Support Recognition

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

Commit Message

Avri Altman Aug. 7, 2024, 6:03 a.m. UTC
ACMD21 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 ACMD21 until
eventually, the host will timed out and give up.

Signed-off-by: Avri Altman <avri.altman@wdc.com>
---
 drivers/mmc/core/sd_ops.c | 19 +++++++++++++++----
 include/linux/mmc/host.h  |  6 ++++++
 include/linux/mmc/sd.h    |  1 +
 3 files changed, 22 insertions(+), 4 deletions(-)

Comments

Ricky WU Aug. 9, 2024, 9:53 a.m. UTC | #1
> 
> ACMD21 was extended to support the host-card handshake during initialization.

Is ACMD41?

> 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 ACMD21 until eventually, the host will timed out and give up.
> 
> Signed-off-by: Avri Altman <avri.altman@wdc.com>
> ---
>  drivers/mmc/core/sd_ops.c | 19 +++++++++++++++----
> include/linux/mmc/host.h  |  6 ++++++
>  include/linux/mmc/sd.h    |  1 +
>  3 files changed, 22 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index
> 8b9b34286ef3..7f6963dac873 100644
> --- a/drivers/mmc/core/sd_ops.c
> +++ b/drivers/mmc/core/sd_ops.c
> @@ -168,12 +168,16 @@ int mmc_send_app_op_cond(struct mmc_host *host,
> u32 ocr, u32 *rocr)
>                 .cmd = &cmd
>         };
>         int err;
> +       u32 sduc_arg = SD_OCR_CCS | SD_OCR_2T;
> 
>         cmd.opcode = SD_APP_OP_COND;
> +       cmd.arg = ocr;
> +
>         if (mmc_host_is_spi(host))
> -               cmd.arg = ocr & (1 << 30); /* SPI only defines one bit */
> +               cmd.arg &= (1 << 30); /* SPI only defines one bit */
>         else
> -               cmd.arg = ocr;
> +               cmd.arg |= sduc_arg;
> +
>         cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;
> 
>         err = __mmc_poll_for_busy(host, SD_APP_OP_COND_PERIOD_US,
> @@ -182,8 +186,15 @@ int mmc_send_app_op_cond(struct mmc_host *host,
> u32 ocr, u32 *rocr)
>         if (err)
>                 return err;
> 
> -       if (rocr && !mmc_host_is_spi(host))
> -               *rocr = cmd.resp[0];
> +       if (!mmc_host_is_spi(host)) {
> +               if (rocr)
> +                       *rocr = cmd.resp[0];
> +
> +               if ((cmd.resp[0] & sduc_arg) == sduc_arg)
> +                       host->caps2 |= MMC_CAP2_SD_SDUC;
> +               else
> +                       host->caps2 &= ~MMC_CAP2_SD_SDUC;

I think host->caps2 is for host to claim caps, here can just call mmc_card_set_ult_capacity? 
Don't need to wait csd, because SDXC and SDHC need to identify by capacity, but SDUC can be identified here
And all your mmc_card_is_sduc() I think change to mmc_card_ult_capacity() to know the card type

> +       }
> 
>         return 0;
>  }
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index
> 88c6a76042ee..a9c36a3e1a10 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -427,6 +427,7 @@ struct mmc_host {
>  #define MMC_CAP2_CRYPTO                0
>  #endif
>  #define MMC_CAP2_ALT_GPT_TEGRA (1 << 28)       /* Host with eMMC
> that has GPT entry at a non-standard location */
> +#define MMC_CAP2_SD_SDUC       (1 << 29)       /* SD over 2TB */
> 
>         int                     fixed_drv_type; /* fixed driver type for
> non-removable media */
> 
> @@ -638,6 +639,11 @@ static inline int mmc_card_uhs(struct mmc_card
> *card)
>                 card->host->ios.timing <= MMC_TIMING_UHS_DDR50;  }
> 
> +static inline int mmc_card_is_sduc(struct mmc_host *host) {
> +       return host->caps2 & MMC_CAP2_SD_SDUC; }
> +
>  void mmc_retune_timer_stop(struct mmc_host *host);
> 
>  static inline void mmc_retune_needed(struct mmc_host *host) diff --git
> a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h index
> 6727576a8755..865cc0ca8543 100644
> --- a/include/linux/mmc/sd.h
> +++ b/include/linux/mmc/sd.h
> @@ -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 */
> 
> --
> 2.25.1
Avri Altman Aug. 10, 2024, 7:58 a.m. UTC | #2
> > ACMD21 was extended to support the host-card handshake during initialization.
> 
> Is ACMD41?
Yes.  Thank you.

> 
> > 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 ACMD21 until eventually, the host will timed out
> and give up.
> >
> > Signed-off-by: Avri Altman <avri.altman@wdc.com>
> > ---
> >  drivers/mmc/core/sd_ops.c | 19 +++++++++++++++----
> > include/linux/mmc/host.h  |  6 ++++++
> >  include/linux/mmc/sd.h    |  1 +
> >  3 files changed, 22 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
> > index
> > 8b9b34286ef3..7f6963dac873 100644
> > --- a/drivers/mmc/core/sd_ops.c
> > +++ b/drivers/mmc/core/sd_ops.c
> > @@ -168,12 +168,16 @@ int mmc_send_app_op_cond(struct mmc_host
> *host,
> > u32 ocr, u32 *rocr)
> >                 .cmd = &cmd
> >         };
> >         int err;
> > +       u32 sduc_arg = SD_OCR_CCS | SD_OCR_2T;
> >
> >         cmd.opcode = SD_APP_OP_COND;
> > +       cmd.arg = ocr;
> > +
> >         if (mmc_host_is_spi(host))
> > -               cmd.arg = ocr & (1 << 30); /* SPI only defines one bit */
> > +               cmd.arg &= (1 << 30); /* SPI only defines one bit */
> >         else
> > -               cmd.arg = ocr;
> > +               cmd.arg |= sduc_arg;
> > +
> >         cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;
> >
> >         err = __mmc_poll_for_busy(host, SD_APP_OP_COND_PERIOD_US, @@
> > -182,8 +186,15 @@ int mmc_send_app_op_cond(struct mmc_host *host,
> > u32 ocr, u32 *rocr)
> >         if (err)
> >                 return err;
> >
> > -       if (rocr && !mmc_host_is_spi(host))
> > -               *rocr = cmd.resp[0];
> > +       if (!mmc_host_is_spi(host)) {
> > +               if (rocr)
> > +                       *rocr = cmd.resp[0];
> > +
> > +               if ((cmd.resp[0] & sduc_arg) == sduc_arg)
> > +                       host->caps2 |= MMC_CAP2_SD_SDUC;
> > +               else
> > +                       host->caps2 &= ~MMC_CAP2_SD_SDUC;
> 
> I think host->caps2 is for host to claim caps, here can just call
> mmc_card_set_ult_capacity?
> Don't need to wait csd, because SDXC and SDHC need to identify by capacity, but
> SDUC can be identified here And all your mmc_card_is_sduc() I think change to
> mmc_card_ult_capacity() to know the card type
This is an interesting idea - and yes, we can do that.
Also the line of reasoning that you provide makes a lot of sense.
However, SDUC is not a card state, so I am not sure I should use it.
I added it to comply with SDXC, but using the card state to imply of a card type doesn't seems right.

Thanks,
Avri

> 
> > +       }
> >
> >         return 0;
> >  }
> > diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index
> > 88c6a76042ee..a9c36a3e1a10 100644
> > --- a/include/linux/mmc/host.h
> > +++ b/include/linux/mmc/host.h
> > @@ -427,6 +427,7 @@ struct mmc_host {
> >  #define MMC_CAP2_CRYPTO                0
> >  #endif
> >  #define MMC_CAP2_ALT_GPT_TEGRA (1 << 28)       /* Host with eMMC
> > that has GPT entry at a non-standard location */
> > +#define MMC_CAP2_SD_SDUC       (1 << 29)       /* SD over 2TB */
> >
> >         int                     fixed_drv_type; /* fixed driver type for
> > non-removable media */
> >
> > @@ -638,6 +639,11 @@ static inline int mmc_card_uhs(struct mmc_card
> > *card)
> >                 card->host->ios.timing <= MMC_TIMING_UHS_DDR50;  }
> >
> > +static inline int mmc_card_is_sduc(struct mmc_host *host) {
> > +       return host->caps2 & MMC_CAP2_SD_SDUC; }
> > +
> >  void mmc_retune_timer_stop(struct mmc_host *host);
> >
> >  static inline void mmc_retune_needed(struct mmc_host *host) diff
> > --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h index
> > 6727576a8755..865cc0ca8543 100644
> > --- a/include/linux/mmc/sd.h
> > +++ b/include/linux/mmc/sd.h
> > @@ -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 */
> >
> > --
> > 2.25.1
Avri Altman Aug. 13, 2024, 5:42 a.m. UTC | #3
> > > -182,8 +186,15 @@ int mmc_send_app_op_cond(struct mmc_host *host,
> > > u32 ocr, u32 *rocr)
> > >         if (err)
> > >                 return err;
> > >
> > > -       if (rocr && !mmc_host_is_spi(host))
> > > -               *rocr = cmd.resp[0];
> > > +       if (!mmc_host_is_spi(host)) {
> > > +               if (rocr)
> > > +                       *rocr = cmd.resp[0];
> > > +
> > > +               if ((cmd.resp[0] & sduc_arg) == sduc_arg)
> > > +                       host->caps2 |= MMC_CAP2_SD_SDUC;
> > > +               else
> > > +                       host->caps2 &= ~MMC_CAP2_SD_SDUC;
> >
> > I think host->caps2 is for host to claim caps, here can just call
> > mmc_card_set_ult_capacity?
> > Don't need to wait csd, because SDXC and SDHC need to identify by
> > capacity, but SDUC can be identified here And all your
> > mmc_card_is_sduc() I think change to
> > mmc_card_ult_capacity() to know the card type
> This is an interesting idea - and yes, we can do that.
> Also the line of reasoning that you provide makes a lot of sense.
> However, SDUC is not a card state, so I am not sure I should use it.
> I added it to comply with SDXC, but using the card state to imply of a card type
> doesn't seems right.
How about extending the use of card->type for that?
e.g., adding the various SD sub-types etc.
But this needs to be done in a separate patch, probably after this series get accepted.

Thanks,
Avri

> 
> Thanks,
> Avri
> 
> >
> > > +       }
> > >
> > >         return 0;
> > >  }
> > > diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> > > index
> > > 88c6a76042ee..a9c36a3e1a10 100644
> > > --- a/include/linux/mmc/host.h
> > > +++ b/include/linux/mmc/host.h
> > > @@ -427,6 +427,7 @@ struct mmc_host {
> > >  #define MMC_CAP2_CRYPTO                0
> > >  #endif
> > >  #define MMC_CAP2_ALT_GPT_TEGRA (1 << 28)       /* Host with eMMC
> > > that has GPT entry at a non-standard location */
> > > +#define MMC_CAP2_SD_SDUC       (1 << 29)       /* SD over 2TB */
> > >
> > >         int                     fixed_drv_type; /* fixed driver type for
> > > non-removable media */
> > >
> > > @@ -638,6 +639,11 @@ static inline int mmc_card_uhs(struct mmc_card
> > > *card)
> > >                 card->host->ios.timing <= MMC_TIMING_UHS_DDR50;  }
> > >
> > > +static inline int mmc_card_is_sduc(struct mmc_host *host) {
> > > +       return host->caps2 & MMC_CAP2_SD_SDUC; }
> > > +
> > >  void mmc_retune_timer_stop(struct mmc_host *host);
> > >
> > >  static inline void mmc_retune_needed(struct mmc_host *host) diff
> > > --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h index
> > > 6727576a8755..865cc0ca8543 100644
> > > --- a/include/linux/mmc/sd.h
> > > +++ b/include/linux/mmc/sd.h
> > > @@ -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 */
> > >
> > > --
> > > 2.25.1
diff mbox series

Patch

diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
index 8b9b34286ef3..7f6963dac873 100644
--- a/drivers/mmc/core/sd_ops.c
+++ b/drivers/mmc/core/sd_ops.c
@@ -168,12 +168,16 @@  int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
 		.cmd = &cmd
 	};
 	int err;
+	u32 sduc_arg = SD_OCR_CCS | SD_OCR_2T;
 
 	cmd.opcode = SD_APP_OP_COND;
+	cmd.arg = ocr;
+
 	if (mmc_host_is_spi(host))
-		cmd.arg = ocr & (1 << 30); /* SPI only defines one bit */
+		cmd.arg &= (1 << 30); /* SPI only defines one bit */
 	else
-		cmd.arg = ocr;
+		cmd.arg |= sduc_arg;
+
 	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;
 
 	err = __mmc_poll_for_busy(host, SD_APP_OP_COND_PERIOD_US,
@@ -182,8 +186,15 @@  int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
 	if (err)
 		return err;
 
-	if (rocr && !mmc_host_is_spi(host))
-		*rocr = cmd.resp[0];
+	if (!mmc_host_is_spi(host)) {
+		if (rocr)
+			*rocr = cmd.resp[0];
+
+		if ((cmd.resp[0] & sduc_arg) == sduc_arg)
+			host->caps2 |= MMC_CAP2_SD_SDUC;
+		else
+			host->caps2 &= ~MMC_CAP2_SD_SDUC;
+	}
 
 	return 0;
 }
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 88c6a76042ee..a9c36a3e1a10 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -427,6 +427,7 @@  struct mmc_host {
 #define MMC_CAP2_CRYPTO		0
 #endif
 #define MMC_CAP2_ALT_GPT_TEGRA	(1 << 28)	/* Host with eMMC that has GPT entry at a non-standard location */
+#define MMC_CAP2_SD_SDUC	(1 << 29)	/* SD over 2TB */
 
 	int			fixed_drv_type;	/* fixed driver type for non-removable media */
 
@@ -638,6 +639,11 @@  static inline int mmc_card_uhs(struct mmc_card *card)
 		card->host->ios.timing <= MMC_TIMING_UHS_DDR50;
 }
 
+static inline int mmc_card_is_sduc(struct mmc_host *host)
+{
+	return host->caps2 & MMC_CAP2_SD_SDUC;
+}
+
 void mmc_retune_timer_stop(struct mmc_host *host);
 
 static inline void mmc_retune_needed(struct mmc_host *host)
diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h
index 6727576a8755..865cc0ca8543 100644
--- a/include/linux/mmc/sd.h
+++ b/include/linux/mmc/sd.h
@@ -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 */