[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