[U-Boot] [PATCH V4 1/2] mmc: add HS400 support

Tom Rini trini at konsulko.com
Wed Aug 29 11:21:26 UTC 2018


On Wed, Aug 29, 2018 at 12:35:05PM +0200, Marek Vasut wrote:

> On 08/29/2018 07:32 AM, Peng Fan wrote:
> > Hi,
> 
> Hi,
> 
> > Would anyone pick up this patchset? Tom, I delegated the patchset to you, would you mind pick it up? 
> 
> I've been nagging Tom about this for a while , he said he will pick it
> for next release, but having it in this one would be IMO fine, since it
> doesn't interfere with anything and it's been posted way before the RC
> cycle started.

Yes, I still intend to pick it up after v2018.09.  Thanks for the
reminder!

> 

> > Thanks,
> > Peng.
> > 
> > -----Original Message-----
> > From: Peng Fan 
> > Sent: 2018年8月10日 14:08
> > To: jh80.chung at samsung.com; sbabic at denx.de
> > Cc: u-boot at lists.denx.de; dl-linux-imx <linux-imx at nxp.com>; Peng Fan <peng.fan at nxp.com>; Jean-Jacques Hiblot <jjhiblot at ti.com>; Kishon Vijay Abraham I <kishon at ti.com>; Faiz Abbas <faiz_abbas at ti.com>; Marek Vasut <marex at denx.de>
> > Subject: [PATCH V4 1/2] mmc: add HS400 support
> > 
> > Add HS400 support.
> > Selecting HS400 needs first select HS200 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.
> > 
> > Signed-off-by: Peng Fan <peng.fan at nxp.com>
> > Cc: Jaehoon Chung <jh80.chung at samsung.com>
> > Cc: Jean-Jacques Hiblot <jjhiblot at ti.com>
> > Cc: Stefano Babic <sbabic at denx.de>
> > Cc: Kishon Vijay Abraham I <kishon at ti.com>
> > Cc: Faiz Abbas <faiz_abbas at ti.com>
> > Cc: Marek Vasut <marex at denx.de>
> > ---
> > 
> > V4:
> >  Add SPL_MMC_HS400_SUPPORT Kconfig entry  typo fix, HS199->HS200 in commit log.
> > 
> > V3:
> >  Simplify code
> >  add error msg
> > 
> > V2:
> >  remove 4bits support from HS400, as HS400 does not support 4bits per spec.
> > 
> >  drivers/mmc/Kconfig |  13 +++++
> >  drivers/mmc/mmc.c   | 137 +++++++++++++++++++++++++++++++++++++++++-----------
> >  include/mmc.h       |  11 +++++
> >  3 files changed, 134 insertions(+), 27 deletions(-)
> > 
> > diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 377b1c4b3b..1616022b91 100644
> > --- a/drivers/mmc/Kconfig
> > +++ b/drivers/mmc/Kconfig
> > @@ -111,6 +111,19 @@ 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 SPL_MMC_HS400_SUPPORT
> > +	bool "enable HS400 support in SPL"
> > +	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 ad429f49c9..585951cd78 100644
> > --- a/drivers/mmc/mmc.c
> > +++ b/drivers/mmc/mmc.c
> > @@ -147,6 +147,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)
> > @@ -171,6 +172,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)
> > @@ -769,6 +771,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;
> > @@ -816,7 +823,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)
> > @@ -824,6 +831,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) @@ -1734,10 +1747,13 @@ static int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode,
> >  	u32 card_mask = 0;
> >  
> >  	switch (mode) {
> > +	case MMC_HS_400:
> >  	case MMC_HS_200:
> > -		if (mmc->cardtype & EXT_CSD_CARD_TYPE_HS200_1_8V)
> > +		if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_8V |
> > +		    EXT_CSD_CARD_TYPE_HS400_1_8V))
> >  			card_mask |= MMC_SIGNAL_VOLTAGE_180;
> > -		if (mmc->cardtype & EXT_CSD_CARD_TYPE_HS200_1_2V)
> > +		if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V |
> > +		    EXT_CSD_CARD_TYPE_HS400_1_2V))
> >  			card_mask |= MMC_SIGNAL_VOLTAGE_120;
> >  		break;
> >  	case MMC_DDR_52:
> > @@ -1773,6 +1789,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,
> > +		.tuning = MMC_CMD_SEND_TUNING_BLOCK_HS200
> > +	},
> > +#endif
> >  #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
> >  	{
> >  		.mode = MMC_HS_200,
> > @@ -1816,6 +1839,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;
> > +
> > +	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);\ @@ -1869,37 +1940,49 @@ 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);
> > +				if (err) {
> > +					printf("Select HS400 failed %d\n", 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, MMC_CLK_ENABLE);
> > +				/*
> > +				 * 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,
> > +					      MMC_CLK_ENABLE);
> >  #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 df4255b828..9b9cbedadc 100644
> > --- a/include/mmc.h
> > +++ b/include/mmc.h
> > @@ -64,6 +64,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)
> > @@ -248,6 +249,10 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
> >  						/* SDR mode @1.2V I/O */
> >  #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 */
> > @@ -259,6 +264,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)
> > @@ -519,6 +525,7 @@ enum bus_mode {
> >  	UHS_DDR50,
> >  	UHS_SDR104,
> >  	MMC_HS_200,
> > +	MMC_HS_400,
> >  	MMC_MODES_END
> >  };
> >  
> > @@ -532,6 +539,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;
> > --
> > 2.14.1
> > 
> 
> 
> -- 
> Best regards,
> Marek Vasut

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180829/dbfda43d/attachment.sig>


More information about the U-Boot mailing list