From mboxrd@z Thu Jan 1 00:00:00 1970 From: zhangfei gao Subject: Re: [PATCH v2 09/12] mmc: sd: add support for tuning during uhs initialization Date: Tue, 15 Mar 2011 06:32:18 -0400 Message-ID: References: <1299238369-1768-1-git-send-email-arindam.nath@amd.com> <1299238369-1768-10-git-send-email-arindam.nath@amd.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: QUOTED-PRINTABLE Return-path: Received: from mail-vx0-f174.google.com ([209.85.220.174]:40455 "EHLO mail-vx0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755412Ab1COKcT convert rfc822-to-8bit (ORCPT ); Tue, 15 Mar 2011 06:32:19 -0400 Received: by vxi39 with SMTP id 39so399882vxi.19 for ; Tue, 15 Mar 2011 03:32:18 -0700 (PDT) In-Reply-To: <1299238369-1768-10-git-send-email-arindam.nath@amd.com> Sender: linux-mmc-owner@vger.kernel.org List-Id: linux-mmc@vger.kernel.org To: Arindam Nath Cc: cjb@laptop.org, prakity@marvell.com, subhashj@codeaurora.org, linux-mmc@vger.kernel.org, henry.su@amd.com, aaron.lu@amd.com, anath.amd@gmail.com On Fri, Mar 4, 2011 at 6:32 AM, Arindam Nath wro= te: > 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. 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 leve= l. > 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 > --- > =A0drivers/mmc/core/sd.c =A0 =A0 | =A0 =A04 + > =A0drivers/mmc/host/sdhci.c =A0| =A0137 +++++++++++++++++++++++++++++= +++++++++++++++- > =A0drivers/mmc/host/sdhci.h =A0| =A0 =A03 + > =A0include/linux/mmc/host.h =A0| =A0 =A01 + > =A0include/linux/mmc/mmc.h =A0 | =A0 =A01 + > =A0include/linux/mmc/sdhci.h | =A0 =A04 + > =A06 files changed, 149 insertions(+), 1 deletions(-) > > diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c > index be01397..1e2d157 100644 > --- a/drivers/mmc/core/sd.c > +++ b/drivers/mmc/core/sd.c > @@ -637,6 +637,10 @@ static int mmc_sd_init_uhs_card(struct mmc_card = *card) > =A0 =A0 =A0 =A0/* Set current limit for the card */ > =A0 =A0 =A0 =A0err =3D sd_set_current_limit(card, status); > > + =A0 =A0 =A0 /* SPI mode doesn't define CMD19 */ > + =A0 =A0 =A0 if (!mmc_host_is_spi(card->host) && card->host->ops->ex= ecute_tuning) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 card->host->ops->execute_tuning(card->h= ost); > + > =A0out: > =A0 =A0 =A0 =A0kfree(status); > > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c > index 245cc39..8f4f102 100644 > --- a/drivers/mmc/host/sdhci.c > +++ b/drivers/mmc/host/sdhci.c > @@ -39,6 +39,8 @@ > =A0#define SDHCI_USE_LEDS_CLASS > =A0#endif > > +#define MAX_TUNING_LOOP 40 > + > =A0static unsigned int debug_quirks =3D 0; > > =A0static void sdhci_prepare_data(struct sdhci_host *, struct mmc_dat= a *); > @@ -985,7 +987,9 @@ static void sdhci_send_command(struct sdhci_host = *host, struct mmc_command *cmd) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0flags |=3D SDHCI_CMD_CRC; > =A0 =A0 =A0 =A0if (cmd->flags & MMC_RSP_OPCODE) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0flags |=3D SDHCI_CMD_INDEX; > - =A0 =A0 =A0 if (cmd->data) > + > + =A0 =A0 =A0 /* CMD19 is special in that the Data Present Select sho= uld be set */ > + =A0 =A0 =A0 if (cmd->data || (cmd->opcode =3D=3D MMC_SEND_TUNING_BL= OCK)) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0flags |=3D SDHCI_CMD_DATA; > > =A0 =A0 =A0 =A0sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags),= SDHCI_COMMAND); > @@ -1485,6 +1489,119 @@ static int sdhci_get_max_current_180(struct m= mc_host *mmc) > =A0 =A0 =A0 =A0return max_current_180; > =A0} > > +static void sdhci_execute_tuning(struct mmc_host *mmc) > +{ > + =A0 =A0 =A0 struct sdhci_host *host; > + =A0 =A0 =A0 u16 ctrl; > + =A0 =A0 =A0 int tuning_loop_counter =3D MAX_TUNING_LOOP; > + =A0 =A0 =A0 unsigned long flags; > + =A0 =A0 =A0 unsigned long timeout; > + > + =A0 =A0 =A0 host =3D mmc_priv(mmc); > + > + =A0 =A0 =A0 spin_lock_irqsave(&host->lock, flags); > + > + =A0 =A0 =A0 ctrl =3D sdhci_readw(host, SDHCI_HOST_CONTROL2); > + > + =A0 =A0 =A0 /* > + =A0 =A0 =A0 =A0* Host Controller needs tuning only in case of SDR10= 4 mode > + =A0 =A0 =A0 =A0* and for SDR50 mode when Use Tuning for SDR50 is se= t in > + =A0 =A0 =A0 =A0* Capabilities register. > + =A0 =A0 =A0 =A0*/ > + =A0 =A0 =A0 if ((ctrl & SDHCI_CTRL_UHS_SDR104) || > + =A0 =A0 =A0 =A0 =A0 ((ctrl & SDHCI_CTRL_UHS_SDR50) && > + =A0 =A0 =A0 =A0 =A0 (host->flags & SDHCI_SDR50_NEEDS_TUNING))) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ctrl |=3D SDHCI_CTRL_EXEC_TUNING; > + =A0 =A0 =A0 else { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 spin_unlock_irqrestore(&host->lock, fla= gs); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return; > + =A0 =A0 =A0 } > + > + =A0 =A0 =A0 sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); > + > + =A0 =A0 =A0 /* > + =A0 =A0 =A0 =A0* As per the Host Controller spec v3.00, tuning comm= and > + =A0 =A0 =A0 =A0* generates Buffer Read Ready interrupt, so enable t= hat. > + =A0 =A0 =A0 =A0*/ > + =A0 =A0 =A0 sdhci_unmask_irqs(host, SDHCI_INT_DATA_AVAIL); > + > + =A0 =A0 =A0 /* > + =A0 =A0 =A0 =A0* Issue CMD19 repeatedly till Execute Tuning is set = to 0 or the number > + =A0 =A0 =A0 =A0* of loops reaches 40 times or a timeout of 150ms oc= curs. > + =A0 =A0 =A0 =A0*/ > + =A0 =A0 =A0 timeout =3D 150; > + =A0 =A0 =A0 do { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct mmc_command cmd; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct mmc_request mrq; > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!tuning_loop_counter && !timeout) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break; > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 memset(&cmd, 0, sizeof(struct mmc_comma= nd)); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cmd.opcode =3D MMC_SEND_TUNING_BLOCK; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cmd.arg =3D 0; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cmd.flags =3D MMC_RSP_R1 | MMC_CMD_ADTC= ; > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 memset(&cmd.resp, 0, sizeof(cmd.resp)); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cmd.retries =3D 0; > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cmd.data =3D NULL; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 cmd.error =3D 0; > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 memset(&mrq, 0, sizeof(struct mmc_reque= st)); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mrq.cmd =3D &cmd; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 host->mrq =3D &mrq; Tune may fail since SDHCI_TRNS_DMA is set in SDHCI_TRANSFER_MODE, SDHCI_TRNS_DMA required to be cleared before send_command, such as sdhci_writew(host, 0x12, SDHCI_TRANSFER_MODE); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 sdhci_send_command(host, &cmd); > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 host->cmd =3D NULL; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 host->mrq =3D NULL; > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 spin_unlock_irqrestore(&host->lock, fla= gs); > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Wait for Buffer Read Ready interrupt= */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 wait_event_interruptible_timeout(host->= buf_ready_int, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= =A0 =A0 (host->tuning_done =3D=3D 1), > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= =A0 =A0 msecs_to_jiffies(50)); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 spin_lock_irqsave(&host->lock, flags); > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!host->tuning_done) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 printk(KERN_INFO DRIVER= _NAME ": Tuning procedure" > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 " faile= d, falling back to fixed sampling" > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 " clock= \n"); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ctrl &=3D ~SDHCI_CTRL_T= UNED_CLK; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ctrl &=3D ~SDHCI_CTRL_E= XEC_TUNING; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 sdhci_writew(host, ctrl= , SDHCI_HOST_CONTROL2); > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto out; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 host->tuning_done =3D 0; > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ctrl =3D sdhci_readw(host, SDHCI_HOST_C= ONTROL2); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 tuning_loop_counter--; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 timeout--; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mdelay(1); > + =A0 =A0 =A0 } while (ctrl & SDHCI_CTRL_EXEC_TUNING); > + > + =A0 =A0 =A0 /* > + =A0 =A0 =A0 =A0* The Host Driver has exhausted the maximum number o= f loops allowed, > + =A0 =A0 =A0 =A0* so use fixed sampling frequency. > + =A0 =A0 =A0 =A0*/ > + =A0 =A0 =A0 if (!tuning_loop_counter || !timeout) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ctrl &=3D ~SDHCI_CTRL_TUNED_CLK; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 sdhci_writew(host, ctrl, SDHCI_HOST_CON= TROL2); > + =A0 =A0 =A0 } else { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 printk(KERN_INFO DRIVER= _NAME ": Tuning procedure" > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 " faile= d, falling back to fixed sampling" > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 " clock= \n"); > + =A0 =A0 =A0 } > + > +out: > + =A0 =A0 =A0 sdhci_mask_irqs(host, SDHCI_INT_DATA_AVAIL); > + =A0 =A0 =A0 spin_unlock_irqrestore(&host->lock, flags); > +} > + > =A0static const struct mmc_host_ops sdhci_ops =3D { > =A0 =A0 =A0 =A0.request =A0 =A0 =A0 =A0=3D sdhci_request, > =A0 =A0 =A0 =A0.set_ios =A0 =A0 =A0 =A0=3D sdhci_set_ios, > @@ -1492,6 +1609,7 @@ static const struct mmc_host_ops sdhci_ops =3D = { > =A0 =A0 =A0 =A0.enable_sdio_irq =3D sdhci_enable_sdio_irq, > =A0 =A0 =A0 =A0.start_signal_voltage_switch =A0 =A0=3D sdhci_start_si= gnal_voltage_switch, > =A0 =A0 =A0 =A0.get_max_current_180 =A0 =A0 =A0 =A0 =A0 =A0=3D sdhci_= get_max_current_180, > + =A0 =A0 =A0 .execute_tuning =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =3D sdh= ci_execute_tuning, > =A0}; > > =A0/*****************************************************************= ************\ > @@ -1703,6 +1821,16 @@ static void sdhci_data_irq(struct sdhci_host *= host, u32 intmask) > =A0{ > =A0 =A0 =A0 =A0BUG_ON(intmask =3D=3D 0); > > + =A0 =A0 =A0 /* CMD19 generates _only_ Buffer Read Ready interrupt *= / > + =A0 =A0 =A0 if (intmask & SDHCI_INT_DATA_AVAIL) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (SDHCI_GET_CMD(sdhci_readw(host, SDH= CI_COMMAND)) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =3D=3D = MMC_SEND_TUNING_BLOCK) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 host->tuning_done =3D 1= ; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 wake_up(&host->buf_read= y_int); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > + =A0 =A0 =A0 } > + > =A0 =A0 =A0 =A0if (!host->data) { > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 * The "data complete" interrupt is al= so used to > @@ -2126,6 +2254,10 @@ int sdhci_add_host(struct sdhci_host *host) > =A0 =A0 =A0 =A0if (caps[1] & SDHCI_SUPPORT_DDR50) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0mmc->caps |=3D MMC_CAP_UHS_DDR50; > > + =A0 =A0 =A0 /* Does the host needs tuning for SDR50? */ > + =A0 =A0 =A0 if (caps[1] & SDHCI_USE_SDR50_TUNING) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 host->flags |=3D SDHCI_SDR50_NEEDS_TUNI= NG; > + > =A0 =A0 =A0 =A0/* Driver Type(s) (A, C, D) supported by the host */ > =A0 =A0 =A0 =A0if (caps[1] & SDHCI_DRIVER_TYPE_A) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0mmc->caps |=3D MMC_CAP_DRIVER_TYPE_A; > @@ -2269,6 +2401,9 @@ int sdhci_add_host(struct sdhci_host *host) > > =A0 =A0 =A0 =A0setup_timer(&host->timer, sdhci_timeout_timer, (unsign= ed long)host); > > + =A0 =A0 =A0 if (host->version >=3D SDHCI_SPEC_300) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 init_waitqueue_head(&host->buf_ready_in= t); > + > =A0 =A0 =A0 =A0ret =3D request_irq(host->irq, sdhci_irq, IRQF_SHARED, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0mmc_hostname(mmc), host); > =A0 =A0 =A0 =A0if (ret) > diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h > index 5bf244d..4746879 100644 > --- a/drivers/mmc/host/sdhci.h > +++ b/drivers/mmc/host/sdhci.h > @@ -160,6 +160,8 @@ > =A0#define =A0SDHCI_CTRL_DRV_TYPE_A =A0 =A0 =A0 =A0 0x0010 > =A0#define =A0SDHCI_CTRL_DRV_TYPE_C =A0 =A0 =A0 =A0 0x0020 > =A0#define =A0SDHCI_CTRL_DRV_TYPE_D =A0 =A0 =A0 =A0 0x0030 > +#define =A0SDHCI_CTRL_EXEC_TUNING =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A00x0= 040 > +#define =A0SDHCI_CTRL_TUNED_CLK =A0 =A0 =A0 =A0 =A00x0080 > =A0#define =A0SDHCI_CTRL_PRESET_VAL_ENABLE =A00x8000 > > =A0#define SDHCI_CAPABILITIES =A0 =A0 0x40 > @@ -187,6 +189,7 @@ > =A0#define =A0SDHCI_DRIVER_TYPE_A =A0 0x00000010 > =A0#define =A0SDHCI_DRIVER_TYPE_C =A0 0x00000020 > =A0#define =A0SDHCI_DRIVER_TYPE_D =A0 0x00000040 > +#define =A0SDHCI_USE_SDR50_TUNING =A0 =A0 =A0 =A00x00002000 > > =A0#define SDHCI_CAPABILITIES_1 =A0 0x44 > > diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h > index e84cd05..651e40b 100644 > --- a/include/linux/mmc/host.h > +++ b/include/linux/mmc/host.h > @@ -129,6 +129,7 @@ struct mmc_host_ops { > > =A0 =A0 =A0 =A0int =A0 =A0 (*start_signal_voltage_switch)(struct mmc_= host *host); > =A0 =A0 =A0 =A0int =A0 =A0 (*get_max_current_180)(struct mmc_host *mm= c); > + =A0 =A0 =A0 void =A0 =A0(*execute_tuning)(struct mmc_host *host); > =A0}; > > =A0struct mmc_card; > diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h > index 612301f..9194f9e 100644 > --- a/include/linux/mmc/mmc.h > +++ b/include/linux/mmc/mmc.h > @@ -50,6 +50,7 @@ > =A0#define MMC_SET_BLOCKLEN =A0 =A0 =A0 =A0 16 =A0 /* ac =A0 [31:0] b= lock len =A0 R1 =A0*/ > =A0#define MMC_READ_SINGLE_BLOCK =A0 =A017 =A0 /* adtc [31:0] data ad= dr =A0 R1 =A0*/ > =A0#define MMC_READ_MULTIPLE_BLOCK =A018 =A0 /* adtc [31:0] data addr= =A0 R1 =A0*/ > +#define MMC_SEND_TUNING_BLOCK =A0 =A019 =A0 /* adtc =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0R1 =A0*/ > > =A0 /* class 3 */ > =A0#define MMC_WRITE_DAT_UNTIL_STOP 20 =A0 /* adtc [31:0] data addr =A0= R1 =A0*/ > diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h > index 282d158..5203b97 100644 > --- a/include/linux/mmc/sdhci.h > +++ b/include/linux/mmc/sdhci.h > @@ -109,6 +109,7 @@ struct sdhci_host { > =A0#define SDHCI_USE_ADMA =A0 =A0 =A0 =A0 (1<<1) =A0/* Host is ADMA c= apable */ > =A0#define SDHCI_REQ_USE_DMA =A0 =A0 =A0(1<<2) =A0/* Use DMA for this= req. */ > =A0#define SDHCI_DEVICE_DEAD =A0 =A0 =A0(1<<3) =A0/* Device unrespons= ive */ > +#define SDHCI_SDR50_NEEDS_TUNING (1<<4) =A0 =A0 =A0 =A0/* SDR50 need= s tuning */ > > =A0 =A0 =A0 =A0unsigned int version; =A0 /* SDHCI spec. version */ > > @@ -147,6 +148,9 @@ struct sdhci_host { > > =A0 =A0 =A0 =A0struct mmc_command =A0 =A0 =A0*saved_abort_cmd; /* Abo= rt command saved for data error recovery */ > > + =A0 =A0 =A0 wait_queue_head_t =A0 =A0 =A0 buf_ready_int; =A0/* Wait= queue for Buffer Read Ready interrupt */ > + =A0 =A0 =A0 unsigned int =A0 =A0 =A0 =A0 =A0 =A0tuning_done; =A0 =A0= /* Condition flag set when CMD19 succeeds */ > + > =A0 =A0 =A0 =A0unsigned long private[0] ____cacheline_aligned; > =A0}; > =A0#endif /* __SDHCI_H */ > -- > 1.7.1 > >