> Subject: [PATCH V2 1/7] mmc: support hs400 enhanced strobe mode
> 
> eMMC 5.1+ supports HS400 Enhances Strobe mode without the need for
> tuning procedure.
> The flow is as following:
>  - set HS_TIMIMG (Highspeed)
>  - Host change freq to <= 52Mhz
>  - set the bus width to Enhanced strobe and DDR8Bit(CMD6),
>    EXT_CSD[183] = 0x86 instead of 0x80
>  - set HS_TIMING to 0x3 (HS400)
>  - Host change freq to <= 200Mhz
>  - Host select HS400 enhanced strobe complete
> 
> Signed-off-by: Peng Fan <[email protected]>
> Cc: Jean-Jacques Hiblot <[email protected]>
> Cc: Baruch Siach <[email protected]>
> Cc: Michal Simek <[email protected]>
> Cc: T Karthik Reddy <[email protected]>
> Cc: Simon Glass <[email protected]>
> Cc: Marek Vasut <[email protected]>
> Cc: Jon Nettleton <[email protected]>
> ---
> 
> V2:
>  Add return value for mmc strobe functions  Use mmc_set_card_speed to
> replace mmc_switch
> 
>  drivers/mmc/Kconfig      | 12 ++++++++
>  drivers/mmc/mmc-uclass.c | 17 ++++++++++++
>  drivers/mmc/mmc.c        | 72
> +++++++++++++++++++++++++++++++++++++++++++++++-
>  include/mmc.h            | 15 ++++++++++
>  4 files changed, 115 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index
> 93588725f2..f22c0a0589 100644
> --- a/drivers/mmc/Kconfig
> +++ b/drivers/mmc/Kconfig
> @@ -117,6 +117,18 @@ config SPL_MMC_UHS_SUPPORT
>         cards. The IO voltage must be switchable from 3.3v to 1.8v. The bus
>         frequency can go up to 208MHz (SDR104)
> 
> +config MMC_HS400_ES_SUPPORT
> +     bool "enable HS400 Enhanced Strobe support"
> +     help
> +       The HS400 Enhanced Strobe mode is support by some eMMC. The bus
> +       frequency is up to 200MHz. This mode does not tune the IO.
> +
> +config SPL_MMC_HS400_ES_SUPPORT
> +     bool "enable HS400 Enhanced Strobe support in SPL"
> +     help
> +       The HS400 Enhanced Strobe mode is support by some eMMC. The bus
> +       frequency is up to 200MHz. This mode does not tune the IO.
> +
>  config MMC_HS400_SUPPORT
>       bool "enable HS400 support"
>       select MMC_HS200_SUPPORT
> diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index
> fa4d1af55d..890b380f1f 100644
> --- a/drivers/mmc/mmc-uclass.c
> +++ b/drivers/mmc/mmc-uclass.c
> @@ -120,6 +120,23 @@ int mmc_execute_tuning(struct mmc *mmc, uint
> opcode)  }  #endif
> 
> +#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
> +int dm_mmc_set_enhanced_strobe(struct udevice *dev) {
> +     struct dm_mmc_ops *ops = mmc_get_ops(dev);
> +
> +     if (ops->set_enhanced_strobe)
> +             return ops->set_enhanced_strobe(dev);
> +
> +     return -ENOTSUPP;
> +}
> +
> +int mmc_set_enhanced_strobe(struct mmc *mmc) {
> +     return dm_mmc_set_enhanced_strobe(mmc->dev);
> +}
> +#endif
> +
>  int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg)  {
>       int val;
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index
> 71b52c6cf2..c6b5488352 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -148,6 +148,7 @@ const char *mmc_mode_name(enum bus_mode
> mode)
>             [MMC_DDR_52]      = "MMC DDR52 (52MHz)",
>             [MMC_HS_200]      = "HS200 (200MHz)",
>             [MMC_HS_400]      = "HS400 (200MHz)",
> +           [MMC_HS_400_ES]   = "HS400ES (200MHz)",
>       };
> 
>       if (mode >= MMC_MODES_END)
> @@ -173,6 +174,7 @@ static uint mmc_mode2freq(struct mmc *mmc, enum
> bus_mode mode)
>             [UHS_SDR104]      = 208000000,
>             [MMC_HS_200]      = 200000000,
>             [MMC_HS_400]      = 200000000,
> +           [MMC_HS_400_ES]   = 200000000,
>       };
> 
>       if (mode == MMC_LEGACY)
> @@ -788,6 +790,11 @@ static int mmc_set_card_speed(struct mmc *mmc,
> enum bus_mode mode,
>       case MMC_HS_400:
>               speed_bits = EXT_CSD_TIMING_HS400;
>               break;
> +#endif
> +#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
> +     case MMC_HS_400_ES:
> +             speed_bits = EXT_CSD_TIMING_HS400;
> +             break;
>  #endif
>       case MMC_LEGACY:
>               speed_bits = EXT_CSD_TIMING_LEGACY;
> @@ -859,7 +866,8 @@ static int mmc_get_capabilities(struct mmc *mmc)
>               mmc->card_caps |= MMC_MODE_HS200;
>       }
>  #endif
> -#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
> +#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) || \
> +     CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
>       if (cardtype & (EXT_CSD_CARD_TYPE_HS400_1_2V |
>                       EXT_CSD_CARD_TYPE_HS400_1_8V)) {
>               mmc->card_caps |= MMC_MODE_HS400;
> @@ -873,6 +881,13 @@ static int mmc_get_capabilities(struct mmc *mmc)
>       if (cardtype & EXT_CSD_CARD_TYPE_26)
>               mmc->card_caps |= MMC_MODE_HS;
> 
> +#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
> +     if (ext_csd[EXT_CSD_STROBE_SUPPORT] &&
> +         (mmc->card_caps & MMC_MODE_HS400)) {
> +             mmc->card_caps |= MMC_MODE_HS400_ES;
> +     }
> +#endif
> +
>       return 0;
>  }
>  #endif
> @@ -1778,6 +1793,7 @@ static int mmc_set_lowest_voltage(struct mmc
> *mmc, enum bus_mode mode,
>       u32 card_mask = 0;
> 
>       switch (mode) {
> +     case MMC_HS_400_ES:
>       case MMC_HS_400:
>       case MMC_HS_200:
>               if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_8V | @@
> -1820,6 +1836,12 @@ static inline int mmc_set_lowest_voltage(struct mmc
> *mmc, enum bus_mode mode,  #endif
> 
>  static const struct mode_width_tuning mmc_modes_by_pref[] = {
> +#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
> +     {
> +             .mode = MMC_HS_400_ES,
> +             .widths = MMC_MODE_8BIT,
> +     },
> +#endif
>  #if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
>       {
>               .mode = MMC_HS_400,
> @@ -1917,6 +1939,47 @@ static int mmc_select_hs400(struct mmc
> *mmc)  }  #endif
> 
> +#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
> +#if !CONFIG_IS_ENABLED(DM_MMC)
> +static int mmc_set_enhanced_strobe(struct mmc *mmc) {
> +     return -ENOTSUPP;
> +}
> +#endif
> +static int mmc_select_hs400es(struct mmc *mmc) {
> +     int err;
> +
> +     err = mmc_set_card_speed(mmc, MMC_HS, true);
> +     if (err)
> +             return err;
> +
> +     err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
> EXT_CSD_BUS_WIDTH,
> +                      EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG |
> +                      EXT_CSD_BUS_WIDTH_STROBE);
> +     if (err) {
> +             printf("switch to bus width for hs400 failed\n");
> +             return err;
> +     }
> +     /* TODO: driver strength */
> +     err = mmc_set_card_speed(mmc, MMC_HS_400_ES, false);
> +     if (err)
> +             return err;
> +
> +     mmc_select_mode(mmc, MMC_HS_400_ES);
> +     err = mmc_set_clock(mmc, mmc->tran_speed, false);
> +     if (err)
> +             return err;
> +
> +     return mmc_set_enhanced_strobe(mmc);
> +}
> +#else
> +static int mmc_select_hs400es(struct mmc *mmc) {
> +     return -ENOTSUPP;
> +}
> +#endif
> +
>  #define for_each_supported_width(caps, ddr, ecbv) \
>       for (ecbv = ext_csd_bus_width;\
>           ecbv < ext_csd_bus_width + ARRAY_SIZE(ext_csd_bus_width);\
> @@ -1988,6 +2051,13 @@ static int mmc_select_mode_and_width(struct
> mmc *mmc, uint card_caps)
>                                       printf("Select HS400 failed %d\n", err);
>                                       goto error;
>                               }
> +                     } else if (mwt->mode == MMC_HS_400_ES) {
> +                             err = mmc_select_hs400es(mmc);
> +                             if (err) {
> +                                     printf("Select HS400ES failed %d\n",
> +                                            err);
> +                                     goto error;
> +                             }
>                       } else {
>                               /* configure the bus speed (card) */
>                               err = mmc_set_card_speed(mmc, mwt->mode, 
> false); diff
> --git a/include/mmc.h b/include/mmc.h index 2be3e91fcb..b42687395c
> 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -65,6 +65,7 @@
>  #define MMC_MODE_DDR_52MHz   MMC_CAP(MMC_DDR_52)
>  #define MMC_MODE_HS200               MMC_CAP(MMC_HS_200)
>  #define MMC_MODE_HS400               MMC_CAP(MMC_HS_400)
> +#define MMC_MODE_HS400_ES    MMC_CAP(MMC_HS_400_ES)
> 
>  #define MMC_CAP_NONREMOVABLE BIT(14)
>  #define MMC_CAP_NEEDS_POLL   BIT(15)
> @@ -223,6 +224,7 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
>  #define EXT_CSD_BOOT_BUS_WIDTH               177
>  #define EXT_CSD_PART_CONF            179     /* R/W */
>  #define EXT_CSD_BUS_WIDTH            183     /* R/W */
> +#define EXT_CSD_STROBE_SUPPORT               184     /* R/W */
>  #define EXT_CSD_HS_TIMING            185     /* R/W */
>  #define EXT_CSD_REV                  192     /* RO */
>  #define EXT_CSD_CARD_TYPE            196     /* RO */
> @@ -264,11 +266,13 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
>  #define EXT_CSD_DDR_BUS_WIDTH_4      5       /* Card is in 4 bit DDR mode
> */
>  #define EXT_CSD_DDR_BUS_WIDTH_8      6       /* Card is in 8 bit DDR mode
> */
>  #define EXT_CSD_DDR_FLAG     BIT(2)  /* Flag for DDR mode */
> +#define EXT_CSD_BUS_WIDTH_STROBE BIT(7)      /* Enhanced strobe mode */
> 
>  #define EXT_CSD_TIMING_LEGACY        0       /* no high speed */
>  #define EXT_CSD_TIMING_HS    1       /* HS */
>  #define EXT_CSD_TIMING_HS200 2       /* HS200 */
>  #define EXT_CSD_TIMING_HS400 3       /* HS400 */
> +#define EXT_CSD_DRV_STR_SHIFT        4       /* Driver Strength shift */
> 
>  #define EXT_CSD_BOOT_ACK_ENABLE                      (1 << 6)
>  #define EXT_CSD_BOOT_PARTITION_ENABLE                (1 << 3)
> @@ -465,6 +469,11 @@ struct dm_mmc_ops {
>        */
>       int (*wait_dat0)(struct udevice *dev, int state, int timeout);  #endif
> +
> +#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
> +     /* set_enhanced_strobe() - set HS400 enhanced strobe */
> +     int (*set_enhanced_strobe)(struct udevice *dev); #endif
>  };
> 
>  #define mmc_get_ops(dev)        ((struct dm_mmc_ops
> *)(dev)->driver->ops)
> @@ -485,6 +494,7 @@ int mmc_getcd(struct mmc *mmc);  int
> mmc_getwp(struct mmc *mmc);  int mmc_execute_tuning(struct mmc
> *mmc, uint opcode);  int mmc_wait_dat0(struct mmc *mmc, int state, int
> timeout);
> +int mmc_set_enhanced_strobe(struct mmc *mmc);
> 
>  #else
>  struct mmc_ops {
> @@ -530,6 +540,7 @@ enum bus_mode {
>       UHS_SDR104,
>       MMC_HS_200,
>       MMC_HS_400,
> +     MMC_HS_400_ES,
>       MMC_MODES_END
>  };
> 
> @@ -547,6 +558,10 @@ static inline bool mmc_is_mode_ddr(enum
> bus_mode mode)  #if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
>       else if (mode == MMC_HS_400)
>               return true;
> +#endif
> +#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
> +     else if (mode == MMC_HS_400_ES)
> +             return true;
>  #endif
>       else
>               return false;

Patchset applied to mmc/master after rebasing minor conflicts fixed in 1/7.

Thanks,
Peng.
> --
> 2.16.4

_______________________________________________
U-Boot mailing list
[email protected]
https://lists.denx.de/listinfo/u-boot

Reply via email to