All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
@ 2017-05-12 18:16 ` Jean-Jacques Hiblot
  2017-05-12 18:16   ` [U-Boot] [PATCH 01/22] mmc: split mmc_startup() Jean-Jacques Hiblot
                     ` (23 more replies)
  0 siblings, 24 replies; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

This series brings support for HS200 and UHS modes to the mmc core.
It has been tested with the hsmmc driver on several platforms (DRA7,
AM57x, AM437x, beaglebone black). Some modifications are required in
the host driver to take advantage of this (voltage switching, tuning).
The changes to the host driver will be posted a another series as this
one is already long enough. 

The series starts with a small refactoring of th sd/mmc startup. The first 4 commits
are mostly moving code around with little or no functionnal change.

Then the notion of "mode" is introduced. Until now, this information wasn't
kept in struct mmc. Only the clock and a flag for ddr was kept. Later the mode
information will be used to select the clock frequency, the ddr flag and the
tuning procedure. It will be also be check against the host capabilities.

Then comes the big refactoring job in:
"mmc: refactor MMC startup to make it easier to support new modes" and
"mmc: refactor SD startup to make it easier to support new modes"
Since the number of modes is increasing, it makes sense to try them in a more
organized way. those commits use a list of supported modes and iterate through
them to find the best working one. It also allows to switch more easilly from
one mode to another (switching from HS200 to DDR52 to access boot partitions for example)

Then there are a couple of new callback added to:
- enable/disable Vdd
- check if the card is busy (used during UHS voltage switching)
- select the IO voltage

Then Power cycle is added. Without power cycle, if a UHS card fails to enumerate in
UHS mode, it can't fall back to high speed mode and card enumeration will fail.

And finally the last commits add the support for HS200 and UHS.
I haven't been able to test the UHS SDR104 mode by lack of compatible sdcard.

With this in place and the required changes in the HSMMC (including DAM), we observe significant
improvements in the performances on a DRA7 evm:
eMMC HS200: 130 MB/s
eMMC DDR52: 80 MB/s
sd   SDR50: 80 MB/s

cheers,

Jean-Jacques


Jean-Jacques Hiblot (18):
  mmc: split mmc_startup()
  mmc: move the MMC startup for version above v4.0 in a separate
    function
  mmc: make ext_csd part of struct mmc
  mmc: add a function to read and test the ext csd (mmc >= 4)
  mmc: introduces mmc modes.
  mmc: Add a fonction to dump the mmc capabilities
  mmc: use mmc modes to select the correct bus speed
  cmd: mmc: display the mode name and current bus speed in the mmc info
  mmc: refactor SD startup to make it easier to support new modes
  mmc: refactor MMC startup to make it easier to support new modes
  mmc: make mmc_set_ios() return status
  mmc: add power cyle support in mmc core
  mmc: add a new mmc parameter to disable mmc clock
  mmc: Add a execute_tuning() callback to the mmc operations.
  mmc: add HS200 support in MMC core
  mmc: Add a new callback function to check if the card is busy
  mmc: Add support for UHS modes
  mmc: Change mode when switching to a boot partition

Kishon Vijay Abraham I (3):
  mmc: Enable signal voltage to be selected from mmc core
  mmc: Add a new callback function to enable/disable vdd
  mmc: disable the mmc clock during power off

Vignesh R (1):
  mmc: Retry some MMC cmds on failure

 cmd/mmc.c                |    3 +-
 drivers/mmc/fsl_esdhc.c  |    2 +-
 drivers/mmc/mmc-uclass.c |   42 ++
 drivers/mmc/mmc.c        | 1220 +++++++++++++++++++++++++++++++++-------------
 include/mmc.h            |  138 +++++-
 5 files changed, 1058 insertions(+), 347 deletions(-)

-- 
1.9.1

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 01/22] mmc: split mmc_startup()
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:27     ` Simon Glass
  2017-05-12 18:16   ` [U-Boot] [PATCH 02/22] mmc: move the MMC startup for version above v4.0 in a separate function Jean-Jacques Hiblot
                     ` (22 subsequent siblings)
  23 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

No functionnal change here. The function is really big and can be split.
The part related to bus configuration are put in 2 separate functions: one
for MMC and one for SD.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc.c | 275 +++++++++++++++++++++++++++++-------------------------
 1 file changed, 149 insertions(+), 126 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 72fc177..7a17bac 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1103,6 +1103,153 @@ static void mmc_set_bus_width(struct mmc *mmc, uint width)
 	mmc_set_ios(mmc);
 }
 
+static int sd_select_bus_freq_width(struct mmc *mmc)
+{
+	int err;
+	struct mmc_cmd cmd;
+
+	err = sd_change_freq(mmc);
+	if (err)
+		return err;
+
+	/* Restrict card's capabilities by what the host can do */
+	mmc->card_caps &= mmc->cfg->host_caps;
+
+	if (mmc->card_caps & MMC_MODE_4BIT) {
+		cmd.cmdidx = MMC_CMD_APP_CMD;
+		cmd.resp_type = MMC_RSP_R1;
+		cmd.cmdarg = mmc->rca << 16;
+
+		err = mmc_send_cmd(mmc, &cmd, NULL);
+		if (err)
+			return err;
+
+		cmd.cmdidx = SD_CMD_APP_SET_BUS_WIDTH;
+		cmd.resp_type = MMC_RSP_R1;
+		cmd.cmdarg = 2;
+		err = mmc_send_cmd(mmc, &cmd, NULL);
+		if (err)
+			return err;
+
+		mmc_set_bus_width(mmc, 4);
+	}
+
+	err = sd_read_ssr(mmc);
+	if (err)
+		return err;
+
+	if (mmc->card_caps & MMC_MODE_HS)
+		mmc->tran_speed = 50000000;
+	else
+		mmc->tran_speed = 25000000;
+
+	return 0;
+}
+
+static int mmc_select_bus_freq_width(struct mmc *mmc, const u8 *ext_csd)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
+	/* An array of possible bus widths in order of preference */
+	static const unsigned ext_csd_bits[] = {
+		EXT_CSD_DDR_BUS_WIDTH_8,
+		EXT_CSD_DDR_BUS_WIDTH_4,
+		EXT_CSD_BUS_WIDTH_8,
+		EXT_CSD_BUS_WIDTH_4,
+		EXT_CSD_BUS_WIDTH_1,
+	};
+	/* An array to map CSD bus widths to host cap bits */
+	static const unsigned ext_to_hostcaps[] = {
+		[EXT_CSD_DDR_BUS_WIDTH_4] =
+			MMC_MODE_DDR_52MHz | MMC_MODE_4BIT,
+		[EXT_CSD_DDR_BUS_WIDTH_8] =
+			MMC_MODE_DDR_52MHz | MMC_MODE_8BIT,
+		[EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT,
+		[EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT,
+	};
+	/* An array to map chosen bus width to an integer */
+	static const unsigned widths[] = {
+		8, 4, 8, 4, 1,
+	};
+	int err;
+	int idx;
+
+	err = mmc_change_freq(mmc);
+	if (err)
+		return err;
+
+	/* Restrict card's capabilities by what the host can do */
+	mmc->card_caps &= mmc->cfg->host_caps;
+
+	/* Only version 4 of MMC supports wider bus widths */
+	if (mmc->version < MMC_VERSION_4)
+		return 0;
+
+	for (idx = 0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
+		unsigned int extw = ext_csd_bits[idx];
+		unsigned int caps = ext_to_hostcaps[extw];
+
+		/*
+		  * If the bus width is still not changed,
+		  * don't try to set the default again.
+		  * Otherwise, recover from switch attempts
+		  * by switching to 1-bit bus width.
+		  */
+		if (extw == EXT_CSD_BUS_WIDTH_1 &&
+		    mmc->bus_width == 1) {
+			err = 0;
+			break;
+		}
+
+		/*
+		  * Check to make sure the card and controller support
+		  * these capabilities
+		  */
+		if ((mmc->card_caps & caps) != caps)
+			continue;
+
+		err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
+				EXT_CSD_BUS_WIDTH, extw);
+
+		if (err)
+			continue;
+
+		mmc->ddr_mode = (caps & MMC_MODE_DDR_52MHz) ? 1 : 0;
+		mmc_set_bus_width(mmc, widths[idx]);
+
+		err = mmc_send_ext_csd(mmc, test_csd);
+
+		if (err)
+			continue;
+
+		/* Only compare read only fields */
+		if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT]
+			== test_csd[EXT_CSD_PARTITIONING_SUPPORT] &&
+		    ext_csd[EXT_CSD_HC_WP_GRP_SIZE]
+			== test_csd[EXT_CSD_HC_WP_GRP_SIZE] &&
+		    ext_csd[EXT_CSD_REV]
+			== test_csd[EXT_CSD_REV] &&
+		    ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
+			== test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] &&
+		    memcmp(&ext_csd[EXT_CSD_SEC_CNT],
+			    &test_csd[EXT_CSD_SEC_CNT], 4) == 0)
+			break;
+		else
+			err = -EBADMSG;
+	}
+
+	if (err)
+		return err;
+
+	if (mmc->card_caps & MMC_MODE_HS) {
+		if (mmc->card_caps & MMC_MODE_HS_52MHz)
+			mmc->tran_speed = 52000000;
+		else
+			mmc->tran_speed = 26000000;
+	}
+
+	return err;
+}
+
 static int mmc_startup(struct mmc *mmc)
 {
 	int err, i;
@@ -1110,7 +1257,6 @@ static int mmc_startup(struct mmc *mmc)
 	u64 cmult, csize, capacity;
 	struct mmc_cmd cmd;
 	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
-	ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
 	bool has_parts = false;
 	bool part_completed;
 	struct blk_desc *bdesc;
@@ -1415,136 +1561,13 @@ static int mmc_startup(struct mmc *mmc)
 		return err;
 
 	if (IS_SD(mmc))
-		err = sd_change_freq(mmc);
+		err = sd_select_bus_freq_width(mmc);
 	else
-		err = mmc_change_freq(mmc);
+		err = mmc_select_bus_freq_width(mmc, ext_csd);
 
 	if (err)
 		return err;
 
-	/* Restrict card's capabilities by what the host can do */
-	mmc->card_caps &= mmc->cfg->host_caps;
-
-	if (IS_SD(mmc)) {
-		if (mmc->card_caps & MMC_MODE_4BIT) {
-			cmd.cmdidx = MMC_CMD_APP_CMD;
-			cmd.resp_type = MMC_RSP_R1;
-			cmd.cmdarg = mmc->rca << 16;
-
-			err = mmc_send_cmd(mmc, &cmd, NULL);
-			if (err)
-				return err;
-
-			cmd.cmdidx = SD_CMD_APP_SET_BUS_WIDTH;
-			cmd.resp_type = MMC_RSP_R1;
-			cmd.cmdarg = 2;
-			err = mmc_send_cmd(mmc, &cmd, NULL);
-			if (err)
-				return err;
-
-			mmc_set_bus_width(mmc, 4);
-		}
-
-		err = sd_read_ssr(mmc);
-		if (err)
-			return err;
-
-		if (mmc->card_caps & MMC_MODE_HS)
-			mmc->tran_speed = 50000000;
-		else
-			mmc->tran_speed = 25000000;
-	} else if (mmc->version >= MMC_VERSION_4) {
-		/* Only version 4 of MMC supports wider bus widths */
-		int idx;
-
-		/* An array of possible bus widths in order of preference */
-		static unsigned ext_csd_bits[] = {
-			EXT_CSD_DDR_BUS_WIDTH_8,
-			EXT_CSD_DDR_BUS_WIDTH_4,
-			EXT_CSD_BUS_WIDTH_8,
-			EXT_CSD_BUS_WIDTH_4,
-			EXT_CSD_BUS_WIDTH_1,
-		};
-
-		/* An array to map CSD bus widths to host cap bits */
-		static unsigned ext_to_hostcaps[] = {
-			[EXT_CSD_DDR_BUS_WIDTH_4] =
-				MMC_MODE_DDR_52MHz | MMC_MODE_4BIT,
-			[EXT_CSD_DDR_BUS_WIDTH_8] =
-				MMC_MODE_DDR_52MHz | MMC_MODE_8BIT,
-			[EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT,
-			[EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT,
-		};
-
-		/* An array to map chosen bus width to an integer */
-		static unsigned widths[] = {
-			8, 4, 8, 4, 1,
-		};
-
-		for (idx=0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
-			unsigned int extw = ext_csd_bits[idx];
-			unsigned int caps = ext_to_hostcaps[extw];
-
-			/*
-			 * If the bus width is still not changed,
-			 * don't try to set the default again.
-			 * Otherwise, recover from switch attempts
-			 * by switching to 1-bit bus width.
-			 */
-			if (extw == EXT_CSD_BUS_WIDTH_1 &&
-					mmc->bus_width == 1) {
-				err = 0;
-				break;
-			}
-
-			/*
-			 * Check to make sure the card and controller support
-			 * these capabilities
-			 */
-			if ((mmc->card_caps & caps) != caps)
-				continue;
-
-			err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
-					EXT_CSD_BUS_WIDTH, extw);
-
-			if (err)
-				continue;
-
-			mmc->ddr_mode = (caps & MMC_MODE_DDR_52MHz) ? 1 : 0;
-			mmc_set_bus_width(mmc, widths[idx]);
-
-			err = mmc_send_ext_csd(mmc, test_csd);
-
-			if (err)
-				continue;
-
-			/* Only compare read only fields */
-			if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT]
-				== test_csd[EXT_CSD_PARTITIONING_SUPPORT] &&
-			    ext_csd[EXT_CSD_HC_WP_GRP_SIZE]
-				== test_csd[EXT_CSD_HC_WP_GRP_SIZE] &&
-			    ext_csd[EXT_CSD_REV]
-				== test_csd[EXT_CSD_REV] &&
-			    ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
-				== test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] &&
-			    memcmp(&ext_csd[EXT_CSD_SEC_CNT],
-				   &test_csd[EXT_CSD_SEC_CNT], 4) == 0)
-				break;
-			else
-				err = -EBADMSG;
-		}
-
-		if (err)
-			return err;
-
-		if (mmc->card_caps & MMC_MODE_HS) {
-			if (mmc->card_caps & MMC_MODE_HS_52MHz)
-				mmc->tran_speed = 52000000;
-			else
-				mmc->tran_speed = 26000000;
-		}
-	}
-
 	mmc_set_clock(mmc, mmc->tran_speed);
 
 	/* Fix the block length for DDR mode */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 02/22] mmc: move the MMC startup for version above v4.0 in a separate function
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
  2017-05-12 18:16   ` [U-Boot] [PATCH 01/22] mmc: split mmc_startup() Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:27     ` Simon Glass
  2017-05-12 18:16   ` [U-Boot] [PATCH 03/22] mmc: make ext_csd part of struct mmc Jean-Jacques Hiblot
                     ` (21 subsequent siblings)
  23 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

no functionnal change. This is only to further reduce the size o
mmc_startup().

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc.c | 316 ++++++++++++++++++++++++++++--------------------------
 1 file changed, 165 insertions(+), 151 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 7a17bac..1ae10d1 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1250,15 +1250,174 @@ static int mmc_select_bus_freq_width(struct mmc *mmc, const u8 *ext_csd)
 	return err;
 }
 
+static int mmc_startup_v4(struct mmc *mmc, u8 *ext_csd)
+{
+	int err, i;
+	u64 capacity;
+	bool has_parts = false;
+	bool part_completed;
+
+	if (IS_SD(mmc) || (mmc->version < MMC_VERSION_4))
+		return 0;
+
+	/* check  ext_csd version and capacity */
+	err = mmc_send_ext_csd(mmc, ext_csd);
+	if (err)
+		return err;
+	if (ext_csd[EXT_CSD_REV] >= 2) {
+		/*
+		  * According to the JEDEC Standard, the value of
+		  * ext_csd's capacity is valid if the value is more
+		  * than 2GB
+		  */
+		capacity = ext_csd[EXT_CSD_SEC_CNT] << 0
+				| ext_csd[EXT_CSD_SEC_CNT + 1] << 8
+				| ext_csd[EXT_CSD_SEC_CNT + 2] << 16
+				| ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
+		capacity *= MMC_MAX_BLOCK_LEN;
+		if ((capacity >> 20) > 2 * 1024)
+			mmc->capacity_user = capacity;
+	}
+
+	switch (ext_csd[EXT_CSD_REV]) {
+	case 1:
+		mmc->version = MMC_VERSION_4_1;
+		break;
+	case 2:
+		mmc->version = MMC_VERSION_4_2;
+		break;
+	case 3:
+		mmc->version = MMC_VERSION_4_3;
+		break;
+	case 5:
+		mmc->version = MMC_VERSION_4_41;
+		break;
+	case 6:
+		mmc->version = MMC_VERSION_4_5;
+		break;
+	case 7:
+		mmc->version = MMC_VERSION_5_0;
+		break;
+	case 8:
+		mmc->version = MMC_VERSION_5_1;
+		break;
+	}
+
+	/* The partition data may be non-zero but it is only
+	  * effective if PARTITION_SETTING_COMPLETED is set in
+	  * EXT_CSD, so ignore any data if this bit is not set,
+	  * except for enabling the high-capacity group size
+	  * definition (see below). */
+	part_completed = !!(ext_csd[EXT_CSD_PARTITION_SETTING] &
+			    EXT_CSD_PARTITION_SETTING_COMPLETED);
+
+	/* store the partition info of emmc */
+	mmc->part_support = ext_csd[EXT_CSD_PARTITIONING_SUPPORT];
+	if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) ||
+	    ext_csd[EXT_CSD_BOOT_MULT])
+		mmc->part_config = ext_csd[EXT_CSD_PART_CONF];
+	if (part_completed &&
+	    (ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & ENHNCD_SUPPORT))
+		mmc->part_attr = ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE];
+
+	mmc->capacity_boot = ext_csd[EXT_CSD_BOOT_MULT] << 17;
+
+	mmc->capacity_rpmb = ext_csd[EXT_CSD_RPMB_MULT] << 17;
+
+	for (i = 0; i < 4; i++) {
+		int idx = EXT_CSD_GP_SIZE_MULT + i * 3;
+		uint mult = (ext_csd[idx + 2] << 16) +
+			(ext_csd[idx + 1] << 8) + ext_csd[idx];
+		if (mult)
+			has_parts = true;
+		if (!part_completed)
+			continue;
+		mmc->capacity_gp[i] = mult;
+		mmc->capacity_gp[i] *=
+			ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
+		mmc->capacity_gp[i] *= ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
+		mmc->capacity_gp[i] <<= 19;
+	}
+
+	if (part_completed) {
+		mmc->enh_user_size =
+			(ext_csd[EXT_CSD_ENH_SIZE_MULT+2] << 16) +
+			(ext_csd[EXT_CSD_ENH_SIZE_MULT+1] << 8) +
+			ext_csd[EXT_CSD_ENH_SIZE_MULT];
+		mmc->enh_user_size *= ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
+		mmc->enh_user_size *= ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
+		mmc->enh_user_size <<= 19;
+		mmc->enh_user_start =
+			(ext_csd[EXT_CSD_ENH_START_ADDR+3] << 24) +
+			(ext_csd[EXT_CSD_ENH_START_ADDR+2] << 16) +
+			(ext_csd[EXT_CSD_ENH_START_ADDR+1] << 8) +
+			ext_csd[EXT_CSD_ENH_START_ADDR];
+		if (mmc->high_capacity)
+			mmc->enh_user_start <<= 9;
+	}
+
+	/*
+	  * Host needs to enable ERASE_GRP_DEF bit if device is
+	  * partitioned. This bit will be lost every time after a reset
+	  * or power off. This will affect erase size.
+	  */
+	if (part_completed)
+		has_parts = true;
+	if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) &&
+	    (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & PART_ENH_ATTRIB))
+		has_parts = true;
+	if (has_parts) {
+		err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
+			EXT_CSD_ERASE_GROUP_DEF, 1);
+
+		if (err)
+			return err;
+		else
+			ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1;
+	}
+
+	if (ext_csd[EXT_CSD_ERASE_GROUP_DEF] & 0x01) {
+		/* Read out group size from ext_csd */
+		mmc->erase_grp_size =
+			ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 1024;
+		/*
+		  * if high capacity and partition setting completed
+		  * SEC_COUNT is valid even if it is smaller than 2 GiB
+		  * JEDEC Standard JESD84-B45, 6.2.4
+		  */
+		if (mmc->high_capacity && part_completed) {
+			capacity = (ext_csd[EXT_CSD_SEC_CNT]) |
+				(ext_csd[EXT_CSD_SEC_CNT + 1] << 8) |
+				(ext_csd[EXT_CSD_SEC_CNT + 2] << 16) |
+				(ext_csd[EXT_CSD_SEC_CNT + 3] << 24);
+			capacity *= MMC_MAX_BLOCK_LEN;
+			mmc->capacity_user = capacity;
+		}
+	} else {
+		/* Calculate the group size from the csd value. */
+		int erase_gsz, erase_gmul;
+		erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10;
+		erase_gmul = (mmc->csd[2] & 0x000003e0) >> 5;
+		mmc->erase_grp_size = (erase_gsz + 1)
+			* (erase_gmul + 1);
+	}
+
+	mmc->hc_wp_grp_size = 1024
+		* ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
+		* ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
+
+	mmc->wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET];
+
+	return 0;
+}
+
 static int mmc_startup(struct mmc *mmc)
 {
 	int err, i;
 	uint mult, freq;
-	u64 cmult, csize, capacity;
+	u64 cmult, csize;
 	struct mmc_cmd cmd;
 	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
-	bool has_parts = false;
-	bool part_completed;
 	struct blk_desc *bdesc;
 
 #ifdef CONFIG_MMC_SPI_CRC_ON
@@ -1406,155 +1565,10 @@ static int mmc_startup(struct mmc *mmc)
 	 */
 	mmc->erase_grp_size = 1;
 	mmc->part_config = MMCPART_NOAVAILABLE;
-	if (!IS_SD(mmc) && (mmc->version >= MMC_VERSION_4)) {
-		/* check  ext_csd version and capacity */
-		err = mmc_send_ext_csd(mmc, ext_csd);
-		if (err)
-			return err;
-		if (ext_csd[EXT_CSD_REV] >= 2) {
-			/*
-			 * According to the JEDEC Standard, the value of
-			 * ext_csd's capacity is valid if the value is more
-			 * than 2GB
-			 */
-			capacity = ext_csd[EXT_CSD_SEC_CNT] << 0
-					| ext_csd[EXT_CSD_SEC_CNT + 1] << 8
-					| ext_csd[EXT_CSD_SEC_CNT + 2] << 16
-					| ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
-			capacity *= MMC_MAX_BLOCK_LEN;
-			if ((capacity >> 20) > 2 * 1024)
-				mmc->capacity_user = capacity;
-		}
 
-		switch (ext_csd[EXT_CSD_REV]) {
-		case 1:
-			mmc->version = MMC_VERSION_4_1;
-			break;
-		case 2:
-			mmc->version = MMC_VERSION_4_2;
-			break;
-		case 3:
-			mmc->version = MMC_VERSION_4_3;
-			break;
-		case 5:
-			mmc->version = MMC_VERSION_4_41;
-			break;
-		case 6:
-			mmc->version = MMC_VERSION_4_5;
-			break;
-		case 7:
-			mmc->version = MMC_VERSION_5_0;
-			break;
-		case 8:
-			mmc->version = MMC_VERSION_5_1;
-			break;
-		}
-
-		/* The partition data may be non-zero but it is only
-		 * effective if PARTITION_SETTING_COMPLETED is set in
-		 * EXT_CSD, so ignore any data if this bit is not set,
-		 * except for enabling the high-capacity group size
-		 * definition (see below). */
-		part_completed = !!(ext_csd[EXT_CSD_PARTITION_SETTING] &
-				    EXT_CSD_PARTITION_SETTING_COMPLETED);
-
-		/* store the partition info of emmc */
-		mmc->part_support = ext_csd[EXT_CSD_PARTITIONING_SUPPORT];
-		if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) ||
-		    ext_csd[EXT_CSD_BOOT_MULT])
-			mmc->part_config = ext_csd[EXT_CSD_PART_CONF];
-		if (part_completed &&
-		    (ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & ENHNCD_SUPPORT))
-			mmc->part_attr = ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE];
-
-		mmc->capacity_boot = ext_csd[EXT_CSD_BOOT_MULT] << 17;
-
-		mmc->capacity_rpmb = ext_csd[EXT_CSD_RPMB_MULT] << 17;
-
-		for (i = 0; i < 4; i++) {
-			int idx = EXT_CSD_GP_SIZE_MULT + i * 3;
-			uint mult = (ext_csd[idx + 2] << 16) +
-				(ext_csd[idx + 1] << 8) + ext_csd[idx];
-			if (mult)
-				has_parts = true;
-			if (!part_completed)
-				continue;
-			mmc->capacity_gp[i] = mult;
-			mmc->capacity_gp[i] *=
-				ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
-			mmc->capacity_gp[i] *= ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
-			mmc->capacity_gp[i] <<= 19;
-		}
-
-		if (part_completed) {
-			mmc->enh_user_size =
-				(ext_csd[EXT_CSD_ENH_SIZE_MULT+2] << 16) +
-				(ext_csd[EXT_CSD_ENH_SIZE_MULT+1] << 8) +
-				ext_csd[EXT_CSD_ENH_SIZE_MULT];
-			mmc->enh_user_size *= ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
-			mmc->enh_user_size *= ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
-			mmc->enh_user_size <<= 19;
-			mmc->enh_user_start =
-				(ext_csd[EXT_CSD_ENH_START_ADDR+3] << 24) +
-				(ext_csd[EXT_CSD_ENH_START_ADDR+2] << 16) +
-				(ext_csd[EXT_CSD_ENH_START_ADDR+1] << 8) +
-				ext_csd[EXT_CSD_ENH_START_ADDR];
-			if (mmc->high_capacity)
-				mmc->enh_user_start <<= 9;
-		}
-
-		/*
-		 * Host needs to enable ERASE_GRP_DEF bit if device is
-		 * partitioned. This bit will be lost every time after a reset
-		 * or power off. This will affect erase size.
-		 */
-		if (part_completed)
-			has_parts = true;
-		if ((ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT) &&
-		    (ext_csd[EXT_CSD_PARTITIONS_ATTRIBUTE] & PART_ENH_ATTRIB))
-			has_parts = true;
-		if (has_parts) {
-			err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
-				EXT_CSD_ERASE_GROUP_DEF, 1);
-
-			if (err)
-				return err;
-			else
-				ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1;
-		}
-
-		if (ext_csd[EXT_CSD_ERASE_GROUP_DEF] & 0x01) {
-			/* Read out group size from ext_csd */
-			mmc->erase_grp_size =
-				ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 1024;
-			/*
-			 * if high capacity and partition setting completed
-			 * SEC_COUNT is valid even if it is smaller than 2 GiB
-			 * JEDEC Standard JESD84-B45, 6.2.4
-			 */
-			if (mmc->high_capacity && part_completed) {
-				capacity = (ext_csd[EXT_CSD_SEC_CNT]) |
-					(ext_csd[EXT_CSD_SEC_CNT + 1] << 8) |
-					(ext_csd[EXT_CSD_SEC_CNT + 2] << 16) |
-					(ext_csd[EXT_CSD_SEC_CNT + 3] << 24);
-				capacity *= MMC_MAX_BLOCK_LEN;
-				mmc->capacity_user = capacity;
-			}
-		} else {
-			/* Calculate the group size from the csd value. */
-			int erase_gsz, erase_gmul;
-			erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10;
-			erase_gmul = (mmc->csd[2] & 0x000003e0) >> 5;
-			mmc->erase_grp_size = (erase_gsz + 1)
-				* (erase_gmul + 1);
-		}
-
-		mmc->hc_wp_grp_size = 1024
-			* ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
-			* ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
-
-		mmc->wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET];
-	}
+	err = mmc_startup_v4(mmc, ext_csd);
+	if (err)
+		return err;
 
 	err = mmc_set_capacity(mmc, mmc_get_blk_desc(mmc)->hwpart);
 	if (err)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 03/22] mmc: make ext_csd part of struct mmc
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
  2017-05-12 18:16   ` [U-Boot] [PATCH 01/22] mmc: split mmc_startup() Jean-Jacques Hiblot
  2017-05-12 18:16   ` [U-Boot] [PATCH 02/22] mmc: move the MMC startup for version above v4.0 in a separate function Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:27     ` Simon Glass
  2017-05-12 18:16   ` [U-Boot] [PATCH 04/22] mmc: add a function to read and test the ext csd (mmc >= 4) Jean-Jacques Hiblot
                     ` (20 subsequent siblings)
  23 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

The ext csd is used for comparison many times. Keep a reference content
of the ext csd in the struct mmc to avoid reading multiple times

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc.c | 22 +++++++++++++++++-----
 include/mmc.h     |  1 +
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 1ae10d1..4bd6a96 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1146,9 +1146,10 @@ static int sd_select_bus_freq_width(struct mmc *mmc)
 	return 0;
 }
 
-static int mmc_select_bus_freq_width(struct mmc *mmc, const u8 *ext_csd)
+static int mmc_select_bus_freq_width(struct mmc *mmc)
 {
 	ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
+	const u8 *ext_csd = mmc->ext_csd;
 	/* An array of possible bus widths in order of preference */
 	static const unsigned ext_csd_bits[] = {
 		EXT_CSD_DDR_BUS_WIDTH_8,
@@ -1184,6 +1185,11 @@ static int mmc_select_bus_freq_width(struct mmc *mmc, const u8 *ext_csd)
 	if (mmc->version < MMC_VERSION_4)
 		return 0;
 
+	if (!mmc->ext_csd) {
+		error("No ext_csd found!\n"); /* this should enver happen */
+		return -ENOTSUPP;
+	}
+
 	for (idx = 0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
 		unsigned int extw = ext_csd_bits[idx];
 		unsigned int caps = ext_to_hostcaps[extw];
@@ -1250,16 +1256,23 @@ static int mmc_select_bus_freq_width(struct mmc *mmc, const u8 *ext_csd)
 	return err;
 }
 
-static int mmc_startup_v4(struct mmc *mmc, u8 *ext_csd)
+static int mmc_startup_v4(struct mmc *mmc)
 {
 	int err, i;
 	u64 capacity;
 	bool has_parts = false;
 	bool part_completed;
+	u8 *ext_csd;
 
 	if (IS_SD(mmc) || (mmc->version < MMC_VERSION_4))
 		return 0;
 
+	ext_csd = malloc_cache_aligned(MMC_MAX_BLOCK_LEN);
+	if (!ext_csd)
+		return -ENOMEM;
+
+	mmc->ext_csd = ext_csd;
+
 	/* check  ext_csd version and capacity */
 	err = mmc_send_ext_csd(mmc, ext_csd);
 	if (err)
@@ -1417,7 +1430,6 @@ static int mmc_startup(struct mmc *mmc)
 	uint mult, freq;
 	u64 cmult, csize;
 	struct mmc_cmd cmd;
-	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
 	struct blk_desc *bdesc;
 
 #ifdef CONFIG_MMC_SPI_CRC_ON
@@ -1566,7 +1578,7 @@ static int mmc_startup(struct mmc *mmc)
 	mmc->erase_grp_size = 1;
 	mmc->part_config = MMCPART_NOAVAILABLE;
 
-	err = mmc_startup_v4(mmc, ext_csd);
+	err = mmc_startup_v4(mmc);
 	if (err)
 		return err;
 
@@ -1577,7 +1589,7 @@ static int mmc_startup(struct mmc *mmc)
 	if (IS_SD(mmc))
 		err = sd_select_bus_freq_width(mmc);
 	else
-		err = mmc_select_bus_freq_width(mmc, ext_csd);
+		err = mmc_select_bus_freq_width(mmc);
 
 	if (err)
 		return err;
diff --git a/include/mmc.h b/include/mmc.h
index fad12d6..9af6b52 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -454,6 +454,7 @@ struct mmc {
 #ifdef CONFIG_DM_MMC
 	struct udevice *dev;	/* Device for this MMC controller */
 #endif
+	u8 *ext_csd;
 };
 
 struct mmc_hwpart_conf {
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 04/22] mmc: add a function to read and test the ext csd (mmc >= 4)
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (2 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 03/22] mmc: make ext_csd part of struct mmc Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-12 18:16   ` [U-Boot] [PATCH 05/22] mmc: introduces mmc modes Jean-Jacques Hiblot
                     ` (19 subsequent siblings)
  23 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

This will be reused later in the selection of high speed and ddr modes.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc.c | 49 +++++++++++++++++++++++++++++--------------------
 1 file changed, 29 insertions(+), 20 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 4bd6a96..344d760 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1146,10 +1146,35 @@ static int sd_select_bus_freq_width(struct mmc *mmc)
 	return 0;
 }
 
-static int mmc_select_bus_freq_width(struct mmc *mmc)
+static int mmc_read_and_compare_ext_csd(struct mmc *mmc)
 {
-	ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
+	int err;
 	const u8 *ext_csd = mmc->ext_csd;
+	ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
+
+	err = mmc_send_ext_csd(mmc, test_csd);
+	if (err)
+		return err;
+
+	/* Only compare read only fields */
+	if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT]
+		== test_csd[EXT_CSD_PARTITIONING_SUPPORT] &&
+	    ext_csd[EXT_CSD_HC_WP_GRP_SIZE]
+		== test_csd[EXT_CSD_HC_WP_GRP_SIZE] &&
+	    ext_csd[EXT_CSD_REV]
+		== test_csd[EXT_CSD_REV] &&
+	    ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
+		== test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] &&
+	    memcmp(&ext_csd[EXT_CSD_SEC_CNT],
+		    &test_csd[EXT_CSD_SEC_CNT], 4) == 0)
+		return 0;
+
+	return -EBADMSG;
+}
+
+
+static int mmc_select_bus_freq_width(struct mmc *mmc)
+{
 	/* An array of possible bus widths in order of preference */
 	static const unsigned ext_csd_bits[] = {
 		EXT_CSD_DDR_BUS_WIDTH_8,
@@ -1222,25 +1247,9 @@ static int mmc_select_bus_freq_width(struct mmc *mmc)
 		mmc->ddr_mode = (caps & MMC_MODE_DDR_52MHz) ? 1 : 0;
 		mmc_set_bus_width(mmc, widths[idx]);
 
-		err = mmc_send_ext_csd(mmc, test_csd);
-
-		if (err)
-			continue;
-
-		/* Only compare read only fields */
-		if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT]
-			== test_csd[EXT_CSD_PARTITIONING_SUPPORT] &&
-		    ext_csd[EXT_CSD_HC_WP_GRP_SIZE]
-			== test_csd[EXT_CSD_HC_WP_GRP_SIZE] &&
-		    ext_csd[EXT_CSD_REV]
-			== test_csd[EXT_CSD_REV] &&
-		    ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
-			== test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] &&
-		    memcmp(&ext_csd[EXT_CSD_SEC_CNT],
-			    &test_csd[EXT_CSD_SEC_CNT], 4) == 0)
+		err = mmc_read_and_compare_ext_csd(mmc);
+		if (!err)
 			break;
-		else
-			err = -EBADMSG;
 	}
 
 	if (err)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 05/22] mmc: introduces mmc modes.
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (3 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 04/22] mmc: add a function to read and test the ext csd (mmc >= 4) Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-12 18:16   ` [U-Boot] [PATCH 06/22] mmc: Add a fonction to dump the mmc capabilities Jean-Jacques Hiblot
                     ` (18 subsequent siblings)
  23 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

no functionnal changes.
In order to add the support for the high speed SD and MMC modes, it is
useful to track this information.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++-------
 include/mmc.h     | 34 ++++++++++++++++++++++++++++------
 2 files changed, 74 insertions(+), 13 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 344d760..2e1cb0d 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -149,6 +149,36 @@ void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd)
 }
 #endif
 
+const char *mmc_mode_name(enum bus_mode mode)
+{
+	static const char *const names[] = {
+	      [MMC_LEGACY]	= "MMC legacy",
+	      [SD_LEGACY]	= "SD Legacy",
+	      [MMC_HS]		= "MMC High Speed (26MHz)",
+	      [SD_HS]		= "SD High Speed (50MHz)",
+	      [UHS_SDR12]	= "UHS SDR12 (25MHz)",
+	      [UHS_SDR25]	= "UHS SDR25 (50MHz)",
+	      [UHS_SDR50]	= "UHS SDR50 (100MHz)",
+	      [UHS_SDR104]	= "UHS SDR104 (208MHz)",
+	      [UHS_DDR50]	= "UHS DDR50 (50MHz)",
+	      [MMC_HS_52]	= "MMC High Speed (52MHz)",
+	      [MMC_DDR_52]	= "MMC DDR52 (52MHz)",
+	      [MMC_HS_200]	= "HS200 (200MHz)",
+	};
+
+	if (mode >= MMC_MODES_END)
+		return "Unknown mode";
+	else
+		return names[mode];
+}
+static int mmc_select_mode(struct mmc *mmc, enum bus_mode mode)
+{
+	mmc->selected_mode = mode;
+	debug("selecting mode %s (freq : %d MHz)\n", mmc_mode_name(mode),
+	      mmc->tran_speed / 1000000);
+	return 0;
+}
+
 #ifndef CONFIG_DM_MMC_OPS
 int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 {
@@ -1138,10 +1168,13 @@ static int sd_select_bus_freq_width(struct mmc *mmc)
 	if (err)
 		return err;
 
-	if (mmc->card_caps & MMC_MODE_HS)
+	if (mmc->card_caps & MMC_MODE_HS) {
+		mmc_select_mode(mmc, SD_HS);
 		mmc->tran_speed = 50000000;
-	else
+	} else {
+		mmc_select_mode(mmc, SD_LEGACY);
 		mmc->tran_speed = 25000000;
+	}
 
 	return 0;
 }
@@ -1255,11 +1288,15 @@ static int mmc_select_bus_freq_width(struct mmc *mmc)
 	if (err)
 		return err;
 
-	if (mmc->card_caps & MMC_MODE_HS) {
-		if (mmc->card_caps & MMC_MODE_HS_52MHz)
-			mmc->tran_speed = 52000000;
+	if (mmc->card_caps & MMC_MODE_HS_52MHz) {
+		if (mmc->ddr_mode)
+			mmc_select_mode(mmc, MMC_DDR_52);
 		else
-			mmc->tran_speed = 26000000;
+			mmc_select_mode(mmc, MMC_HS_52);
+		mmc->tran_speed = 52000000;
+	} else if (mmc->card_caps & MMC_MODE_HS) {
+		mmc_select_mode(mmc, MMC_HS);
+		mmc->tran_speed = 26000000;
 	}
 
 	return err;
@@ -1529,7 +1566,9 @@ static int mmc_startup(struct mmc *mmc)
 	freq = fbase[(cmd.response[0] & 0x7)];
 	mult = multipliers[((cmd.response[0] >> 3) & 0xf)];
 
-	mmc->tran_speed = freq * mult;
+	mmc->legacy_speed = freq * mult;
+	mmc->tran_speed = mmc->legacy_speed;
+	mmc_select_mode(mmc, MMC_LEGACY);
 
 	mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1);
 	mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf);
diff --git a/include/mmc.h b/include/mmc.h
index 9af6b52..60a43b0 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -52,12 +52,15 @@
 #define MMC_VERSION_5_0		MAKE_MMC_VERSION(5, 0, 0)
 #define MMC_VERSION_5_1		MAKE_MMC_VERSION(5, 1, 0)
 
-#define MMC_MODE_HS		(1 << 0)
-#define MMC_MODE_HS_52MHz	(1 << 1)
-#define MMC_MODE_4BIT		(1 << 2)
-#define MMC_MODE_8BIT		(1 << 3)
-#define MMC_MODE_SPI		(1 << 4)
-#define MMC_MODE_DDR_52MHz	(1 << 5)
+#define MMC_CAP(mode)		(1 << mode)
+#define MMC_MODE_HS		(MMC_CAP(MMC_HS) | MMC_CAP(SD_HS))
+#define MMC_MODE_HS_52MHz	MMC_CAP(MMC_HS_52)
+#define MMC_MODE_DDR_52MHz	MMC_CAP(MMC_DDR_52)
+
+#define MMC_MODE_8BIT		(1 << 30)
+#define MMC_MODE_4BIT		(1 << 29)
+#define MMC_MODE_SPI		(1 << 27)
+
 
 #define SD_DATA_4BIT	0x00040000
 
@@ -402,6 +405,23 @@ struct sd_ssr {
 	unsigned int erase_offset;	/* In milliseconds */
 };
 
+enum bus_mode {
+	MMC_LEGACY	= 0,
+	SD_LEGACY	= 1,
+	MMC_HS		= 2,
+	SD_HS		= 3,
+	UHS_SDR12	= 4,
+	UHS_SDR25	= 5,
+	UHS_SDR50	= 6,
+	UHS_SDR104	= 7,
+	UHS_DDR50	= 8,
+	MMC_HS_52	= 9,
+	MMC_DDR_52	= 10,
+	MMC_HS_200	= 11,
+	MMC_MODES_END
+};
+
+const char *mmc_mode_name(enum bus_mode mode);
 /*
  * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device
  * with mmc_get_mmc_dev().
@@ -432,6 +452,7 @@ struct mmc {
 	u8 wr_rel_set;
 	char part_config;
 	uint tran_speed;
+	uint legacy_speed;
 	uint read_bl_len;
 	uint write_bl_len;
 	uint erase_grp_size;	/* in 512-byte sectors */
@@ -455,6 +476,7 @@ struct mmc {
 	struct udevice *dev;	/* Device for this MMC controller */
 #endif
 	u8 *ext_csd;
+	enum bus_mode selected_mode;
 };
 
 struct mmc_hwpart_conf {
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 06/22] mmc: Add a fonction to dump the mmc capabilities
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (4 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 05/22] mmc: introduces mmc modes Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-12 18:16   ` [U-Boot] [PATCH 07/22] mmc: use mmc modes to select the correct bus speed Jean-Jacques Hiblot
                     ` (17 subsequent siblings)
  23 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

This adds a simple helper function to display information (bus width and
mode) based on a capability mask. Useful for debug.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc.c | 17 +++++++++++++++++
 include/mmc.h     |  1 +
 2 files changed, 18 insertions(+)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 2e1cb0d..5d418c5 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1133,6 +1133,23 @@ static void mmc_set_bus_width(struct mmc *mmc, uint width)
 	mmc_set_ios(mmc);
 }
 
+void mmc_dump_capabilities(const char *text, uint caps)
+{
+	enum bus_mode mode;
+
+	printf("%s: widths [", text);
+	if (caps & MMC_MODE_8BIT)
+		printf("8, ");
+	if (caps & MMC_MODE_4BIT)
+		printf("4, ");
+	printf("1] modes [");
+
+	for (mode = MMC_LEGACY; mode < MMC_MODES_END; mode++)
+		if (MMC_CAP(mode) & caps)
+			printf("%s, ", mmc_mode_name(mode));
+	printf("\b\b]\n");
+}
+
 static int sd_select_bus_freq_width(struct mmc *mmc)
 {
 	int err;
diff --git a/include/mmc.h b/include/mmc.h
index 60a43b0..afda02d 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -422,6 +422,7 @@ enum bus_mode {
 };
 
 const char *mmc_mode_name(enum bus_mode mode);
+void mmc_dump_capabilities(const char *text, uint caps);
 /*
  * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device
  * with mmc_get_mmc_dev().
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 07/22] mmc: use mmc modes to select the correct bus speed
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (5 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 06/22] mmc: Add a fonction to dump the mmc capabilities Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-12 18:16   ` [U-Boot] [PATCH 08/22] cmd: mmc: display the mode name and current bus speed in the mmc info Jean-Jacques Hiblot
                     ` (16 subsequent siblings)
  23 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc.c | 40 +++++++++++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 5d418c5..dc7985f 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -171,9 +171,35 @@ const char *mmc_mode_name(enum bus_mode mode)
 	else
 		return names[mode];
 }
+
+static uint mmc_mode2freq(struct mmc *mmc, enum bus_mode mode)
+{
+	static const int freqs[] = {
+	      [SD_LEGACY]	= 25000000,
+	      [MMC_HS]		= 26000000,
+	      [SD_HS]		= 50000000,
+	      [UHS_SDR12]	= 25000000,
+	      [UHS_SDR25]	= 50000000,
+	      [UHS_SDR50]	= 100000000,
+	      [UHS_SDR104]	= 208000000,
+	      [UHS_DDR50]	= 50000000,
+	      [MMC_HS_52]	= 52000000,
+	      [MMC_DDR_52]	= 52000000,
+	      [MMC_HS_200]	= 200000000,
+	};
+
+	if (mode == MMC_LEGACY)
+		return mmc->legacy_speed;
+	else if (mode >= MMC_MODES_END)
+		return 0;
+	else
+		return freqs[mode];
+}
+
 static int mmc_select_mode(struct mmc *mmc, enum bus_mode mode)
 {
 	mmc->selected_mode = mode;
+	mmc->tran_speed = mmc_mode2freq(mmc, mode);
 	debug("selecting mode %s (freq : %d MHz)\n", mmc_mode_name(mode),
 	      mmc->tran_speed / 1000000);
 	return 0;
@@ -1185,13 +1211,10 @@ static int sd_select_bus_freq_width(struct mmc *mmc)
 	if (err)
 		return err;
 
-	if (mmc->card_caps & MMC_MODE_HS) {
+	if (mmc->card_caps & MMC_MODE_HS)
 		mmc_select_mode(mmc, SD_HS);
-		mmc->tran_speed = 50000000;
-	} else {
+	else
 		mmc_select_mode(mmc, SD_LEGACY);
-		mmc->tran_speed = 25000000;
-	}
 
 	return 0;
 }
@@ -1310,11 +1333,8 @@ static int mmc_select_bus_freq_width(struct mmc *mmc)
 			mmc_select_mode(mmc, MMC_DDR_52);
 		else
 			mmc_select_mode(mmc, MMC_HS_52);
-		mmc->tran_speed = 52000000;
-	} else if (mmc->card_caps & MMC_MODE_HS) {
+	} else if (mmc->card_caps & MMC_MODE_HS)
 		mmc_select_mode(mmc, MMC_HS);
-		mmc->tran_speed = 26000000;
-	}
 
 	return err;
 }
@@ -1584,7 +1604,6 @@ static int mmc_startup(struct mmc *mmc)
 	mult = multipliers[((cmd.response[0] >> 3) & 0xf)];
 
 	mmc->legacy_speed = freq * mult;
-	mmc->tran_speed = mmc->legacy_speed;
 	mmc_select_mode(mmc, MMC_LEGACY);
 
 	mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1);
@@ -1659,7 +1678,6 @@ static int mmc_startup(struct mmc *mmc)
 	if (err)
 		return err;
 
-	mmc_set_clock(mmc, mmc->tran_speed);
 
 	/* Fix the block length for DDR mode */
 	if (mmc->ddr_mode) {
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 08/22] cmd: mmc: display the mode name and current bus speed in the mmc info
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (6 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 07/22] mmc: use mmc modes to select the correct bus speed Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-12 18:16   ` [U-Boot] [PATCH 09/22] mmc: refactor SD startup to make it easier to support new modes Jean-Jacques Hiblot
                     ` (15 subsequent siblings)
  23 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

Display the mode name when the user execute 'mmc info'. Also instead of
displaying tran_speed, display the actual bus speed.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 cmd/mmc.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/cmd/mmc.c b/cmd/mmc.c
index f83032e..59c8023 100644
--- a/cmd/mmc.c
+++ b/cmd/mmc.c
@@ -23,7 +23,8 @@ static void print_mmcinfo(struct mmc *mmc)
 			(mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
 			(mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff);
 
-	printf("Tran Speed: %d\n", mmc->tran_speed);
+	printf("Bus Speed: %d\n", mmc->clock);
+	printf("Mode : %s\n", mmc_mode_name(mmc->selected_mode));
 	printf("Rd Block Len: %d\n", mmc->read_bl_len);
 
 	printf("%s version %d.%d", IS_SD(mmc) ? "SD" : "MMC",
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 09/22] mmc: refactor SD startup to make it easier to support new modes
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (7 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 08/22] cmd: mmc: display the mode name and current bus speed in the mmc info Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-12 18:16   ` [U-Boot] [PATCH 10/22] mmc: refactor MMC " Jean-Jacques Hiblot
                     ` (14 subsequent siblings)
  23 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

The SDcard startup process currently handles only 2 modes. To make it
easier to add support for more modes, let's make the process more generic
and use a list of the modes to try.
The major functional change is that when a mode fails we try the next one.
Not all modes are tried, only those supported by the card and the host.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc.c | 180 ++++++++++++++++++++++++++++++++++++++----------------
 include/mmc.h     |   1 +
 2 files changed, 128 insertions(+), 53 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index dc7985f..f42a0fe 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -608,7 +608,7 @@ static int mmc_change_freq(struct mmc *mmc)
 	char cardtype;
 	int err;
 
-	mmc->card_caps = 0;
+	mmc->card_caps = MMC_MODE_1BIT;
 
 	if (mmc_host_is_spi(mmc))
 		return 0;
@@ -934,7 +934,7 @@ static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
 }
 
 
-static int sd_change_freq(struct mmc *mmc)
+static int sd_get_capabilities(struct mmc *mmc)
 {
 	int err;
 	struct mmc_cmd cmd;
@@ -943,7 +943,7 @@ static int sd_change_freq(struct mmc *mmc)
 	struct mmc_data data;
 	int timeout;
 
-	mmc->card_caps = 0;
+	mmc->card_caps = MMC_MODE_1BIT;
 
 	if (mmc_host_is_spi(mmc))
 		return 0;
@@ -1020,26 +1020,53 @@ retry_scr:
 	}
 
 	/* If high-speed isn't supported, we return */
-	if (!(__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED))
-		return 0;
+	if (__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED)
+		mmc->card_caps |= MMC_CAP(SD_HS);
 
-	/*
-	 * If the host doesn't support SD_HIGHSPEED, do not switch card to
-	 * HIGHSPEED mode even if the card support SD_HIGHSPPED.
-	 * This can avoid furthur problem when the card runs in different
-	 * mode between the host.
-	 */
-	if (!((mmc->cfg->host_caps & MMC_MODE_HS_52MHz) &&
-		(mmc->cfg->host_caps & MMC_MODE_HS)))
-		return 0;
+	return 0;
+}
+
+static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode)
+{
+	int err;
+	ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);
 
 	err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status);
 
 	if (err)
 		return err;
 
-	if ((__be32_to_cpu(switch_status[4]) & 0x0f000000) == 0x01000000)
-		mmc->card_caps |= MMC_MODE_HS;
+	if ((__be32_to_cpu(switch_status[4]) & 0x0f000000) != 0x01000000)
+		return -ENOTSUPP;
+
+	return 0;
+}
+
+int sd_select_bus_width(struct mmc *mmc, int w)
+{
+	int err;
+	struct mmc_cmd cmd;
+
+	if ((w != 4) && (w != 1))
+		return -EINVAL;
+
+	cmd.cmdidx = MMC_CMD_APP_CMD;
+	cmd.resp_type = MMC_RSP_R1;
+	cmd.cmdarg = mmc->rca << 16;
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err)
+		return err;
+
+	cmd.cmdidx = SD_CMD_APP_SET_BUS_WIDTH;
+	cmd.resp_type = MMC_RSP_R1;
+	if (w == 4)
+		cmd.cmdarg = 2;
+	else if (w == 1)
+		cmd.cmdarg = 0;
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err)
+		return err;
 
 	return 0;
 }
@@ -1131,6 +1158,19 @@ static const u8 multipliers[] = {
 	80,
 };
 
+
+static inline int bus_width(uint cap)
+{
+	if (cap == MMC_MODE_8BIT)
+		return 8;
+	if (cap == MMC_MODE_4BIT)
+		return 4;
+	if (cap == MMC_MODE_1BIT)
+		return 1;
+	error("invalid bus witdh capability 0x%x\n", cap);
+	return 0;
+}
+
 #ifndef CONFIG_DM_MMC_OPS
 static void mmc_set_ios(struct mmc *mmc)
 {
@@ -1168,55 +1208,89 @@ void mmc_dump_capabilities(const char *text, uint caps)
 		printf("8, ");
 	if (caps & MMC_MODE_4BIT)
 		printf("4, ");
-	printf("1] modes [");
-
+	if (caps & MMC_MODE_1BIT)
+		printf("1, ");
+	printf("\b\b] modes [");
 	for (mode = MMC_LEGACY; mode < MMC_MODES_END; mode++)
 		if (MMC_CAP(mode) & caps)
 			printf("%s, ", mmc_mode_name(mode));
 	printf("\b\b]\n");
 }
 
-static int sd_select_bus_freq_width(struct mmc *mmc)
+struct mode_width_tuning {
+	enum bus_mode mode;
+	uint widths;
+};
+
+static const struct mode_width_tuning sd_modes_by_pref[] = {
+	{
+		.mode = SD_HS,
+		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
+	},
+	{
+		.mode = SD_LEGACY,
+		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
+	}
+};
+#define for_each_sd_mode_by_pref(caps, mwt) \
+	for (mwt = sd_modes_by_pref;\
+	     mwt < sd_modes_by_pref + ARRAY_SIZE(sd_modes_by_pref);\
+	     mwt++) \
+		if (caps & MMC_CAP(mwt->mode))
+
+static int sd_select_mode_and_width(struct mmc *mmc)
 {
 	int err;
-	struct mmc_cmd cmd;
+	uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT};
+	const struct mode_width_tuning *mwt;
 
-	err = sd_change_freq(mmc);
+	err = sd_get_capabilities(mmc);
 	if (err)
 		return err;
-
 	/* Restrict card's capabilities by what the host can do */
-	mmc->card_caps &= mmc->cfg->host_caps;
-
-	if (mmc->card_caps & MMC_MODE_4BIT) {
-		cmd.cmdidx = MMC_CMD_APP_CMD;
-		cmd.resp_type = MMC_RSP_R1;
-		cmd.cmdarg = mmc->rca << 16;
-
-		err = mmc_send_cmd(mmc, &cmd, NULL);
-		if (err)
-			return err;
-
-		cmd.cmdidx = SD_CMD_APP_SET_BUS_WIDTH;
-		cmd.resp_type = MMC_RSP_R1;
-		cmd.cmdarg = 2;
-		err = mmc_send_cmd(mmc, &cmd, NULL);
-		if (err)
-			return err;
-
-		mmc_set_bus_width(mmc, 4);
+	mmc->card_caps &= (mmc->cfg->host_caps | MMC_MODE_1BIT);
+
+	for_each_sd_mode_by_pref(mmc->card_caps, mwt) {
+		uint *w;
+
+		for (w = widths; w < widths + ARRAY_SIZE(widths); w++) {
+			if (*w & mmc->card_caps & mwt->widths) {
+				debug("trying mode %s width %d (at %d MHz)\n",
+				      mmc_mode_name(mwt->mode),
+				      bus_width(*w),
+				      mmc_mode2freq(mmc, mwt->mode) / 1000000);
+
+				/* configure the bus width (card + host) */
+				err = sd_select_bus_width(mmc, bus_width(*w));
+				if (err)
+					goto error;
+				mmc_set_bus_width(mmc, bus_width(*w));
+
+				/* configure the bus mode (card) */
+				err = sd_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);
+
+				err = sd_read_ssr(mmc);
+				if (!err)
+					return 0;
+				else
+					printf("bad ssr\n");
+
+error:
+				/* revert to a safer bus speed */
+				mmc_select_mode(mmc, SD_LEGACY);
+				mmc_set_clock(mmc, mmc->tran_speed);
+			}
+		}
 	}
 
-	err = sd_read_ssr(mmc);
-	if (err)
-		return err;
-
-	if (mmc->card_caps & MMC_MODE_HS)
-		mmc_select_mode(mmc, SD_HS);
-	else
-		mmc_select_mode(mmc, SD_LEGACY);
-
-	return 0;
+	error("unable to select a mode\n");
+	return -ENOTSUPP;
 }
 
 static int mmc_read_and_compare_ext_csd(struct mmc *mmc)
@@ -1277,7 +1351,7 @@ static int mmc_select_bus_freq_width(struct mmc *mmc)
 		return err;
 
 	/* Restrict card's capabilities by what the host can do */
-	mmc->card_caps &= mmc->cfg->host_caps;
+	mmc->card_caps &= (mmc->cfg->host_caps | MMC_MODE_1BIT);
 
 	/* Only version 4 of MMC supports wider bus widths */
 	if (mmc->version < MMC_VERSION_4)
@@ -1671,7 +1745,7 @@ static int mmc_startup(struct mmc *mmc)
 		return err;
 
 	if (IS_SD(mmc))
-		err = sd_select_bus_freq_width(mmc);
+		err = sd_select_mode_and_width(mmc);
 	else
 		err = mmc_select_bus_freq_width(mmc);
 
diff --git a/include/mmc.h b/include/mmc.h
index afda02d..1ffa7ec 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -59,6 +59,7 @@
 
 #define MMC_MODE_8BIT		(1 << 30)
 #define MMC_MODE_4BIT		(1 << 29)
+#define MMC_MODE_1BIT		(1 << 28)
 #define MMC_MODE_SPI		(1 << 27)
 
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 10/22] mmc: refactor MMC startup to make it easier to support new modes
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (8 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 09/22] mmc: refactor SD startup to make it easier to support new modes Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-25 12:25     ` Jaehoon Chung
  2017-05-12 18:16   ` [U-Boot] [PATCH 11/22] mmc: make mmc_set_ios() return status Jean-Jacques Hiblot
                     ` (13 subsequent siblings)
  23 siblings, 2 replies; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

The MMC startup process currently handles 4 modes. To make it easier to
add support for more modes, let's make the process more generic and use a
list of the modes to try.
The major functional change is that when a mode fails we try the next one.
Not all modes are tried, only those supported by the card and the host.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc.c | 238 +++++++++++++++++++++++++++++++++---------------------
 include/mmc.h     |  15 +++-
 2 files changed, 157 insertions(+), 96 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index f42a0fe..2931871 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -200,6 +200,7 @@ static int mmc_select_mode(struct mmc *mmc, enum bus_mode mode)
 {
 	mmc->selected_mode = mode;
 	mmc->tran_speed = mmc_mode2freq(mmc, mode);
+	mmc->ddr_mode = mmc_is_mode_ddr(mode);
 	debug("selecting mode %s (freq : %d MHz)\n", mmc_mode_name(mode),
 	      mmc->tran_speed / 1000000);
 	return 0;
@@ -602,11 +603,46 @@ int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
 
 }
 
-static int mmc_change_freq(struct mmc *mmc)
+static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode)
 {
-	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
-	char cardtype;
 	int err;
+	int speed_bits;
+	ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
+
+	switch (mode) {
+	case MMC_HS:
+	case MMC_HS_52:
+	case MMC_DDR_52:
+		  speed_bits = EXT_CSD_TIMING_HS;
+	case MMC_LEGACY:
+		  speed_bits = EXT_CSD_TIMING_LEGACY;
+		  break;
+	default:
+		  return -EINVAL;
+	}
+	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
+			 speed_bits);
+	if (err)
+		return err;
+
+	if ((mode == MMC_HS) || (mode == MMC_HS_52)) {
+		/* Now check to see that it worked */
+		err = mmc_send_ext_csd(mmc, test_csd);
+		if (err)
+			return err;
+
+		/* No high-speed support */
+		if (!test_csd[EXT_CSD_HS_TIMING])
+			return -ENOTSUPP;
+	}
+
+	return 0;
+}
+
+static int mmc_get_capabilities(struct mmc *mmc)
+{
+	u8 *ext_csd = mmc->ext_csd;
+	char cardtype;
 
 	mmc->card_caps = MMC_MODE_1BIT;
 
@@ -617,38 +653,23 @@ static int mmc_change_freq(struct mmc *mmc)
 	if (mmc->version < MMC_VERSION_4)
 		return 0;
 
-	mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
-
-	err = mmc_send_ext_csd(mmc, ext_csd);
+	if (!ext_csd) {
+		error("No ext_csd found!\n"); /* this should enver happen */
+		return -ENOTSUPP;
+	}
 
-	if (err)
-		return err;
+	mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
 
 	cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0xf;
 
-	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);
-
-	if (err)
-		return err;
-
-	/* Now check to see that it worked */
-	err = mmc_send_ext_csd(mmc, ext_csd);
-
-	if (err)
-		return err;
-
-	/* No high-speed support */
-	if (!ext_csd[EXT_CSD_HS_TIMING])
-		return 0;
-
 	/* High Speed is set, there are two types: 52MHz and 26MHz */
 	if (cardtype & EXT_CSD_CARD_TYPE_52) {
-		if (cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V)
+		if (cardtype & EXT_CSD_CARD_TYPE_DDR_52)
 			mmc->card_caps |= MMC_MODE_DDR_52MHz;
-		mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
-	} else {
-		mmc->card_caps |= MMC_MODE_HS;
+		mmc->card_caps |= MMC_MODE_HS_52MHz;
 	}
+	if (cardtype & EXT_CSD_CARD_TYPE_26)
+		mmc->card_caps |= MMC_MODE_HS;
 
 	return 0;
 }
@@ -1320,33 +1341,58 @@ static int mmc_read_and_compare_ext_csd(struct mmc *mmc)
 }
 
 
-static int mmc_select_bus_freq_width(struct mmc *mmc)
+static const struct mode_width_tuning mmc_modes_by_pref[] = {
+	{
+		.mode = MMC_HS_200,
+		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
+	},
+	{
+		.mode = MMC_DDR_52,
+		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
+	},
+	{
+		.mode = MMC_HS_52,
+		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
+	},
+	{
+		.mode = MMC_HS,
+		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
+	},
+	{
+		.mode = MMC_LEGACY,
+		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
+	}
+};
+#define for_each_mmc_mode_by_pref(caps, mwt) \
+	for (mwt = mmc_modes_by_pref;\
+	    mwt < mmc_modes_by_pref + ARRAY_SIZE(mmc_modes_by_pref);\
+	    mwt++) \
+		if (caps & MMC_CAP(mwt->mode))
+
+static const struct ext_csd_bus_width {
+	uint cap;
+	bool is_ddr;
+	uint ext_csd_bits;
+} ext_csd_bus_width[] = {
+	{MMC_MODE_8BIT, true, EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR},
+	{MMC_MODE_4BIT, true, EXT_CSD_BUS_WIDTH_4 | EXT_CSD_DDR},
+	{MMC_MODE_8BIT, false, EXT_CSD_BUS_WIDTH_8},
+	{MMC_MODE_4BIT, false, EXT_CSD_BUS_WIDTH_4},
+	{MMC_MODE_1BIT, false, EXT_CSD_BUS_WIDTH_1},
+};
+#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);\
+	    ecbv++) \
+		if ((ddr == ecbv->is_ddr) && (caps & ecbv->cap))
+
+static int mmc_select_mode_and_width(struct mmc *mmc)
 {
-	/* An array of possible bus widths in order of preference */
-	static const unsigned ext_csd_bits[] = {
-		EXT_CSD_DDR_BUS_WIDTH_8,
-		EXT_CSD_DDR_BUS_WIDTH_4,
-		EXT_CSD_BUS_WIDTH_8,
-		EXT_CSD_BUS_WIDTH_4,
-		EXT_CSD_BUS_WIDTH_1,
-	};
-	/* An array to map CSD bus widths to host cap bits */
-	static const unsigned ext_to_hostcaps[] = {
-		[EXT_CSD_DDR_BUS_WIDTH_4] =
-			MMC_MODE_DDR_52MHz | MMC_MODE_4BIT,
-		[EXT_CSD_DDR_BUS_WIDTH_8] =
-			MMC_MODE_DDR_52MHz | MMC_MODE_8BIT,
-		[EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT,
-		[EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT,
-	};
-	/* An array to map chosen bus width to an integer */
-	static const unsigned widths[] = {
-		8, 4, 8, 4, 1,
-	};
 	int err;
-	int idx;
+	const struct mode_width_tuning *mwt;
+	const struct ext_csd_bus_width *ecbw;
 
-	err = mmc_change_freq(mmc);
+	err = mmc_get_capabilities(mmc);
 	if (err)
 		return err;
 
@@ -1357,60 +1403,64 @@ static int mmc_select_bus_freq_width(struct mmc *mmc)
 	if (mmc->version < MMC_VERSION_4)
 		return 0;
 
+
 	if (!mmc->ext_csd) {
 		error("No ext_csd found!\n"); /* this should enver happen */
 		return -ENOTSUPP;
 	}
 
-	for (idx = 0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
-		unsigned int extw = ext_csd_bits[idx];
-		unsigned int caps = ext_to_hostcaps[extw];
+	for_each_mmc_mode_by_pref(mmc->card_caps, mwt) {
+		for_each_supported_width(mmc->card_caps & mwt->widths,
+					 mmc_is_mode_ddr(mwt->mode), ecbw) {
+			debug("trying mode %s width %d (at %d MHz)\n",
+			      mmc_mode_name(mwt->mode),
+			      bus_width(ecbw->cap),
+			      mmc_mode2freq(mmc, mwt->mode) / 1000000);
 
-		/*
-		  * If the bus width is still not changed,
-		  * don't try to set the default again.
-		  * Otherwise, recover from switch attempts
-		  * by switching to 1-bit bus width.
-		  */
-		if (extw == EXT_CSD_BUS_WIDTH_1 &&
-		    mmc->bus_width == 1) {
-			err = 0;
-			break;
-		}
-
-		/*
-		  * Check to make sure the card and controller support
-		  * these capabilities
-		  */
-		if ((mmc->card_caps & caps) != caps)
-			continue;
-
-		err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
-				EXT_CSD_BUS_WIDTH, extw);
+			/* configure the bus width (card + host) */
+			err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
+				EXT_CSD_BUS_WIDTH,
+				ecbw->ext_csd_bits & ~EXT_CSD_DDR);
+			if (err)
+				goto error;
+			mmc_set_bus_width(mmc, bus_width(ecbw->cap));
 
-		if (err)
-			continue;
+			/* 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) {
+				err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
+					EXT_CSD_BUS_WIDTH, ecbw->ext_csd_bits);
+				if (err)
+					goto error;
+			}
 
-		mmc->ddr_mode = (caps & MMC_MODE_DDR_52MHz) ? 1 : 0;
-		mmc_set_bus_width(mmc, widths[idx]);
+			/* configure the bus mode (host) */
+			mmc_select_mode(mmc, mwt->mode);
+			mmc_set_clock(mmc, mmc->tran_speed);
 
-		err = mmc_read_and_compare_ext_csd(mmc);
-		if (!err)
-			break;
+			/* do a transfer to check the configuration */
+			err = mmc_read_and_compare_ext_csd(mmc);
+			if (!err)
+				return 0;
+error:
+			/* if an error occured, revert to a safer bus mode */
+			mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
+				   EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_1);
+			mmc_select_mode(mmc, MMC_LEGACY);
+			mmc_set_bus_width(mmc, 1);
+		}
 	}
 
-	if (err)
-		return err;
-
-	if (mmc->card_caps & MMC_MODE_HS_52MHz) {
-		if (mmc->ddr_mode)
-			mmc_select_mode(mmc, MMC_DDR_52);
-		else
-			mmc_select_mode(mmc, MMC_HS_52);
-	} else if (mmc->card_caps & MMC_MODE_HS)
-		mmc_select_mode(mmc, MMC_HS);
+	error("unable to select a mode\n");
 
-	return err;
+	return -ENOTSUPP;
 }
 
 static int mmc_startup_v4(struct mmc *mmc)
@@ -1747,7 +1797,7 @@ static int mmc_startup(struct mmc *mmc)
 	if (IS_SD(mmc))
 		err = sd_select_mode_and_width(mmc);
 	else
-		err = mmc_select_bus_freq_width(mmc);
+		err = mmc_select_mode_and_width(mmc);
 
 	if (err)
 		return err;
diff --git a/include/mmc.h b/include/mmc.h
index 1ffa7ec..3c6971d 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -213,9 +213,10 @@
 #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 */
-#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		4	/* Card is in DDR mode */
 
+#define EXT_CSD_TIMING_LEGACY	0	/* no high speed */
+#define EXT_CSD_TIMING_HS	1	/* HS */
 #define EXT_CSD_BOOT_ACK_ENABLE			(1 << 6)
 #define EXT_CSD_BOOT_PARTITION_ENABLE		(1 << 3)
 #define EXT_CSD_PARTITION_ACCESS_ENABLE		(1 << 0)
@@ -424,6 +425,16 @@ enum bus_mode {
 
 const char *mmc_mode_name(enum bus_mode mode);
 void mmc_dump_capabilities(const char *text, uint caps);
+
+static inline bool mmc_is_mode_ddr(enum bus_mode mode)
+{
+	if ((mode == MMC_DDR_52) || (mode == UHS_DDR50))
+		return true;
+	else
+		return false;
+}
+
+
 /*
  * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device
  * with mmc_get_mmc_dev().
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 11/22] mmc: make mmc_set_ios() return status
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (9 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 10/22] mmc: refactor MMC " Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-12 18:16   ` [U-Boot] [PATCH 12/22] mmc: Enable signal voltage to be selected from mmc core Jean-Jacques Hiblot
                     ` (12 subsequent siblings)
  23 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

set_ios callback has a return value of 'int' but the mmc_set_ios()
function ignore this. Modify mmc_set_ios() and the callers of mmc_set_ios() to
to return the error status.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc.c | 16 ++++++++++------
 include/mmc.h     |  2 +-
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 2931871..2ae6f1c 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1193,14 +1193,18 @@ static inline int bus_width(uint cap)
 }
 
 #ifndef CONFIG_DM_MMC_OPS
-static void mmc_set_ios(struct mmc *mmc)
+static int mmc_set_ios(struct mmc *mmc)
 {
+	int ret = 0;
+
 	if (mmc->cfg->ops->set_ios)
-		mmc->cfg->ops->set_ios(mmc);
+		ret = mmc->cfg->ops->set_ios(mmc);
+
+	return ret;
 }
 #endif
 
-void mmc_set_clock(struct mmc *mmc, uint clock)
+int mmc_set_clock(struct mmc *mmc, uint clock)
 {
 	if (clock > mmc->cfg->f_max)
 		clock = mmc->cfg->f_max;
@@ -1210,14 +1214,14 @@ void mmc_set_clock(struct mmc *mmc, uint clock)
 
 	mmc->clock = clock;
 
-	mmc_set_ios(mmc);
+	return mmc_set_ios(mmc);
 }
 
-static void mmc_set_bus_width(struct mmc *mmc, uint width)
+static int mmc_set_bus_width(struct mmc *mmc, uint width)
 {
 	mmc->bus_width = width;
 
-	mmc_set_ios(mmc);
+	return mmc_set_ios(mmc);
 }
 
 void mmc_dump_capabilities(const char *text, uint caps)
diff --git a/include/mmc.h b/include/mmc.h
index 3c6971d..9f20eb4 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -540,7 +540,7 @@ int mmc_unbind(struct udevice *dev);
 int mmc_initialize(bd_t *bis);
 int mmc_init(struct mmc *mmc);
 int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
-void mmc_set_clock(struct mmc *mmc, uint clock);
+int mmc_set_clock(struct mmc *mmc, uint clock);
 struct mmc *find_mmc_device(int dev_num);
 int mmc_set_dev(int dev_num);
 void print_mmc_devices(char separator);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 12/22] mmc: Enable signal voltage to be selected from mmc core
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (10 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 11/22] mmc: make mmc_set_ios() return status Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-12 18:16   ` [U-Boot] [PATCH 13/22] mmc: Add a new callback function to enable/disable vdd Jean-Jacques Hiblot
                     ` (11 subsequent siblings)
  23 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

From: Kishon Vijay Abraham I <kishon@ti.com>

Add a new function *mmc_set_signal_voltage* in mmc core
which can be used during mmc initialization to select the
signal voltage. Platform driver should use the set_ios
callback function to select the signal voltage.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc.c | 15 +++++++++++++++
 include/mmc.h     |  5 +++++
 2 files changed, 20 insertions(+)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 2ae6f1c..10af81d 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -29,6 +29,7 @@ static const unsigned int sd_au_size[] = {
 	SZ_4M / 512,	SZ_8M / 512,		(SZ_8M + SZ_4M) / 512,
 	SZ_16M / 512,	(SZ_16M + SZ_8M) / 512,	SZ_32M / 512,	SZ_64M / 512,
 };
+static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
 
 #if CONFIG_IS_ENABLED(MMC_TINY)
 static struct mmc mmc_static;
@@ -1247,6 +1248,12 @@ struct mode_width_tuning {
 	uint widths;
 };
 
+static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
+{
+	mmc->signal_voltage = signal_voltage;
+	return mmc_set_ios(mmc);
+}
+
 static const struct mode_width_tuning sd_modes_by_pref[] = {
 	{
 		.mode = SD_HS,
@@ -1935,6 +1942,14 @@ int mmc_start_init(struct mmc *mmc)
 		return err;
 #endif
 	mmc->ddr_mode = 0;
+
+	/* First try to set 3.3V. If it fails set to 1.8V */
+	err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
+	if (err != 0)
+		err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
+	if (err != 0)
+		printf("failed to set signal voltage\n");
+
 	mmc_set_bus_width(mmc, 1);
 	mmc_set_clock(mmc, 1);
 
diff --git a/include/mmc.h b/include/mmc.h
index 9f20eb4..89cb26c 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -266,6 +266,10 @@
 #define ENHNCD_SUPPORT		(0x2)
 #define PART_ENH_ATTRIB		(0x1f)
 
+#define MMC_SIGNAL_VOLTAGE_330	1
+#define MMC_SIGNAL_VOLTAGE_180	2
+#define MMC_SIGNAL_VOLTAGE_120	3
+
 /* Maximum block size for MMC */
 #define MMC_MAX_BLOCK_LEN	512
 
@@ -452,6 +456,7 @@ struct mmc {
 	int high_capacity;
 	uint bus_width;
 	uint clock;
+	uint signal_voltage;
 	uint card_caps;
 	uint ocr;
 	uint dsr;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 13/22] mmc: Add a new callback function to enable/disable vdd
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (11 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 12/22] mmc: Enable signal voltage to be selected from mmc core Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-12 18:16   ` [U-Boot] [PATCH 14/22] mmc: add power cyle support in mmc core Jean-Jacques Hiblot
                     ` (10 subsequent siblings)
  23 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

From: Kishon Vijay Abraham I <kishon@ti.com>

Add a new callback function *set_vdd* which can be used
by the platform mmc driver to enable or disable vdd.
The mmc core can use *mmc_set_vdd* in order to invoke
the callback function. This will be used during power cycle
where the specification requires vdd to be disabled for
1ms and enabled again.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc-uclass.c | 14 ++++++++++++++
 drivers/mmc/mmc.c        | 12 +++++++++++-
 include/mmc.h            | 12 ++++++++++++
 3 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 9c07871..e1f7995 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -52,6 +52,20 @@ int mmc_set_ios(struct mmc *mmc)
 	return dm_mmc_set_ios(mmc->dev);
 }
 
+int dm_mmc_set_vdd(struct udevice *dev, bool enable)
+{
+	struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+	if (!ops->set_vdd)
+		return -ENOSYS;
+	return ops->set_vdd(dev, enable);
+}
+
+int mmc_set_vdd(struct mmc *mmc, bool enable)
+{
+	return dm_mmc_set_vdd(mmc->dev, enable);
+}
+
 int dm_mmc_get_wp(struct udevice *dev)
 {
 	struct dm_mmc_ops *ops = mmc_get_ops(dev);
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 10af81d..d40a22b 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1194,6 +1194,16 @@ static inline int bus_width(uint cap)
 }
 
 #ifndef CONFIG_DM_MMC_OPS
+static int mmc_set_vdd(struct mmc *mmc, bool enable)
+{
+	int ret = 0;
+
+	if (mmc->cfg->ops->set_vdd)
+		ret = mmc->cfg->ops->set_vdd(mmc, enable);
+
+	return ret;
+}
+
 static int mmc_set_ios(struct mmc *mmc)
 {
 	int ret = 0;
@@ -1942,7 +1952,7 @@ int mmc_start_init(struct mmc *mmc)
 		return err;
 #endif
 	mmc->ddr_mode = 0;
-
+	mmc_set_vdd(mmc, true);
 	/* First try to set 3.3V. If it fails set to 1.8V */
 	err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
 	if (err != 0)
diff --git a/include/mmc.h b/include/mmc.h
index 89cb26c..43d37a4 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -352,6 +352,15 @@ struct dm_mmc_ops {
 	int (*set_ios)(struct udevice *dev);
 
 	/**
+	 * set_vdd() - Enable or Disable the Vdd line
+	 *
+	 * @dev:	Device to update
+	 * @enable:	true or false to enable or disable Vdd respectively
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*set_vdd)(struct udevice *dev, bool enable);
+
+	/**
 	 * get_cd() - See whether a card is present
 	 *
 	 * @dev:	Device to check
@@ -373,11 +382,13 @@ struct dm_mmc_ops {
 int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 		    struct mmc_data *data);
 int dm_mmc_set_ios(struct udevice *dev);
+int dm_mmc_set_vdd(struct udevice *dev, bool enable);
 int dm_mmc_get_cd(struct udevice *dev);
 int dm_mmc_get_wp(struct udevice *dev);
 
 /* Transition functions for compatibility */
 int mmc_set_ios(struct mmc *mmc);
+int mmc_set_vdd(struct mmc *mmc, bool enable);
 int mmc_getcd(struct mmc *mmc);
 int mmc_getwp(struct mmc *mmc);
 
@@ -387,6 +398,7 @@ struct mmc_ops {
 			struct mmc_cmd *cmd, struct mmc_data *data);
 	int (*set_ios)(struct mmc *mmc);
 	int (*init)(struct mmc *mmc);
+	int (*set_vdd)(struct mmc *mmc, bool enable);
 	int (*getcd)(struct mmc *mmc);
 	int (*getwp)(struct mmc *mmc);
 };
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 14/22] mmc: add power cyle support in mmc core
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (12 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 13/22] mmc: Add a new callback function to enable/disable vdd Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-25 12:35     ` Jaehoon Chung
  2017-05-12 18:16   ` [U-Boot] [PATCH 15/22] mmc: add a new mmc parameter to disable mmc clock Jean-Jacques Hiblot
                     ` (9 subsequent siblings)
  23 siblings, 2 replies; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

mmc/sd specification requires vdd to be disabled for 1 ms
and then enabled again during power cycle. Add a
function in mmc core to perform power cycle and set
the io signal to it's initial state.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc.c | 50 +++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 41 insertions(+), 9 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index d40a22b..032260b 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -30,6 +30,7 @@ static const unsigned int sd_au_size[] = {
 	SZ_16M / 512,	(SZ_16M + SZ_8M) / 512,	SZ_32M / 512,	SZ_64M / 512,
 };
 static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
+static void mmc_power_cycle(struct mmc *mmc);
 
 #if CONFIG_IS_ENABLED(MMC_TINY)
 static struct mmc mmc_static;
@@ -1915,6 +1916,45 @@ static int mmc_power_init(struct mmc *mmc)
 	return 0;
 }
 
+static void mmc_set_initial_state(struct mmc *mmc)
+{
+	int err;
+
+	/* First try to set 3.3V. If it fails set to 1.8V */
+	err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
+	if (err != 0)
+		err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
+	if (err != 0)
+		printf("failed to set signal voltage\n");
+
+	mmc_set_bus_width(mmc, 1);
+	mmc_set_clock(mmc, 1);
+	mmc_select_mode(mmc, MMC_LEGACY);
+}
+
+static void mmc_power_up(struct mmc *mmc)
+{
+	mmc_set_initial_state(mmc);
+	mmc_set_vdd(mmc, true);
+	udelay(10000);
+}
+
+static void mmc_power_off(struct mmc *mmc)
+{
+	mmc_set_vdd(mmc, false);
+}
+
+static void mmc_power_cycle(struct mmc *mmc)
+{
+	mmc_power_off(mmc);
+	/*
+	 * SD spec recommends at least 1ms of delay. Let's wait for 2ms
+	 * to be on the safer side.
+	 */
+	udelay(2000);
+	mmc_power_up(mmc);
+}
+
 int mmc_start_init(struct mmc *mmc)
 {
 	bool no_card;
@@ -1952,16 +1992,8 @@ int mmc_start_init(struct mmc *mmc)
 		return err;
 #endif
 	mmc->ddr_mode = 0;
-	mmc_set_vdd(mmc, true);
-	/* First try to set 3.3V. If it fails set to 1.8V */
-	err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
-	if (err != 0)
-		err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
-	if (err != 0)
-		printf("failed to set signal voltage\n");
 
-	mmc_set_bus_width(mmc, 1);
-	mmc_set_clock(mmc, 1);
+	mmc_power_cycle(mmc);
 
 	/* Reset the Card */
 	err = mmc_go_idle(mmc);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 15/22] mmc: add a new mmc parameter to disable mmc clock
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (13 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 14/22] mmc: add power cyle support in mmc core Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-12 18:16   ` [U-Boot] [PATCH 16/22] mmc: disable the mmc clock during power off Jean-Jacques Hiblot
                     ` (8 subsequent siblings)
  23 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

mmc clock has to be disabled in certain cases like during
the voltage switch sequence. Modify mmc_set_clock function
to take disable as an argument that signifies if the
clock has to be enabled or disabled.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/fsl_esdhc.c |  2 +-
 drivers/mmc/mmc.c       | 11 ++++++-----
 include/mmc.h           |  3 ++-
 3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index f3c6358..b631392 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -658,7 +658,7 @@ static int esdhc_init(struct mmc *mmc)
 #endif
 
 	/* Set the initial clock speed */
-	mmc_set_clock(mmc, 400000);
+	mmc_set_clock(mmc, 400000, false);
 
 	/* Disable the BRR and BWR bits in IRQSTAT */
 	esdhc_clrbits32(&regs->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR);
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 032260b..70b7d19 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1216,7 +1216,7 @@ static int mmc_set_ios(struct mmc *mmc)
 }
 #endif
 
-int mmc_set_clock(struct mmc *mmc, uint clock)
+int mmc_set_clock(struct mmc *mmc, uint clock, u8 disable)
 {
 	if (clock > mmc->cfg->f_max)
 		clock = mmc->cfg->f_max;
@@ -1225,6 +1225,7 @@ int mmc_set_clock(struct mmc *mmc, uint clock)
 		clock = mmc->cfg->f_min;
 
 	mmc->clock = clock;
+	mmc->clk_disable = disable;
 
 	return mmc_set_ios(mmc);
 }
@@ -1316,7 +1317,7 @@ static int sd_select_mode_and_width(struct mmc *mmc)
 
 				/* configure the bus mode (host) */
 				mmc_select_mode(mmc, mwt->mode);
-				mmc_set_clock(mmc, mmc->tran_speed);
+				mmc_set_clock(mmc, mmc->tran_speed, false);
 
 				err = sd_read_ssr(mmc);
 				if (!err)
@@ -1327,7 +1328,7 @@ static int sd_select_mode_and_width(struct mmc *mmc)
 error:
 				/* revert to a safer bus speed */
 				mmc_select_mode(mmc, SD_LEGACY);
-				mmc_set_clock(mmc, mmc->tran_speed);
+				mmc_set_clock(mmc, mmc->tran_speed, false);
 			}
 		}
 	}
@@ -1465,7 +1466,7 @@ static int mmc_select_mode_and_width(struct mmc *mmc)
 
 			/* configure the bus mode (host) */
 			mmc_select_mode(mmc, mwt->mode);
-			mmc_set_clock(mmc, mmc->tran_speed);
+			mmc_set_clock(mmc, mmc->tran_speed, false);
 
 			/* do a transfer to check the configuration */
 			err = mmc_read_and_compare_ext_csd(mmc);
@@ -1928,7 +1929,7 @@ static void mmc_set_initial_state(struct mmc *mmc)
 		printf("failed to set signal voltage\n");
 
 	mmc_set_bus_width(mmc, 1);
-	mmc_set_clock(mmc, 1);
+	mmc_set_clock(mmc, 1, false);
 	mmc_select_mode(mmc, MMC_LEGACY);
 }
 
diff --git a/include/mmc.h b/include/mmc.h
index 43d37a4..097a685 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -466,6 +466,7 @@ struct mmc {
 	void *priv;
 	uint has_init;
 	int high_capacity;
+	u8 clk_disable;
 	uint bus_width;
 	uint clock;
 	uint signal_voltage;
@@ -557,7 +558,7 @@ int mmc_unbind(struct udevice *dev);
 int mmc_initialize(bd_t *bis);
 int mmc_init(struct mmc *mmc);
 int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
-int mmc_set_clock(struct mmc *mmc, uint clock);
+int mmc_set_clock(struct mmc *mmc, uint clock, u8 disable);
 struct mmc *find_mmc_device(int dev_num);
 int mmc_set_dev(int dev_num);
 void print_mmc_devices(char separator);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 16/22] mmc: disable the mmc clock during power off
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (14 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 15/22] mmc: add a new mmc parameter to disable mmc clock Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-12 18:16   ` [U-Boot] [PATCH 17/22] mmc: Add a execute_tuning() callback to the mmc operations Jean-Jacques Hiblot
                     ` (7 subsequent siblings)
  23 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

From: Kishon Vijay Abraham I <kishon@ti.com>

There is no point in having the mmc clock enabled during
power off. Disable the mmc clock. This is similar to how it's
programmed in Linux Kernel.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Vignesh R <vigneshr@ti.com>
Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 70b7d19..415484e 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1943,6 +1943,7 @@ static void mmc_power_up(struct mmc *mmc)
 static void mmc_power_off(struct mmc *mmc)
 {
 	mmc_set_vdd(mmc, false);
+	mmc_set_clock(mmc, 1, true);
 }
 
 static void mmc_power_cycle(struct mmc *mmc)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 17/22] mmc: Add a execute_tuning() callback to the mmc operations.
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (15 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 16/22] mmc: disable the mmc clock during power off Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-25 12:37     ` Jaehoon Chung
  2017-05-12 18:16   ` [U-Boot] [PATCH 18/22] mmc: add HS200 support in MMC core Jean-Jacques Hiblot
                     ` (6 subsequent siblings)
  23 siblings, 2 replies; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

Tuning is a mandatory step in the initialization of SDR104 and HS200 modes.
This callback execute the tuning process.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc-uclass.c | 14 ++++++++++++++
 drivers/mmc/mmc.c        |  5 +++++
 include/mmc.h            | 12 ++++++++++++
 3 files changed, 31 insertions(+)

diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index e1f7995..b7433cf 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -93,6 +93,20 @@ int mmc_getcd(struct mmc *mmc)
 {
 	return dm_mmc_get_cd(mmc->dev);
 }
+
+int dm_mmc_execute_tuning(struct udevice *dev, uint opcode)
+{
+	struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+	if (!ops->execute_tuning)
+		return -ENOSYS;
+	return ops->execute_tuning(dev, opcode);
+}
+
+int mmc_execute_tuning(struct mmc *mmc, uint opcode)
+{
+	return dm_mmc_execute_tuning(mmc->dev, opcode);
+}
 #endif
 
 struct mmc *mmc_get_mmc_dev(struct udevice *dev)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 415484e..d7d1c91 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -219,6 +219,11 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 
 	return ret;
 }
+
+int mmc_execute_tuning(struct mmc *mmc, uint opcode)
+{
+	return mmc->cfg->ops->execute_tuning(mmc, opcode);
+}
 #endif
 
 int mmc_send_status(struct mmc *mmc, int timeout)
diff --git a/include/mmc.h b/include/mmc.h
index 097a685..dab68c5 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -375,6 +375,15 @@ struct dm_mmc_ops {
 	 * @return 0 if write-enabled, 1 if write-protected, -ve on error
 	 */
 	int (*get_wp)(struct udevice *dev);
+
+	/**
+	 * execute_tuning() - Start the tuning process
+	 *
+	 * @dev:	Device to start the tuning
+	 * @opcode:	Command opcode to send
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*execute_tuning)(struct udevice *dev, uint opcode);
 };
 
 #define mmc_get_ops(dev)        ((struct dm_mmc_ops *)(dev)->driver->ops)
@@ -385,12 +394,14 @@ int dm_mmc_set_ios(struct udevice *dev);
 int dm_mmc_set_vdd(struct udevice *dev, bool enable);
 int dm_mmc_get_cd(struct udevice *dev);
 int dm_mmc_get_wp(struct udevice *dev);
+int dm_mmc_execute_tuning(struct udevice *dev, uint opcode);
 
 /* Transition functions for compatibility */
 int mmc_set_ios(struct mmc *mmc);
 int mmc_set_vdd(struct mmc *mmc, bool enable);
 int mmc_getcd(struct mmc *mmc);
 int mmc_getwp(struct mmc *mmc);
+int mmc_execute_tuning(struct mmc *mmc, uint opcode);
 
 #else
 struct mmc_ops {
@@ -401,6 +412,7 @@ struct mmc_ops {
 	int (*set_vdd)(struct mmc *mmc, bool enable);
 	int (*getcd)(struct mmc *mmc);
 	int (*getwp)(struct mmc *mmc);
+	int (*execute_tuning)(struct mmc *mmc, uint opcode);
 };
 #endif
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 18/22] mmc: add HS200 support in MMC core
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (16 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 17/22] mmc: Add a execute_tuning() callback to the mmc operations Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-25 12:42     ` Jaehoon Chung
  2017-05-12 18:16   ` [U-Boot] [PATCH 19/22] mmc: Add a new callback function to check if the card is busy Jean-Jacques Hiblot
                     ` (5 subsequent siblings)
  23 siblings, 2 replies; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

Add HS200 to the list of supported modes and introduce tuning in the MMC
startup process.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc.c | 22 ++++++++++++++++++++--
 include/mmc.h     | 17 +++++++++++++++++
 2 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index d7d1c91..2b710fe 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -621,6 +621,10 @@ static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode)
 	case MMC_HS_52:
 	case MMC_DDR_52:
 		  speed_bits = EXT_CSD_TIMING_HS;
+		  break;
+	case MMC_HS_200:
+		  speed_bits = EXT_CSD_TIMING_HS200;
+		  break;
 	case MMC_LEGACY:
 		  speed_bits = EXT_CSD_TIMING_LEGACY;
 		  break;
@@ -667,9 +671,12 @@ static int mmc_get_capabilities(struct mmc *mmc)
 
 	mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
 
-	cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0xf;
+	cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0x3f;
 
-	/* High Speed is set, there are two types: 52MHz and 26MHz */
+	if (cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V |
+			EXT_CSD_CARD_TYPE_HS200_1_8V)) {
+		mmc->card_caps |= MMC_MODE_HS200;
+	}
 	if (cardtype & EXT_CSD_CARD_TYPE_52) {
 		if (cardtype & EXT_CSD_CARD_TYPE_DDR_52)
 			mmc->card_caps |= MMC_MODE_DDR_52MHz;
@@ -1263,6 +1270,7 @@ void mmc_dump_capabilities(const char *text, uint caps)
 struct mode_width_tuning {
 	enum bus_mode mode;
 	uint widths;
+	uint tuning;
 };
 
 static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
@@ -1373,6 +1381,7 @@ static const struct mode_width_tuning mmc_modes_by_pref[] = {
 	{
 		.mode = MMC_HS_200,
 		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
+		.tuning = MMC_SEND_TUNING_BLOCK_HS200
 	},
 	{
 		.mode = MMC_DDR_52,
@@ -1473,6 +1482,15 @@ static int mmc_select_mode_and_width(struct mmc *mmc)
 			mmc_select_mode(mmc, mwt->mode);
 			mmc_set_clock(mmc, mmc->tran_speed, false);
 
+			/* execute tuning if needed */
+			if (mwt->tuning) {
+				err = mmc_execute_tuning(mmc, mwt->tuning);
+				if (err) {
+					debug("tuning failed\n");
+					goto error;
+				}
+			}
+
 			/* do a transfer to check the configuration */
 			err = mmc_read_and_compare_ext_csd(mmc);
 			if (!err)
diff --git a/include/mmc.h b/include/mmc.h
index dab68c5..b4ffa6a 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -56,6 +56,7 @@
 #define MMC_MODE_HS		(MMC_CAP(MMC_HS) | MMC_CAP(SD_HS))
 #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_8BIT		(1 << 30)
 #define MMC_MODE_4BIT		(1 << 29)
@@ -86,6 +87,7 @@
 #define MMC_CMD_SET_BLOCKLEN		16
 #define MMC_CMD_READ_SINGLE_BLOCK	17
 #define MMC_CMD_READ_MULTIPLE_BLOCK	18
+#define MMC_SEND_TUNING_BLOCK_HS200	21
 #define MMC_CMD_SET_BLOCK_COUNT         23
 #define MMC_CMD_WRITE_SINGLE_BLOCK	24
 #define MMC_CMD_WRITE_MULTIPLE_BLOCK	25
@@ -113,6 +115,13 @@
 #define SD_CMD_APP_SEND_OP_COND		41
 #define SD_CMD_APP_SEND_SCR		51
 
+static inline bool mmc_is_tuning_cmd(uint cmdidx)
+{
+	if (cmdidx == MMC_SEND_TUNING_BLOCK_HS200)
+		return true;
+	return false;
+}
+
 /* SCR definitions in different words */
 #define SD_HIGHSPEED_BUSY	0x00020000
 #define SD_HIGHSPEED_SUPPORTED	0x00020000
@@ -210,6 +219,12 @@
 #define EXT_CSD_CARD_TYPE_DDR_52	(EXT_CSD_CARD_TYPE_DDR_1_8V \
 					| EXT_CSD_CARD_TYPE_DDR_1_2V)
 
+#define EXT_CSD_CARD_TYPE_HS200_1_8V	(1<<4)	/* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_2V	(1<<5)	/* Card can run@200MHz */
+						/* 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_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 */
@@ -217,6 +232,8 @@
 
 #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_BOOT_ACK_ENABLE			(1 << 6)
 #define EXT_CSD_BOOT_PARTITION_ENABLE		(1 << 3)
 #define EXT_CSD_PARTITION_ACCESS_ENABLE		(1 << 0)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 19/22] mmc: Add a new callback function to check if the card is busy
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (17 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 18/22] mmc: add HS200 support in MMC core Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-12 18:16   ` [U-Boot] [PATCH 20/22] mmc: Add support for UHS modes Jean-Jacques Hiblot
                     ` (4 subsequent siblings)
  23 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

Add a new callback function *card_busy* which can be used to check if the
card is busy. This is useful during UHS voltage switching to check if the
switch was successful. Not all controllers may support this, so it's
optional and when not provided the card is deemed ready.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc-uclass.c | 14 ++++++++++++++
 drivers/mmc/mmc.c        | 10 ++++++++++
 include/mmc.h            | 11 +++++++++++
 3 files changed, 35 insertions(+)

diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index b7433cf..75352ed 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -66,6 +66,20 @@ int mmc_set_vdd(struct mmc *mmc, bool enable)
 	return dm_mmc_set_vdd(mmc->dev, enable);
 }
 
+int dm_mmc_card_busy(struct udevice *dev)
+{
+	struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+	if (!ops->card_busy)
+		return 0;
+	return ops->card_busy(dev);
+}
+
+int mmc_card_busy(struct mmc *mmc)
+{
+	return dm_mmc_card_busy(mmc->dev);
+}
+
 int dm_mmc_get_wp(struct udevice *dev)
 {
 	struct dm_mmc_ops *ops = mmc_get_ops(dev);
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 2b710fe..f6509f1 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1217,6 +1217,16 @@ static int mmc_set_vdd(struct mmc *mmc, bool enable)
 	return ret;
 }
 
+static int mmc_card_busy(struct mmc *mmc)
+{
+	int ret = 0;
+
+	if (mmc->cfg->ops->card_busy)
+		ret = mmc->cfg->ops->card_busy(mmc);
+
+	return ret;
+}
+
 static int mmc_set_ios(struct mmc *mmc)
 {
 	int ret = 0;
diff --git a/include/mmc.h b/include/mmc.h
index b4ffa6a..b42f686 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -401,6 +401,14 @@ struct dm_mmc_ops {
 	 * @return 0 if OK, -ve on error
 	 */
 	int (*execute_tuning)(struct udevice *dev, uint opcode);
+
+	/**
+	 * card_busy() - See whether a card is busy
+	 *
+	 * @dev:	Device to check
+	 * @return 1 if busy, O if not busy
+	 */
+	int (*card_busy)(struct udevice *dev);
 };
 
 #define mmc_get_ops(dev)        ((struct dm_mmc_ops *)(dev)->driver->ops)
@@ -412,6 +420,7 @@ int dm_mmc_set_vdd(struct udevice *dev, bool enable);
 int dm_mmc_get_cd(struct udevice *dev);
 int dm_mmc_get_wp(struct udevice *dev);
 int dm_mmc_execute_tuning(struct udevice *dev, uint opcode);
+int dm_mmc_card_busy(struct udevice *dev);
 
 /* Transition functions for compatibility */
 int mmc_set_ios(struct mmc *mmc);
@@ -419,6 +428,7 @@ int mmc_set_vdd(struct mmc *mmc, bool enable);
 int mmc_getcd(struct mmc *mmc);
 int mmc_getwp(struct mmc *mmc);
 int mmc_execute_tuning(struct mmc *mmc, uint opcode);
+int mmc_card_busy(struct mmc *mmc);
 
 #else
 struct mmc_ops {
@@ -430,6 +440,7 @@ struct mmc_ops {
 	int (*getcd)(struct mmc *mmc);
 	int (*getwp)(struct mmc *mmc);
 	int (*execute_tuning)(struct mmc *mmc, uint opcode);
+	int (*card_busy)(struct mmc *mmc);
 };
 #endif
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 20/22] mmc: Add support for UHS modes
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (18 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 19/22] mmc: Add a new callback function to check if the card is busy Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
                       ` (2 more replies)
  2017-05-12 18:16   ` [U-Boot] [PATCH 21/22] mmc: Change mode when switching to a boot partition Jean-Jacques Hiblot
                     ` (3 subsequent siblings)
  23 siblings, 3 replies; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

Add UHS modes to the list of supported modes, get the UHS capabilites of
the SDcard and implement the procedure to switch the voltage (UHS modes
use 1v8 IO lines)
During the voltage switch procedure, DAT0 is used by the card to signal
when it's ready. The optional card_busy() callback can be used to get this
information from the host driver.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 include/mmc.h     |  27 ++++++++-
 2 files changed, 188 insertions(+), 8 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index f6509f1..074d286 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -31,6 +31,7 @@ static const unsigned int sd_au_size[] = {
 };
 static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
 static void mmc_power_cycle(struct mmc *mmc);
+static int mmc_card_busy(struct mmc *mmc);
 
 #if CONFIG_IS_ENABLED(MMC_TINY)
 static struct mmc mmc_static;
@@ -403,7 +404,68 @@ static int mmc_go_idle(struct mmc *mmc)
 	return 0;
 }
 
-static int sd_send_op_cond(struct mmc *mmc)
+static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage)
+{
+	struct mmc_cmd cmd;
+	int err = 0;
+
+	/*
+	 * Send CMD11 only if the request is to switch the card to
+	 * 1.8V signalling.
+	 */
+	if (signal_voltage == MMC_SIGNAL_VOLTAGE_330)
+		return mmc_set_signal_voltage(mmc, signal_voltage);
+
+	cmd.cmdidx = SD_CMD_SWITCH_UHS18V;
+	cmd.cmdarg = 0;
+	cmd.resp_type = MMC_RSP_R1;
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err)
+		goto fail;
+
+	if (!mmc_host_is_spi(host) && (cmd.response[0] & MMC_STATUS_ERROR))
+		goto fail;
+
+	/*
+	 * The card should drive cmd and dat[0:3] low immediately
+	 * after the response of cmd11, but wait 1 ms to be sure
+	 */
+	udelay(1000);
+	if (mmc_card_busy(mmc))
+		goto fail;
+
+	/*
+	 * During a signal voltage level switch, the clock must be gated
+	 * for 5 ms according to the SD spec
+	 */
+	mmc_set_clock(mmc, mmc->clock, true);
+
+	err = mmc_set_signal_voltage(mmc, signal_voltage);
+	if (err)
+		goto fail;
+
+	/* Keep clock gated for at least 10 ms, though spec only says 5 ms */
+	udelay(10000);
+	mmc_set_clock(mmc, mmc->clock, false);
+
+	/* Wait for at least 1 ms according to spec */
+	udelay(1000);
+
+	/*
+	 * Failure to switch is indicated by the card holding
+	 * dat[0:3] low
+	 */
+	if (mmc_card_busy(mmc))
+		goto fail;
+
+	return 0;
+
+fail:
+	return -EIO;
+}
+
+static int sd_send_op_cond(struct mmc *mmc, bool uhs_en)
 {
 	int timeout = 1000;
 	int err;
@@ -435,6 +497,9 @@ static int sd_send_op_cond(struct mmc *mmc)
 		if (mmc->version == SD_VERSION_2)
 			cmd.cmdarg |= OCR_HCS;
 
+		if (uhs_en)
+			cmd.cmdarg |= OCR_S18R;
+
 		err = mmc_send_cmd(mmc, &cmd, NULL);
 
 		if (err)
@@ -465,6 +530,13 @@ static int sd_send_op_cond(struct mmc *mmc)
 
 	mmc->ocr = cmd.response[0];
 
+	if (!(mmc_host_is_spi(mmc)) && (cmd.response[0] & 0x41000000)
+	    == 0x41000000) {
+		err = mmc_switch_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
+		if (err)
+			return err;
+	}
+
 	mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
 	mmc->rca = 0;
 
@@ -977,6 +1049,7 @@ static int sd_get_capabilities(struct mmc *mmc)
 	ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);
 	struct mmc_data data;
 	int timeout;
+	u32 sd3_bus_mode;
 
 	mmc->card_caps = MMC_MODE_1BIT;
 
@@ -1058,6 +1131,22 @@ retry_scr:
 	if (__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED)
 		mmc->card_caps |= MMC_CAP(SD_HS);
 
+	/* Version before 3.0 don't support UHS modes */
+	if (mmc->version < SD_VERSION_3)
+		return 0;
+
+	sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f;
+	if (sd3_bus_mode & SD_MODE_UHS_SDR104)
+		mmc->card_caps |= MMC_CAP(UHS_SDR104);
+	if (sd3_bus_mode & SD_MODE_UHS_SDR50)
+		mmc->card_caps |= MMC_CAP(UHS_SDR50);
+	if (sd3_bus_mode & SD_MODE_UHS_SDR25)
+		mmc->card_caps |= MMC_CAP(UHS_SDR25);
+	if (sd3_bus_mode & SD_MODE_UHS_SDR12)
+		mmc->card_caps |= MMC_CAP(UHS_SDR12);
+	if (sd3_bus_mode & SD_MODE_UHS_DDR50)
+		mmc->card_caps |= MMC_CAP(UHS_DDR50);
+
 	return 0;
 }
 
@@ -1065,13 +1154,36 @@ static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode)
 {
 	int err;
 	ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);
+	int speed;
+
+	switch (mode) {
+	case SD_LEGACY:
+	case UHS_SDR12:
+		speed = UHS_SDR12_BUS_SPEED;
+		break;
+	case SD_HS:
+	case UHS_SDR25:
+		speed = UHS_SDR25_BUS_SPEED;
+		break;
+	case UHS_SDR50:
+		speed = UHS_SDR50_BUS_SPEED;
+		break;
+	case UHS_DDR50:
+		speed = UHS_DDR50_BUS_SPEED;
+		break;
+	case UHS_SDR104:
+		speed = UHS_SDR104_BUS_SPEED;
+		break;
+	default:
+		return -EINVAL;
+	}
 
-	err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status);
+	err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, speed, (u8 *)switch_status);
 
 	if (err)
 		return err;
 
-	if ((__be32_to_cpu(switch_status[4]) & 0x0f000000) != 0x01000000)
+	if ((__be32_to_cpu(switch_status[4]) >> 24) != speed)
 		return -ENOTSUPP;
 
 	return 0;
@@ -1291,10 +1403,31 @@ static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
 
 static const struct mode_width_tuning sd_modes_by_pref[] = {
 	{
+		.mode = UHS_SDR104,
+		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
+		.tuning = MMC_SEND_TUNING_BLOCK
+	},
+	{
+		.mode = UHS_SDR50,
+		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
+	},
+	{
+		.mode = UHS_DDR50,
+		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
+	},
+	{
+		.mode = UHS_SDR25,
+		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
+	},
+	{
 		.mode = SD_HS,
 		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
 	},
 	{
+		.mode = UHS_SDR12,
+		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
+	},
+	{
 		.mode = SD_LEGACY,
 		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
 	}
@@ -1310,18 +1443,24 @@ static int sd_select_mode_and_width(struct mmc *mmc)
 	int err;
 	uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT};
 	const struct mode_width_tuning *mwt;
+	bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false;
+	uint caps;
+
 
 	err = sd_get_capabilities(mmc);
 	if (err)
 		return err;
 	/* Restrict card's capabilities by what the host can do */
-	mmc->card_caps &= (mmc->cfg->host_caps | MMC_MODE_1BIT);
+	caps = mmc->card_caps & (mmc->cfg->host_caps | MMC_MODE_1BIT);
 
-	for_each_sd_mode_by_pref(mmc->card_caps, mwt) {
+	if (!uhs_en)
+		caps &= ~UHS_CAPS;
+
+	for_each_sd_mode_by_pref(caps, mwt) {
 		uint *w;
 
 		for (w = widths; w < widths + ARRAY_SIZE(widths); w++) {
-			if (*w & mmc->card_caps & mwt->widths) {
+			if (*w & caps & mwt->widths) {
 				debug("trying mode %s width %d (at %d MHz)\n",
 				      mmc_mode_name(mwt->mode),
 				      bus_width(*w),
@@ -1342,6 +1481,16 @@ static int sd_select_mode_and_width(struct mmc *mmc)
 				mmc_select_mode(mmc, mwt->mode);
 				mmc_set_clock(mmc, mmc->tran_speed, false);
 
+				/* execute tuning if needed */
+				if (mwt->tuning && !mmc_host_is_spi(mmc)) {
+					err = mmc_execute_tuning(mmc,
+								 mwt->tuning);
+					if (err) {
+						debug("tuning failed\n");
+						goto error;
+					}
+				}
+
 				err = sd_read_ssr(mmc);
 				if (!err)
 					return 0;
@@ -1993,6 +2142,7 @@ static void mmc_power_cycle(struct mmc *mmc)
 int mmc_start_init(struct mmc *mmc)
 {
 	bool no_card;
+	bool uhs_en = supports_uhs(mmc->cfg->host_caps);
 	int err;
 
 	/* we pretend there's no card when init is NULL */
@@ -2028,6 +2178,7 @@ int mmc_start_init(struct mmc *mmc)
 #endif
 	mmc->ddr_mode = 0;
 
+retry:
 	mmc_power_cycle(mmc);
 
 	/* Reset the Card */
@@ -2043,7 +2194,11 @@ int mmc_start_init(struct mmc *mmc)
 	err = mmc_send_if_cond(mmc);
 
 	/* Now try to get the SD card's operating condition */
-	err = sd_send_op_cond(mmc);
+	err = sd_send_op_cond(mmc, uhs_en);
+	if (err && uhs_en) {
+		uhs_en = false;
+		goto retry;
+	}
 
 	/* If the command timed out, we check for an MMC card */
 	if (err == -ETIMEDOUT) {
diff --git a/include/mmc.h b/include/mmc.h
index b42f686..775c47e 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -87,6 +87,7 @@
 #define MMC_CMD_SET_BLOCKLEN		16
 #define MMC_CMD_READ_SINGLE_BLOCK	17
 #define MMC_CMD_READ_MULTIPLE_BLOCK	18
+#define MMC_SEND_TUNING_BLOCK		19
 #define MMC_SEND_TUNING_BLOCK_HS200	21
 #define MMC_CMD_SET_BLOCK_COUNT         23
 #define MMC_CMD_WRITE_SINGLE_BLOCK	24
@@ -117,7 +118,8 @@
 
 static inline bool mmc_is_tuning_cmd(uint cmdidx)
 {
-	if (cmdidx == MMC_SEND_TUNING_BLOCK_HS200)
+	if ((cmdidx == MMC_SEND_TUNING_BLOCK_HS200) ||
+	    (cmdidx == MMC_SEND_TUNING_BLOCK))
 		return true;
 	return false;
 }
@@ -126,8 +128,22 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
 #define SD_HIGHSPEED_BUSY	0x00020000
 #define SD_HIGHSPEED_SUPPORTED	0x00020000
 
+#define UHS_SDR12_BUS_SPEED	0
+#define HIGH_SPEED_BUS_SPEED	1
+#define UHS_SDR25_BUS_SPEED	1
+#define UHS_SDR50_BUS_SPEED	2
+#define UHS_SDR104_BUS_SPEED	3
+#define UHS_DDR50_BUS_SPEED	4
+
+#define SD_MODE_UHS_SDR12	(1 << UHS_SDR12_BUS_SPEED)
+#define SD_MODE_UHS_SDR25	(1 << UHS_SDR25_BUS_SPEED)
+#define SD_MODE_UHS_SDR50	(1 << UHS_SDR50_BUS_SPEED)
+#define SD_MODE_UHS_SDR104	(1 << UHS_SDR104_BUS_SPEED)
+#define SD_MODE_UHS_DDR50	(1 << UHS_DDR50_BUS_SPEED)
+
 #define OCR_BUSY		0x80000000
 #define OCR_HCS			0x40000000
+#define OCR_S18R		0x1000000
 #define OCR_VOLTAGE_MASK	0x007FFF80
 #define OCR_ACCESS_MODE		0x60000000
 
@@ -490,6 +506,15 @@ static inline bool mmc_is_mode_ddr(enum bus_mode mode)
 		return false;
 }
 
+#define UHS_CAPS (MMC_CAP(UHS_SDR12) | MMC_CAP(UHS_SDR25) | \
+		  MMC_CAP(UHS_SDR50) | MMC_CAP(UHS_SDR104) | \
+		  MMC_CAP(UHS_DDR50))
+
+static inline bool supports_uhs(uint caps)
+{
+	return (caps & UHS_CAPS) ? true : false;
+}
+
 
 /*
  * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 21/22] mmc: Change mode when switching to a boot partition
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (19 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 20/22] mmc: Add support for UHS modes Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-25 12:53     ` Jaehoon Chung
  2017-05-12 18:16   ` [U-Boot] [PATCH 22/22] mmc: Retry some MMC cmds on failure Jean-Jacques Hiblot
                     ` (2 subsequent siblings)
  23 siblings, 2 replies; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

Boot partitions do not support HS200. Changing to a lower performance mode
is required to access them.
mmc_select_mode_and_width() and sd_select_mode_and_width() are modified to
make it easier to call them outside of the initialization context.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc.c | 66 +++++++++++++++++++++++++++++++++++++++++--------------
 include/mmc.h     |  1 +
 2 files changed, 50 insertions(+), 17 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 074d286..c7dda64 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -32,6 +32,7 @@ static const unsigned int sd_au_size[] = {
 static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
 static void mmc_power_cycle(struct mmc *mmc);
 static int mmc_card_busy(struct mmc *mmc);
+static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps);
 
 #if CONFIG_IS_ENABLED(MMC_TINY)
 static struct mmc mmc_static;
@@ -788,10 +789,38 @@ static int mmc_set_capacity(struct mmc *mmc, int part_num)
 	return 0;
 }
 
+static int mmc_boot_part_access_chk(struct mmc *mmc, unsigned int part_num)
+{
+	int forbiden = 0;
+	bool change = false;
+
+	if (part_num & PART_ACCESS_MASK)
+		forbiden = MMC_CAP(MMC_HS_200);
+
+	if (MMC_CAP(mmc->selected_mode) & forbiden) {
+		debug("selected mode (%s) is forbiden for part %d\n",
+		      mmc_mode_name(mmc->selected_mode), part_num);
+		change = true;
+	} else if (mmc->selected_mode != mmc->best_mode) {
+		debug("selected mode is not optimal\n");
+		change = true;
+	}
+
+	if (change)
+		return mmc_select_mode_and_width(mmc,
+						 mmc->card_caps & ~forbiden);
+
+	return 0;
+}
+
 int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
 {
 	int ret;
 
+	ret = mmc_boot_part_access_chk(mmc, part_num);
+	if (ret)
+		return ret;
+
 	ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
 			 (mmc->part_config & ~PART_ACCESS_MASK)
 			 | (part_num & PART_ACCESS_MASK));
@@ -1438,7 +1467,7 @@ static const struct mode_width_tuning sd_modes_by_pref[] = {
 	     mwt++) \
 		if (caps & MMC_CAP(mwt->mode))
 
-static int sd_select_mode_and_width(struct mmc *mmc)
+static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
 {
 	int err;
 	uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT};
@@ -1447,11 +1476,8 @@ static int sd_select_mode_and_width(struct mmc *mmc)
 	uint caps;
 
 
-	err = sd_get_capabilities(mmc);
-	if (err)
-		return err;
 	/* Restrict card's capabilities by what the host can do */
-	caps = mmc->card_caps & (mmc->cfg->host_caps | MMC_MODE_1BIT);
+	caps = card_caps & (mmc->cfg->host_caps | MMC_MODE_1BIT);
 
 	if (!uhs_en)
 		caps &= ~UHS_CAPS;
@@ -1582,18 +1608,14 @@ static const struct ext_csd_bus_width {
 	    ecbv++) \
 		if ((ddr == ecbv->is_ddr) && (caps & ecbv->cap))
 
-static int mmc_select_mode_and_width(struct mmc *mmc)
+static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
 {
 	int err;
 	const struct mode_width_tuning *mwt;
 	const struct ext_csd_bus_width *ecbw;
 
-	err = mmc_get_capabilities(mmc);
-	if (err)
-		return err;
-
 	/* Restrict card's capabilities by what the host can do */
-	mmc->card_caps &= (mmc->cfg->host_caps | MMC_MODE_1BIT);
+	card_caps &= (mmc->cfg->host_caps | MMC_MODE_1BIT);
 
 	/* Only version 4 of MMC supports wider bus widths */
 	if (mmc->version < MMC_VERSION_4)
@@ -1605,8 +1627,10 @@ static int mmc_select_mode_and_width(struct mmc *mmc)
 		return -ENOTSUPP;
 	}
 
-	for_each_mmc_mode_by_pref(mmc->card_caps, mwt) {
-		for_each_supported_width(mmc->card_caps & mwt->widths,
+	mmc_set_clock(mmc, mmc->legacy_speed, false);
+
+	for_each_mmc_mode_by_pref(card_caps, mwt) {
+		for_each_supported_width(card_caps & mwt->widths,
 					 mmc_is_mode_ddr(mwt->mode), ecbw) {
 			debug("trying mode %s width %d (at %d MHz)\n",
 			      mmc_mode_name(mwt->mode),
@@ -1999,14 +2023,22 @@ static int mmc_startup(struct mmc *mmc)
 	if (err)
 		return err;
 
-	if (IS_SD(mmc))
-		err = sd_select_mode_and_width(mmc);
-	else
-		err = mmc_select_mode_and_width(mmc);
+	if (IS_SD(mmc)) {
+		err = sd_get_capabilities(mmc);
+		if (err)
+			return err;
+		err = sd_select_mode_and_width(mmc, mmc->card_caps);
+	} else {
+		err = mmc_get_capabilities(mmc);
+		if (err)
+			return err;
+		mmc_select_mode_and_width(mmc, mmc->card_caps);
+	}
 
 	if (err)
 		return err;
 
+	mmc->best_mode = mmc->selected_mode;
 
 	/* Fix the block length for DDR mode */
 	if (mmc->ddr_mode) {
diff --git a/include/mmc.h b/include/mmc.h
index 775c47e..921a7ff 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -573,6 +573,7 @@ struct mmc {
 #endif
 	u8 *ext_csd;
 	enum bus_mode selected_mode;
+	enum bus_mode best_mode;
 };
 
 struct mmc_hwpart_conf {
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 22/22] mmc: Retry some MMC cmds on failure
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (20 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 21/22] mmc: Change mode when switching to a boot partition Jean-Jacques Hiblot
@ 2017-05-12 18:16   ` Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-15  2:33   ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jaehoon Chung
  2017-05-18  4:27   ` Jaehoon Chung
  23 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-12 18:16 UTC (permalink / raw)
  To: u-boot

From: Vignesh R <vigneshr@ti.com>

With certain SD cards like Kingston 8GB/16GB UHS card, it is seen that
MMC_CMD_ALL_SEND_CID cmd fails on first attempt, but succeeds
subsequently. Therefore, retry MMC_CMD_ALL_SEND_CID cmd at least thrice
as done in Linux kernel.
Similarly, it is seen that MMC_CMD_SET_BLOCKLEN may fail on first
attempt, therefore retry this cmd five times as done in kernel.

Signed-off-by: Vignesh R <vigneshr@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
---
 drivers/mmc/mmc.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index c7dda64..49edf52 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -275,6 +275,8 @@ int mmc_send_status(struct mmc *mmc, int timeout)
 int mmc_set_blocklen(struct mmc *mmc, int len)
 {
 	struct mmc_cmd cmd;
+	int retries = 5;
+	int err;
 
 	if (mmc->ddr_mode)
 		return 0;
@@ -282,8 +284,13 @@ int mmc_set_blocklen(struct mmc *mmc, int len)
 	cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
 	cmd.resp_type = MMC_RSP_R1;
 	cmd.cmdarg = len;
+	do {
+		err = mmc_send_cmd(mmc, &cmd, NULL);
+		if (!err)
+			break;
+	} while (retries--);
 
-	return mmc_send_cmd(mmc, &cmd, NULL);
+	return err;
 }
 
 static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
@@ -1867,6 +1874,7 @@ static int mmc_startup(struct mmc *mmc)
 	u64 cmult, csize;
 	struct mmc_cmd cmd;
 	struct blk_desc *bdesc;
+	int retries = 3;
 
 #ifdef CONFIG_MMC_SPI_CRC_ON
 	if (mmc_host_is_spi(mmc)) { /* enable CRC check for spi */
@@ -1874,7 +1882,6 @@ static int mmc_startup(struct mmc *mmc)
 		cmd.resp_type = MMC_RSP_R1;
 		cmd.cmdarg = 1;
 		err = mmc_send_cmd(mmc, &cmd, NULL);
-
 		if (err)
 			return err;
 	}
@@ -1886,7 +1893,9 @@ static int mmc_startup(struct mmc *mmc)
 	cmd.resp_type = MMC_RSP_R2;
 	cmd.cmdarg = 0;
 
-	err = mmc_send_cmd(mmc, &cmd, NULL);
+	do {
+		err = mmc_send_cmd(mmc, &cmd, NULL);
+	} while (err && retries-- > 0);
 
 	if (err)
 		return err;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (21 preceding siblings ...)
  2017-05-12 18:16   ` [U-Boot] [PATCH 22/22] mmc: Retry some MMC cmds on failure Jean-Jacques Hiblot
@ 2017-05-15  2:33   ` Jaehoon Chung
  2017-05-18  4:27   ` Jaehoon Chung
  23 siblings, 0 replies; 85+ messages in thread
From: Jaehoon Chung @ 2017-05-15  2:33 UTC (permalink / raw)
  To: u-boot

Hi Jean,

On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
> This series brings support for HS200 and UHS modes to the mmc core.
> It has been tested with the hsmmc driver on several platforms (DRA7,
> AM57x, AM437x, beaglebone black). Some modifications are required in
> the host driver to take advantage of this (voltage switching, tuning).
> The changes to the host driver will be posted a another series as this
> one is already long enough. 
> 
> The series starts with a small refactoring of th sd/mmc startup. The first 4 commits
> are mostly moving code around with little or no functionnal change.
> 
> Then the notion of "mode" is introduced. Until now, this information wasn't
> kept in struct mmc. Only the clock and a flag for ddr was kept. Later the mode
> information will be used to select the clock frequency, the ddr flag and the
> tuning procedure. It will be also be check against the host capabilities.
> 
> Then comes the big refactoring job in:
> "mmc: refactor MMC startup to make it easier to support new modes" and
> "mmc: refactor SD startup to make it easier to support new modes"
> Since the number of modes is increasing, it makes sense to try them in a more
> organized way. those commits use a list of supported modes and iterate through
> them to find the best working one. It also allows to switch more easilly from
> one mode to another (switching from HS200 to DDR52 to access boot partitions for example)

Thanks for sending patches. After testing your patches, i will reply.

Best Regards,
Jaehoon Chung

> 
> Then there are a couple of new callback added to:
> - enable/disable Vdd
> - check if the card is busy (used during UHS voltage switching)
> - select the IO voltage
> 
> Then Power cycle is added. Without power cycle, if a UHS card fails to enumerate in
> UHS mode, it can't fall back to high speed mode and card enumeration will fail.
> 
> And finally the last commits add the support for HS200 and UHS.
> I haven't been able to test the UHS SDR104 mode by lack of compatible sdcard.
> 
> With this in place and the required changes in the HSMMC (including DAM), we observe significant
> improvements in the performances on a DRA7 evm:
> eMMC HS200: 130 MB/s
> eMMC DDR52: 80 MB/s
> sd   SDR50: 80 MB/s
> 
> cheers,
> 
> Jean-Jacques
> 
> 
> Jean-Jacques Hiblot (18):
>   mmc: split mmc_startup()
>   mmc: move the MMC startup for version above v4.0 in a separate
>     function
>   mmc: make ext_csd part of struct mmc
>   mmc: add a function to read and test the ext csd (mmc >= 4)
>   mmc: introduces mmc modes.
>   mmc: Add a fonction to dump the mmc capabilities
>   mmc: use mmc modes to select the correct bus speed
>   cmd: mmc: display the mode name and current bus speed in the mmc info
>   mmc: refactor SD startup to make it easier to support new modes
>   mmc: refactor MMC startup to make it easier to support new modes
>   mmc: make mmc_set_ios() return status
>   mmc: add power cyle support in mmc core
>   mmc: add a new mmc parameter to disable mmc clock
>   mmc: Add a execute_tuning() callback to the mmc operations.
>   mmc: add HS200 support in MMC core
>   mmc: Add a new callback function to check if the card is busy
>   mmc: Add support for UHS modes
>   mmc: Change mode when switching to a boot partition
> 
> Kishon Vijay Abraham I (3):
>   mmc: Enable signal voltage to be selected from mmc core
>   mmc: Add a new callback function to enable/disable vdd
>   mmc: disable the mmc clock during power off
> 
> Vignesh R (1):
>   mmc: Retry some MMC cmds on failure
> 
>  cmd/mmc.c                |    3 +-
>  drivers/mmc/fsl_esdhc.c  |    2 +-
>  drivers/mmc/mmc-uclass.c |   42 ++
>  drivers/mmc/mmc.c        | 1220 +++++++++++++++++++++++++++++++++-------------
>  include/mmc.h            |  138 +++++-
>  5 files changed, 1058 insertions(+), 347 deletions(-)
> 

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 01/22] mmc: split mmc_startup()
  2017-05-12 18:16   ` [U-Boot] [PATCH 01/22] mmc: split mmc_startup() Jean-Jacques Hiblot
@ 2017-05-15  3:27     ` Simon Glass
  0 siblings, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:27 UTC (permalink / raw)
  To: u-boot

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> No functionnal change here. The function is really big and can be split.
> The part related to bus configuration are put in 2 separate functions: one
> for MMC and one for SD.
>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 275 +++++++++++++++++++++++++++++-------------------------
>  1 file changed, 149 insertions(+), 126 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 02/22] mmc: move the MMC startup for version above v4.0 in a separate function
  2017-05-12 18:16   ` [U-Boot] [PATCH 02/22] mmc: move the MMC startup for version above v4.0 in a separate function Jean-Jacques Hiblot
@ 2017-05-15  3:27     ` Simon Glass
  0 siblings, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:27 UTC (permalink / raw)
  To: u-boot

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> no functionnal change. This is only to further reduce the size o
> mmc_startup().
>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 316 ++++++++++++++++++++++++++++--------------------------
>  1 file changed, 165 insertions(+), 151 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 03/22] mmc: make ext_csd part of struct mmc
  2017-05-12 18:16   ` [U-Boot] [PATCH 03/22] mmc: make ext_csd part of struct mmc Jean-Jacques Hiblot
@ 2017-05-15  3:27     ` Simon Glass
  0 siblings, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:27 UTC (permalink / raw)
  To: u-boot

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> The ext csd is used for comparison many times. Keep a reference content
> of the ext csd in the struct mmc to avoid reading multiple times
>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 22 +++++++++++++++++-----
>  include/mmc.h     |  1 +
>  2 files changed, 18 insertions(+), 5 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

But I think debug() is better than error() to avoid code bloat for
something that cannot happen.

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 04/22] mmc: add a function to read and test the ext csd (mmc >= 4)
  2017-05-12 18:16   ` [U-Boot] [PATCH 04/22] mmc: add a function to read and test the ext csd (mmc >= 4) Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  0 siblings, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> This will be reused later in the selection of high speed and ddr modes.
>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 49 +++++++++++++++++++++++++++++--------------------
>  1 file changed, 29 insertions(+), 20 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

Please add a function comment.

>
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 4bd6a96..344d760 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -1146,10 +1146,35 @@ static int sd_select_bus_freq_width(struct mmc *mmc)
>         return 0;
>  }
>
> -static int mmc_select_bus_freq_width(struct mmc *mmc)
> +static int mmc_read_and_compare_ext_csd(struct mmc *mmc)
>  {
> -       ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
> +       int err;
>         const u8 *ext_csd = mmc->ext_csd;
> +       ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
> +
> +       err = mmc_send_ext_csd(mmc, test_csd);
> +       if (err)
> +               return err;
> +
> +       /* Only compare read only fields */
> +       if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT]
> +               == test_csd[EXT_CSD_PARTITIONING_SUPPORT] &&
> +           ext_csd[EXT_CSD_HC_WP_GRP_SIZE]
> +               == test_csd[EXT_CSD_HC_WP_GRP_SIZE] &&
> +           ext_csd[EXT_CSD_REV]
> +               == test_csd[EXT_CSD_REV] &&
> +           ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
> +               == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] &&
> +           memcmp(&ext_csd[EXT_CSD_SEC_CNT],
> +                   &test_csd[EXT_CSD_SEC_CNT], 4) == 0)
> +               return 0;
> +
> +       return -EBADMSG;
> +}
> +
> +
> +static int mmc_select_bus_freq_width(struct mmc *mmc)
> +{
>         /* An array of possible bus widths in order of preference */
>         static const unsigned ext_csd_bits[] = {
>                 EXT_CSD_DDR_BUS_WIDTH_8,
> @@ -1222,25 +1247,9 @@ static int mmc_select_bus_freq_width(struct mmc *mmc)
>                 mmc->ddr_mode = (caps & MMC_MODE_DDR_52MHz) ? 1 : 0;
>                 mmc_set_bus_width(mmc, widths[idx]);
>
> -               err = mmc_send_ext_csd(mmc, test_csd);
> -
> -               if (err)
> -                       continue;
> -
> -               /* Only compare read only fields */
> -               if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT]
> -                       == test_csd[EXT_CSD_PARTITIONING_SUPPORT] &&
> -                   ext_csd[EXT_CSD_HC_WP_GRP_SIZE]
> -                       == test_csd[EXT_CSD_HC_WP_GRP_SIZE] &&
> -                   ext_csd[EXT_CSD_REV]
> -                       == test_csd[EXT_CSD_REV] &&
> -                   ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
> -                       == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] &&
> -                   memcmp(&ext_csd[EXT_CSD_SEC_CNT],
> -                           &test_csd[EXT_CSD_SEC_CNT], 4) == 0)
> +               err = mmc_read_and_compare_ext_csd(mmc);
> +               if (!err)
>                         break;
> -               else
> -                       err = -EBADMSG;
>         }
>
>         if (err)
> --
> 1.9.1
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 05/22] mmc: introduces mmc modes.
  2017-05-12 18:16   ` [U-Boot] [PATCH 05/22] mmc: introduces mmc modes Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  2017-05-15 10:34       ` Jean-Jacques Hiblot
  0 siblings, 1 reply; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:

Subject: drop the period at the end

Also I think 'mmc: Introduce MMC modes' is better (imperative tense)

> no functionnal changes.
> In order to add the support for the high speed SD and MMC modes, it is
> useful to track this information.
>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++-------
>  include/mmc.h     | 34 ++++++++++++++++++++++++++++------
>  2 files changed, 74 insertions(+), 13 deletions(-)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

Also see below

> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 344d760..2e1cb0d 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -149,6 +149,36 @@ void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd)
>  }
>  #endif
>
> +const char *mmc_mode_name(enum bus_mode mode)
> +{
> +       static const char *const names[] = {
> +             [MMC_LEGACY]      = "MMC legacy",
> +             [SD_LEGACY]       = "SD Legacy",
> +             [MMC_HS]          = "MMC High Speed (26MHz)",
> +             [SD_HS]           = "SD High Speed (50MHz)",
> +             [UHS_SDR12]       = "UHS SDR12 (25MHz)",
> +             [UHS_SDR25]       = "UHS SDR25 (50MHz)",
> +             [UHS_SDR50]       = "UHS SDR50 (100MHz)",
> +             [UHS_SDR104]      = "UHS SDR104 (208MHz)",
> +             [UHS_DDR50]       = "UHS DDR50 (50MHz)",
> +             [MMC_HS_52]       = "MMC High Speed (52MHz)",
> +             [MMC_DDR_52]      = "MMC DDR52 (52MHz)",
> +             [MMC_HS_200]      = "HS200 (200MHz)",

Can we hide this behind a Kconfig so boards can turn it off to reduce
code size in SPL?

> +       };
> +
> +       if (mode >= MMC_MODES_END)
> +               return "Unknown mode";
> +       else
> +               return names[mode];
> +}
> +static int mmc_select_mode(struct mmc *mmc, enum bus_mode mode)
> +{
> +       mmc->selected_mode = mode;
> +       debug("selecting mode %s (freq : %d MHz)\n", mmc_mode_name(mode),
> +             mmc->tran_speed / 1000000);
> +       return 0;
> +}
> +
>  #ifndef CONFIG_DM_MMC_OPS
>  int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
>  {
> @@ -1138,10 +1168,13 @@ static int sd_select_bus_freq_width(struct mmc *mmc)
>         if (err)
>                 return err;
>
> -       if (mmc->card_caps & MMC_MODE_HS)
> +       if (mmc->card_caps & MMC_MODE_HS) {
> +               mmc_select_mode(mmc, SD_HS);
>                 mmc->tran_speed = 50000000;
> -       else
> +       } else {
> +               mmc_select_mode(mmc, SD_LEGACY);
>                 mmc->tran_speed = 25000000;
> +       }
>
>         return 0;
>  }
> @@ -1255,11 +1288,15 @@ static int mmc_select_bus_freq_width(struct mmc *mmc)
>         if (err)
>                 return err;
>
> -       if (mmc->card_caps & MMC_MODE_HS) {
> -               if (mmc->card_caps & MMC_MODE_HS_52MHz)
> -                       mmc->tran_speed = 52000000;
> +       if (mmc->card_caps & MMC_MODE_HS_52MHz) {
> +               if (mmc->ddr_mode)
> +                       mmc_select_mode(mmc, MMC_DDR_52);
>                 else
> -                       mmc->tran_speed = 26000000;
> +                       mmc_select_mode(mmc, MMC_HS_52);
> +               mmc->tran_speed = 52000000;
> +       } else if (mmc->card_caps & MMC_MODE_HS) {
> +               mmc_select_mode(mmc, MMC_HS);
> +               mmc->tran_speed = 26000000;
>         }
>
>         return err;
> @@ -1529,7 +1566,9 @@ static int mmc_startup(struct mmc *mmc)
>         freq = fbase[(cmd.response[0] & 0x7)];
>         mult = multipliers[((cmd.response[0] >> 3) & 0xf)];
>
> -       mmc->tran_speed = freq * mult;
> +       mmc->legacy_speed = freq * mult;
> +       mmc->tran_speed = mmc->legacy_speed;
> +       mmc_select_mode(mmc, MMC_LEGACY);
>
>         mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1);
>         mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf);
> diff --git a/include/mmc.h b/include/mmc.h
> index 9af6b52..60a43b0 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -52,12 +52,15 @@
>  #define MMC_VERSION_5_0                MAKE_MMC_VERSION(5, 0, 0)
>  #define MMC_VERSION_5_1                MAKE_MMC_VERSION(5, 1, 0)
>
> -#define MMC_MODE_HS            (1 << 0)
> -#define MMC_MODE_HS_52MHz      (1 << 1)
> -#define MMC_MODE_4BIT          (1 << 2)
> -#define MMC_MODE_8BIT          (1 << 3)
> -#define MMC_MODE_SPI           (1 << 4)
> -#define MMC_MODE_DDR_52MHz     (1 << 5)
> +#define MMC_CAP(mode)          (1 << mode)
> +#define MMC_MODE_HS            (MMC_CAP(MMC_HS) | MMC_CAP(SD_HS))
> +#define MMC_MODE_HS_52MHz      MMC_CAP(MMC_HS_52)
> +#define MMC_MODE_DDR_52MHz     MMC_CAP(MMC_DDR_52)
> +
> +#define MMC_MODE_8BIT          (1 << 30)
> +#define MMC_MODE_4BIT          (1 << 29)
> +#define MMC_MODE_SPI           (1 << 27)
> +
>
>  #define SD_DATA_4BIT   0x00040000
>
> @@ -402,6 +405,23 @@ struct sd_ssr {
>         unsigned int erase_offset;      /* In milliseconds */
>  };
>
> +enum bus_mode {
> +       MMC_LEGACY      = 0,
> +       SD_LEGACY       = 1,
> +       MMC_HS          = 2,
> +       SD_HS           = 3,
> +       UHS_SDR12       = 4,
> +       UHS_SDR25       = 5,
> +       UHS_SDR50       = 6,
> +       UHS_SDR104      = 7,
> +       UHS_DDR50       = 8,
> +       MMC_HS_52       = 9,
> +       MMC_DDR_52      = 10,
> +       MMC_HS_200      = 11,

Do you need to specify the values or would defaults be OK?

> +       MMC_MODES_END
> +};
> +
> +const char *mmc_mode_name(enum bus_mode mode);
>  /*
>   * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device
>   * with mmc_get_mmc_dev().
> @@ -432,6 +452,7 @@ struct mmc {
>         u8 wr_rel_set;
>         char part_config;
>         uint tran_speed;
> +       uint legacy_speed;

Please add comment. Should this be an enum?

>         uint read_bl_len;
>         uint write_bl_len;
>         uint erase_grp_size;    /* in 512-byte sectors */
> @@ -455,6 +476,7 @@ struct mmc {
>         struct udevice *dev;    /* Device for this MMC controller */
>  #endif
>         u8 *ext_csd;
> +       enum bus_mode selected_mode;
>  };
>
>  struct mmc_hwpart_conf {
> --
> 1.9.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 07/22] mmc: use mmc modes to select the correct bus speed
  2017-05-12 18:16   ` [U-Boot] [PATCH 07/22] mmc: use mmc modes to select the correct bus speed Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  0 siblings, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:

Please add commit message which what is happening and motivation.

> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 40 +++++++++++++++++++++++++++++-----------
>  1 file changed, 29 insertions(+), 11 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

>
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 5d418c5..dc7985f 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -171,9 +171,35 @@ const char *mmc_mode_name(enum bus_mode mode)
>         else
>                 return names[mode];
>  }
> +
> +static uint mmc_mode2freq(struct mmc *mmc, enum bus_mode mode)
> +{
> +       static const int freqs[] = {
> +             [SD_LEGACY]       = 25000000,
> +             [MMC_HS]          = 26000000,
> +             [SD_HS]           = 50000000,
> +             [UHS_SDR12]       = 25000000,
> +             [UHS_SDR25]       = 50000000,
> +             [UHS_SDR50]       = 100000000,
> +             [UHS_SDR104]      = 208000000,
> +             [UHS_DDR50]       = 50000000,
> +             [MMC_HS_52]       = 52000000,
> +             [MMC_DDR_52]      = 52000000,
> +             [MMC_HS_200]      = 200000000,
> +       };
> +
> +       if (mode == MMC_LEGACY)
> +               return mmc->legacy_speed;
> +       else if (mode >= MMC_MODES_END)
> +               return 0;
> +       else
> +               return freqs[mode];
> +}
> +
>  static int mmc_select_mode(struct mmc *mmc, enum bus_mode mode)
>  {
>         mmc->selected_mode = mode;
> +       mmc->tran_speed = mmc_mode2freq(mmc, mode);
>         debug("selecting mode %s (freq : %d MHz)\n", mmc_mode_name(mode),
>               mmc->tran_speed / 1000000);
>         return 0;
> @@ -1185,13 +1211,10 @@ static int sd_select_bus_freq_width(struct mmc *mmc)
>         if (err)
>                 return err;
>
> -       if (mmc->card_caps & MMC_MODE_HS) {
> +       if (mmc->card_caps & MMC_MODE_HS)
>                 mmc_select_mode(mmc, SD_HS);
> -               mmc->tran_speed = 50000000;
> -       } else {
> +       else
>                 mmc_select_mode(mmc, SD_LEGACY);
> -               mmc->tran_speed = 25000000;
> -       }
>
>         return 0;
>  }
> @@ -1310,11 +1333,8 @@ static int mmc_select_bus_freq_width(struct mmc *mmc)
>                         mmc_select_mode(mmc, MMC_DDR_52);
>                 else
>                         mmc_select_mode(mmc, MMC_HS_52);
> -               mmc->tran_speed = 52000000;
> -       } else if (mmc->card_caps & MMC_MODE_HS) {
> +       } else if (mmc->card_caps & MMC_MODE_HS)
>                 mmc_select_mode(mmc, MMC_HS);
> -               mmc->tran_speed = 26000000;
> -       }
>
>         return err;
>  }
> @@ -1584,7 +1604,6 @@ static int mmc_startup(struct mmc *mmc)
>         mult = multipliers[((cmd.response[0] >> 3) & 0xf)];
>
>         mmc->legacy_speed = freq * mult;
> -       mmc->tran_speed = mmc->legacy_speed;
>         mmc_select_mode(mmc, MMC_LEGACY);
>
>         mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1);
> @@ -1659,7 +1678,6 @@ static int mmc_startup(struct mmc *mmc)
>         if (err)
>                 return err;
>
> -       mmc_set_clock(mmc, mmc->tran_speed);
>
>         /* Fix the block length for DDR mode */
>         if (mmc->ddr_mode) {
> --
> 1.9.1
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 09/22] mmc: refactor SD startup to make it easier to support new modes
  2017-05-12 18:16   ` [U-Boot] [PATCH 09/22] mmc: refactor SD startup to make it easier to support new modes Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  2017-05-15 10:49       ` Jean-Jacques Hiblot
  0 siblings, 1 reply; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> The SDcard startup process currently handles only 2 modes. To make it
> easier to add support for more modes, let's make the process more generic
> and use a list of the modes to try.
> The major functional change is that when a mode fails we try the next one.
> Not all modes are tried, only those supported by the card and the host.
>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 180 ++++++++++++++++++++++++++++++++++++++----------------
>  include/mmc.h     |   1 +
>  2 files changed, 128 insertions(+), 53 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

Will you be using that foreach macro multiple times?

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 10/22] mmc: refactor MMC startup to make it easier to support new modes
  2017-05-12 18:16   ` [U-Boot] [PATCH 10/22] mmc: refactor MMC " Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  2017-05-25 12:25     ` Jaehoon Chung
  1 sibling, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> The MMC startup process currently handles 4 modes. To make it easier to
> add support for more modes, let's make the process more generic and use a
> list of the modes to try.
> The major functional change is that when a mode fails we try the next one.
> Not all modes are tried, only those supported by the card and the host.
>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 238 +++++++++++++++++++++++++++++++++---------------------
>  include/mmc.h     |  15 +++-
>  2 files changed, 157 insertions(+), 96 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 11/22] mmc: make mmc_set_ios() return status
  2017-05-12 18:16   ` [U-Boot] [PATCH 11/22] mmc: make mmc_set_ios() return status Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  0 siblings, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> set_ios callback has a return value of 'int' but the mmc_set_ios()
> function ignore this. Modify mmc_set_ios() and the callers of mmc_set_ios() to
> to return the error status.
>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 16 ++++++++++------
>  include/mmc.h     |  2 +-
>  2 files changed, 11 insertions(+), 7 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

>
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 2931871..2ae6f1c 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -1193,14 +1193,18 @@ static inline int bus_width(uint cap)
>  }
>
>  #ifndef CONFIG_DM_MMC_OPS
> -static void mmc_set_ios(struct mmc *mmc)
> +static int mmc_set_ios(struct mmc *mmc)
>  {
> +       int ret = 0;
> +
>         if (mmc->cfg->ops->set_ios)
> -               mmc->cfg->ops->set_ios(mmc);
> +               ret = mmc->cfg->ops->set_ios(mmc);
> +
> +       return ret;
>  }
>  #endif
>
> -void mmc_set_clock(struct mmc *mmc, uint clock)
> +int mmc_set_clock(struct mmc *mmc, uint clock)
>  {
>         if (clock > mmc->cfg->f_max)
>                 clock = mmc->cfg->f_max;
> @@ -1210,14 +1214,14 @@ void mmc_set_clock(struct mmc *mmc, uint clock)
>
>         mmc->clock = clock;
>
> -       mmc_set_ios(mmc);
> +       return mmc_set_ios(mmc);
>  }
>
> -static void mmc_set_bus_width(struct mmc *mmc, uint width)
> +static int mmc_set_bus_width(struct mmc *mmc, uint width)
>  {
>         mmc->bus_width = width;
>
> -       mmc_set_ios(mmc);
> +       return mmc_set_ios(mmc);
>  }
>
>  void mmc_dump_capabilities(const char *text, uint caps)
> diff --git a/include/mmc.h b/include/mmc.h
> index 3c6971d..9f20eb4 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -540,7 +540,7 @@ int mmc_unbind(struct udevice *dev);
>  int mmc_initialize(bd_t *bis);
>  int mmc_init(struct mmc *mmc);
>  int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
> -void mmc_set_clock(struct mmc *mmc, uint clock);
> +int mmc_set_clock(struct mmc *mmc, uint clock);

Please add function comment.

>  struct mmc *find_mmc_device(int dev_num);
>  int mmc_set_dev(int dev_num);
>  void print_mmc_devices(char separator);
> --
> 1.9.1
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 13/22] mmc: Add a new callback function to enable/disable vdd
  2017-05-12 18:16   ` [U-Boot] [PATCH 13/22] mmc: Add a new callback function to enable/disable vdd Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  0 siblings, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

Hi,

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> From: Kishon Vijay Abraham I <kishon@ti.com>
>
> Add a new callback function *set_vdd* which can be used
> by the platform mmc driver to enable or disable vdd.
> The mmc core can use *mmc_set_vdd* in order to invoke
> the callback function. This will be used during power cycle
> where the specification requires vdd to be disabled for
> 1ms and enabled again.
>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc-uclass.c | 14 ++++++++++++++
>  drivers/mmc/mmc.c        | 12 +++++++++++-
>  include/mmc.h            | 12 ++++++++++++
>  3 files changed, 37 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
> index 9c07871..e1f7995 100644
> --- a/drivers/mmc/mmc-uclass.c
> +++ b/drivers/mmc/mmc-uclass.c
> @@ -52,6 +52,20 @@ int mmc_set_ios(struct mmc *mmc)
>         return dm_mmc_set_ios(mmc->dev);
>  }
>
> +int dm_mmc_set_vdd(struct udevice *dev, bool enable)
> +{
> +       struct dm_mmc_ops *ops = mmc_get_ops(dev);
> +
> +       if (!ops->set_vdd)
> +               return -ENOSYS;
> +       return ops->set_vdd(dev, enable);
> +}
> +
> +int mmc_set_vdd(struct mmc *mmc, bool enable)
> +{
> +       return dm_mmc_set_vdd(mmc->dev, enable);
> +}
> +
>  int dm_mmc_get_wp(struct udevice *dev)
>  {
>         struct dm_mmc_ops *ops = mmc_get_ops(dev);
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 10af81d..d40a22b 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -1194,6 +1194,16 @@ static inline int bus_width(uint cap)
>  }
>
>  #ifndef CONFIG_DM_MMC_OPS

Please don't do this. This option is the current way of doing things -
we should not support features in legacy code. Instead, boards should
upgrade to DM to get new features.

> +static int mmc_set_vdd(struct mmc *mmc, bool enable)
> +{
> +       int ret = 0;
> +
> +       if (mmc->cfg->ops->set_vdd)
> +               ret = mmc->cfg->ops->set_vdd(mmc, enable);
> +
> +       return ret;
> +}
> +
>  static int mmc_set_ios(struct mmc *mmc)
>  {
>         int ret = 0;
> @@ -1942,7 +1952,7 @@ int mmc_start_init(struct mmc *mmc)
>                 return err;
>  #endif
>         mmc->ddr_mode = 0;
> -
> +       mmc_set_vdd(mmc, true);
>         /* First try to set 3.3V. If it fails set to 1.8V */
>         err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
>         if (err != 0)
> diff --git a/include/mmc.h b/include/mmc.h
> index 89cb26c..43d37a4 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -352,6 +352,15 @@ struct dm_mmc_ops {
>         int (*set_ios)(struct udevice *dev);
>
>         /**
> +        * set_vdd() - Enable or Disable the Vdd line
> +        *
> +        * @dev:        Device to update
> +        * @enable:     true or false to enable or disable Vdd respectively
> +        * @return 0 if OK, -ve on error
> +        */
> +       int (*set_vdd)(struct udevice *dev, bool enable);
> +
> +       /**
>          * get_cd() - See whether a card is present
>          *
>          * @dev:        Device to check
> @@ -373,11 +382,13 @@ struct dm_mmc_ops {
>  int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
>                     struct mmc_data *data);
>  int dm_mmc_set_ios(struct udevice *dev);
> +int dm_mmc_set_vdd(struct udevice *dev, bool enable);
>  int dm_mmc_get_cd(struct udevice *dev);
>  int dm_mmc_get_wp(struct udevice *dev);
>
>  /* Transition functions for compatibility */
>  int mmc_set_ios(struct mmc *mmc);
> +int mmc_set_vdd(struct mmc *mmc, bool enable);
>  int mmc_getcd(struct mmc *mmc);
>  int mmc_getwp(struct mmc *mmc);
>
> @@ -387,6 +398,7 @@ struct mmc_ops {
>                         struct mmc_cmd *cmd, struct mmc_data *data);
>         int (*set_ios)(struct mmc *mmc);
>         int (*init)(struct mmc *mmc);
> +       int (*set_vdd)(struct mmc *mmc, bool enable);

Just drop this.

>         int (*getcd)(struct mmc *mmc);
>         int (*getwp)(struct mmc *mmc);
>  };
> --
> 1.9.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 15/22] mmc: add a new mmc parameter to disable mmc clock
  2017-05-12 18:16   ` [U-Boot] [PATCH 15/22] mmc: add a new mmc parameter to disable mmc clock Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  0 siblings, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

Hi,

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> mmc clock has to be disabled in certain cases like during
> the voltage switch sequence. Modify mmc_set_clock function
> to take disable as an argument that signifies if the
> clock has to be enabled or disabled.
>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/fsl_esdhc.c |  2 +-
>  drivers/mmc/mmc.c       | 11 ++++++-----
>  include/mmc.h           |  3 ++-
>  3 files changed, 9 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
> index f3c6358..b631392 100644
> --- a/drivers/mmc/fsl_esdhc.c
> +++ b/drivers/mmc/fsl_esdhc.c
> @@ -658,7 +658,7 @@ static int esdhc_init(struct mmc *mmc)
>  #endif
>
>         /* Set the initial clock speed */
> -       mmc_set_clock(mmc, 400000);
> +       mmc_set_clock(mmc, 400000, false);
>
>         /* Disable the BRR and BWR bits in IRQSTAT */
>         esdhc_clrbits32(&regs->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR);
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 032260b..70b7d19 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -1216,7 +1216,7 @@ static int mmc_set_ios(struct mmc *mmc)
>  }
>  #endif
>
> -int mmc_set_clock(struct mmc *mmc, uint clock)
> +int mmc_set_clock(struct mmc *mmc, uint clock, u8 disable)
>  {
>         if (clock > mmc->cfg->f_max)
>                 clock = mmc->cfg->f_max;
> @@ -1225,6 +1225,7 @@ int mmc_set_clock(struct mmc *mmc, uint clock)
>                 clock = mmc->cfg->f_min;
>
>         mmc->clock = clock;
> +       mmc->clk_disable = disable;
>
>         return mmc_set_ios(mmc);
>  }
> @@ -1316,7 +1317,7 @@ static int sd_select_mode_and_width(struct mmc *mmc)
>
>                                 /* configure the bus mode (host) */
>                                 mmc_select_mode(mmc, mwt->mode);
> -                               mmc_set_clock(mmc, mmc->tran_speed);
> +                               mmc_set_clock(mmc, mmc->tran_speed, false);
>
>                                 err = sd_read_ssr(mmc);
>                                 if (!err)
> @@ -1327,7 +1328,7 @@ static int sd_select_mode_and_width(struct mmc *mmc)
>  error:
>                                 /* revert to a safer bus speed */
>                                 mmc_select_mode(mmc, SD_LEGACY);
> -                               mmc_set_clock(mmc, mmc->tran_speed);
> +                               mmc_set_clock(mmc, mmc->tran_speed, false);
>                         }
>                 }
>         }
> @@ -1465,7 +1466,7 @@ static int mmc_select_mode_and_width(struct mmc *mmc)
>
>                         /* configure the bus mode (host) */
>                         mmc_select_mode(mmc, mwt->mode);
> -                       mmc_set_clock(mmc, mmc->tran_speed);
> +                       mmc_set_clock(mmc, mmc->tran_speed, false);
>
>                         /* do a transfer to check the configuration */
>                         err = mmc_read_and_compare_ext_csd(mmc);
> @@ -1928,7 +1929,7 @@ static void mmc_set_initial_state(struct mmc *mmc)
>                 printf("failed to set signal voltage\n");
>
>         mmc_set_bus_width(mmc, 1);
> -       mmc_set_clock(mmc, 1);
> +       mmc_set_clock(mmc, 1, false);
>         mmc_select_mode(mmc, MMC_LEGACY);
>  }
>
> diff --git a/include/mmc.h b/include/mmc.h
> index 43d37a4..097a685 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -466,6 +466,7 @@ struct mmc {
>         void *priv;
>         uint has_init;
>         int high_capacity;
> +       u8 clk_disable;

bool? Also add comment.

>         uint bus_width;
>         uint clock;
>         uint signal_voltage;
> @@ -557,7 +558,7 @@ int mmc_unbind(struct udevice *dev);
>  int mmc_initialize(bd_t *bis);
>  int mmc_init(struct mmc *mmc);
>  int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
> -int mmc_set_clock(struct mmc *mmc, uint clock);
> +int mmc_set_clock(struct mmc *mmc, uint clock, u8 disable);

Function comment

>  struct mmc *find_mmc_device(int dev_num);
>  int mmc_set_dev(int dev_num);
>  void print_mmc_devices(char separator);
> --
> 1.9.1
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 16/22] mmc: disable the mmc clock during power off
  2017-05-12 18:16   ` [U-Boot] [PATCH 16/22] mmc: disable the mmc clock during power off Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  0 siblings, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> From: Kishon Vijay Abraham I <kishon@ti.com>
>
> There is no point in having the mmc clock enabled during
> power off. Disable the mmc clock. This is similar to how it's
> programmed in Linux Kernel.
>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> Signed-off-by: Vignesh R <vigneshr@ti.com>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 1 +
>  1 file changed, 1 insertion(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 06/22] mmc: Add a fonction to dump the mmc capabilities
  2017-05-12 18:16   ` [U-Boot] [PATCH 06/22] mmc: Add a fonction to dump the mmc capabilities Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  0 siblings, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> This adds a simple helper function to display information (bus width and
> mode) based on a capability mask. Useful for debug.
>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 17 +++++++++++++++++
>  include/mmc.h     |  1 +
>  2 files changed, 18 insertions(+)

subject: fonction typo

>
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 2e1cb0d..5d418c5 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -1133,6 +1133,23 @@ static void mmc_set_bus_width(struct mmc *mmc, uint width)
>         mmc_set_ios(mmc);
>  }
>
> +void mmc_dump_capabilities(const char *text, uint caps)
> +{
> +       enum bus_mode mode;
> +
> +       printf("%s: widths [", text);
> +       if (caps & MMC_MODE_8BIT)
> +               printf("8, ");
> +       if (caps & MMC_MODE_4BIT)
> +               printf("4, ");
> +       printf("1] modes [");
> +
> +       for (mode = MMC_LEGACY; mode < MMC_MODES_END; mode++)
> +               if (MMC_CAP(mode) & caps)
> +                       printf("%s, ", mmc_mode_name(mode));
> +       printf("\b\b]\n");
> +}
> +
>  static int sd_select_bus_freq_width(struct mmc *mmc)
>  {
>         int err;
> diff --git a/include/mmc.h b/include/mmc.h
> index 60a43b0..afda02d 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -422,6 +422,7 @@ enum bus_mode {
>  };
>
>  const char *mmc_mode_name(enum bus_mode mode);
> +void mmc_dump_capabilities(const char *text, uint caps);

Add function comment

>  /*
>   * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device
>   * with mmc_get_mmc_dev().
> --
> 1.9.1
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 08/22] cmd: mmc: display the mode name and current bus speed in the mmc info
  2017-05-12 18:16   ` [U-Boot] [PATCH 08/22] cmd: mmc: display the mode name and current bus speed in the mmc info Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  0 siblings, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> Display the mode name when the user execute 'mmc info'. Also instead of
> displaying tran_speed, display the actual bus speed.
>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  cmd/mmc.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 12/22] mmc: Enable signal voltage to be selected from mmc core
  2017-05-12 18:16   ` [U-Boot] [PATCH 12/22] mmc: Enable signal voltage to be selected from mmc core Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  2017-05-15 14:18       ` Jean-Jacques Hiblot
  2017-05-17 10:35       ` Kishon Vijay Abraham I
  0 siblings, 2 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

Hi Jen-Jacques,

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> From: Kishon Vijay Abraham I <kishon@ti.com>
>
> Add a new function *mmc_set_signal_voltage* in mmc core
> which can be used during mmc initialization to select the
> signal voltage. Platform driver should use the set_ios
> callback function to select the signal voltage.
>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 15 +++++++++++++++
>  include/mmc.h     |  5 +++++
>  2 files changed, 20 insertions(+)
>
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 2ae6f1c..10af81d 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -29,6 +29,7 @@ static const unsigned int sd_au_size[] = {
>         SZ_4M / 512,    SZ_8M / 512,            (SZ_8M + SZ_4M) / 512,
>         SZ_16M / 512,   (SZ_16M + SZ_8M) / 512, SZ_32M / 512,   SZ_64M / 512,
>  };
> +static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
>
>  #if CONFIG_IS_ENABLED(MMC_TINY)
>  static struct mmc mmc_static;
> @@ -1247,6 +1248,12 @@ struct mode_width_tuning {
>         uint widths;
>  };
>
> +static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
> +{
> +       mmc->signal_voltage = signal_voltage;
> +       return mmc_set_ios(mmc);
> +}
> +
>  static const struct mode_width_tuning sd_modes_by_pref[] = {
>         {
>                 .mode = SD_HS,
> @@ -1935,6 +1942,14 @@ int mmc_start_init(struct mmc *mmc)
>                 return err;
>  #endif
>         mmc->ddr_mode = 0;
> +
> +       /* First try to set 3.3V. If it fails set to 1.8V */
> +       err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
> +       if (err != 0)
> +               err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
> +       if (err != 0)
> +               printf("failed to set signal voltage\n");

Return error?

> +
>         mmc_set_bus_width(mmc, 1);
>         mmc_set_clock(mmc, 1);
>
> diff --git a/include/mmc.h b/include/mmc.h
> index 9f20eb4..89cb26c 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -266,6 +266,10 @@
>  #define ENHNCD_SUPPORT         (0x2)
>  #define PART_ENH_ATTRIB                (0x1f)
>
> +#define MMC_SIGNAL_VOLTAGE_330 1
> +#define MMC_SIGNAL_VOLTAGE_180 2
> +#define MMC_SIGNAL_VOLTAGE_120 3
> +
>  /* Maximum block size for MMC */
>  #define MMC_MAX_BLOCK_LEN      512
>
> @@ -452,6 +456,7 @@ struct mmc {
>         int high_capacity;
>         uint bus_width;
>         uint clock;
> +       uint signal_voltage;

Comment. What does this value mean? What units is it? Millivolts or
something else?

>         uint card_caps;
>         uint ocr;
>         uint dsr;
> --
> 1.9.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 14/22] mmc: add power cyle support in mmc core
  2017-05-12 18:16   ` [U-Boot] [PATCH 14/22] mmc: add power cyle support in mmc core Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  2017-05-15 15:50       ` Jean-Jacques Hiblot
  2017-05-25 12:35     ` Jaehoon Chung
  1 sibling, 1 reply; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

Hi,

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> mmc/sd specification requires vdd to be disabled for 1 ms
> and then enabled again during power cycle. Add a
> function in mmc core to perform power cycle and set
> the io signal to it's initial state.
>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 50 +++++++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 41 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index d40a22b..032260b 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -30,6 +30,7 @@ static const unsigned int sd_au_size[] = {
>         SZ_16M / 512,   (SZ_16M + SZ_8M) / 512, SZ_32M / 512,   SZ_64M / 512,
>  };
>  static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
> +static void mmc_power_cycle(struct mmc *mmc);
>
>  #if CONFIG_IS_ENABLED(MMC_TINY)
>  static struct mmc mmc_static;
> @@ -1915,6 +1916,45 @@ static int mmc_power_init(struct mmc *mmc)
>         return 0;
>  }
>
> +static void mmc_set_initial_state(struct mmc *mmc)

Function comment

> +{
> +       int err;
> +
> +       /* First try to set 3.3V. If it fails set to 1.8V */
> +       err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
> +       if (err != 0)
> +               err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
> +       if (err != 0)
> +               printf("failed to set signal voltage\n");
> +
> +       mmc_set_bus_width(mmc, 1);
> +       mmc_set_clock(mmc, 1);
> +       mmc_select_mode(mmc, MMC_LEGACY);
> +}
> +
> +static void mmc_power_up(struct mmc *mmc)
> +{
> +       mmc_set_initial_state(mmc);
> +       mmc_set_vdd(mmc, true);
> +       udelay(10000);

Eek. Please add a comment as to why

> +}
> +
> +static void mmc_power_off(struct mmc *mmc)
> +{
> +       mmc_set_vdd(mmc, false);
> +}
> +
> +static void mmc_power_cycle(struct mmc *mmc)
> +{
> +       mmc_power_off(mmc);
> +       /*
> +        * SD spec recommends at least 1ms of delay. Let's wait for 2ms
> +        * to be on the safer side.
> +        */
> +       udelay(2000);
> +       mmc_power_up(mmc);
> +}
> +
>  int mmc_start_init(struct mmc *mmc)
>  {
>         bool no_card;
> @@ -1952,16 +1992,8 @@ int mmc_start_init(struct mmc *mmc)
>                 return err;
>  #endif
>         mmc->ddr_mode = 0;
> -       mmc_set_vdd(mmc, true);
> -       /* First try to set 3.3V. If it fails set to 1.8V */
> -       err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
> -       if (err != 0)
> -               err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
> -       if (err != 0)
> -               printf("failed to set signal voltage\n");

Return error? Also please add some mmc: to your message.

>
> -       mmc_set_bus_width(mmc, 1);
> -       mmc_set_clock(mmc, 1);
> +       mmc_power_cycle(mmc);
>
>         /* Reset the Card */
>         err = mmc_go_idle(mmc);
> --
> 1.9.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 17/22] mmc: Add a execute_tuning() callback to the mmc operations.
  2017-05-12 18:16   ` [U-Boot] [PATCH 17/22] mmc: Add a execute_tuning() callback to the mmc operations Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  2017-05-25 12:37     ` Jaehoon Chung
  1 sibling, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

Hi,

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> Tuning is a mandatory step in the initialization of SDR104 and HS200 modes.
> This callback execute the tuning process.
>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc-uclass.c | 14 ++++++++++++++
>  drivers/mmc/mmc.c        |  5 +++++
>  include/mmc.h            | 12 ++++++++++++
>  3 files changed, 31 insertions(+)

This should only support boards which define CONFIG_DM_MMC and DM_MMC_OPS.

Please don't add to the legacy code.

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 18/22] mmc: add HS200 support in MMC core
  2017-05-12 18:16   ` [U-Boot] [PATCH 18/22] mmc: add HS200 support in MMC core Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  2017-05-25 12:42     ` Jaehoon Chung
  1 sibling, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> Add HS200 to the list of supported modes and introduce tuning in the MMC
> startup process.
>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 22 ++++++++++++++++++++--
>  include/mmc.h     | 17 +++++++++++++++++
>  2 files changed, 37 insertions(+), 2 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 19/22] mmc: Add a new callback function to check if the card is busy
  2017-05-12 18:16   ` [U-Boot] [PATCH 19/22] mmc: Add a new callback function to check if the card is busy Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  0 siblings, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> Add a new callback function *card_busy* which can be used to check if the
> card is busy. This is useful during UHS voltage switching to check if the
> switch was successful. Not all controllers may support this, so it's
> optional and when not provided the card is deemed ready.
>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc-uclass.c | 14 ++++++++++++++
>  drivers/mmc/mmc.c        | 10 ++++++++++
>  include/mmc.h            | 11 +++++++++++
>  3 files changed, 35 insertions(+)
>

Again please don't add to legacy code. There is enough of it already!

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 20/22] mmc: Add support for UHS modes
  2017-05-12 18:16   ` [U-Boot] [PATCH 20/22] mmc: Add support for UHS modes Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  2017-05-16 14:20     ` Jean-Jacques Hiblot
  2017-05-25 12:50     ` Jaehoon Chung
  2 siblings, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> Add UHS modes to the list of supported modes, get the UHS capabilites of
> the SDcard and implement the procedure to switch the voltage (UHS modes
> use 1v8 IO lines)
> During the voltage switch procedure, DAT0 is used by the card to signal
> when it's ready. The optional card_busy() callback can be used to get this
> information from the host driver.
>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++---
>  include/mmc.h     |  27 ++++++++-
>  2 files changed, 188 insertions(+), 8 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 21/22] mmc: Change mode when switching to a boot partition
  2017-05-12 18:16   ` [U-Boot] [PATCH 21/22] mmc: Change mode when switching to a boot partition Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  2017-05-25 12:53     ` Jaehoon Chung
  1 sibling, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> Boot partitions do not support HS200. Changing to a lower performance mode
> is required to access them.
> mmc_select_mode_and_width() and sd_select_mode_and_width() are modified to
> make it easier to call them outside of the initialization context.
>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 66 +++++++++++++++++++++++++++++++++++++++++--------------
>  include/mmc.h     |  1 +
>  2 files changed, 50 insertions(+), 17 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

Please comment best_mode.

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 22/22] mmc: Retry some MMC cmds on failure
  2017-05-12 18:16   ` [U-Boot] [PATCH 22/22] mmc: Retry some MMC cmds on failure Jean-Jacques Hiblot
@ 2017-05-15  3:28     ` Simon Glass
  2017-05-15 15:49       ` Jean-Jacques Hiblot
  0 siblings, 1 reply; 85+ messages in thread
From: Simon Glass @ 2017-05-15  3:28 UTC (permalink / raw)
  To: u-boot

On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> From: Vignesh R <vigneshr@ti.com>
>
> With certain SD cards like Kingston 8GB/16GB UHS card, it is seen that
> MMC_CMD_ALL_SEND_CID cmd fails on first attempt, but succeeds
> subsequently. Therefore, retry MMC_CMD_ALL_SEND_CID cmd at least thrice
> as done in Linux kernel.
> Similarly, it is seen that MMC_CMD_SET_BLOCKLEN may fail on first
> attempt, therefore retry this cmd five times as done in kernel.
>
> Signed-off-by: Vignesh R <vigneshr@ti.com>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 15 ++++++++++++---
>  1 file changed, 12 insertions(+), 3 deletions(-)
>

So sad to see this sort of thing.

Can we enable this via a quirk and a Kconfig? Could default to on, but
I'm not sure we want this code in regardless.

Reviewed-by: Simon Glass <sjg@chromium.org>


> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index c7dda64..49edf52 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -275,6 +275,8 @@ int mmc_send_status(struct mmc *mmc, int timeout)
>  int mmc_set_blocklen(struct mmc *mmc, int len)
>  {
>         struct mmc_cmd cmd;
> +       int retries = 5;
> +       int err;
>
>         if (mmc->ddr_mode)
>                 return 0;
> @@ -282,8 +284,13 @@ int mmc_set_blocklen(struct mmc *mmc, int len)
>         cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
>         cmd.resp_type = MMC_RSP_R1;
>         cmd.cmdarg = len;
> +       do {
> +               err = mmc_send_cmd(mmc, &cmd, NULL);
> +               if (!err)
> +                       break;
> +       } while (retries--);
>
> -       return mmc_send_cmd(mmc, &cmd, NULL);
> +       return err;
>  }
>
>  static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
> @@ -1867,6 +1874,7 @@ static int mmc_startup(struct mmc *mmc)
>         u64 cmult, csize;
>         struct mmc_cmd cmd;
>         struct blk_desc *bdesc;
> +       int retries = 3;
>
>  #ifdef CONFIG_MMC_SPI_CRC_ON
>         if (mmc_host_is_spi(mmc)) { /* enable CRC check for spi */
> @@ -1874,7 +1882,6 @@ static int mmc_startup(struct mmc *mmc)
>                 cmd.resp_type = MMC_RSP_R1;
>                 cmd.cmdarg = 1;
>                 err = mmc_send_cmd(mmc, &cmd, NULL);
> -
>                 if (err)
>                         return err;
>         }
> @@ -1886,7 +1893,9 @@ static int mmc_startup(struct mmc *mmc)
>         cmd.resp_type = MMC_RSP_R2;
>         cmd.cmdarg = 0;
>
> -       err = mmc_send_cmd(mmc, &cmd, NULL);
> +       do {
> +               err = mmc_send_cmd(mmc, &cmd, NULL);
> +       } while (err && retries-- > 0);
>
>         if (err)
>                 return err;
> --
> 1.9.1
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 05/22] mmc: introduces mmc modes.
  2017-05-15  3:28     ` Simon Glass
@ 2017-05-15 10:34       ` Jean-Jacques Hiblot
  0 siblings, 0 replies; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-15 10:34 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 15/05/2017 05:28, Simon Glass wrote:
> On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
>
> Subject: drop the period at the end
>
> Also I think 'mmc: Introduce MMC modes' is better (imperative tense)
>
>> no functionnal changes.
>> In order to add the support for the high speed SD and MMC modes, it is
>> useful to track this information.
>>
>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
>> ---
>>   drivers/mmc/mmc.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++-------
>>   include/mmc.h     | 34 ++++++++++++++++++++++++++++------
>>   2 files changed, 74 insertions(+), 13 deletions(-)
>>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> Also see below
>
>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>> index 344d760..2e1cb0d 100644
>> --- a/drivers/mmc/mmc.c
>> +++ b/drivers/mmc/mmc.c
>> @@ -149,6 +149,36 @@ void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd)
>>   }
>>   #endif
>>
>> +const char *mmc_mode_name(enum bus_mode mode)
>> +{
>> +       static const char *const names[] = {
>> +             [MMC_LEGACY]      = "MMC legacy",
>> +             [SD_LEGACY]       = "SD Legacy",
>> +             [MMC_HS]          = "MMC High Speed (26MHz)",
>> +             [SD_HS]           = "SD High Speed (50MHz)",
>> +             [UHS_SDR12]       = "UHS SDR12 (25MHz)",
>> +             [UHS_SDR25]       = "UHS SDR25 (50MHz)",
>> +             [UHS_SDR50]       = "UHS SDR50 (100MHz)",
>> +             [UHS_SDR104]      = "UHS SDR104 (208MHz)",
>> +             [UHS_DDR50]       = "UHS DDR50 (50MHz)",
>> +             [MMC_HS_52]       = "MMC High Speed (52MHz)",
>> +             [MMC_DDR_52]      = "MMC DDR52 (52MHz)",
>> +             [MMC_HS_200]      = "HS200 (200MHz)",
> Can we hide this behind a Kconfig so boards can turn it off to reduce
> code size in SPL?
I'll add a MMC_VERBOSE and SPL_MMC_VERBOSE options. And also enable it 
if DEBUG is defined
>
>> +       };
>> +
>> +       if (mode >= MMC_MODES_END)
>> +               return "Unknown mode";
>> +       else
>> +               return names[mode];
>> +}
>> +static int mmc_select_mode(struct mmc *mmc, enum bus_mode mode)
>> +{
>> +       mmc->selected_mode = mode;
>> +       debug("selecting mode %s (freq : %d MHz)\n", mmc_mode_name(mode),
>> +             mmc->tran_speed / 1000000);
>> +       return 0;
>> +}
>> +
>>   #ifndef CONFIG_DM_MMC_OPS
>>   int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
>>   {
>> @@ -1138,10 +1168,13 @@ static int sd_select_bus_freq_width(struct mmc *mmc)
>>          if (err)
>>                  return err;
>>
>> -       if (mmc->card_caps & MMC_MODE_HS)
>> +       if (mmc->card_caps & MMC_MODE_HS) {
>> +               mmc_select_mode(mmc, SD_HS);
>>                  mmc->tran_speed = 50000000;
>> -       else
>> +       } else {
>> +               mmc_select_mode(mmc, SD_LEGACY);
>>                  mmc->tran_speed = 25000000;
>> +       }
>>
>>          return 0;
>>   }
>> @@ -1255,11 +1288,15 @@ static int mmc_select_bus_freq_width(struct mmc *mmc)
>>          if (err)
>>                  return err;
>>
>> -       if (mmc->card_caps & MMC_MODE_HS) {
>> -               if (mmc->card_caps & MMC_MODE_HS_52MHz)
>> -                       mmc->tran_speed = 52000000;
>> +       if (mmc->card_caps & MMC_MODE_HS_52MHz) {
>> +               if (mmc->ddr_mode)
>> +                       mmc_select_mode(mmc, MMC_DDR_52);
>>                  else
>> -                       mmc->tran_speed = 26000000;
>> +                       mmc_select_mode(mmc, MMC_HS_52);
>> +               mmc->tran_speed = 52000000;
>> +       } else if (mmc->card_caps & MMC_MODE_HS) {
>> +               mmc_select_mode(mmc, MMC_HS);
>> +               mmc->tran_speed = 26000000;
>>          }
>>
>>          return err;
>> @@ -1529,7 +1566,9 @@ static int mmc_startup(struct mmc *mmc)
>>          freq = fbase[(cmd.response[0] & 0x7)];
>>          mult = multipliers[((cmd.response[0] >> 3) & 0xf)];
>>
>> -       mmc->tran_speed = freq * mult;
>> +       mmc->legacy_speed = freq * mult;
>> +       mmc->tran_speed = mmc->legacy_speed;
>> +       mmc_select_mode(mmc, MMC_LEGACY);
>>
>>          mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1);
>>          mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf);
>> diff --git a/include/mmc.h b/include/mmc.h
>> index 9af6b52..60a43b0 100644
>> --- a/include/mmc.h
>> +++ b/include/mmc.h
>> @@ -52,12 +52,15 @@
>>   #define MMC_VERSION_5_0                MAKE_MMC_VERSION(5, 0, 0)
>>   #define MMC_VERSION_5_1                MAKE_MMC_VERSION(5, 1, 0)
>>
>> -#define MMC_MODE_HS            (1 << 0)
>> -#define MMC_MODE_HS_52MHz      (1 << 1)
>> -#define MMC_MODE_4BIT          (1 << 2)
>> -#define MMC_MODE_8BIT          (1 << 3)
>> -#define MMC_MODE_SPI           (1 << 4)
>> -#define MMC_MODE_DDR_52MHz     (1 << 5)
>> +#define MMC_CAP(mode)          (1 << mode)
>> +#define MMC_MODE_HS            (MMC_CAP(MMC_HS) | MMC_CAP(SD_HS))
>> +#define MMC_MODE_HS_52MHz      MMC_CAP(MMC_HS_52)
>> +#define MMC_MODE_DDR_52MHz     MMC_CAP(MMC_DDR_52)
>> +
>> +#define MMC_MODE_8BIT          (1 << 30)
>> +#define MMC_MODE_4BIT          (1 << 29)
>> +#define MMC_MODE_SPI           (1 << 27)
>> +
>>
>>   #define SD_DATA_4BIT   0x00040000
>>
>> @@ -402,6 +405,23 @@ struct sd_ssr {
>>          unsigned int erase_offset;      /* In milliseconds */
>>   };
>>
>> +enum bus_mode {
>> +       MMC_LEGACY      = 0,
>> +       SD_LEGACY       = 1,
>> +       MMC_HS          = 2,
>> +       SD_HS           = 3,
>> +       UHS_SDR12       = 4,
>> +       UHS_SDR25       = 5,
>> +       UHS_SDR50       = 6,
>> +       UHS_SDR104      = 7,
>> +       UHS_DDR50       = 8,
>> +       MMC_HS_52       = 9,
>> +       MMC_DDR_52      = 10,
>> +       MMC_HS_200      = 11,
> Do you need to specify the values or would defaults be OK?
I assigned fixed values for debug purpose, I'll remove them.
>
>> +       MMC_MODES_END
>> +};
>> +
>> +const char *mmc_mode_name(enum bus_mode mode);
>>   /*
>>    * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device
>>    * with mmc_get_mmc_dev().
>> @@ -432,6 +452,7 @@ struct mmc {
>>          u8 wr_rel_set;
>>          char part_config;
>>          uint tran_speed;
>> +       uint legacy_speed;
> Please add comment. Should this be an enum?
No. The legacy speed is a value in Hz. It's computed from values 
provided by the card during the initialization process.
>
>>          uint read_bl_len;
>>          uint write_bl_len;
>>          uint erase_grp_size;    /* in 512-byte sectors */
>> @@ -455,6 +476,7 @@ struct mmc {
>>          struct udevice *dev;    /* Device for this MMC controller */
>>   #endif
>>          u8 *ext_csd;
>> +       enum bus_mode selected_mode;
>>   };
>>
>>   struct mmc_hwpart_conf {
>> --
>> 1.9.1
>>
> Regards,
> Simon
>
thanks for taking time to review this whole series.


Jean-Jacques

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 09/22] mmc: refactor SD startup to make it easier to support new modes
  2017-05-15  3:28     ` Simon Glass
@ 2017-05-15 10:49       ` Jean-Jacques Hiblot
  0 siblings, 0 replies; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-15 10:49 UTC (permalink / raw)
  To: u-boot



On 15/05/2017 05:28, Simon Glass wrote:
> On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
>> The SDcard startup process currently handles only 2 modes. To make it
>> easier to add support for more modes, let's make the process more generic
>> and use a list of the modes to try.
>> The major functional change is that when a mode fails we try the next one.
>> Not all modes are tried, only those supported by the card and the host.
>>
>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
>> ---
>>   drivers/mmc/mmc.c | 180 ++++++++++++++++++++++++++++++++++++++----------------
>>   include/mmc.h     |   1 +
>>   2 files changed, 128 insertions(+), 53 deletions(-)
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> Will you be using that foreach macro multiple times?
No. I defined it only for a matter of readability: to focus the the 
attention to the body of the loop, not the control of the loop.
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 12/22] mmc: Enable signal voltage to be selected from mmc core
  2017-05-15  3:28     ` Simon Glass
@ 2017-05-15 14:18       ` Jean-Jacques Hiblot
  2017-05-17  1:38         ` Simon Glass
  2017-05-17 10:35       ` Kishon Vijay Abraham I
  1 sibling, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-15 14:18 UTC (permalink / raw)
  To: u-boot



On 15/05/2017 05:28, Simon Glass wrote:
> Hi Jen-Jacques,
>
> On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
>> From: Kishon Vijay Abraham I <kishon@ti.com>
>>
>> Add a new function *mmc_set_signal_voltage* in mmc core
>> which can be used during mmc initialization to select the
>> signal voltage. Platform driver should use the set_ios
>> callback function to select the signal voltage.
>>
>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
>> ---
>>   drivers/mmc/mmc.c | 15 +++++++++++++++
>>   include/mmc.h     |  5 +++++
>>   2 files changed, 20 insertions(+)
>>
>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>> index 2ae6f1c..10af81d 100644
>> --- a/drivers/mmc/mmc.c
>> +++ b/drivers/mmc/mmc.c
>> @@ -29,6 +29,7 @@ static const unsigned int sd_au_size[] = {
>>          SZ_4M / 512,    SZ_8M / 512,            (SZ_8M + SZ_4M) / 512,
>>          SZ_16M / 512,   (SZ_16M + SZ_8M) / 512, SZ_32M / 512,   SZ_64M / 512,
>>   };
>> +static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
>>
>>   #if CONFIG_IS_ENABLED(MMC_TINY)
>>   static struct mmc mmc_static;
>> @@ -1247,6 +1248,12 @@ struct mode_width_tuning {
>>          uint widths;
>>   };
>>
>> +static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
>> +{
>> +       mmc->signal_voltage = signal_voltage;
>> +       return mmc_set_ios(mmc);
>> +}
>> +
>>   static const struct mode_width_tuning sd_modes_by_pref[] = {
>>          {
>>                  .mode = SD_HS,
>> @@ -1935,6 +1942,14 @@ int mmc_start_init(struct mmc *mmc)
>>                  return err;
>>   #endif
>>          mmc->ddr_mode = 0;
>> +
>> +       /* First try to set 3.3V. If it fails set to 1.8V */
>> +       err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
>> +       if (err != 0)
>> +               err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
>> +       if (err != 0)
>> +               printf("failed to set signal voltage\n");
> Return error?
Maybe we should. I don't know.
Setting signal voltage is optional (at least for most modes), some 
platforms don't support it. So I wouldn't exit on this kind of error. 
Those 2 calls to mmc_set_signal_voltage() are here merely to turn on 
regulators before doing the card init. If setting voltage is required 
and fails, the init process won't go very far.

>> +
>>          mmc_set_bus_width(mmc, 1);
>>          mmc_set_clock(mmc, 1);
>>
>> diff --git a/include/mmc.h b/include/mmc.h
>> index 9f20eb4..89cb26c 100644
>> --- a/include/mmc.h
>> +++ b/include/mmc.h
>> @@ -266,6 +266,10 @@
>>   #define ENHNCD_SUPPORT         (0x2)
>>   #define PART_ENH_ATTRIB                (0x1f)
>>
>> +#define MMC_SIGNAL_VOLTAGE_330 1
>> +#define MMC_SIGNAL_VOLTAGE_180 2
>> +#define MMC_SIGNAL_VOLTAGE_120 3
>> +
>>   /* Maximum block size for MMC */
>>   #define MMC_MAX_BLOCK_LEN      512
>>
>> @@ -452,6 +456,7 @@ struct mmc {
>>          int high_capacity;
>>          uint bus_width;
>>          uint clock;
>> +       uint signal_voltage;
> Comment. What does this value mean? What units is it? Millivolts or
> something else?
it's more an enum than a value with a physical meaning (like mV). I'll 
change this in the next version to be a real enum.
>
>>          uint card_caps;
>>          uint ocr;
>>          uint dsr;
>> --
>> 1.9.1
>>
> Regards,
> Simon
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 22/22] mmc: Retry some MMC cmds on failure
  2017-05-15  3:28     ` Simon Glass
@ 2017-05-15 15:49       ` Jean-Jacques Hiblot
  2017-05-17  1:38         ` Simon Glass
  0 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-15 15:49 UTC (permalink / raw)
  To: u-boot



On 15/05/2017 05:28, Simon Glass wrote:
> On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
>> From: Vignesh R <vigneshr@ti.com>
>>
>> With certain SD cards like Kingston 8GB/16GB UHS card, it is seen that
>> MMC_CMD_ALL_SEND_CID cmd fails on first attempt, but succeeds
>> subsequently. Therefore, retry MMC_CMD_ALL_SEND_CID cmd at least thrice
>> as done in Linux kernel.
>> Similarly, it is seen that MMC_CMD_SET_BLOCKLEN may fail on first
>> attempt, therefore retry this cmd five times as done in kernel.
>>
>> Signed-off-by: Vignesh R <vigneshr@ti.com>
>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
>> ---
>>   drivers/mmc/mmc.c | 15 ++++++++++++---
>>   1 file changed, 12 insertions(+), 3 deletions(-)
>>
> So sad to see this sort of thing.
>
> Can we enable this via a quirk and a Kconfig? Could default to on, but
> I'm not sure we want this code in regardless.
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
I admit that it's ugly...  no clean code survives contact with a few 
hundred different hardware parts.
We could add KConfig options to enable/disable those quirks but I don't 
see the point of being able to. It's just a basic retry that has no 
impact on things that work well already and might make other work more 
reliably.

>
>
>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>> index c7dda64..49edf52 100644
>> --- a/drivers/mmc/mmc.c
>> +++ b/drivers/mmc/mmc.c
>> @@ -275,6 +275,8 @@ int mmc_send_status(struct mmc *mmc, int timeout)
>>   int mmc_set_blocklen(struct mmc *mmc, int len)
>>   {
>>          struct mmc_cmd cmd;
>> +       int retries = 5;
>> +       int err;
>>
>>          if (mmc->ddr_mode)
>>                  return 0;
>> @@ -282,8 +284,13 @@ int mmc_set_blocklen(struct mmc *mmc, int len)
>>          cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
>>          cmd.resp_type = MMC_RSP_R1;
>>          cmd.cmdarg = len;
>> +       do {
>> +               err = mmc_send_cmd(mmc, &cmd, NULL);
>> +               if (!err)
>> +                       break;
>> +       } while (retries--);
>>
>> -       return mmc_send_cmd(mmc, &cmd, NULL);
>> +       return err;
>>   }
>>
>>   static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
>> @@ -1867,6 +1874,7 @@ static int mmc_startup(struct mmc *mmc)
>>          u64 cmult, csize;
>>          struct mmc_cmd cmd;
>>          struct blk_desc *bdesc;
>> +       int retries = 3;
>>
>>   #ifdef CONFIG_MMC_SPI_CRC_ON
>>          if (mmc_host_is_spi(mmc)) { /* enable CRC check for spi */
>> @@ -1874,7 +1882,6 @@ static int mmc_startup(struct mmc *mmc)
>>                  cmd.resp_type = MMC_RSP_R1;
>>                  cmd.cmdarg = 1;
>>                  err = mmc_send_cmd(mmc, &cmd, NULL);
>> -
>>                  if (err)
>>                          return err;
>>          }
>> @@ -1886,7 +1893,9 @@ static int mmc_startup(struct mmc *mmc)
>>          cmd.resp_type = MMC_RSP_R2;
>>          cmd.cmdarg = 0;
>>
>> -       err = mmc_send_cmd(mmc, &cmd, NULL);
>> +       do {
>> +               err = mmc_send_cmd(mmc, &cmd, NULL);
>> +       } while (err && retries-- > 0);
>>
>>          if (err)
>>                  return err;
>> --
>> 1.9.1
>>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 14/22] mmc: add power cyle support in mmc core
  2017-05-15  3:28     ` Simon Glass
@ 2017-05-15 15:50       ` Jean-Jacques Hiblot
  0 siblings, 0 replies; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-15 15:50 UTC (permalink / raw)
  To: u-boot



On 15/05/2017 05:28, Simon Glass wrote:
> Hi,
>
> On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
>> mmc/sd specification requires vdd to be disabled for 1 ms
>> and then enabled again during power cycle. Add a
>> function in mmc core to perform power cycle and set
>> the io signal to it's initial state.
>>
>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
>> ---
>>   drivers/mmc/mmc.c | 50 +++++++++++++++++++++++++++++++++++++++++---------
>>   1 file changed, 41 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>> index d40a22b..032260b 100644
>> --- a/drivers/mmc/mmc.c
>> +++ b/drivers/mmc/mmc.c
>> @@ -30,6 +30,7 @@ static const unsigned int sd_au_size[] = {
>>          SZ_16M / 512,   (SZ_16M + SZ_8M) / 512, SZ_32M / 512,   SZ_64M / 512,
>>   };
>>   static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
>> +static void mmc_power_cycle(struct mmc *mmc);
>>
>>   #if CONFIG_IS_ENABLED(MMC_TINY)
>>   static struct mmc mmc_static;
>> @@ -1915,6 +1916,45 @@ static int mmc_power_init(struct mmc *mmc)
>>          return 0;
>>   }
>>
>> +static void mmc_set_initial_state(struct mmc *mmc)
> Function comment
OK
>
>> +{
>> +       int err;
>> +
>> +       /* First try to set 3.3V. If it fails set to 1.8V */
>> +       err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
>> +       if (err != 0)
>> +               err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
>> +       if (err != 0)
>> +               printf("failed to set signal voltage\n");
>> +
>> +       mmc_set_bus_width(mmc, 1);
>> +       mmc_set_clock(mmc, 1);
>> +       mmc_select_mode(mmc, MMC_LEGACY);
>> +}
>> +
>> +static void mmc_power_up(struct mmc *mmc)
>> +{
>> +       mmc_set_initial_state(mmc);
>> +       mmc_set_vdd(mmc, true);
>> +       udelay(10000);
> Eek. Please add a comment as to why
This is to let the Vdd time to settle. I'll remove this for the next 
version. If a delay is required by the platform it can be handled by the 
host driver.
>
>> +}
>> +
>> +static void mmc_power_off(struct mmc *mmc)
>> +{
>> +       mmc_set_vdd(mmc, false);
>> +}
>> +
>> +static void mmc_power_cycle(struct mmc *mmc)
>> +{
>> +       mmc_power_off(mmc);
>> +       /*
>> +        * SD spec recommends at least 1ms of delay. Let's wait for 2ms
>> +        * to be on the safer side.
>> +        */
>> +       udelay(2000);
>> +       mmc_power_up(mmc);
>> +}
>> +
>>   int mmc_start_init(struct mmc *mmc)
>>   {
>>          bool no_card;
>> @@ -1952,16 +1992,8 @@ int mmc_start_init(struct mmc *mmc)
>>                  return err;
>>   #endif
>>          mmc->ddr_mode = 0;
>> -       mmc_set_vdd(mmc, true);
>> -       /* First try to set 3.3V. If it fails set to 1.8V */
>> -       err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
>> -       if (err != 0)
>> -               err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
>> -       if (err != 0)
>> -               printf("failed to set signal voltage\n");
> Return error? Also please add some mmc: to your message.
>
>> -       mmc_set_bus_width(mmc, 1);
>> -       mmc_set_clock(mmc, 1);
>> +       mmc_power_cycle(mmc);
>>
>>          /* Reset the Card */
>>          err = mmc_go_idle(mmc);
>> --
>> 1.9.1
>>
> Regards,
> Simon
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 20/22] mmc: Add support for UHS modes
  2017-05-12 18:16   ` [U-Boot] [PATCH 20/22] mmc: Add support for UHS modes Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
@ 2017-05-16 14:20     ` Jean-Jacques Hiblot
  2017-05-17  1:59       ` Jaehoon Chung
  2017-05-25 12:50     ` Jaehoon Chung
  2 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-16 14:20 UTC (permalink / raw)
  To: u-boot



On 12/05/2017 20:16, Jean-Jacques Hiblot wrote:
> Add UHS modes to the list of supported modes, get the UHS capabilites of
> the SDcard and implement the procedure to switch the voltage (UHS modes
> use 1v8 IO lines)
> During the voltage switch procedure, DAT0 is used by the card to signal
> when it's ready. The optional card_busy() callback can be used to get this
> information from the host driver.
>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>   drivers/mmc/mmc.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++---
>   include/mmc.h     |  27 ++++++++-
>   2 files changed, 188 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index f6509f1..074d286 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -31,6 +31,7 @@ static const unsigned int sd_au_size[] = {
>   };
>   static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
>   static void mmc_power_cycle(struct mmc *mmc);
> +static int mmc_card_busy(struct mmc *mmc);
>   
>   #if CONFIG_IS_ENABLED(MMC_TINY)
>   static struct mmc mmc_static;
> @@ -403,7 +404,68 @@ static int mmc_go_idle(struct mmc *mmc)
>   	return 0;
>   }
>   
> -static int sd_send_op_cond(struct mmc *mmc)
> +static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage)
> +{
> +	struct mmc_cmd cmd;
> +	int err = 0;
> +
> +	/*
> +	 * Send CMD11 only if the request is to switch the card to
> +	 * 1.8V signalling.
> +	 */
> +	if (signal_voltage == MMC_SIGNAL_VOLTAGE_330)
> +		return mmc_set_signal_voltage(mmc, signal_voltage);
> +
> +	cmd.cmdidx = SD_CMD_SWITCH_UHS18V;
> +	cmd.cmdarg = 0;
> +	cmd.resp_type = MMC_RSP_R1;
> +
> +	err = mmc_send_cmd(mmc, &cmd, NULL);
> +	if (err)
> +		goto fail;
> +
> +	if (!mmc_host_is_spi(host) && (cmd.response[0] & MMC_STATUS_ERROR))
> +		goto fail;
> +
> +	/*
> +	 * The card should drive cmd and dat[0:3] low immediately
> +	 * after the response of cmd11, but wait 1 ms to be sure
> +	 */
> +	udelay(1000);
> +	if (mmc_card_busy(mmc))
Hi all,

there is an error her that I let through while cleaning the code before 
posting.
The line above should be:  if (!mmc_card_busy(mmc)).
I'll fix this in the v2.

Jaehoon, if you're testing the patches you might want to fix this first 
(you can just remove the calls to mmc_card_busy() for the moment). I 
hope it did not impede you.

Jean-Jacques
> +		goto fail;
> +
> +	/*
> +	 * During a signal voltage level switch, the clock must be gated
> +	 * for 5 ms according to the SD spec
> +	 */
> +	mmc_set_clock(mmc, mmc->clock, true);
> +
> +	err = mmc_set_signal_voltage(mmc, signal_voltage);
> +	if (err)
> +		goto fail;
> +
> +	/* Keep clock gated for at least 10 ms, though spec only says 5 ms */
> +	udelay(10000);
> +	mmc_set_clock(mmc, mmc->clock, false);
> +
> +	/* Wait for at least 1 ms according to spec */
> +	udelay(1000);
> +
> +	/*
> +	 * Failure to switch is indicated by the card holding
> +	 * dat[0:3] low
> +	 */
> +	if (mmc_card_busy(mmc))
> +		goto fail;
> +
> +	return 0;
> +
> +fail:
> +	return -EIO;
> +}
> +
> +static int sd_send_op_cond(struct mmc *mmc, bool uhs_en)
>   {
>   	int timeout = 1000;
>   	int err;
> @@ -435,6 +497,9 @@ static int sd_send_op_cond(struct mmc *mmc)
>   		if (mmc->version == SD_VERSION_2)
>   			cmd.cmdarg |= OCR_HCS;
>   
> +		if (uhs_en)
> +			cmd.cmdarg |= OCR_S18R;
> +
>   		err = mmc_send_cmd(mmc, &cmd, NULL);
>   
>   		if (err)
> @@ -465,6 +530,13 @@ static int sd_send_op_cond(struct mmc *mmc)
>   
>   	mmc->ocr = cmd.response[0];
>   
> +	if (!(mmc_host_is_spi(mmc)) && (cmd.response[0] & 0x41000000)
> +	    == 0x41000000) {
> +		err = mmc_switch_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
> +		if (err)
> +			return err;
> +	}
> +
>   	mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
>   	mmc->rca = 0;
>   
> @@ -977,6 +1049,7 @@ static int sd_get_capabilities(struct mmc *mmc)
>   	ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);
>   	struct mmc_data data;
>   	int timeout;
> +	u32 sd3_bus_mode;
>   
>   	mmc->card_caps = MMC_MODE_1BIT;
>   
> @@ -1058,6 +1131,22 @@ retry_scr:
>   	if (__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED)
>   		mmc->card_caps |= MMC_CAP(SD_HS);
>   
> +	/* Version before 3.0 don't support UHS modes */
> +	if (mmc->version < SD_VERSION_3)
> +		return 0;
> +
> +	sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f;
> +	if (sd3_bus_mode & SD_MODE_UHS_SDR104)
> +		mmc->card_caps |= MMC_CAP(UHS_SDR104);
> +	if (sd3_bus_mode & SD_MODE_UHS_SDR50)
> +		mmc->card_caps |= MMC_CAP(UHS_SDR50);
> +	if (sd3_bus_mode & SD_MODE_UHS_SDR25)
> +		mmc->card_caps |= MMC_CAP(UHS_SDR25);
> +	if (sd3_bus_mode & SD_MODE_UHS_SDR12)
> +		mmc->card_caps |= MMC_CAP(UHS_SDR12);
> +	if (sd3_bus_mode & SD_MODE_UHS_DDR50)
> +		mmc->card_caps |= MMC_CAP(UHS_DDR50);
> +
>   	return 0;
>   }
>   
> @@ -1065,13 +1154,36 @@ static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode)
>   {
>   	int err;
>   	ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);
> +	int speed;
> +
> +	switch (mode) {
> +	case SD_LEGACY:
> +	case UHS_SDR12:
> +		speed = UHS_SDR12_BUS_SPEED;
> +		break;
> +	case SD_HS:
> +	case UHS_SDR25:
> +		speed = UHS_SDR25_BUS_SPEED;
> +		break;
> +	case UHS_SDR50:
> +		speed = UHS_SDR50_BUS_SPEED;
> +		break;
> +	case UHS_DDR50:
> +		speed = UHS_DDR50_BUS_SPEED;
> +		break;
> +	case UHS_SDR104:
> +		speed = UHS_SDR104_BUS_SPEED;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
>   
> -	err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status);
> +	err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, speed, (u8 *)switch_status);
>   
>   	if (err)
>   		return err;
>   
> -	if ((__be32_to_cpu(switch_status[4]) & 0x0f000000) != 0x01000000)
> +	if ((__be32_to_cpu(switch_status[4]) >> 24) != speed)
>   		return -ENOTSUPP;
>   
>   	return 0;
> @@ -1291,10 +1403,31 @@ static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
>   
>   static const struct mode_width_tuning sd_modes_by_pref[] = {
>   	{
> +		.mode = UHS_SDR104,
> +		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
> +		.tuning = MMC_SEND_TUNING_BLOCK
> +	},
> +	{
> +		.mode = UHS_SDR50,
> +		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
> +	},
> +	{
> +		.mode = UHS_DDR50,
> +		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
> +	},
> +	{
> +		.mode = UHS_SDR25,
> +		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
> +	},
> +	{
>   		.mode = SD_HS,
>   		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
>   	},
>   	{
> +		.mode = UHS_SDR12,
> +		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
> +	},
> +	{
>   		.mode = SD_LEGACY,
>   		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
>   	}
> @@ -1310,18 +1443,24 @@ static int sd_select_mode_and_width(struct mmc *mmc)
>   	int err;
>   	uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT};
>   	const struct mode_width_tuning *mwt;
> +	bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false;
> +	uint caps;
> +
>   
>   	err = sd_get_capabilities(mmc);
>   	if (err)
>   		return err;
>   	/* Restrict card's capabilities by what the host can do */
> -	mmc->card_caps &= (mmc->cfg->host_caps | MMC_MODE_1BIT);
> +	caps = mmc->card_caps & (mmc->cfg->host_caps | MMC_MODE_1BIT);
>   
> -	for_each_sd_mode_by_pref(mmc->card_caps, mwt) {
> +	if (!uhs_en)
> +		caps &= ~UHS_CAPS;
> +
> +	for_each_sd_mode_by_pref(caps, mwt) {
>   		uint *w;
>   
>   		for (w = widths; w < widths + ARRAY_SIZE(widths); w++) {
> -			if (*w & mmc->card_caps & mwt->widths) {
> +			if (*w & caps & mwt->widths) {
>   				debug("trying mode %s width %d (at %d MHz)\n",
>   				      mmc_mode_name(mwt->mode),
>   				      bus_width(*w),
> @@ -1342,6 +1481,16 @@ static int sd_select_mode_and_width(struct mmc *mmc)
>   				mmc_select_mode(mmc, mwt->mode);
>   				mmc_set_clock(mmc, mmc->tran_speed, false);
>   
> +				/* execute tuning if needed */
> +				if (mwt->tuning && !mmc_host_is_spi(mmc)) {
> +					err = mmc_execute_tuning(mmc,
> +								 mwt->tuning);
> +					if (err) {
> +						debug("tuning failed\n");
> +						goto error;
> +					}
> +				}
> +
>   				err = sd_read_ssr(mmc);
>   				if (!err)
>   					return 0;
> @@ -1993,6 +2142,7 @@ static void mmc_power_cycle(struct mmc *mmc)
>   int mmc_start_init(struct mmc *mmc)
>   {
>   	bool no_card;
> +	bool uhs_en = supports_uhs(mmc->cfg->host_caps);
>   	int err;
>   
>   	/* we pretend there's no card when init is NULL */
> @@ -2028,6 +2178,7 @@ int mmc_start_init(struct mmc *mmc)
>   #endif
>   	mmc->ddr_mode = 0;
>   
> +retry:
>   	mmc_power_cycle(mmc);
>   
>   	/* Reset the Card */
> @@ -2043,7 +2194,11 @@ int mmc_start_init(struct mmc *mmc)
>   	err = mmc_send_if_cond(mmc);
>   
>   	/* Now try to get the SD card's operating condition */
> -	err = sd_send_op_cond(mmc);
> +	err = sd_send_op_cond(mmc, uhs_en);
> +	if (err && uhs_en) {
> +		uhs_en = false;
> +		goto retry;
> +	}
>   
>   	/* If the command timed out, we check for an MMC card */
>   	if (err == -ETIMEDOUT) {
> diff --git a/include/mmc.h b/include/mmc.h
> index b42f686..775c47e 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -87,6 +87,7 @@
>   #define MMC_CMD_SET_BLOCKLEN		16
>   #define MMC_CMD_READ_SINGLE_BLOCK	17
>   #define MMC_CMD_READ_MULTIPLE_BLOCK	18
> +#define MMC_SEND_TUNING_BLOCK		19
>   #define MMC_SEND_TUNING_BLOCK_HS200	21
>   #define MMC_CMD_SET_BLOCK_COUNT         23
>   #define MMC_CMD_WRITE_SINGLE_BLOCK	24
> @@ -117,7 +118,8 @@
>   
>   static inline bool mmc_is_tuning_cmd(uint cmdidx)
>   {
> -	if (cmdidx == MMC_SEND_TUNING_BLOCK_HS200)
> +	if ((cmdidx == MMC_SEND_TUNING_BLOCK_HS200) ||
> +	    (cmdidx == MMC_SEND_TUNING_BLOCK))
>   		return true;
>   	return false;
>   }
> @@ -126,8 +128,22 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
>   #define SD_HIGHSPEED_BUSY	0x00020000
>   #define SD_HIGHSPEED_SUPPORTED	0x00020000
>   
> +#define UHS_SDR12_BUS_SPEED	0
> +#define HIGH_SPEED_BUS_SPEED	1
> +#define UHS_SDR25_BUS_SPEED	1
> +#define UHS_SDR50_BUS_SPEED	2
> +#define UHS_SDR104_BUS_SPEED	3
> +#define UHS_DDR50_BUS_SPEED	4
> +
> +#define SD_MODE_UHS_SDR12	(1 << UHS_SDR12_BUS_SPEED)
> +#define SD_MODE_UHS_SDR25	(1 << UHS_SDR25_BUS_SPEED)
> +#define SD_MODE_UHS_SDR50	(1 << UHS_SDR50_BUS_SPEED)
> +#define SD_MODE_UHS_SDR104	(1 << UHS_SDR104_BUS_SPEED)
> +#define SD_MODE_UHS_DDR50	(1 << UHS_DDR50_BUS_SPEED)
> +
>   #define OCR_BUSY		0x80000000
>   #define OCR_HCS			0x40000000
> +#define OCR_S18R		0x1000000
>   #define OCR_VOLTAGE_MASK	0x007FFF80
>   #define OCR_ACCESS_MODE		0x60000000
>   
> @@ -490,6 +506,15 @@ static inline bool mmc_is_mode_ddr(enum bus_mode mode)
>   		return false;
>   }
>   
> +#define UHS_CAPS (MMC_CAP(UHS_SDR12) | MMC_CAP(UHS_SDR25) | \
> +		  MMC_CAP(UHS_SDR50) | MMC_CAP(UHS_SDR104) | \
> +		  MMC_CAP(UHS_DDR50))
> +
> +static inline bool supports_uhs(uint caps)
> +{
> +	return (caps & UHS_CAPS) ? true : false;
> +}
> +
>   
>   /*
>    * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 12/22] mmc: Enable signal voltage to be selected from mmc core
  2017-05-15 14:18       ` Jean-Jacques Hiblot
@ 2017-05-17  1:38         ` Simon Glass
  0 siblings, 0 replies; 85+ messages in thread
From: Simon Glass @ 2017-05-17  1:38 UTC (permalink / raw)
  To: u-boot

Hi Jean-Jacques,

On 15 May 2017 at 08:18, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
>
>
> On 15/05/2017 05:28, Simon Glass wrote:
>>
>> Hi Jen-Jacques,
>>
>> On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
>>>
>>> From: Kishon Vijay Abraham I <kishon@ti.com>
>>>
>>> Add a new function *mmc_set_signal_voltage* in mmc core
>>> which can be used during mmc initialization to select the
>>> signal voltage. Platform driver should use the set_ios
>>> callback function to select the signal voltage.
>>>
>>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
>>> ---
>>>   drivers/mmc/mmc.c | 15 +++++++++++++++
>>>   include/mmc.h     |  5 +++++
>>>   2 files changed, 20 insertions(+)
>>>
>>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>>> index 2ae6f1c..10af81d 100644
>>> --- a/drivers/mmc/mmc.c
>>> +++ b/drivers/mmc/mmc.c
>>> @@ -29,6 +29,7 @@ static const unsigned int sd_au_size[] = {
>>>          SZ_4M / 512,    SZ_8M / 512,            (SZ_8M + SZ_4M) / 512,
>>>          SZ_16M / 512,   (SZ_16M + SZ_8M) / 512, SZ_32M / 512,   SZ_64M /
>>> 512,
>>>   };
>>> +static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
>>>
>>>   #if CONFIG_IS_ENABLED(MMC_TINY)
>>>   static struct mmc mmc_static;
>>> @@ -1247,6 +1248,12 @@ struct mode_width_tuning {
>>>          uint widths;
>>>   };
>>>
>>> +static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
>>> +{
>>> +       mmc->signal_voltage = signal_voltage;
>>> +       return mmc_set_ios(mmc);
>>> +}
>>> +
>>>   static const struct mode_width_tuning sd_modes_by_pref[] = {
>>>          {
>>>                  .mode = SD_HS,
>>> @@ -1935,6 +1942,14 @@ int mmc_start_init(struct mmc *mmc)
>>>                  return err;
>>>   #endif
>>>          mmc->ddr_mode = 0;
>>> +
>>> +       /* First try to set 3.3V. If it fails set to 1.8V */
>>> +       err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
>>> +       if (err != 0)
>>> +               err = mmc_set_signal_voltage(mmc,
>>> MMC_SIGNAL_VOLTAGE_180);
>>> +       if (err != 0)
>>> +               printf("failed to set signal voltage\n");
>>
>> Return error?
>
> Maybe we should. I don't know.
> Setting signal voltage is optional (at least for most modes), some platforms
> don't support it. So I wouldn't exit on this kind of error. Those 2 calls to
> mmc_set_signal_voltage() are here merely to turn on regulators before doing
> the card init. If setting voltage is required and fails, the init process
> won't go very far.

If there is no regulator, then how about checking the error return
value, and if it is -ENODEV, continue. But any other error, you exit.

>
>>> +
>>>          mmc_set_bus_width(mmc, 1);
>>>          mmc_set_clock(mmc, 1);
>>>
>>> diff --git a/include/mmc.h b/include/mmc.h
>>> index 9f20eb4..89cb26c 100644
>>> --- a/include/mmc.h
>>> +++ b/include/mmc.h
>>> @@ -266,6 +266,10 @@
>>>   #define ENHNCD_SUPPORT         (0x2)
>>>   #define PART_ENH_ATTRIB                (0x1f)
>>>
>>> +#define MMC_SIGNAL_VOLTAGE_330 1
>>> +#define MMC_SIGNAL_VOLTAGE_180 2
>>> +#define MMC_SIGNAL_VOLTAGE_120 3
>>> +
>>>   /* Maximum block size for MMC */
>>>   #define MMC_MAX_BLOCK_LEN      512
>>>
>>> @@ -452,6 +456,7 @@ struct mmc {
>>>          int high_capacity;
>>>          uint bus_width;
>>>          uint clock;
>>> +       uint signal_voltage;
>>
>> Comment. What does this value mean? What units is it? Millivolts or
>> something else?
>
> it's more an enum than a value with a physical meaning (like mV). I'll
> change this in the next version to be a real enum.
>
>>
>>>          uint card_caps;
>>>          uint ocr;
>>>          uint dsr;
>>> --
>>> 1.9.1
>>

Regards,
Simon

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 22/22] mmc: Retry some MMC cmds on failure
  2017-05-15 15:49       ` Jean-Jacques Hiblot
@ 2017-05-17  1:38         ` Simon Glass
  2017-05-17 14:47           ` Jean-Jacques Hiblot
  0 siblings, 1 reply; 85+ messages in thread
From: Simon Glass @ 2017-05-17  1:38 UTC (permalink / raw)
  To: u-boot

Hi Jean-Jacques,

On 15 May 2017 at 09:49, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
>
>
> On 15/05/2017 05:28, Simon Glass wrote:
>>
>> On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
>>>
>>> From: Vignesh R <vigneshr@ti.com>
>>>
>>> With certain SD cards like Kingston 8GB/16GB UHS card, it is seen that
>>> MMC_CMD_ALL_SEND_CID cmd fails on first attempt, but succeeds
>>> subsequently. Therefore, retry MMC_CMD_ALL_SEND_CID cmd at least thrice
>>> as done in Linux kernel.
>>> Similarly, it is seen that MMC_CMD_SET_BLOCKLEN may fail on first
>>> attempt, therefore retry this cmd five times as done in kernel.
>>>
>>> Signed-off-by: Vignesh R <vigneshr@ti.com>
>>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
>>> ---
>>>   drivers/mmc/mmc.c | 15 ++++++++++++---
>>>   1 file changed, 12 insertions(+), 3 deletions(-)
>>>
>> So sad to see this sort of thing.
>>
>> Can we enable this via a quirk and a Kconfig? Could default to on, but
>> I'm not sure we want this code in regardless.
>>
>> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> I admit that it's ugly...  no clean code survives contact with a few hundred
> different hardware parts.
> We could add KConfig options to enable/disable those quirks but I don't see
> the point of being able to. It's just a basic retry that has no impact on
> things that work well already and might make other work more reliably.

I'm OK with it being there. But I suggest it should be a quirk flag in
struct mmc. You can always have it enabled (by default), but that way
it becomes very clear that this is a work-around, since it can be
disabled at run-time.

Regards,
Simon

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 20/22] mmc: Add support for UHS modes
  2017-05-16 14:20     ` Jean-Jacques Hiblot
@ 2017-05-17  1:59       ` Jaehoon Chung
  0 siblings, 0 replies; 85+ messages in thread
From: Jaehoon Chung @ 2017-05-17  1:59 UTC (permalink / raw)
  To: u-boot

On 05/16/2017 11:20 PM, Jean-Jacques Hiblot wrote:
> 
> 
> On 12/05/2017 20:16, Jean-Jacques Hiblot wrote:
>> Add UHS modes to the list of supported modes, get the UHS capabilites of
>> the SDcard and implement the procedure to switch the voltage (UHS modes
>> use 1v8 IO lines)
>> During the voltage switch procedure, DAT0 is used by the card to signal
>> when it's ready. The optional card_busy() callback can be used to get this
>> information from the host driver.
>>
>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
>> ---
>>   drivers/mmc/mmc.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++---
>>   include/mmc.h     |  27 ++++++++-
>>   2 files changed, 188 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>> index f6509f1..074d286 100644
>> --- a/drivers/mmc/mmc.c
>> +++ b/drivers/mmc/mmc.c
>> @@ -31,6 +31,7 @@ static const unsigned int sd_au_size[] = {
>>   };
>>   static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
>>   static void mmc_power_cycle(struct mmc *mmc);
>> +static int mmc_card_busy(struct mmc *mmc);
>>     #if CONFIG_IS_ENABLED(MMC_TINY)
>>   static struct mmc mmc_static;
>> @@ -403,7 +404,68 @@ static int mmc_go_idle(struct mmc *mmc)
>>       return 0;
>>   }
>>   -static int sd_send_op_cond(struct mmc *mmc)
>> +static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage)
>> +{
>> +    struct mmc_cmd cmd;
>> +    int err = 0;
>> +
>> +    /*
>> +     * Send CMD11 only if the request is to switch the card to
>> +     * 1.8V signalling.
>> +     */
>> +    if (signal_voltage == MMC_SIGNAL_VOLTAGE_330)
>> +        return mmc_set_signal_voltage(mmc, signal_voltage);
>> +
>> +    cmd.cmdidx = SD_CMD_SWITCH_UHS18V;
>> +    cmd.cmdarg = 0;
>> +    cmd.resp_type = MMC_RSP_R1;
>> +
>> +    err = mmc_send_cmd(mmc, &cmd, NULL);
>> +    if (err)
>> +        goto fail;
>> +
>> +    if (!mmc_host_is_spi(host) && (cmd.response[0] & MMC_STATUS_ERROR))
>> +        goto fail;
>> +
>> +    /*
>> +     * The card should drive cmd and dat[0:3] low immediately
>> +     * after the response of cmd11, but wait 1 ms to be sure
>> +     */
>> +    udelay(1000);
>> +    if (mmc_card_busy(mmc))
> Hi all,
> 
> there is an error her that I let through while cleaning the code before posting.
> The line above should be:  if (!mmc_card_busy(mmc)).
> I'll fix this in the v2.
> 
> Jaehoon, if you're testing the patches you might want to fix this first (you can just remove the calls to mmc_card_busy() for the moment). I hope it did not impede you.

Thanks for noticing. :)

Best Regards,
Jaehoon Chung

> 
> Jean-Jacques
>> +        goto fail;
>> +
>> +    /*
>> +     * During a signal voltage level switch, the clock must be gated
>> +     * for 5 ms according to the SD spec
>> +     */
>> +    mmc_set_clock(mmc, mmc->clock, true);
>> +
>> +    err = mmc_set_signal_voltage(mmc, signal_voltage);
>> +    if (err)
>> +        goto fail;
>> +
>> +    /* Keep clock gated for at least 10 ms, though spec only says 5 ms */
>> +    udelay(10000);
>> +    mmc_set_clock(mmc, mmc->clock, false);
>> +
>> +    /* Wait for at least 1 ms according to spec */
>> +    udelay(1000);
>> +
>> +    /*
>> +     * Failure to switch is indicated by the card holding
>> +     * dat[0:3] low
>> +     */
>> +    if (mmc_card_busy(mmc))
>> +        goto fail;
>> +
>> +    return 0;
>> +
>> +fail:
>> +    return -EIO;
>> +}
>> +
>> +static int sd_send_op_cond(struct mmc *mmc, bool uhs_en)
>>   {
>>       int timeout = 1000;
>>       int err;
>> @@ -435,6 +497,9 @@ static int sd_send_op_cond(struct mmc *mmc)
>>           if (mmc->version == SD_VERSION_2)
>>               cmd.cmdarg |= OCR_HCS;
>>   +        if (uhs_en)
>> +            cmd.cmdarg |= OCR_S18R;
>> +
>>           err = mmc_send_cmd(mmc, &cmd, NULL);
>>             if (err)
>> @@ -465,6 +530,13 @@ static int sd_send_op_cond(struct mmc *mmc)
>>         mmc->ocr = cmd.response[0];
>>   +    if (!(mmc_host_is_spi(mmc)) && (cmd.response[0] & 0x41000000)
>> +        == 0x41000000) {
>> +        err = mmc_switch_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
>> +        if (err)
>> +            return err;
>> +    }
>> +
>>       mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
>>       mmc->rca = 0;
>>   @@ -977,6 +1049,7 @@ static int sd_get_capabilities(struct mmc *mmc)
>>       ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);
>>       struct mmc_data data;
>>       int timeout;
>> +    u32 sd3_bus_mode;
>>         mmc->card_caps = MMC_MODE_1BIT;
>>   @@ -1058,6 +1131,22 @@ retry_scr:
>>       if (__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED)
>>           mmc->card_caps |= MMC_CAP(SD_HS);
>>   +    /* Version before 3.0 don't support UHS modes */
>> +    if (mmc->version < SD_VERSION_3)
>> +        return 0;
>> +
>> +    sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f;
>> +    if (sd3_bus_mode & SD_MODE_UHS_SDR104)
>> +        mmc->card_caps |= MMC_CAP(UHS_SDR104);
>> +    if (sd3_bus_mode & SD_MODE_UHS_SDR50)
>> +        mmc->card_caps |= MMC_CAP(UHS_SDR50);
>> +    if (sd3_bus_mode & SD_MODE_UHS_SDR25)
>> +        mmc->card_caps |= MMC_CAP(UHS_SDR25);
>> +    if (sd3_bus_mode & SD_MODE_UHS_SDR12)
>> +        mmc->card_caps |= MMC_CAP(UHS_SDR12);
>> +    if (sd3_bus_mode & SD_MODE_UHS_DDR50)
>> +        mmc->card_caps |= MMC_CAP(UHS_DDR50);
>> +
>>       return 0;
>>   }
>>   @@ -1065,13 +1154,36 @@ static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode)
>>   {
>>       int err;
>>       ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);
>> +    int speed;
>> +
>> +    switch (mode) {
>> +    case SD_LEGACY:
>> +    case UHS_SDR12:
>> +        speed = UHS_SDR12_BUS_SPEED;
>> +        break;
>> +    case SD_HS:
>> +    case UHS_SDR25:
>> +        speed = UHS_SDR25_BUS_SPEED;
>> +        break;
>> +    case UHS_SDR50:
>> +        speed = UHS_SDR50_BUS_SPEED;
>> +        break;
>> +    case UHS_DDR50:
>> +        speed = UHS_DDR50_BUS_SPEED;
>> +        break;
>> +    case UHS_SDR104:
>> +        speed = UHS_SDR104_BUS_SPEED;
>> +        break;
>> +    default:
>> +        return -EINVAL;
>> +    }
>>   -    err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status);
>> +    err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, speed, (u8 *)switch_status);
>>         if (err)
>>           return err;
>>   -    if ((__be32_to_cpu(switch_status[4]) & 0x0f000000) != 0x01000000)
>> +    if ((__be32_to_cpu(switch_status[4]) >> 24) != speed)
>>           return -ENOTSUPP;
>>         return 0;
>> @@ -1291,10 +1403,31 @@ static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
>>     static const struct mode_width_tuning sd_modes_by_pref[] = {
>>       {
>> +        .mode = UHS_SDR104,
>> +        .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
>> +        .tuning = MMC_SEND_TUNING_BLOCK
>> +    },
>> +    {
>> +        .mode = UHS_SDR50,
>> +        .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
>> +    },
>> +    {
>> +        .mode = UHS_DDR50,
>> +        .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
>> +    },
>> +    {
>> +        .mode = UHS_SDR25,
>> +        .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
>> +    },
>> +    {
>>           .mode = SD_HS,
>>           .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
>>       },
>>       {
>> +        .mode = UHS_SDR12,
>> +        .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
>> +    },
>> +    {
>>           .mode = SD_LEGACY,
>>           .widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
>>       }
>> @@ -1310,18 +1443,24 @@ static int sd_select_mode_and_width(struct mmc *mmc)
>>       int err;
>>       uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT};
>>       const struct mode_width_tuning *mwt;
>> +    bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false;
>> +    uint caps;
>> +
>>         err = sd_get_capabilities(mmc);
>>       if (err)
>>           return err;
>>       /* Restrict card's capabilities by what the host can do */
>> -    mmc->card_caps &= (mmc->cfg->host_caps | MMC_MODE_1BIT);
>> +    caps = mmc->card_caps & (mmc->cfg->host_caps | MMC_MODE_1BIT);
>>   -    for_each_sd_mode_by_pref(mmc->card_caps, mwt) {
>> +    if (!uhs_en)
>> +        caps &= ~UHS_CAPS;
>> +
>> +    for_each_sd_mode_by_pref(caps, mwt) {
>>           uint *w;
>>             for (w = widths; w < widths + ARRAY_SIZE(widths); w++) {
>> -            if (*w & mmc->card_caps & mwt->widths) {
>> +            if (*w & caps & mwt->widths) {
>>                   debug("trying mode %s width %d (at %d MHz)\n",
>>                         mmc_mode_name(mwt->mode),
>>                         bus_width(*w),
>> @@ -1342,6 +1481,16 @@ static int sd_select_mode_and_width(struct mmc *mmc)
>>                   mmc_select_mode(mmc, mwt->mode);
>>                   mmc_set_clock(mmc, mmc->tran_speed, false);
>>   +                /* execute tuning if needed */
>> +                if (mwt->tuning && !mmc_host_is_spi(mmc)) {
>> +                    err = mmc_execute_tuning(mmc,
>> +                                 mwt->tuning);
>> +                    if (err) {
>> +                        debug("tuning failed\n");
>> +                        goto error;
>> +                    }
>> +                }
>> +
>>                   err = sd_read_ssr(mmc);
>>                   if (!err)
>>                       return 0;
>> @@ -1993,6 +2142,7 @@ static void mmc_power_cycle(struct mmc *mmc)
>>   int mmc_start_init(struct mmc *mmc)
>>   {
>>       bool no_card;
>> +    bool uhs_en = supports_uhs(mmc->cfg->host_caps);
>>       int err;
>>         /* we pretend there's no card when init is NULL */
>> @@ -2028,6 +2178,7 @@ int mmc_start_init(struct mmc *mmc)
>>   #endif
>>       mmc->ddr_mode = 0;
>>   +retry:
>>       mmc_power_cycle(mmc);
>>         /* Reset the Card */
>> @@ -2043,7 +2194,11 @@ int mmc_start_init(struct mmc *mmc)
>>       err = mmc_send_if_cond(mmc);
>>         /* Now try to get the SD card's operating condition */
>> -    err = sd_send_op_cond(mmc);
>> +    err = sd_send_op_cond(mmc, uhs_en);
>> +    if (err && uhs_en) {
>> +        uhs_en = false;
>> +        goto retry;
>> +    }
>>         /* If the command timed out, we check for an MMC card */
>>       if (err == -ETIMEDOUT) {
>> diff --git a/include/mmc.h b/include/mmc.h
>> index b42f686..775c47e 100644
>> --- a/include/mmc.h
>> +++ b/include/mmc.h
>> @@ -87,6 +87,7 @@
>>   #define MMC_CMD_SET_BLOCKLEN        16
>>   #define MMC_CMD_READ_SINGLE_BLOCK    17
>>   #define MMC_CMD_READ_MULTIPLE_BLOCK    18
>> +#define MMC_SEND_TUNING_BLOCK        19
>>   #define MMC_SEND_TUNING_BLOCK_HS200    21
>>   #define MMC_CMD_SET_BLOCK_COUNT         23
>>   #define MMC_CMD_WRITE_SINGLE_BLOCK    24
>> @@ -117,7 +118,8 @@
>>     static inline bool mmc_is_tuning_cmd(uint cmdidx)
>>   {
>> -    if (cmdidx == MMC_SEND_TUNING_BLOCK_HS200)
>> +    if ((cmdidx == MMC_SEND_TUNING_BLOCK_HS200) ||
>> +        (cmdidx == MMC_SEND_TUNING_BLOCK))
>>           return true;
>>       return false;
>>   }
>> @@ -126,8 +128,22 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
>>   #define SD_HIGHSPEED_BUSY    0x00020000
>>   #define SD_HIGHSPEED_SUPPORTED    0x00020000
>>   +#define UHS_SDR12_BUS_SPEED    0
>> +#define HIGH_SPEED_BUS_SPEED    1
>> +#define UHS_SDR25_BUS_SPEED    1
>> +#define UHS_SDR50_BUS_SPEED    2
>> +#define UHS_SDR104_BUS_SPEED    3
>> +#define UHS_DDR50_BUS_SPEED    4
>> +
>> +#define SD_MODE_UHS_SDR12    (1 << UHS_SDR12_BUS_SPEED)
>> +#define SD_MODE_UHS_SDR25    (1 << UHS_SDR25_BUS_SPEED)
>> +#define SD_MODE_UHS_SDR50    (1 << UHS_SDR50_BUS_SPEED)
>> +#define SD_MODE_UHS_SDR104    (1 << UHS_SDR104_BUS_SPEED)
>> +#define SD_MODE_UHS_DDR50    (1 << UHS_DDR50_BUS_SPEED)
>> +
>>   #define OCR_BUSY        0x80000000
>>   #define OCR_HCS            0x40000000
>> +#define OCR_S18R        0x1000000
>>   #define OCR_VOLTAGE_MASK    0x007FFF80
>>   #define OCR_ACCESS_MODE        0x60000000
>>   @@ -490,6 +506,15 @@ static inline bool mmc_is_mode_ddr(enum bus_mode mode)
>>           return false;
>>   }
>>   +#define UHS_CAPS (MMC_CAP(UHS_SDR12) | MMC_CAP(UHS_SDR25) | \
>> +          MMC_CAP(UHS_SDR50) | MMC_CAP(UHS_SDR104) | \
>> +          MMC_CAP(UHS_DDR50))
>> +
>> +static inline bool supports_uhs(uint caps)
>> +{
>> +    return (caps & UHS_CAPS) ? true : false;
>> +}
>> +
>>     /*
>>    * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device
> 
> 
> 
> 

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 12/22] mmc: Enable signal voltage to be selected from mmc core
  2017-05-15  3:28     ` Simon Glass
  2017-05-15 14:18       ` Jean-Jacques Hiblot
@ 2017-05-17 10:35       ` Kishon Vijay Abraham I
  1 sibling, 0 replies; 85+ messages in thread
From: Kishon Vijay Abraham I @ 2017-05-17 10:35 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Monday 15 May 2017 08:58 AM, Simon Glass wrote:
> Hi Jen-Jacques,
> 
> On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
>> From: Kishon Vijay Abraham I <kishon@ti.com>
>>
>> Add a new function *mmc_set_signal_voltage* in mmc core
>> which can be used during mmc initialization to select the
>> signal voltage. Platform driver should use the set_ios
>> callback function to select the signal voltage.
>>
>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
>> ---
>>  drivers/mmc/mmc.c | 15 +++++++++++++++
>>  include/mmc.h     |  5 +++++
>>  2 files changed, 20 insertions(+)
>>
>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>> index 2ae6f1c..10af81d 100644
>> --- a/drivers/mmc/mmc.c
>> +++ b/drivers/mmc/mmc.c
>> @@ -29,6 +29,7 @@ static const unsigned int sd_au_size[] = {
>>         SZ_4M / 512,    SZ_8M / 512,            (SZ_8M + SZ_4M) / 512,
>>         SZ_16M / 512,   (SZ_16M + SZ_8M) / 512, SZ_32M / 512,   SZ_64M / 512,
>>  };
>> +static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
>>
>>  #if CONFIG_IS_ENABLED(MMC_TINY)
>>  static struct mmc mmc_static;
>> @@ -1247,6 +1248,12 @@ struct mode_width_tuning {
>>         uint widths;
>>  };
>>
>> +static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
>> +{
>> +       mmc->signal_voltage = signal_voltage;
>> +       return mmc_set_ios(mmc);
>> +}
>> +
>>  static const struct mode_width_tuning sd_modes_by_pref[] = {
>>         {
>>                 .mode = SD_HS,
>> @@ -1935,6 +1942,14 @@ int mmc_start_init(struct mmc *mmc)
>>                 return err;
>>  #endif
>>         mmc->ddr_mode = 0;
>> +
>> +       /* First try to set 3.3V. If it fails set to 1.8V */
>> +       err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
>> +       if (err != 0)
>> +               err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
>> +       if (err != 0)
>> +               printf("failed to set signal voltage\n");
> 
> Return error?

Since other API's here like mmc_set_bus_width, mmc_set_clock wasn't returning
error, I didn't return error from mmc_set_signal_voltage too. Thought returning
error can be added as a separate patch later for all the APIs used here.

Thanks
Kishon

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 22/22] mmc: Retry some MMC cmds on failure
  2017-05-17  1:38         ` Simon Glass
@ 2017-05-17 14:47           ` Jean-Jacques Hiblot
  0 siblings, 0 replies; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-17 14:47 UTC (permalink / raw)
  To: u-boot



On 17/05/2017 03:38, Simon Glass wrote:
> Hi Jean-Jacques,
>
> On 15 May 2017 at 09:49, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
>>
>> On 15/05/2017 05:28, Simon Glass wrote:
>>> On 12 May 2017 at 12:16, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
>>>> From: Vignesh R <vigneshr@ti.com>
>>>>
>>>> With certain SD cards like Kingston 8GB/16GB UHS card, it is seen that
>>>> MMC_CMD_ALL_SEND_CID cmd fails on first attempt, but succeeds
>>>> subsequently. Therefore, retry MMC_CMD_ALL_SEND_CID cmd at least thrice
>>>> as done in Linux kernel.
>>>> Similarly, it is seen that MMC_CMD_SET_BLOCKLEN may fail on first
>>>> attempt, therefore retry this cmd five times as done in kernel.
>>>>
>>>> Signed-off-by: Vignesh R <vigneshr@ti.com>
>>>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>>>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
>>>> ---
>>>>    drivers/mmc/mmc.c | 15 ++++++++++++---
>>>>    1 file changed, 12 insertions(+), 3 deletions(-)
>>>>
>>> So sad to see this sort of thing.
>>>
>>> Can we enable this via a quirk and a Kconfig? Could default to on, but
>>> I'm not sure we want this code in regardless.
>>>
>>> Reviewed-by: Simon Glass <sjg@chromium.org>
>> I admit that it's ugly...  no clean code survives contact with a few hundred
>> different hardware parts.
>> We could add KConfig options to enable/disable those quirks but I don't see
>> the point of being able to. It's just a basic retry that has no impact on
>> things that work well already and might make other work more reliably.
> I'm OK with it being there. But I suggest it should be a quirk flag in
> struct mmc. You can always have it enabled (by default), but that way
> it becomes very clear that this is a work-around, since it can be
> disabled at run-time.
OK. It'll be in v2
>
> Regards,
> Simon
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (22 preceding siblings ...)
  2017-05-15  2:33   ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jaehoon Chung
@ 2017-05-18  4:27   ` Jaehoon Chung
  2017-05-23 15:24     ` Jean-Jacques Hiblot
  23 siblings, 1 reply; 85+ messages in thread
From: Jaehoon Chung @ 2017-05-18  4:27 UTC (permalink / raw)
  To: u-boot

Hi,

On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
> This series brings support for HS200 and UHS modes to the mmc core.
> It has been tested with the hsmmc driver on several platforms (DRA7,
> AM57x, AM437x, beaglebone black). Some modifications are required in
> the host driver to take advantage of this (voltage switching, tuning).
> The changes to the host driver will be posted a another series as this
> one is already long enough. 
> 
> The series starts with a small refactoring of th sd/mmc startup. The first 4 commits
> are mostly moving code around with little or no functionnal change.
> 
> Then the notion of "mode" is introduced. Until now, this information wasn't
> kept in struct mmc. Only the clock and a flag for ddr was kept. Later the mode
> information will be used to select the clock frequency, the ddr flag and the
> tuning procedure. It will be also be check against the host capabilities.
> 
> Then comes the big refactoring job in:
> "mmc: refactor MMC startup to make it easier to support new modes" and
> "mmc: refactor SD startup to make it easier to support new modes"
> Since the number of modes is increasing, it makes sense to try them in a more
> organized way. those commits use a list of supported modes and iterate through
> them to find the best working one. It also allows to switch more easilly from
> one mode to another (switching from HS200 to DDR52 to access boot partitions for example)
> 
> Then there are a couple of new callback added to:
> - enable/disable Vdd
> - check if the card is busy (used during UHS voltage switching)
> - select the IO voltage
> 
> Then Power cycle is added. Without power cycle, if a UHS card fails to enumerate in
> UHS mode, it can't fall back to high speed mode and card enumeration will fail.
> 
> And finally the last commits add the support for HS200 and UHS.
> I haven't been able to test the UHS SDR104 mode by lack of compatible sdcard.

After testing my targets, some boards don't work fine..So i'm checking this problem..

> 
> With this in place and the required changes in the HSMMC (including DAM), we observe significant
> improvements in the performances on a DRA7 evm:
> eMMC HS200: 130 MB/s
> eMMC DDR52: 80 MB/s
> sd   SDR50: 80 MB/s
> 
> cheers,
> 
> Jean-Jacques
> 
> 
> Jean-Jacques Hiblot (18):
>   mmc: split mmc_startup()
>   mmc: move the MMC startup for version above v4.0 in a separate
>     function
>   mmc: make ext_csd part of struct mmc
>   mmc: add a function to read and test the ext csd (mmc >= 4)
>   mmc: introduces mmc modes.
>   mmc: Add a fonction to dump the mmc capabilities
>   mmc: use mmc modes to select the correct bus speed
>   cmd: mmc: display the mode name and current bus speed in the mmc info
>   mmc: refactor SD startup to make it easier to support new modes
>   mmc: refactor MMC startup to make it easier to support new modes
>   mmc: make mmc_set_ios() return status
>   mmc: add power cyle support in mmc core
>   mmc: add a new mmc parameter to disable mmc clock
>   mmc: Add a execute_tuning() callback to the mmc operations.
>   mmc: add HS200 support in MMC core
>   mmc: Add a new callback function to check if the card is busy
>   mmc: Add support for UHS modes
>   mmc: Change mode when switching to a boot partition
> 
> Kishon Vijay Abraham I (3):
>   mmc: Enable signal voltage to be selected from mmc core
>   mmc: Add a new callback function to enable/disable vdd
>   mmc: disable the mmc clock during power off
> 
> Vignesh R (1):
>   mmc: Retry some MMC cmds on failure
> 
>  cmd/mmc.c                |    3 +-
>  drivers/mmc/fsl_esdhc.c  |    2 +-
>  drivers/mmc/mmc-uclass.c |   42 ++
>  drivers/mmc/mmc.c        | 1220 +++++++++++++++++++++++++++++++++-------------
>  include/mmc.h            |  138 +++++-
>  5 files changed, 1058 insertions(+), 347 deletions(-)
> 

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-05-18  4:27   ` Jaehoon Chung
@ 2017-05-23 15:24     ` Jean-Jacques Hiblot
  2017-05-25  7:41       ` Jaehoon Chung
  0 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-23 15:24 UTC (permalink / raw)
  To: u-boot

Hi,


On 18/05/2017 06:27, Jaehoon Chung wrote:
> Hi,
>
> On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
>> This series brings support for HS200 and UHS modes to the mmc core.
>> It has been tested with the hsmmc driver on several platforms (DRA7,
>> AM57x, AM437x, beaglebone black). Some modifications are required in
>> the host driver to take advantage of this (voltage switching, tuning).
>> The changes to the host driver will be posted a another series as this
>> one is already long enough.
>>
>> The series starts with a small refactoring of th sd/mmc startup. The first 4 commits
>> are mostly moving code around with little or no functionnal change.
>>
>> Then the notion of "mode" is introduced. Until now, this information wasn't
>> kept in struct mmc. Only the clock and a flag for ddr was kept. Later the mode
>> information will be used to select the clock frequency, the ddr flag and the
>> tuning procedure. It will be also be check against the host capabilities.
>>
>> Then comes the big refactoring job in:
>> "mmc: refactor MMC startup to make it easier to support new modes" and
>> "mmc: refactor SD startup to make it easier to support new modes"
>> Since the number of modes is increasing, it makes sense to try them in a more
>> organized way. those commits use a list of supported modes and iterate through
>> them to find the best working one. It also allows to switch more easilly from
>> one mode to another (switching from HS200 to DDR52 to access boot partitions for example)
>>
>> Then there are a couple of new callback added to:
>> - enable/disable Vdd
>> - check if the card is busy (used during UHS voltage switching)
>> - select the IO voltage
>>
>> Then Power cycle is added. Without power cycle, if a UHS card fails to enumerate in
>> UHS mode, it can't fall back to high speed mode and card enumeration will fail.
>>
>> And finally the last commits add the support for HS200 and UHS.
>> I haven't been able to test the UHS SDR104 mode by lack of compatible sdcard.
> After testing my targets, some boards don't work fine..So i'm checking this problem..
Jaehoon,

what kind of issues are you running into and on what platforms ?
So far, besides the items brought-up by the reviews, there are 2 issues 
that are in the pipe for the next version:
  * signal voltage selection is not done for the MMCs only for SDs.
  * I noticed a timing constraint in voltage selection for SDs that can 
be a problem when trying a UHS mode with some SDs (seen only with 
Sandisk Ultra  64Gb micro SD class I) :  the voltage must be switched 
quickly after the cmd SWITCH_UHS18V has been sent, making debug messages 
in that context a problem. With this SD I've been able to check that 
SDR104 is working.

Jean-Jacques
>
>> With this in place and the required changes in the HSMMC (including DAM), we observe significant
>> improvements in the performances on a DRA7 evm:
>> eMMC HS200: 130 MB/s
>> eMMC DDR52: 80 MB/s
>> sd   SDR50: 80 MB/s
>>
>> cheers,
>>
>> Jean-Jacques
>>
>>
>> Jean-Jacques Hiblot (18):
>>    mmc: split mmc_startup()
>>    mmc: move the MMC startup for version above v4.0 in a separate
>>      function
>>    mmc: make ext_csd part of struct mmc
>>    mmc: add a function to read and test the ext csd (mmc >= 4)
>>    mmc: introduces mmc modes.
>>    mmc: Add a fonction to dump the mmc capabilities
>>    mmc: use mmc modes to select the correct bus speed
>>    cmd: mmc: display the mode name and current bus speed in the mmc info
>>    mmc: refactor SD startup to make it easier to support new modes
>>    mmc: refactor MMC startup to make it easier to support new modes
>>    mmc: make mmc_set_ios() return status
>>    mmc: add power cyle support in mmc core
>>    mmc: add a new mmc parameter to disable mmc clock
>>    mmc: Add a execute_tuning() callback to the mmc operations.
>>    mmc: add HS200 support in MMC core
>>    mmc: Add a new callback function to check if the card is busy
>>    mmc: Add support for UHS modes
>>    mmc: Change mode when switching to a boot partition
>>
>> Kishon Vijay Abraham I (3):
>>    mmc: Enable signal voltage to be selected from mmc core
>>    mmc: Add a new callback function to enable/disable vdd
>>    mmc: disable the mmc clock during power off
>>
>> Vignesh R (1):
>>    mmc: Retry some MMC cmds on failure
>>
>>   cmd/mmc.c                |    3 +-
>>   drivers/mmc/fsl_esdhc.c  |    2 +-
>>   drivers/mmc/mmc-uclass.c |   42 ++
>>   drivers/mmc/mmc.c        | 1220 +++++++++++++++++++++++++++++++++-------------
>>   include/mmc.h            |  138 +++++-
>>   5 files changed, 1058 insertions(+), 347 deletions(-)
>>
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-05-23 15:24     ` Jean-Jacques Hiblot
@ 2017-05-25  7:41       ` Jaehoon Chung
  2017-05-25 14:42         ` Jean-Jacques Hiblot
                           ` (2 more replies)
  0 siblings, 3 replies; 85+ messages in thread
From: Jaehoon Chung @ 2017-05-25  7:41 UTC (permalink / raw)
  To: u-boot

Hi,

On 05/24/2017 12:24 AM, Jean-Jacques Hiblot wrote:
> Hi,
> 
> 
> On 18/05/2017 06:27, Jaehoon Chung wrote:
>> Hi,
>>
>> On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
>>> This series brings support for HS200 and UHS modes to the mmc core.
>>> It has been tested with the hsmmc driver on several platforms (DRA7,
>>> AM57x, AM437x, beaglebone black). Some modifications are required in
>>> the host driver to take advantage of this (voltage switching, tuning).
>>> The changes to the host driver will be posted a another series as this
>>> one is already long enough.
>>>
>>> The series starts with a small refactoring of th sd/mmc startup. The first 4 commits
>>> are mostly moving code around with little or no functionnal change.
>>>
>>> Then the notion of "mode" is introduced. Until now, this information wasn't
>>> kept in struct mmc. Only the clock and a flag for ddr was kept. Later the mode
>>> information will be used to select the clock frequency, the ddr flag and the
>>> tuning procedure. It will be also be check against the host capabilities.
>>>
>>> Then comes the big refactoring job in:
>>> "mmc: refactor MMC startup to make it easier to support new modes" and
>>> "mmc: refactor SD startup to make it easier to support new modes"
>>> Since the number of modes is increasing, it makes sense to try them in a more
>>> organized way. those commits use a list of supported modes and iterate through
>>> them to find the best working one. It also allows to switch more easilly from
>>> one mode to another (switching from HS200 to DDR52 to access boot partitions for example)
>>>
>>> Then there are a couple of new callback added to:
>>> - enable/disable Vdd
>>> - check if the card is busy (used during UHS voltage switching)
>>> - select the IO voltage
>>>
>>> Then Power cycle is added. Without power cycle, if a UHS card fails to enumerate in
>>> UHS mode, it can't fall back to high speed mode and card enumeration will fail.
>>>
>>> And finally the last commits add the support for HS200 and UHS.
>>> I haven't been able to test the UHS SDR104 mode by lack of compatible sdcard.
>> After testing my targets, some boards don't work fine..So i'm checking this problem..
> Jaehoon,
> 
> what kind of issues are you running into and on what platforms ?
> So far, besides the items brought-up by the reviews, there are 2 issues that are in the pipe for the next version:
>  * signal voltage selection is not done for the MMCs only for SDs.
>  * I noticed a timing constraint in voltage selection for SDs that can be a problem when trying a UHS mode with some SDs (seen only with Sandisk Ultra  64Gb micro SD class I) :  the voltage must be switched quickly after the cmd SWITCH_UHS18V has been sent, making debug messages in that context a problem. With this SD I've been able to check that SDR104 is working.

How about making the "testing-hs200-uhs" branch for this? It needs to test more..
I guess my target doesn't do the voltage change..i'm doing for ufs driver on u-boot in my local..
So i didn't see fully..today i have a free time..So i'm doing full review other thing..and about pending patches.

Thanks for waiting me.. :)

Best Regards,
Jaehoon Chung

> 
> Jean-Jacques
>>
>>> With this in place and the required changes in the HSMMC (including DAM), we observe significant
>>> improvements in the performances on a DRA7 evm:
>>> eMMC HS200: 130 MB/s
>>> eMMC DDR52: 80 MB/s
>>> sd   SDR50: 80 MB/s
>>>
>>> cheers,
>>>
>>> Jean-Jacques
>>>
>>>
>>> Jean-Jacques Hiblot (18):
>>>    mmc: split mmc_startup()
>>>    mmc: move the MMC startup for version above v4.0 in a separate
>>>      function
>>>    mmc: make ext_csd part of struct mmc
>>>    mmc: add a function to read and test the ext csd (mmc >= 4)
>>>    mmc: introduces mmc modes.
>>>    mmc: Add a fonction to dump the mmc capabilities
>>>    mmc: use mmc modes to select the correct bus speed
>>>    cmd: mmc: display the mode name and current bus speed in the mmc info
>>>    mmc: refactor SD startup to make it easier to support new modes
>>>    mmc: refactor MMC startup to make it easier to support new modes
>>>    mmc: make mmc_set_ios() return status
>>>    mmc: add power cyle support in mmc core
>>>    mmc: add a new mmc parameter to disable mmc clock
>>>    mmc: Add a execute_tuning() callback to the mmc operations.
>>>    mmc: add HS200 support in MMC core
>>>    mmc: Add a new callback function to check if the card is busy
>>>    mmc: Add support for UHS modes
>>>    mmc: Change mode when switching to a boot partition
>>>
>>> Kishon Vijay Abraham I (3):
>>>    mmc: Enable signal voltage to be selected from mmc core
>>>    mmc: Add a new callback function to enable/disable vdd
>>>    mmc: disable the mmc clock during power off
>>>
>>> Vignesh R (1):
>>>    mmc: Retry some MMC cmds on failure
>>>
>>>   cmd/mmc.c                |    3 +-
>>>   drivers/mmc/fsl_esdhc.c  |    2 +-
>>>   drivers/mmc/mmc-uclass.c |   42 ++
>>>   drivers/mmc/mmc.c        | 1220 +++++++++++++++++++++++++++++++++-------------
>>>   include/mmc.h            |  138 +++++-
>>>   5 files changed, 1058 insertions(+), 347 deletions(-)
>>>
>>
> 
> 
> 
> 

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 10/22] mmc: refactor MMC startup to make it easier to support new modes
  2017-05-12 18:16   ` [U-Boot] [PATCH 10/22] mmc: refactor MMC " Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
@ 2017-05-25 12:25     ` Jaehoon Chung
  2017-05-25 14:40       ` Jean-Jacques Hiblot
  1 sibling, 1 reply; 85+ messages in thread
From: Jaehoon Chung @ 2017-05-25 12:25 UTC (permalink / raw)
  To: u-boot

On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
> The MMC startup process currently handles 4 modes. To make it easier to
> add support for more modes, let's make the process more generic and use a
> list of the modes to try.
> The major functional change is that when a mode fails we try the next one.
> Not all modes are tried, only those supported by the card and the host.
> 
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 238 +++++++++++++++++++++++++++++++++---------------------
>  include/mmc.h     |  15 +++-
>  2 files changed, 157 insertions(+), 96 deletions(-)
> 
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index f42a0fe..2931871 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -200,6 +200,7 @@ static int mmc_select_mode(struct mmc *mmc, enum bus_mode mode)
>  {
>  	mmc->selected_mode = mode;
>  	mmc->tran_speed = mmc_mode2freq(mmc, mode);
> +	mmc->ddr_mode = mmc_is_mode_ddr(mode);
>  	debug("selecting mode %s (freq : %d MHz)\n", mmc_mode_name(mode),
>  	      mmc->tran_speed / 1000000);
>  	return 0;
> @@ -602,11 +603,46 @@ int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
>  
>  }
>  
> -static int mmc_change_freq(struct mmc *mmc)
> +static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode)
>  {
> -	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
> -	char cardtype;
>  	int err;
> +	int speed_bits;
> +	ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
> +
> +	switch (mode) {
> +	case MMC_HS:
> +	case MMC_HS_52:
> +	case MMC_DDR_52:
> +		  speed_bits = EXT_CSD_TIMING_HS;
> +	case MMC_LEGACY:
> +		  speed_bits = EXT_CSD_TIMING_LEGACY;
> +		  break;
> +	default:
> +		  return -EINVAL;
> +	}
> +	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
> +			 speed_bits);
> +	if (err)
> +		return err;
> +
> +	if ((mode == MMC_HS) || (mode == MMC_HS_52)) {
> +		/* Now check to see that it worked */
> +		err = mmc_send_ext_csd(mmc, test_csd);
> +		if (err)
> +			return err;
> +
> +		/* No high-speed support */
> +		if (!test_csd[EXT_CSD_HS_TIMING])
> +			return -ENOTSUPP;
> +	}
> +
> +	return 0;
> +}
> +
> +static int mmc_get_capabilities(struct mmc *mmc)
> +{
> +	u8 *ext_csd = mmc->ext_csd;
> +	char cardtype;
>  
>  	mmc->card_caps = MMC_MODE_1BIT;
>  
> @@ -617,38 +653,23 @@ static int mmc_change_freq(struct mmc *mmc)
>  	if (mmc->version < MMC_VERSION_4)
>  		return 0;
>  
> -	mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
> -
> -	err = mmc_send_ext_csd(mmc, ext_csd);
> +	if (!ext_csd) {
> +		error("No ext_csd found!\n"); /* this should enver happen */
> +		return -ENOTSUPP;
> +	}
>  
> -	if (err)
> -		return err;
> +	mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
>  
>  	cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0xf;
>  
> -	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);
> -
> -	if (err)
> -		return err;
> -
> -	/* Now check to see that it worked */
> -	err = mmc_send_ext_csd(mmc, ext_csd);
> -
> -	if (err)
> -		return err;
> -
> -	/* No high-speed support */
> -	if (!ext_csd[EXT_CSD_HS_TIMING])
> -		return 0;
> -
>  	/* High Speed is set, there are two types: 52MHz and 26MHz */
>  	if (cardtype & EXT_CSD_CARD_TYPE_52) {
> -		if (cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V)
> +		if (cardtype & EXT_CSD_CARD_TYPE_DDR_52)
>  			mmc->card_caps |= MMC_MODE_DDR_52MHz;
> -		mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
> -	} else {
> -		mmc->card_caps |= MMC_MODE_HS;
> +		mmc->card_caps |= MMC_MODE_HS_52MHz;
>  	}
> +	if (cardtype & EXT_CSD_CARD_TYPE_26)
> +		mmc->card_caps |= MMC_MODE_HS;
>  
>  	return 0;
>  }
> @@ -1320,33 +1341,58 @@ static int mmc_read_and_compare_ext_csd(struct mmc *mmc)
>  }
>  
>  
> -static int mmc_select_bus_freq_width(struct mmc *mmc)
> +static const struct mode_width_tuning mmc_modes_by_pref[] = {
> +	{
> +		.mode = MMC_HS_200,
> +		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
> +	},
> +	{
> +		.mode = MMC_DDR_52,
> +		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
> +	},
> +	{
> +		.mode = MMC_HS_52,
> +		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
> +	},
> +	{
> +		.mode = MMC_HS,
> +		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
> +	},
> +	{
> +		.mode = MMC_LEGACY,
> +		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
> +	}
> +};
> +#define for_each_mmc_mode_by_pref(caps, mwt) \
> +	for (mwt = mmc_modes_by_pref;\
> +	    mwt < mmc_modes_by_pref + ARRAY_SIZE(mmc_modes_by_pref);\
> +	    mwt++) \
> +		if (caps & MMC_CAP(mwt->mode))
> +
> +static const struct ext_csd_bus_width {
> +	uint cap;
> +	bool is_ddr;
> +	uint ext_csd_bits;
> +} ext_csd_bus_width[] = {
> +	{MMC_MODE_8BIT, true, EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR},
> +	{MMC_MODE_4BIT, true, EXT_CSD_BUS_WIDTH_4 | EXT_CSD_DDR},
> +	{MMC_MODE_8BIT, false, EXT_CSD_BUS_WIDTH_8},
> +	{MMC_MODE_4BIT, false, EXT_CSD_BUS_WIDTH_4},
> +	{MMC_MODE_1BIT, false, EXT_CSD_BUS_WIDTH_1},
> +};
> +#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);\
> +	    ecbv++) \
> +		if ((ddr == ecbv->is_ddr) && (caps & ecbv->cap))
> +
> +static int mmc_select_mode_and_width(struct mmc *mmc)
>  {
> -	/* An array of possible bus widths in order of preference */
> -	static const unsigned ext_csd_bits[] = {
> -		EXT_CSD_DDR_BUS_WIDTH_8,
> -		EXT_CSD_DDR_BUS_WIDTH_4,
> -		EXT_CSD_BUS_WIDTH_8,
> -		EXT_CSD_BUS_WIDTH_4,
> -		EXT_CSD_BUS_WIDTH_1,
> -	};
> -	/* An array to map CSD bus widths to host cap bits */
> -	static const unsigned ext_to_hostcaps[] = {
> -		[EXT_CSD_DDR_BUS_WIDTH_4] =
> -			MMC_MODE_DDR_52MHz | MMC_MODE_4BIT,
> -		[EXT_CSD_DDR_BUS_WIDTH_8] =
> -			MMC_MODE_DDR_52MHz | MMC_MODE_8BIT,
> -		[EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT,
> -		[EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT,
> -	};
> -	/* An array to map chosen bus width to an integer */
> -	static const unsigned widths[] = {
> -		8, 4, 8, 4, 1,
> -	};
>  	int err;
> -	int idx;
> +	const struct mode_width_tuning *mwt;
> +	const struct ext_csd_bus_width *ecbw;
>  
> -	err = mmc_change_freq(mmc);
> +	err = mmc_get_capabilities(mmc);
>  	if (err)
>  		return err;
>  
> @@ -1357,60 +1403,64 @@ static int mmc_select_bus_freq_width(struct mmc *mmc)
>  	if (mmc->version < MMC_VERSION_4)
>  		return 0;
>  
> +
>  	if (!mmc->ext_csd) {
>  		error("No ext_csd found!\n"); /* this should enver happen */
>  		return -ENOTSUPP;
>  	}
>  
> -	for (idx = 0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
> -		unsigned int extw = ext_csd_bits[idx];
> -		unsigned int caps = ext_to_hostcaps[extw];
> +	for_each_mmc_mode_by_pref(mmc->card_caps, mwt) {
> +		for_each_supported_width(mmc->card_caps & mwt->widths,
> +					 mmc_is_mode_ddr(mwt->mode), ecbw) {
> +			debug("trying mode %s width %d (at %d MHz)\n",
> +			      mmc_mode_name(mwt->mode),
> +			      bus_width(ecbw->cap),
> +			      mmc_mode2freq(mmc, mwt->mode) / 1000000);
>  
> -		/*
> -		  * If the bus width is still not changed,
> -		  * don't try to set the default again.
> -		  * Otherwise, recover from switch attempts
> -		  * by switching to 1-bit bus width.
> -		  */
> -		if (extw == EXT_CSD_BUS_WIDTH_1 &&
> -		    mmc->bus_width == 1) {
> -			err = 0;
> -			break;
> -		}
> -
> -		/*
> -		  * Check to make sure the card and controller support
> -		  * these capabilities
> -		  */
> -		if ((mmc->card_caps & caps) != caps)
> -			continue;
> -
> -		err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
> -				EXT_CSD_BUS_WIDTH, extw);
> +			/* configure the bus width (card + host) */
> +			err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
> +				EXT_CSD_BUS_WIDTH,
> +				ecbw->ext_csd_bits & ~EXT_CSD_DDR);
> +			if (err)
> +				goto error;
> +			mmc_set_bus_width(mmc, bus_width(ecbw->cap));
>  
> -		if (err)
> -			continue;
> +			/* 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) {
> +				err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
> +					EXT_CSD_BUS_WIDTH, ecbw->ext_csd_bits);
> +				if (err)
> +					goto error;
> +			}
>  
> -		mmc->ddr_mode = (caps & MMC_MODE_DDR_52MHz) ? 1 : 0;
> -		mmc_set_bus_width(mmc, widths[idx]);
> +			/* configure the bus mode (host) */
> +			mmc_select_mode(mmc, mwt->mode);
> +			mmc_set_clock(mmc, mmc->tran_speed);
>  
> -		err = mmc_read_and_compare_ext_csd(mmc);
> -		if (!err)
> -			break;
> +			/* do a transfer to check the configuration */
> +			err = mmc_read_and_compare_ext_csd(mmc);
> +			if (!err)
> +				return 0;
> +error:
> +			/* if an error occured, revert to a safer bus mode */
> +			mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
> +				   EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_1);
> +			mmc_select_mode(mmc, MMC_LEGACY);
> +			mmc_set_bus_width(mmc, 1);
> +		}
>  	}
>  
> -	if (err)
> -		return err;
> -
> -	if (mmc->card_caps & MMC_MODE_HS_52MHz) {
> -		if (mmc->ddr_mode)
> -			mmc_select_mode(mmc, MMC_DDR_52);
> -		else
> -			mmc_select_mode(mmc, MMC_HS_52);
> -	} else if (mmc->card_caps & MMC_MODE_HS)
> -		mmc_select_mode(mmc, MMC_HS);
> +	error("unable to select a mode\n");
>  
> -	return err;
> +	return -ENOTSUPP;
>  }
>  
>  static int mmc_startup_v4(struct mmc *mmc)
> @@ -1747,7 +1797,7 @@ static int mmc_startup(struct mmc *mmc)
>  	if (IS_SD(mmc))
>  		err = sd_select_mode_and_width(mmc);
>  	else
> -		err = mmc_select_bus_freq_width(mmc);
> +		err = mmc_select_mode_and_width(mmc);
>  
>  	if (err)
>  		return err;
> diff --git a/include/mmc.h b/include/mmc.h
> index 1ffa7ec..3c6971d 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -213,9 +213,10 @@
>  #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 */
> -#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		4	/* Card is in DDR mode */

Why do you change to 4 as DDR mode?

>  
> +#define EXT_CSD_TIMING_LEGACY	0	/* no high speed */
> +#define EXT_CSD_TIMING_HS	1	/* HS */
>  #define EXT_CSD_BOOT_ACK_ENABLE			(1 << 6)
>  #define EXT_CSD_BOOT_PARTITION_ENABLE		(1 << 3)
>  #define EXT_CSD_PARTITION_ACCESS_ENABLE		(1 << 0)
> @@ -424,6 +425,16 @@ enum bus_mode {
>  
>  const char *mmc_mode_name(enum bus_mode mode);
>  void mmc_dump_capabilities(const char *text, uint caps);
> +
> +static inline bool mmc_is_mode_ddr(enum bus_mode mode)
> +{
> +	if ((mode == MMC_DDR_52) || (mode == UHS_DDR50))
> +		return true;
> +	else
> +		return false;
> +}
> +
> +
>  /*
>   * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device
>   * with mmc_get_mmc_dev().
> 

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 14/22] mmc: add power cyle support in mmc core
  2017-05-12 18:16   ` [U-Boot] [PATCH 14/22] mmc: add power cyle support in mmc core Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
@ 2017-05-25 12:35     ` Jaehoon Chung
  2017-05-25 14:50       ` Jean-Jacques Hiblot
  2017-06-15 16:13       ` Jean-Jacques Hiblot
  1 sibling, 2 replies; 85+ messages in thread
From: Jaehoon Chung @ 2017-05-25 12:35 UTC (permalink / raw)
  To: u-boot

On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
> mmc/sd specification requires vdd to be disabled for 1 ms
> and then enabled again during power cycle. Add a
> function in mmc core to perform power cycle and set
> the io signal to it's initial state.
> 
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 50 +++++++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 41 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index d40a22b..032260b 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -30,6 +30,7 @@ static const unsigned int sd_au_size[] = {
>  	SZ_16M / 512,	(SZ_16M + SZ_8M) / 512,	SZ_32M / 512,	SZ_64M / 512,
>  };
>  static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
> +static void mmc_power_cycle(struct mmc *mmc);
>  
>  #if CONFIG_IS_ENABLED(MMC_TINY)
>  static struct mmc mmc_static;
> @@ -1915,6 +1916,45 @@ static int mmc_power_init(struct mmc *mmc)
>  	return 0;
>  }
>  
> +static void mmc_set_initial_state(struct mmc *mmc)
> +{
> +	int err;
> +
> +	/* First try to set 3.3V. If it fails set to 1.8V */
> +	err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
> +	if (err != 0)
> +		err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
> +	if (err != 0)
> +		printf("failed to set signal voltage\n");
> +
> +	mmc_set_bus_width(mmc, 1);
> +	mmc_set_clock(mmc, 1);
> +	mmc_select_mode(mmc, MMC_LEGACY);
> +}
> +
> +static void mmc_power_up(struct mmc *mmc)
> +{
> +	mmc_set_initial_state(mmc);
> +	mmc_set_vdd(mmc, true);

mmc_set_vdd has the return value..but there are no usage anywhere..
if this is correct, mmc_set_vdd can be *void* type.

> +	udelay(10000);
> +}
> +
> +static void mmc_power_off(struct mmc *mmc)
> +{
> +	mmc_set_vdd(mmc, false);
> +}
> +
> +static void mmc_power_cycle(struct mmc *mmc)
> +{
> +	mmc_power_off(mmc);
> +	/*
> +	 * SD spec recommends at least 1ms of delay. Let's wait for 2ms
> +	 * to be on the safer side.
> +	 */

Could you put the SD spec version and about which part...?
I didn't find the 2ms so..i want to see the spec about 2ms.

> +	udelay(2000);
> +	mmc_power_up(mmc);
> +}
> +
>  int mmc_start_init(struct mmc *mmc)
>  {
>  	bool no_card;
> @@ -1952,16 +1992,8 @@ int mmc_start_init(struct mmc *mmc)
>  		return err;
>  #endif
>  	mmc->ddr_mode = 0;
> -	mmc_set_vdd(mmc, true);
> -	/* First try to set 3.3V. If it fails set to 1.8V */
> -	err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
> -	if (err != 0)
> -		err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
> -	if (err != 0)
> -		printf("failed to set signal voltage\n");
>  
> -	mmc_set_bus_width(mmc, 1);
> -	mmc_set_clock(mmc, 1);
> +	mmc_power_cycle(mmc);
>  
>  	/* Reset the Card */
>  	err = mmc_go_idle(mmc);
> 

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 17/22] mmc: Add a execute_tuning() callback to the mmc operations.
  2017-05-12 18:16   ` [U-Boot] [PATCH 17/22] mmc: Add a execute_tuning() callback to the mmc operations Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
@ 2017-05-25 12:37     ` Jaehoon Chung
  2017-05-25 14:51       ` Jean-Jacques Hiblot
  1 sibling, 1 reply; 85+ messages in thread
From: Jaehoon Chung @ 2017-05-25 12:37 UTC (permalink / raw)
  To: u-boot

On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
> Tuning is a mandatory step in the initialization of SDR104 and HS200 modes.
> This callback execute the tuning process.
> 
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc-uclass.c | 14 ++++++++++++++
>  drivers/mmc/mmc.c        |  5 +++++
>  include/mmc.h            | 12 ++++++++++++
>  3 files changed, 31 insertions(+)
> 
> diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
> index e1f7995..b7433cf 100644
> --- a/drivers/mmc/mmc-uclass.c
> +++ b/drivers/mmc/mmc-uclass.c
> @@ -93,6 +93,20 @@ int mmc_getcd(struct mmc *mmc)
>  {
>  	return dm_mmc_get_cd(mmc->dev);
>  }
> +
> +int dm_mmc_execute_tuning(struct udevice *dev, uint opcode)
> +{
> +	struct dm_mmc_ops *ops = mmc_get_ops(dev);
> +
> +	if (!ops->execute_tuning)
> +		return -ENOSYS;
> +	return ops->execute_tuning(dev, opcode);
> +}
> +
> +int mmc_execute_tuning(struct mmc *mmc, uint opcode)
> +{
> +	return dm_mmc_execute_tuning(mmc->dev, opcode);
> +}
>  #endif
>  
>  struct mmc *mmc_get_mmc_dev(struct udevice *dev)
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 415484e..d7d1c91 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -219,6 +219,11 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
>  
>  	return ret;
>  }
> +
> +int mmc_execute_tuning(struct mmc *mmc, uint opcode)
> +{
> +	return mmc->cfg->ops->execute_tuning(mmc, opcode);

Doesn't need to check about execute_tuing callback function?

> +}
>  #endif
>  
>  int mmc_send_status(struct mmc *mmc, int timeout)
> diff --git a/include/mmc.h b/include/mmc.h
> index 097a685..dab68c5 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -375,6 +375,15 @@ struct dm_mmc_ops {
>  	 * @return 0 if write-enabled, 1 if write-protected, -ve on error
>  	 */
>  	int (*get_wp)(struct udevice *dev);
> +
> +	/**
> +	 * execute_tuning() - Start the tuning process
> +	 *
> +	 * @dev:	Device to start the tuning
> +	 * @opcode:	Command opcode to send
> +	 * @return 0 if OK, -ve on error
> +	 */
> +	int (*execute_tuning)(struct udevice *dev, uint opcode);
>  };
>  
>  #define mmc_get_ops(dev)        ((struct dm_mmc_ops *)(dev)->driver->ops)
> @@ -385,12 +394,14 @@ int dm_mmc_set_ios(struct udevice *dev);
>  int dm_mmc_set_vdd(struct udevice *dev, bool enable);
>  int dm_mmc_get_cd(struct udevice *dev);
>  int dm_mmc_get_wp(struct udevice *dev);
> +int dm_mmc_execute_tuning(struct udevice *dev, uint opcode);
>  
>  /* Transition functions for compatibility */
>  int mmc_set_ios(struct mmc *mmc);
>  int mmc_set_vdd(struct mmc *mmc, bool enable);
>  int mmc_getcd(struct mmc *mmc);
>  int mmc_getwp(struct mmc *mmc);
> +int mmc_execute_tuning(struct mmc *mmc, uint opcode);
>  
>  #else
>  struct mmc_ops {
> @@ -401,6 +412,7 @@ struct mmc_ops {
>  	int (*set_vdd)(struct mmc *mmc, bool enable);
>  	int (*getcd)(struct mmc *mmc);
>  	int (*getwp)(struct mmc *mmc);
> +	int (*execute_tuning)(struct mmc *mmc, uint opcode);
>  };
>  #endif
>  
> 

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 18/22] mmc: add HS200 support in MMC core
  2017-05-12 18:16   ` [U-Boot] [PATCH 18/22] mmc: add HS200 support in MMC core Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
@ 2017-05-25 12:42     ` Jaehoon Chung
  1 sibling, 0 replies; 85+ messages in thread
From: Jaehoon Chung @ 2017-05-25 12:42 UTC (permalink / raw)
  To: u-boot

On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
> Add HS200 to the list of supported modes and introduce tuning in the MMC
> startup process.
> 
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 22 ++++++++++++++++++++--
>  include/mmc.h     | 17 +++++++++++++++++
>  2 files changed, 37 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index d7d1c91..2b710fe 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -621,6 +621,10 @@ static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode)
>  	case MMC_HS_52:
>  	case MMC_DDR_52:
>  		  speed_bits = EXT_CSD_TIMING_HS;
> +		  break;
> +	case MMC_HS_200:
> +		  speed_bits = EXT_CSD_TIMING_HS200;
> +		  break;
>  	case MMC_LEGACY:
>  		  speed_bits = EXT_CSD_TIMING_LEGACY;
>  		  break;
> @@ -667,9 +671,12 @@ static int mmc_get_capabilities(struct mmc *mmc)
>  
>  	mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
>  
> -	cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0xf;
> +	cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0x3f;
>  
> -	/* High Speed is set, there are two types: 52MHz and 26MHz */
> +	if (cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V |
> +			EXT_CSD_CARD_TYPE_HS200_1_8V)) {
> +		mmc->card_caps |= MMC_MODE_HS200;
> +	}
>  	if (cardtype & EXT_CSD_CARD_TYPE_52) {
>  		if (cardtype & EXT_CSD_CARD_TYPE_DDR_52)
>  			mmc->card_caps |= MMC_MODE_DDR_52MHz;
> @@ -1263,6 +1270,7 @@ void mmc_dump_capabilities(const char *text, uint caps)
>  struct mode_width_tuning {
>  	enum bus_mode mode;
>  	uint widths;
> +	uint tuning;
>  };
>  
>  static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
> @@ -1373,6 +1381,7 @@ static const struct mode_width_tuning mmc_modes_by_pref[] = {
>  	{
>  		.mode = MMC_HS_200,
>  		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
> +		.tuning = MMC_SEND_TUNING_BLOCK_HS200
>  	},
>  	{
>  		.mode = MMC_DDR_52,
> @@ -1473,6 +1482,15 @@ static int mmc_select_mode_and_width(struct mmc *mmc)
>  			mmc_select_mode(mmc, mwt->mode);
>  			mmc_set_clock(mmc, mmc->tran_speed, false);
>  
> +			/* execute tuning if needed */
> +			if (mwt->tuning) {
> +				err = mmc_execute_tuning(mmc, mwt->tuning);
> +				if (err) {
> +					debug("tuning failed\n");
> +					goto error;
> +				}
> +			}
> +
>  			/* do a transfer to check the configuration */
>  			err = mmc_read_and_compare_ext_csd(mmc);
>  			if (!err)
> diff --git a/include/mmc.h b/include/mmc.h
> index dab68c5..b4ffa6a 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -56,6 +56,7 @@
>  #define MMC_MODE_HS		(MMC_CAP(MMC_HS) | MMC_CAP(SD_HS))
>  #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_8BIT		(1 << 30)
>  #define MMC_MODE_4BIT		(1 << 29)
> @@ -86,6 +87,7 @@
>  #define MMC_CMD_SET_BLOCKLEN		16
>  #define MMC_CMD_READ_SINGLE_BLOCK	17
>  #define MMC_CMD_READ_MULTIPLE_BLOCK	18
> +#define MMC_SEND_TUNING_BLOCK_HS200	21

To maintain the consistency..use the prefix as "MMC_CMD_*", plz.

>  #define MMC_CMD_SET_BLOCK_COUNT         23
>  #define MMC_CMD_WRITE_SINGLE_BLOCK	24
>  #define MMC_CMD_WRITE_MULTIPLE_BLOCK	25
> @@ -113,6 +115,13 @@
>  #define SD_CMD_APP_SEND_OP_COND		41
>  #define SD_CMD_APP_SEND_SCR		51
>  
> +static inline bool mmc_is_tuning_cmd(uint cmdidx)
> +{
> +	if (cmdidx == MMC_SEND_TUNING_BLOCK_HS200)
> +		return true;
> +	return false;

return (cmdidx == MMC_SEND_TUNING_BLOCK_HS200? ...);

> +}
> +
>  /* SCR definitions in different words */
>  #define SD_HIGHSPEED_BUSY	0x00020000
>  #define SD_HIGHSPEED_SUPPORTED	0x00020000
> @@ -210,6 +219,12 @@
>  #define EXT_CSD_CARD_TYPE_DDR_52	(EXT_CSD_CARD_TYPE_DDR_1_8V \
>  					| EXT_CSD_CARD_TYPE_DDR_1_2V)
>  
> +#define EXT_CSD_CARD_TYPE_HS200_1_8V	(1<<4)	/* Card can run@200MHz */
> +#define EXT_CSD_CARD_TYPE_HS200_1_2V	(1<<5)	/* Card can run@200MHz */

Use the BIT().

> +						/* 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_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 */
> @@ -217,6 +232,8 @@
>  
>  #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_BOOT_ACK_ENABLE			(1 << 6)
>  #define EXT_CSD_BOOT_PARTITION_ENABLE		(1 << 3)
>  #define EXT_CSD_PARTITION_ACCESS_ENABLE		(1 << 0)
> 

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 20/22] mmc: Add support for UHS modes
  2017-05-12 18:16   ` [U-Boot] [PATCH 20/22] mmc: Add support for UHS modes Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
  2017-05-16 14:20     ` Jean-Jacques Hiblot
@ 2017-05-25 12:50     ` Jaehoon Chung
  2 siblings, 0 replies; 85+ messages in thread
From: Jaehoon Chung @ 2017-05-25 12:50 UTC (permalink / raw)
  To: u-boot

On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
> Add UHS modes to the list of supported modes, get the UHS capabilites of
> the SDcard and implement the procedure to switch the voltage (UHS modes
> use 1v8 IO lines)
> During the voltage switch procedure, DAT0 is used by the card to signal
> when it's ready. The optional card_busy() callback can be used to get this
> information from the host driver.
> 
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++---
>  include/mmc.h     |  27 ++++++++-
>  2 files changed, 188 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index f6509f1..074d286 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -31,6 +31,7 @@ static const unsigned int sd_au_size[] = {
>  };
>  static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
>  static void mmc_power_cycle(struct mmc *mmc);
> +static int mmc_card_busy(struct mmc *mmc);
>  
>  #if CONFIG_IS_ENABLED(MMC_TINY)
>  static struct mmc mmc_static;
> @@ -403,7 +404,68 @@ static int mmc_go_idle(struct mmc *mmc)
>  	return 0;
>  }
>  
> -static int sd_send_op_cond(struct mmc *mmc)
> +static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage)
> +{
> +	struct mmc_cmd cmd;
> +	int err = 0;
> +
> +	/*
> +	 * Send CMD11 only if the request is to switch the card to
> +	 * 1.8V signalling.
> +	 */
> +	if (signal_voltage == MMC_SIGNAL_VOLTAGE_330)
> +		return mmc_set_signal_voltage(mmc, signal_voltage);
> +
> +	cmd.cmdidx = SD_CMD_SWITCH_UHS18V;
> +	cmd.cmdarg = 0;
> +	cmd.resp_type = MMC_RSP_R1;
> +
> +	err = mmc_send_cmd(mmc, &cmd, NULL);
> +	if (err)
> +		goto fail;

goto fail..then it's changed the error number..just return err.

> +
> +	if (!mmc_host_is_spi(host) && (cmd.response[0] & MMC_STATUS_ERROR))
> +		goto fail;
> +
> +	/*
> +	 * The card should drive cmd and dat[0:3] low immediately
> +	 * after the response of cmd11, but wait 1 ms to be sure
> +	 */
> +	udelay(1000);
> +	if (mmc_card_busy(mmc))
> +		goto fail;

If Card is busy..it's not -EIO..it may be -EBUSY.

> +
> +	/*
> +	 * During a signal voltage level switch, the clock must be gated
> +	 * for 5 ms according to the SD spec
> +	 */
> +	mmc_set_clock(mmc, mmc->clock, true);
> +
> +	err = mmc_set_signal_voltage(mmc, signal_voltage);
> +	if (err)
> +		goto fail;

ditto..return err.

> +
> +	/* Keep clock gated for at least 10 ms, though spec only says 5 ms */
> +	udelay(10000);
> +	mmc_set_clock(mmc, mmc->clock, false);
> +
> +	/* Wait for at least 1 ms according to spec */
> +	udelay(1000);
> +
> +	/*
> +	 * Failure to switch is indicated by the card holding
> +	 * dat[0:3] low
> +	 */
> +	if (mmc_card_busy(mmc))
> +		goto fail;

ditto -EBUSY.

> +
> +	return 0;
> +
> +fail:
> +	return -EIO;
> +}
> +
> +static int sd_send_op_cond(struct mmc *mmc, bool uhs_en)
>  {
>  	int timeout = 1000;
>  	int err;
> @@ -435,6 +497,9 @@ static int sd_send_op_cond(struct mmc *mmc)
>  		if (mmc->version == SD_VERSION_2)
>  			cmd.cmdarg |= OCR_HCS;
>  
> +		if (uhs_en)
> +			cmd.cmdarg |= OCR_S18R;
> +
>  		err = mmc_send_cmd(mmc, &cmd, NULL);
>  
>  		if (err)
> @@ -465,6 +530,13 @@ static int sd_send_op_cond(struct mmc *mmc)
>  
>  	mmc->ocr = cmd.response[0];
>  
> +	if (!(mmc_host_is_spi(mmc)) && (cmd.response[0] & 0x41000000)
> +	    == 0x41000000) {
> +		err = mmc_switch_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
> +		if (err)
> +			return err;
> +	}
> +
>  	mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
>  	mmc->rca = 0;
>  
> @@ -977,6 +1049,7 @@ static int sd_get_capabilities(struct mmc *mmc)
>  	ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);
>  	struct mmc_data data;
>  	int timeout;
> +	u32 sd3_bus_mode;
>  
>  	mmc->card_caps = MMC_MODE_1BIT;
>  
> @@ -1058,6 +1131,22 @@ retry_scr:
>  	if (__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED)
>  		mmc->card_caps |= MMC_CAP(SD_HS);
>  
> +	/* Version before 3.0 don't support UHS modes */
> +	if (mmc->version < SD_VERSION_3)
> +		return 0;
> +
> +	sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f;
> +	if (sd3_bus_mode & SD_MODE_UHS_SDR104)
> +		mmc->card_caps |= MMC_CAP(UHS_SDR104);
> +	if (sd3_bus_mode & SD_MODE_UHS_SDR50)
> +		mmc->card_caps |= MMC_CAP(UHS_SDR50);
> +	if (sd3_bus_mode & SD_MODE_UHS_SDR25)
> +		mmc->card_caps |= MMC_CAP(UHS_SDR25);
> +	if (sd3_bus_mode & SD_MODE_UHS_SDR12)
> +		mmc->card_caps |= MMC_CAP(UHS_SDR12);
> +	if (sd3_bus_mode & SD_MODE_UHS_DDR50)
> +		mmc->card_caps |= MMC_CAP(UHS_DDR50);
> +
>  	return 0;
>  }
>  
> @@ -1065,13 +1154,36 @@ static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode)
>  {
>  	int err;
>  	ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);
> +	int speed;
> +
> +	switch (mode) {
> +	case SD_LEGACY:
> +	case UHS_SDR12:
> +		speed = UHS_SDR12_BUS_SPEED;
> +		break;
> +	case SD_HS:
> +	case UHS_SDR25:
> +		speed = UHS_SDR25_BUS_SPEED;
> +		break;
> +	case UHS_SDR50:
> +		speed = UHS_SDR50_BUS_SPEED;
> +		break;
> +	case UHS_DDR50:
> +		speed = UHS_DDR50_BUS_SPEED;
> +		break;
> +	case UHS_SDR104:
> +		speed = UHS_SDR104_BUS_SPEED;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
>  
> -	err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status);
> +	err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, speed, (u8 *)switch_status);
>  
>  	if (err)
>  		return err;
>  
> -	if ((__be32_to_cpu(switch_status[4]) & 0x0f000000) != 0x01000000)
> +	if ((__be32_to_cpu(switch_status[4]) >> 24) != speed)
>  		return -ENOTSUPP;
>  
>  	return 0;
> @@ -1291,10 +1403,31 @@ static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
>  
>  static const struct mode_width_tuning sd_modes_by_pref[] = {
>  	{
> +		.mode = UHS_SDR104,
> +		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
> +		.tuning = MMC_SEND_TUNING_BLOCK
> +	},
> +	{
> +		.mode = UHS_SDR50,
> +		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
> +	},
> +	{
> +		.mode = UHS_DDR50,
> +		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
> +	},
> +	{
> +		.mode = UHS_SDR25,
> +		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
> +	},
> +	{
>  		.mode = SD_HS,
>  		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
>  	},
>  	{
> +		.mode = UHS_SDR12,
> +		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
> +	},
> +	{
>  		.mode = SD_LEGACY,
>  		.widths = MMC_MODE_4BIT | MMC_MODE_1BIT,
>  	}
> @@ -1310,18 +1443,24 @@ static int sd_select_mode_and_width(struct mmc *mmc)
>  	int err;
>  	uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT};
>  	const struct mode_width_tuning *mwt;
> +	bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false;
> +	uint caps;
> +
>  
>  	err = sd_get_capabilities(mmc);
>  	if (err)
>  		return err;
>  	/* Restrict card's capabilities by what the host can do */
> -	mmc->card_caps &= (mmc->cfg->host_caps | MMC_MODE_1BIT);
> +	caps = mmc->card_caps & (mmc->cfg->host_caps | MMC_MODE_1BIT);
>  
> -	for_each_sd_mode_by_pref(mmc->card_caps, mwt) {
> +	if (!uhs_en)
> +		caps &= ~UHS_CAPS;
> +
> +	for_each_sd_mode_by_pref(caps, mwt) {
>  		uint *w;
>  
>  		for (w = widths; w < widths + ARRAY_SIZE(widths); w++) {
> -			if (*w & mmc->card_caps & mwt->widths) {
> +			if (*w & caps & mwt->widths) {
>  				debug("trying mode %s width %d (at %d MHz)\n",
>  				      mmc_mode_name(mwt->mode),
>  				      bus_width(*w),
> @@ -1342,6 +1481,16 @@ static int sd_select_mode_and_width(struct mmc *mmc)
>  				mmc_select_mode(mmc, mwt->mode);
>  				mmc_set_clock(mmc, mmc->tran_speed, false);
>  
> +				/* execute tuning if needed */
> +				if (mwt->tuning && !mmc_host_is_spi(mmc)) {
> +					err = mmc_execute_tuning(mmc,
> +								 mwt->tuning);
> +					if (err) {
> +						debug("tuning failed\n");
> +						goto error;
> +					}
> +				}
> +
>  				err = sd_read_ssr(mmc);
>  				if (!err)
>  					return 0;
> @@ -1993,6 +2142,7 @@ static void mmc_power_cycle(struct mmc *mmc)
>  int mmc_start_init(struct mmc *mmc)
>  {
>  	bool no_card;
> +	bool uhs_en = supports_uhs(mmc->cfg->host_caps);
>  	int err;
>  
>  	/* we pretend there's no card when init is NULL */
> @@ -2028,6 +2178,7 @@ int mmc_start_init(struct mmc *mmc)
>  #endif
>  	mmc->ddr_mode = 0;
>  
> +retry:
>  	mmc_power_cycle(mmc);
>  
>  	/* Reset the Card */
> @@ -2043,7 +2194,11 @@ int mmc_start_init(struct mmc *mmc)
>  	err = mmc_send_if_cond(mmc);
>  
>  	/* Now try to get the SD card's operating condition */
> -	err = sd_send_op_cond(mmc);
> +	err = sd_send_op_cond(mmc, uhs_en);
> +	if (err && uhs_en) {
> +		uhs_en = false;
> +		goto retry;
> +	}
>  
>  	/* If the command timed out, we check for an MMC card */
>  	if (err == -ETIMEDOUT) {
> diff --git a/include/mmc.h b/include/mmc.h
> index b42f686..775c47e 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -87,6 +87,7 @@
>  #define MMC_CMD_SET_BLOCKLEN		16
>  #define MMC_CMD_READ_SINGLE_BLOCK	17
>  #define MMC_CMD_READ_MULTIPLE_BLOCK	18
> +#define MMC_SEND_TUNING_BLOCK		19

Ditto..Use the MMC_CMD prefix. :)

>  #define MMC_SEND_TUNING_BLOCK_HS200	21
>  #define MMC_CMD_SET_BLOCK_COUNT         23
>  #define MMC_CMD_WRITE_SINGLE_BLOCK	24
> @@ -117,7 +118,8 @@
>  
>  static inline bool mmc_is_tuning_cmd(uint cmdidx)
>  {
> -	if (cmdidx == MMC_SEND_TUNING_BLOCK_HS200)
> +	if ((cmdidx == MMC_SEND_TUNING_BLOCK_HS200) ||
> +	    (cmdidx == MMC_SEND_TUNING_BLOCK))
>  		return true;
>  	return false;
>  }
> @@ -126,8 +128,22 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
>  #define SD_HIGHSPEED_BUSY	0x00020000
>  #define SD_HIGHSPEED_SUPPORTED	0x00020000
>  
> +#define UHS_SDR12_BUS_SPEED	0
> +#define HIGH_SPEED_BUS_SPEED	1
> +#define UHS_SDR25_BUS_SPEED	1
> +#define UHS_SDR50_BUS_SPEED	2
> +#define UHS_SDR104_BUS_SPEED	3
> +#define UHS_DDR50_BUS_SPEED	4
> +
> +#define SD_MODE_UHS_SDR12	(1 << UHS_SDR12_BUS_SPEED)
> +#define SD_MODE_UHS_SDR25	(1 << UHS_SDR25_BUS_SPEED)
> +#define SD_MODE_UHS_SDR50	(1 << UHS_SDR50_BUS_SPEED)
> +#define SD_MODE_UHS_SDR104	(1 << UHS_SDR104_BUS_SPEED)
> +#define SD_MODE_UHS_DDR50	(1 << UHS_DDR50_BUS_SPEED)
> +
>  #define OCR_BUSY		0x80000000
>  #define OCR_HCS			0x40000000
> +#define OCR_S18R		0x1000000
>  #define OCR_VOLTAGE_MASK	0x007FFF80
>  #define OCR_ACCESS_MODE		0x60000000
>  
> @@ -490,6 +506,15 @@ static inline bool mmc_is_mode_ddr(enum bus_mode mode)
>  		return false;
>  }
>  
> +#define UHS_CAPS (MMC_CAP(UHS_SDR12) | MMC_CAP(UHS_SDR25) | \
> +		  MMC_CAP(UHS_SDR50) | MMC_CAP(UHS_SDR104) | \
> +		  MMC_CAP(UHS_DDR50))
> +
> +static inline bool supports_uhs(uint caps)
> +{
> +	return (caps & UHS_CAPS) ? true : false;
> +}
> +
>  
>  /*
>   * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device
> 

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 21/22] mmc: Change mode when switching to a boot partition
  2017-05-12 18:16   ` [U-Boot] [PATCH 21/22] mmc: Change mode when switching to a boot partition Jean-Jacques Hiblot
  2017-05-15  3:28     ` Simon Glass
@ 2017-05-25 12:53     ` Jaehoon Chung
  1 sibling, 0 replies; 85+ messages in thread
From: Jaehoon Chung @ 2017-05-25 12:53 UTC (permalink / raw)
  To: u-boot

On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
> Boot partitions do not support HS200. Changing to a lower performance mode
> is required to access them.
> mmc_select_mode_and_width() and sd_select_mode_and_width() are modified to
> make it easier to call them outside of the initialization context.

This patch should be important to support the HS200 mode on u-boot..
So i need to test this..more detail..

> 
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 66 +++++++++++++++++++++++++++++++++++++++++--------------
>  include/mmc.h     |  1 +
>  2 files changed, 50 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 074d286..c7dda64 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -32,6 +32,7 @@ static const unsigned int sd_au_size[] = {
>  static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
>  static void mmc_power_cycle(struct mmc *mmc);
>  static int mmc_card_busy(struct mmc *mmc);
> +static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps);
>  
>  #if CONFIG_IS_ENABLED(MMC_TINY)
>  static struct mmc mmc_static;
> @@ -788,10 +789,38 @@ static int mmc_set_capacity(struct mmc *mmc, int part_num)
>  	return 0;
>  }
>  
> +static int mmc_boot_part_access_chk(struct mmc *mmc, unsigned int part_num)
> +{
> +	int forbiden = 0;

forbiden? typo?

> +	bool change = false;
> +
> +	if (part_num & PART_ACCESS_MASK)
> +		forbiden = MMC_CAP(MMC_HS_200);
> +
> +	if (MMC_CAP(mmc->selected_mode) & forbiden) {
> +		debug("selected mode (%s) is forbiden for part %d\n",
> +		      mmc_mode_name(mmc->selected_mode), part_num);
> +		change = true;
> +	} else if (mmc->selected_mode != mmc->best_mode) {
> +		debug("selected mode is not optimal\n");
> +		change = true;
> +	}
> +
> +	if (change)
> +		return mmc_select_mode_and_width(mmc,
> +						 mmc->card_caps & ~forbiden);
> +
> +	return 0;
> +}
> +
>  int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
>  {
>  	int ret;
>  
> +	ret = mmc_boot_part_access_chk(mmc, part_num);
> +	if (ret)
> +		return ret;
> +
>  	ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
>  			 (mmc->part_config & ~PART_ACCESS_MASK)
>  			 | (part_num & PART_ACCESS_MASK));
> @@ -1438,7 +1467,7 @@ static const struct mode_width_tuning sd_modes_by_pref[] = {
>  	     mwt++) \
>  		if (caps & MMC_CAP(mwt->mode))
>  
> -static int sd_select_mode_and_width(struct mmc *mmc)
> +static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
>  {
>  	int err;
>  	uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT};
> @@ -1447,11 +1476,8 @@ static int sd_select_mode_and_width(struct mmc *mmc)
>  	uint caps;
>  
>  
> -	err = sd_get_capabilities(mmc);
> -	if (err)
> -		return err;
>  	/* Restrict card's capabilities by what the host can do */
> -	caps = mmc->card_caps & (mmc->cfg->host_caps | MMC_MODE_1BIT);
> +	caps = card_caps & (mmc->cfg->host_caps | MMC_MODE_1BIT);
>  
>  	if (!uhs_en)
>  		caps &= ~UHS_CAPS;
> @@ -1582,18 +1608,14 @@ static const struct ext_csd_bus_width {
>  	    ecbv++) \
>  		if ((ddr == ecbv->is_ddr) && (caps & ecbv->cap))
>  
> -static int mmc_select_mode_and_width(struct mmc *mmc)
> +static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
>  {
>  	int err;
>  	const struct mode_width_tuning *mwt;
>  	const struct ext_csd_bus_width *ecbw;
>  
> -	err = mmc_get_capabilities(mmc);
> -	if (err)
> -		return err;
> -
>  	/* Restrict card's capabilities by what the host can do */
> -	mmc->card_caps &= (mmc->cfg->host_caps | MMC_MODE_1BIT);
> +	card_caps &= (mmc->cfg->host_caps | MMC_MODE_1BIT);
>  
>  	/* Only version 4 of MMC supports wider bus widths */
>  	if (mmc->version < MMC_VERSION_4)
> @@ -1605,8 +1627,10 @@ static int mmc_select_mode_and_width(struct mmc *mmc)
>  		return -ENOTSUPP;
>  	}
>  
> -	for_each_mmc_mode_by_pref(mmc->card_caps, mwt) {
> -		for_each_supported_width(mmc->card_caps & mwt->widths,
> +	mmc_set_clock(mmc, mmc->legacy_speed, false);
> +
> +	for_each_mmc_mode_by_pref(card_caps, mwt) {
> +		for_each_supported_width(card_caps & mwt->widths,
>  					 mmc_is_mode_ddr(mwt->mode), ecbw) {
>  			debug("trying mode %s width %d (at %d MHz)\n",
>  			      mmc_mode_name(mwt->mode),
> @@ -1999,14 +2023,22 @@ static int mmc_startup(struct mmc *mmc)
>  	if (err)
>  		return err;
>  
> -	if (IS_SD(mmc))
> -		err = sd_select_mode_and_width(mmc);
> -	else
> -		err = mmc_select_mode_and_width(mmc);
> +	if (IS_SD(mmc)) {
> +		err = sd_get_capabilities(mmc);
> +		if (err)
> +			return err;
> +		err = sd_select_mode_and_width(mmc, mmc->card_caps);
> +	} else {
> +		err = mmc_get_capabilities(mmc);
> +		if (err)
> +			return err;
> +		mmc_select_mode_and_width(mmc, mmc->card_caps);
> +	}
>  
>  	if (err)
>  		return err;
>  
> +	mmc->best_mode = mmc->selected_mode;
>  
>  	/* Fix the block length for DDR mode */
>  	if (mmc->ddr_mode) {
> diff --git a/include/mmc.h b/include/mmc.h
> index 775c47e..921a7ff 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -573,6 +573,7 @@ struct mmc {
>  #endif
>  	u8 *ext_csd;
>  	enum bus_mode selected_mode;
> +	enum bus_mode best_mode;
>  };
>  
>  struct mmc_hwpart_conf {
> 

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 10/22] mmc: refactor MMC startup to make it easier to support new modes
  2017-05-25 12:25     ` Jaehoon Chung
@ 2017-05-25 14:40       ` Jean-Jacques Hiblot
  2017-05-26  1:12         ` Jaehoon Chung
  0 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-25 14:40 UTC (permalink / raw)
  To: u-boot

Hi,


On 25/05/2017 14:25, Jaehoon Chung wrote:
> On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
>> The MMC startup process currently handles 4 modes. To make it easier to
>> add support for more modes, let's make the process more generic and use a
>> list of the modes to try.
>> The major functional change is that when a mode fails we try the next one.
>> Not all modes are tried, only those supported by the card and the host.
>>
>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
>> ---
>>   drivers/mmc/mmc.c | 238 +++++++++++++++++++++++++++++++++---------------------
>>   include/mmc.h     |  15 +++-
>>   2 files changed, 157 insertions(+), 96 deletions(-)
>>
>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>> index f42a0fe..2931871 100644
>> --- a/drivers/mmc/mmc.c
>> +++ b/drivers/mmc/mmc.c
>> @@ -200,6 +200,7 @@ static int mmc_select_mode(struct mmc *mmc, enum bus_mode mode)
>>   {
>>   	mmc->selected_mode = mode;
>>   	mmc->tran_speed = mmc_mode2freq(mmc, mode);
>> +	mmc->ddr_mode = mmc_is_mode_ddr(mode);
>>   	debug("selecting mode %s (freq : %d MHz)\n", mmc_mode_name(mode),
>>   	      mmc->tran_speed / 1000000);
>>   	return 0;
>> @@ -602,11 +603,46 @@ int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
>>   
>>   }
>>   
>> -static int mmc_change_freq(struct mmc *mmc)
>> +static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode)
>>   {
>> -	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
>> -	char cardtype;
>>   	int err;
>> +	int speed_bits;
>> +	ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
>> +
>> +	switch (mode) {
>> +	case MMC_HS:
>> +	case MMC_HS_52:
>> +	case MMC_DDR_52:
>> +		  speed_bits = EXT_CSD_TIMING_HS;
>> +	case MMC_LEGACY:
>> +		  speed_bits = EXT_CSD_TIMING_LEGACY;
>> +		  break;
>> +	default:
>> +		  return -EINVAL;
>> +	}
>> +	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
>> +			 speed_bits);
>> +	if (err)
>> +		return err;
>> +
>> +	if ((mode == MMC_HS) || (mode == MMC_HS_52)) {
>> +		/* Now check to see that it worked */
>> +		err = mmc_send_ext_csd(mmc, test_csd);
>> +		if (err)
>> +			return err;
>> +
>> +		/* No high-speed support */
>> +		if (!test_csd[EXT_CSD_HS_TIMING])
>> +			return -ENOTSUPP;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int mmc_get_capabilities(struct mmc *mmc)
>> +{
>> +	u8 *ext_csd = mmc->ext_csd;
>> +	char cardtype;
>>   
>>   	mmc->card_caps = MMC_MODE_1BIT;
>>   
>> @@ -617,38 +653,23 @@ static int mmc_change_freq(struct mmc *mmc)
>>   	if (mmc->version < MMC_VERSION_4)
>>   		return 0;
>>   
>> -	mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
>> -
>> -	err = mmc_send_ext_csd(mmc, ext_csd);
>> +	if (!ext_csd) {
>> +		error("No ext_csd found!\n"); /* this should enver happen */
>> +		return -ENOTSUPP;
>> +	}
>>   
>> -	if (err)
>> -		return err;
>> +	mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
>>   
>>   	cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0xf;
>>   
>> -	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);
>> -
>> -	if (err)
>> -		return err;
>> -
>> -	/* Now check to see that it worked */
>> -	err = mmc_send_ext_csd(mmc, ext_csd);
>> -
>> -	if (err)
>> -		return err;
>> -
>> -	/* No high-speed support */
>> -	if (!ext_csd[EXT_CSD_HS_TIMING])
>> -		return 0;
>> -
>>   	/* High Speed is set, there are two types: 52MHz and 26MHz */
>>   	if (cardtype & EXT_CSD_CARD_TYPE_52) {
>> -		if (cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V)
>> +		if (cardtype & EXT_CSD_CARD_TYPE_DDR_52)
>>   			mmc->card_caps |= MMC_MODE_DDR_52MHz;
>> -		mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
>> -	} else {
>> -		mmc->card_caps |= MMC_MODE_HS;
>> +		mmc->card_caps |= MMC_MODE_HS_52MHz;
>>   	}
>> +	if (cardtype & EXT_CSD_CARD_TYPE_26)
>> +		mmc->card_caps |= MMC_MODE_HS;
>>   
>>   	return 0;
>>   }
>> @@ -1320,33 +1341,58 @@ static int mmc_read_and_compare_ext_csd(struct mmc *mmc)
>>   }
>>   
>>   
>> -static int mmc_select_bus_freq_width(struct mmc *mmc)
>> +static const struct mode_width_tuning mmc_modes_by_pref[] = {
>> +	{
>> +		.mode = MMC_HS_200,
>> +		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
>> +	},
>> +	{
>> +		.mode = MMC_DDR_52,
>> +		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
>> +	},
>> +	{
>> +		.mode = MMC_HS_52,
>> +		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
>> +	},
>> +	{
>> +		.mode = MMC_HS,
>> +		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
>> +	},
>> +	{
>> +		.mode = MMC_LEGACY,
>> +		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
>> +	}
>> +};
>> +#define for_each_mmc_mode_by_pref(caps, mwt) \
>> +	for (mwt = mmc_modes_by_pref;\
>> +	    mwt < mmc_modes_by_pref + ARRAY_SIZE(mmc_modes_by_pref);\
>> +	    mwt++) \
>> +		if (caps & MMC_CAP(mwt->mode))
>> +
>> +static const struct ext_csd_bus_width {
>> +	uint cap;
>> +	bool is_ddr;
>> +	uint ext_csd_bits;
>> +} ext_csd_bus_width[] = {
>> +	{MMC_MODE_8BIT, true, EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR},
>> +	{MMC_MODE_4BIT, true, EXT_CSD_BUS_WIDTH_4 | EXT_CSD_DDR},
>> +	{MMC_MODE_8BIT, false, EXT_CSD_BUS_WIDTH_8},
>> +	{MMC_MODE_4BIT, false, EXT_CSD_BUS_WIDTH_4},
>> +	{MMC_MODE_1BIT, false, EXT_CSD_BUS_WIDTH_1},
>> +};
>> +#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);\
>> +	    ecbv++) \
>> +		if ((ddr == ecbv->is_ddr) && (caps & ecbv->cap))
>> +
>> +static int mmc_select_mode_and_width(struct mmc *mmc)
>>   {
>> -	/* An array of possible bus widths in order of preference */
>> -	static const unsigned ext_csd_bits[] = {
>> -		EXT_CSD_DDR_BUS_WIDTH_8,
>> -		EXT_CSD_DDR_BUS_WIDTH_4,
>> -		EXT_CSD_BUS_WIDTH_8,
>> -		EXT_CSD_BUS_WIDTH_4,
>> -		EXT_CSD_BUS_WIDTH_1,
>> -	};
>> -	/* An array to map CSD bus widths to host cap bits */
>> -	static const unsigned ext_to_hostcaps[] = {
>> -		[EXT_CSD_DDR_BUS_WIDTH_4] =
>> -			MMC_MODE_DDR_52MHz | MMC_MODE_4BIT,
>> -		[EXT_CSD_DDR_BUS_WIDTH_8] =
>> -			MMC_MODE_DDR_52MHz | MMC_MODE_8BIT,
>> -		[EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT,
>> -		[EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT,
>> -	};
>> -	/* An array to map chosen bus width to an integer */
>> -	static const unsigned widths[] = {
>> -		8, 4, 8, 4, 1,
>> -	};
>>   	int err;
>> -	int idx;
>> +	const struct mode_width_tuning *mwt;
>> +	const struct ext_csd_bus_width *ecbw;
>>   
>> -	err = mmc_change_freq(mmc);
>> +	err = mmc_get_capabilities(mmc);
>>   	if (err)
>>   		return err;
>>   
>> @@ -1357,60 +1403,64 @@ static int mmc_select_bus_freq_width(struct mmc *mmc)
>>   	if (mmc->version < MMC_VERSION_4)
>>   		return 0;
>>   
>> +
>>   	if (!mmc->ext_csd) {
>>   		error("No ext_csd found!\n"); /* this should enver happen */
>>   		return -ENOTSUPP;
>>   	}
>>   
>> -	for (idx = 0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
>> -		unsigned int extw = ext_csd_bits[idx];
>> -		unsigned int caps = ext_to_hostcaps[extw];
>> +	for_each_mmc_mode_by_pref(mmc->card_caps, mwt) {
>> +		for_each_supported_width(mmc->card_caps & mwt->widths,
>> +					 mmc_is_mode_ddr(mwt->mode), ecbw) {
>> +			debug("trying mode %s width %d (at %d MHz)\n",
>> +			      mmc_mode_name(mwt->mode),
>> +			      bus_width(ecbw->cap),
>> +			      mmc_mode2freq(mmc, mwt->mode) / 1000000);
>>   
>> -		/*
>> -		  * If the bus width is still not changed,
>> -		  * don't try to set the default again.
>> -		  * Otherwise, recover from switch attempts
>> -		  * by switching to 1-bit bus width.
>> -		  */
>> -		if (extw == EXT_CSD_BUS_WIDTH_1 &&
>> -		    mmc->bus_width == 1) {
>> -			err = 0;
>> -			break;
>> -		}
>> -
>> -		/*
>> -		  * Check to make sure the card and controller support
>> -		  * these capabilities
>> -		  */
>> -		if ((mmc->card_caps & caps) != caps)
>> -			continue;
>> -
>> -		err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
>> -				EXT_CSD_BUS_WIDTH, extw);
>> +			/* configure the bus width (card + host) */
>> +			err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
>> +				EXT_CSD_BUS_WIDTH,
>> +				ecbw->ext_csd_bits & ~EXT_CSD_DDR);
>> +			if (err)
>> +				goto error;
>> +			mmc_set_bus_width(mmc, bus_width(ecbw->cap));
>>   
>> -		if (err)
>> -			continue;
>> +			/* 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) {
>> +				err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
>> +					EXT_CSD_BUS_WIDTH, ecbw->ext_csd_bits);
>> +				if (err)
>> +					goto error;
>> +			}
>>   
>> -		mmc->ddr_mode = (caps & MMC_MODE_DDR_52MHz) ? 1 : 0;
>> -		mmc_set_bus_width(mmc, widths[idx]);
>> +			/* configure the bus mode (host) */
>> +			mmc_select_mode(mmc, mwt->mode);
>> +			mmc_set_clock(mmc, mmc->tran_speed);
>>   
>> -		err = mmc_read_and_compare_ext_csd(mmc);
>> -		if (!err)
>> -			break;
>> +			/* do a transfer to check the configuration */
>> +			err = mmc_read_and_compare_ext_csd(mmc);
>> +			if (!err)
>> +				return 0;
>> +error:
>> +			/* if an error occured, revert to a safer bus mode */
>> +			mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
>> +				   EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_1);
>> +			mmc_select_mode(mmc, MMC_LEGACY);
>> +			mmc_set_bus_width(mmc, 1);
>> +		}
>>   	}
>>   
>> -	if (err)
>> -		return err;
>> -
>> -	if (mmc->card_caps & MMC_MODE_HS_52MHz) {
>> -		if (mmc->ddr_mode)
>> -			mmc_select_mode(mmc, MMC_DDR_52);
>> -		else
>> -			mmc_select_mode(mmc, MMC_HS_52);
>> -	} else if (mmc->card_caps & MMC_MODE_HS)
>> -		mmc_select_mode(mmc, MMC_HS);
>> +	error("unable to select a mode\n");
>>   
>> -	return err;
>> +	return -ENOTSUPP;
>>   }
>>   
>>   static int mmc_startup_v4(struct mmc *mmc)
>> @@ -1747,7 +1797,7 @@ static int mmc_startup(struct mmc *mmc)
>>   	if (IS_SD(mmc))
>>   		err = sd_select_mode_and_width(mmc);
>>   	else
>> -		err = mmc_select_bus_freq_width(mmc);
>> +		err = mmc_select_mode_and_width(mmc);
>>   
>>   	if (err)
>>   		return err;
>> diff --git a/include/mmc.h b/include/mmc.h
>> index 1ffa7ec..3c6971d 100644
>> --- a/include/mmc.h
>> +++ b/include/mmc.h
>> @@ -213,9 +213,10 @@
>>   #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 */
>> -#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		4	/* Card is in DDR mode */
> Why do you change to 4 as DDR mode?
It's a flag to add to EXT_CSD_BUS_WIDTH_x. for example 
EXT_CSD_BUS_WIDTH_4 | EXT_CSD_DDR = 1 | 4 = 5

JJ
>
>>   
>> +#define EXT_CSD_TIMING_LEGACY	0	/* no high speed */
>> +#define EXT_CSD_TIMING_HS	1	/* HS */
>>   #define EXT_CSD_BOOT_ACK_ENABLE			(1 << 6)
>>   #define EXT_CSD_BOOT_PARTITION_ENABLE		(1 << 3)
>>   #define EXT_CSD_PARTITION_ACCESS_ENABLE		(1 << 0)
>> @@ -424,6 +425,16 @@ enum bus_mode {
>>   
>>   const char *mmc_mode_name(enum bus_mode mode);
>>   void mmc_dump_capabilities(const char *text, uint caps);
>> +
>> +static inline bool mmc_is_mode_ddr(enum bus_mode mode)
>> +{
>> +	if ((mode == MMC_DDR_52) || (mode == UHS_DDR50))
>> +		return true;
>> +	else
>> +		return false;
>> +}
>> +
>> +
>>   /*
>>    * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device
>>    * with mmc_get_mmc_dev().
>>
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-05-25  7:41       ` Jaehoon Chung
@ 2017-05-25 14:42         ` Jean-Jacques Hiblot
  2017-06-02 16:46         ` Jean-Jacques Hiblot
  2017-06-16 10:00         ` Jean-Jacques Hiblot
  2 siblings, 0 replies; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-25 14:42 UTC (permalink / raw)
  To: u-boot



On 25/05/2017 09:41, Jaehoon Chung wrote:
> Hi,
>
> On 05/24/2017 12:24 AM, Jean-Jacques Hiblot wrote:
>> Hi,
>>
>>
>> On 18/05/2017 06:27, Jaehoon Chung wrote:
>>> Hi,
>>>
>>> On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
>>>> This series brings support for HS200 and UHS modes to the mmc core.
>>>> It has been tested with the hsmmc driver on several platforms (DRA7,
>>>> AM57x, AM437x, beaglebone black). Some modifications are required in
>>>> the host driver to take advantage of this (voltage switching, tuning).
>>>> The changes to the host driver will be posted a another series as this
>>>> one is already long enough.
>>>>
>>>> The series starts with a small refactoring of th sd/mmc startup. The first 4 commits
>>>> are mostly moving code around with little or no functionnal change.
>>>>
>>>> Then the notion of "mode" is introduced. Until now, this information wasn't
>>>> kept in struct mmc. Only the clock and a flag for ddr was kept. Later the mode
>>>> information will be used to select the clock frequency, the ddr flag and the
>>>> tuning procedure. It will be also be check against the host capabilities.
>>>>
>>>> Then comes the big refactoring job in:
>>>> "mmc: refactor MMC startup to make it easier to support new modes" and
>>>> "mmc: refactor SD startup to make it easier to support new modes"
>>>> Since the number of modes is increasing, it makes sense to try them in a more
>>>> organized way. those commits use a list of supported modes and iterate through
>>>> them to find the best working one. It also allows to switch more easilly from
>>>> one mode to another (switching from HS200 to DDR52 to access boot partitions for example)
>>>>
>>>> Then there are a couple of new callback added to:
>>>> - enable/disable Vdd
>>>> - check if the card is busy (used during UHS voltage switching)
>>>> - select the IO voltage
>>>>
>>>> Then Power cycle is added. Without power cycle, if a UHS card fails to enumerate in
>>>> UHS mode, it can't fall back to high speed mode and card enumeration will fail.
>>>>
>>>> And finally the last commits add the support for HS200 and UHS.
>>>> I haven't been able to test the UHS SDR104 mode by lack of compatible sdcard.
>>> After testing my targets, some boards don't work fine..So i'm checking this problem..
>> Jaehoon,
>>
>> what kind of issues are you running into and on what platforms ?
>> So far, besides the items brought-up by the reviews, there are 2 issues that are in the pipe for the next version:
>>   * signal voltage selection is not done for the MMCs only for SDs.
>>   * I noticed a timing constraint in voltage selection for SDs that can be a problem when trying a UHS mode with some SDs (seen only with Sandisk Ultra  64Gb micro SD class I) :  the voltage must be switched quickly after the cmd SWITCH_UHS18V has been sent, making debug messages in that context a problem. With this SD I've been able to check that SDR104 is working.
> How about making the "testing-hs200-uhs" branch for this? It needs to test more..
Sure. It seems a good idea.
> I guess my target doesn't do the voltage change..i'm doing for ufs driver on u-boot in my local..
> So i didn't see fully..today i have a free time..So i'm doing full review other thing..and about pending patches.
>
> Thanks for waiting me.. :)
>
> Best Regards,
> Jaehoon Chung
>
>> Jean-Jacques
>>>> With this in place and the required changes in the HSMMC (including DAM), we observe significant
>>>> improvements in the performances on a DRA7 evm:
>>>> eMMC HS200: 130 MB/s
>>>> eMMC DDR52: 80 MB/s
>>>> sd   SDR50: 80 MB/s
>>>>
>>>> cheers,
>>>>
>>>> Jean-Jacques
>>>>
>>>>
>>>> Jean-Jacques Hiblot (18):
>>>>     mmc: split mmc_startup()
>>>>     mmc: move the MMC startup for version above v4.0 in a separate
>>>>       function
>>>>     mmc: make ext_csd part of struct mmc
>>>>     mmc: add a function to read and test the ext csd (mmc >= 4)
>>>>     mmc: introduces mmc modes.
>>>>     mmc: Add a fonction to dump the mmc capabilities
>>>>     mmc: use mmc modes to select the correct bus speed
>>>>     cmd: mmc: display the mode name and current bus speed in the mmc info
>>>>     mmc: refactor SD startup to make it easier to support new modes
>>>>     mmc: refactor MMC startup to make it easier to support new modes
>>>>     mmc: make mmc_set_ios() return status
>>>>     mmc: add power cyle support in mmc core
>>>>     mmc: add a new mmc parameter to disable mmc clock
>>>>     mmc: Add a execute_tuning() callback to the mmc operations.
>>>>     mmc: add HS200 support in MMC core
>>>>     mmc: Add a new callback function to check if the card is busy
>>>>     mmc: Add support for UHS modes
>>>>     mmc: Change mode when switching to a boot partition
>>>>
>>>> Kishon Vijay Abraham I (3):
>>>>     mmc: Enable signal voltage to be selected from mmc core
>>>>     mmc: Add a new callback function to enable/disable vdd
>>>>     mmc: disable the mmc clock during power off
>>>>
>>>> Vignesh R (1):
>>>>     mmc: Retry some MMC cmds on failure
>>>>
>>>>    cmd/mmc.c                |    3 +-
>>>>    drivers/mmc/fsl_esdhc.c  |    2 +-
>>>>    drivers/mmc/mmc-uclass.c |   42 ++
>>>>    drivers/mmc/mmc.c        | 1220 +++++++++++++++++++++++++++++++++-------------
>>>>    include/mmc.h            |  138 +++++-
>>>>    5 files changed, 1058 insertions(+), 347 deletions(-)
>>>>
>>
>>
>>
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 14/22] mmc: add power cyle support in mmc core
  2017-05-25 12:35     ` Jaehoon Chung
@ 2017-05-25 14:50       ` Jean-Jacques Hiblot
  2017-06-15 16:13       ` Jean-Jacques Hiblot
  1 sibling, 0 replies; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-25 14:50 UTC (permalink / raw)
  To: u-boot



On 25/05/2017 14:35, Jaehoon Chung wrote:
> On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
>> mmc/sd specification requires vdd to be disabled for 1 ms
>> and then enabled again during power cycle. Add a
>> function in mmc core to perform power cycle and set
>> the io signal to it's initial state.
>>
>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
>> ---
>>   drivers/mmc/mmc.c | 50 +++++++++++++++++++++++++++++++++++++++++---------
>>   1 file changed, 41 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>> index d40a22b..032260b 100644
>> --- a/drivers/mmc/mmc.c
>> +++ b/drivers/mmc/mmc.c
>> @@ -30,6 +30,7 @@ static const unsigned int sd_au_size[] = {
>>   	SZ_16M / 512,	(SZ_16M + SZ_8M) / 512,	SZ_32M / 512,	SZ_64M / 512,
>>   };
>>   static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
>> +static void mmc_power_cycle(struct mmc *mmc);
>>   
>>   #if CONFIG_IS_ENABLED(MMC_TINY)
>>   static struct mmc mmc_static;
>> @@ -1915,6 +1916,45 @@ static int mmc_power_init(struct mmc *mmc)
>>   	return 0;
>>   }
>>   
>> +static void mmc_set_initial_state(struct mmc *mmc)
>> +{
>> +	int err;
>> +
>> +	/* First try to set 3.3V. If it fails set to 1.8V */
>> +	err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
>> +	if (err != 0)
>> +		err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
>> +	if (err != 0)
>> +		printf("failed to set signal voltage\n");
>> +
>> +	mmc_set_bus_width(mmc, 1);
>> +	mmc_set_clock(mmc, 1);
>> +	mmc_select_mode(mmc, MMC_LEGACY);
>> +}
>> +
>> +static void mmc_power_up(struct mmc *mmc)
>> +{
>> +	mmc_set_initial_state(mmc);
>> +	mmc_set_vdd(mmc, true);
> mmc_set_vdd has the return value..but there are no usage anywhere..
> if this is correct, mmc_set_vdd can be *void* type.
OK. i'll change it in v2.
>
>> +	udelay(10000);
>> +}
>> +
>> +static void mmc_power_off(struct mmc *mmc)
>> +{
>> +	mmc_set_vdd(mmc, false);
>> +}
>> +
>> +static void mmc_power_cycle(struct mmc *mmc)
>> +{
>> +	mmc_power_off(mmc);
>> +	/*
>> +	 * SD spec recommends at least 1ms of delay. Let's wait for 2ms
>> +	 * to be on the safer side.
>> +	 */
> Could you put the SD spec version and about which part...?
> I didn't find the 2ms so..i want to see the spec about 2ms.
I need to figure this out. I forgot to mention it, but all this code is 
based on the work of Kishon Vijay Abraham who did the hs200 support for 
the ti u-boot tree.

Kishon,

can you point to the relevant part of the spec ?
>
>> +	udelay(2000);
>> +	mmc_power_up(mmc);
>> +}
>> +
>>   int mmc_start_init(struct mmc *mmc)
>>   {
>>   	bool no_card;
>> @@ -1952,16 +1992,8 @@ int mmc_start_init(struct mmc *mmc)
>>   		return err;
>>   #endif
>>   	mmc->ddr_mode = 0;
>> -	mmc_set_vdd(mmc, true);
>> -	/* First try to set 3.3V. If it fails set to 1.8V */
>> -	err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
>> -	if (err != 0)
>> -		err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
>> -	if (err != 0)
>> -		printf("failed to set signal voltage\n");
>>   
>> -	mmc_set_bus_width(mmc, 1);
>> -	mmc_set_clock(mmc, 1);
>> +	mmc_power_cycle(mmc);
>>   
>>   	/* Reset the Card */
>>   	err = mmc_go_idle(mmc);
>>
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 17/22] mmc: Add a execute_tuning() callback to the mmc operations.
  2017-05-25 12:37     ` Jaehoon Chung
@ 2017-05-25 14:51       ` Jean-Jacques Hiblot
  0 siblings, 0 replies; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-05-25 14:51 UTC (permalink / raw)
  To: u-boot



On 25/05/2017 14:37, Jaehoon Chung wrote:
> On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
>> Tuning is a mandatory step in the initialization of SDR104 and HS200 modes.
>> This callback execute the tuning process.
>>
>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
>> ---
>>   drivers/mmc/mmc-uclass.c | 14 ++++++++++++++
>>   drivers/mmc/mmc.c        |  5 +++++
>>   include/mmc.h            | 12 ++++++++++++
>>   3 files changed, 31 insertions(+)
>>
>> diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
>> index e1f7995..b7433cf 100644
>> --- a/drivers/mmc/mmc-uclass.c
>> +++ b/drivers/mmc/mmc-uclass.c
>> @@ -93,6 +93,20 @@ int mmc_getcd(struct mmc *mmc)
>>   {
>>   	return dm_mmc_get_cd(mmc->dev);
>>   }
>> +
>> +int dm_mmc_execute_tuning(struct udevice *dev, uint opcode)
>> +{
>> +	struct dm_mmc_ops *ops = mmc_get_ops(dev);
>> +
>> +	if (!ops->execute_tuning)
>> +		return -ENOSYS;
>> +	return ops->execute_tuning(dev, opcode);
>> +}
>> +
>> +int mmc_execute_tuning(struct mmc *mmc, uint opcode)
>> +{
>> +	return dm_mmc_execute_tuning(mmc->dev, opcode);
>> +}
>>   #endif
>>   
>>   struct mmc *mmc_get_mmc_dev(struct udevice *dev)
>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>> index 415484e..d7d1c91 100644
>> --- a/drivers/mmc/mmc.c
>> +++ b/drivers/mmc/mmc.c
>> @@ -219,6 +219,11 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
>>   
>>   	return ret;
>>   }
>> +
>> +int mmc_execute_tuning(struct mmc *mmc, uint opcode)
>> +{
>> +	return mmc->cfg->ops->execute_tuning(mmc, opcode);
> Doesn't need to check about execute_tuing callback function?
>
Yes it should. However this has been removed for v2. Simon pointed out 
that new features should support only the driver model.
>> +}
>>   #endif
>>   
>>   int mmc_send_status(struct mmc *mmc, int timeout)
>> diff --git a/include/mmc.h b/include/mmc.h
>> index 097a685..dab68c5 100644
>> --- a/include/mmc.h
>> +++ b/include/mmc.h
>> @@ -375,6 +375,15 @@ struct dm_mmc_ops {
>>   	 * @return 0 if write-enabled, 1 if write-protected, -ve on error
>>   	 */
>>   	int (*get_wp)(struct udevice *dev);
>> +
>> +	/**
>> +	 * execute_tuning() - Start the tuning process
>> +	 *
>> +	 * @dev:	Device to start the tuning
>> +	 * @opcode:	Command opcode to send
>> +	 * @return 0 if OK, -ve on error
>> +	 */
>> +	int (*execute_tuning)(struct udevice *dev, uint opcode);
>>   };
>>   
>>   #define mmc_get_ops(dev)        ((struct dm_mmc_ops *)(dev)->driver->ops)
>> @@ -385,12 +394,14 @@ int dm_mmc_set_ios(struct udevice *dev);
>>   int dm_mmc_set_vdd(struct udevice *dev, bool enable);
>>   int dm_mmc_get_cd(struct udevice *dev);
>>   int dm_mmc_get_wp(struct udevice *dev);
>> +int dm_mmc_execute_tuning(struct udevice *dev, uint opcode);
>>   
>>   /* Transition functions for compatibility */
>>   int mmc_set_ios(struct mmc *mmc);
>>   int mmc_set_vdd(struct mmc *mmc, bool enable);
>>   int mmc_getcd(struct mmc *mmc);
>>   int mmc_getwp(struct mmc *mmc);
>> +int mmc_execute_tuning(struct mmc *mmc, uint opcode);
>>   
>>   #else
>>   struct mmc_ops {
>> @@ -401,6 +412,7 @@ struct mmc_ops {
>>   	int (*set_vdd)(struct mmc *mmc, bool enable);
>>   	int (*getcd)(struct mmc *mmc);
>>   	int (*getwp)(struct mmc *mmc);
>> +	int (*execute_tuning)(struct mmc *mmc, uint opcode);
>>   };
>>   #endif
>>   
>>
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 10/22] mmc: refactor MMC startup to make it easier to support new modes
  2017-05-25 14:40       ` Jean-Jacques Hiblot
@ 2017-05-26  1:12         ` Jaehoon Chung
  0 siblings, 0 replies; 85+ messages in thread
From: Jaehoon Chung @ 2017-05-26  1:12 UTC (permalink / raw)
  To: u-boot

On 05/25/2017 11:40 PM, Jean-Jacques Hiblot wrote:
> Hi,
> 
> 
> On 25/05/2017 14:25, Jaehoon Chung wrote:
>> On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
>>> The MMC startup process currently handles 4 modes. To make it easier to
>>> add support for more modes, let's make the process more generic and use a
>>> list of the modes to try.
>>> The major functional change is that when a mode fails we try the next one.
>>> Not all modes are tried, only those supported by the card and the host.
>>>
>>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
>>> ---
>>>   drivers/mmc/mmc.c | 238 +++++++++++++++++++++++++++++++++---------------------
>>>   include/mmc.h     |  15 +++-
>>>   2 files changed, 157 insertions(+), 96 deletions(-)
>>>
>>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>>> index f42a0fe..2931871 100644
>>> --- a/drivers/mmc/mmc.c
>>> +++ b/drivers/mmc/mmc.c
>>> @@ -200,6 +200,7 @@ static int mmc_select_mode(struct mmc *mmc, enum bus_mode mode)
>>>   {
>>>       mmc->selected_mode = mode;
>>>       mmc->tran_speed = mmc_mode2freq(mmc, mode);
>>> +    mmc->ddr_mode = mmc_is_mode_ddr(mode);
>>>       debug("selecting mode %s (freq : %d MHz)\n", mmc_mode_name(mode),
>>>             mmc->tran_speed / 1000000);
>>>       return 0;
>>> @@ -602,11 +603,46 @@ int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
>>>     }
>>>   -static int mmc_change_freq(struct mmc *mmc)
>>> +static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode)
>>>   {
>>> -    ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
>>> -    char cardtype;
>>>       int err;
>>> +    int speed_bits;
>>> +    ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
>>> +
>>> +    switch (mode) {
>>> +    case MMC_HS:
>>> +    case MMC_HS_52:
>>> +    case MMC_DDR_52:
>>> +          speed_bits = EXT_CSD_TIMING_HS;
>>> +    case MMC_LEGACY:
>>> +          speed_bits = EXT_CSD_TIMING_LEGACY;
>>> +          break;
>>> +    default:
>>> +          return -EINVAL;
>>> +    }
>>> +    err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
>>> +             speed_bits);
>>> +    if (err)
>>> +        return err;
>>> +
>>> +    if ((mode == MMC_HS) || (mode == MMC_HS_52)) {
>>> +        /* Now check to see that it worked */
>>> +        err = mmc_send_ext_csd(mmc, test_csd);
>>> +        if (err)
>>> +            return err;
>>> +
>>> +        /* No high-speed support */
>>> +        if (!test_csd[EXT_CSD_HS_TIMING])
>>> +            return -ENOTSUPP;
>>> +    }
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int mmc_get_capabilities(struct mmc *mmc)
>>> +{
>>> +    u8 *ext_csd = mmc->ext_csd;
>>> +    char cardtype;
>>>         mmc->card_caps = MMC_MODE_1BIT;
>>>   @@ -617,38 +653,23 @@ static int mmc_change_freq(struct mmc *mmc)
>>>       if (mmc->version < MMC_VERSION_4)
>>>           return 0;
>>>   -    mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
>>> -
>>> -    err = mmc_send_ext_csd(mmc, ext_csd);
>>> +    if (!ext_csd) {
>>> +        error("No ext_csd found!\n"); /* this should enver happen */
>>> +        return -ENOTSUPP;
>>> +    }
>>>   -    if (err)
>>> -        return err;
>>> +    mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
>>>         cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0xf;
>>>   -    err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);
>>> -
>>> -    if (err)
>>> -        return err;
>>> -
>>> -    /* Now check to see that it worked */
>>> -    err = mmc_send_ext_csd(mmc, ext_csd);
>>> -
>>> -    if (err)
>>> -        return err;
>>> -
>>> -    /* No high-speed support */
>>> -    if (!ext_csd[EXT_CSD_HS_TIMING])
>>> -        return 0;
>>> -
>>>       /* High Speed is set, there are two types: 52MHz and 26MHz */
>>>       if (cardtype & EXT_CSD_CARD_TYPE_52) {
>>> -        if (cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V)
>>> +        if (cardtype & EXT_CSD_CARD_TYPE_DDR_52)
>>>               mmc->card_caps |= MMC_MODE_DDR_52MHz;
>>> -        mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
>>> -    } else {
>>> -        mmc->card_caps |= MMC_MODE_HS;
>>> +        mmc->card_caps |= MMC_MODE_HS_52MHz;
>>>       }
>>> +    if (cardtype & EXT_CSD_CARD_TYPE_26)
>>> +        mmc->card_caps |= MMC_MODE_HS;
>>>         return 0;
>>>   }
>>> @@ -1320,33 +1341,58 @@ static int mmc_read_and_compare_ext_csd(struct mmc *mmc)
>>>   }
>>>     -static int mmc_select_bus_freq_width(struct mmc *mmc)
>>> +static const struct mode_width_tuning mmc_modes_by_pref[] = {
>>> +    {
>>> +        .mode = MMC_HS_200,
>>> +        .widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
>>> +    },
>>> +    {
>>> +        .mode = MMC_DDR_52,
>>> +        .widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
>>> +    },
>>> +    {
>>> +        .mode = MMC_HS_52,
>>> +        .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
>>> +    },
>>> +    {
>>> +        .mode = MMC_HS,
>>> +        .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
>>> +    },
>>> +    {
>>> +        .mode = MMC_LEGACY,
>>> +        .widths = MMC_MODE_8BIT | MMC_MODE_4BIT | MMC_MODE_1BIT,
>>> +    }
>>> +};
>>> +#define for_each_mmc_mode_by_pref(caps, mwt) \
>>> +    for (mwt = mmc_modes_by_pref;\
>>> +        mwt < mmc_modes_by_pref + ARRAY_SIZE(mmc_modes_by_pref);\
>>> +        mwt++) \
>>> +        if (caps & MMC_CAP(mwt->mode))
>>> +
>>> +static const struct ext_csd_bus_width {
>>> +    uint cap;
>>> +    bool is_ddr;
>>> +    uint ext_csd_bits;
>>> +} ext_csd_bus_width[] = {
>>> +    {MMC_MODE_8BIT, true, EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR},
>>> +    {MMC_MODE_4BIT, true, EXT_CSD_BUS_WIDTH_4 | EXT_CSD_DDR},
>>> +    {MMC_MODE_8BIT, false, EXT_CSD_BUS_WIDTH_8},
>>> +    {MMC_MODE_4BIT, false, EXT_CSD_BUS_WIDTH_4},
>>> +    {MMC_MODE_1BIT, false, EXT_CSD_BUS_WIDTH_1},
>>> +};
>>> +#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);\
>>> +        ecbv++) \
>>> +        if ((ddr == ecbv->is_ddr) && (caps & ecbv->cap))
>>> +
>>> +static int mmc_select_mode_and_width(struct mmc *mmc)
>>>   {
>>> -    /* An array of possible bus widths in order of preference */
>>> -    static const unsigned ext_csd_bits[] = {
>>> -        EXT_CSD_DDR_BUS_WIDTH_8,
>>> -        EXT_CSD_DDR_BUS_WIDTH_4,
>>> -        EXT_CSD_BUS_WIDTH_8,
>>> -        EXT_CSD_BUS_WIDTH_4,
>>> -        EXT_CSD_BUS_WIDTH_1,
>>> -    };
>>> -    /* An array to map CSD bus widths to host cap bits */
>>> -    static const unsigned ext_to_hostcaps[] = {
>>> -        [EXT_CSD_DDR_BUS_WIDTH_4] =
>>> -            MMC_MODE_DDR_52MHz | MMC_MODE_4BIT,
>>> -        [EXT_CSD_DDR_BUS_WIDTH_8] =
>>> -            MMC_MODE_DDR_52MHz | MMC_MODE_8BIT,
>>> -        [EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT,
>>> -        [EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT,
>>> -    };
>>> -    /* An array to map chosen bus width to an integer */
>>> -    static const unsigned widths[] = {
>>> -        8, 4, 8, 4, 1,
>>> -    };
>>>       int err;
>>> -    int idx;
>>> +    const struct mode_width_tuning *mwt;
>>> +    const struct ext_csd_bus_width *ecbw;
>>>   -    err = mmc_change_freq(mmc);
>>> +    err = mmc_get_capabilities(mmc);
>>>       if (err)
>>>           return err;
>>>   @@ -1357,60 +1403,64 @@ static int mmc_select_bus_freq_width(struct mmc *mmc)
>>>       if (mmc->version < MMC_VERSION_4)
>>>           return 0;
>>>   +
>>>       if (!mmc->ext_csd) {
>>>           error("No ext_csd found!\n"); /* this should enver happen */
>>>           return -ENOTSUPP;
>>>       }
>>>   -    for (idx = 0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
>>> -        unsigned int extw = ext_csd_bits[idx];
>>> -        unsigned int caps = ext_to_hostcaps[extw];
>>> +    for_each_mmc_mode_by_pref(mmc->card_caps, mwt) {
>>> +        for_each_supported_width(mmc->card_caps & mwt->widths,
>>> +                     mmc_is_mode_ddr(mwt->mode), ecbw) {
>>> +            debug("trying mode %s width %d (at %d MHz)\n",
>>> +                  mmc_mode_name(mwt->mode),
>>> +                  bus_width(ecbw->cap),
>>> +                  mmc_mode2freq(mmc, mwt->mode) / 1000000);
>>>   -        /*
>>> -          * If the bus width is still not changed,
>>> -          * don't try to set the default again.
>>> -          * Otherwise, recover from switch attempts
>>> -          * by switching to 1-bit bus width.
>>> -          */
>>> -        if (extw == EXT_CSD_BUS_WIDTH_1 &&
>>> -            mmc->bus_width == 1) {
>>> -            err = 0;
>>> -            break;
>>> -        }
>>> -
>>> -        /*
>>> -          * Check to make sure the card and controller support
>>> -          * these capabilities
>>> -          */
>>> -        if ((mmc->card_caps & caps) != caps)
>>> -            continue;
>>> -
>>> -        err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
>>> -                EXT_CSD_BUS_WIDTH, extw);
>>> +            /* configure the bus width (card + host) */
>>> +            err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
>>> +                EXT_CSD_BUS_WIDTH,
>>> +                ecbw->ext_csd_bits & ~EXT_CSD_DDR);
>>> +            if (err)
>>> +                goto error;
>>> +            mmc_set_bus_width(mmc, bus_width(ecbw->cap));
>>>   -        if (err)
>>> -            continue;
>>> +            /* 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) {
>>> +                err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
>>> +                    EXT_CSD_BUS_WIDTH, ecbw->ext_csd_bits);
>>> +                if (err)
>>> +                    goto error;
>>> +            }
>>>   -        mmc->ddr_mode = (caps & MMC_MODE_DDR_52MHz) ? 1 : 0;
>>> -        mmc_set_bus_width(mmc, widths[idx]);
>>> +            /* configure the bus mode (host) */
>>> +            mmc_select_mode(mmc, mwt->mode);
>>> +            mmc_set_clock(mmc, mmc->tran_speed);
>>>   -        err = mmc_read_and_compare_ext_csd(mmc);
>>> -        if (!err)
>>> -            break;
>>> +            /* do a transfer to check the configuration */
>>> +            err = mmc_read_and_compare_ext_csd(mmc);
>>> +            if (!err)
>>> +                return 0;
>>> +error:
>>> +            /* if an error occured, revert to a safer bus mode */
>>> +            mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
>>> +                   EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_1);
>>> +            mmc_select_mode(mmc, MMC_LEGACY);
>>> +            mmc_set_bus_width(mmc, 1);
>>> +        }
>>>       }
>>>   -    if (err)
>>> -        return err;
>>> -
>>> -    if (mmc->card_caps & MMC_MODE_HS_52MHz) {
>>> -        if (mmc->ddr_mode)
>>> -            mmc_select_mode(mmc, MMC_DDR_52);
>>> -        else
>>> -            mmc_select_mode(mmc, MMC_HS_52);
>>> -    } else if (mmc->card_caps & MMC_MODE_HS)
>>> -        mmc_select_mode(mmc, MMC_HS);
>>> +    error("unable to select a mode\n");
>>>   -    return err;
>>> +    return -ENOTSUPP;
>>>   }
>>>     static int mmc_startup_v4(struct mmc *mmc)
>>> @@ -1747,7 +1797,7 @@ static int mmc_startup(struct mmc *mmc)
>>>       if (IS_SD(mmc))
>>>           err = sd_select_mode_and_width(mmc);
>>>       else
>>> -        err = mmc_select_bus_freq_width(mmc);
>>> +        err = mmc_select_mode_and_width(mmc);
>>>         if (err)
>>>           return err;
>>> diff --git a/include/mmc.h b/include/mmc.h
>>> index 1ffa7ec..3c6971d 100644
>>> --- a/include/mmc.h
>>> +++ b/include/mmc.h
>>> @@ -213,9 +213,10 @@
>>>   #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 */
>>> -#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        4    /* Card is in DDR mode */
>> Why do you change to 4 as DDR mode?
> It's a flag to add to EXT_CSD_BUS_WIDTH_x. for example EXT_CSD_BUS_WIDTH_4 | EXT_CSD_DDR = 1 | 4 = 5

I want to maintain the original flag values..because it's specified value at spec.
Someone can confuse about value 4 when just see this define.
(According to spec, value 4 is reserved.)

Best Regards,
Jaehoon Chung

> 
> JJ
>>
>>>   +#define EXT_CSD_TIMING_LEGACY    0    /* no high speed */
>>> +#define EXT_CSD_TIMING_HS    1    /* HS */
>>>   #define EXT_CSD_BOOT_ACK_ENABLE            (1 << 6)
>>>   #define EXT_CSD_BOOT_PARTITION_ENABLE        (1 << 3)
>>>   #define EXT_CSD_PARTITION_ACCESS_ENABLE        (1 << 0)
>>> @@ -424,6 +425,16 @@ enum bus_mode {
>>>     const char *mmc_mode_name(enum bus_mode mode);
>>>   void mmc_dump_capabilities(const char *text, uint caps);
>>> +
>>> +static inline bool mmc_is_mode_ddr(enum bus_mode mode)
>>> +{
>>> +    if ((mode == MMC_DDR_52) || (mode == UHS_DDR50))
>>> +        return true;
>>> +    else
>>> +        return false;
>>> +}
>>> +
>>> +
>>>   /*
>>>    * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device
>>>    * with mmc_get_mmc_dev().
>>>
>>
> 
> 
> 
> 

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-05-25  7:41       ` Jaehoon Chung
  2017-05-25 14:42         ` Jean-Jacques Hiblot
@ 2017-06-02 16:46         ` Jean-Jacques Hiblot
  2017-06-16 10:00         ` Jean-Jacques Hiblot
  2 siblings, 0 replies; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-06-02 16:46 UTC (permalink / raw)
  To: u-boot



On 25/05/2017 09:41, Jaehoon Chung wrote:
> Hi,
>
> On 05/24/2017 12:24 AM, Jean-Jacques Hiblot wrote:
>> Hi,
>>
>>
>> On 18/05/2017 06:27, Jaehoon Chung wrote:
>>> Hi,
>>>
>>> On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
>>>> This series brings support for HS200 and UHS modes to the mmc core.
>>>> It has been tested with the hsmmc driver on several platforms (DRA7,
>>>> AM57x, AM437x, beaglebone black). Some modifications are required in
>>>> the host driver to take advantage of this (voltage switching, tuning).
>>>> The changes to the host driver will be posted a another series as this
>>>> one is already long enough.
>>>>
>>>> The series starts with a small refactoring of th sd/mmc startup. The first 4 commits
>>>> are mostly moving code around with little or no functionnal change.
>>>>
>>>> Then the notion of "mode" is introduced. Until now, this information wasn't
>>>> kept in struct mmc. Only the clock and a flag for ddr was kept. Later the mode
>>>> information will be used to select the clock frequency, the ddr flag and the
>>>> tuning procedure. It will be also be check against the host capabilities.
>>>>
>>>> Then comes the big refactoring job in:
>>>> "mmc: refactor MMC startup to make it easier to support new modes" and
>>>> "mmc: refactor SD startup to make it easier to support new modes"
>>>> Since the number of modes is increasing, it makes sense to try them in a more
>>>> organized way. those commits use a list of supported modes and iterate through
>>>> them to find the best working one. It also allows to switch more easilly from
>>>> one mode to another (switching from HS200 to DDR52 to access boot partitions for example)
>>>>
>>>> Then there are a couple of new callback added to:
>>>> - enable/disable Vdd
>>>> - check if the card is busy (used during UHS voltage switching)
>>>> - select the IO voltage
>>>>
>>>> Then Power cycle is added. Without power cycle, if a UHS card fails to enumerate in
>>>> UHS mode, it can't fall back to high speed mode and card enumeration will fail.
>>>>
>>>> And finally the last commits add the support for HS200 and UHS.
>>>> I haven't been able to test the UHS SDR104 mode by lack of compatible sdcard.
>>> After testing my targets, some boards don't work fine..So i'm checking this problem..
>> Jaehoon,
>>
>> what kind of issues are you running into and on what platforms ?
>> So far, besides the items brought-up by the reviews, there are 2 issues that are in the pipe for the next version:
>>   * signal voltage selection is not done for the MMCs only for SDs.
>>   * I noticed a timing constraint in voltage selection for SDs that can be a problem when trying a UHS mode with some SDs (seen only with Sandisk Ultra  64Gb micro SD class I) :  the voltage must be switched quickly after the cmd SWITCH_UHS18V has been sent, making debug messages in that context a problem. With this SD I've been able to check that SDR104 is working.
> How about making the "testing-hs200-uhs" branch for this? It needs to test more..
Jaehoon,

Have you been able to track down the issue you had with your boards ? 
Next week I can borrow some boards if it can help (at91 and imx6 based), 
have they been part of your tests ?

Also I set up a repository with the code for testing:
git at github.com:jjhiblot/u-boot.git testing-hs200-uhs_v2

If you have a omap5 based board (dra7 or am57), you can test with this 
branch that also includes the host support for high speed modes:
git at github.com:jjhiblot/u-boot.git high_speed_hsmmc

Regards,

Jean-jacques


****
> I guess my target doesn't do the voltage change..i'm doing for ufs driver on u-boot in my local..
> So i didn't see fully..today i have a free time..So i'm doing full review other thing..and about pending patches.
>
> Thanks for waiting me.. :)
>
> Best Regards,
> Jaehoon Chung
>
>> Jean-Jacques
>>>> With this in place and the required changes in the HSMMC (including DAM), we observe significant
>>>> improvements in the performances on a DRA7 evm:
>>>> eMMC HS200: 130 MB/s
>>>> eMMC DDR52: 80 MB/s
>>>> sd   SDR50: 80 MB/s
>>>>
>>>> cheers,
>>>>
>>>> Jean-Jacques
>>>>
>>>>
>>>> Jean-Jacques Hiblot (18):
>>>>     mmc: split mmc_startup()
>>>>     mmc: move the MMC startup for version above v4.0 in a separate
>>>>       function
>>>>     mmc: make ext_csd part of struct mmc
>>>>     mmc: add a function to read and test the ext csd (mmc >= 4)
>>>>     mmc: introduces mmc modes.
>>>>     mmc: Add a fonction to dump the mmc capabilities
>>>>     mmc: use mmc modes to select the correct bus speed
>>>>     cmd: mmc: display the mode name and current bus speed in the mmc info
>>>>     mmc: refactor SD startup to make it easier to support new modes
>>>>     mmc: refactor MMC startup to make it easier to support new modes
>>>>     mmc: make mmc_set_ios() return status
>>>>     mmc: add power cyle support in mmc core
>>>>     mmc: add a new mmc parameter to disable mmc clock
>>>>     mmc: Add a execute_tuning() callback to the mmc operations.
>>>>     mmc: add HS200 support in MMC core
>>>>     mmc: Add a new callback function to check if the card is busy
>>>>     mmc: Add support for UHS modes
>>>>     mmc: Change mode when switching to a boot partition
>>>>
>>>> Kishon Vijay Abraham I (3):
>>>>     mmc: Enable signal voltage to be selected from mmc core
>>>>     mmc: Add a new callback function to enable/disable vdd
>>>>     mmc: disable the mmc clock during power off
>>>>
>>>> Vignesh R (1):
>>>>     mmc: Retry some MMC cmds on failure
>>>>
>>>>    cmd/mmc.c                |    3 +-
>>>>    drivers/mmc/fsl_esdhc.c  |    2 +-
>>>>    drivers/mmc/mmc-uclass.c |   42 ++
>>>>    drivers/mmc/mmc.c        | 1220 +++++++++++++++++++++++++++++++++-------------
>>>>    include/mmc.h            |  138 +++++-
>>>>    5 files changed, 1058 insertions(+), 347 deletions(-)
>>>>
>>
>>
>>
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 14/22] mmc: add power cyle support in mmc core
  2017-05-25 12:35     ` Jaehoon Chung
  2017-05-25 14:50       ` Jean-Jacques Hiblot
@ 2017-06-15 16:13       ` Jean-Jacques Hiblot
  1 sibling, 0 replies; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-06-15 16:13 UTC (permalink / raw)
  To: u-boot

Hi Jaehoon,


On 25/05/2017 14:35, Jaehoon Chung wrote:
> On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
>> mmc/sd specification requires vdd to be disabled for 1 ms
>> and then enabled again during power cycle. Add a
>> function in mmc core to perform power cycle and set
>> the io signal to it's initial state.
>>
>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
>> ---
>>   drivers/mmc/mmc.c | 50 +++++++++++++++++++++++++++++++++++++++++---------
>>   1 file changed, 41 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>> index d40a22b..032260b 100644
>> --- a/drivers/mmc/mmc.c
>> +++ b/drivers/mmc/mmc.c
>> @@ -30,6 +30,7 @@ static const unsigned int sd_au_size[] = {
>>   	SZ_16M / 512,	(SZ_16M + SZ_8M) / 512,	SZ_32M / 512,	SZ_64M / 512,
>>   };
>>   static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
>> +static void mmc_power_cycle(struct mmc *mmc);
>>   
>>   #if CONFIG_IS_ENABLED(MMC_TINY)
>>   static struct mmc mmc_static;
>> @@ -1915,6 +1916,45 @@ static int mmc_power_init(struct mmc *mmc)
>>   	return 0;
>>   }
>>   
>> +static void mmc_set_initial_state(struct mmc *mmc)
>> +{
>> +	int err;
>> +
>> +	/* First try to set 3.3V. If it fails set to 1.8V */
>> +	err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
>> +	if (err != 0)
>> +		err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
>> +	if (err != 0)
>> +		printf("failed to set signal voltage\n");
>> +
>> +	mmc_set_bus_width(mmc, 1);
>> +	mmc_set_clock(mmc, 1);
>> +	mmc_select_mode(mmc, MMC_LEGACY);
>> +}
>> +
>> +static void mmc_power_up(struct mmc *mmc)
>> +{
>> +	mmc_set_initial_state(mmc);
>> +	mmc_set_vdd(mmc, true);
> mmc_set_vdd has the return value..but there are no usage anywhere..
> if this is correct, mmc_set_vdd can be *void* type.
>
>> +	udelay(10000);
>> +}
>> +
>> +static void mmc_power_off(struct mmc *mmc)
>> +{
>> +	mmc_set_vdd(mmc, false);
>> +}
>> +
>> +static void mmc_power_cycle(struct mmc *mmc)
>> +{
>> +	mmc_power_off(mmc);
>> +	/*
>> +	 * SD spec recommends at least 1ms of delay. Let's wait for 2ms
>> +	 * to be on the safer side.
>> +	 */
> Could you put the SD spec version and about which part...?
> I didn't find the 2ms so..i want to see the spec about 2ms.
The requirement for 1ms is found in the simplified specifications 
"Part1_Physical_Layer_Simplified_Specification_Ver6.00.pdf":

[...]
6.4.1.5 Power Down and Power Cycle
When the host shuts down the power, the card VDD shall be lowered to 
less than 0.5Volt for a minimum period of 1ms.
[....]

2ms is just to be on the safer side.

JJ

>
>> +	udelay(2000);
>> +	mmc_power_up(mmc);
>> +}
>> +
>>   int mmc_start_init(struct mmc *mmc)
>>   {
>>   	bool no_card;
>> @@ -1952,16 +1992,8 @@ int mmc_start_init(struct mmc *mmc)
>>   		return err;
>>   #endif
>>   	mmc->ddr_mode = 0;
>> -	mmc_set_vdd(mmc, true);
>> -	/* First try to set 3.3V. If it fails set to 1.8V */
>> -	err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330);
>> -	if (err != 0)
>> -		err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
>> -	if (err != 0)
>> -		printf("failed to set signal voltage\n");
>>   
>> -	mmc_set_bus_width(mmc, 1);
>> -	mmc_set_clock(mmc, 1);
>> +	mmc_power_cycle(mmc);
>>   
>>   	/* Reset the Card */
>>   	err = mmc_go_idle(mmc);
>>
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-05-25  7:41       ` Jaehoon Chung
  2017-05-25 14:42         ` Jean-Jacques Hiblot
  2017-06-02 16:46         ` Jean-Jacques Hiblot
@ 2017-06-16 10:00         ` Jean-Jacques Hiblot
  2017-06-29  9:59           ` Jaehoon Chung
  2 siblings, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-06-16 10:00 UTC (permalink / raw)
  To: u-boot

Hi Jaehoon,


On 25/05/2017 09:41, Jaehoon Chung wrote:
> Hi,
>
> On 05/24/2017 12:24 AM, Jean-Jacques Hiblot wrote:
>> Hi,
>>
>>
>> On 18/05/2017 06:27, Jaehoon Chung wrote:
>>> Hi,
>>>
>>> On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
>>>> This series brings support for HS200 and UHS modes to the mmc core.
>>>> It has been tested with the hsmmc driver on several platforms (DRA7,
>>>> AM57x, AM437x, beaglebone black). Some modifications are required in
>>>> the host driver to take advantage of this (voltage switching, tuning).
>>>> The changes to the host driver will be posted a another series as this
>>>> one is already long enough.
>>>>
>>>> The series starts with a small refactoring of th sd/mmc startup. The first 4 commits
>>>> are mostly moving code around with little or no functionnal change.
>>>>
>>>> Then the notion of "mode" is introduced. Until now, this information wasn't
>>>> kept in struct mmc. Only the clock and a flag for ddr was kept. Later the mode
>>>> information will be used to select the clock frequency, the ddr flag and the
>>>> tuning procedure. It will be also be check against the host capabilities.
>>>>
>>>> Then comes the big refactoring job in:
>>>> "mmc: refactor MMC startup to make it easier to support new modes" and
>>>> "mmc: refactor SD startup to make it easier to support new modes"
>>>> Since the number of modes is increasing, it makes sense to try them in a more
>>>> organized way. those commits use a list of supported modes and iterate through
>>>> them to find the best working one. It also allows to switch more easilly from
>>>> one mode to another (switching from HS200 to DDR52 to access boot partitions for example)
>>>>
>>>> Then there are a couple of new callback added to:
>>>> - enable/disable Vdd
>>>> - check if the card is busy (used during UHS voltage switching)
>>>> - select the IO voltage
>>>>
>>>> Then Power cycle is added. Without power cycle, if a UHS card fails to enumerate in
>>>> UHS mode, it can't fall back to high speed mode and card enumeration will fail.
>>>>
>>>> And finally the last commits add the support for HS200 and UHS.
>>>> I haven't been able to test the UHS SDR104 mode by lack of compatible sdcard.
>>> After testing my targets, some boards don't work fine..So i'm checking this problem..
>> Jaehoon,
>>
>> what kind of issues are you running into and on what platforms ?
>> So far, besides the items brought-up by the reviews, there are 2 issues that are in the pipe for the next version:
>>   * signal voltage selection is not done for the MMCs only for SDs.
>>   * I noticed a timing constraint in voltage selection for SDs that can be a problem when trying a UHS mode with some SDs (seen only with Sandisk Ultra  64Gb micro SD class I) :  the voltage must be switched quickly after the cmd SWITCH_UHS18V has been sent, making debug messages in that context a problem. With this SD I've been able to check that SDR104 is working.
> How about making the "testing-hs200-uhs" branch for this? It needs to test more..
> I guess my target doesn't do the voltage change..i'm doing for ufs driver on u-boot in my local..
> So i didn't see fully..today i have a free time..So i'm doing full review other thing..and about pending patches.
>
> Thanks for waiting me.. :)

I updated the branches for testing in my github repo 
(https://github.com/jjhiblot/u-boot.git )
branch testing-hs200-uhs_v2 touches only the MMC core
branch high_speed_hsmmc_v2 implements the required bit for th HSMMC 
found on TI boards

Most of the comments (if not all of them) have been taken in account and 
the branches have been rebased on top of u-boot master.

Will you be able to do some testing and let me know if there are other 
things to change ? Don't hesitate to let me know what boards it breaks 
(if any), I'll do my best to get my hands on one and help with the 
debugging.

Thanks,

JJ
>
> Best Regards,
> Jaehoon Chung
>
>> Jean-Jacques
>>>> With this in place and the required changes in the HSMMC (including DAM), we observe significant
>>>> improvements in the performances on a DRA7 evm:
>>>> eMMC HS200: 130 MB/s
>>>> eMMC DDR52: 80 MB/s
>>>> sd   SDR50: 80 MB/s
>>>>
>>>> cheers,
>>>>
>>>> Jean-Jacques
>>>>
>>>>
>>>> Jean-Jacques Hiblot (18):
>>>>     mmc: split mmc_startup()
>>>>     mmc: move the MMC startup for version above v4.0 in a separate
>>>>       function
>>>>     mmc: make ext_csd part of struct mmc
>>>>     mmc: add a function to read and test the ext csd (mmc >= 4)
>>>>     mmc: introduces mmc modes.
>>>>     mmc: Add a fonction to dump the mmc capabilities
>>>>     mmc: use mmc modes to select the correct bus speed
>>>>     cmd: mmc: display the mode name and current bus speed in the mmc info
>>>>     mmc: refactor SD startup to make it easier to support new modes
>>>>     mmc: refactor MMC startup to make it easier to support new modes
>>>>     mmc: make mmc_set_ios() return status
>>>>     mmc: add power cyle support in mmc core
>>>>     mmc: add a new mmc parameter to disable mmc clock
>>>>     mmc: Add a execute_tuning() callback to the mmc operations.
>>>>     mmc: add HS200 support in MMC core
>>>>     mmc: Add a new callback function to check if the card is busy
>>>>     mmc: Add support for UHS modes
>>>>     mmc: Change mode when switching to a boot partition
>>>>
>>>> Kishon Vijay Abraham I (3):
>>>>     mmc: Enable signal voltage to be selected from mmc core
>>>>     mmc: Add a new callback function to enable/disable vdd
>>>>     mmc: disable the mmc clock during power off
>>>>
>>>> Vignesh R (1):
>>>>     mmc: Retry some MMC cmds on failure
>>>>
>>>>    cmd/mmc.c                |    3 +-
>>>>    drivers/mmc/fsl_esdhc.c  |    2 +-
>>>>    drivers/mmc/mmc-uclass.c |   42 ++
>>>>    drivers/mmc/mmc.c        | 1220 +++++++++++++++++++++++++++++++++-------------
>>>>    include/mmc.h            |  138 +++++-
>>>>    5 files changed, 1058 insertions(+), 347 deletions(-)
>>>>
>>
>>
>>
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-06-16 10:00         ` Jean-Jacques Hiblot
@ 2017-06-29  9:59           ` Jaehoon Chung
  2017-07-26 11:33             ` Kever Yang
  0 siblings, 1 reply; 85+ messages in thread
From: Jaehoon Chung @ 2017-06-29  9:59 UTC (permalink / raw)
  To: u-boot

On 06/16/2017 07:00 PM, Jean-Jacques Hiblot wrote:
> Hi Jaehoon,
> 
> 
> On 25/05/2017 09:41, Jaehoon Chung wrote:
>> Hi,
>>
>> On 05/24/2017 12:24 AM, Jean-Jacques Hiblot wrote:
>>> Hi,
>>>
>>>
>>> On 18/05/2017 06:27, Jaehoon Chung wrote:
>>>> Hi,
>>>>
>>>> On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
>>>>> This series brings support for HS200 and UHS modes to the mmc core.
>>>>> It has been tested with the hsmmc driver on several platforms (DRA7,
>>>>> AM57x, AM437x, beaglebone black). Some modifications are required in
>>>>> the host driver to take advantage of this (voltage switching, tuning).
>>>>> The changes to the host driver will be posted a another series as this
>>>>> one is already long enough.
>>>>>
>>>>> The series starts with a small refactoring of th sd/mmc startup. The first 4 commits
>>>>> are mostly moving code around with little or no functionnal change.
>>>>>
>>>>> Then the notion of "mode" is introduced. Until now, this information wasn't
>>>>> kept in struct mmc. Only the clock and a flag for ddr was kept. Later the mode
>>>>> information will be used to select the clock frequency, the ddr flag and the
>>>>> tuning procedure. It will be also be check against the host capabilities.
>>>>>
>>>>> Then comes the big refactoring job in:
>>>>> "mmc: refactor MMC startup to make it easier to support new modes" and
>>>>> "mmc: refactor SD startup to make it easier to support new modes"
>>>>> Since the number of modes is increasing, it makes sense to try them in a more
>>>>> organized way. those commits use a list of supported modes and iterate through
>>>>> them to find the best working one. It also allows to switch more easilly from
>>>>> one mode to another (switching from HS200 to DDR52 to access boot partitions for example)
>>>>>
>>>>> Then there are a couple of new callback added to:
>>>>> - enable/disable Vdd
>>>>> - check if the card is busy (used during UHS voltage switching)
>>>>> - select the IO voltage
>>>>>
>>>>> Then Power cycle is added. Without power cycle, if a UHS card fails to enumerate in
>>>>> UHS mode, it can't fall back to high speed mode and card enumeration will fail.
>>>>>
>>>>> And finally the last commits add the support for HS200 and UHS.
>>>>> I haven't been able to test the UHS SDR104 mode by lack of compatible sdcard.
>>>> After testing my targets, some boards don't work fine..So i'm checking this problem..
>>> Jaehoon,
>>>
>>> what kind of issues are you running into and on what platforms ?
>>> So far, besides the items brought-up by the reviews, there are 2 issues that are in the pipe for the next version:
>>>   * signal voltage selection is not done for the MMCs only for SDs.
>>>   * I noticed a timing constraint in voltage selection for SDs that can be a problem when trying a UHS mode with some SDs (seen only with Sandisk Ultra  64Gb micro SD class I) :  the voltage must be switched quickly after the cmd SWITCH_UHS18V has been sent, making debug messages in that context a problem. With this SD I've been able to check that SDR104 is working.
>> How about making the "testing-hs200-uhs" branch for this? It needs to test more..
>> I guess my target doesn't do the voltage change..i'm doing for ufs driver on u-boot in my local..
>> So i didn't see fully..today i have a free time..So i'm doing full review other thing..and about pending patches.
>>
>> Thanks for waiting me.. :)
> 
> I updated the branches for testing in my github repo (https://github.com/jjhiblot/u-boot.git )
> branch testing-hs200-uhs_v2 touches only the MMC core
> branch high_speed_hsmmc_v2 implements the required bit for th HSMMC found on TI boards

Sorry for late..I make the hs200-ufs-testing branch in u-boot-mmc repo.
I will rebase on latest u-boot. and start the testing.

Best Regards,
Jaehoon Chung

> 
> Most of the comments (if not all of them) have been taken in account and the branches have been rebased on top of u-boot master.
> 
> Will you be able to do some testing and let me know if there are other things to change ? Don't hesitate to let me know what boards it breaks (if any), I'll do my best to get my hands on one and help with the debugging.
> 
> Thanks,
> 
> JJ
>>
>> Best Regards,
>> Jaehoon Chung
>>
>>> Jean-Jacques
>>>>> With this in place and the required changes in the HSMMC (including DAM), we observe significant
>>>>> improvements in the performances on a DRA7 evm:
>>>>> eMMC HS200: 130 MB/s
>>>>> eMMC DDR52: 80 MB/s
>>>>> sd   SDR50: 80 MB/s
>>>>>
>>>>> cheers,
>>>>>
>>>>> Jean-Jacques
>>>>>
>>>>>
>>>>> Jean-Jacques Hiblot (18):
>>>>>     mmc: split mmc_startup()
>>>>>     mmc: move the MMC startup for version above v4.0 in a separate
>>>>>       function
>>>>>     mmc: make ext_csd part of struct mmc
>>>>>     mmc: add a function to read and test the ext csd (mmc >= 4)
>>>>>     mmc: introduces mmc modes.
>>>>>     mmc: Add a fonction to dump the mmc capabilities
>>>>>     mmc: use mmc modes to select the correct bus speed
>>>>>     cmd: mmc: display the mode name and current bus speed in the mmc info
>>>>>     mmc: refactor SD startup to make it easier to support new modes
>>>>>     mmc: refactor MMC startup to make it easier to support new modes
>>>>>     mmc: make mmc_set_ios() return status
>>>>>     mmc: add power cyle support in mmc core
>>>>>     mmc: add a new mmc parameter to disable mmc clock
>>>>>     mmc: Add a execute_tuning() callback to the mmc operations.
>>>>>     mmc: add HS200 support in MMC core
>>>>>     mmc: Add a new callback function to check if the card is busy
>>>>>     mmc: Add support for UHS modes
>>>>>     mmc: Change mode when switching to a boot partition
>>>>>
>>>>> Kishon Vijay Abraham I (3):
>>>>>     mmc: Enable signal voltage to be selected from mmc core
>>>>>     mmc: Add a new callback function to enable/disable vdd
>>>>>     mmc: disable the mmc clock during power off
>>>>>
>>>>> Vignesh R (1):
>>>>>     mmc: Retry some MMC cmds on failure
>>>>>
>>>>>    cmd/mmc.c                |    3 +-
>>>>>    drivers/mmc/fsl_esdhc.c  |    2 +-
>>>>>    drivers/mmc/mmc-uclass.c |   42 ++
>>>>>    drivers/mmc/mmc.c        | 1220 +++++++++++++++++++++++++++++++++-------------
>>>>>    include/mmc.h            |  138 +++++-
>>>>>    5 files changed, 1058 insertions(+), 347 deletions(-)
>>>>>
>>>
>>>
>>>
>>
> 
> 
> 
> 

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-06-29  9:59           ` Jaehoon Chung
@ 2017-07-26 11:33             ` Kever Yang
  2017-07-28 13:05               ` Jaehoon Chung
  0 siblings, 1 reply; 85+ messages in thread
From: Kever Yang @ 2017-07-26 11:33 UTC (permalink / raw)
  To: u-boot

Hi Jaehoon,


     What's the status of this patch set now?

     Can we land this patch set or the other patch set from Ziyuan Xu?

The performance for  mmc in U-Boot is really bad now, and this patch set 
has been

on list for more than two months now, I'm using the patch set from 
Ziyuan Xu locally,

but really hope the upstream can move forward.


Thanks,
- Kever
On 06/29/2017 05:59 PM, Jaehoon Chung wrote:
> On 06/16/2017 07:00 PM, Jean-Jacques Hiblot wrote:
>> Hi Jaehoon,
>>
>>
>> On 25/05/2017 09:41, Jaehoon Chung wrote:
>>> Hi,
>>>
>>> On 05/24/2017 12:24 AM, Jean-Jacques Hiblot wrote:
>>>> Hi,
>>>>
>>>>
>>>> On 18/05/2017 06:27, Jaehoon Chung wrote:
>>>>> Hi,
>>>>>
>>>>> On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
>>>>>> This series brings support for HS200 and UHS modes to the mmc core.
>>>>>> It has been tested with the hsmmc driver on several platforms (DRA7,
>>>>>> AM57x, AM437x, beaglebone black). Some modifications are required in
>>>>>> the host driver to take advantage of this (voltage switching, tuning).
>>>>>> The changes to the host driver will be posted a another series as this
>>>>>> one is already long enough.
>>>>>>
>>>>>> The series starts with a small refactoring of th sd/mmc startup. The first 4 commits
>>>>>> are mostly moving code around with little or no functionnal change.
>>>>>>
>>>>>> Then the notion of "mode" is introduced. Until now, this information wasn't
>>>>>> kept in struct mmc. Only the clock and a flag for ddr was kept. Later the mode
>>>>>> information will be used to select the clock frequency, the ddr flag and the
>>>>>> tuning procedure. It will be also be check against the host capabilities.
>>>>>>
>>>>>> Then comes the big refactoring job in:
>>>>>> "mmc: refactor MMC startup to make it easier to support new modes" and
>>>>>> "mmc: refactor SD startup to make it easier to support new modes"
>>>>>> Since the number of modes is increasing, it makes sense to try them in a more
>>>>>> organized way. those commits use a list of supported modes and iterate through
>>>>>> them to find the best working one. It also allows to switch more easilly from
>>>>>> one mode to another (switching from HS200 to DDR52 to access boot partitions for example)
>>>>>>
>>>>>> Then there are a couple of new callback added to:
>>>>>> - enable/disable Vdd
>>>>>> - check if the card is busy (used during UHS voltage switching)
>>>>>> - select the IO voltage
>>>>>>
>>>>>> Then Power cycle is added. Without power cycle, if a UHS card fails to enumerate in
>>>>>> UHS mode, it can't fall back to high speed mode and card enumeration will fail.
>>>>>>
>>>>>> And finally the last commits add the support for HS200 and UHS.
>>>>>> I haven't been able to test the UHS SDR104 mode by lack of compatible sdcard.
>>>>> After testing my targets, some boards don't work fine..So i'm checking this problem..
>>>> Jaehoon,
>>>>
>>>> what kind of issues are you running into and on what platforms ?
>>>> So far, besides the items brought-up by the reviews, there are 2 issues that are in the pipe for the next version:
>>>>    * signal voltage selection is not done for the MMCs only for SDs.
>>>>    * I noticed a timing constraint in voltage selection for SDs that can be a problem when trying a UHS mode with some SDs (seen only with Sandisk Ultra  64Gb micro SD class I) :  the voltage must be switched quickly after the cmd SWITCH_UHS18V has been sent, making debug messages in that context a problem. With this SD I've been able to check that SDR104 is working.
>>> How about making the "testing-hs200-uhs" branch for this? It needs to test more..
>>> I guess my target doesn't do the voltage change..i'm doing for ufs driver on u-boot in my local..
>>> So i didn't see fully..today i have a free time..So i'm doing full review other thing..and about pending patches.
>>>
>>> Thanks for waiting me.. :)
>> I updated the branches for testing in my github repo (https://github.com/jjhiblot/u-boot.git )
>> branch testing-hs200-uhs_v2 touches only the MMC core
>> branch high_speed_hsmmc_v2 implements the required bit for th HSMMC found on TI boards
> Sorry for late..I make the hs200-ufs-testing branch in u-boot-mmc repo.
> I will rebase on latest u-boot. and start the testing.
>
> Best Regards,
> Jaehoon Chung
>
>> Most of the comments (if not all of them) have been taken in account and the branches have been rebased on top of u-boot master.
>>
>> Will you be able to do some testing and let me know if there are other things to change ? Don't hesitate to let me know what boards it breaks (if any), I'll do my best to get my hands on one and help with the debugging.
>>
>> Thanks,
>>
>> JJ
>>> Best Regards,
>>> Jaehoon Chung
>>>
>>>> Jean-Jacques
>>>>>> With this in place and the required changes in the HSMMC (including DAM), we observe significant
>>>>>> improvements in the performances on a DRA7 evm:
>>>>>> eMMC HS200: 130 MB/s
>>>>>> eMMC DDR52: 80 MB/s
>>>>>> sd   SDR50: 80 MB/s
>>>>>>
>>>>>> cheers,
>>>>>>
>>>>>> Jean-Jacques
>>>>>>
>>>>>>
>>>>>> Jean-Jacques Hiblot (18):
>>>>>>      mmc: split mmc_startup()
>>>>>>      mmc: move the MMC startup for version above v4.0 in a separate
>>>>>>        function
>>>>>>      mmc: make ext_csd part of struct mmc
>>>>>>      mmc: add a function to read and test the ext csd (mmc >= 4)
>>>>>>      mmc: introduces mmc modes.
>>>>>>      mmc: Add a fonction to dump the mmc capabilities
>>>>>>      mmc: use mmc modes to select the correct bus speed
>>>>>>      cmd: mmc: display the mode name and current bus speed in the mmc info
>>>>>>      mmc: refactor SD startup to make it easier to support new modes
>>>>>>      mmc: refactor MMC startup to make it easier to support new modes
>>>>>>      mmc: make mmc_set_ios() return status
>>>>>>      mmc: add power cyle support in mmc core
>>>>>>      mmc: add a new mmc parameter to disable mmc clock
>>>>>>      mmc: Add a execute_tuning() callback to the mmc operations.
>>>>>>      mmc: add HS200 support in MMC core
>>>>>>      mmc: Add a new callback function to check if the card is busy
>>>>>>      mmc: Add support for UHS modes
>>>>>>      mmc: Change mode when switching to a boot partition
>>>>>>
>>>>>> Kishon Vijay Abraham I (3):
>>>>>>      mmc: Enable signal voltage to be selected from mmc core
>>>>>>      mmc: Add a new callback function to enable/disable vdd
>>>>>>      mmc: disable the mmc clock during power off
>>>>>>
>>>>>> Vignesh R (1):
>>>>>>      mmc: Retry some MMC cmds on failure
>>>>>>
>>>>>>     cmd/mmc.c                |    3 +-
>>>>>>     drivers/mmc/fsl_esdhc.c  |    2 +-
>>>>>>     drivers/mmc/mmc-uclass.c |   42 ++
>>>>>>     drivers/mmc/mmc.c        | 1220 +++++++++++++++++++++++++++++++++-------------
>>>>>>     include/mmc.h            |  138 +++++-
>>>>>>     5 files changed, 1058 insertions(+), 347 deletions(-)
>>>>>>
>>>>
>>>>
>>
>>
>>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-07-26 11:33             ` Kever Yang
@ 2017-07-28 13:05               ` Jaehoon Chung
  2017-08-25  8:16                 ` Ziyuan
  2017-09-15 13:20                 ` Jean-Jacques Hiblot
  0 siblings, 2 replies; 85+ messages in thread
From: Jaehoon Chung @ 2017-07-28 13:05 UTC (permalink / raw)
  To: u-boot

Hi Kever,

On 07/26/2017 08:33 PM, Kever Yang wrote:
> Hi Jaehoon,
> 
> 
>     What's the status of this patch set now?
> 
>     Can we land this patch set or the other patch set from Ziyuan Xu?
> 
> The performance for  mmc in U-Boot is really bad now, and this patch set has been
> 
> on list for more than two months now, I'm using the patch set from Ziyuan Xu locally,
> 
> but really hope the upstream can move forward.

Apologized for late. Will try to upstream this before releasing v2017.09.
Really sorry for late, again. Thanks for reminding this.

Best Regards,
Jaehoon Chung

> 
> 
> Thanks,
> - Kever
> On 06/29/2017 05:59 PM, Jaehoon Chung wrote:
>> On 06/16/2017 07:00 PM, Jean-Jacques Hiblot wrote:
>>> Hi Jaehoon,
>>>
>>>
>>> On 25/05/2017 09:41, Jaehoon Chung wrote:
>>>> Hi,
>>>>
>>>> On 05/24/2017 12:24 AM, Jean-Jacques Hiblot wrote:
>>>>> Hi,
>>>>>
>>>>>
>>>>> On 18/05/2017 06:27, Jaehoon Chung wrote:
>>>>>> Hi,
>>>>>>
>>>>>> On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
>>>>>>> This series brings support for HS200 and UHS modes to the mmc core.
>>>>>>> It has been tested with the hsmmc driver on several platforms (DRA7,
>>>>>>> AM57x, AM437x, beaglebone black). Some modifications are required in
>>>>>>> the host driver to take advantage of this (voltage switching, tuning).
>>>>>>> The changes to the host driver will be posted a another series as this
>>>>>>> one is already long enough.
>>>>>>>
>>>>>>> The series starts with a small refactoring of th sd/mmc startup. The first 4 commits
>>>>>>> are mostly moving code around with little or no functionnal change.
>>>>>>>
>>>>>>> Then the notion of "mode" is introduced. Until now, this information wasn't
>>>>>>> kept in struct mmc. Only the clock and a flag for ddr was kept. Later the mode
>>>>>>> information will be used to select the clock frequency, the ddr flag and the
>>>>>>> tuning procedure. It will be also be check against the host capabilities.
>>>>>>>
>>>>>>> Then comes the big refactoring job in:
>>>>>>> "mmc: refactor MMC startup to make it easier to support new modes" and
>>>>>>> "mmc: refactor SD startup to make it easier to support new modes"
>>>>>>> Since the number of modes is increasing, it makes sense to try them in a more
>>>>>>> organized way. those commits use a list of supported modes and iterate through
>>>>>>> them to find the best working one. It also allows to switch more easilly from
>>>>>>> one mode to another (switching from HS200 to DDR52 to access boot partitions for example)
>>>>>>>
>>>>>>> Then there are a couple of new callback added to:
>>>>>>> - enable/disable Vdd
>>>>>>> - check if the card is busy (used during UHS voltage switching)
>>>>>>> - select the IO voltage
>>>>>>>
>>>>>>> Then Power cycle is added. Without power cycle, if a UHS card fails to enumerate in
>>>>>>> UHS mode, it can't fall back to high speed mode and card enumeration will fail.
>>>>>>>
>>>>>>> And finally the last commits add the support for HS200 and UHS.
>>>>>>> I haven't been able to test the UHS SDR104 mode by lack of compatible sdcard.
>>>>>> After testing my targets, some boards don't work fine..So i'm checking this problem..
>>>>> Jaehoon,
>>>>>
>>>>> what kind of issues are you running into and on what platforms ?
>>>>> So far, besides the items brought-up by the reviews, there are 2 issues that are in the pipe for the next version:
>>>>>    * signal voltage selection is not done for the MMCs only for SDs.
>>>>>    * I noticed a timing constraint in voltage selection for SDs that can be a problem when trying a UHS mode with some SDs (seen only with Sandisk Ultra  64Gb micro SD class I) :  the voltage must be switched quickly after the cmd SWITCH_UHS18V has been sent, making debug messages in that context a problem. With this SD I've been able to check that SDR104 is working.
>>>> How about making the "testing-hs200-uhs" branch for this? It needs to test more..
>>>> I guess my target doesn't do the voltage change..i'm doing for ufs driver on u-boot in my local..
>>>> So i didn't see fully..today i have a free time..So i'm doing full review other thing..and about pending patches.
>>>>
>>>> Thanks for waiting me.. :)
>>> I updated the branches for testing in my github repo (https://github.com/jjhiblot/u-boot.git )
>>> branch testing-hs200-uhs_v2 touches only the MMC core
>>> branch high_speed_hsmmc_v2 implements the required bit for th HSMMC found on TI boards
>> Sorry for late..I make the hs200-ufs-testing branch in u-boot-mmc repo.
>> I will rebase on latest u-boot. and start the testing.
>>
>> Best Regards,
>> Jaehoon Chung
>>
>>> Most of the comments (if not all of them) have been taken in account and the branches have been rebased on top of u-boot master.
>>>
>>> Will you be able to do some testing and let me know if there are other things to change ? Don't hesitate to let me know what boards it breaks (if any), I'll do my best to get my hands on one and help with the debugging.
>>>
>>> Thanks,
>>>
>>> JJ
>>>> Best Regards,
>>>> Jaehoon Chung
>>>>
>>>>> Jean-Jacques
>>>>>>> With this in place and the required changes in the HSMMC (including DAM), we observe significant
>>>>>>> improvements in the performances on a DRA7 evm:
>>>>>>> eMMC HS200: 130 MB/s
>>>>>>> eMMC DDR52: 80 MB/s
>>>>>>> sd   SDR50: 80 MB/s
>>>>>>>
>>>>>>> cheers,
>>>>>>>
>>>>>>> Jean-Jacques
>>>>>>>
>>>>>>>
>>>>>>> Jean-Jacques Hiblot (18):
>>>>>>>      mmc: split mmc_startup()
>>>>>>>      mmc: move the MMC startup for version above v4.0 in a separate
>>>>>>>        function
>>>>>>>      mmc: make ext_csd part of struct mmc
>>>>>>>      mmc: add a function to read and test the ext csd (mmc >= 4)
>>>>>>>      mmc: introduces mmc modes.
>>>>>>>      mmc: Add a fonction to dump the mmc capabilities
>>>>>>>      mmc: use mmc modes to select the correct bus speed
>>>>>>>      cmd: mmc: display the mode name and current bus speed in the mmc info
>>>>>>>      mmc: refactor SD startup to make it easier to support new modes
>>>>>>>      mmc: refactor MMC startup to make it easier to support new modes
>>>>>>>      mmc: make mmc_set_ios() return status
>>>>>>>      mmc: add power cyle support in mmc core
>>>>>>>      mmc: add a new mmc parameter to disable mmc clock
>>>>>>>      mmc: Add a execute_tuning() callback to the mmc operations.
>>>>>>>      mmc: add HS200 support in MMC core
>>>>>>>      mmc: Add a new callback function to check if the card is busy
>>>>>>>      mmc: Add support for UHS modes
>>>>>>>      mmc: Change mode when switching to a boot partition
>>>>>>>
>>>>>>> Kishon Vijay Abraham I (3):
>>>>>>>      mmc: Enable signal voltage to be selected from mmc core
>>>>>>>      mmc: Add a new callback function to enable/disable vdd
>>>>>>>      mmc: disable the mmc clock during power off
>>>>>>>
>>>>>>> Vignesh R (1):
>>>>>>>      mmc: Retry some MMC cmds on failure
>>>>>>>
>>>>>>>     cmd/mmc.c                |    3 +-
>>>>>>>     drivers/mmc/fsl_esdhc.c  |    2 +-
>>>>>>>     drivers/mmc/mmc-uclass.c |   42 ++
>>>>>>>     drivers/mmc/mmc.c        | 1220 +++++++++++++++++++++++++++++++++-------------
>>>>>>>     include/mmc.h            |  138 +++++-
>>>>>>>     5 files changed, 1058 insertions(+), 347 deletions(-)
>>>>>>>
>>>>>
>>>>>
>>>
>>>
>>>
>> _______________________________________________
>> U-Boot mailing list
>> U-Boot at lists.denx.de
>> https://lists.denx.de/listinfo/u-boot
> 
> 
> 
> 
> 

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-07-28 13:05               ` Jaehoon Chung
@ 2017-08-25  8:16                 ` Ziyuan
  2017-08-27 20:10                   ` Simon Glass
  2017-09-15 13:20                 ` Jean-Jacques Hiblot
  1 sibling, 1 reply; 85+ messages in thread
From: Ziyuan @ 2017-08-25  8:16 UTC (permalink / raw)
  To: u-boot

hi Jaehoon,

On 07/28/2017 09:05 PM, Jaehoon Chung wrote:
> Hi Kever,
>
> On 07/26/2017 08:33 PM, Kever Yang wrote:
>> Hi Jaehoon,
>>
>>
>>      What's the status of this patch set now?
>>
>>      Can we land this patch set or the other patch set from Ziyuan Xu?
>>
>> The performance for  mmc in U-Boot is really bad now, and this patch set has been
>>
>> on list for more than two months now, I'm using the patch set from Ziyuan Xu locally,
>>
>> but really hope the upstream can move forward.
> Apologized for late. Will try to upstream this before releasing v2017.09.
> Really sorry for late, again. Thanks for reminding this.

*ping*
Anything update?

>
> Best Regards,
> Jaehoon Chung
>
>>
>> Thanks,
>> - Kever
>> On 06/29/2017 05:59 PM, Jaehoon Chung wrote:
>>> On 06/16/2017 07:00 PM, Jean-Jacques Hiblot wrote:
>>>> Hi Jaehoon,
>>>>
>>>>
>>>> On 25/05/2017 09:41, Jaehoon Chung wrote:
>>>>> Hi,
>>>>>
>>>>> On 05/24/2017 12:24 AM, Jean-Jacques Hiblot wrote:
>>>>>> Hi,
>>>>>>
>>>>>>
>>>>>> On 18/05/2017 06:27, Jaehoon Chung wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
>>>>>>>> This series brings support for HS200 and UHS modes to the mmc core.
>>>>>>>> It has been tested with the hsmmc driver on several platforms (DRA7,
>>>>>>>> AM57x, AM437x, beaglebone black). Some modifications are required in
>>>>>>>> the host driver to take advantage of this (voltage switching, tuning).
>>>>>>>> The changes to the host driver will be posted a another series as this
>>>>>>>> one is already long enough.
>>>>>>>>
>>>>>>>> The series starts with a small refactoring of th sd/mmc startup. The first 4 commits
>>>>>>>> are mostly moving code around with little or no functionnal change.
>>>>>>>>
>>>>>>>> Then the notion of "mode" is introduced. Until now, this information wasn't
>>>>>>>> kept in struct mmc. Only the clock and a flag for ddr was kept. Later the mode
>>>>>>>> information will be used to select the clock frequency, the ddr flag and the
>>>>>>>> tuning procedure. It will be also be check against the host capabilities.
>>>>>>>>
>>>>>>>> Then comes the big refactoring job in:
>>>>>>>> "mmc: refactor MMC startup to make it easier to support new modes" and
>>>>>>>> "mmc: refactor SD startup to make it easier to support new modes"
>>>>>>>> Since the number of modes is increasing, it makes sense to try them in a more
>>>>>>>> organized way. those commits use a list of supported modes and iterate through
>>>>>>>> them to find the best working one. It also allows to switch more easilly from
>>>>>>>> one mode to another (switching from HS200 to DDR52 to access boot partitions for example)
>>>>>>>>
>>>>>>>> Then there are a couple of new callback added to:
>>>>>>>> - enable/disable Vdd
>>>>>>>> - check if the card is busy (used during UHS voltage switching)
>>>>>>>> - select the IO voltage
>>>>>>>>
>>>>>>>> Then Power cycle is added. Without power cycle, if a UHS card fails to enumerate in
>>>>>>>> UHS mode, it can't fall back to high speed mode and card enumeration will fail.
>>>>>>>>
>>>>>>>> And finally the last commits add the support for HS200 and UHS.
>>>>>>>> I haven't been able to test the UHS SDR104 mode by lack of compatible sdcard.
>>>>>>> After testing my targets, some boards don't work fine..So i'm checking this problem..
>>>>>> Jaehoon,
>>>>>>
>>>>>> what kind of issues are you running into and on what platforms ?
>>>>>> So far, besides the items brought-up by the reviews, there are 2 issues that are in the pipe for the next version:
>>>>>>     * signal voltage selection is not done for the MMCs only for SDs.
>>>>>>     * I noticed a timing constraint in voltage selection for SDs that can be a problem when trying a UHS mode with some SDs (seen only with Sandisk Ultra  64Gb micro SD class I) :  the voltage must be switched quickly after the cmd SWITCH_UHS18V has been sent, making debug messages in that context a problem. With this SD I've been able to check that SDR104 is working.
>>>>> How about making the "testing-hs200-uhs" branch for this? It needs to test more..
>>>>> I guess my target doesn't do the voltage change..i'm doing for ufs driver on u-boot in my local..
>>>>> So i didn't see fully..today i have a free time..So i'm doing full review other thing..and about pending patches.
>>>>>
>>>>> Thanks for waiting me.. :)
>>>> I updated the branches for testing in my github repo (https://github.com/jjhiblot/u-boot.git )
>>>> branch testing-hs200-uhs_v2 touches only the MMC core
>>>> branch high_speed_hsmmc_v2 implements the required bit for th HSMMC found on TI boards
>>> Sorry for late..I make the hs200-ufs-testing branch in u-boot-mmc repo.
>>> I will rebase on latest u-boot. and start the testing.
>>>
>>> Best Regards,
>>> Jaehoon Chung
>>>
>>>> Most of the comments (if not all of them) have been taken in account and the branches have been rebased on top of u-boot master.
>>>>
>>>> Will you be able to do some testing and let me know if there are other things to change ? Don't hesitate to let me know what boards it breaks (if any), I'll do my best to get my hands on one and help with the debugging.
>>>>
>>>> Thanks,
>>>>
>>>> JJ
>>>>> Best Regards,
>>>>> Jaehoon Chung
>>>>>
>>>>>> Jean-Jacques
>>>>>>>> With this in place and the required changes in the HSMMC (including DAM), we observe significant
>>>>>>>> improvements in the performances on a DRA7 evm:
>>>>>>>> eMMC HS200: 130 MB/s
>>>>>>>> eMMC DDR52: 80 MB/s
>>>>>>>> sd   SDR50: 80 MB/s
>>>>>>>>
>>>>>>>> cheers,
>>>>>>>>
>>>>>>>> Jean-Jacques
>>>>>>>>
>>>>>>>>
>>>>>>>> Jean-Jacques Hiblot (18):
>>>>>>>>       mmc: split mmc_startup()
>>>>>>>>       mmc: move the MMC startup for version above v4.0 in a separate
>>>>>>>>         function
>>>>>>>>       mmc: make ext_csd part of struct mmc
>>>>>>>>       mmc: add a function to read and test the ext csd (mmc >= 4)
>>>>>>>>       mmc: introduces mmc modes.
>>>>>>>>       mmc: Add a fonction to dump the mmc capabilities
>>>>>>>>       mmc: use mmc modes to select the correct bus speed
>>>>>>>>       cmd: mmc: display the mode name and current bus speed in the mmc info
>>>>>>>>       mmc: refactor SD startup to make it easier to support new modes
>>>>>>>>       mmc: refactor MMC startup to make it easier to support new modes
>>>>>>>>       mmc: make mmc_set_ios() return status
>>>>>>>>       mmc: add power cyle support in mmc core
>>>>>>>>       mmc: add a new mmc parameter to disable mmc clock
>>>>>>>>       mmc: Add a execute_tuning() callback to the mmc operations.
>>>>>>>>       mmc: add HS200 support in MMC core
>>>>>>>>       mmc: Add a new callback function to check if the card is busy
>>>>>>>>       mmc: Add support for UHS modes
>>>>>>>>       mmc: Change mode when switching to a boot partition
>>>>>>>>
>>>>>>>> Kishon Vijay Abraham I (3):
>>>>>>>>       mmc: Enable signal voltage to be selected from mmc core
>>>>>>>>       mmc: Add a new callback function to enable/disable vdd
>>>>>>>>       mmc: disable the mmc clock during power off
>>>>>>>>
>>>>>>>> Vignesh R (1):
>>>>>>>>       mmc: Retry some MMC cmds on failure
>>>>>>>>
>>>>>>>>      cmd/mmc.c                |    3 +-
>>>>>>>>      drivers/mmc/fsl_esdhc.c  |    2 +-
>>>>>>>>      drivers/mmc/mmc-uclass.c |   42 ++
>>>>>>>>      drivers/mmc/mmc.c        | 1220 +++++++++++++++++++++++++++++++++-------------
>>>>>>>>      include/mmc.h            |  138 +++++-
>>>>>>>>      5 files changed, 1058 insertions(+), 347 deletions(-)
>>>>>>>>
>>>>>>
>>>>
>>>>
>>> _______________________________________________
>>> U-Boot mailing list
>>> U-Boot at lists.denx.de
>>> https://lists.denx.de/listinfo/u-boot
>>
>>
>>
>>
>
>
>

-- 
Ziyuan Xu

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-08-25  8:16                 ` Ziyuan
@ 2017-08-27 20:10                   ` Simon Glass
  2017-08-27 20:17                     ` Tom Rini
  2017-08-28  5:45                     ` Ziyuan
  0 siblings, 2 replies; 85+ messages in thread
From: Simon Glass @ 2017-08-27 20:10 UTC (permalink / raw)
  To: u-boot

Hi,

On 25 August 2017 at 02:16, Ziyuan <xzy.xu@rock-chips.com> wrote:
> hi Jaehoon,
>
> On 07/28/2017 09:05 PM, Jaehoon Chung wrote:
>>
>> Hi Kever,
>>
>> On 07/26/2017 08:33 PM, Kever Yang wrote:
>>>
>>> Hi Jaehoon,
>>>
>>>
>>>      What's the status of this patch set now?
>>>
>>>      Can we land this patch set or the other patch set from Ziyuan Xu?
>>>
>>> The performance for  mmc in U-Boot is really bad now, and this patch set
>>> has been
>>>
>>> on list for more than two months now, I'm using the patch set from Ziyuan
>>> Xu locally,
>>>
>>> but really hope the upstream can move forward.
>>
>> Apologized for late. Will try to upstream this before releasing v2017.09.
>> Really sorry for late, again. Thanks for reminding this.
>
>
> *ping*
> Anything update?

It would be great to get this applied.

Tom, this might now be too late for the release?

Regards,
Simon

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-08-27 20:10                   ` Simon Glass
@ 2017-08-27 20:17                     ` Tom Rini
  2017-08-28  5:53                       ` Jaehoon Chung
  2017-08-28  5:45                     ` Ziyuan
  1 sibling, 1 reply; 85+ messages in thread
From: Tom Rini @ 2017-08-27 20:17 UTC (permalink / raw)
  To: u-boot

On Sun, Aug 27, 2017 at 02:10:08PM -0600, Simon Glass wrote:
> Hi,
> 
> On 25 August 2017 at 02:16, Ziyuan <xzy.xu@rock-chips.com> wrote:
> > hi Jaehoon,
> >
> > On 07/28/2017 09:05 PM, Jaehoon Chung wrote:
> >>
> >> Hi Kever,
> >>
> >> On 07/26/2017 08:33 PM, Kever Yang wrote:
> >>>
> >>> Hi Jaehoon,
> >>>
> >>>
> >>>      What's the status of this patch set now?
> >>>
> >>>      Can we land this patch set or the other patch set from Ziyuan Xu?
> >>>
> >>> The performance for  mmc in U-Boot is really bad now, and this patch set
> >>> has been
> >>>
> >>> on list for more than two months now, I'm using the patch set from Ziyuan
> >>> Xu locally,
> >>>
> >>> but really hope the upstream can move forward.
> >>
> >> Apologized for late. Will try to upstream this before releasing v2017.09.
> >> Really sorry for late, again. Thanks for reminding this.
> >
> >
> > *ping*
> > Anything update?
> 
> It would be great to get this applied.
> 
> Tom, this might now be too late for the release?

Yeah, too late for this release.  But it could get queued up now (in a
/next) for next release.

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

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-08-27 20:10                   ` Simon Glass
  2017-08-27 20:17                     ` Tom Rini
@ 2017-08-28  5:45                     ` Ziyuan
  1 sibling, 0 replies; 85+ messages in thread
From: Ziyuan @ 2017-08-28  5:45 UTC (permalink / raw)
  To: u-boot

hi simon,

On 08/28/2017 04:10 AM, Simon Glass wrote:
> Hi,
>
> On 25 August 2017 at 02:16, Ziyuan <xzy.xu@rock-chips.com> wrote:
>> hi Jaehoon,
>>
>> On 07/28/2017 09:05 PM, Jaehoon Chung wrote:
>>> Hi Kever,
>>>
>>> On 07/26/2017 08:33 PM, Kever Yang wrote:
>>>> Hi Jaehoon,
>>>>
>>>>
>>>>       What's the status of this patch set now?
>>>>
>>>>       Can we land this patch set or the other patch set from Ziyuan Xu?
>>>>
>>>> The performance for  mmc in U-Boot is really bad now, and this patch set
>>>> has been
>>>>
>>>> on list for more than two months now, I'm using the patch set from Ziyuan
>>>> Xu locally,
>>>>
>>>> but really hope the upstream can move forward.
>>> Apologized for late. Will try to upstream this before releasing v2017.09.
>>> Really sorry for late, again. Thanks for reminding this.
>>
>> *ping*
>> Anything update?
> It would be great to get this applied.

I don't know the current status, but it seems that something need to be 
fixed in v1.

>
> Tom, this might now be too late for the release?
>
> Regards,
> Simon
>
>
>

-- 
Ziyuan Xu

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-08-27 20:17                     ` Tom Rini
@ 2017-08-28  5:53                       ` Jaehoon Chung
  2017-09-12 21:31                         ` Marek Vasut
  0 siblings, 1 reply; 85+ messages in thread
From: Jaehoon Chung @ 2017-08-28  5:53 UTC (permalink / raw)
  To: u-boot

On 08/28/2017 05:17 AM, Tom Rini wrote:
> On Sun, Aug 27, 2017 at 02:10:08PM -0600, Simon Glass wrote:
>> Hi,
>>
>> On 25 August 2017 at 02:16, Ziyuan <xzy.xu@rock-chips.com> wrote:
>>> hi Jaehoon,
>>>
>>> On 07/28/2017 09:05 PM, Jaehoon Chung wrote:
>>>>
>>>> Hi Kever,
>>>>
>>>> On 07/26/2017 08:33 PM, Kever Yang wrote:
>>>>>
>>>>> Hi Jaehoon,
>>>>>
>>>>>
>>>>>      What's the status of this patch set now?
>>>>>
>>>>>      Can we land this patch set or the other patch set from Ziyuan Xu?
>>>>>
>>>>> The performance for  mmc in U-Boot is really bad now, and this patch set
>>>>> has been
>>>>>
>>>>> on list for more than two months now, I'm using the patch set from Ziyuan
>>>>> Xu locally,
>>>>>
>>>>> but really hope the upstream can move forward.
>>>>
>>>> Apologized for late. Will try to upstream this before releasing v2017.09.
>>>> Really sorry for late, again. Thanks for reminding this.
>>>
>>>
>>> *ping*
>>> Anything update?
>>
>> It would be great to get this applied.
>>
>> Tom, this might now be too late for the release?
> 
> Yeah, too late for this release.  But it could get queued up now (in a
> /next) for next release.

Sorry..i will make a plan to update the next release!

Best Regards,
Jaehoon Chung

> 

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-08-28  5:53                       ` Jaehoon Chung
@ 2017-09-12 21:31                         ` Marek Vasut
  0 siblings, 0 replies; 85+ messages in thread
From: Marek Vasut @ 2017-09-12 21:31 UTC (permalink / raw)
  To: u-boot

On 08/28/2017 07:53 AM, Jaehoon Chung wrote:
> On 08/28/2017 05:17 AM, Tom Rini wrote:
>> On Sun, Aug 27, 2017 at 02:10:08PM -0600, Simon Glass wrote:
>>> Hi,
>>>
>>> On 25 August 2017 at 02:16, Ziyuan <xzy.xu@rock-chips.com> wrote:
>>>> hi Jaehoon,
>>>>
>>>> On 07/28/2017 09:05 PM, Jaehoon Chung wrote:
>>>>>
>>>>> Hi Kever,
>>>>>
>>>>> On 07/26/2017 08:33 PM, Kever Yang wrote:
>>>>>>
>>>>>> Hi Jaehoon,
>>>>>>
>>>>>>
>>>>>>      What's the status of this patch set now?
>>>>>>
>>>>>>      Can we land this patch set or the other patch set from Ziyuan Xu?
>>>>>>
>>>>>> The performance for  mmc in U-Boot is really bad now, and this patch set
>>>>>> has been
>>>>>>
>>>>>> on list for more than two months now, I'm using the patch set from Ziyuan
>>>>>> Xu locally,
>>>>>>
>>>>>> but really hope the upstream can move forward.
>>>>>
>>>>> Apologized for late. Will try to upstream this before releasing v2017.09.
>>>>> Really sorry for late, again. Thanks for reminding this.
>>>>
>>>>
>>>> *ping*
>>>> Anything update?
>>>
>>> It would be great to get this applied.
>>>
>>> Tom, this might now be too late for the release?
>>
>> Yeah, too late for this release.  But it could get queued up now (in a
>> /next) for next release.
> 
> Sorry..i will make a plan to update the next release!
So what's the status of this patchset ?

-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-07-28 13:05               ` Jaehoon Chung
  2017-08-25  8:16                 ` Ziyuan
@ 2017-09-15 13:20                 ` Jean-Jacques Hiblot
  2017-09-16 17:12                   ` Marek Vasut
  1 sibling, 1 reply; 85+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-15 13:20 UTC (permalink / raw)
  To: u-boot

Hi Jaehoon,

What is the status on this one?

Do you still have issues with some platforms?

Jean-Jacques


On 28/07/2017 15:05, Jaehoon Chung wrote:
> Hi Kever,
>
> On 07/26/2017 08:33 PM, Kever Yang wrote:
>> Hi Jaehoon,
>>
>>
>>      What's the status of this patch set now?
>>
>>      Can we land this patch set or the other patch set from Ziyuan Xu?
>>
>> The performance for  mmc in U-Boot is really bad now, and this patch set has been
>>
>> on list for more than two months now, I'm using the patch set from Ziyuan Xu locally,
>>
>> but really hope the upstream can move forward.
> Apologized for late. Will try to upstream this before releasing v2017.09.
> Really sorry for late, again. Thanks for reminding this.
>
> Best Regards,
> Jaehoon Chung
>
>>
>> Thanks,
>> - Kever
>> On 06/29/2017 05:59 PM, Jaehoon Chung wrote:
>>> On 06/16/2017 07:00 PM, Jean-Jacques Hiblot wrote:
>>>> Hi Jaehoon,
>>>>
>>>>
>>>> On 25/05/2017 09:41, Jaehoon Chung wrote:
>>>>> Hi,
>>>>>
>>>>> On 05/24/2017 12:24 AM, Jean-Jacques Hiblot wrote:
>>>>>> Hi,
>>>>>>
>>>>>>
>>>>>> On 18/05/2017 06:27, Jaehoon Chung wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
>>>>>>>> This series brings support for HS200 and UHS modes to the mmc core.
>>>>>>>> It has been tested with the hsmmc driver on several platforms (DRA7,
>>>>>>>> AM57x, AM437x, beaglebone black). Some modifications are required in
>>>>>>>> the host driver to take advantage of this (voltage switching, tuning).
>>>>>>>> The changes to the host driver will be posted a another series as this
>>>>>>>> one is already long enough.
>>>>>>>>
>>>>>>>> The series starts with a small refactoring of th sd/mmc startup. The first 4 commits
>>>>>>>> are mostly moving code around with little or no functionnal change.
>>>>>>>>
>>>>>>>> Then the notion of "mode" is introduced. Until now, this information wasn't
>>>>>>>> kept in struct mmc. Only the clock and a flag for ddr was kept. Later the mode
>>>>>>>> information will be used to select the clock frequency, the ddr flag and the
>>>>>>>> tuning procedure. It will be also be check against the host capabilities.
>>>>>>>>
>>>>>>>> Then comes the big refactoring job in:
>>>>>>>> "mmc: refactor MMC startup to make it easier to support new modes" and
>>>>>>>> "mmc: refactor SD startup to make it easier to support new modes"
>>>>>>>> Since the number of modes is increasing, it makes sense to try them in a more
>>>>>>>> organized way. those commits use a list of supported modes and iterate through
>>>>>>>> them to find the best working one. It also allows to switch more easilly from
>>>>>>>> one mode to another (switching from HS200 to DDR52 to access boot partitions for example)
>>>>>>>>
>>>>>>>> Then there are a couple of new callback added to:
>>>>>>>> - enable/disable Vdd
>>>>>>>> - check if the card is busy (used during UHS voltage switching)
>>>>>>>> - select the IO voltage
>>>>>>>>
>>>>>>>> Then Power cycle is added. Without power cycle, if a UHS card fails to enumerate in
>>>>>>>> UHS mode, it can't fall back to high speed mode and card enumeration will fail.
>>>>>>>>
>>>>>>>> And finally the last commits add the support for HS200 and UHS.
>>>>>>>> I haven't been able to test the UHS SDR104 mode by lack of compatible sdcard.
>>>>>>> After testing my targets, some boards don't work fine..So i'm checking this problem..
>>>>>> Jaehoon,
>>>>>>
>>>>>> what kind of issues are you running into and on what platforms ?
>>>>>> So far, besides the items brought-up by the reviews, there are 2 issues that are in the pipe for the next version:
>>>>>>     * signal voltage selection is not done for the MMCs only for SDs.
>>>>>>     * I noticed a timing constraint in voltage selection for SDs that can be a problem when trying a UHS mode with some SDs (seen only with Sandisk Ultra  64Gb micro SD class I) :  the voltage must be switched quickly after the cmd SWITCH_UHS18V has been sent, making debug messages in that context a problem. With this SD I've been able to check that SDR104 is working.
>>>>> How about making the "testing-hs200-uhs" branch for this? It needs to test more..
>>>>> I guess my target doesn't do the voltage change..i'm doing for ufs driver on u-boot in my local..
>>>>> So i didn't see fully..today i have a free time..So i'm doing full review other thing..and about pending patches.
>>>>>
>>>>> Thanks for waiting me.. :)
>>>> I updated the branches for testing in my github repo (https://github.com/jjhiblot/u-boot.git )
>>>> branch testing-hs200-uhs_v2 touches only the MMC core
>>>> branch high_speed_hsmmc_v2 implements the required bit for th HSMMC found on TI boards
>>> Sorry for late..I make the hs200-ufs-testing branch in u-boot-mmc repo.
>>> I will rebase on latest u-boot. and start the testing.
>>>
>>> Best Regards,
>>> Jaehoon Chung
>>>
>>>> Most of the comments (if not all of them) have been taken in account and the branches have been rebased on top of u-boot master.
>>>>
>>>> Will you be able to do some testing and let me know if there are other things to change ? Don't hesitate to let me know what boards it breaks (if any), I'll do my best to get my hands on one and help with the debugging.
>>>>
>>>> Thanks,
>>>>
>>>> JJ
>>>>> Best Regards,
>>>>> Jaehoon Chung
>>>>>
>>>>>> Jean-Jacques
>>>>>>>> With this in place and the required changes in the HSMMC (including DAM), we observe significant
>>>>>>>> improvements in the performances on a DRA7 evm:
>>>>>>>> eMMC HS200: 130 MB/s
>>>>>>>> eMMC DDR52: 80 MB/s
>>>>>>>> sd   SDR50: 80 MB/s
>>>>>>>>
>>>>>>>> cheers,
>>>>>>>>
>>>>>>>> Jean-Jacques
>>>>>>>>
>>>>>>>>
>>>>>>>> Jean-Jacques Hiblot (18):
>>>>>>>>       mmc: split mmc_startup()
>>>>>>>>       mmc: move the MMC startup for version above v4.0 in a separate
>>>>>>>>         function
>>>>>>>>       mmc: make ext_csd part of struct mmc
>>>>>>>>       mmc: add a function to read and test the ext csd (mmc >= 4)
>>>>>>>>       mmc: introduces mmc modes.
>>>>>>>>       mmc: Add a fonction to dump the mmc capabilities
>>>>>>>>       mmc: use mmc modes to select the correct bus speed
>>>>>>>>       cmd: mmc: display the mode name and current bus speed in the mmc info
>>>>>>>>       mmc: refactor SD startup to make it easier to support new modes
>>>>>>>>       mmc: refactor MMC startup to make it easier to support new modes
>>>>>>>>       mmc: make mmc_set_ios() return status
>>>>>>>>       mmc: add power cyle support in mmc core
>>>>>>>>       mmc: add a new mmc parameter to disable mmc clock
>>>>>>>>       mmc: Add a execute_tuning() callback to the mmc operations.
>>>>>>>>       mmc: add HS200 support in MMC core
>>>>>>>>       mmc: Add a new callback function to check if the card is busy
>>>>>>>>       mmc: Add support for UHS modes
>>>>>>>>       mmc: Change mode when switching to a boot partition
>>>>>>>>
>>>>>>>> Kishon Vijay Abraham I (3):
>>>>>>>>       mmc: Enable signal voltage to be selected from mmc core
>>>>>>>>       mmc: Add a new callback function to enable/disable vdd
>>>>>>>>       mmc: disable the mmc clock during power off
>>>>>>>>
>>>>>>>> Vignesh R (1):
>>>>>>>>       mmc: Retry some MMC cmds on failure
>>>>>>>>
>>>>>>>>      cmd/mmc.c                |    3 +-
>>>>>>>>      drivers/mmc/fsl_esdhc.c  |    2 +-
>>>>>>>>      drivers/mmc/mmc-uclass.c |   42 ++
>>>>>>>>      drivers/mmc/mmc.c        | 1220 +++++++++++++++++++++++++++++++++-------------
>>>>>>>>      include/mmc.h            |  138 +++++-
>>>>>>>>      5 files changed, 1058 insertions(+), 347 deletions(-)
>>>>>>>>
>>>>>>
>>>>
>>>>
>>> _______________________________________________
>>> U-Boot mailing list
>>> U-Boot at lists.denx.de
>>> https://lists.denx.de/listinfo/u-boot
>>
>>
>>
>>
>

^ permalink raw reply	[flat|nested] 85+ messages in thread

* [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes
  2017-09-15 13:20                 ` Jean-Jacques Hiblot
@ 2017-09-16 17:12                   ` Marek Vasut
  0 siblings, 0 replies; 85+ messages in thread
From: Marek Vasut @ 2017-09-16 17:12 UTC (permalink / raw)
  To: u-boot

On 09/15/2017 03:20 PM, Jean-Jacques Hiblot wrote:
> Hi Jaehoon,
> 
> What is the status on this one?

I'd like to know that too. Plus all the other outstanding SD/MMC patches
which block other stuff and already missed at least one MW ...

> Do you still have issues with some platforms?
> 
> Jean-Jacques
> 
> 
> On 28/07/2017 15:05, Jaehoon Chung wrote:
>> Hi Kever,
>>
>> On 07/26/2017 08:33 PM, Kever Yang wrote:
>>> Hi Jaehoon,
>>>
>>>
>>>      What's the status of this patch set now?
>>>
>>>      Can we land this patch set or the other patch set from Ziyuan Xu?
>>>
>>> The performance for  mmc in U-Boot is really bad now, and this patch
>>> set has been
>>>
>>> on list for more than two months now, I'm using the patch set from
>>> Ziyuan Xu locally,
>>>
>>> but really hope the upstream can move forward.
>> Apologized for late. Will try to upstream this before releasing v2017.09.
>> Really sorry for late, again. Thanks for reminding this.
>>
>> Best Regards,
>> Jaehoon Chung
>>
>>>
>>> Thanks,
>>> - Kever
>>> On 06/29/2017 05:59 PM, Jaehoon Chung wrote:
>>>> On 06/16/2017 07:00 PM, Jean-Jacques Hiblot wrote:
>>>>> Hi Jaehoon,
>>>>>
>>>>>
>>>>> On 25/05/2017 09:41, Jaehoon Chung wrote:
>>>>>> Hi,
>>>>>>
>>>>>> On 05/24/2017 12:24 AM, Jean-Jacques Hiblot wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>>
>>>>>>> On 18/05/2017 06:27, Jaehoon Chung wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
>>>>>>>>> This series brings support for HS200 and UHS modes to the mmc
>>>>>>>>> core.
>>>>>>>>> It has been tested with the hsmmc driver on several platforms
>>>>>>>>> (DRA7,
>>>>>>>>> AM57x, AM437x, beaglebone black). Some modifications are
>>>>>>>>> required in
>>>>>>>>> the host driver to take advantage of this (voltage switching,
>>>>>>>>> tuning).
>>>>>>>>> The changes to the host driver will be posted a another series
>>>>>>>>> as this
>>>>>>>>> one is already long enough.
>>>>>>>>>
>>>>>>>>> The series starts with a small refactoring of th sd/mmc
>>>>>>>>> startup. The first 4 commits
>>>>>>>>> are mostly moving code around with little or no functionnal
>>>>>>>>> change.
>>>>>>>>>
>>>>>>>>> Then the notion of "mode" is introduced. Until now, this
>>>>>>>>> information wasn't
>>>>>>>>> kept in struct mmc. Only the clock and a flag for ddr was kept.
>>>>>>>>> Later the mode
>>>>>>>>> information will be used to select the clock frequency, the ddr
>>>>>>>>> flag and the
>>>>>>>>> tuning procedure. It will be also be check against the host
>>>>>>>>> capabilities.
>>>>>>>>>
>>>>>>>>> Then comes the big refactoring job in:
>>>>>>>>> "mmc: refactor MMC startup to make it easier to support new
>>>>>>>>> modes" and
>>>>>>>>> "mmc: refactor SD startup to make it easier to support new modes"
>>>>>>>>> Since the number of modes is increasing, it makes sense to try
>>>>>>>>> them in a more
>>>>>>>>> organized way. those commits use a list of supported modes and
>>>>>>>>> iterate through
>>>>>>>>> them to find the best working one. It also allows to switch
>>>>>>>>> more easilly from
>>>>>>>>> one mode to another (switching from HS200 to DDR52 to access
>>>>>>>>> boot partitions for example)
>>>>>>>>>
>>>>>>>>> Then there are a couple of new callback added to:
>>>>>>>>> - enable/disable Vdd
>>>>>>>>> - check if the card is busy (used during UHS voltage switching)
>>>>>>>>> - select the IO voltage
>>>>>>>>>
>>>>>>>>> Then Power cycle is added. Without power cycle, if a UHS card
>>>>>>>>> fails to enumerate in
>>>>>>>>> UHS mode, it can't fall back to high speed mode and card
>>>>>>>>> enumeration will fail.
>>>>>>>>>
>>>>>>>>> And finally the last commits add the support for HS200 and UHS.
>>>>>>>>> I haven't been able to test the UHS SDR104 mode by lack of
>>>>>>>>> compatible sdcard.
>>>>>>>> After testing my targets, some boards don't work fine..So i'm
>>>>>>>> checking this problem..
>>>>>>> Jaehoon,
>>>>>>>
>>>>>>> what kind of issues are you running into and on what platforms ?
>>>>>>> So far, besides the items brought-up by the reviews, there are 2
>>>>>>> issues that are in the pipe for the next version:
>>>>>>>     * signal voltage selection is not done for the MMCs only for
>>>>>>> SDs.
>>>>>>>     * I noticed a timing constraint in voltage selection for SDs
>>>>>>> that can be a problem when trying a UHS mode with some SDs (seen
>>>>>>> only with Sandisk Ultra  64Gb micro SD class I) :  the voltage
>>>>>>> must be switched quickly after the cmd SWITCH_UHS18V has been
>>>>>>> sent, making debug messages in that context a problem. With this
>>>>>>> SD I've been able to check that SDR104 is working.
>>>>>> How about making the "testing-hs200-uhs" branch for this? It needs
>>>>>> to test more..
>>>>>> I guess my target doesn't do the voltage change..i'm doing for ufs
>>>>>> driver on u-boot in my local..
>>>>>> So i didn't see fully..today i have a free time..So i'm doing full
>>>>>> review other thing..and about pending patches.
>>>>>>
>>>>>> Thanks for waiting me.. :)
>>>>> I updated the branches for testing in my github repo
>>>>> (https://github.com/jjhiblot/u-boot.git )
>>>>> branch testing-hs200-uhs_v2 touches only the MMC core
>>>>> branch high_speed_hsmmc_v2 implements the required bit for th HSMMC
>>>>> found on TI boards
>>>> Sorry for late..I make the hs200-ufs-testing branch in u-boot-mmc repo.
>>>> I will rebase on latest u-boot. and start the testing.
>>>>
>>>> Best Regards,
>>>> Jaehoon Chung
>>>>
>>>>> Most of the comments (if not all of them) have been taken in
>>>>> account and the branches have been rebased on top of u-boot master.
>>>>>
>>>>> Will you be able to do some testing and let me know if there are
>>>>> other things to change ? Don't hesitate to let me know what boards
>>>>> it breaks (if any), I'll do my best to get my hands on one and help
>>>>> with the debugging.
>>>>>
>>>>> Thanks,
>>>>>
>>>>> JJ
>>>>>> Best Regards,
>>>>>> Jaehoon Chung
>>>>>>
>>>>>>> Jean-Jacques
>>>>>>>>> With this in place and the required changes in the HSMMC
>>>>>>>>> (including DAM), we observe significant
>>>>>>>>> improvements in the performances on a DRA7 evm:
>>>>>>>>> eMMC HS200: 130 MB/s
>>>>>>>>> eMMC DDR52: 80 MB/s
>>>>>>>>> sd   SDR50: 80 MB/s
>>>>>>>>>
>>>>>>>>> cheers,
>>>>>>>>>
>>>>>>>>> Jean-Jacques
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Jean-Jacques Hiblot (18):
>>>>>>>>>       mmc: split mmc_startup()
>>>>>>>>>       mmc: move the MMC startup for version above v4.0 in a
>>>>>>>>> separate
>>>>>>>>>         function
>>>>>>>>>       mmc: make ext_csd part of struct mmc
>>>>>>>>>       mmc: add a function to read and test the ext csd (mmc >= 4)
>>>>>>>>>       mmc: introduces mmc modes.
>>>>>>>>>       mmc: Add a fonction to dump the mmc capabilities
>>>>>>>>>       mmc: use mmc modes to select the correct bus speed
>>>>>>>>>       cmd: mmc: display the mode name and current bus speed in
>>>>>>>>> the mmc info
>>>>>>>>>       mmc: refactor SD startup to make it easier to support new
>>>>>>>>> modes
>>>>>>>>>       mmc: refactor MMC startup to make it easier to support
>>>>>>>>> new modes
>>>>>>>>>       mmc: make mmc_set_ios() return status
>>>>>>>>>       mmc: add power cyle support in mmc core
>>>>>>>>>       mmc: add a new mmc parameter to disable mmc clock
>>>>>>>>>       mmc: Add a execute_tuning() callback to the mmc operations.
>>>>>>>>>       mmc: add HS200 support in MMC core
>>>>>>>>>       mmc: Add a new callback function to check if the card is
>>>>>>>>> busy
>>>>>>>>>       mmc: Add support for UHS modes
>>>>>>>>>       mmc: Change mode when switching to a boot partition
>>>>>>>>>
>>>>>>>>> Kishon Vijay Abraham I (3):
>>>>>>>>>       mmc: Enable signal voltage to be selected from mmc core
>>>>>>>>>       mmc: Add a new callback function to enable/disable vdd
>>>>>>>>>       mmc: disable the mmc clock during power off
>>>>>>>>>
>>>>>>>>> Vignesh R (1):
>>>>>>>>>       mmc: Retry some MMC cmds on failure
>>>>>>>>>
>>>>>>>>>      cmd/mmc.c                |    3 +-
>>>>>>>>>      drivers/mmc/fsl_esdhc.c  |    2 +-
>>>>>>>>>      drivers/mmc/mmc-uclass.c |   42 ++
>>>>>>>>>      drivers/mmc/mmc.c        | 1220
>>>>>>>>> +++++++++++++++++++++++++++++++++-------------
>>>>>>>>>      include/mmc.h            |  138 +++++-
>>>>>>>>>      5 files changed, 1058 insertions(+), 347 deletions(-)
>>>>>>>>>
>>>>>>>
>>>>>
>>>>>
>>>> _______________________________________________
>>>> U-Boot mailing list
>>>> U-Boot at lists.denx.de
>>>> https://lists.denx.de/listinfo/u-boot
>>>
>>>
>>>
>>>
>>
> 
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot


-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 85+ messages in thread

end of thread, other threads:[~2017-09-16 17:12 UTC | newest]

Thread overview: 85+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20170512181724epcas5p36ff2843856a4d329a0b106cd063f7286@epcas5p3.samsung.com>
2017-05-12 18:16 ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
2017-05-12 18:16   ` [U-Boot] [PATCH 01/22] mmc: split mmc_startup() Jean-Jacques Hiblot
2017-05-15  3:27     ` Simon Glass
2017-05-12 18:16   ` [U-Boot] [PATCH 02/22] mmc: move the MMC startup for version above v4.0 in a separate function Jean-Jacques Hiblot
2017-05-15  3:27     ` Simon Glass
2017-05-12 18:16   ` [U-Boot] [PATCH 03/22] mmc: make ext_csd part of struct mmc Jean-Jacques Hiblot
2017-05-15  3:27     ` Simon Glass
2017-05-12 18:16   ` [U-Boot] [PATCH 04/22] mmc: add a function to read and test the ext csd (mmc >= 4) Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-12 18:16   ` [U-Boot] [PATCH 05/22] mmc: introduces mmc modes Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-15 10:34       ` Jean-Jacques Hiblot
2017-05-12 18:16   ` [U-Boot] [PATCH 06/22] mmc: Add a fonction to dump the mmc capabilities Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-12 18:16   ` [U-Boot] [PATCH 07/22] mmc: use mmc modes to select the correct bus speed Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-12 18:16   ` [U-Boot] [PATCH 08/22] cmd: mmc: display the mode name and current bus speed in the mmc info Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-12 18:16   ` [U-Boot] [PATCH 09/22] mmc: refactor SD startup to make it easier to support new modes Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-15 10:49       ` Jean-Jacques Hiblot
2017-05-12 18:16   ` [U-Boot] [PATCH 10/22] mmc: refactor MMC " Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-25 12:25     ` Jaehoon Chung
2017-05-25 14:40       ` Jean-Jacques Hiblot
2017-05-26  1:12         ` Jaehoon Chung
2017-05-12 18:16   ` [U-Boot] [PATCH 11/22] mmc: make mmc_set_ios() return status Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-12 18:16   ` [U-Boot] [PATCH 12/22] mmc: Enable signal voltage to be selected from mmc core Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-15 14:18       ` Jean-Jacques Hiblot
2017-05-17  1:38         ` Simon Glass
2017-05-17 10:35       ` Kishon Vijay Abraham I
2017-05-12 18:16   ` [U-Boot] [PATCH 13/22] mmc: Add a new callback function to enable/disable vdd Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-12 18:16   ` [U-Boot] [PATCH 14/22] mmc: add power cyle support in mmc core Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-15 15:50       ` Jean-Jacques Hiblot
2017-05-25 12:35     ` Jaehoon Chung
2017-05-25 14:50       ` Jean-Jacques Hiblot
2017-06-15 16:13       ` Jean-Jacques Hiblot
2017-05-12 18:16   ` [U-Boot] [PATCH 15/22] mmc: add a new mmc parameter to disable mmc clock Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-12 18:16   ` [U-Boot] [PATCH 16/22] mmc: disable the mmc clock during power off Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-12 18:16   ` [U-Boot] [PATCH 17/22] mmc: Add a execute_tuning() callback to the mmc operations Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-25 12:37     ` Jaehoon Chung
2017-05-25 14:51       ` Jean-Jacques Hiblot
2017-05-12 18:16   ` [U-Boot] [PATCH 18/22] mmc: add HS200 support in MMC core Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-25 12:42     ` Jaehoon Chung
2017-05-12 18:16   ` [U-Boot] [PATCH 19/22] mmc: Add a new callback function to check if the card is busy Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-12 18:16   ` [U-Boot] [PATCH 20/22] mmc: Add support for UHS modes Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-16 14:20     ` Jean-Jacques Hiblot
2017-05-17  1:59       ` Jaehoon Chung
2017-05-25 12:50     ` Jaehoon Chung
2017-05-12 18:16   ` [U-Boot] [PATCH 21/22] mmc: Change mode when switching to a boot partition Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-25 12:53     ` Jaehoon Chung
2017-05-12 18:16   ` [U-Boot] [PATCH 22/22] mmc: Retry some MMC cmds on failure Jean-Jacques Hiblot
2017-05-15  3:28     ` Simon Glass
2017-05-15 15:49       ` Jean-Jacques Hiblot
2017-05-17  1:38         ` Simon Glass
2017-05-17 14:47           ` Jean-Jacques Hiblot
2017-05-15  2:33   ` [U-Boot] [PATCH 00/22] mmc: Add support for HS200 and UHS modes Jaehoon Chung
2017-05-18  4:27   ` Jaehoon Chung
2017-05-23 15:24     ` Jean-Jacques Hiblot
2017-05-25  7:41       ` Jaehoon Chung
2017-05-25 14:42         ` Jean-Jacques Hiblot
2017-06-02 16:46         ` Jean-Jacques Hiblot
2017-06-16 10:00         ` Jean-Jacques Hiblot
2017-06-29  9:59           ` Jaehoon Chung
2017-07-26 11:33             ` Kever Yang
2017-07-28 13:05               ` Jaehoon Chung
2017-08-25  8:16                 ` Ziyuan
2017-08-27 20:10                   ` Simon Glass
2017-08-27 20:17                     ` Tom Rini
2017-08-28  5:53                       ` Jaehoon Chung
2017-09-12 21:31                         ` Marek Vasut
2017-08-28  5:45                     ` Ziyuan
2017-09-15 13:20                 ` Jean-Jacques Hiblot
2017-09-16 17:12                   ` Marek Vasut

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.