答复: [PATCH] mmc: core: Initial support for SD express card/host
From: 冯锐
Date: Sun Aug 23 2020 - 21:05:17 EST
Hi Hansson:
If this patch will not be changed, I will post a patch for rtsx driver according your patch.
>
> Rui,
>
> On Thu, 16 Jul 2020 at 16:16, Ulf Hansson <ulf.hansson@xxxxxxxxxx> wrote:
> >
> > In the SD specification v7.10 the SD express card has been added. This
> > new type of removable SD card, can be managed via a PCIe/NVMe based
> > interface, while also allowing backwards compatibility towards the
> > legacy SD interface.
> >
> > To keep the backwards compatibility, it's required to start the
> > initialization through the legacy SD interface. If it turns out that
> > the mmc host and the SD card, both supports the PCIe/NVMe interface,
> > then a switch should be allowed.
> >
> > Therefore, let's introduce some basic support for this type of SD
> > cards to the mmc core. The mmc host, should set MMC_CAP2_SD_EXP if it
> > supports this interface and MMC_CAP2_SD_EXP_1_2V, if also 1.2V is
> > supported, as to inform the core about it.
> >
> > To deal with the switch to the PCIe/NVMe interface, the mmc host is
> > required to implement a new host ops, ->init_sd_express(). Based on
> > the initial communication between the host and the card,
> > host->ios.timing is set to either MMC_TIMING_SD_EXP or
> > MMC_TIMING_SD_EXP_1_2V, depending on if 1.2V is supported or not. In
> > this way, the mmc host can check these values in its ->init_sd_express() ops,
> to know how to proceed with the handover.
> >
> > Note that, to manage card insert/removal, the mmc core sticks with
> > using the ->get_cd() callback, which means it's the host's
> > responsibility to make sure it provides valid data, even if the card
> > may be managed by PCIe/NVMe at the moment. As long as the card seems
> > to be present, the mmc core keeps the card powered on.
> >
> > Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
> > Cc: Arnd Bergmann <arnd@xxxxxxxx>
> > Cc: Christoph Hellwig <hch@xxxxxx>
> > Cc: Rui Feng <rui_feng@xxxxxxxxxxxxxx>
> > Signed-off-by: Ulf Hansson <ulf.hansson@xxxxxxxxxx>
>
> Rui, did you manage to get some time to look at $subject patch?
>
> If you need some help to understand what's needed to implement the
> corresponding support in drivers/mmc/host/rtsx_pci_sdmmc.c, then please
> just ask.
>
> I think it would make sense to queue changes for rtsx_pci at the same point as
> the mmc core changes. That's because I don't want to maintain code in the
> mmc core that's left unused.
>
> Kind regards
> Uffe
>
> > ---
> > drivers/mmc/core/core.c | 15 ++++++++++--
> > drivers/mmc/core/host.h | 6 +++++
> > drivers/mmc/core/sd_ops.c | 49
> > +++++++++++++++++++++++++++++++++++++--
> > drivers/mmc/core/sd_ops.h | 1 +
> > include/linux/mmc/host.h | 7 ++++++
> > 5 files changed, 74 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index
> > 8ccae6452b9c..6673c0f33cc7 100644
> > --- a/drivers/mmc/core/core.c
> > +++ b/drivers/mmc/core/core.c
> > @@ -2137,8 +2137,12 @@ static int mmc_rescan_try_freq(struct
> mmc_host
> > *host, unsigned freq)
> >
> > mmc_go_idle(host);
> >
> > - if (!(host->caps2 & MMC_CAP2_NO_SD))
> > - mmc_send_if_cond(host, host->ocr_avail);
> > + if (!(host->caps2 & MMC_CAP2_NO_SD)) {
> > + if (mmc_send_if_cond_pcie(host, host->ocr_avail))
> > + goto out;
> > + if (mmc_card_sd_express(host))
> > + return 0;
> > + }
> >
> > /* Order's important: probe SDIO, then SD, then MMC */
> > if (!(host->caps2 & MMC_CAP2_NO_SDIO)) @@ -2153,6 +2157,7
> @@
> > static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
> > if (!mmc_attach_mmc(host))
> > return 0;
> >
> > +out:
> > mmc_power_off(host);
> > return -EIO;
> > }
> > @@ -2280,6 +2285,12 @@ void mmc_rescan(struct work_struct *work)
> > goto out;
> > }
> >
> > + /* If an SD express card is present, then leave it as is. */
> > + if (mmc_card_sd_express(host)) {
> > + mmc_release_host(host);
> > + goto out;
> > + }
> > +
> > for (i = 0; i < ARRAY_SIZE(freqs); i++) {
> > unsigned int freq = freqs[i];
> > if (freq > host->f_max) { diff --git
> > a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h index
> > 5e3b9534ffb2..ba407617ed23 100644
> > --- a/drivers/mmc/core/host.h
> > +++ b/drivers/mmc/core/host.h
> > @@ -77,5 +77,11 @@ static inline bool mmc_card_hs400es(struct
> mmc_card *card)
> > return card->host->ios.enhanced_strobe; }
> >
> > +static inline bool mmc_card_sd_express(struct mmc_host *host) {
> > + return host->ios.timing == MMC_TIMING_SD_EXP ||
> > + host->ios.timing == MMC_TIMING_SD_EXP_1_2V; }
> > +
> > #endif
> >
> > diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
> > index 22bf528294b9..d61ff811218c 100644
> > --- a/drivers/mmc/core/sd_ops.c
> > +++ b/drivers/mmc/core/sd_ops.c
> > @@ -158,7 +158,8 @@ int mmc_send_app_op_cond(struct mmc_host *host,
> u32 ocr, u32 *rocr)
> > return err;
> > }
> >
> > -int mmc_send_if_cond(struct mmc_host *host, u32 ocr)
> > +static int __mmc_send_if_cond(struct mmc_host *host, u32 ocr, u8
> pcie_bits,
> > + u32 *resp)
> > {
> > struct mmc_command cmd = {};
> > int err;
> > @@ -171,7 +172,7 @@ int mmc_send_if_cond(struct mmc_host *host, u32
> ocr)
> > * SD 1.0 cards.
> > */
> > cmd.opcode = SD_SEND_IF_COND;
> > - cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
> > + cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | pcie_bits << 8 |
> > + test_pattern;
> > cmd.flags = MMC_RSP_SPI_R7 | MMC_RSP_R7 |
> MMC_CMD_BCR;
> >
> > err = mmc_wait_for_cmd(host, &cmd, 0); @@ -186,6 +187,50
> @@
> > int mmc_send_if_cond(struct mmc_host *host, u32 ocr)
> > if (result_pattern != test_pattern)
> > return -EIO;
> >
> > + if (resp)
> > + *resp = cmd.resp[0];
> > +
> > + return 0;
> > +}
> > +
> > +int mmc_send_if_cond(struct mmc_host *host, u32 ocr) {
> > + return __mmc_send_if_cond(host, ocr, 0, NULL); }
> > +
> > +int mmc_send_if_cond_pcie(struct mmc_host *host, u32 ocr) {
> > + u32 resp = 0;
> > + u8 pcie_bits = 0;
> > + int ret;
> > +
> > + if (host->caps2 & MMC_CAP2_SD_EXP) {
> > + /* Probe card for SD express support via PCIe. */
> > + pcie_bits = 0x10;
> > + if (host->caps2 & MMC_CAP2_SD_EXP_1_2V)
> > + /* Probe also for 1.2V support. */
> > + pcie_bits = 0x30;
> > + }
> > +
> > + ret = __mmc_send_if_cond(host, ocr, pcie_bits, &resp);
> > + if (ret)
> > + return 0;
> > +
> > + /* Continue with the SD express init, if the card supports it. */
> > + resp &= 0x3000;
> > + if (pcie_bits && resp) {
> > + if (resp == 0x3000)
> > + host->ios.timing =
> MMC_TIMING_SD_EXP_1_2V;
> > + else
> > + host->ios.timing = MMC_TIMING_SD_EXP;
> > +
> > + /*
> > + * According to the spec the clock shall also be gated, but
> > + * let's leave this to the host driver for more flexibility.
> > + */
> > + return host->ops->init_sd_express(host, &host->ios);
> > + }
> > +
> > return 0;
> > }
> >
> > diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h
> > index 2194cabfcfc5..3ba7b3cf4652 100644
> > --- a/drivers/mmc/core/sd_ops.h
> > +++ b/drivers/mmc/core/sd_ops.h
> > @@ -16,6 +16,7 @@ struct mmc_host;
> > int mmc_app_set_bus_width(struct mmc_card *card, int width); int
> > mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr); int
> > mmc_send_if_cond(struct mmc_host *host, u32 ocr);
> > +int mmc_send_if_cond_pcie(struct mmc_host *host, u32 ocr);
> > int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca);
> > int mmc_app_send_scr(struct mmc_card *card); int mmc_sd_switch(struct
> > mmc_card *card, int mode, int group, diff --git
> > a/include/linux/mmc/host.h b/include/linux/mmc/host.h index
> > c5b6e97cb21a..905cddc5e6f3 100644
> > --- a/include/linux/mmc/host.h
> > +++ b/include/linux/mmc/host.h
> > @@ -60,6 +60,8 @@ struct mmc_ios {
> > #define MMC_TIMING_MMC_DDR52 8
> > #define MMC_TIMING_MMC_HS200 9
> > #define MMC_TIMING_MMC_HS400 10
> > +#define MMC_TIMING_SD_EXP 11
> > +#define MMC_TIMING_SD_EXP_1_2V 12
> >
> > unsigned char signal_voltage; /* signalling voltage
> (1.8V or 3.3V) */
> >
> > @@ -172,6 +174,9 @@ struct mmc_host_ops {
> > */
> > int (*multi_io_quirk)(struct mmc_card *card,
> > unsigned int direction, int
> > blk_size);
> > +
> > + /* Initialize an SD express card, mandatory for MMC_CAP2_SD_EXP.
> */
> > + int (*init_sd_express)(struct mmc_host *host, struct
> mmc_ios *ios);
> > };
> >
> > struct mmc_cqe_ops {
> > @@ -357,6 +362,8 @@ struct mmc_host {
> > #define MMC_CAP2_HS200_1_2V_SDR (1 << 6) /* can
> support */
> > #define MMC_CAP2_HS200 (MMC_CAP2_HS200_1_8V_SDR | \
> > MMC_CAP2_HS200_1_2V_SDR)
> > +#define MMC_CAP2_SD_EXP (1 << 7) /* SD
> express via PCIe */
> > +#define MMC_CAP2_SD_EXP_1_2V (1 << 8) /* SD express 1.2V
> */
> > #define MMC_CAP2_CD_ACTIVE_HIGH (1 << 10) /*
> Card-detect signal active high */
> > #define MMC_CAP2_RO_ACTIVE_HIGH (1 << 11) /*
> Write-protect signal active high */
> > #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power
> up
> > before scan */
> > --
> > 2.20.1
> >
>
> ------Please consider the environment before printing this e-mail.