From: Peng Fan <van.freenix@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 1/2] mmc: add HS400 support
Date: Tue, 6 Mar 2018 09:46:04 +0800 [thread overview]
Message-ID: <20180306014604.GA18685@shlinux2> (raw)
In-Reply-To: <592c7f4d-6fbe-3e6f-fcda-bbc7788f05c5@ti.com>
Hi,
On Mon, Mar 05, 2018 at 05:29:08PM +0100, Jean-Jacques Hiblot wrote:
>Hi Peng,
>
>I'm glad you are adding HS400 support. Thanks.
>
>
>On 05/03/2018 10:11, 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.
>>
>>Signed-off-by: Peng Fan <peng.fan@nxp.com>
>>Cc: Jaehoon Chung <jh80.chung@samsung.com>
>>Cc: Jean-Jacques Hiblot <jjhiblot@ti.com>
>>Cc: Stefano Babic <sbabic@denx.de>
>>Cc: Simon Glass <sjg@chromium.org>
>>Cc: Kishon Vijay Abraham I <kishon@ti.com>
>>Cc: Bin Meng <bmeng.cn@gmail.com>
>>---
>> 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
>I'd use "depends on" instead of select or maybe use the same option
>for both HS200 and HS400
>>+ 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;
>> 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,
>>+ .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);
>What happens if only 4 wires are used. It is a legit mode, isn't it ?
According to spec, HS400 only supports 8bits mode, see "5.3.6 HS400 Bus Speed Mode".
>>+ 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);\
>>@@ -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);
>>+ if (err)
>>+ goto error;
>>+ } else {
>>+ /* configure the bus speed (card) */
>>+ err = mmc_set_card_speed(mmc, mwt->mode);
>Instead of having?? a separate mmc_select_hs400() is not possible to
>leverage the existing code ?
hs400 requires first runs into HS200 mode, after tuning finished,
need switch back to HS mode to configure bus. It's not that straightforward
to use the existing code. Use a dedicated mmc_select_hs400 will make it
clearer compared with adding more logic in the existing flow.
Thanks,
Peng.
>
>JJ
>
>> 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
>U-Boot at lists.denx.de
>https://lists.denx.de/listinfo/u-boot
--
next prev parent reply other threads:[~2018-03-06 1:46 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <CGME20180426103029epcas1p4f0292a99571b6970f61d67ff42728fb0@epcas1p4.samsung.com>
2018-03-05 9:11 ` [U-Boot] [PATCH 1/2] mmc: add HS400 support Peng Fan
2018-03-05 9:11 ` [U-Boot] [PATCH 2/2] mmc: fsl_esdhc: enable HS400 feature Peng Fan
2018-04-26 10:30 ` [U-Boot] [U-Boot,2/2] " Jaehoon Chung
2018-03-05 16:29 ` [U-Boot] [PATCH 1/2] mmc: add HS400 support Jean-Jacques Hiblot
2018-03-06 1:46 ` Peng Fan [this message]
2018-03-06 14:35 ` Jean-Jacques Hiblot
2018-03-07 2:07 ` Peng Fan
2018-03-06 17:41 ` Simon Glass
2018-03-07 2:12 ` Peng Fan
2018-04-26 10:30 ` [U-Boot] [U-Boot,1/2] " Jaehoon Chung
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180306014604.GA18685@shlinux2 \
--to=van.freenix@gmail.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox