Hi,

On 03/05/2018 06:11 PM, Peng Fan wrote:
> Add HS400 support.
> Selecting HS400 needs first select HS199 according to spec, so use
> a dedicated function for HS400.
> Add HS400 related macros.
> Remove the restriction of only using the low 6 bits of
> EXT_CSD_CARD_TYPE, using all the 8 bits.

Sorry for late.

> 
> Signed-off-by: Peng Fan <[email protected]>
> Cc: Jaehoon Chung <[email protected]>
> Cc: Jean-Jacques Hiblot <[email protected]>
> Cc: Stefano Babic <[email protected]>
> Cc: Simon Glass <[email protected]>
> Cc: Kishon Vijay Abraham I <[email protected]>
> Cc: Bin Meng <[email protected]>
> ---
>  drivers/mmc/Kconfig |   7 +++
>  drivers/mmc/mmc.c   | 133 
> ++++++++++++++++++++++++++++++++++++++++++----------
>  include/mmc.h       |  12 +++++
>  3 files changed, 127 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
> index 5f67e336db..e9be18b333 100644
> --- a/drivers/mmc/Kconfig
> +++ b/drivers/mmc/Kconfig
> @@ -104,6 +104,13 @@ 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_SUPPORT
> +     bool "enable HS400 support"
> +     select MMC_HS200_SUPPORT
> +     help
> +       The HS400 mode is support by some eMMC. The bus frequency is up to
> +       200MHz. This mode requires tuning the IO.
> +
>  config MMC_HS200_SUPPORT
>       bool "enable HS200 support"
>       help
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 92ea78b8af..eef229c8b4 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -169,6 +169,7 @@ const char *mmc_mode_name(enum bus_mode mode)
>             [MMC_HS_52]       = "MMC High Speed (52MHz)",
>             [MMC_DDR_52]      = "MMC DDR52 (52MHz)",
>             [MMC_HS_200]      = "HS200 (200MHz)",
> +           [MMC_HS_400]      = "HS400 (200MHz)",
>       };
>  
>       if (mode >= MMC_MODES_END)
> @@ -193,6 +194,7 @@ static uint mmc_mode2freq(struct mmc *mmc, enum bus_mode 
> mode)
>             [UHS_DDR50]       = 50000000,
>             [UHS_SDR104]      = 208000000,
>             [MMC_HS_200]      = 200000000,
> +           [MMC_HS_400]      = 200000000,
>       };
>  
>       if (mode == MMC_LEGACY)
> @@ -790,6 +792,11 @@ static int mmc_set_card_speed(struct mmc *mmc, enum 
> bus_mode mode)
>       case MMC_HS_200:
>               speed_bits = EXT_CSD_TIMING_HS200;
>               break;
> +#endif
> +#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
> +     case MMC_HS_400:
> +             speed_bits = EXT_CSD_TIMING_HS400;
> +             break;>  #endif
>       case MMC_LEGACY:
>               speed_bits = EXT_CSD_TIMING_LEGACY;
> @@ -837,7 +844,7 @@ static int mmc_get_capabilities(struct mmc *mmc)
>  
>       mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
>  
> -     cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0x3f;
> +     cardtype = ext_csd[EXT_CSD_CARD_TYPE];
>       mmc->cardtype = cardtype;
>  
>  #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
> @@ -845,6 +852,12 @@ static int mmc_get_capabilities(struct mmc *mmc)
>                       EXT_CSD_CARD_TYPE_HS200_1_8V)) {
>               mmc->card_caps |= MMC_MODE_HS200;
>       }
> +#endif
> +#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
> +     if (cardtype & (EXT_CSD_CARD_TYPE_HS400_1_2V |
> +                     EXT_CSD_CARD_TYPE_HS400_1_8V)) {
> +             mmc->card_caps |= MMC_MODE_HS400;
> +     }
>  #endif
>       if (cardtype & EXT_CSD_CARD_TYPE_52) {
>               if (cardtype & EXT_CSD_CARD_TYPE_DDR_52)
> @@ -1748,6 +1761,12 @@ static int mmc_set_lowest_voltage(struct mmc *mmc, 
> enum bus_mode mode,
>       u32 card_mask = 0;
>  
>       switch (mode) {
> +     case MMC_HS_400:
> +             if (mmc->cardtype & EXT_CSD_CARD_TYPE_HS400_1_8V)
> +                     card_mask |= MMC_SIGNAL_VOLTAGE_180;
> +             if (mmc->cardtype & EXT_CSD_CARD_TYPE_HS400_1_2V)
> +                     card_mask |= MMC_SIGNAL_VOLTAGE_120;
> +             break;

I think that it's possible to use the below.

case MMS_HS_400:
case MMC_HS_200:
        if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_8V | 
EXT_CSD_CARD_TYPE_HS400_1_8V)
                ....

Isn't it?

>       case MMC_HS_200:
>               if (mmc->cardtype & EXT_CSD_CARD_TYPE_HS200_1_8V)
>                       card_mask |= MMC_SIGNAL_VOLTAGE_180;
> @@ -1787,6 +1806,13 @@ 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_SUPPORT)
> +     {
> +             .mode = MMC_HS_400,
> +             .widths = MMC_MODE_8BIT | MMC_MODE_4BIT,

4BIT? As i know, HS400 mode doesn't support the 4BIT mode.

> +             .tuning = MMC_CMD_SEND_TUNING_BLOCK_HS200
> +     },
> +#endif
>  #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
>       {
>               .mode = MMC_HS_200,
> @@ -1830,6 +1856,54 @@ static const struct ext_csd_bus_width {
>       {MMC_MODE_1BIT, false, EXT_CSD_BUS_WIDTH_1},
>  };
>  
> +#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
> +static int mmc_select_hs400(struct mmc *mmc)
> +{
> +     int err;
> +
> +     /* Set timing to HS200 for tuning */
> +     err = mmc_set_card_speed(mmc, MMC_HS_200);
> +     if (err)
> +             return err;
> +
> +     /* configure the bus mode (host) */
> +     mmc_select_mode(mmc, MMC_HS_200);
> +     mmc_set_clock(mmc, mmc->tran_speed, false);
> +
> +     /* execute tuning if needed */
> +     err = mmc_execute_tuning(mmc, MMC_CMD_SEND_TUNING_BLOCK_HS200);
> +     if (err) {
> +             debug("tuning failed\n");
> +             return err;
> +     }
> +
> +     /* Set back to HS */
> +     mmc_set_card_speed(mmc, MMC_HS);
> +     mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS), false);
> +
> +     err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
> +                      EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG);
> +     if (err)
> +             return err;
> +
> +     err = mmc_set_card_speed(mmc, MMC_HS_400);
> +     if (err)
> +             return err;
> +
> +     mmc_select_mode(mmc, MMC_HS_400);
> +     err = mmc_set_clock(mmc, mmc->tran_speed, false);
> +     if (err)
> +             return err;

Hmm. I didn't test this patch.. but i guess if it's failed, isn't it possible 
to use the other bus mode?

> +
> +     return 0;
> +}
> +#else
> +static int mmc_select_hs400(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);\
> @@ -1883,37 +1957,46 @@ static int mmc_select_mode_and_width(struct mmc *mmc, 
> uint card_caps)
>                               goto error;
>                       mmc_set_bus_width(mmc, bus_width(ecbw->cap));
>  
> -                     /* configure the bus speed (card) */
> -                     err = mmc_set_card_speed(mmc, mwt->mode);
> -                     if (err)
> -                             goto error;
> -
> -                     /*
> -                      * configure the bus width AND the ddr mode (card)
> -                      * The host side will be taken care of in the next step
> -                      */
> -                     if (ecbw->ext_csd_bits & EXT_CSD_DDR_FLAG) {
> -                             err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
> -                                              EXT_CSD_BUS_WIDTH,
> -                                              ecbw->ext_csd_bits);
> +                     if (mwt->mode == MMC_HS_400) {
> +                             err = mmc_select_hs400(mmc);

doesn't need to add some error message? It's useful to notice to user.

> +                             if (err)
> +                                     goto error;
> +                     } else {
> +                             /* configure the bus speed (card) */
> +                             err = mmc_set_card_speed(mmc, mwt->mode);
>                               if (err)
>                                       goto error;
> -                     }
>  
> -                     /* configure the bus mode (host) */
> -                     mmc_select_mode(mmc, mwt->mode);
> -                     mmc_set_clock(mmc, mmc->tran_speed, false);
> +                             /*
> +                              * configure the bus width AND the ddr mode
> +                              * (card). The host side will be taken care
> +                              * of in the next step
> +                              */
> +                             if (ecbw->ext_csd_bits & EXT_CSD_DDR_FLAG) {
> +                                     err = mmc_switch(mmc,
> +                                                      EXT_CSD_CMD_SET_NORMAL,
> +                                                      EXT_CSD_BUS_WIDTH,
> +                                                      ecbw->ext_csd_bits);
> +                                     if (err)
> +                                             goto error;
> +                             }
> +
> +                             /* configure the bus mode (host) */
> +                             mmc_select_mode(mmc, mwt->mode);
> +                             mmc_set_clock(mmc, mmc->tran_speed, false);
>  #ifdef MMC_SUPPORTS_TUNING
>  
> -                     /* execute tuning if needed */
> -                     if (mwt->tuning) {
> -                             err = mmc_execute_tuning(mmc, mwt->tuning);
> -                             if (err) {
> -                                     pr_debug("tuning failed\n");
> -                                     goto error;
> +                             /* execute tuning if needed */
> +                             if (mwt->tuning) {
> +                                     err = mmc_execute_tuning(mmc,
> +                                                              mwt->tuning);
> +                                     if (err) {
> +                                             pr_debug("tuning failed\n");
> +                                             goto error;
> +                                     }
>                               }
> -                     }
>  #endif
> +                     }
>  
>                       /* do a transfer to check the configuration */
>                       err = mmc_read_and_compare_ext_csd(mmc);
> diff --git a/include/mmc.h b/include/mmc.h
> index 86f885b504..8c01c6a530 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -65,6 +65,7 @@
>  #define MMC_MODE_HS_52MHz    MMC_CAP(MMC_HS_52)
>  #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_8BIT                BIT(30)
>  #define MMC_MODE_4BIT                BIT(29)
> @@ -250,6 +251,11 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
>  #define EXT_CSD_CARD_TYPE_HS200              (EXT_CSD_CARD_TYPE_HS200_1_8V | 
> \
>                                        EXT_CSD_CARD_TYPE_HS200_1_2V)
>  
> +#define EXT_CSD_CARD_TYPE_HS400_1_8V BIT(6)
> +#define EXT_CSD_CARD_TYPE_HS400_1_2V BIT(7)
> +#define EXT_CSD_CARD_TYPE_HS400              (EXT_CSD_CARD_TYPE_HS400_1_8V | 
> \
> +                                      EXT_CSD_CARD_TYPE_HS400_1_2V)
> +
>  #define EXT_CSD_BUS_WIDTH_1  0       /* Card is in 1 bit mode */
>  #define EXT_CSD_BUS_WIDTH_4  1       /* Card is in 4 bit mode */
>  #define EXT_CSD_BUS_WIDTH_8  2       /* Card is in 8 bit mode */
> @@ -260,6 +266,7 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
>  #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_BOOT_ACK_ENABLE                      (1 << 6)
>  #define EXT_CSD_BOOT_PARTITION_ENABLE                (1 << 3)
> @@ -520,6 +527,7 @@ enum bus_mode {
>       UHS_DDR50,
>       UHS_SDR104,
>       MMC_HS_200,
> +     MMC_HS_400,
>       MMC_MODES_END
>  };
>  
> @@ -533,6 +541,10 @@ static inline bool mmc_is_mode_ddr(enum bus_mode mode)
>  #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
>       else if (mode == UHS_DDR50)
>               return true;
> +#endif
> +#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
> +     else if (mode == MMC_HS_400)
> +             return true;
>  #endif
>       else
>               return false;
> 

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

Reply via email to