Re: [PATCH V5] mmc: core: HS200 mode support for eMMC 4.5

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.
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


[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux