On 5 December 2011 20:29, Saugata Das <saugata....@linaro.org> wrote:
> Hi Girish
>
> Please refer to Figure 71 (HS200 device output timing) of the MMC-4.5
> spec. It shows that both CMD and DATA[7-0] will have some latency till
> valid window. This implies that even the CMD line will need tuning for
> reading the response. The specification talks about identifying
> sampling point for data lines by reading tuning blocks. Based on host
> controller capability, even the CMD line will get the good sample
> point during the same tuning sequence.
>Thanks for pointing the right place. will do the necessary changes
> We need to have the tuning done (execute_tuning) soon after switching
> to HS200 mode and 200MHz clock.
>
>
> Regards
> Saugata
>
>
> On 5 December 2011 16:59, Subhash Jadavani <subha...@codeaurora.org> wrote:
>>
>>
>>> -----Original Message-----
>>> From: Girish K S [mailto:girish.shivananja...@linaro.org]
>>> Sent: Monday, December 05, 2011 12:20 PM
>>> To: Subhash Jadavani
>>> Cc: linux-mmc@vger.kernel.org; patc...@linaro.org; linux-samsung-
>>> s...@vger.kernel.org; Chris Ball
>>> Subject: Re: [PATCH V5] mmc: core: HS200 mode support for eMMC 4.5
>>>
>>> On 5 December 2011 11:46, Subhash Jadavani <subha...@codeaurora.org>
>>> wrote:
>>> >
>>> >
>>> >> -----Original Message-----
>>> >> From: Girish K S [mailto:girish.shivananja...@linaro.org]
>>> >> Sent: Friday, December 02, 2011 5:08 PM
>>> >> To: Subhash Jadavani
>>> >> Cc: linux-mmc@vger.kernel.org; patc...@linaro.org; linux-samsung-
>>> >> s...@vger.kernel.org; Chris Ball
>>> >> Subject: Re: [PATCH V5] mmc: core: HS200 mode support for eMMC 4.5
>>> >>
>>> >> On 2 December 2011 00:02, Subhash Jadavani <subha...@codeaurora.org>
>>> >> wrote:
>>> >> >
>>> >> >
>>> >> >> -----Original Message-----
>>> >> >> From: linux-mmc-ow...@vger.kernel.org [mailto:linux-mmc-
>>> >> >> ow...@vger.kernel.org] On Behalf Of Girish K S
>>> >> >> Sent: Thursday, December 01, 2011 7:48 PM
>>> >> >> To: Subhash Jadavani
>>> >> >> Cc: linux-mmc@vger.kernel.org; patc...@linaro.org; linux-samsung-
>>> >> >> s...@vger.kernel.org; Chris Ball
>>> >> >> Subject: Re: [PATCH V5] mmc: core: HS200 mode support for eMMC
>>> 4.5
>>> >> >>
>>> >> >> On 1 December 2011 16:27, Subhash Jadavani
>>> <subha...@codeaurora.org>
>>> >> >> wrote:
>>> >> >> >
>>> >> >> >
>>> >> >> >> -----Original Message-----
>>> >> >> >> From: linux-mmc-ow...@vger.kernel.org [mailto:linux-mmc-
>>> >> >> >> ow...@vger.kernel.org] On Behalf Of Girish K S
>>> >> >> >> Sent: Thursday, December 01, 2011 3:58 PM
>>> >> >> >> To: Subhash Jadavani
>>> >> >> >> Cc: linux-mmc@vger.kernel.org; patc...@linaro.org; linux-
>>> samsung-
>>> >> >> >> s...@vger.kernel.org; Chris Ball
>>> >> >> >> Subject: Re: [PATCH V5] mmc: core: HS200 mode support for eMMC
>>> >> 4.5
>>> >> >> >>
>>> >> >> >> On 1 December 2011 15:33, Subhash Jadavani
>>> >> <subha...@codeaurora.org>
>>> >> >> >> wrote:
>>> >> >> >> > Hi Girish,
>>> >> >> >> >
>>> >> >> >> >> -----Original Message-----
>>> >> >> >> >> From: linux-mmc-ow...@vger.kernel.org [mailto:linux-mmc-
>>> >> >> >> >> ow...@vger.kernel.org] On Behalf Of Girish K S
>>> >> >> >> >> Sent: Wednesday, November 30, 2011 2:24 PM
>>> >> >> >> >> To: linux-mmc@vger.kernel.org
>>> >> >> >> >> Cc: patc...@linaro.org; linux-samsung-...@vger.kernel.org;
>>> >> >> >> >> subha...@codeaurora.org; Girish K S; Chris Ball
>>> >> >> >> >> Subject: [PATCH V5] mmc: core: HS200 mode support for eMMC
>>> 4.5
>>> >> >> >> >>
>>> >> >> >> >> This patch adds the support of the HS200 bus speed for eMMC
>>> >> 4.5
>>> >> >> >> >> devices.
>>> >> >> >> >> The eMMC 4.5 devices have support for 200MHz bus speed.The
>>> mmc
>>> >> >> core
>>> >> >> >> and
>>> >> >> >> >> host modules have been touched to add support for this
>>> module.
>>> >> >> >> >>
>>> >> >> >> >> It is necessary to know the card type in the sdhci.c file
>>> to
>>> >> add
>>> >> >> >> >> support
>>> >> >> >> >> for eMMC tuning function. So card.h file is included to
>>> import
>>> >> >> the
>>> >> >> >> card
>>> >> >> >> >> data structure.
>>> >> >> >> >>
>>> >> >> >> >> cc: Chris Ball <c...@laptop.org>
>>> >> >> >> >> Signed-off-by: Girish K S <girish.shivananja...@linaro.org>
>>> >> >> >> >> ---
>>> >> >> >> >> Changes in v5:
>>> >> >> >> >> Reduced the case statements for better code
>>> readability.
>>> >> >> >> Removed
>>> >> >> >> >> unused macro definitions. Modified the tuning
>>> function
>>> >> >> >> prototype
>>> >> >> >> >> and definition to support tuning for both SD and eMMC
>>> >> >> cards.
>>> >> >> >> >> Changes in v4:
>>> >> >> >> >> Rebased onto chris-mmc/mmc-next branch. This patch is
>>> >> >> >> >> successfully
>>> >> >> >> >> applied on commit with id
>>> >> >> >> >> de022ed3fdc14808299b2fa66dbb1ed5ab921912.
>>> >> >> >> >> Changes in v3:
>>> >> >> >> >> In the previous commits of chris-mmc/mmc-next branch,
>>> >> the
>>> >> >> >> patch
>>> >> >> >> >> with
>>> >> >> >> >> commit id (c0f22a2c92e357e7cb3988b0b13034d70b7461f9)
>>> >> >> defines
>>> >> >> >> >> caps2 for
>>> >> >> >> >> more capabilities. This patch version deletes the
>>> member
>>> >> >> >> >> ext_caps(created
>>> >> >> >> >> in my earlier patch) from struct mmc_host and reuses
>>> >> >> already
>>> >> >> >> >> accepted
>>> >> >> >> >> caps2 member.
>>> >> >> >> >> Changes in v2:
>>> >> >> >> >> Rebased to latest chris-mmc/mmc-next branch. Resolved
>>> >> >> >> indentation
>>> >> >> >> >> problems identified in review. This patch has to be
>>> >> applied
>>> >> >> >> >> before
>>> >> >> >> >> the patch released for modifying the printk messages.
>>> >> >> >> >> Changes in v1:
>>> >> >> >> >> Case statements in switch that produce same result
>>> have
>>> >> >> >> >> been combined to reduce repeated assignments.
>>> >> >> >> >> patch recreated after rebase to chris balls mmc-next
>>> >> >> branch.
>>> >> >> >> >>
>>> >> >> >> >> drivers/mmc/core/bus.c | 3 +-
>>> >> >> >> >> drivers/mmc/core/mmc.c | 77
>>> >> >> >> >> ++++++++++++++++++++++++++++++++++++++++----
>>> >> >> >> >> drivers/mmc/core/sd.c | 3 +-
>>> >> >> >> >> drivers/mmc/core/sdio.c | 4 ++-
>>> >> >> >> >> drivers/mmc/host/sdhci.c | 38 +++++++++++++++++-----
>>> >> >> >> >> include/linux/mmc/card.h | 3 ++
>>> >> >> >> >> include/linux/mmc/host.h | 11 ++++++-
>>> >> >> >> >> include/linux/mmc/mmc.h | 66
>>> >> >> >> >> ++++++++++++++++++++++++++++++++++++++-
>>> >> >> >> >> include/linux/mmc/sdhci.h | 1 +
>>> >> >> >> >> 9 files changed, 185 insertions(+), 21 deletions(-)
>>> >> >> >> >>
>>> >> >> >> >> diff --git a/drivers/mmc/core/bus.c
>>> b/drivers/mmc/core/bus.c
>>> >> >> >> >> index 5639fdf..83c9f8d 100644
>>> >> >> >> >> --- a/drivers/mmc/core/bus.c
>>> >> >> >> >> +++ b/drivers/mmc/core/bus.c
>>> >> >> >> >> @@ -301,10 +301,11 @@ int mmc_add_card(struct mmc_card
>>> *card)
>>> >> >> >> >> mmc_card_ddr_mode(card) ? "DDR " :
>>> "",
>>> >> >> >> >> type);
>>> >> >> >> >> } else {
>>> >> >> >> >> - printk(KERN_INFO "%s: new %s%s%s card at
>>> address
>>> >> >> >> %04x\n",
>>> >> >> >> >> + pr_info("%s: new %s%s%s%s card at address
>>> >> %04x\n",
>>> >> >> >> >> mmc_hostname(card->host),
>>> >> >> >> >> mmc_card_uhs(card) ? "ultra high
>>> speed "
>>> >> :
>>> >> >> >> >> (mmc_card_highspeed(card) ? "high
>>> speed
>>> >> " :
>>> >> >> >> ""),
>>> >> >> >> >> + (mmc_card_hs200(card) ? "HS200 " :
>>> ""),
>>> >> >> >> >> mmc_card_ddr_mode(card) ? "DDR " :
>>> "",
>>> >> >> >> >> type, card->rca);
>>> >> >> >> >> }
>>> >> >> >> >> diff --git a/drivers/mmc/core/mmc.c
>>> b/drivers/mmc/core/mmc.c
>>> >> >> >> >> index a1223bd..f4124d6 100644
>>> >> >> >> >> --- a/drivers/mmc/core/mmc.c
>>> >> >> >> >> +++ b/drivers/mmc/core/mmc.c
>>> >> >> >> >> @@ -285,6 +285,27 @@ static int mmc_read_ext_csd(struct
>>> >> mmc_card
>>> >> >> >> *card,
>>> >> >> >> >> u8 *ext_csd)
>>> >> >> >> >> }
>>> >> >> >> >> card->ext_csd.raw_card_type =
>>> >> ext_csd[EXT_CSD_CARD_TYPE];
>>> >> >> >> >> switch (ext_csd[EXT_CSD_CARD_TYPE] &
>>> >> >> EXT_CSD_CARD_TYPE_MASK) {
>>> >> >> >> >> + case EXT_CSD_CARD_TYPE_SDR_ALL:
>>> >> >> >> >> + case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_8V:
>>> >> >> >> >> + case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_2V:
>>> >> >> >> >> + case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_52:
>>> >> >> >> >> + card->ext_csd.hs_max_dtr = 200000000;
>>> >> >> >> >> + card->ext_csd.card_type =
>>> >> >> EXT_CSD_CARD_TYPE_SDR_200;
>>> >> >> >> >> + break;
>>> >> >> >> >> + case EXT_CSD_CARD_TYPE_SDR_1_2V_ALL:
>>> >> >> >> >> + case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_8V:
>>> >> >> >> >> + case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_2V:
>>> >> >> >> >> + case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_52:
>>> >> >> >> >> + card->ext_csd.hs_max_dtr = 200000000;
>>> >> >> >> >> + card->ext_csd.card_type =
>>> >> >> EXT_CSD_CARD_TYPE_SDR_1_2V;
>>> >> >> >> >> + break;
>>> >> >> >> >> + case EXT_CSD_CARD_TYPE_SDR_1_8V_ALL:
>>> >> >> >> >> + case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_8V:
>>> >> >> >> >> + case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_2V:
>>> >> >> >> >> + case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_52:
>>> >> >> >> >> + card->ext_csd.hs_max_dtr = 200000000;
>>> >> >> >> >> + card->ext_csd.card_type =
>>> >> >> EXT_CSD_CARD_TYPE_SDR_1_8V;
>>> >> >> >> >> + break;
>>> >> >> >> >> case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52
>>> |
>>> >> >> >> >> EXT_CSD_CARD_TYPE_26:
>>> >> >> >> >> card->ext_csd.hs_max_dtr = 52000000;
>>> >> >> >> >> @@ -699,6 +720,7 @@ static int mmc_init_card(struct
>>> mmc_host
>>> >> >> *host,
>>> >> >> >> u32
>>> >> >> >> >> ocr,
>>> >> >> >> >> {
>>> >> >> >> >> struct mmc_card *card;
>>> >> >> >> >> int err, ddr = 0;
>>> >> >> >> >> + int hs_sdr = 0;
>>> >> >> >> >> u32 cid[4];
>>> >> >> >> >> unsigned int max_dtr;
>>> >> >> >> >> u32 rocr;
>>> >> >> >> >> @@ -894,11 +916,16 @@ static int mmc_init_card(struct
>>> mmc_host
>>> >> >> >> *host,
>>> >> >> >> >> u32 ocr,
>>> >> >> >> >> /*
>>> >> >> >> >> * Activate high speed (if supported)
>>> >> >> >> >> */
>>> >> >> >> >> - if ((card->ext_csd.hs_max_dtr != 0) &&
>>> >> >> >> >> - (host->caps & MMC_CAP_MMC_HIGHSPEED)) {
>>> >> >> >> >> - err = mmc_switch(card,
>>> EXT_CSD_CMD_SET_NORMAL,
>>> >> >> >> >> - EXT_CSD_HS_TIMING, 1,
>>> >> >> >> >> - card-
>>> >> >ext_csd.generic_cmd6_time);
>>> >> >> >> >> + if (card->ext_csd.hs_max_dtr != 0) {
>>> >> >> >> >> + err = 0;
>>> >> >> >> >> + if ((card->ext_csd.hs_max_dtr > 52000000) &&
>>> >> >> >> >> + (host->caps2 & MMC_CAP2_HS200))
>>> >> >> >> >> + err = mmc_switch(card,
>>> >> >> EXT_CSD_CMD_SET_NORMAL,
>>> >> >> >> >> + EXT_CSD_HS_TIMING,
>>> 2,
>>> >> 0);
>>> >> >> >> >> + else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
>>> >> >> >> >> + err = mmc_switch(card,
>>> >> >> EXT_CSD_CMD_SET_NORMAL,
>>> >> >> >> >> + EXT_CSD_HS_TIMING,
>>> 1,
>>> >> 0);
>>> >> >> >> >> +
>>> >> >> >> >> if (err && err != -EBADMSG)
>>> >> >> >> >> goto free_card;
>>> >> >> >> >>
>>> >> >> >> >> @@ -907,7 +934,11 @@ static int mmc_init_card(struct
>>> mmc_host
>>> >> >> *host,
>>> >> >> >> >> u32 ocr,
>>> >> >> >> >> mmc_hostname(card->host));
>>> >> >> >> >> err = 0;
>>> >> >> >> >> } else {
>>> >> >> >> >> - mmc_card_set_highspeed(card);
>>> >> >> >> >> + if ((card->ext_csd.hs_max_dtr >
>>> >> 52000000)
>>> >> >> &&
>>> >> >> >> >> + (host->caps2 & MMC_CAP2_HS200))
>>> >> >> >> >> + mmc_card_set_hs200(card);
>>> >> >> >> >> + else
>>> >> >> >> >> + mmc_card_set_highspeed(card);
>>> >> >> >> >> mmc_set_timing(card->host,
>>> >> >> MMC_TIMING_MMC_HS);
>>> >> >> >> >
>>> >> >> >> > MMC_TIMING_MMC_HS200 is defined but still not used.
>>> >> >> >> >
>>> >> >> >> > So I guess it should be like this ::
>>> >> >> >> > + if ((card->ext_csd.hs_max_dtr >
>>> >> 52000000)
>>> >> >> &&
>>> >> >> >> > + (host->caps2 & MMC_CAP2_HS200))
>>> {
>>> >> >> >> > + mmc_card_set_hs200(card);
>>> >> >> >> > + mmc_set_timing(card->host,
>>> >> >> >> MMC_TIMING_MMC_HS200)
>>> >> >> >> > + } else {
>>> >> >> >> > +
>>> mmc_card_set_highspeed(card);
>>> >> >> >> > + mmc_set_timing(card->host,
>>> >> >> >> > MMC_TIMING_MMC_HS)
>>> >> >> >> > + }
>>> >> >> >> >
>>> >> >> >> >
>>> >> >> >> >
>>> >> >> >> >
>>> >> >> >> >
>>> >> >> >> >
>>> >> >> >> >
>>> >> >> >> >
>>> >> >> >> >
>>> >> >> >> >
>>> >> >> >> >
>>> >> >> >> >
>>> >> >> >> >
>>> >> >> >> >
>>> >> >> >> >> }
>>> >> >> >> >> }
>>> >> >> >> >> @@ -933,7 +964,7 @@ static int mmc_init_card(struct
>>> mmc_host
>>> >> >> *host,
>>> >> >> >> u32
>>> >> >> >> >> ocr,
>>> >> >> >> >> */
>>> >> >> >> >> max_dtr = (unsigned int)-1;
>>> >> >> >> >>
>>> >> >> >> >> - if (mmc_card_highspeed(card)) {
>>> >> >> >> >> + if (mmc_card_highspeed(card) || mmc_card_hs200(card))
>>> {
>>> >> >> >> >> if (max_dtr > card->ext_csd.hs_max_dtr)
>>> >> >> >> >> max_dtr = card->ext_csd.hs_max_dtr;
>>> >> >> >> >> } else if (max_dtr > card->csd.max_dtr) {
>>> >> >> >> >> @@ -959,6 +990,18 @@ static int mmc_init_card(struct
>>> mmc_host
>>> >> >> *host,
>>> >> >> >> >> u32 ocr,
>>> >> >> >> >> }
>>> >> >> >> >>
>>> >> >> >> >> /*
>>> >> >> >> >> + * Indicate HS200 SDR mode (if supported).
>>> >> >> >> >> + */
>>> >> >> >> >> + if (mmc_card_hs200(card)) {
>>> >> >> >> >> + if ((card->ext_csd.card_type &
>>> >> >> >> EXT_CSD_CARD_TYPE_SDR_1_8V)
>>> >> >> >> >> + && (host->caps2 &
>>> >> MMC_CAP2_HS200_1_8V_SDR))
>>> >> >> >> >> + hs_sdr = MMC_1_8V_SDR_MODE;
>>> >> >> >> >> + else if ((card->ext_csd.card_type &
>>> >> >> >> >> EXT_CSD_CARD_TYPE_SDR_1_2V)
>>> >> >> >> >> + && (host->caps2 &
>>> >> MMC_CAP2_HS200_1_2V_SDR))
>>> >> >> >> >> + hs_sdr = MMC_1_2V_SDR_MODE;
>>> >> >> >> >> + }
>>> >> >> >> >> +
>>> >> >> >> >> + /*
>>> >> >> >> >> * Activate wide bus and DDR (if supported).
>>> >> >> >> >> */
>>> >> >> >> >> if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
>>> >> >> >> >> @@ -998,6 +1041,17 @@ static int mmc_init_card(struct
>>> mmc_host
>>> >> >> >> *host,
>>> >> >> >> >> u32 ocr,
>>> >> >> >> >> if (!err) {
>>> >> >> >> >> mmc_set_bus_width(card->host,
>>> >> >> >> bus_width);
>>> >> >> >> >>
>>> >> >> >> >> + if ((host->caps2 &
>>> >> MMC_CAP2_HS200)
>>> >> >> &&
>>> >> >> >> >> + card->host->ops-
>>> >> >> >execute_tuning)
>>> >> >> >> >> + err = card->host-
>>> >ops->
>>> >> \
>>> >> >> >> >> +
>>> >> execute_tuning(card-
>>> >> >> >> >host,
>>> >> >> >> >> +
>>> >> >> >> > MMC_SEND_TUNING_BLOCK_HS200);
>>> >> >> >> >
>>> >> >> >> >
>>> >> >> >> > execute_tuning should be done right after the timing is
>>> changed
>>> >> to
>>> >> >> >> HS200 and
>>> >> >> >> > clock rate is changed to 200Mhz. This is not the correct
>>> >> sequence
>>> >> >> to
>>> >> >> >> call
>>> >> >> >> > the execute_tuning().
>>> >> >> >> > As told earlier, It is mentioned in the spec that tuning
>>> should
>>> >> be
>>> >> >> >> executed after change of buswidth (mandatory). Also it
>>> mentions
>>> >> that
>>> >> >> >> "The host may invoke the HS200 tuning sequence, by sending
>>> CMD21
>>> >> to
>>> >> >> the
>>> >> >> >> device". It means that
>>> >> >> >> after setting the HS200 mode, Changing to freq > 52Mhz and
>>> >> changing
>>> >> >> >> the bus width tuning can be executed anytime to identify the
>>> >> >> sampling
>>> >> >> >> point to read.(By anytime i mean before actual block read
>>> >> >> Operation).
>>> >> >> >> Can you please point me to the place in the spec where it
>>> >> specifies
>>> >> >> >> tuning should be done immediately after freq change (may be i
>>> >> missed
>>> >> >> >> to read it).
>>> >> >> >
>>> >> >> >
>>> >> >> > Ok. let me ask you this. Why do we run the execute_tuning()?
>>> It's
>>> >> to
>>> >> >> tune
>>> >> >> > the sampling clock generator of host controller before you
>>> start
>>> >> any
>>> >> >> read
>>> >> >> > operation (on command line or data line) from card. If you
>>> don't
>>> >> tune
>>> >> >> the
>>> >> >> > sampling clock generator before the read operation (after
>>> changing
>>> >> >> the
>>> >> >> > timing to HS200 and clock rate to 200mhz), you can't be sure
>>> that
>>> >> >> read
>>> >> >> > operation from card will be completed without errors. You may
>>> get
>>> >> the
>>> >> >> data /
>>> >> >> > cmd response CRC errors. At least this will surely fail on our
>>> MSM
>>> >> >> SDCC host
>>> >> >> > controller. That's what we had faced with SD3.0 UHS-I tuning as
>>> >> well
>>> >> >> as
>>> >> >> > mentioned in http://www.spinics.net/lists/linux-arm-
>>> >> >> msm/msg03867.html.
>>> >> >
>>> >> >> > this tuning is done before any read opration for the best bus
>>> >> width
>>> >> >> supported.
>>> >> > Agreed. But can we be sure that "command response" for bus width
>>> >> change via
>>> >> > CMD6, will not have any command CRC failures if tuning is not
>>> done?
>>> >> All responses are sent on CMD line not on data lines, And sampling
>>> is
>>> >> done for Data lines before reading. So command CRC failure doesnt
>>> >> depend on tuning. If you get error during CMD6 it could be that
>>> device
>>> >> cannot support the bus width at the set frequency.
>>> >
>>> > I guess it's not the correct assumption here. Sampling point tuning
>>> is to
>>> Its Not assumption "Specification says responses are all sent on CMD
>>> only"
>>
>>
>>
>> Where does it say that tuning is not required for data received on command
>> line? If the 200Mhz clock can effect the data received on DATA lines then
>> why it won't affect the data (responses) received on CMD lines?
>> If you still have doubt, I would suggest to get the clarification from
>> JEDEC. From SD3.01 spec, for sure CMD lines also requires tuning.
>>
>> "Sampling clock generation" on our host controller also says that tuning is
>> required for data transfer on both DATA and CMD lines.
>>
>> I am not sure what is the issue with doing the tuning immediately after
>> changing to bus speed mode to HS200 (changing controller timing, changing
>> clock etc ...)? This is what we are doing it for SD3.0 cards as well.
>>
>> Your current implementation is not going to work with all host controllers.
>>
>>
>>
>>
>>
>>
>>> > tune the sampling point for data received on both CMD and DATA lines
>>> (not
>>> > just data lines). I can't find detailed mentioning of this in eMMC4.5
>>> Pls check the section 6.6.7.1. the 2nd paragraph quotes "which in turn
>>> uses it to find the
>>> optimal sampling point for the data lines"
>>> > (that's the documentation short coming, you can even confirm whether
>>> tuning
>>> > procedure is required for CMD line or not from JEDEC) but SD3.01
>>> > specification does mention this tuning procedure in great details.
>>> NOTE:
>>> > eMMC4.5 HS200 mode is mostly inspired from SD3.01 UHS-I bus speed
>>> modes.
>>> >
>>> > Section " 4.2.4.5 Tuning Command" in "SD3.01 - Simplified
>>> >
>>> (Part_1_Physical_Layer_Simplified_Specification_Ver_3.01_Final_100518)"
>>> > specification(can be downloaded from here:
>>> > https://www.sdcard.org/downloads/pls/), clearly states this:
>>> >
>>> > 4.2.4.5 Tuning Command
>>> > CMD19 is defined for Send Tuning Block Command. R1 type response is
>>> defined.
>>> > CMD19 can be
>>> > executed in transfer state of 1.8V signaling mode while the card is
>>> > unlocked. The other case, CMD19 is
>>> > treated as illegal command. Data block, carried by DAT[3:0], contains
>>> a
>>> > pattern for tuning sampling
>>> > position to receive data on the CMD and DAT[3:0] line. The block
>>> length of
>>> > CMD19 is fixed and CMD16
>>> > is not required.
>>> > I have no idea of the SD spec. I have just seen the eMMC spec and
>>> above quotes might answer your doubt
>>> > So before tuning, you may get the Command CRC errors in HS200 mode.
>>> >
>>> > Regards,
>>> > Subhash
>>> >
>>> >> >
>>> >> >> ps:Chris need your comment on this
>>> >> >> >
>>> >> >> >> >> +
>>> >> >> >> >> + if (err) {
>>> >> >> >> >> + pr_warning("tuning
>>> >> >> execution
>>> >> >> >> > failed\n");
>>> >> >> >> >> + continue;
>>> >> >> >> >> + }
>>> >> >> >> >> +
>>> >> >> >> >> /*
>>> >> >> >> >> * If controller can't handle
>>> >> bus
>>> >> >> >> width
>>> >> >> >> > test,
>>> >> >> >> >> * compare ext_csd previously
>>> >> read
>>> >> >> in
>>> >> >> >> 1 bit
>>> >> >> >> >> mode
>>> >> >> >> >> @@ -1056,6 +1110,15 @@ static int mmc_init_card(struct
>>> >> mmc_host
>>> >> >> >> *host,
>>> >> >> >> >> u32 ocr,
>>> >> >> >> >> mmc_card_set_ddr_mode(card);
>>> >> >> >> >> mmc_set_timing(card->host,
>>> >> >> >> MMC_TIMING_UHS_DDR50);
>>> >> >> >> >> mmc_set_bus_width(card->host,
>>> >> bus_width);
>>> >> >> >> >> + } else if (hs_sdr) {
>>> >> >> >> >> + if (hs_sdr ==
>>> >> EXT_CSD_CARD_TYPE_SDR_1_2V) {
>>> >> >> >> >> + err =
>>> >> mmc_set_signal_voltage(host,
>>> >> >> >> >> +
>>> MMC_SIGNAL_VOLTAGE_120,
>>> >> 0);
>>> >> >> >> >> + if (err)
>>> >> >> >> >> + goto err;
>>> >> >> >> >> + }
>>> >> >> >> >> + mmc_set_timing(card->host,
>>> >> >> MMC_TIMING_MMC_HS);
>>> >> >> >> >> + mmc_set_bus_width(card->host,
>>> >> bus_width);
>>> >> >> >> >> }
>>> >> >> >> >> }
>>> >> >> >> >>
>>> >> >> >> >> diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
>>> >> >> >> >> index 1d5a3bd..c1d3ee3 100644
>>> >> >> >> >> --- a/drivers/mmc/core/sd.c
>>> >> >> >> >> +++ b/drivers/mmc/core/sd.c
>>> >> >> >> >> @@ -660,7 +660,8 @@ static int mmc_sd_init_uhs_card(struct
>>> >> >> mmc_card
>>> >> >> >> >> *card)
>>> >> >> >> >>
>>> >> >> >> >> /* SPI mode doesn't define CMD19 */
>>> >> >> >> >> if (!mmc_host_is_spi(card->host) && card->host->ops-
>>> >> >> >> >> >execute_tuning)
>>> >> >> >> >> - err = card->host->ops->execute_tuning(card-
>>> >> >host);
>>> >> >> >> >> + err = card->host->ops->execute_tuning(card-
>>> >> >host,
>>> >> >> >> \
>>> >> >> >> >> +
>>> >> >> >> > MMC_SEND_TUNING_BLOCK);
>>> >> >> >> >>
>>> >> >> >> >> out:
>>> >> >> >> >> kfree(status);
>>> >> >> >> >> diff --git a/drivers/mmc/core/sdio.c
>>> b/drivers/mmc/core/sdio.c
>>> >> >> >> >> index 8c04f7f..8ef8817 100644
>>> >> >> >> >> --- a/drivers/mmc/core/sdio.c
>>> >> >> >> >> +++ b/drivers/mmc/core/sdio.c
>>> >> >> >> >> @@ -14,6 +14,7 @@
>>> >> >> >> >>
>>> >> >> >> >> #include <linux/mmc/host.h>
>>> >> >> >> >> #include <linux/mmc/card.h>
>>> >> >> >> >> +#include <linux/mmc/mmc.h>
>>> >> >> >> >> #include <linux/mmc/sdio.h>
>>> >> >> >> >> #include <linux/mmc/sdio_func.h>
>>> >> >> >> >> #include <linux/mmc/sdio_ids.h>
>>> >> >> >> >> @@ -556,7 +557,8 @@ static int
>>> mmc_sdio_init_uhs_card(struct
>>> >> >> >> mmc_card
>>> >> >> >> >> *card)
>>> >> >> >> >>
>>> >> >> >> >> /* Initialize and start re-tuning timer */
>>> >> >> >> >> if (!mmc_host_is_spi(card->host) && card->host->ops-
>>> >> >> >> >> >execute_tuning)
>>> >> >> >> >> - err = card->host->ops->execute_tuning(card-
>>> >> >host);
>>> >> >> >> >> + err = card->host->ops->execute_tuning(card-
>>> >> >host,
>>> >> >> >> >> +
>>> >> >> >> > MMC_SEND_TUNING_BLOCK);
>>> >> >> >> >>
>>> >> >> >> >> out:
>>> >> >> >> >>
>>> >> >> >> >> diff --git a/drivers/mmc/host/sdhci.c
>>> >> b/drivers/mmc/host/sdhci.c
>>> >> >> >> >> index a7c2311..13d74bb 100644
>>> >> >> >> >> --- a/drivers/mmc/host/sdhci.c
>>> >> >> >> >> +++ b/drivers/mmc/host/sdhci.c
>>> >> >> >> >> @@ -49,7 +49,7 @@ static void sdhci_finish_data(struct
>>> >> sdhci_host
>>> >> >> >> *);
>>> >> >> >> >>
>>> >> >> >> >> static void sdhci_send_command(struct sdhci_host *, struct
>>> >> >> >> mmc_command
>>> >> >> >> >> *);
>>> >> >> >> >> static void sdhci_finish_command(struct sdhci_host *);
>>> >> >> >> >> -static int sdhci_execute_tuning(struct mmc_host *mmc);
>>> >> >> >> >> +static int sdhci_execute_tuning(struct mmc_host *mmc, u32
>>> >> >> opcode);
>>> >> >> >> >> static void sdhci_tuning_timer(unsigned long data);
>>> >> >> >> >>
>>> >> >> >> >> #ifdef CONFIG_PM_RUNTIME
>>> >> >> >> >> @@ -1016,7 +1016,8 @@ static void sdhci_send_command(struct
>>> >> >> >> sdhci_host
>>> >> >> >> >> *host, struct mmc_command *cmd)
>>> >> >> >> >> flags |= SDHCI_CMD_INDEX;
>>> >> >> >> >>
>>> >> >> >> >> /* CMD19 is special in that the Data Present Select
>>> >> should
>>> >> >> be
>>> >> >> >> set
>>> >> >> >> >> */
>>> >> >> >> >> - if (cmd->data || (cmd->opcode ==
>>> MMC_SEND_TUNING_BLOCK))
>>> >> >> >> >> + if (cmd->data || (cmd->opcode ==
>>> MMC_SEND_TUNING_BLOCK)
>>> >> ||
>>> >> >> >> >> + (cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200))
>>> >> >> >> >> flags |= SDHCI_CMD_DATA;
>>> >> >> >> >>
>>> >> >> >> >> sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode,
>>> flags),
>>> >> >> >> >> SDHCI_COMMAND);
>>> >> >> >> >> @@ -1287,7 +1288,7 @@ static void sdhci_request(struct
>>> >> mmc_host
>>> >> >> >> *mmc,
>>> >> >> >> >> struct mmc_request *mrq)
>>> >> >> >> >> if ((host->flags & SDHCI_NEEDS_RETUNING) &&
>>> >> >> >> >> !(present_state & (SDHCI_DOING_WRITE |
>>> >> >> >> >> SDHCI_DOING_READ))) {
>>> >> >> >> >> spin_unlock_irqrestore(&host->lock,
>>> >> flags);
>>> >> >> >> >> - sdhci_execute_tuning(mmc);
>>> >> >> >> >> + sdhci_execute_tuning(mmc, mrq->cmd-
>>> >> >> >opcode);
>>> >> >> >> >> spin_lock_irqsave(&host->lock,
>>> flags);
>>> >> >> >> >>
>>> >> >> >> >> /* Restore original mmc_request
>>> >> structure
>>> >> >> */
>>> >> >> >> >> @@ -1673,7 +1674,7 @@ static int
>>> >> >> >> >> sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>>> >> >> >> >> return err;
>>> >> >> >> >> }
>>> >> >> >> >>
>>> >> >> >> >> -static int sdhci_execute_tuning(struct mmc_host *mmc)
>>> >> >> >> >> +static int sdhci_execute_tuning(struct mmc_host *mmc, u32
>>> >> >> opcode)
>>> >> >> >> >> {
>>> >> >> >> >> struct sdhci_host *host;
>>> >> >> >> >> u16 ctrl;
>>> >> >> >> >> @@ -1694,10 +1695,13 @@ static int
>>> sdhci_execute_tuning(struct
>>> >> >> >> mmc_host
>>> >> >> >> >> *mmc)
>>> >> >> >> >> * Host Controller needs tuning only in case of
>>> SDR104
>>> >> mode
>>> >> >> >> >> * and for SDR50 mode when Use Tuning for SDR50 is
>>> set
>>> >> in
>>> >> >> >> >> * Capabilities register.
>>> >> >> >> >> + * If the Host Controller supports the HS200 mode
>>> then
>>> >> >> tuning
>>> >> >> >> >> + * function has to be executed.
>>> >> >> >> >> */
>>> >> >> >> >> if (((ctrl & SDHCI_CTRL_UHS_MASK) ==
>>> >> SDHCI_CTRL_UHS_SDR104)
>>> >> >> ||
>>> >> >> >> >> (((ctrl & SDHCI_CTRL_UHS_MASK) ==
>>> >> SDHCI_CTRL_UHS_SDR50)
>>> >> >> &&
>>> >> >> >> >> - (host->flags & SDHCI_SDR50_NEEDS_TUNING)))
>>> >> >> >> >> + (host->flags & SDHCI_SDR50_NEEDS_TUNING)) ||
>>> >> >> >> >> + (host->flags & SDHCI_HS200_NEEDS_TUNING))
>>> >> >> >> >> ctrl |= SDHCI_CTRL_EXEC_TUNING;
>>> >> >> >> >> else {
>>> >> >> >> >> spin_unlock(&host->lock);
>>> >> >> >> >> @@ -1733,7 +1737,7 @@ static int
>>> sdhci_execute_tuning(struct
>>> >> >> >> mmc_host
>>> >> >> >> >> *mmc)
>>> >> >> >> >> if (!tuning_loop_counter && !timeout)
>>> >> >> >> >> break;
>>> >> >> >> >>
>>> >> >> >> >> - cmd.opcode = MMC_SEND_TUNING_BLOCK;
>>> >> >> >> >> + cmd.opcode = opcode;
>>> >> >> >> >> cmd.arg = 0;
>>> >> >> >> >> cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
>>> >> >> >> >> cmd.retries = 0;
>>> >> >> >> >> @@ -1748,7 +1752,17 @@ static int
>>> sdhci_execute_tuning(struct
>>> >> >> >> mmc_host
>>> >> >> >> >> *mmc)
>>> >> >> >> >> * block to the Host Controller. So we set
>>> the
>>> >> >> block
>>> >> >> >> size
>>> >> >> >> >> * to 64 here.
>>> >> >> >> >> */
>>> >> >> >> >> - sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64),
>>> >> >> >> >> SDHCI_BLOCK_SIZE);
>>> >> >> >> >> + if (cmd.opcode ==
>>> MMC_SEND_TUNING_BLOCK_HS200) {
>>> >> >> >> >> + if (mmc->ios.bus_width ==
>>> >> MMC_BUS_WIDTH_8)
>>> >> >> >> >> + sdhci_writew(host,
>>> >> >> SDHCI_MAKE_BLKSZ(7,
>>> >> >> >> 128),
>>> >> >> >> >> +
>>> SDHCI_BLOCK_SIZE);
>>> >> >> >> >> + else if (mmc->ios.bus_width ==
>>> >> >> >> MMC_BUS_WIDTH_4)
>>> >> >> >> >> + sdhci_writew(host,
>>> >> >> SDHCI_MAKE_BLKSZ(7,
>>> >> >> >> 64),
>>> >> >> >> >> +
>>> SDHCI_BLOCK_SIZE);
>>> >> >> >> >> + } else {
>>> >> >> >> >> + sdhci_writew(host,
>>> SDHCI_MAKE_BLKSZ(7,
>>> >> 64),
>>> >> >> >> >> + SDHCI_BLOCK_SIZE);
>>> >> >> >> >> + }
>>> >> >> >> >>
>>> >> >> >> >> /*
>>> >> >> >> >> * The tuning block is sent by the card to
>>> the
>>> >> host
>>> >> >> >> >> controller.
>>> >> >> >> >> @@ -2131,12 +2145,14 @@ static void
>>> >> sdhci_show_adma_error(struct
>>> >> >> >> >> sdhci_host *host) { }
>>> >> >> >> >>
>>> >> >> >> >> static void sdhci_data_irq(struct sdhci_host *host, u32
>>> >> intmask)
>>> >> >> >> >> {
>>> >> >> >> >> + u32 command;
>>> >> >> >> >> BUG_ON(intmask == 0);
>>> >> >> >> >>
>>> >> >> >> >> /* CMD19 generates _only_ Buffer Read Ready interrupt
>>> */
>>> >> >> >> >> if (intmask & SDHCI_INT_DATA_AVAIL) {
>>> >> >> >> >> - if (SDHCI_GET_CMD(sdhci_readw(host,
>>> >> SDHCI_COMMAND))
>>> >> >> ==
>>> >> >> >> >> - MMC_SEND_TUNING_BLOCK) {
>>> >> >> >> >> + command = SDHCI_GET_CMD(sdhci_readw(host,
>>> >> >> >> SDHCI_COMMAND));
>>> >> >> >> >> + if ((command == MMC_SEND_TUNING_BLOCK) ||
>>> >> >> >> >> + (command == MMC_SEND_TUNING_BLOCK_HS200))
>>> {
>>> >> >> >> >> host->tuning_done = 1;
>>> >> >> >> >> wake_up(&host->buf_ready_int);
>>> >> >> >> >> return;
>>> >> >> >> >> @@ -2741,6 +2757,10 @@ int sdhci_add_host(struct sdhci_host
>>> >> >> *host)
>>> >> >> >> >> if (caps[1] & SDHCI_USE_SDR50_TUNING)
>>> >> >> >> >> host->flags |= SDHCI_SDR50_NEEDS_TUNING;
>>> >> >> >> >>
>>> >> >> >> >> + /* Does the host needs tuning for HS200? */
>>> >> >> >> >> + if (mmc->caps2 & MMC_CAP2_HS200)
>>> >> >> >> >> + host->flags |= SDHCI_HS200_NEEDS_TUNING;
>>> >> >> >> >> +
>>> >> >> >> >> /* Driver Type(s) (A, C, D) supported by the host */
>>> >> >> >> >> if (caps[1] & SDHCI_DRIVER_TYPE_A)
>>> >> >> >> >> mmc->caps |= MMC_CAP_DRIVER_TYPE_A;
>>> >> >> >> >> diff --git a/include/linux/mmc/card.h
>>> >> b/include/linux/mmc/card.h
>>> >> >> >> >> index 534974c..e76f649 100644
>>> >> >> >> >> --- a/include/linux/mmc/card.h
>>> >> >> >> >> +++ b/include/linux/mmc/card.h
>>> >> >> >> >> @@ -209,6 +209,7 @@ struct mmc_card {
>>> >> >> >> >> #define MMC_STATE_HIGHSPEED_DDR (1<<4) /*
>>> card
>>> >> is
>>> >> >> in
>>> >> >> >> high
>>> >> >> >> >> speed mode */
>>> >> >> >> >> #define MMC_STATE_ULTRAHIGHSPEED (1<<5) /*
>>> card
>>> >> is
>>> >> >> in
>>> >> >> >> ultra
>>> >> >> >> >> high speed mode */
>>> >> >> >> >> #define MMC_CARD_SDXC (1<<6) /*
>>> card
>>> >> is
>>> >> >> >> SDXC */
>>> >> >> >> >> +#define MMC_STATE_HIGHSPEED_200 (1<<7) /* card is in
>>> >> HS200
>>> >> >> >> >> mode */
>>> >> >> >> >> unsigned int quirks; /* card
>>> quirks
>>> >> */
>>> >> >> >> >> #define MMC_QUIRK_LENIENT_FN0 (1<<0) /*
>>> allow
>>> >> >> SDIO
>>> >> >> >> FN0
>>> >> >> >> >> writes outside of the VS CCCR range */
>>> >> >> >> >> #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func-
>>> >> >> >> >> >cur_blksize */
>>> >> >> >> >> @@ -365,6 +366,7 @@ static inline void __maybe_unused
>>> >> >> >> >> remove_quirk(struct mmc_card *card, int data)
>>> >> >> >> >> #define mmc_card_present(c) ((c)->state &
>>> MMC_STATE_PRESENT)
>>> >> >> >> >> #define mmc_card_readonly(c) ((c)->state &
>>> >> MMC_STATE_READONLY)
>>> >> >> >> >> #define mmc_card_highspeed(c) ((c)->state &
>>> >> >> >> MMC_STATE_HIGHSPEED)
>>> >> >> >> >> +#define mmc_card_hs200(c) ((c)->state &
>>> >> >> MMC_STATE_HIGHSPEED_200)
>>> >> >> >> >> #define mmc_card_blockaddr(c) ((c)->state &
>>> >> >> >> MMC_STATE_BLOCKADDR)
>>> >> >> >> >> #define mmc_card_ddr_mode(c) ((c)->state &
>>> >> >> MMC_STATE_HIGHSPEED_DDR)
>>> >> >> >> >> #define mmc_card_uhs(c) ((c)->state &
>>> >> >> >> >> MMC_STATE_ULTRAHIGHSPEED)
>>> >> >> >> >> @@ -374,6 +376,7 @@ static inline void __maybe_unused
>>> >> >> >> >> remove_quirk(struct mmc_card *card, int data)
>>> >> >> >> >> #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_highspeed(c) ((c)->state |=
>>> >> >> >> MMC_STATE_HIGHSPEED)
>>> >> >> >> >> +#define mmc_card_set_hs200(c) ((c)->state |=
>>> >> >> >> >> MMC_STATE_HIGHSPEED_200)
>>> >> >> >> >> #define mmc_card_set_blockaddr(c) ((c)->state |=
>>> >> >> >> MMC_STATE_BLOCKADDR)
>>> >> >> >> >> #define mmc_card_set_ddr_mode(c) ((c)->state |=
>>> >> >> >> >> MMC_STATE_HIGHSPEED_DDR)
>>> >> >> >> >> #define mmc_card_set_uhs(c) ((c)->state |=
>>> >> >> >> MMC_STATE_ULTRAHIGHSPEED)
>>> >> >> >> >> diff --git a/include/linux/mmc/host.h
>>> >> b/include/linux/mmc/host.h
>>> >> >> >> >> index 706f722..5eac57a 100644
>>> >> >> >> >> --- a/include/linux/mmc/host.h
>>> >> >> >> >> +++ b/include/linux/mmc/host.h
>>> >> >> >> >> @@ -50,6 +50,7 @@ struct mmc_ios {
>>> >> >> >> >>
>>> >> >> >> >> #define MMC_TIMING_LEGACY 0
>>> >> >> >> >> #define MMC_TIMING_MMC_HS 1
>>> >> >> >> >> +#define MMC_TIMING_MMC_HS200 2
>>> >> >> >> >> #define MMC_TIMING_SD_HS 2
>>> >> >> >> >> #define MMC_TIMING_UHS_SDR12 MMC_TIMING_LEGACY
>>> >> >> >> >> #define MMC_TIMING_UHS_SDR25 MMC_TIMING_SD_HS
>>> >> >> >> >> @@ -60,6 +61,8 @@ struct mmc_ios {
>>> >> >> >> >> #define MMC_SDR_MODE 0
>>> >> >> >> >> #define MMC_1_2V_DDR_MODE 1
>>> >> >> >> >> #define MMC_1_8V_DDR_MODE 2
>>> >> >> >> >> +#define MMC_1_2V_SDR_MODE 3
>>> >> >> >> >> +#define MMC_1_8V_SDR_MODE 4
>>> >> >> >> >>
>>> >> >> >> >> unsigned char signal_voltage; /* signalling
>>> >> >> voltage
>>> >> >> >> >> (1.8V or 3.3V) */
>>> >> >> >> >>
>>> >> >> >> >> @@ -148,7 +151,9 @@ struct mmc_host_ops {
>>> >> >> >> >> void (*init_card)(struct mmc_host *host, struct
>>> >> mmc_card
>>> >> >> >> *card);
>>> >> >> >> >>
>>> >> >> >> >> int (*start_signal_voltage_switch)(struct
>>> mmc_host
>>> >> >> *host,
>>> >> >> >> >> struct mmc_ios *ios);
>>> >> >> >> >> - int (*execute_tuning)(struct mmc_host *host);
>>> >> >> >> >> +
>>> >> >> >> >> + /* The tuning command opcode value is different for
>>> SD
>>> >> and
>>> >> >> >> eMMC
>>> >> >> >> >> cards */
>>> >> >> >> >> + int (*execute_tuning)(struct mmc_host *host, u32
>>> >> >> opcode);
>>> >> >> >> >> void (*enable_preset_value)(struct mmc_host *host,
>>> >> bool
>>> >> >> >> enable);
>>> >> >> >> >> int (*select_drive_strength)(unsigned int
>>> max_dtr,
>>> >> int
>>> >> >> >> >> host_drv, int card_drv);
>>> >> >> >> >> void (*hw_reset)(struct mmc_host *host);
>>> >> >> >> >> @@ -242,6 +247,10 @@ struct mmc_host {
>>> >> >> >> >> #define MMC_CAP2_CACHE_CTRL (1 << 1) /* Allow
>>> cache
>>> >> >> control
>>> >> >> >> */
>>> >> >> >> >> #define MMC_CAP2_POWEROFF_NOTIFY (1 << 2) /* Notify
>>> >> poweroff
>>> >> >> >> >> supported */
>>> >> >> >> >> #define MMC_CAP2_NO_MULTI_READ (1 << 3) /*
>>> >> >> Multiblock
>>> >> >> >> reads
>>> >> >> >> >> don't work */
>>> >> >> >> >> +#define MMC_CAP2_HS200_1_8V_SDR (1 << 4) /*
>>> can
>>> >> >> support
>>> >> >> >> */
>>> >> >> >> >> +#define MMC_CAP2_HS200_1_2V_SDR (1 << 5) /*
>>> can
>>> >> >> support
>>> >> >> >> */
>>> >> >> >> >> +#define MMC_CAP2_HS200
>>> (MMC_CAP2_HS200_1_8V_SDR
>>> >> |
>>> >> >> \
>>> >> >> >> >> + MMC_CAP2_HS200_1_2V_SDR)
>>> >> >> >> >>
>>> >> >> >> >> mmc_pm_flag_t pm_caps; /* supported
>>> pm
>>> >> >> >> features */
>>> >> >> >> >> unsigned int power_notify_type;
>>> >> >> >> >> diff --git a/include/linux/mmc/mmc.h
>>> b/include/linux/mmc/mmc.h
>>> >> >> >> >> index 0e71356..7996272 100644
>>> >> >> >> >> --- a/include/linux/mmc/mmc.h
>>> >> >> >> >> +++ b/include/linux/mmc/mmc.h
>>> >> >> >> >> @@ -51,6 +51,7 @@
>>> >> >> >> >> #define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data
>>> >> addr
>>> >> >> R1
>>> >> >> >> >> */
>>> >> >> >> >> #define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data
>>> >> addr
>>> >> >> R1
>>> >> >> >> >> */
>>> >> >> >> >> #define MMC_SEND_TUNING_BLOCK 19 /* adtc
>>> >> >> R1
>>> >> >> >> >> */
>>> >> >> >> >> +#define MMC_SEND_TUNING_BLOCK_HS200 21 /* adtc R1
>>> */
>>> >> >> >> >>
>>> >> >> >> >> /* class 3 */
>>> >> >> >> >> #define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data
>>> >> addr
>>> >> >> R1
>>> >> >> >> >> */
>>> >> >> >> >> @@ -333,13 +334,76 @@ struct _mmc_csd {
>>> >> >> >> >>
>>> >> >> >> >> #define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at
>>> 26MHz
>>> >> */
>>> >> >> >> >> #define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at
>>> 52MHz
>>> >> */
>>> >> >> >> >> -#define EXT_CSD_CARD_TYPE_MASK 0xF /* Mask out
>>> >> >> reserved
>>> >> >> >> bits */
>>> >> >> >> >> +#define EXT_CSD_CARD_TYPE_MASK 0x3F /* Mask out
>>> >> >> reserved
>>> >> >> >> bits */
>>> >> >> >> >> #define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can
>>> run
>>> >> at
>>> >> >> >> 52MHz
>>> >> >> >> >> */
>>> >> >> >> >> /* DDR mode
>>> @1.8V
>>> >> or
>>> >> >> 3V
>>> >> >> >> I/O */
>>> >> >> >> >> #define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can
>>> run
>>> >> at
>>> >> >> >> 52MHz
>>> >> >> >> >> */
>>> >> >> >> >> /* DDR mode
>>> @1.2V
>>> >> I/O
>>> >> >> */
>>> >> >> >> >> #define EXT_CSD_CARD_TYPE_DDR_52
>>> >> >> (EXT_CSD_CARD_TYPE_DDR_1_8V
>>> >> >> >> \
>>> >> >> >> >> |
>>> >> >> EXT_CSD_CARD_TYPE_DDR_1_2V)
>>> >> >> >> >> +#define EXT_CSD_CARD_TYPE_SDR_1_8V (1<<4) /* Card can
>>> run
>>> >> at
>>> >> >> >> >> 200MHz */
>>> >> >> >> >> +#define EXT_CSD_CARD_TYPE_SDR_1_2V (1<<5) /* Card can
>>> run
>>> >> at
>>> >> >> >> >> 200MHz */
>>> >> >> >> >> + /* SDR mode
>>> >> @1.2V
>>> >> >> I/O
>>> >> >> >> */
>>> >> >> >> >> +
>>> >> >> >> >> +#define EXT_CSD_CARD_TYPE_SDR_200
>>> >> (EXT_CSD_CARD_TYPE_SDR_1_8V
>>> >> >> >> \
>>> >> >> >> >> + |
>>> >> >> EXT_CSD_CARD_TYPE_SDR_1_2V)
>>> >> >> >> >> +
>>> >> >> >> >> +#define EXT_CSD_CARD_TYPE_SDR_ALL
>>> >> (EXT_CSD_CARD_TYPE_SDR_200
>>> >> >> >> \
>>> >> >> >> >> + |
>>> EXT_CSD_CARD_TYPE_52
>>> >> >> >> \
>>> >> >> >> >> + |
>>> EXT_CSD_CARD_TYPE_26)
>>> >> >> >> >> +
>>> >> >> >> >> +#define EXT_CSD_CARD_TYPE_SDR_1_2V_ALL
>>> >> >> >> >> (EXT_CSD_CARD_TYPE_SDR_1_2V \
>>> >> >> >> >> + |
>>> EXT_CSD_CARD_TYPE_52
>>> >> >> >> \
>>> >> >> >> >> + |
>>> EXT_CSD_CARD_TYPE_26)
>>> >> >> >> >> +
>>> >> >> >> >> +#define EXT_CSD_CARD_TYPE_SDR_1_8V_ALL
>>> >> >> >> >> (EXT_CSD_CARD_TYPE_SDR_1_8V \
>>> >> >> >> >> + |
>>> EXT_CSD_CARD_TYPE_52
>>> >> >> >> \
>>> >> >> >> >> + |
>>> EXT_CSD_CARD_TYPE_26)
>>> >> >> >> >> +
>>> >> >> >> >> +#define EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_8V
>>> >> >> >> >> (EXT_CSD_CARD_TYPE_SDR_1_2V \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_DDR_1_8V
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> EXT_CSD_CARD_TYPE_52
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_26)
>>> >> >> >> >> +
>>> >> >> >> >> +#define EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_8V
>>> >> >> >> >> (EXT_CSD_CARD_TYPE_SDR_1_8V \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_DDR_1_8V
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> EXT_CSD_CARD_TYPE_52
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_26)
>>> >> >> >> >> +
>>> >> >> >> >> +#define EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_2V
>>> >> >> >> >> (EXT_CSD_CARD_TYPE_SDR_1_2V \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_DDR_1_2V
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> EXT_CSD_CARD_TYPE_52
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_26)
>>> >> >> >> >> +
>>> >> >> >> >> +#define EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_2V
>>> >> >> >> >> (EXT_CSD_CARD_TYPE_SDR_1_8V \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_DDR_1_2V
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> EXT_CSD_CARD_TYPE_52
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_26)
>>> >> >> >> >> +
>>> >> >> >> >> +#define EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_52
>>> >> >> >> >> (EXT_CSD_CARD_TYPE_SDR_1_2V \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_DDR_52
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> EXT_CSD_CARD_TYPE_52
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_26)
>>> >> >> >> >> +
>>> >> >> >> >> +#define EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_52
>>> >> >> >> >> (EXT_CSD_CARD_TYPE_SDR_1_8V \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_DDR_52
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> EXT_CSD_CARD_TYPE_52
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_26)
>>> >> >> >> >> +
>>> >> >> >> >> +#define EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_8V
>>> >> >> >> >> (EXT_CSD_CARD_TYPE_SDR_200 \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_DDR_1_8V
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> EXT_CSD_CARD_TYPE_52
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_26)
>>> >> >> >> >> +
>>> >> >> >> >> +#define EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_2V
>>> >> >> >> >> (EXT_CSD_CARD_TYPE_SDR_200 \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_DDR_1_2V
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> EXT_CSD_CARD_TYPE_52
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_26)
>>> >> >> >> >> +
>>> >> >> >> >> +#define EXT_CSD_CARD_TYPE_SDR_ALL_DDR_52
>>> >> >> >> (EXT_CSD_CARD_TYPE_SDR_200
>>> >> >> >> >> \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_DDR_52
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> EXT_CSD_CARD_TYPE_52
>>> >> >> >> > \
>>> >> >> >> >> + |
>>> >> >> >> EXT_CSD_CARD_TYPE_26)
>>> >> >> >> >>
>>> >> >> >> >> #define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit
>>> mode
>>> >> */
>>> >> >> >> >> #define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit
>>> mode
>>> >> */
>>> >> >> >> >> diff --git a/include/linux/mmc/sdhci.h
>>> >> >> b/include/linux/mmc/sdhci.h
>>> >> >> >> >> index e4b6935..d9a2222 100644
>>> >> >> >> >> --- a/include/linux/mmc/sdhci.h
>>> >> >> >> >> +++ b/include/linux/mmc/sdhci.h
>>> >> >> >> >> @@ -121,6 +121,7 @@ struct sdhci_host {
>>> >> >> >> >> #define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support
>>> */
>>> >> >> >> >> #define SDHCI_PV_ENABLED (1<<8) /* Preset value
>>> enabled
>>> >> */
>>> >> >> >> >> #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq
>>> >> enabled
>>> >> >> */
>>> >> >> >> >> +#define SDHCI_HS200_NEEDS_TUNING (1<<10) /* HS200
>>> needs
>>> >> >> tuning
>>> >> >> >> */
>>> >> >> >> >>
>>> >> >> >> >> unsigned int version; /* SDHCI spec. version */
>>> >> >> >> >>
>>> >> >> >> >> --
>>> >> >> >> >> 1.7.1
>>> >> >> >> >>
>>> >> >> >> >> --
>>> >> >> >> >> To unsubscribe from this list: send the line "unsubscribe
>>> >> linux-
>>> >> >> mmc"
>>> >> >> >> in
>>> >> >> >> >> the body of a message to majord...@vger.kernel.org
>>> >> >> >> >> More majordomo info at http://vger.kernel.org/majordomo-
>>> >> >> info.html
>>> >> >> >> >
>>> >> >> >> > --
>>> >> >> >> > To unsubscribe from this list: send the line "unsubscribe
>>> >> linux-
>>> >> >> mmc"
>>> >> >> >> in
>>> >> >> >> > the body of a message to majord...@vger.kernel.org
>>> >> >> >> > More majordomo info at http://vger.kernel.org/majordomo-
>>> >> info.html
>>> >> >> >> >
>>> >> >> >> --
>>> >> >> >> To unsubscribe from this list: send the line "unsubscribe
>>> linux-
>>> >> mmc"
>>> >> >> in
>>> >> >> >> the body of a message to majord...@vger.kernel.org
>>> >> >> >> More majordomo info at http://vger.kernel.org/majordomo-
>>> >> info.html
>>> >> >> >
>>> >> >> --
>>> >> >> To unsubscribe from this list: send the line "unsubscribe linux-
>>> mmc"
>>> >> in
>>> >> >> the body of a message to majord...@vger.kernel.org
>>> >> >> More majordomo info at http://vger.kernel.org/majordomo-
>>> info.html
>>> >> >
>>> >
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> the body of a message to majord...@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html