[U-Boot] [PATCH V2 1/7] mmc: support hs400 enhanced strobe mode

Peng Fan peng.fan at nxp.com
Mon Jul 15 07:08:26 UTC 2019


> 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 <peng.fan at nxp.com>
> Cc: Jean-Jacques Hiblot <jjhiblot at ti.com>
> Cc: Baruch Siach <baruch at tkos.co.il>
> Cc: Michal Simek <michal.simek at xilinx.com>
> Cc: T Karthik Reddy <t.karthik.reddy at xilinx.com>
> Cc: Simon Glass <sjg at chromium.org>
> Cc: Marek Vasut <marek.vasut+renesas at gmail.com>
> Cc: Jon Nettleton <jon at solid-run.com>
> ---
> 
> 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



More information about the U-Boot mailing list