Hi Zhangfei,
> -----Original Message-----
> From: zhangfei gao [mailto:[email protected]]
> Sent: Friday, February 18, 2011 4:20 PM
> To: Nath, Arindam
> Cc: [email protected]; [email protected]; Su, Henry; Lu, Aaron;
> [email protected]
> 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 <[email protected]>
> 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 <[email protected]>
> > ---
> > 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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html