Hi Zhangfei, > -----Original Message----- > From: zhangfei gao [mailto:zhangfei.gao@xxxxxxxxx] > Sent: Friday, February 18, 2011 4:20 PM > To: Nath, Arindam > Cc: cjb@xxxxxxxxxx; linux-mmc@xxxxxxxxxxxxxxx; Su, Henry; Lu, Aaron; > anath.amd@xxxxxxxxx > Subject: Re: [PATCH 09/12] mmc: sd: add support for tuning during uhs > initialization > > On Tue, Feb 15, 2011 at 4:35 AM, Arindam Nath <arindam.nath@xxxxxxx> > wrote: > > Host Controller needs tuning during initialization to operate SDR50 > > and SDR104 UHS-I cards. Whether SDR50 mode actually needs tuning is > > indicated by bit 45 of the Host Controller Capabilities register. > > A new command CMD19 has been defined in the Physical Layer spec v3.01 > > to request the card to send tuning pattern. > > > > We enable Buffer Read Ready interrupt at the very begining of tuning > > procedure, because that is the only interrupt generated by the Host > > Controller during tuning. Since there is no actual data transfer > > between card and host memory, we don't set DMA Enable (bit 0) in the > > Transfer Mode register. The tuning block is sent by the card to the > > Host Controller using DAT lines, so we set Data Present Select (bit > 5) > > in the Command register. The Host Controller is responsible for doing > > the verfication of tuning block sent by the card at the hardware > level. > > After sending CMD19, we wait for Buffer Read Ready interrupt. In case > > we don't receive an interrupt after the specified timeout value, we > > fall back on fixed sampling clock by setting Execute Tuning (bit 6) > > and Sampling Clock Seletc (bit 7) of Host Control2 register to 0. > > Before exiting the tuning procedure, we disable Buffer Read Ready > interrupt. > > > > Signed-off-by: Arindam Nath <arindam.nath@xxxxxxx> > > --- > > drivers/mmc/core/sd.c | 4 + > > drivers/mmc/host/sdhci.c | 142 > ++++++++++++++++++++++++++++++++++++++++++++- > > drivers/mmc/host/sdhci.h | 3 + > > include/linux/mmc/host.h | 1 + > > include/linux/mmc/mmc.h | 1 + > > include/linux/mmc/sdhci.h | 4 + > > 6 files changed, 153 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c > > index c52d427..3113cb6 100644 > > --- a/drivers/mmc/core/sd.c > > +++ b/drivers/mmc/core/sd.c > > @@ -624,6 +624,10 @@ static int mmc_sd_init_uhs_card(struct mmc_card > *card) > > /* Set current limit for the card */ > > err = sd_set_current_limit(card, status); > > > > + /* SPI mode doesn't define CMD19 */ > > + if (!mmc_host_is_spi(card->host)) > > + card->host->ops->execute_tuning(card->host); > > + > > out: > > kfree(status); > > > > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c > > index fc2cba6..6f3f0dc 100644 > > --- a/drivers/mmc/host/sdhci.c > > +++ b/drivers/mmc/host/sdhci.c > > @@ -39,6 +39,8 @@ > > #define SDHCI_USE_LEDS_CLASS > > #endif > > > > +#define MAX_TUNING_LOOP 40 > > + > > static unsigned int debug_quirks = 0; > > > > static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data > *); > > @@ -872,7 +874,10 @@ static void sdhci_set_transfer_mode(struct > sdhci_host *host, > > > > if (data->flags & MMC_DATA_READ) > > mode |= SDHCI_TRNS_READ; > > - if (host->flags & SDHCI_REQ_USE_DMA) > > + > > + /* CMD19 requires DMA Enable to be set to 0 */ > > + if ((host->flags & SDHCI_REQ_USE_DMA) && > > + (host->cmd->opcode != MMC_SEND_TUNING_BLOCK)) > > mode |= SDHCI_TRNS_DMA; > > Here may have no chance to execute, since sdhci_set_transfer_mode will > return directly if data is NULL. Thanks. Since we are setting data to NULL inside sdhci_execute_tuning() below, this condition check becomes redundant. I will remove this check in V2 of the patch. > > > > > sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); > > @@ -988,7 +993,9 @@ static void sdhci_send_command(struct sdhci_host > *host, struct mmc_command *cmd) > > flags |= SDHCI_CMD_CRC; > > if (cmd->flags & MMC_RSP_OPCODE) > > flags |= SDHCI_CMD_INDEX; > > - if (cmd->data) > > + > > + /* CMD19 is special in that the Data Present Select should be > set */ > > + if (cmd->data || (cmd->opcode == MMC_SEND_TUNING_BLOCK)) > > flags |= SDHCI_CMD_DATA; > > > > sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), > SDHCI_COMMAND); > > @@ -1494,6 +1501,119 @@ static int sdhci_get_max_current_180(struct > mmc_host *mmc) > > return max_current_180; > > } > > > > +static void sdhci_execute_tuning(struct mmc_host *mmc) > > +{ > > + struct sdhci_host *host; > > + u16 ctrl; > > + int tuning_loop_counter = MAX_TUNING_LOOP; > > + unsigned long flags; > > + unsigned long timeout; > > + > > + host = mmc_priv(mmc); > > + > > + spin_lock_irqsave(&host->lock, flags); > > + > > + ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); > > + > > + /* > > + * 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 ((ctrl & SDHCI_CTRL_UHS_SDR104) || > > + ((ctrl & SDHCI_CTRL_UHS_SDR50) && > > + (host->flags & SDHCI_SDR50_NEEDS_TUNING))) > > + ctrl |= SDHCI_CTRL_EXEC_TUNING; > > + else { > > + spin_unlock_irqrestore(&host->lock, flags); > > + return; > > + } > > + > > + sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); > > + > > + /* > > + * As per the Host Controller spec v3.00, tuning command > > + * generates Buffer Read Ready interrupt, so enable that. > > + */ > > + sdhci_unmask_irqs(host, SDHCI_INT_DATA_AVAIL); > > + > > + /* > > + * Issue CMD19 repeatedly till Execute Tuning is set to 0 or > the number > > + * of loops reaches 40 times or a timeout of 150ms occurs. > > + */ > > + timeout = 150; > > + do { > > + struct mmc_command cmd; > > + struct mmc_request mrq; > > + > > + if (!tuning_loop_counter && !timeout) > > + break; > > + > > + memset(&cmd, 0, sizeof(struct mmc_command)); > > + cmd.opcode = MMC_SEND_TUNING_BLOCK; > > + cmd.arg = 0; > > + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; > > + > > + memset(&cmd.resp, 0, sizeof(cmd.resp)); > > + cmd.retries = 0; > > + > > + cmd.data = NULL; > > Set cmd.data = null, then sdhci_set_transfer_mode will return. Thanks. Will take care of that. Regards, Arindam -- 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