On 1 December 2011 15:33, Subhash Jadavani <subha...@codeaurora.org> wrote:
> Hi Girish,
>
>> -----Original Message-----
>> From: linux-mmc-ow...@vger.kernel.org [mailto:linux-mmc-
>> ow...@vger.kernel.org] On Behalf Of Girish K S
>> Sent: Wednesday, November 30, 2011 2:24 PM
>> To: linux-mmc@vger.kernel.org
>> Cc: patc...@linaro.org; linux-samsung-...@vger.kernel.org;
>> subha...@codeaurora.org; Girish K S; Chris Ball
>> Subject: [PATCH V5] mmc: core: HS200 mode support for eMMC 4.5
>>
>> This patch adds the support of the HS200 bus speed for eMMC 4.5
>> devices.
>> The eMMC 4.5 devices have support for 200MHz bus speed.The mmc core and
>> host modules have been touched to add support for this module.
>>
>> It is necessary to know the card type in the sdhci.c file to add
>> support
>> for eMMC tuning function. So card.h file is included to import the card
>> data structure.
>>
>> cc: Chris Ball <c...@laptop.org>
>> Signed-off-by: Girish K S <girish.shivananja...@linaro.org>
>> ---
>> Changes in v5:
>> Reduced the case statements for better code readability. Removed
>> unused macro definitions. Modified the tuning function prototype
>> and definition to support tuning for both SD and eMMC cards.
>> Changes in v4:
>> Rebased onto chris-mmc/mmc-next branch. This patch is
>> successfully
>> applied on commit with id
>> de022ed3fdc14808299b2fa66dbb1ed5ab921912.
>> Changes in v3:
>> In the previous commits of chris-mmc/mmc-next branch, the patch
>> with
>> commit id (c0f22a2c92e357e7cb3988b0b13034d70b7461f9) defines
>> caps2 for
>> more capabilities. This patch version deletes the member
>> ext_caps(created
>> in my earlier patch) from struct mmc_host and reuses already
>> accepted
>> caps2 member.
>> Changes in v2:
>> Rebased to latest chris-mmc/mmc-next branch. Resolved indentation
>> problems identified in review. This patch has to be applied
>> before
>> the patch released for modifying the printk messages.
>> Changes in v1:
>> Case statements in switch that produce same result have
>> been combined to reduce repeated assignments.
>> patch recreated after rebase to chris balls mmc-next branch.
>>
>> drivers/mmc/core/bus.c | 3 +-
>> drivers/mmc/core/mmc.c | 77
>> ++++++++++++++++++++++++++++++++++++++++----
>> drivers/mmc/core/sd.c | 3 +-
>> drivers/mmc/core/sdio.c | 4 ++-
>> drivers/mmc/host/sdhci.c | 38 +++++++++++++++++-----
>> include/linux/mmc/card.h | 3 ++
>> include/linux/mmc/host.h | 11 ++++++-
>> include/linux/mmc/mmc.h | 66
>> ++++++++++++++++++++++++++++++++++++++-
>> include/linux/mmc/sdhci.h | 1 +
>> 9 files changed, 185 insertions(+), 21 deletions(-)
>>
>> diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
>> index 5639fdf..83c9f8d 100644
>> --- a/drivers/mmc/core/bus.c
>> +++ b/drivers/mmc/core/bus.c
>> @@ -301,10 +301,11 @@ int mmc_add_card(struct mmc_card *card)
>> mmc_card_ddr_mode(card) ? "DDR " : "",
>> type);
>> } else {
>> - printk(KERN_INFO "%s: new %s%s%s card at address %04x\n",
>> + pr_info("%s: new %s%s%s%s card at address %04x\n",
>> mmc_hostname(card->host),
>> mmc_card_uhs(card) ? "ultra high speed " :
>> (mmc_card_highspeed(card) ? "high speed " : ""),
>> + (mmc_card_hs200(card) ? "HS200 " : ""),
>> mmc_card_ddr_mode(card) ? "DDR " : "",
>> type, card->rca);
>> }
>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
>> index a1223bd..f4124d6 100644
>> --- a/drivers/mmc/core/mmc.c
>> +++ b/drivers/mmc/core/mmc.c
>> @@ -285,6 +285,27 @@ static int mmc_read_ext_csd(struct mmc_card *card,
>> u8 *ext_csd)
>> }
>> card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE];
>> switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) {
>> + case EXT_CSD_CARD_TYPE_SDR_ALL:
>> + case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_8V:
>> + case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_2V:
>> + case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_52:
>> + card->ext_csd.hs_max_dtr = 200000000;
>> + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_200;
>> + break;
>> + case EXT_CSD_CARD_TYPE_SDR_1_2V_ALL:
>> + case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_8V:
>> + case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_2V:
>> + case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_52:
>> + card->ext_csd.hs_max_dtr = 200000000;
>> + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_2V;
>> + break;
>> + case EXT_CSD_CARD_TYPE_SDR_1_8V_ALL:
>> + case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_8V:
>> + case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_2V:
>> + case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_52:
>> + card->ext_csd.hs_max_dtr = 200000000;
>> + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_8V;
>> + break;
>> case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 |
>> EXT_CSD_CARD_TYPE_26:
>> card->ext_csd.hs_max_dtr = 52000000;
>> @@ -699,6 +720,7 @@ static int mmc_init_card(struct mmc_host *host, u32
>> ocr,
>> {
>> struct mmc_card *card;
>> int err, ddr = 0;
>> + int hs_sdr = 0;
>> u32 cid[4];
>> unsigned int max_dtr;
>> u32 rocr;
>> @@ -894,11 +916,16 @@ static int mmc_init_card(struct mmc_host *host,
>> u32 ocr,
>> /*
>> * Activate high speed (if supported)
>> */
>> - if ((card->ext_csd.hs_max_dtr != 0) &&
>> - (host->caps & MMC_CAP_MMC_HIGHSPEED)) {
>> - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>> - EXT_CSD_HS_TIMING, 1,
>> - card->ext_csd.generic_cmd6_time);
>> + if (card->ext_csd.hs_max_dtr != 0) {
>> + err = 0;
>> + if ((card->ext_csd.hs_max_dtr > 52000000) &&
>> + (host->caps2 & MMC_CAP2_HS200))
>> + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>> + EXT_CSD_HS_TIMING, 2, 0);
>> + else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
>> + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>> + EXT_CSD_HS_TIMING, 1, 0);
>> +
>> if (err && err != -EBADMSG)
>> goto free_card;
>>
>> @@ -907,7 +934,11 @@ static int mmc_init_card(struct mmc_host *host,
>> u32 ocr,
>> mmc_hostname(card->host));
>> err = 0;
>> } else {
>> - mmc_card_set_highspeed(card);
>> + if ((card->ext_csd.hs_max_dtr > 52000000) &&
>> + (host->caps2 & MMC_CAP2_HS200))
>> + mmc_card_set_hs200(card);
>> + else
>> + mmc_card_set_highspeed(card);
>> mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
>
> MMC_TIMING_MMC_HS200 is defined but still not used.
>
> So I guess it should be like this ::
> + if ((card->ext_csd.hs_max_dtr > 52000000) &&
> + (host->caps2 & MMC_CAP2_HS200)) {
> + mmc_card_set_hs200(card);
> + mmc_set_timing(card->host, MMC_TIMING_MMC_HS200)
> + } else {
> + mmc_card_set_highspeed(card);
> + mmc_set_timing(card->host,
> MMC_TIMING_MMC_HS)
> + }
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>> }
>> }
>> @@ -933,7 +964,7 @@ static int mmc_init_card(struct mmc_host *host, u32
>> ocr,
>> */
>> max_dtr = (unsigned int)-1;
>>
>> - if (mmc_card_highspeed(card)) {
>> + if (mmc_card_highspeed(card) || mmc_card_hs200(card)) {
>> if (max_dtr > card->ext_csd.hs_max_dtr)
>> max_dtr = card->ext_csd.hs_max_dtr;
>> } else if (max_dtr > card->csd.max_dtr) {
>> @@ -959,6 +990,18 @@ static int mmc_init_card(struct mmc_host *host,
>> u32 ocr,
>> }
>>
>> /*
>> + * Indicate HS200 SDR mode (if supported).
>> + */
>> + if (mmc_card_hs200(card)) {
>> + if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V)
>> + && (host->caps2 & MMC_CAP2_HS200_1_8V_SDR))
>> + hs_sdr = MMC_1_8V_SDR_MODE;
>> + else if ((card->ext_csd.card_type &
>> EXT_CSD_CARD_TYPE_SDR_1_2V)
>> + && (host->caps2 & MMC_CAP2_HS200_1_2V_SDR))
>> + hs_sdr = MMC_1_2V_SDR_MODE;
>> + }
>> +
>> + /*
>> * Activate wide bus and DDR (if supported).
>> */
>> if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
>> @@ -998,6 +1041,17 @@ static int mmc_init_card(struct mmc_host *host,
>> u32 ocr,
>> if (!err) {
>> mmc_set_bus_width(card->host, bus_width);
>>
>> + if ((host->caps2 & MMC_CAP2_HS200) &&
>> + card->host->ops->execute_tuning)
>> + err = card->host->ops-> \
>> + execute_tuning(card->host,
>> +
> MMC_SEND_TUNING_BLOCK_HS200);
>
>
> execute_tuning should be done right after the timing is changed to HS200 and
> clock rate is changed to 200Mhz. This is not the correct sequence to call
> the execute_tuning().
> As told earlier, It is mentioned in the spec that tuning should be executed
> after change of buswidth (mandatory). Also it mentions that "The host may
> invoke the HS200 tuning sequence, by sending CMD21 to the device". It means
> that
after setting the HS200 mode, Changing to freq > 52Mhz and changing
the bus width tuning can be executed anytime to identify the sampling
point to read.(By anytime i mean before actual block read Operation).
Can you please point me to the place in the spec where it specifies
tuning should be done immediately after freq change (may be i missed
to read it).
>> +
>> + if (err) {
>> + pr_warning("tuning execution
> failed\n");
>> + continue;
>> + }
>> +
>> /*
>> * If controller can't handle bus width
> test,
>> * compare ext_csd previously read in 1 bit
>> mode
>> @@ -1056,6 +1110,15 @@ static int mmc_init_card(struct mmc_host *host,
>> u32 ocr,
>> mmc_card_set_ddr_mode(card);
>> mmc_set_timing(card->host, MMC_TIMING_UHS_DDR50);
>> mmc_set_bus_width(card->host, bus_width);
>> + } else if (hs_sdr) {
>> + if (hs_sdr == EXT_CSD_CARD_TYPE_SDR_1_2V) {
>> + err = mmc_set_signal_voltage(host,
>> + MMC_SIGNAL_VOLTAGE_120, 0);
>> + if (err)
>> + goto err;
>> + }
>> + mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
>> + mmc_set_bus_width(card->host, bus_width);
>> }
>> }
>>
>> diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
>> index 1d5a3bd..c1d3ee3 100644
>> --- a/drivers/mmc/core/sd.c
>> +++ b/drivers/mmc/core/sd.c
>> @@ -660,7 +660,8 @@ static int mmc_sd_init_uhs_card(struct mmc_card
>> *card)
>>
>> /* SPI mode doesn't define CMD19 */
>> if (!mmc_host_is_spi(card->host) && card->host->ops-
>> >execute_tuning)
>> - err = card->host->ops->execute_tuning(card->host);
>> + err = card->host->ops->execute_tuning(card->host, \
>> +
> MMC_SEND_TUNING_BLOCK);
>>
>> out:
>> kfree(status);
>> diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
>> index 8c04f7f..8ef8817 100644
>> --- a/drivers/mmc/core/sdio.c
>> +++ b/drivers/mmc/core/sdio.c
>> @@ -14,6 +14,7 @@
>>
>> #include <linux/mmc/host.h>
>> #include <linux/mmc/card.h>
>> +#include <linux/mmc/mmc.h>
>> #include <linux/mmc/sdio.h>
>> #include <linux/mmc/sdio_func.h>
>> #include <linux/mmc/sdio_ids.h>
>> @@ -556,7 +557,8 @@ static int mmc_sdio_init_uhs_card(struct mmc_card
>> *card)
>>
>> /* Initialize and start re-tuning timer */
>> if (!mmc_host_is_spi(card->host) && card->host->ops-
>> >execute_tuning)
>> - err = card->host->ops->execute_tuning(card->host);
>> + err = card->host->ops->execute_tuning(card->host,
>> +
> MMC_SEND_TUNING_BLOCK);
>>
>> out:
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index a7c2311..13d74bb 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -49,7 +49,7 @@ static void sdhci_finish_data(struct sdhci_host *);
>>
>> static void sdhci_send_command(struct sdhci_host *, struct mmc_command
>> *);
>> static void sdhci_finish_command(struct sdhci_host *);
>> -static int sdhci_execute_tuning(struct mmc_host *mmc);
>> +static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
>> static void sdhci_tuning_timer(unsigned long data);
>>
>> #ifdef CONFIG_PM_RUNTIME
>> @@ -1016,7 +1016,8 @@ static void sdhci_send_command(struct sdhci_host
>> *host, struct mmc_command *cmd)
>> flags |= SDHCI_CMD_INDEX;
>>
>> /* CMD19 is special in that the Data Present Select should be set
>> */
>> - if (cmd->data || (cmd->opcode == MMC_SEND_TUNING_BLOCK))
>> + if (cmd->data || (cmd->opcode == MMC_SEND_TUNING_BLOCK) ||
>> + (cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200))
>> flags |= SDHCI_CMD_DATA;
>>
>> sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags),
>> SDHCI_COMMAND);
>> @@ -1287,7 +1288,7 @@ static void sdhci_request(struct mmc_host *mmc,
>> struct mmc_request *mrq)
>> if ((host->flags & SDHCI_NEEDS_RETUNING) &&
>> !(present_state & (SDHCI_DOING_WRITE |
>> SDHCI_DOING_READ))) {
>> spin_unlock_irqrestore(&host->lock, flags);
>> - sdhci_execute_tuning(mmc);
>> + sdhci_execute_tuning(mmc, mrq->cmd->opcode);
>> spin_lock_irqsave(&host->lock, flags);
>>
>> /* Restore original mmc_request structure */
>> @@ -1673,7 +1674,7 @@ static int
>> sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>> return err;
>> }
>>
>> -static int sdhci_execute_tuning(struct mmc_host *mmc)
>> +static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
>> {
>> struct sdhci_host *host;
>> u16 ctrl;
>> @@ -1694,10 +1695,13 @@ static int sdhci_execute_tuning(struct mmc_host
>> *mmc)
>> * Host Controller needs tuning only in case of SDR104 mode
>> * and for SDR50 mode when Use Tuning for SDR50 is set in
>> * Capabilities register.
>> + * If the Host Controller supports the HS200 mode then tuning
>> + * function has to be executed.
>> */
>> if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) ||
>> (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) &&
>> - (host->flags & SDHCI_SDR50_NEEDS_TUNING)))
>> + (host->flags & SDHCI_SDR50_NEEDS_TUNING)) ||
>> + (host->flags & SDHCI_HS200_NEEDS_TUNING))
>> ctrl |= SDHCI_CTRL_EXEC_TUNING;
>> else {
>> spin_unlock(&host->lock);
>> @@ -1733,7 +1737,7 @@ static int sdhci_execute_tuning(struct mmc_host
>> *mmc)
>> if (!tuning_loop_counter && !timeout)
>> break;
>>
>> - cmd.opcode = MMC_SEND_TUNING_BLOCK;
>> + cmd.opcode = opcode;
>> cmd.arg = 0;
>> cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
>> cmd.retries = 0;
>> @@ -1748,7 +1752,17 @@ static int sdhci_execute_tuning(struct mmc_host
>> *mmc)
>> * block to the Host Controller. So we set the block size
>> * to 64 here.
>> */
>> - sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64),
>> SDHCI_BLOCK_SIZE);
>> + if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200) {
>> + if (mmc->ios.bus_width == MMC_BUS_WIDTH_8)
>> + sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 128),
>> + SDHCI_BLOCK_SIZE);
>> + else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4)
>> + sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64),
>> + SDHCI_BLOCK_SIZE);
>> + } else {
>> + sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64),
>> + SDHCI_BLOCK_SIZE);
>> + }
>>
>> /*
>> * The tuning block is sent by the card to the host
>> controller.
>> @@ -2131,12 +2145,14 @@ static void sdhci_show_adma_error(struct
>> sdhci_host *host) { }
>>
>> static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
>> {
>> + u32 command;
>> BUG_ON(intmask == 0);
>>
>> /* CMD19 generates _only_ Buffer Read Ready interrupt */
>> if (intmask & SDHCI_INT_DATA_AVAIL) {
>> - if (SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) ==
>> - MMC_SEND_TUNING_BLOCK) {
>> + command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND));
>> + if ((command == MMC_SEND_TUNING_BLOCK) ||
>> + (command == MMC_SEND_TUNING_BLOCK_HS200)) {
>> host->tuning_done = 1;
>> wake_up(&host->buf_ready_int);
>> return;
>> @@ -2741,6 +2757,10 @@ int sdhci_add_host(struct sdhci_host *host)
>> if (caps[1] & SDHCI_USE_SDR50_TUNING)
>> host->flags |= SDHCI_SDR50_NEEDS_TUNING;
>>
>> + /* Does the host needs tuning for HS200? */
>> + if (mmc->caps2 & MMC_CAP2_HS200)
>> + host->flags |= SDHCI_HS200_NEEDS_TUNING;
>> +
>> /* Driver Type(s) (A, C, D) supported by the host */
>> if (caps[1] & SDHCI_DRIVER_TYPE_A)
>> mmc->caps |= MMC_CAP_DRIVER_TYPE_A;
>> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
>> index 534974c..e76f649 100644
>> --- a/include/linux/mmc/card.h
>> +++ b/include/linux/mmc/card.h
>> @@ -209,6 +209,7 @@ struct mmc_card {
>> #define MMC_STATE_HIGHSPEED_DDR (1<<4) /* card is in high
>> speed mode */
>> #define MMC_STATE_ULTRAHIGHSPEED (1<<5) /* card is in ultra
>> high speed mode */
>> #define MMC_CARD_SDXC (1<<6) /* card is SDXC */
>> +#define MMC_STATE_HIGHSPEED_200 (1<<7) /* card is in HS200
>> mode */
>> unsigned int quirks; /* card quirks */
>> #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0
>> writes outside of the VS CCCR range */
>> #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func-
>> >cur_blksize */
>> @@ -365,6 +366,7 @@ static inline void __maybe_unused
>> remove_quirk(struct mmc_card *card, int data)
>> #define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT)
>> #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY)
>> #define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED)
>> +#define mmc_card_hs200(c) ((c)->state & MMC_STATE_HIGHSPEED_200)
>> #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR)
>> #define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR)
>> #define mmc_card_uhs(c) ((c)->state &
>> MMC_STATE_ULTRAHIGHSPEED)
>> @@ -374,6 +376,7 @@ static inline void __maybe_unused
>> remove_quirk(struct mmc_card *card, int data)
>> #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
>> #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
>> #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
>> +#define mmc_card_set_hs200(c) ((c)->state |=
>> MMC_STATE_HIGHSPEED_200)
>> #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
>> #define mmc_card_set_ddr_mode(c) ((c)->state |=
>> MMC_STATE_HIGHSPEED_DDR)
>> #define mmc_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
>> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
>> index 706f722..5eac57a 100644
>> --- a/include/linux/mmc/host.h
>> +++ b/include/linux/mmc/host.h
>> @@ -50,6 +50,7 @@ struct mmc_ios {
>>
>> #define MMC_TIMING_LEGACY 0
>> #define MMC_TIMING_MMC_HS 1
>> +#define MMC_TIMING_MMC_HS200 2
>> #define MMC_TIMING_SD_HS 2
>> #define MMC_TIMING_UHS_SDR12 MMC_TIMING_LEGACY
>> #define MMC_TIMING_UHS_SDR25 MMC_TIMING_SD_HS
>> @@ -60,6 +61,8 @@ struct mmc_ios {
>> #define MMC_SDR_MODE 0
>> #define MMC_1_2V_DDR_MODE 1
>> #define MMC_1_8V_DDR_MODE 2
>> +#define MMC_1_2V_SDR_MODE 3
>> +#define MMC_1_8V_SDR_MODE 4
>>
>> unsigned char signal_voltage; /* signalling voltage
>> (1.8V or 3.3V) */
>>
>> @@ -148,7 +151,9 @@ struct mmc_host_ops {
>> void (*init_card)(struct mmc_host *host, struct mmc_card *card);
>>
>> int (*start_signal_voltage_switch)(struct mmc_host *host,
>> struct mmc_ios *ios);
>> - int (*execute_tuning)(struct mmc_host *host);
>> +
>> + /* The tuning command opcode value is different for SD and eMMC
>> cards */
>> + int (*execute_tuning)(struct mmc_host *host, u32 opcode);
>> void (*enable_preset_value)(struct mmc_host *host, bool enable);
>> int (*select_drive_strength)(unsigned int max_dtr, int
>> host_drv, int card_drv);
>> void (*hw_reset)(struct mmc_host *host);
>> @@ -242,6 +247,10 @@ struct mmc_host {
>> #define MMC_CAP2_CACHE_CTRL (1 << 1) /* Allow cache control */
>> #define MMC_CAP2_POWEROFF_NOTIFY (1 << 2) /* Notify poweroff
>> supported */
>> #define MMC_CAP2_NO_MULTI_READ (1 << 3) /* Multiblock reads
>> don't work */
>> +#define MMC_CAP2_HS200_1_8V_SDR (1 << 4) /* can support */
>> +#define MMC_CAP2_HS200_1_2V_SDR (1 << 5) /* can support */
>> +#define MMC_CAP2_HS200 (MMC_CAP2_HS200_1_8V_SDR | \
>> + MMC_CAP2_HS200_1_2V_SDR)
>>
>> mmc_pm_flag_t pm_caps; /* supported pm features */
>> unsigned int power_notify_type;
>> diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
>> index 0e71356..7996272 100644
>> --- a/include/linux/mmc/mmc.h
>> +++ b/include/linux/mmc/mmc.h
>> @@ -51,6 +51,7 @@
>> #define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1
>> */
>> #define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1
>> */
>> #define MMC_SEND_TUNING_BLOCK 19 /* adtc R1
>> */
>> +#define MMC_SEND_TUNING_BLOCK_HS200 21 /* adtc R1 */
>>
>> /* class 3 */
>> #define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1
>> */
>> @@ -333,13 +334,76 @@ struct _mmc_csd {
>>
>> #define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */
>> #define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */
>> -#define EXT_CSD_CARD_TYPE_MASK 0xF /* Mask out reserved bits */
>> +#define EXT_CSD_CARD_TYPE_MASK 0x3F /* Mask out reserved bits */
>> #define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz
>> */
>> /* DDR mode @1.8V or 3V I/O */
>> #define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz
>> */
>> /* DDR mode @1.2V I/O */
>> #define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \
>> | EXT_CSD_CARD_TYPE_DDR_1_2V)
>> +#define EXT_CSD_CARD_TYPE_SDR_1_8V (1<<4) /* Card can run at
>> 200MHz */
>> +#define EXT_CSD_CARD_TYPE_SDR_1_2V (1<<5) /* Card can run at
>> 200MHz */
>> + /* SDR mode @1.2V I/O */
>> +
>> +#define EXT_CSD_CARD_TYPE_SDR_200 (EXT_CSD_CARD_TYPE_SDR_1_8V \
>> + | EXT_CSD_CARD_TYPE_SDR_1_2V)
>> +
>> +#define EXT_CSD_CARD_TYPE_SDR_ALL (EXT_CSD_CARD_TYPE_SDR_200 \
>> + | EXT_CSD_CARD_TYPE_52 \
>> + | EXT_CSD_CARD_TYPE_26)
>> +
>> +#define EXT_CSD_CARD_TYPE_SDR_1_2V_ALL
>> (EXT_CSD_CARD_TYPE_SDR_1_2V \
>> + | EXT_CSD_CARD_TYPE_52 \
>> + | EXT_CSD_CARD_TYPE_26)
>> +
>> +#define EXT_CSD_CARD_TYPE_SDR_1_8V_ALL
>> (EXT_CSD_CARD_TYPE_SDR_1_8V \
>> + | EXT_CSD_CARD_TYPE_52 \
>> + | EXT_CSD_CARD_TYPE_26)
>> +
>> +#define EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_8V
>> (EXT_CSD_CARD_TYPE_SDR_1_2V \
>> + | EXT_CSD_CARD_TYPE_DDR_1_8V
> \
>> + | EXT_CSD_CARD_TYPE_52
> \
>> + | EXT_CSD_CARD_TYPE_26)
>> +
>> +#define EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_8V
>> (EXT_CSD_CARD_TYPE_SDR_1_8V \
>> + | EXT_CSD_CARD_TYPE_DDR_1_8V
> \
>> + | EXT_CSD_CARD_TYPE_52
> \
>> + | EXT_CSD_CARD_TYPE_26)
>> +
>> +#define EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_2V
>> (EXT_CSD_CARD_TYPE_SDR_1_2V \
>> + | EXT_CSD_CARD_TYPE_DDR_1_2V
> \
>> + | EXT_CSD_CARD_TYPE_52
> \
>> + | EXT_CSD_CARD_TYPE_26)
>> +
>> +#define EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_2V
>> (EXT_CSD_CARD_TYPE_SDR_1_8V \
>> + | EXT_CSD_CARD_TYPE_DDR_1_2V
> \
>> + | EXT_CSD_CARD_TYPE_52
> \
>> + | EXT_CSD_CARD_TYPE_26)
>> +
>> +#define EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_52
>> (EXT_CSD_CARD_TYPE_SDR_1_2V \
>> + | EXT_CSD_CARD_TYPE_DDR_52
> \
>> + | EXT_CSD_CARD_TYPE_52
> \
>> + | EXT_CSD_CARD_TYPE_26)
>> +
>> +#define EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_52
>> (EXT_CSD_CARD_TYPE_SDR_1_8V \
>> + | EXT_CSD_CARD_TYPE_DDR_52
> \
>> + | EXT_CSD_CARD_TYPE_52
> \
>> + | EXT_CSD_CARD_TYPE_26)
>> +
>> +#define EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_8V
>> (EXT_CSD_CARD_TYPE_SDR_200 \
>> + | EXT_CSD_CARD_TYPE_DDR_1_8V
> \
>> + | EXT_CSD_CARD_TYPE_52
> \
>> + | EXT_CSD_CARD_TYPE_26)
>> +
>> +#define EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_2V
>> (EXT_CSD_CARD_TYPE_SDR_200 \
>> + | EXT_CSD_CARD_TYPE_DDR_1_2V
> \
>> + | EXT_CSD_CARD_TYPE_52
> \
>> + | EXT_CSD_CARD_TYPE_26)
>> +
>> +#define EXT_CSD_CARD_TYPE_SDR_ALL_DDR_52 (EXT_CSD_CARD_TYPE_SDR_200
>> \
>> + | EXT_CSD_CARD_TYPE_DDR_52
> \
>> + | EXT_CSD_CARD_TYPE_52
> \
>> + | EXT_CSD_CARD_TYPE_26)
>>
>> #define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
>> #define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
>> diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
>> index e4b6935..d9a2222 100644
>> --- a/include/linux/mmc/sdhci.h
>> +++ b/include/linux/mmc/sdhci.h
>> @@ -121,6 +121,7 @@ struct sdhci_host {
>> #define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */
>> #define SDHCI_PV_ENABLED (1<<8) /* Preset value enabled */
>> #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */
>> +#define SDHCI_HS200_NEEDS_TUNING (1<<10) /* HS200 needs tuning */
>>
>> unsigned int version; /* SDHCI spec. version */
>>
>> --
>> 1.7.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> the body of a message to majord...@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html