On 5 December 2011 20:29, Saugata Das <saugata.das@xxxxxxxxxx> 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 <subhashj@xxxxxxxxxxxxxx> wrote: >> >> >>> -----Original Message----- >>> From: Girish K S [mailto:girish.shivananjappa@xxxxxxxxxx] >>> Sent: Monday, December 05, 2011 12:20 PM >>> To: Subhash Jadavani >>> Cc: linux-mmc@xxxxxxxxxxxxxxx; patches@xxxxxxxxxx; linux-samsung- >>> soc@xxxxxxxxxxxxxxx; Chris Ball >>> Subject: Re: [PATCH V5] mmc: core: HS200 mode support for eMMC 4.5 >>> >>> On 5 December 2011 11:46, Subhash Jadavani <subhashj@xxxxxxxxxxxxxx> >>> wrote: >>> > >>> > >>> >> -----Original Message----- >>> >> From: Girish K S [mailto:girish.shivananjappa@xxxxxxxxxx] >>> >> Sent: Friday, December 02, 2011 5:08 PM >>> >> To: Subhash Jadavani >>> >> Cc: linux-mmc@xxxxxxxxxxxxxxx; patches@xxxxxxxxxx; linux-samsung- >>> >> soc@xxxxxxxxxxxxxxx; Chris Ball >>> >> Subject: Re: [PATCH V5] mmc: core: HS200 mode support for eMMC 4.5 >>> >> >>> >> On 2 December 2011 00:02, Subhash Jadavani <subhashj@xxxxxxxxxxxxxx> >>> >> wrote: >>> >> > >>> >> > >>> >> >> -----Original Message----- >>> >> >> From: linux-mmc-owner@xxxxxxxxxxxxxxx [mailto:linux-mmc- >>> >> >> owner@xxxxxxxxxxxxxxx] On Behalf Of Girish K S >>> >> >> Sent: Thursday, December 01, 2011 7:48 PM >>> >> >> To: Subhash Jadavani >>> >> >> Cc: linux-mmc@xxxxxxxxxxxxxxx; patches@xxxxxxxxxx; linux-samsung- >>> >> >> soc@xxxxxxxxxxxxxxx; Chris Ball >>> >> >> Subject: Re: [PATCH V5] mmc: core: HS200 mode support for eMMC >>> 4.5 >>> >> >> >>> >> >> On 1 December 2011 16:27, Subhash Jadavani >>> <subhashj@xxxxxxxxxxxxxx> >>> >> >> wrote: >>> >> >> > >>> >> >> > >>> >> >> >> -----Original Message----- >>> >> >> >> From: linux-mmc-owner@xxxxxxxxxxxxxxx [mailto:linux-mmc- >>> >> >> >> owner@xxxxxxxxxxxxxxx] On Behalf Of Girish K S >>> >> >> >> Sent: Thursday, December 01, 2011 3:58 PM >>> >> >> >> To: Subhash Jadavani >>> >> >> >> Cc: linux-mmc@xxxxxxxxxxxxxxx; patches@xxxxxxxxxx; linux- >>> samsung- >>> >> >> >> soc@xxxxxxxxxxxxxxx; Chris Ball >>> >> >> >> Subject: Re: [PATCH V5] mmc: core: HS200 mode support for eMMC >>> >> 4.5 >>> >> >> >> >>> >> >> >> On 1 December 2011 15:33, Subhash Jadavani >>> >> <subhashj@xxxxxxxxxxxxxx> >>> >> >> >> wrote: >>> >> >> >> > Hi Girish, >>> >> >> >> > >>> >> >> >> >> -----Original Message----- >>> >> >> >> >> From: linux-mmc-owner@xxxxxxxxxxxxxxx [mailto:linux-mmc- >>> >> >> >> >> owner@xxxxxxxxxxxxxxx] On Behalf Of Girish K S >>> >> >> >> >> Sent: Wednesday, November 30, 2011 2:24 PM >>> >> >> >> >> To: linux-mmc@xxxxxxxxxxxxxxx >>> >> >> >> >> Cc: patches@xxxxxxxxxx; linux-samsung-soc@xxxxxxxxxxxxxxx; >>> >> >> >> >> subhashj@xxxxxxxxxxxxxx; 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 <cjb@xxxxxxxxxx> >>> >> >> >> >> Signed-off-by: Girish K S <girish.shivananjappa@xxxxxxxxxx> >>> >> >> >> >> --- >>> >> >> >> >> 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 majordomo@xxxxxxxxxxxxxxx >>> >> >> >> >> 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 majordomo@xxxxxxxxxxxxxxx >>> >> >> >> > 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 majordomo@xxxxxxxxxxxxxxx >>> >> >> >> 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 majordomo@xxxxxxxxxxxxxxx >>> >> >> 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 majordomo@xxxxxxxxxxxxxxx >> 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html