Hi Peng,

> -----Original Message-----
> From: Peng Fan <peng....@nxp.com>
> Sent: Monday, July 20, 2020 9:42 AM
> To: Y.b. Lu <yangbo...@nxp.com>; u-boot@lists.denx.de; Priyanka Jain
> <priyanka.j...@nxp.com>; 'Jaehoon Chung' <jh80.ch...@samsung.com>
> Cc: Y.b. Lu <yangbo...@nxp.com>
> Subject: RE: [v2, 07/11] mmc: fsl_esdhc: support eMMC HS400 mode
> 
> > Subject: [v2, 07/11] mmc: fsl_esdhc: support eMMC HS400 mode
> >
> > The process for eMMC HS400 mode for eSDHC is,
> >
> > 1. Perform the Tuning Process at the HS400 target operating frequency.
> >    Latched the clock division value.
> > 2. if read transaction, then set the SDTIMNGCTL[FLW_CTL_BG].
> > 3. Switch to High Speed mode and then set the card clock frequency to
> >    a value not greater than 52Mhz
> > 4. Clear TBCTL[TB_EN],tuning block enable bit.
> > 5. Change to 8 bit DDR Mode
> > 6. Switch the card to HS400 mode.
> > 7. Set TBCTL[TB_EN], tuning block enable bit.
> > 8. Clear SYSCTL[SDCLKEN]
> > 9. Wait for PRSSTAT[SDSTB] to be set
> > 10. Change the clock division to latched value.Set TBCTL[HS 400 mode]
> >     and Set SDCLKCTL[CMD_CLK_CTRL]
> > 11. Set SYSCTL[SDCLKEN]
> > 12. Wait for PRSSTAT[SDSTB] to be set
> > 13. Set DLLCFG0[DLL_ENABLE] and DLLCFG0[DLL_FREQ_SEL].
> > 14. Wait for delay chain to lock.
> > 15. Set TBCTL[HS400_WNDW_ADJUST]
> > 16. Again clear SYSCTL[SDCLKEN]
> > 17. Wait for PRSSTAT[SDSTB] to be set
> > 18. Set ESDHCCTL[FAF]
> > 19. Wait for ESDHCCTL[FAF] to be cleared 20. Set SYSCTL[SDCLKEN] 21. Wait
> > for PRSSTAT[SDSTB] to be set.
> >
> > Signed-off-by: Yangbo Lu <yangbo...@nxp.com>
> > ---
> > Changes for v2:
> >     - None.
> > ---
> >  drivers/mmc/fsl_esdhc.c | 98
> > ++++++++++++++++++++++++++++++++-----------------
> >  include/fsl_esdhc.h     | 12 ++++++
> >  2 files changed, 76 insertions(+), 34 deletions(-)
> >
> > diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index
> > 607b420..c1a127c 100644
> > --- a/drivers/mmc/fsl_esdhc.c
> > +++ b/drivers/mmc/fsl_esdhc.c
> > @@ -62,7 +62,12 @@ struct fsl_esdhc {
> >     uint    hostcapblt2;    /* Host controller capabilities register 2 */
> >     char    reserved6[8];   /* reserved */
> >     uint    tbctl;          /* Tuning block control register */
> > -   char    reserved7[744]; /* reserved */
> > +   char    reserved7[32];  /* reserved */
> > +   uint    sdclkctl;       /* SD clock control register */
> > +   uint    sdtimingctl;    /* SD timing control register */
> > +   char    reserved8[20];  /* reserved */
> > +   uint    dllcfg0;        /* DLL config 0 register */
> > +   char    reserved9[680]; /* reserved */
> >     uint    esdhcctl;       /* eSDHC control register */
> >  };
> >
> > @@ -568,6 +573,38 @@ static void esdhc_clock_control(struct
> > fsl_esdhc_priv *priv, bool enable)
> >     }
> >  }
> >
> > +static void esdhc_flush_async_fifo(struct fsl_esdhc_priv *priv) {
> > +   struct fsl_esdhc *regs = priv->esdhc_regs;
> > +   u32 time_out;
> > +
> > +   esdhc_setbits32(&regs->esdhcctl, ESDHCCTL_FAF);
> > +
> > +   time_out = 20;
> > +   while (esdhc_read32(&regs->esdhcctl) & ESDHCCTL_FAF) {
> > +           if (time_out == 0) {
> > +                   printf("fsl_esdhc: Flush asynchronous FIFO timeout.\n");
> > +                   break;
> > +           }
> > +           time_out--;
> > +           mdelay(1);
> > +   }
> > +}
> > +
> > +static void esdhc_tuning_block_enable(struct fsl_esdhc_priv *priv,
> > +                                 bool en)
> > +{
> > +   struct fsl_esdhc *regs = priv->esdhc_regs;
> > +
> > +   esdhc_clock_control(priv, false);
> > +   esdhc_flush_async_fifo(priv);
> > +   if (en)
> > +           esdhc_setbits32(&regs->tbctl, TBCTL_TB_EN);
> > +   else
> > +           esdhc_clrbits32(&regs->tbctl, TBCTL_TB_EN);
> > +   esdhc_clock_control(priv, true);
> > +}
> > +
> >  static void esdhc_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode
> > mode)  {
> >     struct fsl_esdhc *regs = priv->esdhc_regs; @@ -577,7 +614,17 @@
> > static void esdhc_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode
> > mode)
> >     if (mode == MMC_HS_200)
> >             esdhc_clrsetbits32(&regs->autoc12err, UHSM_MASK,
> >                                UHSM_SDR104_HS200);
> > +   if (mode == MMC_HS_400) {
> > +           esdhc_setbits32(&regs->tbctl, HS400_MODE);
> > +           esdhc_setbits32(&regs->sdclkctl, CMD_CLK_CTL);
> > +           esdhc_clock_control(priv, true);
> >
> > +           esdhc_setbits32(&regs->dllcfg0, DLL_ENABLE | DLL_FREQ_SEL);
> > +           esdhc_setbits32(&regs->tbctl, HS400_WNDW_ADJUST);
> > +
> > +           esdhc_clock_control(priv, false);
> > +           esdhc_flush_async_fifo(priv);
> > +   }
> >     esdhc_clock_control(priv, true);
> >  }
> >
> > @@ -592,6 +639,9 @@ static int esdhc_set_ios_common(struct
> > fsl_esdhc_priv *priv, struct mmc *mmc)
> >             esdhc_clock_control(priv, true);
> >     }
> >
> > +   if (mmc->selected_mode == MMC_HS_400)
> > +           esdhc_tuning_block_enable(priv, true);
> > +
> >     /* Set the clock speed */
> >     if (priv->clock != mmc->clock)
> >             set_sysctl(priv, mmc, mmc->clock);
> > @@ -987,38 +1037,6 @@ static int fsl_esdhc_reinit(struct udevice *dev)  }
> >
> >  #ifdef MMC_SUPPORTS_TUNING
> > -static void esdhc_flush_async_fifo(struct fsl_esdhc_priv *priv) -{
> > -   struct fsl_esdhc *regs = priv->esdhc_regs;
> > -   u32 time_out;
> > -
> > -   esdhc_setbits32(&regs->esdhcctl, ESDHCCTL_FAF);
> > -
> > -   time_out = 20;
> > -   while (esdhc_read32(&regs->esdhcctl) & ESDHCCTL_FAF) {
> > -           if (time_out == 0) {
> > -                   printf("fsl_esdhc: Flush asynchronous FIFO timeout.\n");
> > -                   break;
> > -           }
> > -           time_out--;
> > -           mdelay(1);
> > -   }
> > -}
> > -
> > -static void esdhc_tuning_block_enable(struct fsl_esdhc_priv *priv,
> > -                                 bool en)
> > -{
> > -   struct fsl_esdhc *regs = priv->esdhc_regs;
> > -
> > -   esdhc_clock_control(priv, false);
> > -   esdhc_flush_async_fifo(priv);
> > -   if (en)
> > -           esdhc_setbits32(&regs->tbctl, TBCTL_TB_EN);
> > -   else
> > -           esdhc_clrbits32(&regs->tbctl, TBCTL_TB_EN);
> > -   esdhc_clock_control(priv, true);
> > -}
> > -
> >  static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode)
> {
> >     struct fsl_esdhc_plat *plat = dev_get_platdata(dev); @@ -1046,8
> > +1064,11 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev,
> > uint32_t opcode)
> >
> >     esdhc_write32(&regs->irqstaten, irqstaten);
> >
> > -   if (i != MAX_TUNING_LOOP)
> > +   if (i != MAX_TUNING_LOOP) {
> > +           if (plat->mmc.hs400_tuning)
> 
> Ok, it is used here, but I not see the benefit putting hs400_tunning into
> common
> mmc structure.

Do you have any suggestion if we don't use a flag to identify HS400 and HS200 
tuning in common mmc structure?
Thanks.

> 
> Regards,
> Peng.
> 
> > +                   esdhc_setbits32(&regs->sdtimingctl, FLW_CTL_BG);
> >             return 0;
> > +   }
> >
> >     printf("fsl_esdhc: tuning failed!\n");
> >     esdhc_clrbits32(&regs->autoc12err, SMPCLKSEL); @@ -1057,6 +1078,14
> > @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t
> > opcode)  }  #endif
> >
> > +int fsl_esdhc_hs400_prepare_ddr(struct udevice *dev) {
> > +   struct fsl_esdhc_priv *priv = dev_get_priv(dev);
> > +
> > +   esdhc_tuning_block_enable(priv, false);
> > +   return 0;
> > +}
> > +
> >  static const struct dm_mmc_ops fsl_esdhc_ops = {
> >     .get_cd         = fsl_esdhc_get_cd,
> >     .send_cmd       = fsl_esdhc_send_cmd,
> > @@ -1065,6 +1094,7 @@ static const struct dm_mmc_ops fsl_esdhc_ops =
> {
> >     .execute_tuning = fsl_esdhc_execute_tuning,  #endif
> >     .reinit = fsl_esdhc_reinit,
> > +   .hs400_prepare_ddr = fsl_esdhc_hs400_prepare_ddr,
> >  };
> >
> >  static const struct udevice_id fsl_esdhc_ids[] = { diff --git
> > a/include/fsl_esdhc.h b/include/fsl_esdhc.h index ada95bc..cbb2c34 100644
> > --- a/include/fsl_esdhc.h
> > +++ b/include/fsl_esdhc.h
> > @@ -176,6 +176,18 @@
> >
> >  /* Tuning block control register */
> >  #define TBCTL_TB_EN                0x00000004
> > +#define HS400_MODE         0x00000010
> > +#define HS400_WNDW_ADJUST  0x00000040
> > +
> > +/* SD clock control register */
> > +#define CMD_CLK_CTL                0x00008000
> > +
> > +/* SD timing control register */
> > +#define FLW_CTL_BG         0x00008000
> > +
> > +/* DLL config 0 register */
> > +#define DLL_ENABLE         0x80000000
> > +#define DLL_FREQ_SEL               0x08000000
> >
> >  #define MAX_TUNING_LOOP            40
> >
> > --
> > 2.7.4

Reply via email to