On 12 December 2011 12:20, Girish K S <girish.shivananjappa@xxxxxxxxxx> wrote: > 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. >> >> We need to have the tuning done (execute_tuning) soon after switching >> to HS200 mode and 200MHz clock. >> > If i make a change as per subhash suggestion"set bus width before > setting the HS200 mode." then it will affect the entire frame work of > mmc which is developed as per Annexure A6.1 A.6.2 A.6.3 (mentions the > steps for bus initialization). can any of you suggest a way to do > this. Any inputs on this >> >> 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-samsung-soc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html