All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes
@ 2017-09-21 14:29 ` Jean-Jacques Hiblot
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 01/26] mmc: dm: get the IO-line and main voltage regulators from the dts Jean-Jacques Hiblot
                     ` (27 more replies)
  0 siblings, 28 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:29 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, Atmel SAMA5D3 xplained). 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 5 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:
- send the initialization stream (74 clock cycles)
- wait while the card is busy (used during UHS voltage switching). checking is
  done on dat0.
- 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.
Also in case of a reset (as opposed to a power on), it ensures that the SDCard
is in clean state before re-doing the initialization.

And finally the last commits add the support for HS200 and UHS.

With this in place and the required changes in the HSMMC host driver (including
DMA), we observe significant improvements in the performances on a DRA72 evm:
eMMC HS200: 124 MB/s
eMMC DDR52: 78 MB/s
sd   SDR104: 71 MB/s
sd   SDR50: 44 MB/s

cheers,

Jean-Jacques

changes since v1:
Changes take in account all the comment made during the first round of review.
But it also include a rework of the handling of the voltage supplies and 2 new
helper functions that can be used by the host driver during tuning and dts
parsing.

Here is a detailed list:
 * rebase on u-boot/master.
 * add the description for the new functions/members
 * fix the typos found in the reviews
 * limit the new features to DM_MMC only
 * fix the new checkpatch warnings/errors (is it now more strict ?)
 * get the voltage regulators from dts (main and IO-lines)
 * remove the set_vdd callback and do the job in the mmc core
 * add a send_init_stream callback to perform the 74 clock cycle
   sequence after power up
 * do a full power cycle (if possible) before the initialization. This ensures
   that the sd/MMC is in valid knwon state. Also it allows to check if the power
   cycling works as expected.
 * disable the UHS modes is power cycling is not available/working. This ensures
   that we won't be stuck if the UHS initialization fails.
 * select the appropriate signal voltage when selecting a mode (MMC only) 
 * add a helper function to parse the generic dt bindings
 * add a helper function to send the tuning command
 
Jean-Jacques Hiblot (17):
  mmc: dm: get the IO-line and main voltage regulators from the dts
  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: introduce mmc modes
  mmc: Add a function 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: Add a new callback function to perform the 74 clocks cycle
    sequence
  mmc: Add support for UHS modes
  mmc: disable UHS modes if Vcc cannot be switched on and off
  mmc: Change mode when switching to a boot partition
  mmc: use the right voltage level for MMC DDR and HS200 modes
  mmc: add a library function to send tuning command

Kishon Vijay Abraham I (9):
  mmc: make mmc_set_ios() return status
  mmc: Enable signal voltage to be selected from mmc core
  mmc: add power cyle support in mmc core
  mmc: add a new mmc parameter to disable mmc clock
  mmc: disable the mmc clock during power off
  mmc: Add a execute_tuning() callback to the mmc operations.
  mmc: add HS200 support in MMC core
  mmc: Retry some MMC cmds on failure
  dm: mmc: Add a library function to parse generic dt binding

 cmd/mmc.c                |    3 +-
 drivers/mmc/Kconfig      |   23 +
 drivers/mmc/fsl_esdhc.c  |    2 +-
 drivers/mmc/mmc-uclass.c |   87 +++
 drivers/mmc/mmc.c        | 1511 ++++++++++++++++++++++++++++++++++------------
 include/mmc.h            |  176 +++++-
 6 files changed, 1417 insertions(+), 385 deletions(-)

-- 
1.9.1

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

* [U-Boot] [PATCH v2 01/26] mmc: dm: get the IO-line and main voltage regulators from the dts
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
@ 2017-09-21 14:29   ` Jean-Jacques Hiblot
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 02/26] mmc: split mmc_startup() Jean-Jacques Hiblot
                     ` (26 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:29 UTC (permalink / raw)
  To: u-boot

Get a reference to the regulator devices from the dts and store them
in the struct mmc for later use.

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

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 38d2e07..11285be 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1618,21 +1618,25 @@ __weak void board_mmc_power_init(void)
 static int mmc_power_init(struct mmc *mmc)
 {
 #if CONFIG_IS_ENABLED(DM_MMC)
-#if defined(CONFIG_DM_REGULATOR) && !defined(CONFIG_SPL_BUILD)
-	struct udevice *vmmc_supply;
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
 	int ret;
 
 	ret = device_get_supply_regulator(mmc->dev, "vmmc-supply",
-					  &vmmc_supply);
-	if (ret) {
+					  &mmc->vmmc_supply);
+	if (ret)
 		debug("%s: No vmmc supply\n", mmc->dev->name);
-		return 0;
-	}
 
-	ret = regulator_set_enable(vmmc_supply, true);
-	if (ret) {
-		puts("Error enabling VMMC supply\n");
-		return ret;
+	ret = device_get_supply_regulator(mmc->dev, "vqmmc-supply",
+					  &mmc->vqmmc_supply);
+	if (ret)
+		debug("%s: No vqmmc supply\n", mmc->dev->name);
+
+	if (mmc->vmmc_supply) {
+		ret = regulator_set_enable(mmc->vmmc_supply, true);
+		if (ret) {
+			puts("Error enabling VMMC supply\n");
+			return ret;
+		}
 	}
 #endif
 #else /* !CONFIG_DM_MMC */
diff --git a/include/mmc.h b/include/mmc.h
index 010ebe0..188dc74 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -457,6 +457,10 @@ struct mmc {
 	int ddr_mode;
 #if CONFIG_IS_ENABLED(DM_MMC)
 	struct udevice *dev;	/* Device for this MMC controller */
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+	struct udevice *vmmc_supply;	/* Main voltage regulator (Vcc)*/
+	struct udevice *vqmmc_supply;	/* IO voltage regulator (Vccq)*/
+#endif
 #endif
 };
 
-- 
1.9.1

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

* [U-Boot] [PATCH v2 02/26] mmc: split mmc_startup()
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 01/26] mmc: dm: get the IO-line and main voltage regulators from the dts Jean-Jacques Hiblot
@ 2017-09-21 14:29   ` Jean-Jacques Hiblot
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 03/26] mmc: move the MMC startup for version above v4.0 in a separate function Jean-Jacques Hiblot
                     ` (25 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:29 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>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 drivers/mmc/mmc.c | 274 +++++++++++++++++++++++++++++-------------------------
 1 file changed, 148 insertions(+), 126 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 11285be..1946875 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1103,6 +1103,152 @@ 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 int 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 int 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 int 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;
+
+		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 +1256,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 +1560,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] 50+ messages in thread

* [U-Boot] [PATCH v2 03/26] mmc: move the MMC startup for version above v4.0 in a separate function
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 01/26] mmc: dm: get the IO-line and main voltage regulators from the dts Jean-Jacques Hiblot
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 02/26] mmc: split mmc_startup() Jean-Jacques Hiblot
@ 2017-09-21 14:29   ` Jean-Jacques Hiblot
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 04/26] mmc: make ext_csd part of struct mmc Jean-Jacques Hiblot
                     ` (24 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:29 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>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 drivers/mmc/mmc.c | 318 ++++++++++++++++++++++++++++--------------------------
 1 file changed, 167 insertions(+), 151 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 1946875..7c100a4 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1249,15 +1249,176 @@ 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;
+
+		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
@@ -1405,155 +1566,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] 50+ messages in thread

* [U-Boot] [PATCH v2 04/26] mmc: make ext_csd part of struct mmc
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (2 preceding siblings ...)
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 03/26] mmc: move the MMC startup for version above v4.0 in a separate function Jean-Jacques Hiblot
@ 2017-09-21 14:29   ` Jean-Jacques Hiblot
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 05/26] mmc: add a function to read and test the ext csd (mmc >= 4) Jean-Jacques Hiblot
                     ` (23 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:29 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>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 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 7c100a4..cfdfd8d 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 int 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) {
+		debug("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];
@@ -1249,16 +1255,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)
@@ -1418,7 +1431,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
@@ -1567,7 +1579,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;
 
@@ -1578,7 +1590,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 188dc74..7d2b363 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -462,6 +462,7 @@ struct mmc {
 	struct udevice *vqmmc_supply;	/* IO voltage regulator (Vccq)*/
 #endif
 #endif
+	u8 *ext_csd;
 };
 
 struct mmc_hwpart_conf {
-- 
1.9.1

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

* [U-Boot] [PATCH v2 05/26] mmc: add a function to read and test the ext csd (mmc >= 4)
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (3 preceding siblings ...)
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 04/26] mmc: make ext_csd part of struct mmc Jean-Jacques Hiblot
@ 2017-09-21 14:29   ` Jean-Jacques Hiblot
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 06/26] mmc: introduce mmc modes Jean-Jacques Hiblot
                     ` (22 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:29 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>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 drivers/mmc/mmc.c | 53 +++++++++++++++++++++++++++++++++--------------------
 1 file changed, 33 insertions(+), 20 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index cfdfd8d..d360a1a 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1146,10 +1146,39 @@ static int sd_select_bus_freq_width(struct mmc *mmc)
 	return 0;
 }
 
-static int mmc_select_bus_freq_width(struct mmc *mmc)
+/*
+ * read the compare the part of ext csd that is constant.
+ * This can be used to check that the transfer is working
+ * as expected.
+ */
+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 int ext_csd_bits[] = {
 		EXT_CSD_DDR_BUS_WIDTH_8,
@@ -1221,25 +1250,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;
-
-		err = -EBADMSG;
 	}
 
 	if (err)
-- 
1.9.1

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

* [U-Boot] [PATCH v2 06/26] mmc: introduce mmc modes
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (4 preceding siblings ...)
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 05/26] mmc: add a function to read and test the ext csd (mmc >= 4) Jean-Jacques Hiblot
@ 2017-09-21 14:29   ` Jean-Jacques Hiblot
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 07/26] mmc: Add a function to dump the mmc capabilities Jean-Jacques Hiblot
                     ` (21 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:29 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>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 drivers/mmc/Kconfig | 14 ++++++++++++++
 drivers/mmc/mmc.c   | 56 ++++++++++++++++++++++++++++++++++++++++++++++-------
 include/mmc.h       | 35 +++++++++++++++++++++++++++------
 3 files changed, 92 insertions(+), 13 deletions(-)

diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 6de927b..3d577e0 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -33,6 +33,20 @@ config SPL_DM_MMC
 
 if MMC
 
+config MMC_VERBOSE
+	bool "Output more information about the MMC"
+	default y
+	help
+	  Enable the output of more information about the card such as the
+	  operating mode.
+
+config SPL_MMC_VERBOSE
+	bool "Output more information about the MMC in SPL"
+	default n
+	help
+	  Enable the output of more information about the card such as the
+	  operating mode.
+
 config SPL_MMC_TINY
 	bool "Tiny MMC framework in SPL"
 	help
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index d360a1a..94b3a02 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -149,6 +149,39 @@ void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd)
 }
 #endif
 
+#if CONFIG_IS_ENABLED(MMC_VERBOSE) || defined(DEBUG)
+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];
+}
+#endif
+
+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;
+}
+
 #if !CONFIG_IS_ENABLED(DM_MMC)
 int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 {
@@ -1138,10 +1171,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;
 }
@@ -1258,11 +1294,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;
@@ -1534,7 +1574,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 7d2b363..76bd57a 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		BIT(30)
+#define MMC_MODE_4BIT		BIT(29)
+#define MMC_MODE_SPI		BIT(27)
+
 
 #define SD_DATA_4BIT	0x00040000
 
@@ -406,6 +409,24 @@ struct sd_ssr {
 	unsigned int erase_offset;	/* In milliseconds */
 };
 
+enum bus_mode {
+	MMC_LEGACY,
+	SD_LEGACY,
+	MMC_HS,
+	SD_HS,
+	UHS_SDR12,
+	UHS_SDR25,
+	UHS_SDR50,
+	UHS_SDR104,
+	UHS_DDR50,
+	MMC_HS_52,
+	MMC_DDR_52,
+	MMC_HS_200,
+	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().
@@ -436,6 +457,7 @@ struct mmc {
 	u8 wr_rel_set;
 	u8 part_config;
 	uint tran_speed;
+	uint legacy_speed; /* speed for the legacy mode provided by the card */
 	uint read_bl_len;
 	uint write_bl_len;
 	uint erase_grp_size;	/* in 512-byte sectors */
@@ -463,6 +485,7 @@ struct mmc {
 #endif
 #endif
 	u8 *ext_csd;
+	enum bus_mode selected_mode;
 };
 
 struct mmc_hwpart_conf {
-- 
1.9.1

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

* [U-Boot] [PATCH v2 07/26] mmc: Add a function to dump the mmc capabilities
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (5 preceding siblings ...)
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 06/26] mmc: introduce mmc modes Jean-Jacques Hiblot
@ 2017-09-21 14:29   ` Jean-Jacques Hiblot
  2017-09-22 13:54     ` Jaehoon Chung
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 08/26] mmc: use mmc modes to select the correct bus speed Jean-Jacques Hiblot
                     ` (20 subsequent siblings)
  27 siblings, 1 reply; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:29 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 | 24 ++++++++++++++++++++++++
 include/mmc.h     |  1 +
 2 files changed, 25 insertions(+)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 94b3a02..0b74e78 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1136,6 +1136,30 @@ static void mmc_set_bus_width(struct mmc *mmc, uint width)
 	mmc_set_ios(mmc);
 }
 
+#if CONFIG_IS_ENABLED(MMC_VERBOSE) || defined(DEBUG)
+/*
+ * helper function to display the capabilities in a human
+ * friendly manner. The capabilities include bus width and
+ * supported modes.
+ */
+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");
+}
+#endif
+
 static int sd_select_bus_freq_width(struct mmc *mmc)
 {
 	int err;
diff --git a/include/mmc.h b/include/mmc.h
index 76bd57a..dd83f14 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -426,6 +426,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
-- 
1.9.1

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

* [U-Boot] [PATCH v2 08/26] mmc: use mmc modes to select the correct bus speed
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (6 preceding siblings ...)
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 07/26] mmc: Add a function to dump the mmc capabilities Jean-Jacques Hiblot
@ 2017-09-21 14:29   ` Jean-Jacques Hiblot
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 09/26] cmd: mmc: display the mode name and current bus speed in the mmc info Jean-Jacques Hiblot
                     ` (19 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:29 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 drivers/mmc/mmc.c | 39 ++++++++++++++++++++++++++++-----------
 1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 0b74e78..382a9cf 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -174,9 +174,34 @@ const char *mmc_mode_name(enum bus_mode mode)
 }
 #endif
 
+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;
@@ -1195,13 +1220,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;
 }
@@ -1323,11 +1345,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;
 }
@@ -1599,7 +1618,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);
@@ -1674,7 +1692,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] 50+ messages in thread

* [U-Boot] [PATCH v2 09/26] cmd: mmc: display the mode name and current bus speed in the mmc info
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (7 preceding siblings ...)
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 08/26] mmc: use mmc modes to select the correct bus speed Jean-Jacques Hiblot
@ 2017-09-21 14:29   ` Jean-Jacques Hiblot
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 10/26] mmc: refactor SD startup to make it easier to support new modes Jean-Jacques Hiblot
                     ` (18 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:29 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>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 cmd/mmc.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/cmd/mmc.c b/cmd/mmc.c
index 5def4ea..6d48ecb 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] 50+ messages in thread

* [U-Boot] [PATCH v2 10/26] mmc: refactor SD startup to make it easier to support new modes
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (8 preceding siblings ...)
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 09/26] cmd: mmc: display the mode name and current bus speed in the mmc info Jean-Jacques Hiblot
@ 2017-09-21 14:29   ` Jean-Jacques Hiblot
  2018-02-09  0:10     ` Jonathan Gray
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 11/26] mmc: refactor MMC " Jean-Jacques Hiblot
                     ` (17 subsequent siblings)
  27 siblings, 1 reply; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:29 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>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 drivers/mmc/mmc.c | 183 ++++++++++++++++++++++++++++++++++++++----------------
 include/mmc.h     |   1 +
 2 files changed, 130 insertions(+), 54 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 382a9cf..b8e726a 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -237,7 +237,8 @@ int mmc_send_status(struct mmc *mmc, int timeout)
 			    (cmd.response[0] & MMC_STATUS_CURR_STATE) !=
 			     MMC_STATE_PRG)
 				break;
-			else if (cmd.response[0] & MMC_STATUS_MASK) {
+
+			if (cmd.response[0] & MMC_STATUS_MASK) {
 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
 				printf("Status Error: 0x%08X\n",
 					cmd.response[0]);
@@ -610,7 +611,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;
@@ -936,7 +937,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;
@@ -945,7 +946,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;
@@ -1022,26 +1023,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)
+		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;
 
-	if ((__be32_to_cpu(switch_status[4]) & 0x0f000000) == 0x01000000)
-		mmc->card_caps |= MMC_MODE_HS;
+	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;
 }
@@ -1133,6 +1161,18 @@ 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;
+}
+
 #if !CONFIG_IS_ENABLED(DM_MMC)
 static void mmc_set_ios(struct mmc *mmc)
 {
@@ -1176,8 +1216,9 @@ 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));
@@ -1185,47 +1226,81 @@ void mmc_dump_capabilities(const char *text, uint caps)
 }
 #endif
 
-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;
+
+				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;
 }
 
 /*
@@ -1290,7 +1365,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)
@@ -1685,7 +1760,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 dd83f14..9fe6a87 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -59,6 +59,7 @@
 
 #define MMC_MODE_8BIT		BIT(30)
 #define MMC_MODE_4BIT		BIT(29)
+#define MMC_MODE_1BIT		BIT(28)
 #define MMC_MODE_SPI		BIT(27)
 
 
-- 
1.9.1

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

* [U-Boot] [PATCH v2 11/26] mmc: refactor MMC startup to make it easier to support new modes
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (9 preceding siblings ...)
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 10/26] mmc: refactor SD startup to make it easier to support new modes Jean-Jacques Hiblot
@ 2017-09-21 14:29   ` Jean-Jacques Hiblot
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 12/26] mmc: make mmc_set_ios() return status Jean-Jacques Hiblot
                     ` (16 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:29 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>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 drivers/mmc/mmc.c | 241 +++++++++++++++++++++++++++++++++---------------------
 include/mmc.h     |  11 +++
 2 files changed, 158 insertions(+), 94 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index b8e726a..7361447 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -202,6 +202,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;
@@ -605,11 +606,47 @@ 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;
 
@@ -620,38 +657,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;
 }
@@ -1334,33 +1356,60 @@ static int mmc_read_and_compare_ext_csd(struct mmc *mmc)
 	return -EBADMSG;
 }
 
-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_DDR_BUS_WIDTH_8},
+	{MMC_MODE_4BIT, true, EXT_CSD_DDR_BUS_WIDTH_4},
+	{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 int 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 int 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 int 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;
 
@@ -1376,54 +1425,58 @@ static int mmc_select_bus_freq_width(struct mmc *mmc)
 		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];
-		/*
-		 * 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);
+	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);
+			/* 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_FLAG);
+			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_FLAG) {
+				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)
@@ -1762,7 +1815,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 9fe6a87..988bf17 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -215,7 +215,10 @@
 #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_FLAG	BIT(2)	/* Flag for 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)
@@ -429,6 +432,14 @@ 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] 50+ messages in thread

* [U-Boot] [PATCH v2 12/26] mmc: make mmc_set_ios() return status
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (10 preceding siblings ...)
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 11/26] mmc: refactor MMC " Jean-Jacques Hiblot
@ 2017-09-21 14:29   ` Jean-Jacques Hiblot
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 13/26] mmc: Enable signal voltage to be selected from mmc core Jean-Jacques Hiblot
                     ` (15 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:29 UTC (permalink / raw)
  To: u-boot

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

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: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 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 7361447..536cd7f 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1196,14 +1196,18 @@ static inline int bus_width(uint cap)
 }
 
 #if !CONFIG_IS_ENABLED(DM_MMC)
-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;
@@ -1213,14 +1217,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);
 }
 
 #if CONFIG_IS_ENABLED(MMC_VERBOSE) || defined(DEBUG)
diff --git a/include/mmc.h b/include/mmc.h
index 988bf17..3e57887 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -549,7 +549,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] 50+ messages in thread

* [U-Boot] [PATCH v2 13/26] mmc: Enable signal voltage to be selected from mmc core
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (11 preceding siblings ...)
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 12/26] mmc: make mmc_set_ios() return status Jean-Jacques Hiblot
@ 2017-09-21 14:30   ` Jean-Jacques Hiblot
  2017-09-22 13:54     ` Jaehoon Chung
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 14/26] mmc: Add a new callback function to perform the 74 clocks cycle sequence Jean-Jacques Hiblot
                     ` (14 subsequent siblings)
  27 siblings, 1 reply; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:30 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 | 16 ++++++++++++++++
 include/mmc.h     |  8 ++++++++
 2 files changed, 24 insertions(+)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 536cd7f..46ec5e1 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -30,6 +30,8 @@ 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);
+
 #if CONFIG_IS_ENABLED(MMC_TINY)
 static struct mmc mmc_static;
 struct mmc *find_mmc_device(int dev_num)
@@ -1257,6 +1259,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,
@@ -1964,6 +1972,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 3e57887..e524963 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -272,6 +272,13 @@
 #define ENHNCD_SUPPORT		(0x2)
 #define PART_ENH_ATTRIB		(0x1f)
 
+enum mmc_voltage {
+	MMC_SIGNAL_VOLTAGE_000 = 0,
+	MMC_SIGNAL_VOLTAGE_120,
+	MMC_SIGNAL_VOLTAGE_180,
+	MMC_SIGNAL_VOLTAGE_330
+};
+
 /* Maximum block size for MMC */
 #define MMC_MAX_BLOCK_LEN	512
 
@@ -457,6 +464,7 @@ struct mmc {
 	int high_capacity;
 	uint bus_width;
 	uint clock;
+	enum mmc_voltage signal_voltage;
 	uint card_caps;
 	uint ocr;
 	uint dsr;
-- 
1.9.1

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

* [U-Boot] [PATCH v2 14/26] mmc: Add a new callback function to perform the 74 clocks cycle sequence
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (12 preceding siblings ...)
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 13/26] mmc: Enable signal voltage to be selected from mmc core Jean-Jacques Hiblot
@ 2017-09-21 14:30   ` Jean-Jacques Hiblot
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 15/26] mmc: add power cyle support in mmc core Jean-Jacques Hiblot
                     ` (13 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:30 UTC (permalink / raw)
  To: u-boot

Add a new callback function *send_init_stream* which start a sequence of
at least 74 clock cycles.
The mmc core uses *mmc_send_init_stream* in order to invoke the callback
function. This will be used during power cycle where the specification
requires such a sequence after power up.

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

diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 5dda20c..9c6a8ba 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -51,6 +51,19 @@ int mmc_set_ios(struct mmc *mmc)
 	return dm_mmc_set_ios(mmc->dev);
 }
 
+void dm_mmc_send_init_stream(struct udevice *dev)
+{
+	struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+	if (ops->send_init_stream)
+		ops->send_init_stream(dev);
+}
+
+void mmc_send_init_stream(struct mmc *mmc)
+{
+	dm_mmc_send_init_stream(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 46ec5e1..fd93691 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1198,6 +1198,10 @@ static inline int bus_width(uint cap)
 }
 
 #if !CONFIG_IS_ENABLED(DM_MMC)
+static void mmc_send_init_stream(struct mmc *mmc)
+{
+}
+
 static int mmc_set_ios(struct mmc *mmc)
 {
 	int ret = 0;
@@ -1983,6 +1987,8 @@ int mmc_start_init(struct mmc *mmc)
 	mmc_set_bus_width(mmc, 1);
 	mmc_set_clock(mmc, 1);
 
+	mmc_send_init_stream(mmc);
+
 	/* Reset the Card */
 	err = mmc_go_idle(mmc);
 
diff --git a/include/mmc.h b/include/mmc.h
index e524963..bd096ae 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -361,6 +361,14 @@ struct dm_mmc_ops {
 	int (*set_ios)(struct udevice *dev);
 
 	/**
+	 * send_init_stream() - send the initialization stream: 74 clock cycles
+	 * This is used after power up before sending the first command
+	 *
+	 * @dev:	Device to update
+	 */
+	void (*send_init_stream)(struct udevice *dev);
+
+	/**
 	 * get_cd() - See whether a card is present
 	 *
 	 * @dev:	Device to check
@@ -382,11 +390,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);
+void dm_mmc_send_init_stream(struct udevice *dev);
 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);
+void mmc_send_init_stream(struct mmc *mmc);
 int mmc_getcd(struct mmc *mmc);
 int mmc_getwp(struct mmc *mmc);
 
-- 
1.9.1

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

* [U-Boot] [PATCH v2 15/26] mmc: add power cyle support in mmc core
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (13 preceding siblings ...)
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 14/26] mmc: Add a new callback function to perform the 74 clocks cycle sequence Jean-Jacques Hiblot
@ 2017-09-21 14:30   ` Jean-Jacques Hiblot
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 16/26] mmc: add a new mmc parameter to disable mmc clock Jean-Jacques Hiblot
                     ` (12 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:30 UTC (permalink / raw)
  To: u-boot

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

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 | 88 ++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 71 insertions(+), 17 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index fd93691..65a3d8e 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 int mmc_power_cycle(struct mmc *mmc);
 
 #if CONFIG_IS_ENABLED(MMC_TINY)
 static struct mmc mmc_static;
@@ -1920,25 +1921,83 @@ static int mmc_power_init(struct mmc *mmc)
 					  &mmc->vqmmc_supply);
 	if (ret)
 		debug("%s: No vqmmc supply\n", mmc->dev->name);
+#endif
+#else /* !CONFIG_DM_MMC */
+	/*
+	 * Driver model should use a regulator, as above, rather than calling
+	 * out to board code.
+	 */
+	board_mmc_power_init();
+#endif
+	return 0;
+}
+
+/*
+ * put the host in the initial state:
+ * - turn on Vdd (card power supply)
+ * - configure the bus width and clock to minimal values
+ */
+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("mmc: failed to set signal voltage\n");
+
+	mmc_select_mode(mmc, MMC_LEGACY);
+	mmc_set_bus_width(mmc, 1);
+	mmc_set_clock(mmc, 0);
+}
 
+static int mmc_power_on(struct mmc *mmc)
+{
+#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_REGULATOR)
 	if (mmc->vmmc_supply) {
-		ret = regulator_set_enable(mmc->vmmc_supply, true);
+		int ret = regulator_set_enable(mmc->vmmc_supply, true);
+
 		if (ret) {
 			puts("Error enabling VMMC supply\n");
 			return ret;
 		}
 	}
 #endif
-#else /* !CONFIG_DM_MMC */
-	/*
-	 * Driver model should use a regulator, as above, rather than calling
-	 * out to board code.
-	 */
-	board_mmc_power_init();
+	return 0;
+}
+
+static int mmc_power_off(struct mmc *mmc)
+{
+#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_REGULATOR)
+	if (mmc->vmmc_supply) {
+		int ret = regulator_set_enable(mmc->vmmc_supply, false);
+
+		if (ret) {
+			puts("Error disabling VMMC supply\n");
+			return ret;
+		}
+	}
 #endif
 	return 0;
 }
 
+static int mmc_power_cycle(struct mmc *mmc)
+{
+	int ret;
+
+	ret = mmc_power_off(mmc);
+	if (ret)
+		return ret;
+	/*
+	 * SD spec recommends at least 1ms of delay. Let's wait for 2ms
+	 * to be on the safer side.
+	 */
+	udelay(2000);
+	return mmc_power_on(mmc);
+}
+
 int mmc_start_init(struct mmc *mmc)
 {
 	bool no_card;
@@ -1967,6 +2026,10 @@ int mmc_start_init(struct mmc *mmc)
 	if (err)
 		return err;
 
+	err = mmc_power_on(mmc);
+	if (err)
+		return err;
+
 #if CONFIG_IS_ENABLED(DM_MMC)
 	/* The device has already been probed ready for use */
 #else
@@ -1977,16 +2040,7 @@ int mmc_start_init(struct mmc *mmc)
 #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);
-
+	mmc_set_initial_state(mmc);
 	mmc_send_init_stream(mmc);
 
 	/* Reset the Card */
-- 
1.9.1

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

* [U-Boot] [PATCH v2 16/26] mmc: add a new mmc parameter to disable mmc clock
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (14 preceding siblings ...)
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 15/26] mmc: add power cyle support in mmc core Jean-Jacques Hiblot
@ 2017-09-21 14:30   ` Jean-Jacques Hiblot
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 17/26] mmc: disable the mmc clock during power off Jean-Jacques Hiblot
                     ` (11 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:30 UTC (permalink / raw)
  To: u-boot

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

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           | 12 +++++++++++-
 3 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index cc188c4..6b52c6a 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -665,7 +665,7 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, 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 65a3d8e..1c941a2 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1214,7 +1214,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, bool disable)
 {
 	if (clock > mmc->cfg->f_max)
 		clock = mmc->cfg->f_max;
@@ -1223,6 +1223,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);
 }
@@ -1322,7 +1323,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)
@@ -1333,7 +1334,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);
 			}
 		}
 	}
@@ -1476,7 +1477,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);
@@ -1950,7 +1951,7 @@ static void mmc_set_initial_state(struct mmc *mmc)
 
 	mmc_select_mode(mmc, MMC_LEGACY);
 	mmc_set_bus_width(mmc, 1);
-	mmc_set_clock(mmc, 0);
+	mmc_set_clock(mmc, 0, false);
 }
 
 static int mmc_power_on(struct mmc *mmc)
diff --git a/include/mmc.h b/include/mmc.h
index bd096ae..8d6e0f8 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -472,6 +472,7 @@ struct mmc {
 	void *priv;
 	uint has_init;
 	int high_capacity;
+	bool clk_disable; /* true if the clock can be turned off */
 	uint bus_width;
 	uint clock;
 	enum mmc_voltage signal_voltage;
@@ -567,7 +568,16 @@ 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);
+
+/**
+ * mmc_set_clock() - change the bus clock
+ * @mmc:	MMC struct
+ * @clock:	bus frequency in Hz
+ * @disable:	flag indicating if the clock must on or off
+ * @return 0 if OK, -ve on error
+ */
+int mmc_set_clock(struct mmc *mmc, uint clock, bool 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] 50+ messages in thread

* [U-Boot] [PATCH v2 17/26] mmc: disable the mmc clock during power off
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (15 preceding siblings ...)
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 16/26] mmc: add a new mmc parameter to disable mmc clock Jean-Jacques Hiblot
@ 2017-09-21 14:30   ` Jean-Jacques Hiblot
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 18/26] mmc: Add a execute_tuning() callback to the mmc operations Jean-Jacques Hiblot
                     ` (10 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:30 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>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 drivers/mmc/mmc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 1c941a2..1f9730e 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1971,6 +1971,7 @@ static int mmc_power_on(struct mmc *mmc)
 
 static int mmc_power_off(struct mmc *mmc)
 {
+	mmc_set_clock(mmc, 1, true);
 #if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_REGULATOR)
 	if (mmc->vmmc_supply) {
 		int ret = regulator_set_enable(mmc->vmmc_supply, false);
-- 
1.9.1

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

* [U-Boot] [PATCH v2 18/26] mmc: Add a execute_tuning() callback to the mmc operations.
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (16 preceding siblings ...)
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 17/26] mmc: disable the mmc clock during power off Jean-Jacques Hiblot
@ 2017-09-21 14:30   ` Jean-Jacques Hiblot
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 19/26] mmc: add HS200 support in MMC core Jean-Jacques Hiblot
                     ` (9 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:30 UTC (permalink / raw)
  To: u-boot

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

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

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        |  5 +++++
 include/mmc.h            | 11 +++++++++++
 3 files changed, 30 insertions(+)

diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 9c6a8ba..60cc0ac 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -92,6 +92,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);
+}
+
 struct mmc *mmc_get_mmc_dev(struct udevice *dev)
 {
 	struct mmc_uclass_priv *upriv;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 1f9730e..3e2e549 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1199,6 +1199,11 @@ static inline int bus_width(uint cap)
 }
 
 #if !CONFIG_IS_ENABLED(DM_MMC)
+static int mmc_execute_tuning(struct mmc *mmc, uint opcode)
+{
+	return -ENOTSUPP;
+}
+
 static void mmc_send_init_stream(struct mmc *mmc)
 {
 }
diff --git a/include/mmc.h b/include/mmc.h
index 8d6e0f8..56fa869 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -383,6 +383,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)
@@ -393,12 +402,14 @@ int dm_mmc_set_ios(struct udevice *dev);
 void dm_mmc_send_init_stream(struct udevice *dev);
 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);
 void mmc_send_init_stream(struct mmc *mmc);
 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 {
-- 
1.9.1

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

* [U-Boot] [PATCH v2 19/26] mmc: add HS200 support in MMC core
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (17 preceding siblings ...)
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 18/26] mmc: Add a execute_tuning() callback to the mmc operations Jean-Jacques Hiblot
@ 2017-09-21 14:30   ` Jean-Jacques Hiblot
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 20/26] mmc: Add support for UHS modes Jean-Jacques Hiblot
                     ` (8 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:30 UTC (permalink / raw)
  To: u-boot

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

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>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 drivers/mmc/mmc.c | 22 ++++++++++++++++++++--
 include/mmc.h     | 18 ++++++++++++++++++
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 3e2e549..c663709 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;
@@ -1268,6 +1275,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)
@@ -1383,6 +1391,7 @@ static const struct mode_width_tuning mmc_modes_by_pref[] = {
 	{
 		.mode = MMC_HS_200,
 		.widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
+		.tuning = MMC_CMD_SEND_TUNING_BLOCK_HS200
 	},
 	{
 		.mode = MMC_DDR_52,
@@ -1484,6 +1493,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 56fa869..407fddf 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		BIT(30)
 #define MMC_MODE_4BIT		BIT(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_CMD_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_CMD_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,13 @@
 #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	BIT(4)	/* Card can run at 200MHz */
+						/* SDR mode @1.8V I/O */
+#define EXT_CSD_CARD_TYPE_HS200_1_2V	BIT(5)	/* Card can run at 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 */
@@ -219,6 +235,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] 50+ messages in thread

* [U-Boot] [PATCH v2 20/26] mmc: Add support for UHS modes
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (18 preceding siblings ...)
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 19/26] mmc: add HS200 support in MMC core Jean-Jacques Hiblot
@ 2017-09-21 14:30   ` Jean-Jacques Hiblot
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 21/26] mmc: disable UHS modes if Vcc cannot be switched on and off Jean-Jacques Hiblot
                     ` (7 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:30 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: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 drivers/mmc/mmc-uclass.c |  14 ++++
 drivers/mmc/mmc.c        | 176 ++++++++++++++++++++++++++++++++++++++++++++---
 include/mmc.h            |  40 ++++++++++-
 3 files changed, 221 insertions(+), 9 deletions(-)

diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 60cc0ac..7856e0a 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -64,6 +64,20 @@ void mmc_send_init_stream(struct mmc *mmc)
 	dm_mmc_send_init_stream(mmc->dev);
 }
 
+int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout)
+{
+	struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+	if (!ops->wait_dat0)
+		return -ENOSYS;
+	return ops->wait_dat0(dev, state, timeout);
+}
+
+int mmc_wait_dat0(struct mmc *mmc, int state, int timeout)
+{
+	return dm_mmc_wait_dat0(mmc->dev, state, timeout);
+}
+
 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 c663709..ca59e28 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -57,6 +57,12 @@ struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
 #endif
 
 #if !CONFIG_IS_ENABLED(DM_MMC)
+
+static int mmc_wait_dat0(struct mmc *mmc, int state, int timeout)
+{
+	return -ENOSYS;
+}
+
 __weak int board_mmc_getwp(struct mmc *mmc)
 {
 	return -1;
@@ -402,7 +408,67 @@ 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)
+		return err;
+
+	if (!mmc_host_is_spi(host) && (cmd.response[0] & MMC_STATUS_ERROR))
+		return -EIO;
+
+	/*
+	 * The card should drive cmd and dat[0:3] low immediately
+	 * after the response of cmd11, but wait 100 us to be sure
+	 */
+	err = mmc_wait_dat0(mmc, 0, 100);
+	if (err == -ENOSYS)
+		udelay(100);
+	else if (err)
+		return -ETIMEDOUT;
+
+	/*
+	 * 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)
+		return err;
+
+	/* Keep clock gated for at least 10 ms, though spec only says 5 ms */
+	mdelay(10);
+	mmc_set_clock(mmc, mmc->clock, false);
+
+	/*
+	 * Failure to switch is indicated by the card holding
+	 * dat[0:3] low. Wait for at least 1 ms according to spec
+	 */
+	err = mmc_wait_dat0(mmc, 1, 1000);
+	if (err == -ENOSYS)
+		udelay(1000);
+	else if (err)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int sd_send_op_cond(struct mmc *mmc, bool uhs_en)
 {
 	int timeout = 1000;
 	int err;
@@ -434,6 +500,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)
@@ -464,6 +533,13 @@ static int sd_send_op_cond(struct mmc *mmc)
 
 	mmc->ocr = cmd.response[0];
 
+	if (uhs_en && !(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 +1053,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 +1135,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;
 }
 
@@ -1066,12 +1159,35 @@ 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;
 
-	err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status);
+	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, 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;
@@ -1286,10 +1402,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_CMD_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,
 	}
@@ -1306,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),
@@ -1338,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;
@@ -2000,7 +2153,7 @@ static int mmc_power_off(struct mmc *mmc)
 		int ret = regulator_set_enable(mmc->vmmc_supply, false);
 
 		if (ret) {
-			puts("Error disabling VMMC supply\n");
+			debug("Error disabling VMMC supply\n");
 			return ret;
 		}
 	}
@@ -2026,6 +2179,7 @@ static int 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 */
@@ -2065,6 +2219,7 @@ int mmc_start_init(struct mmc *mmc)
 #endif
 	mmc->ddr_mode = 0;
 
+retry:
 	mmc_set_initial_state(mmc);
 	mmc_send_init_stream(mmc);
 
@@ -2081,7 +2236,12 @@ 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;
+		mmc_power_cycle(mmc);
+		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 407fddf..ba4a13e8 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_CMD_SEND_TUNING_BLOCK		19
 #define MMC_CMD_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_CMD_SEND_TUNING_BLOCK_HS200)
+	if ((cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200) ||
+	    (cmdidx == MMC_CMD_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	BIT(UHS_SDR12_BUS_SPEED)
+#define SD_MODE_UHS_SDR25	BIT(UHS_SDR25_BUS_SPEED)
+#define SD_MODE_UHS_SDR50	BIT(UHS_SDR50_BUS_SPEED)
+#define SD_MODE_UHS_SDR104	BIT(UHS_SDR104_BUS_SPEED)
+#define SD_MODE_UHS_DDR50	BIT(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
 
@@ -410,6 +426,17 @@ struct dm_mmc_ops {
 	 * @return 0 if OK, -ve on error
 	 */
 	int (*execute_tuning)(struct udevice *dev, uint opcode);
+
+	/**
+	 * wait_dat0() - wait until dat0 is in the target state
+	 *		(CLK must be running during the wait)
+	 *
+	 * @dev:	Device to check
+	 * @state:	target state
+	 * @timeout:	timeout in us
+	 * @return 0 if dat0 is in the target state, -ve on error
+	 */
+	int (*wait_dat0)(struct udevice *dev, int state, int timeout);
 };
 
 #define mmc_get_ops(dev)        ((struct dm_mmc_ops *)(dev)->driver->ops)
@@ -421,6 +448,7 @@ void dm_mmc_send_init_stream(struct udevice *dev);
 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_wait_dat0(struct udevice *dev, int state, int timeout);
 
 /* Transition functions for compatibility */
 int mmc_set_ios(struct mmc *mmc);
@@ -428,6 +456,7 @@ void mmc_send_init_stream(struct mmc *mmc);
 int mmc_getcd(struct mmc *mmc);
 int mmc_getwp(struct mmc *mmc);
 int mmc_execute_tuning(struct mmc *mmc, uint opcode);
+int mmc_wait_dat0(struct mmc *mmc, int state, int timeout);
 
 #else
 struct mmc_ops {
@@ -486,6 +515,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
  * with mmc_get_mmc_dev().
-- 
1.9.1

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

* [U-Boot] [PATCH v2 21/26] mmc: disable UHS modes if Vcc cannot be switched on and off
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (19 preceding siblings ...)
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 20/26] mmc: Add support for UHS modes Jean-Jacques Hiblot
@ 2017-09-21 14:30   ` Jean-Jacques Hiblot
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 22/26] mmc: Change mode when switching to a boot partition Jean-Jacques Hiblot
                     ` (6 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:30 UTC (permalink / raw)
  To: u-boot

If a power cycle cannot be done on Vcc, it is safer not to try the UHS
modes because we wouldn't be able to recover from an error occurring
during the UHS initialization.

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

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index ca59e28..31accdd 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1451,7 +1451,7 @@ static int sd_select_mode_and_width(struct mmc *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 = mmc->card_caps & (mmc->host_caps | MMC_MODE_1BIT);
 
 	if (!uhs_en)
 		caps &= ~UHS_CAPS;
@@ -1599,7 +1599,7 @@ static int mmc_select_mode_and_width(struct mmc *mmc)
 		return err;
 
 	/* Restrict card's capabilities by what the host can do */
-	mmc->card_caps &= (mmc->cfg->host_caps | MMC_MODE_1BIT);
+	mmc->card_caps &= (mmc->host_caps | MMC_MODE_1BIT);
 
 	/* Only version 4 of MMC supports wider bus widths */
 	if (mmc->version < MMC_VERSION_4)
@@ -2182,6 +2182,8 @@ int mmc_start_init(struct mmc *mmc)
 	bool uhs_en = supports_uhs(mmc->cfg->host_caps);
 	int err;
 
+	mmc->host_caps = mmc->cfg->host_caps;
+
 	/* we pretend there's no card when init is NULL */
 	no_card = mmc_getcd(mmc) == 0;
 #if !CONFIG_IS_ENABLED(DM_MMC)
@@ -2205,7 +2207,18 @@ int mmc_start_init(struct mmc *mmc)
 	if (err)
 		return err;
 
-	err = mmc_power_on(mmc);
+	err = mmc_power_cycle(mmc);
+	if (err) {
+		/*
+		 * if power cycling is not supported, we should not try
+		 * to use the UHS modes, because we wouldn't be able to
+		 * recover from an error during the UHS initialization.
+		 */
+		debug("Unable to do a full power cycle. Disabling the UHS modes for safety\n");
+		uhs_en = false;
+		mmc->host_caps &= ~UHS_CAPS;
+		err = mmc_power_on(mmc);
+	}
 	if (err)
 		return err;
 
diff --git a/include/mmc.h b/include/mmc.h
index ba4a13e8..59ea363 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -544,6 +544,7 @@ struct mmc {
 	uint clock;
 	enum mmc_voltage signal_voltage;
 	uint card_caps;
+	uint host_caps;
 	uint ocr;
 	uint dsr;
 	uint dsr_imp;
-- 
1.9.1

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

* [U-Boot] [PATCH v2 22/26] mmc: Change mode when switching to a boot partition
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (20 preceding siblings ...)
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 21/26] mmc: disable UHS modes if Vcc cannot be switched on and off Jean-Jacques Hiblot
@ 2017-09-21 14:30   ` Jean-Jacques Hiblot
  2018-07-24  8:28     ` Faiz Abbas
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 23/26] mmc: Retry some MMC cmds on failure Jean-Jacques Hiblot
                     ` (5 subsequent siblings)
  27 siblings, 1 reply; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:30 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>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 drivers/mmc/mmc.c | 66 +++++++++++++++++++++++++++++++++++++++++--------------
 include/mmc.h     |  7 +++++-
 2 files changed, 55 insertions(+), 18 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 31accdd..c5eaeaf 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 int mmc_power_cycle(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;
@@ -792,10 +793,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 forbidden = 0;
+	bool change = false;
+
+	if (part_num & PART_ACCESS_MASK)
+		forbidden = MMC_CAP(MMC_HS_200);
+
+	if (MMC_CAP(mmc->selected_mode) & forbidden) {
+		debug("selected mode (%s) is forbidden 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 & ~forbidden);
+
+	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->host_caps | MMC_MODE_1BIT);
+	caps = card_caps & (mmc->host_caps | MMC_MODE_1BIT);
 
 	if (!uhs_en)
 		caps &= ~UHS_CAPS;
@@ -1588,18 +1614,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->host_caps | MMC_MODE_1BIT);
+	card_caps &= (mmc->host_caps | MMC_MODE_1BIT);
 
 	/* Only version 4 of MMC supports wider bus widths */
 	if (mmc->version < MMC_VERSION_4)
@@ -1610,8 +1632,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),
@@ -2006,14 +2030,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 59ea363..a8901bf 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -585,7 +585,12 @@ struct mmc {
 #endif
 #endif
 	u8 *ext_csd;
-	enum bus_mode selected_mode;
+	enum bus_mode selected_mode; /* mode currently used */
+	enum bus_mode best_mode; /* best mode is the supported mode with the
+				  * highest bandwidth. It may not always be the
+				  * operating mode due to limitations when
+				  * accessing the boot partitions
+				  */
 };
 
 struct mmc_hwpart_conf {
-- 
1.9.1

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

* [U-Boot] [PATCH v2 23/26] mmc: Retry some MMC cmds on failure
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (21 preceding siblings ...)
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 22/26] mmc: Change mode when switching to a boot partition Jean-Jacques Hiblot
@ 2017-09-21 14:30   ` Jean-Jacques Hiblot
  2017-09-22 13:54     ` Jaehoon Chung
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 24/26] mmc: use the right voltage level for MMC DDR and HS200 modes Jean-Jacques Hiblot
                     ` (4 subsequent siblings)
  27 siblings, 1 reply; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:30 UTC (permalink / raw)
  To: u-boot

From: Kishon Vijay Abraham I <kishon@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 a few time
as done in Linux kernel.
Similarly, it is seen that MMC_CMD_SET_BLOCKLEN may fail on first
attempt, therefore retry this cmd a few times as done in kernel.

To make it clear that those are optionnal workarounds, a new Kconfig
option 'MMC_QUIRKS' is added (enabled by default).

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/Kconfig |  9 +++++++++
 drivers/mmc/mmc.c   | 41 +++++++++++++++++++++++++++++++++++++++--
 include/mmc.h       |  4 ++++
 3 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 3d577e0..78e58d4 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -33,6 +33,15 @@ config SPL_DM_MMC
 
 if MMC
 
+config MMC_QUIRKS
+	bool "Enable quirks"
+	default y
+	help
+	  Some cards and hosts may sometimes behave unexpectedly (quirks).
+	  This option enable workarounds to handle those quirks. Some of them
+	  are enabled by default, other may require additionnal flags or are
+	  enabled by the host driver.
+
 config MMC_VERBOSE
 	bool "Output more information about the MMC"
 	default y
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index c5eaeaf..6d1bf94 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -279,6 +279,7 @@ int mmc_send_status(struct mmc *mmc, int timeout)
 int mmc_set_blocklen(struct mmc *mmc, int len)
 {
 	struct mmc_cmd cmd;
+	int err;
 
 	if (mmc->ddr_mode)
 		return 0;
@@ -287,7 +288,24 @@ int mmc_set_blocklen(struct mmc *mmc, int len)
 	cmd.resp_type = MMC_RSP_R1;
 	cmd.cmdarg = len;
 
-	return mmc_send_cmd(mmc, &cmd, NULL);
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+
+#ifdef CONFIG_MMC_QUIRKS
+	if (err && (mmc->quirks & MMC_QUIRK_RETRY_SET_BLOCKLEN)) {
+		int retries = 4;
+		/*
+		 * It has been seen that SET_BLOCKLEN may fail on the first
+		 * attempt, let's try a few more time
+		 */
+		do {
+			err = mmc_send_cmd(mmc, &cmd, NULL);
+			if (!err)
+				break;
+		} while (retries--);
+	}
+#endif
+
+	return err;
 }
 
 static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
@@ -1881,7 +1899,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;
 	}
@@ -1895,6 +1912,21 @@ static int mmc_startup(struct mmc *mmc)
 
 	err = mmc_send_cmd(mmc, &cmd, NULL);
 
+#ifdef CONFIG_MMC_QUIRKS
+	if (err && (mmc->quirks & MMC_QUIRK_RETRY_SEND_CID)) {
+		int retries = 4;
+		/*
+		 * It has been seen that SEND_CID may fail on the first
+		 * attempt, let's try a few more time
+		 */
+		do {
+			err = mmc_send_cmd(mmc, &cmd, NULL);
+			if (!err)
+				break;
+		} while (retries--);
+	}
+#endif
+
 	if (err)
 		return err;
 
@@ -2239,6 +2271,11 @@ int mmc_start_init(struct mmc *mmc)
 	if (err)
 		return err;
 
+#ifdef CONFIG_MMC_QUIRKS
+	mmc->quirks = MMC_QUIRK_RETRY_SET_BLOCKLEN |
+		      MMC_QUIRK_RETRY_SEND_CID;
+#endif
+
 	err = mmc_power_cycle(mmc);
 	if (err) {
 		/*
diff --git a/include/mmc.h b/include/mmc.h
index a8901bf..a9ebc88 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -306,6 +306,9 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
 #define ENHNCD_SUPPORT		(0x2)
 #define PART_ENH_ATTRIB		(0x1f)
 
+#define MMC_QUIRK_RETRY_SEND_CID	BIT(0)
+#define MMC_QUIRK_RETRY_SET_BLOCKLEN	BIT(1)
+
 enum mmc_voltage {
 	MMC_SIGNAL_VOLTAGE_000 = 0,
 	MMC_SIGNAL_VOLTAGE_120,
@@ -591,6 +594,7 @@ struct mmc {
 				  * operating mode due to limitations when
 				  * accessing the boot partitions
 				  */
+	u32 quirks;
 };
 
 struct mmc_hwpart_conf {
-- 
1.9.1

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

* [U-Boot] [PATCH v2 24/26] mmc: use the right voltage level for MMC DDR and HS200 modes
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (22 preceding siblings ...)
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 23/26] mmc: Retry some MMC cmds on failure Jean-Jacques Hiblot
@ 2017-09-21 14:30   ` Jean-Jacques Hiblot
  2017-09-22 13:54     ` Jaehoon Chung
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 25/26] mmc: add a library function to send tuning command Jean-Jacques Hiblot
                     ` (3 subsequent siblings)
  27 siblings, 1 reply; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:30 UTC (permalink / raw)
  To: u-boot

HS200 only supports 1.2v and 1.8v signal voltages. DDR52 supports 3.3v/1.8v
or 1.2v signal voltages.
Select the lowest voltage available when using those modes.

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

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 6d1bf94..2d447dd 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -767,6 +767,7 @@ static int mmc_get_capabilities(struct mmc *mmc)
 	mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
 
 	cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0x3f;
+	mmc->cardtype = cardtype;
 
 	if (cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V |
 			EXT_CSD_CARD_TYPE_HS200_1_8V)) {
@@ -1441,10 +1442,30 @@ struct mode_width_tuning {
 	uint tuning;
 };
 
+int mmc_voltage_to_mv(enum mmc_voltage voltage)
+{
+	switch (voltage) {
+	case MMC_SIGNAL_VOLTAGE_000: return 0;
+	case MMC_SIGNAL_VOLTAGE_330: return 3300;
+	case MMC_SIGNAL_VOLTAGE_180: return 1800;
+	case MMC_SIGNAL_VOLTAGE_120: return 1200;
+	}
+	return -EINVAL;
+}
+
 static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
 {
+	int err;
+
+	if (mmc->signal_voltage == signal_voltage)
+		return 0;
+
 	mmc->signal_voltage = signal_voltage;
-	return mmc_set_ios(mmc);
+	err = mmc_set_ios(mmc);
+	if (err)
+		debug("unable to set voltage (err %d)\n", err);
+
+	return err;
 }
 
 static const struct mode_width_tuning sd_modes_by_pref[] = {
@@ -1584,6 +1605,43 @@ static int mmc_read_and_compare_ext_csd(struct mmc *mmc)
 	return -EBADMSG;
 }
 
+static int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode,
+				  uint32_t allowed_mask)
+{
+	u32 card_mask = 0;
+
+	switch (mode) {
+	case MMC_HS_200:
+		if (mmc->cardtype & EXT_CSD_CARD_TYPE_HS200_1_8V)
+			card_mask |= MMC_SIGNAL_VOLTAGE_180;
+		if (mmc->cardtype & EXT_CSD_CARD_TYPE_HS200_1_2V)
+			card_mask |= MMC_SIGNAL_VOLTAGE_120;
+		break;
+	case MMC_DDR_52:
+		if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V)
+			card_mask |= MMC_SIGNAL_VOLTAGE_330 |
+				     MMC_SIGNAL_VOLTAGE_180;
+		if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_2V)
+			card_mask |= MMC_SIGNAL_VOLTAGE_120;
+		break;
+	default:
+		card_mask |= MMC_SIGNAL_VOLTAGE_330;
+		break;
+	}
+
+	while (card_mask & allowed_mask) {
+		enum mmc_voltage best_match;
+
+		best_match = 1 << (ffs(card_mask & allowed_mask) - 1);
+		if (!mmc_set_signal_voltage(mmc,  best_match))
+			return 0;
+
+		allowed_mask &= ~best_match;
+	}
+
+	return -ENOTSUPP;
+}
+
 static const struct mode_width_tuning mmc_modes_by_pref[] = {
 	{
 		.mode = MMC_HS_200,
@@ -1655,10 +1713,17 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
 	for_each_mmc_mode_by_pref(card_caps, mwt) {
 		for_each_supported_width(card_caps & mwt->widths,
 					 mmc_is_mode_ddr(mwt->mode), ecbw) {
+			enum mmc_voltage old_voltage;
 			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);
+			old_voltage = mmc->signal_voltage;
+			err = mmc_set_lowest_voltage(mmc, mwt->mode,
+						     MMC_ALL_SIGNAL_VOLTAGE);
+			if (err)
+				continue;
+
 			/* configure the bus width (card + host) */
 			err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
 				    EXT_CSD_BUS_WIDTH,
@@ -1702,6 +1767,7 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
 			if (!err)
 				return 0;
 error:
+			mmc_set_signal_voltage(mmc, old_voltage);
 			/* 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);
diff --git a/include/mmc.h b/include/mmc.h
index a9ebc88..c11f698 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -311,11 +311,15 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
 
 enum mmc_voltage {
 	MMC_SIGNAL_VOLTAGE_000 = 0,
-	MMC_SIGNAL_VOLTAGE_120,
-	MMC_SIGNAL_VOLTAGE_180,
-	MMC_SIGNAL_VOLTAGE_330
+	MMC_SIGNAL_VOLTAGE_120 = 1,
+	MMC_SIGNAL_VOLTAGE_180 = 2,
+	MMC_SIGNAL_VOLTAGE_330 = 4,
 };
 
+#define MMC_ALL_SIGNAL_VOLTAGE (MMC_SIGNAL_VOLTAGE_120 |\
+				MMC_SIGNAL_VOLTAGE_180 |\
+				MMC_SIGNAL_VOLTAGE_330)
+
 /* Maximum block size for MMC */
 #define MMC_MAX_BLOCK_LEN	512
 
@@ -588,6 +592,8 @@ struct mmc {
 #endif
 #endif
 	u8 *ext_csd;
+	u32 cardtype;		/* cardtype read from the MMC */
+	enum mmc_voltage current_voltage;
 	enum bus_mode selected_mode; /* mode currently used */
 	enum bus_mode best_mode; /* best mode is the supported mode with the
 				  * highest bandwidth. It may not always be the
@@ -647,6 +653,14 @@ int mmc_init(struct mmc *mmc);
 int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
 
 /**
+ * mmc_voltage_to_mv() - Convert a mmc_voltage in mV
+ *
+ * @voltage:	The mmc_voltage to convert
+ * @return the value in mV if OK, -EINVAL on error (invalid mmc_voltage value)
+ */
+int mmc_voltage_to_mv(enum mmc_voltage voltage);
+
+/**
  * mmc_set_clock() - change the bus clock
  * @mmc:	MMC struct
  * @clock:	bus frequency in Hz
-- 
1.9.1

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

* [U-Boot] [PATCH v2 25/26] mmc: add a library function to send tuning command
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (23 preceding siblings ...)
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 24/26] mmc: use the right voltage level for MMC DDR and HS200 modes Jean-Jacques Hiblot
@ 2017-09-21 14:30   ` Jean-Jacques Hiblot
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 26/26] dm: mmc: Add a library function to parse generic dt binding Jean-Jacques Hiblot
                     ` (2 subsequent siblings)
  27 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:30 UTC (permalink / raw)
  To: u-boot

HS200/SDR104 requires tuning command to be sent to the card.
Add a simple function to send tuning command and to read and
compare the received data with the tuning block pattern.
This function can be used by platform driver to perform DLL
tuning.
This patch is similar to
commit 996903de92f0 ("mmc: core: add core-level function for
sending tuning commands") added in linux kernel.

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

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 2d447dd..47e0c99 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -308,6 +308,74 @@ int mmc_set_blocklen(struct mmc *mmc, int len)
 	return err;
 }
 
+static const u8 tuning_blk_pattern_4bit[] = {
+	0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
+	0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
+	0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
+	0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
+	0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
+	0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
+	0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
+	0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
+};
+
+static const u8 tuning_blk_pattern_8bit[] = {
+	0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
+	0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
+	0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
+	0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
+	0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
+	0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
+	0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
+	0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
+	0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
+	0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
+	0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
+	0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
+	0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
+	0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
+	0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
+	0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
+};
+
+int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error)
+{
+	struct mmc_cmd cmd;
+	struct mmc_data data;
+	const u8 *tuning_block_pattern;
+	int size, err;
+
+	if (mmc->bus_width == 8) {
+		tuning_block_pattern = tuning_blk_pattern_8bit;
+		size = sizeof(tuning_blk_pattern_8bit);
+	} else if (mmc->bus_width == 4) {
+		tuning_block_pattern = tuning_blk_pattern_4bit;
+		size = sizeof(tuning_blk_pattern_4bit);
+	} else {
+		return -EINVAL;
+	}
+
+	ALLOC_CACHE_ALIGN_BUFFER(u8, data_buf, size);
+
+	cmd.cmdidx = opcode;
+	cmd.cmdarg = 0;
+	cmd.resp_type = MMC_RSP_R1;
+
+	data.dest = (void *)data_buf;
+	data.blocks = 1;
+	data.blocksize = size;
+	data.flags = MMC_DATA_READ;
+
+	err = mmc_send_cmd(mmc, &cmd, &data);
+	if (err)
+		return err;
+
+	if (memcmp(data_buf, tuning_block_pattern, size))
+		return -EIO;
+
+	return 0;
+}
+
 static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
 			   lbaint_t blkcnt)
 {
diff --git a/include/mmc.h b/include/mmc.h
index c11f698..79be6b4 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -650,6 +650,7 @@ void mmc_destroy(struct mmc *mmc);
 int mmc_unbind(struct udevice *dev);
 int mmc_initialize(bd_t *bis);
 int mmc_init(struct mmc *mmc);
+int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error);
 int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
 
 /**
-- 
1.9.1

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

* [U-Boot] [PATCH v2 26/26] dm: mmc: Add a library function to parse generic dt binding
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (24 preceding siblings ...)
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 25/26] mmc: add a library function to send tuning command Jean-Jacques Hiblot
@ 2017-09-21 14:30   ` Jean-Jacques Hiblot
  2017-09-22 13:54     ` Jaehoon Chung
  2017-09-25  2:14     ` Simon Glass
  2017-09-22 14:42   ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jaehoon Chung
  2017-10-20 11:31   ` Jaehoon Chung
  27 siblings, 2 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-09-21 14:30 UTC (permalink / raw)
  To: u-boot

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

Add a new function to parse host controller dt node and
set mmc_config. This function can be used by mmc controller
drivers to set the generic mmc_config.
This function can be extended to set other UHS mode caps
once UHS mode support is added.

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

diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 7856e0a..e30cde7 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -120,6 +120,52 @@ int mmc_execute_tuning(struct mmc *mmc, uint opcode)
 	return dm_mmc_execute_tuning(mmc->dev, opcode);
 }
 
+int mmc_of_parse(const void *fdt, int node, struct mmc_config *cfg)
+{
+	int val;
+
+	val = fdtdec_get_int(fdt, node, "bus-width", 1);
+
+	switch (val) {
+	case 0x8:
+		cfg->host_caps |= MMC_MODE_8BIT;
+		/* fall through */
+	case 0x4:
+		cfg->host_caps |= MMC_MODE_4BIT;
+		/* fall through */
+	case 0x1:
+		cfg->host_caps |= MMC_MODE_1BIT;
+		break;
+	default:
+		printf("error: %s invalid bus-width property %d\n",
+		       fdt_get_name(fdt, node, NULL), val);
+		return -ENOENT;
+	}
+
+	cfg->f_max = fdtdec_get_int(fdt, node, "max-frequency", 52000000);
+
+	if (fdtdec_get_bool(fdt, node, "cap-sd-highspeed"))
+		cfg->host_caps |= MMC_CAP(SD_HS);
+	if (fdtdec_get_bool(fdt, node, "cap-mmc-highspeed"))
+		cfg->host_caps |= MMC_CAP(MMC_HS);
+	if (fdtdec_get_bool(fdt, node, "sd-uhs-sdr12"))
+		cfg->host_caps |= MMC_CAP(UHS_SDR12);
+	if (fdtdec_get_bool(fdt, node, "sd-uhs-sdr25"))
+		cfg->host_caps |= MMC_CAP(UHS_SDR25);
+	if (fdtdec_get_bool(fdt, node, "sd-uhs-sdr50"))
+		cfg->host_caps |= MMC_CAP(UHS_SDR50);
+	if (fdtdec_get_bool(fdt, node, "sd-uhs-sdr104"))
+		cfg->host_caps |= MMC_CAP(UHS_SDR104);
+	if (fdtdec_get_bool(fdt, node, "sd-uhs-ddr50"))
+		cfg->host_caps |= MMC_CAP(UHS_DDR50);
+	if (fdtdec_get_bool(fdt, node, "mmc-ddr-1_8v"))
+		cfg->host_caps |= MMC_CAP(MMC_DDR_52);
+	if (fdtdec_get_bool(fdt, node, "mmc-hs200-1_8v"))
+		cfg->host_caps |= MMC_CAP(MMC_HS_200);
+
+	return 0;
+}
+
 struct mmc *mmc_get_mmc_dev(struct udevice *dev)
 {
 	struct mmc_uclass_priv *upriv;
diff --git a/include/mmc.h b/include/mmc.h
index 79be6b4..6230a32 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -651,6 +651,7 @@ int mmc_unbind(struct udevice *dev);
 int mmc_initialize(bd_t *bis);
 int mmc_init(struct mmc *mmc);
 int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error);
+int mmc_of_parse(const void *fdt, int node, struct mmc_config *cfg);
 int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
 
 /**
-- 
1.9.1

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

* [U-Boot] [PATCH v2 07/26] mmc: Add a function to dump the mmc capabilities
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 07/26] mmc: Add a function to dump the mmc capabilities Jean-Jacques Hiblot
@ 2017-09-22 13:54     ` Jaehoon Chung
  2017-10-02  8:57       ` Jean-Jacques Hiblot
  0 siblings, 1 reply; 50+ messages in thread
From: Jaehoon Chung @ 2017-09-22 13:54 UTC (permalink / raw)
  To: u-boot

Hi,

On 09/21/2017 11:29 PM, Jean-Jacques Hiblot wrote:
> This adds a simple helper function to display information (bus width and
> mode) based on a capability mask. Useful for debug.

I agreed this is useful.. but there is no usage in your patch.
How did you use this? and Where does call this function..

I think it can be used the one of mmc command. how about?

Best Regards,
Jaehoon Chung

> 
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 24 ++++++++++++++++++++++++
>  include/mmc.h     |  1 +
>  2 files changed, 25 insertions(+)
> 
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 94b3a02..0b74e78 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -1136,6 +1136,30 @@ static void mmc_set_bus_width(struct mmc *mmc, uint width)
>  	mmc_set_ios(mmc);
>  }
>  
> +#if CONFIG_IS_ENABLED(MMC_VERBOSE) || defined(DEBUG)
> +/*
> + * helper function to display the capabilities in a human
> + * friendly manner. The capabilities include bus width and
> + * supported modes.
> + */
> +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");
> +}
> +#endif
> +
>  static int sd_select_bus_freq_width(struct mmc *mmc)
>  {
>  	int err;
> diff --git a/include/mmc.h b/include/mmc.h
> index 76bd57a..dd83f14 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -426,6 +426,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
> 

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

* [U-Boot] [PATCH v2 13/26] mmc: Enable signal voltage to be selected from mmc core
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 13/26] mmc: Enable signal voltage to be selected from mmc core Jean-Jacques Hiblot
@ 2017-09-22 13:54     ` Jaehoon Chung
  2017-10-02  9:04       ` Jean-Jacques Hiblot
  0 siblings, 1 reply; 50+ messages in thread
From: Jaehoon Chung @ 2017-09-22 13:54 UTC (permalink / raw)
  To: u-boot

On 09/21/2017 11:30 PM, Jean-Jacques Hiblot 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 | 16 ++++++++++++++++
>  include/mmc.h     |  8 ++++++++
>  2 files changed, 24 insertions(+)
> 
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 536cd7f..46ec5e1 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -30,6 +30,8 @@ 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);
> +
>  #if CONFIG_IS_ENABLED(MMC_TINY)
>  static struct mmc mmc_static;
>  struct mmc *find_mmc_device(int dev_num)
> @@ -1257,6 +1259,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,
> @@ -1964,6 +1972,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");
> +

Well, it's confused. if 3.3v and 1.8v are failed, there is no problem?
last signal value should be set to 1.8v. Is it correct?

Why didn't try to set the 1.2 voltage?

>  	mmc_set_bus_width(mmc, 1);
>  	mmc_set_clock(mmc, 1);
>  
> diff --git a/include/mmc.h b/include/mmc.h
> index 3e57887..e524963 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -272,6 +272,13 @@
>  #define ENHNCD_SUPPORT		(0x2)
>  #define PART_ENH_ATTRIB		(0x1f)
>  
> +enum mmc_voltage {
> +	MMC_SIGNAL_VOLTAGE_000 = 0,
> +	MMC_SIGNAL_VOLTAGE_120,
> +	MMC_SIGNAL_VOLTAGE_180,
> +	MMC_SIGNAL_VOLTAGE_330
> +};
> +
>  /* Maximum block size for MMC */
>  #define MMC_MAX_BLOCK_LEN	512
>  
> @@ -457,6 +464,7 @@ struct mmc {
>  	int high_capacity;
>  	uint bus_width;
>  	uint clock;
> +	enum mmc_voltage signal_voltage;
>  	uint card_caps;
>  	uint ocr;
>  	uint dsr;
> 

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

* [U-Boot] [PATCH v2 23/26] mmc: Retry some MMC cmds on failure
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 23/26] mmc: Retry some MMC cmds on failure Jean-Jacques Hiblot
@ 2017-09-22 13:54     ` Jaehoon Chung
  2017-10-02  9:05       ` Jean-Jacques Hiblot
  0 siblings, 1 reply; 50+ messages in thread
From: Jaehoon Chung @ 2017-09-22 13:54 UTC (permalink / raw)
  To: u-boot

On 09/21/2017 11:30 PM, Jean-Jacques Hiblot wrote:
> From: Kishon Vijay Abraham I <kishon@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 a few time
> as done in Linux kernel.
> Similarly, it is seen that MMC_CMD_SET_BLOCKLEN may fail on first
> attempt, therefore retry this cmd a few times as done in kernel.
> 
> To make it clear that those are optionnal workarounds, a new Kconfig
> option 'MMC_QUIRKS' is added (enabled by default).
> 
> 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/Kconfig |  9 +++++++++
>  drivers/mmc/mmc.c   | 41 +++++++++++++++++++++++++++++++++++++++--
>  include/mmc.h       |  4 ++++
>  3 files changed, 52 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
> index 3d577e0..78e58d4 100644
> --- a/drivers/mmc/Kconfig
> +++ b/drivers/mmc/Kconfig
> @@ -33,6 +33,15 @@ config SPL_DM_MMC
>  
>  if MMC
>  
> +config MMC_QUIRKS
> +	bool "Enable quirks"
> +	default y
> +	help
> +	  Some cards and hosts may sometimes behave unexpectedly (quirks).
> +	  This option enable workarounds to handle those quirks. Some of them
> +	  are enabled by default, other may require additionnal flags or are
> +	  enabled by the host driver.
> +
>  config MMC_VERBOSE
>  	bool "Output more information about the MMC"
>  	default y
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index c5eaeaf..6d1bf94 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -279,6 +279,7 @@ int mmc_send_status(struct mmc *mmc, int timeout)
>  int mmc_set_blocklen(struct mmc *mmc, int len)
>  {
>  	struct mmc_cmd cmd;
> +	int err;
>  
>  	if (mmc->ddr_mode)
>  		return 0;
> @@ -287,7 +288,24 @@ int mmc_set_blocklen(struct mmc *mmc, int len)
>  	cmd.resp_type = MMC_RSP_R1;
>  	cmd.cmdarg = len;
>  
> -	return mmc_send_cmd(mmc, &cmd, NULL);
> +	err = mmc_send_cmd(mmc, &cmd, NULL);
> +
> +#ifdef CONFIG_MMC_QUIRKS
> +	if (err && (mmc->quirks & MMC_QUIRK_RETRY_SET_BLOCKLEN)) {
> +		int retries = 4;
> +		/*
> +		 * It has been seen that SET_BLOCKLEN may fail on the first
> +		 * attempt, let's try a few more time
> +		 */
> +		do {
> +			err = mmc_send_cmd(mmc, &cmd, NULL);
> +			if (!err)
> +				break;
> +		} while (retries--);
> +	}
> +#endif
> +
> +	return err;
>  }
>  
>  static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
> @@ -1881,7 +1899,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;
>  	}
> @@ -1895,6 +1912,21 @@ static int mmc_startup(struct mmc *mmc)
>  
>  	err = mmc_send_cmd(mmc, &cmd, NULL);
>  
> +#ifdef CONFIG_MMC_QUIRKS
> +	if (err && (mmc->quirks & MMC_QUIRK_RETRY_SEND_CID)) {
> +		int retries = 4;
> +		/*
> +		 * It has been seen that SEND_CID may fail on the first
> +		 * attempt, let's try a few more time
> +		 */
> +		do {
> +			err = mmc_send_cmd(mmc, &cmd, NULL);
> +			if (!err)
> +				break;
> +		} while (retries--);
> +	}
> +#endif
> +
>  	if (err)
>  		return err;
>  
> @@ -2239,6 +2271,11 @@ int mmc_start_init(struct mmc *mmc)
>  	if (err)
>  		return err;
>  
> +#ifdef CONFIG_MMC_QUIRKS
> +	mmc->quirks = MMC_QUIRK_RETRY_SET_BLOCKLEN |
> +		      MMC_QUIRK_RETRY_SEND_CID;
> +#endif
> +
>  	err = mmc_power_cycle(mmc);
>  	if (err) {
>  		/*
> diff --git a/include/mmc.h b/include/mmc.h
> index a8901bf..a9ebc88 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -306,6 +306,9 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
>  #define ENHNCD_SUPPORT		(0x2)
>  #define PART_ENH_ATTRIB		(0x1f)
>  
> +#define MMC_QUIRK_RETRY_SEND_CID	BIT(0)
> +#define MMC_QUIRK_RETRY_SET_BLOCKLEN	BIT(1)
> +
>  enum mmc_voltage {
>  	MMC_SIGNAL_VOLTAGE_000 = 0,
>  	MMC_SIGNAL_VOLTAGE_120,
> @@ -591,6 +594,7 @@ struct mmc {
>  				  * operating mode due to limitations when
>  				  * accessing the boot partitions
>  				  */
> +	u32 quirks;

Use the #ifdef MMC_QUIRK for quirks?

>  };
>  
>  struct mmc_hwpart_conf {
> 

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

* [U-Boot] [PATCH v2 24/26] mmc: use the right voltage level for MMC DDR and HS200 modes
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 24/26] mmc: use the right voltage level for MMC DDR and HS200 modes Jean-Jacques Hiblot
@ 2017-09-22 13:54     ` Jaehoon Chung
  0 siblings, 0 replies; 50+ messages in thread
From: Jaehoon Chung @ 2017-09-22 13:54 UTC (permalink / raw)
  To: u-boot

On 09/21/2017 11:30 PM, Jean-Jacques Hiblot wrote:
> HS200 only supports 1.2v and 1.8v signal voltages. DDR52 supports 3.3v/1.8v
> or 1.2v signal voltages.
> Select the lowest voltage available when using those modes.
> 
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  include/mmc.h     | 20 +++++++++++++---
>  2 files changed, 84 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 6d1bf94..2d447dd 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -767,6 +767,7 @@ static int mmc_get_capabilities(struct mmc *mmc)
>  	mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
>  
>  	cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0x3f;
> +	mmc->cardtype = cardtype;
>  
>  	if (cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V |
>  			EXT_CSD_CARD_TYPE_HS200_1_8V)) {
> @@ -1441,10 +1442,30 @@ struct mode_width_tuning {
>  	uint tuning;
>  };
>  
> +int mmc_voltage_to_mv(enum mmc_voltage voltage)
> +{
> +	switch (voltage) {
> +	case MMC_SIGNAL_VOLTAGE_000: return 0;
> +	case MMC_SIGNAL_VOLTAGE_330: return 3300;
> +	case MMC_SIGNAL_VOLTAGE_180: return 1800;
> +	case MMC_SIGNAL_VOLTAGE_120: return 1200;

Plz, change line.
case xxx:
	return xxx;

> +	}
> +	return -EINVAL;
> +}
> +
>  static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage)
>  {
> +	int err;

Initialized err = 0

> +
> +	if (mmc->signal_voltage == signal_voltage)
> +		return 0;

return err; or use return ret?

> +
>  	mmc->signal_voltage = signal_voltage;
> -	return mmc_set_ios(mmc);
> +	err = mmc_set_ios(mmc);
> +	if (err)
> +		debug("unable to set voltage (err %d)\n", err);
> +
> +	return err;
>  }
>  
>  static const struct mode_width_tuning sd_modes_by_pref[] = {
> @@ -1584,6 +1605,43 @@ static int mmc_read_and_compare_ext_csd(struct mmc *mmc)
>  	return -EBADMSG;
>  }
>  
> +static int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode,
> +				  uint32_t allowed_mask)
> +{
> +	u32 card_mask = 0;
> +
> +	switch (mode) {
> +	case MMC_HS_200:
> +		if (mmc->cardtype & EXT_CSD_CARD_TYPE_HS200_1_8V)
> +			card_mask |= MMC_SIGNAL_VOLTAGE_180;
> +		if (mmc->cardtype & EXT_CSD_CARD_TYPE_HS200_1_2V)
> +			card_mask |= MMC_SIGNAL_VOLTAGE_120;
> +		break;
> +	case MMC_DDR_52:
> +		if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V)
> +			card_mask |= MMC_SIGNAL_VOLTAGE_330 |
> +				     MMC_SIGNAL_VOLTAGE_180;
> +		if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_2V)
> +			card_mask |= MMC_SIGNAL_VOLTAGE_120;
> +		break;
> +	default:
> +		card_mask |= MMC_SIGNAL_VOLTAGE_330;
> +		break;
> +	}
> +
> +	while (card_mask & allowed_mask) {
> +		enum mmc_voltage best_match;
> +
> +		best_match = 1 << (ffs(card_mask & allowed_mask) - 1);
> +		if (!mmc_set_signal_voltage(mmc,  best_match))
> +			return 0;

Just return 0?

> +
> +		allowed_mask &= ~best_match;
> +	}
> +
> +	return -ENOTSUPP;
> +}
> +
>  static const struct mode_width_tuning mmc_modes_by_pref[] = {
>  	{
>  		.mode = MMC_HS_200,
> @@ -1655,10 +1713,17 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
>  	for_each_mmc_mode_by_pref(card_caps, mwt) {
>  		for_each_supported_width(card_caps & mwt->widths,
>  					 mmc_is_mode_ddr(mwt->mode), ecbw) {
> +			enum mmc_voltage old_voltage;
>  			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);
> +			old_voltage = mmc->signal_voltage;
> +			err = mmc_set_lowest_voltage(mmc, mwt->mode,
> +						     MMC_ALL_SIGNAL_VOLTAGE);
> +			if (err)
> +				continue;
> +
>  			/* configure the bus width (card + host) */
>  			err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
>  				    EXT_CSD_BUS_WIDTH,
> @@ -1702,6 +1767,7 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
>  			if (!err)
>  				return 0;
>  error:
> +			mmc_set_signal_voltage(mmc, old_voltage);

doesn't need to check the return value?

>  			/* 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);
> diff --git a/include/mmc.h b/include/mmc.h
> index a9ebc88..c11f698 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -311,11 +311,15 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
>  
>  enum mmc_voltage {
>  	MMC_SIGNAL_VOLTAGE_000 = 0,
> -	MMC_SIGNAL_VOLTAGE_120,
> -	MMC_SIGNAL_VOLTAGE_180,
> -	MMC_SIGNAL_VOLTAGE_330
> +	MMC_SIGNAL_VOLTAGE_120 = 1,
> +	MMC_SIGNAL_VOLTAGE_180 = 2,
> +	MMC_SIGNAL_VOLTAGE_330 = 4,
>  };
>  
> +#define MMC_ALL_SIGNAL_VOLTAGE (MMC_SIGNAL_VOLTAGE_120 |\
> +				MMC_SIGNAL_VOLTAGE_180 |\
> +				MMC_SIGNAL_VOLTAGE_330)
> +
>  /* Maximum block size for MMC */
>  #define MMC_MAX_BLOCK_LEN	512
>  
> @@ -588,6 +592,8 @@ struct mmc {
>  #endif
>  #endif
>  	u8 *ext_csd;
> +	u32 cardtype;		/* cardtype read from the MMC */
> +	enum mmc_voltage current_voltage;
>  	enum bus_mode selected_mode; /* mode currently used */
>  	enum bus_mode best_mode; /* best mode is the supported mode with the
>  				  * highest bandwidth. It may not always be the
> @@ -647,6 +653,14 @@ int mmc_init(struct mmc *mmc);
>  int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
>  
>  /**
> + * mmc_voltage_to_mv() - Convert a mmc_voltage in mV
> + *
> + * @voltage:	The mmc_voltage to convert
> + * @return the value in mV if OK, -EINVAL on error (invalid mmc_voltage value)
> + */
> +int mmc_voltage_to_mv(enum mmc_voltage voltage);
> +
> +/**
>   * mmc_set_clock() - change the bus clock
>   * @mmc:	MMC struct
>   * @clock:	bus frequency in Hz
> 

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

* [U-Boot] [PATCH v2 26/26] dm: mmc: Add a library function to parse generic dt binding
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 26/26] dm: mmc: Add a library function to parse generic dt binding Jean-Jacques Hiblot
@ 2017-09-22 13:54     ` Jaehoon Chung
  2017-10-02  9:08       ` Jean-Jacques Hiblot
  2017-09-25  2:14     ` Simon Glass
  1 sibling, 1 reply; 50+ messages in thread
From: Jaehoon Chung @ 2017-09-22 13:54 UTC (permalink / raw)
  To: u-boot

On 09/21/2017 11:30 PM, Jean-Jacques Hiblot wrote:
> From: Kishon Vijay Abraham I <kishon@ti.com>
> 
> Add a new function to parse host controller dt node and
> set mmc_config. This function can be used by mmc controller
> drivers to set the generic mmc_config.
> This function can be extended to set other UHS mode caps
> once UHS mode support is added.
> 
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc-uclass.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>  include/mmc.h            |  1 +
>  2 files changed, 47 insertions(+)
> 
> diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
> index 7856e0a..e30cde7 100644
> --- a/drivers/mmc/mmc-uclass.c
> +++ b/drivers/mmc/mmc-uclass.c
> @@ -120,6 +120,52 @@ int mmc_execute_tuning(struct mmc *mmc, uint opcode)
>  	return dm_mmc_execute_tuning(mmc->dev, opcode);
>  }
>  
> +int mmc_of_parse(const void *fdt, int node, struct mmc_config *cfg)
> +{
> +	int val;
> +
> +	val = fdtdec_get_int(fdt, node, "bus-width", 1);
> +
> +	switch (val) {
> +	case 0x8:
> +		cfg->host_caps |= MMC_MODE_8BIT;
> +		/* fall through */
> +	case 0x4:
> +		cfg->host_caps |= MMC_MODE_4BIT;
> +		/* fall through */
> +	case 0x1:
> +		cfg->host_caps |= MMC_MODE_1BIT;
> +		break;
> +	default:
> +		printf("error: %s invalid bus-width property %d\n",
> +		       fdt_get_name(fdt, node, NULL), val);

I guess it can be set to 1-bit by default and just display message about invalid bus-width property.

> +		return -ENOENT;
> +	}
> +
> +	cfg->f_max = fdtdec_get_int(fdt, node, "max-frequency", 52000000);
> +
> +	if (fdtdec_get_bool(fdt, node, "cap-sd-highspeed"))
> +		cfg->host_caps |= MMC_CAP(SD_HS);
> +	if (fdtdec_get_bool(fdt, node, "cap-mmc-highspeed"))
> +		cfg->host_caps |= MMC_CAP(MMC_HS);
> +	if (fdtdec_get_bool(fdt, node, "sd-uhs-sdr12"))
> +		cfg->host_caps |= MMC_CAP(UHS_SDR12);
> +	if (fdtdec_get_bool(fdt, node, "sd-uhs-sdr25"))
> +		cfg->host_caps |= MMC_CAP(UHS_SDR25);
> +	if (fdtdec_get_bool(fdt, node, "sd-uhs-sdr50"))
> +		cfg->host_caps |= MMC_CAP(UHS_SDR50);
> +	if (fdtdec_get_bool(fdt, node, "sd-uhs-sdr104"))
> +		cfg->host_caps |= MMC_CAP(UHS_SDR104);
> +	if (fdtdec_get_bool(fdt, node, "sd-uhs-ddr50"))
> +		cfg->host_caps |= MMC_CAP(UHS_DDR50);
> +	if (fdtdec_get_bool(fdt, node, "mmc-ddr-1_8v"))
> +		cfg->host_caps |= MMC_CAP(MMC_DDR_52);
> +	if (fdtdec_get_bool(fdt, node, "mmc-hs200-1_8v"))
> +		cfg->host_caps |= MMC_CAP(MMC_HS_200);

Don't need to check about 1.2v?

> +
> +	return 0;
> +}
> +
>  struct mmc *mmc_get_mmc_dev(struct udevice *dev)
>  {
>  	struct mmc_uclass_priv *upriv;
> diff --git a/include/mmc.h b/include/mmc.h
> index 79be6b4..6230a32 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -651,6 +651,7 @@ int mmc_unbind(struct udevice *dev);
>  int mmc_initialize(bd_t *bis);
>  int mmc_init(struct mmc *mmc);
>  int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error);
> +int mmc_of_parse(const void *fdt, int node, struct mmc_config *cfg);
>  int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
>  
>  /**
> 

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

* [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (25 preceding siblings ...)
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 26/26] dm: mmc: Add a library function to parse generic dt binding Jean-Jacques Hiblot
@ 2017-09-22 14:42   ` Jaehoon Chung
  2017-10-02  9:15     ` Jean-Jacques Hiblot
  2017-10-20 11:31   ` Jaehoon Chung
  27 siblings, 1 reply; 50+ messages in thread
From: Jaehoon Chung @ 2017-09-22 14:42 UTC (permalink / raw)
  To: u-boot

Dear JJ,

On 09/21/2017 11:29 PM, 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, Atmel SAMA5D3 xplained). 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 5 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:
> - send the initialization stream (74 clock cycles)
> - wait while the card is busy (used during UHS voltage switching). checking is
>   done on dat0.
> - 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.
> Also in case of a reset (as opposed to a power on), it ensures that the SDCard
> is in clean state before re-doing the initialization.
> 
> And finally the last commits add the support for HS200 and UHS.
> 
> With this in place and the required changes in the HSMMC host driver (including
> DMA), we observe significant improvements in the performances on a DRA72 evm:
> eMMC HS200: 124 MB/s
> eMMC DDR52: 78 MB/s
> sd   SDR104: 71 MB/s
> sd   SDR50: 44 MB/s

I have one question. 

Did you test about accessing Boot partition of eMMC?
As i know, boot partition doesn't support the HS200 mode.

When i checked your patches, there is no the function of mode changing for accessing boot partition.
If i missed it, let me know, plz.

Best Regards,
Jaehoon Chung

> 
> cheers,
> 
> Jean-Jacques
> 
> changes since v1:
> Changes take in account all the comment made during the first round of review.
> But it also include a rework of the handling of the voltage supplies and 2 new
> helper functions that can be used by the host driver during tuning and dts
> parsing.
> 
> Here is a detailed list:
>  * rebase on u-boot/master.
>  * add the description for the new functions/members
>  * fix the typos found in the reviews
>  * limit the new features to DM_MMC only
>  * fix the new checkpatch warnings/errors (is it now more strict ?)
>  * get the voltage regulators from dts (main and IO-lines)
>  * remove the set_vdd callback and do the job in the mmc core
>  * add a send_init_stream callback to perform the 74 clock cycle
>    sequence after power up
>  * do a full power cycle (if possible) before the initialization. This ensures
>    that the sd/MMC is in valid knwon state. Also it allows to check if the power
>    cycling works as expected.
>  * disable the UHS modes is power cycling is not available/working. This ensures
>    that we won't be stuck if the UHS initialization fails.
>  * select the appropriate signal voltage when selecting a mode (MMC only) 
>  * add a helper function to parse the generic dt bindings
>  * add a helper function to send the tuning command
>  
> Jean-Jacques Hiblot (17):
>   mmc: dm: get the IO-line and main voltage regulators from the dts
>   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: introduce mmc modes
>   mmc: Add a function 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: Add a new callback function to perform the 74 clocks cycle
>     sequence
>   mmc: Add support for UHS modes
>   mmc: disable UHS modes if Vcc cannot be switched on and off
>   mmc: Change mode when switching to a boot partition
>   mmc: use the right voltage level for MMC DDR and HS200 modes
>   mmc: add a library function to send tuning command
> 
> Kishon Vijay Abraham I (9):
>   mmc: make mmc_set_ios() return status
>   mmc: Enable signal voltage to be selected from mmc core
>   mmc: add power cyle support in mmc core
>   mmc: add a new mmc parameter to disable mmc clock
>   mmc: disable the mmc clock during power off
>   mmc: Add a execute_tuning() callback to the mmc operations.
>   mmc: add HS200 support in MMC core
>   mmc: Retry some MMC cmds on failure
>   dm: mmc: Add a library function to parse generic dt binding
> 
>  cmd/mmc.c                |    3 +-
>  drivers/mmc/Kconfig      |   23 +
>  drivers/mmc/fsl_esdhc.c  |    2 +-
>  drivers/mmc/mmc-uclass.c |   87 +++
>  drivers/mmc/mmc.c        | 1511 ++++++++++++++++++++++++++++++++++------------
>  include/mmc.h            |  176 +++++-
>  6 files changed, 1417 insertions(+), 385 deletions(-)
> 

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

* [U-Boot] [PATCH v2 26/26] dm: mmc: Add a library function to parse generic dt binding
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 26/26] dm: mmc: Add a library function to parse generic dt binding Jean-Jacques Hiblot
  2017-09-22 13:54     ` Jaehoon Chung
@ 2017-09-25  2:14     ` Simon Glass
  1 sibling, 0 replies; 50+ messages in thread
From: Simon Glass @ 2017-09-25  2:14 UTC (permalink / raw)
  To: u-boot

On 21 September 2017 at 08:30, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> From: Kishon Vijay Abraham I <kishon@ti.com>
>
> Add a new function to parse host controller dt node and
> set mmc_config. This function can be used by mmc controller
> drivers to set the generic mmc_config.
> This function can be extended to set other UHS mode caps
> once UHS mode support is added.
>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
> ---
>  drivers/mmc/mmc-uclass.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>  include/mmc.h            |  1 +
>  2 files changed, 47 insertions(+)

Can you please use the live API here - e.g. dev_read_bool(). Otherwise
boards which use live tree will fail.

Regards,
Simon

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

* [U-Boot] [PATCH v2 07/26] mmc: Add a function to dump the mmc capabilities
  2017-09-22 13:54     ` Jaehoon Chung
@ 2017-10-02  8:57       ` Jean-Jacques Hiblot
  2017-10-09  4:48         ` Simon Glass
  0 siblings, 1 reply; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-10-02  8:57 UTC (permalink / raw)
  To: u-boot

Hi Jaehoon,


On 22/09/2017 15:54, Jaehoon Chung wrote:
> Hi,
>
> On 09/21/2017 11:29 PM, Jean-Jacques Hiblot wrote:
>> This adds a simple helper function to display information (bus width and
>> mode) based on a capability mask. Useful for debug.
> I agreed this is useful.. but there is no usage in your patch.
> How did you use this? and Where does call this function..
>
> I think it can be used the one of mmc command. how about?
At first I added it to "mmc info" but it's more for the developer than 
the user, so I removed it from there.
At the moment it is not referenced anywhere the code, but I left it in 
place because it's indeed useful when debugging the initialization.
Thinking of it I could add something right after the card capabilities 
are discovered if debug is enabled. What do you think?

Jean-Jacques

>
> Best Regards,
> Jaehoon Chung
>
>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
>> ---
>>   drivers/mmc/mmc.c | 24 ++++++++++++++++++++++++
>>   include/mmc.h     |  1 +
>>   2 files changed, 25 insertions(+)
>>
>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>> index 94b3a02..0b74e78 100644
>> --- a/drivers/mmc/mmc.c
>> +++ b/drivers/mmc/mmc.c
>> @@ -1136,6 +1136,30 @@ static void mmc_set_bus_width(struct mmc *mmc, uint width)
>>   	mmc_set_ios(mmc);
>>   }
>>   
>> +#if CONFIG_IS_ENABLED(MMC_VERBOSE) || defined(DEBUG)
>> +/*
>> + * helper function to display the capabilities in a human
>> + * friendly manner. The capabilities include bus width and
>> + * supported modes.
>> + */
>> +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");
>> +}
>> +#endif
>> +
>>   static int sd_select_bus_freq_width(struct mmc *mmc)
>>   {
>>   	int err;
>> diff --git a/include/mmc.h b/include/mmc.h
>> index 76bd57a..dd83f14 100644
>> --- a/include/mmc.h
>> +++ b/include/mmc.h
>> @@ -426,6 +426,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
>>
>

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

* [U-Boot] [PATCH v2 13/26] mmc: Enable signal voltage to be selected from mmc core
  2017-09-22 13:54     ` Jaehoon Chung
@ 2017-10-02  9:04       ` Jean-Jacques Hiblot
  0 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-10-02  9:04 UTC (permalink / raw)
  To: u-boot



On 22/09/2017 15:54, Jaehoon Chung wrote:
> On 09/21/2017 11:30 PM, Jean-Jacques Hiblot 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 | 16 ++++++++++++++++
>>   include/mmc.h     |  8 ++++++++
>>   2 files changed, 24 insertions(+)
>>
>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>> index 536cd7f..46ec5e1 100644
>> --- a/drivers/mmc/mmc.c
>> +++ b/drivers/mmc/mmc.c
>> @@ -30,6 +30,8 @@ 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);
>> +
>>   #if CONFIG_IS_ENABLED(MMC_TINY)
>>   static struct mmc mmc_static;
>>   struct mmc *find_mmc_device(int dev_num)
>> @@ -1257,6 +1259,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,
>> @@ -1964,6 +1972,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");
>> +
> Well, it's confused. if 3.3v and 1.8v are failed, there is no problem?
> last signal value should be set to 1.8v. Is it correct?
If both 3.3v and 1.8v fail, then it may be because the underlying layer 
doesn't handle this properly (maybe it's using a fixed voltage, and 
refuses any switch).
If there is a real issue when turning on the signal voltage, it'll be 
handled later in the initialization process because the dialog with the 
sd/mmc will not work.

>
> Why didn't try to set the 1.2 voltage?
I didn't think of it. Is this allowed by the MMC spec ?

Jean-Jacques
>
>>   	mmc_set_bus_width(mmc, 1);
>>   	mmc_set_clock(mmc, 1);
>>   
>> diff --git a/include/mmc.h b/include/mmc.h
>> index 3e57887..e524963 100644
>> --- a/include/mmc.h
>> +++ b/include/mmc.h
>> @@ -272,6 +272,13 @@
>>   #define ENHNCD_SUPPORT		(0x2)
>>   #define PART_ENH_ATTRIB		(0x1f)
>>   
>> +enum mmc_voltage {
>> +	MMC_SIGNAL_VOLTAGE_000 = 0,
>> +	MMC_SIGNAL_VOLTAGE_120,
>> +	MMC_SIGNAL_VOLTAGE_180,
>> +	MMC_SIGNAL_VOLTAGE_330
>> +};
>> +
>>   /* Maximum block size for MMC */
>>   #define MMC_MAX_BLOCK_LEN	512
>>   
>> @@ -457,6 +464,7 @@ struct mmc {
>>   	int high_capacity;
>>   	uint bus_width;
>>   	uint clock;
>> +	enum mmc_voltage signal_voltage;
>>   	uint card_caps;
>>   	uint ocr;
>>   	uint dsr;
>>
>

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

* [U-Boot] [PATCH v2 23/26] mmc: Retry some MMC cmds on failure
  2017-09-22 13:54     ` Jaehoon Chung
@ 2017-10-02  9:05       ` Jean-Jacques Hiblot
  0 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-10-02  9:05 UTC (permalink / raw)
  To: u-boot



On 22/09/2017 15:54, Jaehoon Chung wrote:
> On 09/21/2017 11:30 PM, Jean-Jacques Hiblot wrote:
>> From: Kishon Vijay Abraham I <kishon@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 a few time
>> as done in Linux kernel.
>> Similarly, it is seen that MMC_CMD_SET_BLOCKLEN may fail on first
>> attempt, therefore retry this cmd a few times as done in kernel.
>>
>> To make it clear that those are optionnal workarounds, a new Kconfig
>> option 'MMC_QUIRKS' is added (enabled by default).
>>
>> 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/Kconfig |  9 +++++++++
>>   drivers/mmc/mmc.c   | 41 +++++++++++++++++++++++++++++++++++++++--
>>   include/mmc.h       |  4 ++++
>>   3 files changed, 52 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
>> index 3d577e0..78e58d4 100644
>> --- a/drivers/mmc/Kconfig
>> +++ b/drivers/mmc/Kconfig
>> @@ -33,6 +33,15 @@ config SPL_DM_MMC
>>   
>>   if MMC
>>   
>> +config MMC_QUIRKS
>> +	bool "Enable quirks"
>> +	default y
>> +	help
>> +	  Some cards and hosts may sometimes behave unexpectedly (quirks).
>> +	  This option enable workarounds to handle those quirks. Some of them
>> +	  are enabled by default, other may require additionnal flags or are
>> +	  enabled by the host driver.
>> +
>>   config MMC_VERBOSE
>>   	bool "Output more information about the MMC"
>>   	default y
>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>> index c5eaeaf..6d1bf94 100644
>> --- a/drivers/mmc/mmc.c
>> +++ b/drivers/mmc/mmc.c
>> @@ -279,6 +279,7 @@ int mmc_send_status(struct mmc *mmc, int timeout)
>>   int mmc_set_blocklen(struct mmc *mmc, int len)
>>   {
>>   	struct mmc_cmd cmd;
>> +	int err;
>>   
>>   	if (mmc->ddr_mode)
>>   		return 0;
>> @@ -287,7 +288,24 @@ int mmc_set_blocklen(struct mmc *mmc, int len)
>>   	cmd.resp_type = MMC_RSP_R1;
>>   	cmd.cmdarg = len;
>>   
>> -	return mmc_send_cmd(mmc, &cmd, NULL);
>> +	err = mmc_send_cmd(mmc, &cmd, NULL);
>> +
>> +#ifdef CONFIG_MMC_QUIRKS
>> +	if (err && (mmc->quirks & MMC_QUIRK_RETRY_SET_BLOCKLEN)) {
>> +		int retries = 4;
>> +		/*
>> +		 * It has been seen that SET_BLOCKLEN may fail on the first
>> +		 * attempt, let's try a few more time
>> +		 */
>> +		do {
>> +			err = mmc_send_cmd(mmc, &cmd, NULL);
>> +			if (!err)
>> +				break;
>> +		} while (retries--);
>> +	}
>> +#endif
>> +
>> +	return err;
>>   }
>>   
>>   static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
>> @@ -1881,7 +1899,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;
>>   	}
>> @@ -1895,6 +1912,21 @@ static int mmc_startup(struct mmc *mmc)
>>   
>>   	err = mmc_send_cmd(mmc, &cmd, NULL);
>>   
>> +#ifdef CONFIG_MMC_QUIRKS
>> +	if (err && (mmc->quirks & MMC_QUIRK_RETRY_SEND_CID)) {
>> +		int retries = 4;
>> +		/*
>> +		 * It has been seen that SEND_CID may fail on the first
>> +		 * attempt, let's try a few more time
>> +		 */
>> +		do {
>> +			err = mmc_send_cmd(mmc, &cmd, NULL);
>> +			if (!err)
>> +				break;
>> +		} while (retries--);
>> +	}
>> +#endif
>> +
>>   	if (err)
>>   		return err;
>>   
>> @@ -2239,6 +2271,11 @@ int mmc_start_init(struct mmc *mmc)
>>   	if (err)
>>   		return err;
>>   
>> +#ifdef CONFIG_MMC_QUIRKS
>> +	mmc->quirks = MMC_QUIRK_RETRY_SET_BLOCKLEN |
>> +		      MMC_QUIRK_RETRY_SEND_CID;
>> +#endif
>> +
>>   	err = mmc_power_cycle(mmc);
>>   	if (err) {
>>   		/*
>> diff --git a/include/mmc.h b/include/mmc.h
>> index a8901bf..a9ebc88 100644
>> --- a/include/mmc.h
>> +++ b/include/mmc.h
>> @@ -306,6 +306,9 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
>>   #define ENHNCD_SUPPORT		(0x2)
>>   #define PART_ENH_ATTRIB		(0x1f)
>>   
>> +#define MMC_QUIRK_RETRY_SEND_CID	BIT(0)
>> +#define MMC_QUIRK_RETRY_SET_BLOCKLEN	BIT(1)
>> +
>>   enum mmc_voltage {
>>   	MMC_SIGNAL_VOLTAGE_000 = 0,
>>   	MMC_SIGNAL_VOLTAGE_120,
>> @@ -591,6 +594,7 @@ struct mmc {
>>   				  * operating mode due to limitations when
>>   				  * accessing the boot partitions
>>   				  */
>> +	u32 quirks;
> Use the #ifdef MMC_QUIRK for quirks?
OK. I'll fix it in the next round
Thanks,
Jean-Jacques
>
>>   };
>>   
>>   struct mmc_hwpart_conf {
>>
>

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

* [U-Boot] [PATCH v2 26/26] dm: mmc: Add a library function to parse generic dt binding
  2017-09-22 13:54     ` Jaehoon Chung
@ 2017-10-02  9:08       ` Jean-Jacques Hiblot
  0 siblings, 0 replies; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-10-02  9:08 UTC (permalink / raw)
  To: u-boot



On 22/09/2017 15:54, Jaehoon Chung wrote:
> On 09/21/2017 11:30 PM, Jean-Jacques Hiblot wrote:
>> From: Kishon Vijay Abraham I <kishon@ti.com>
>>
>> Add a new function to parse host controller dt node and
>> set mmc_config. This function can be used by mmc controller
>> drivers to set the generic mmc_config.
>> This function can be extended to set other UHS mode caps
>> once UHS mode support is added.
>>
>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
>> ---
>>   drivers/mmc/mmc-uclass.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>>   include/mmc.h            |  1 +
>>   2 files changed, 47 insertions(+)
>>
>> diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
>> index 7856e0a..e30cde7 100644
>> --- a/drivers/mmc/mmc-uclass.c
>> +++ b/drivers/mmc/mmc-uclass.c
>> @@ -120,6 +120,52 @@ int mmc_execute_tuning(struct mmc *mmc, uint opcode)
>>   	return dm_mmc_execute_tuning(mmc->dev, opcode);
>>   }
>>   
>> +int mmc_of_parse(const void *fdt, int node, struct mmc_config *cfg)
>> +{
>> +	int val;
>> +
>> +	val = fdtdec_get_int(fdt, node, "bus-width", 1);
>> +
>> +	switch (val) {
>> +	case 0x8:
>> +		cfg->host_caps |= MMC_MODE_8BIT;
>> +		/* fall through */
>> +	case 0x4:
>> +		cfg->host_caps |= MMC_MODE_4BIT;
>> +		/* fall through */
>> +	case 0x1:
>> +		cfg->host_caps |= MMC_MODE_1BIT;
>> +		break;
>> +	default:
>> +		printf("error: %s invalid bus-width property %d\n",
>> +		       fdt_get_name(fdt, node, NULL), val);
> I guess it can be set to 1-bit by default and just display message about invalid bus-width property.
OK.
>
>> +		return -ENOENT;
>> +	}
>> +
>> +	cfg->f_max = fdtdec_get_int(fdt, node, "max-frequency", 52000000);
>> +
>> +	if (fdtdec_get_bool(fdt, node, "cap-sd-highspeed"))
>> +		cfg->host_caps |= MMC_CAP(SD_HS);
>> +	if (fdtdec_get_bool(fdt, node, "cap-mmc-highspeed"))
>> +		cfg->host_caps |= MMC_CAP(MMC_HS);
>> +	if (fdtdec_get_bool(fdt, node, "sd-uhs-sdr12"))
>> +		cfg->host_caps |= MMC_CAP(UHS_SDR12);
>> +	if (fdtdec_get_bool(fdt, node, "sd-uhs-sdr25"))
>> +		cfg->host_caps |= MMC_CAP(UHS_SDR25);
>> +	if (fdtdec_get_bool(fdt, node, "sd-uhs-sdr50"))
>> +		cfg->host_caps |= MMC_CAP(UHS_SDR50);
>> +	if (fdtdec_get_bool(fdt, node, "sd-uhs-sdr104"))
>> +		cfg->host_caps |= MMC_CAP(UHS_SDR104);
>> +	if (fdtdec_get_bool(fdt, node, "sd-uhs-ddr50"))
>> +		cfg->host_caps |= MMC_CAP(UHS_DDR50);
>> +	if (fdtdec_get_bool(fdt, node, "mmc-ddr-1_8v"))
>> +		cfg->host_caps |= MMC_CAP(MMC_DDR_52);
>> +	if (fdtdec_get_bool(fdt, node, "mmc-hs200-1_8v"))
>> +		cfg->host_caps |= MMC_CAP(MMC_HS_200);
> Don't need to check about 1.2v?
I'll add it. I won't be able to test though by lack of hardware.

>
>> +
>> +	return 0;
>> +}
>> +
>>   struct mmc *mmc_get_mmc_dev(struct udevice *dev)
>>   {
>>   	struct mmc_uclass_priv *upriv;
>> diff --git a/include/mmc.h b/include/mmc.h
>> index 79be6b4..6230a32 100644
>> --- a/include/mmc.h
>> +++ b/include/mmc.h
>> @@ -651,6 +651,7 @@ int mmc_unbind(struct udevice *dev);
>>   int mmc_initialize(bd_t *bis);
>>   int mmc_init(struct mmc *mmc);
>>   int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error);
>> +int mmc_of_parse(const void *fdt, int node, struct mmc_config *cfg);
>>   int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
>>   
>>   /**
>>
>

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

* [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes
  2017-09-22 14:42   ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jaehoon Chung
@ 2017-10-02  9:15     ` Jean-Jacques Hiblot
  2017-10-14 14:51       ` Marek Vasut
  0 siblings, 1 reply; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-10-02  9:15 UTC (permalink / raw)
  To: u-boot



On 22/09/2017 16:42, Jaehoon Chung wrote:
> Dear JJ,
>
> On 09/21/2017 11:29 PM, 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, Atmel SAMA5D3 xplained). 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 5 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:
>> - send the initialization stream (74 clock cycles)
>> - wait while the card is busy (used during UHS voltage switching). checking is
>>    done on dat0.
>> - 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.
>> Also in case of a reset (as opposed to a power on), it ensures that the SDCard
>> is in clean state before re-doing the initialization.
>>
>> And finally the last commits add the support for HS200 and UHS.
>>
>> With this in place and the required changes in the HSMMC host driver (including
>> DMA), we observe significant improvements in the performances on a DRA72 evm:
>> eMMC HS200: 124 MB/s
>> eMMC DDR52: 78 MB/s
>> sd   SDR104: 71 MB/s
>> sd   SDR50: 44 MB/s
> I have one question.
>
> Did you test about accessing Boot partition of eMMC?

> As i know, boot partition doesn't support the HS200 mode.
>
> When i checked your patches, there is no the function of mode changing for accessing boot partition.
> If i missed it, let me know, plz.
Yes I did test the boot partitions. HS200 is not used in this case.
The key function is mmc_boot_part_access_chk(). It checks if the current 
mode is supported by the partition. If not, it'll reselect a new mode.

Jean-Jacques


>
> Best Regards,
> Jaehoon Chung
>
>> cheers,
>>
>> Jean-Jacques
>>
>> changes since v1:
>> Changes take in account all the comment made during the first round of review.
>> But it also include a rework of the handling of the voltage supplies and 2 new
>> helper functions that can be used by the host driver during tuning and dts
>> parsing.
>>
>> Here is a detailed list:
>>   * rebase on u-boot/master.
>>   * add the description for the new functions/members
>>   * fix the typos found in the reviews
>>   * limit the new features to DM_MMC only
>>   * fix the new checkpatch warnings/errors (is it now more strict ?)
>>   * get the voltage regulators from dts (main and IO-lines)
>>   * remove the set_vdd callback and do the job in the mmc core
>>   * add a send_init_stream callback to perform the 74 clock cycle
>>     sequence after power up
>>   * do a full power cycle (if possible) before the initialization. This ensures
>>     that the sd/MMC is in valid knwon state. Also it allows to check if the power
>>     cycling works as expected.
>>   * disable the UHS modes is power cycling is not available/working. This ensures
>>     that we won't be stuck if the UHS initialization fails.
>>   * select the appropriate signal voltage when selecting a mode (MMC only)
>>   * add a helper function to parse the generic dt bindings
>>   * add a helper function to send the tuning command
>>   
>> Jean-Jacques Hiblot (17):
>>    mmc: dm: get the IO-line and main voltage regulators from the dts
>>    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: introduce mmc modes
>>    mmc: Add a function 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: Add a new callback function to perform the 74 clocks cycle
>>      sequence
>>    mmc: Add support for UHS modes
>>    mmc: disable UHS modes if Vcc cannot be switched on and off
>>    mmc: Change mode when switching to a boot partition
>>    mmc: use the right voltage level for MMC DDR and HS200 modes
>>    mmc: add a library function to send tuning command
>>
>> Kishon Vijay Abraham I (9):
>>    mmc: make mmc_set_ios() return status
>>    mmc: Enable signal voltage to be selected from mmc core
>>    mmc: add power cyle support in mmc core
>>    mmc: add a new mmc parameter to disable mmc clock
>>    mmc: disable the mmc clock during power off
>>    mmc: Add a execute_tuning() callback to the mmc operations.
>>    mmc: add HS200 support in MMC core
>>    mmc: Retry some MMC cmds on failure
>>    dm: mmc: Add a library function to parse generic dt binding
>>
>>   cmd/mmc.c                |    3 +-
>>   drivers/mmc/Kconfig      |   23 +
>>   drivers/mmc/fsl_esdhc.c  |    2 +-
>>   drivers/mmc/mmc-uclass.c |   87 +++
>>   drivers/mmc/mmc.c        | 1511 ++++++++++++++++++++++++++++++++++------------
>>   include/mmc.h            |  176 +++++-
>>   6 files changed, 1417 insertions(+), 385 deletions(-)
>>
>

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

* [U-Boot] [PATCH v2 07/26] mmc: Add a function to dump the mmc capabilities
  2017-10-02  8:57       ` Jean-Jacques Hiblot
@ 2017-10-09  4:48         ` Simon Glass
  0 siblings, 0 replies; 50+ messages in thread
From: Simon Glass @ 2017-10-09  4:48 UTC (permalink / raw)
  To: u-boot

On 2 October 2017 at 02:57, Jean-Jacques Hiblot <jjhiblot@ti.com> wrote:
> Hi Jaehoon,
>
>
> On 22/09/2017 15:54, Jaehoon Chung wrote:
>>
>> Hi,
>>
>> On 09/21/2017 11:29 PM, Jean-Jacques Hiblot wrote:
>>>
>>> This adds a simple helper function to display information (bus width and
>>> mode) based on a capability mask. Useful for debug.
>>
>> I agreed this is useful.. but there is no usage in your patch.
>> How did you use this? and Where does call this function..
>>
>> I think it can be used the one of mmc command. how about?
>
> At first I added it to "mmc info" but it's more for the developer than the
> user, so I removed it from there.
> At the moment it is not referenced anywhere the code, but I left it in place
> because it's indeed useful when debugging the initialization.
> Thinking of it I could add something right after the card capabilities are
> discovered if debug is enabled. What do you think?
>
> Jean-Jacques

That seems reasonable.

In any case, we cannot add dead code.

- Simon

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

* [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes
  2017-10-02  9:15     ` Jean-Jacques Hiblot
@ 2017-10-14 14:51       ` Marek Vasut
  2017-10-18 13:19         ` Jean-Jacques Hiblot
  2017-10-20 10:49         ` Jaehoon Chung
  0 siblings, 2 replies; 50+ messages in thread
From: Marek Vasut @ 2017-10-14 14:51 UTC (permalink / raw)
  To: u-boot

On 10/02/2017 11:15 AM, Jean-Jacques Hiblot wrote:
> 
> 
> On 22/09/2017 16:42, Jaehoon Chung wrote:
>> Dear JJ,
>>
>> On 09/21/2017 11:29 PM, 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, Atmel SAMA5D3 xplained). 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 5 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:
>>> - send the initialization stream (74 clock cycles)
>>> - wait while the card is busy (used during UHS voltage switching).
>>> checking is
>>>    done on dat0.
>>> - 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.
>>> Also in case of a reset (as opposed to a power on), it ensures that
>>> the SDCard
>>> is in clean state before re-doing the initialization.
>>>
>>> And finally the last commits add the support for HS200 and UHS.
>>>
>>> With this in place and the required changes in the HSMMC host driver
>>> (including
>>> DMA), we observe significant improvements in the performances on a
>>> DRA72 evm:
>>> eMMC HS200: 124 MB/s
>>> eMMC DDR52: 78 MB/s
>>> sd   SDR104: 71 MB/s
>>> sd   SDR50: 44 MB/s
>> I have one question.
>>
>> Did you test about accessing Boot partition of eMMC?
> 
>> As i know, boot partition doesn't support the HS200 mode.
>>
>> When i checked your patches, there is no the function of mode changing
>> for accessing boot partition.
>> If i missed it, let me know, plz.
> Yes I did test the boot partitions. HS200 is not used in this case.
> The key function is mmc_boot_part_access_chk(). It checks if the current
> mode is supported by the partition. If not, it'll reselect a new mode.

Is anything new happening on the HS200 front ?

-- 
Best regards,
Marek Vasut

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

* [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes
  2017-10-14 14:51       ` Marek Vasut
@ 2017-10-18 13:19         ` Jean-Jacques Hiblot
  2017-10-18 13:26           ` Marek Vasut
  2017-10-20 10:49         ` Jaehoon Chung
  1 sibling, 1 reply; 50+ messages in thread
From: Jean-Jacques Hiblot @ 2017-10-18 13:19 UTC (permalink / raw)
  To: u-boot



On 14/10/2017 16:51, Marek Vasut wrote:
> On 10/02/2017 11:15 AM, Jean-Jacques Hiblot wrote:
>>
>> On 22/09/2017 16:42, Jaehoon Chung wrote:
>>> Dear JJ,
>>>
>>> On 09/21/2017 11:29 PM, 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, Atmel SAMA5D3 xplained). 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 5 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:
>>>> - send the initialization stream (74 clock cycles)
>>>> - wait while the card is busy (used during UHS voltage switching).
>>>> checking is
>>>>     done on dat0.
>>>> - 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.
>>>> Also in case of a reset (as opposed to a power on), it ensures that
>>>> the SDCard
>>>> is in clean state before re-doing the initialization.
>>>>
>>>> And finally the last commits add the support for HS200 and UHS.
>>>>
>>>> With this in place and the required changes in the HSMMC host driver
>>>> (including
>>>> DMA), we observe significant improvements in the performances on a
>>>> DRA72 evm:
>>>> eMMC HS200: 124 MB/s
>>>> eMMC DDR52: 78 MB/s
>>>> sd   SDR104: 71 MB/s
>>>> sd   SDR50: 44 MB/s
>>> I have one question.
>>>
>>> Did you test about accessing Boot partition of eMMC?
>>> As i know, boot partition doesn't support the HS200 mode.
>>>
>>> When i checked your patches, there is no the function of mode changing
>>> for accessing boot partition.
>>> If i missed it, let me know, plz.
>> Yes I did test the boot partitions. HS200 is not used in this case.
>> The key function is mmc_boot_part_access_chk(). It checks if the current
>> mode is supported by the partition. If not, it'll reselect a new mode.
> Is anything new happening on the HS200 front ?
I've been busy lately but I'll send the v3  in a few days that adresses 
all the comments done by Jaheoon and Simon.

Jean-Jacques
>

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

* [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes
  2017-10-18 13:19         ` Jean-Jacques Hiblot
@ 2017-10-18 13:26           ` Marek Vasut
  0 siblings, 0 replies; 50+ messages in thread
From: Marek Vasut @ 2017-10-18 13:26 UTC (permalink / raw)
  To: u-boot

On 10/18/2017 03:19 PM, Jean-Jacques Hiblot wrote:
> 
> 
> On 14/10/2017 16:51, Marek Vasut wrote:
>> On 10/02/2017 11:15 AM, Jean-Jacques Hiblot wrote:
>>>
>>> On 22/09/2017 16:42, Jaehoon Chung wrote:
>>>> Dear JJ,
>>>>
>>>> On 09/21/2017 11:29 PM, 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, Atmel SAMA5D3 xplained). 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 5 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:
>>>>> - send the initialization stream (74 clock cycles)
>>>>> - wait while the card is busy (used during UHS voltage switching).
>>>>> checking is
>>>>>     done on dat0.
>>>>> - 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.
>>>>> Also in case of a reset (as opposed to a power on), it ensures that
>>>>> the SDCard
>>>>> is in clean state before re-doing the initialization.
>>>>>
>>>>> And finally the last commits add the support for HS200 and UHS.
>>>>>
>>>>> With this in place and the required changes in the HSMMC host driver
>>>>> (including
>>>>> DMA), we observe significant improvements in the performances on a
>>>>> DRA72 evm:
>>>>> eMMC HS200: 124 MB/s
>>>>> eMMC DDR52: 78 MB/s
>>>>> sd   SDR104: 71 MB/s
>>>>> sd   SDR50: 44 MB/s
>>>> I have one question.
>>>>
>>>> Did you test about accessing Boot partition of eMMC?
>>>> As i know, boot partition doesn't support the HS200 mode.
>>>>
>>>> When i checked your patches, there is no the function of mode changing
>>>> for accessing boot partition.
>>>> If i missed it, let me know, plz.
>>> Yes I did test the boot partitions. HS200 is not used in this case.
>>> The key function is mmc_boot_part_access_chk(). It checks if the current
>>> mode is supported by the partition. If not, it'll reselect a new mode.
>> Is anything new happening on the HS200 front ?
> I've been busy lately but I'll send the v3  in a few days that adresses
> all the comments done by Jaheoon and Simon.

Awesome, thanks !

If you have a tree with those patches applied somewhere, that'd be nice
as I'm working on adding HS200/SDR104 support into the uniphier-sd driver.

Also, any plan for HS400 ? :-)

-- 
Best regards,
Marek Vasut

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

* [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes
  2017-10-14 14:51       ` Marek Vasut
  2017-10-18 13:19         ` Jean-Jacques Hiblot
@ 2017-10-20 10:49         ` Jaehoon Chung
  1 sibling, 0 replies; 50+ messages in thread
From: Jaehoon Chung @ 2017-10-20 10:49 UTC (permalink / raw)
  To: u-boot

On 10/14/2017 11:51 PM, Marek Vasut wrote:
> On 10/02/2017 11:15 AM, Jean-Jacques Hiblot wrote:
>>
>>
>> On 22/09/2017 16:42, Jaehoon Chung wrote:
>>> Dear JJ,
>>>
>>> On 09/21/2017 11:29 PM, 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, Atmel SAMA5D3 xplained). 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 5 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:
>>>> - send the initialization stream (74 clock cycles)
>>>> - wait while the card is busy (used during UHS voltage switching).
>>>> checking is
>>>>    done on dat0.
>>>> - 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.
>>>> Also in case of a reset (as opposed to a power on), it ensures that
>>>> the SDCard
>>>> is in clean state before re-doing the initialization.
>>>>
>>>> And finally the last commits add the support for HS200 and UHS.
>>>>
>>>> With this in place and the required changes in the HSMMC host driver
>>>> (including
>>>> DMA), we observe significant improvements in the performances on a
>>>> DRA72 evm:
>>>> eMMC HS200: 124 MB/s
>>>> eMMC DDR52: 78 MB/s
>>>> sd   SDR104: 71 MB/s
>>>> sd   SDR50: 44 MB/s
>>> I have one question.
>>>
>>> Did you test about accessing Boot partition of eMMC?
>>
>>> As i know, boot partition doesn't support the HS200 mode.
>>>
>>> When i checked your patches, there is no the function of mode changing
>>> for accessing boot partition.
>>> If i missed it, let me know, plz.
>> Yes I did test the boot partitions. HS200 is not used in this case.
>> The key function is mmc_boot_part_access_chk(). It checks if the current
>> mode is supported by the partition. If not, it'll reselect a new mode.
> 
> Is anything new happening on the HS200 front ?

Will apply this patchset. Thanks!

Best Regards,
Jaehoon Chung

> 

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

* [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes
  2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
                     ` (26 preceding siblings ...)
  2017-09-22 14:42   ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jaehoon Chung
@ 2017-10-20 11:31   ` Jaehoon Chung
  2017-11-23  9:46     ` Siva Durga Prasad Paladugu
  27 siblings, 1 reply; 50+ messages in thread
From: Jaehoon Chung @ 2017-10-20 11:31 UTC (permalink / raw)
  To: u-boot

Dear JJ

On 09/21/2017 11:29 PM, 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, Atmel SAMA5D3 xplained). 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 5 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:
> - send the initialization stream (74 clock cycles)
> - wait while the card is busy (used during UHS voltage switching). checking is
>   done on dat0.
> - 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.
> Also in case of a reset (as opposed to a power on), it ensures that the SDCard
> is in clean state before re-doing the initialization.
> 
> And finally the last commits add the support for HS200 and UHS.
> 
> With this in place and the required changes in the HSMMC host driver (including
> DMA), we observe significant improvements in the performances on a DRA72 evm:
> eMMC HS200: 124 MB/s
> eMMC DDR52: 78 MB/s
> sd   SDR104: 71 MB/s
> sd   SDR50: 44 MB/s

Applied to u-boot-mmc! Thanks!
I will apply the patches relevant to this patchset. Sorry for late applying this.

Best Regards,
Jaehoon Chung

> 
> cheers,
> 
> Jean-Jacques
> 
> changes since v1:
> Changes take in account all the comment made during the first round of review.
> But it also include a rework of the handling of the voltage supplies and 2 new
> helper functions that can be used by the host driver during tuning and dts
> parsing.
> 
> Here is a detailed list:
>  * rebase on u-boot/master.
>  * add the description for the new functions/members
>  * fix the typos found in the reviews
>  * limit the new features to DM_MMC only
>  * fix the new checkpatch warnings/errors (is it now more strict ?)
>  * get the voltage regulators from dts (main and IO-lines)
>  * remove the set_vdd callback and do the job in the mmc core
>  * add a send_init_stream callback to perform the 74 clock cycle
>    sequence after power up
>  * do a full power cycle (if possible) before the initialization. This ensures
>    that the sd/MMC is in valid knwon state. Also it allows to check if the power
>    cycling works as expected.
>  * disable the UHS modes is power cycling is not available/working. This ensures
>    that we won't be stuck if the UHS initialization fails.
>  * select the appropriate signal voltage when selecting a mode (MMC only) 
>  * add a helper function to parse the generic dt bindings
>  * add a helper function to send the tuning command
>  
> Jean-Jacques Hiblot (17):
>   mmc: dm: get the IO-line and main voltage regulators from the dts
>   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: introduce mmc modes
>   mmc: Add a function 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: Add a new callback function to perform the 74 clocks cycle
>     sequence
>   mmc: Add support for UHS modes
>   mmc: disable UHS modes if Vcc cannot be switched on and off
>   mmc: Change mode when switching to a boot partition
>   mmc: use the right voltage level for MMC DDR and HS200 modes
>   mmc: add a library function to send tuning command
> 
> Kishon Vijay Abraham I (9):
>   mmc: make mmc_set_ios() return status
>   mmc: Enable signal voltage to be selected from mmc core
>   mmc: add power cyle support in mmc core
>   mmc: add a new mmc parameter to disable mmc clock
>   mmc: disable the mmc clock during power off
>   mmc: Add a execute_tuning() callback to the mmc operations.
>   mmc: add HS200 support in MMC core
>   mmc: Retry some MMC cmds on failure
>   dm: mmc: Add a library function to parse generic dt binding
> 
>  cmd/mmc.c                |    3 +-
>  drivers/mmc/Kconfig      |   23 +
>  drivers/mmc/fsl_esdhc.c  |    2 +-
>  drivers/mmc/mmc-uclass.c |   87 +++
>  drivers/mmc/mmc.c        | 1511 ++++++++++++++++++++++++++++++++++------------
>  include/mmc.h            |  176 +++++-
>  6 files changed, 1417 insertions(+), 385 deletions(-)
> 

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

* [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes
  2017-10-20 11:31   ` Jaehoon Chung
@ 2017-11-23  9:46     ` Siva Durga Prasad Paladugu
  2017-11-23  9:51       ` Marek Vasut
  2017-11-27 10:13       ` Jaehoon Chung
  0 siblings, 2 replies; 50+ messages in thread
From: Siva Durga Prasad Paladugu @ 2017-11-23  9:46 UTC (permalink / raw)
  To: u-boot

Hi Jaehoon,

> -----Original Message-----
> From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Jaehoon
> Chung
> Sent: Friday, October 20, 2017 5:02 PM
> To: Jean-Jacques Hiblot <jjhiblot@ti.com>; trini at konsulko.com;
> kishon at ti.com; sjg at chromium.org
> Cc: u-boot at lists.denx.de
> Subject: Re: [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and
> UHS modes
> 
> Dear JJ
> 
> On 09/21/2017 11:29 PM, 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, Atmel SAMA5D3 xplained). 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 5 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:
> > - send the initialization stream (74 clock cycles)
> > - wait while the card is busy (used during UHS voltage switching). checking
> is
> >   done on dat0.
> > - 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.
> > Also in case of a reset (as opposed to a power on), it ensures that
> > the SDCard is in clean state before re-doing the initialization.
> >
> > And finally the last commits add the support for HS200 and UHS.
> >
> > With this in place and the required changes in the HSMMC host driver
> > (including DMA), we observe significant improvements in the
> performances on a DRA72 evm:
> > eMMC HS200: 124 MB/s
> > eMMC DDR52: 78 MB/s
> > sd   SDR104: 71 MB/s
> > sd   SDR50: 44 MB/s
> 
> Applied to u-boot-mmc! Thanks!
> I will apply the patches relevant to this patchset. Sorry for late applying this.

I would like to test UHS and HS200 series on ZynqMP platform. 
Is it the branch " testing-uhs-supporting" that I should be using for testing it?
Please confirm.

Thanks,
Siva

> 
> Best Regards,
> Jaehoon Chung
> 
> >
> > cheers,
> >
> > Jean-Jacques
> >
> > changes since v1:
> > Changes take in account all the comment made during the first round of
> review.
> > But it also include a rework of the handling of the voltage supplies
> > and 2 new helper functions that can be used by the host driver during
> > tuning and dts parsing.
> >
> > Here is a detailed list:
> >  * rebase on u-boot/master.
> >  * add the description for the new functions/members
> >  * fix the typos found in the reviews
> >  * limit the new features to DM_MMC only
> >  * fix the new checkpatch warnings/errors (is it now more strict ?)
> >  * get the voltage regulators from dts (main and IO-lines)
> >  * remove the set_vdd callback and do the job in the mmc core
> >  * add a send_init_stream callback to perform the 74 clock cycle
> >    sequence after power up
> >  * do a full power cycle (if possible) before the initialization. This ensures
> >    that the sd/MMC is in valid knwon state. Also it allows to check if the
> power
> >    cycling works as expected.
> >  * disable the UHS modes is power cycling is not available/working. This
> ensures
> >    that we won't be stuck if the UHS initialization fails.
> >  * select the appropriate signal voltage when selecting a mode (MMC
> > only)
> >  * add a helper function to parse the generic dt bindings
> >  * add a helper function to send the tuning command
> >
> > Jean-Jacques Hiblot (17):
> >   mmc: dm: get the IO-line and main voltage regulators from the dts
> >   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: introduce mmc modes
> >   mmc: Add a function 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: Add a new callback function to perform the 74 clocks cycle
> >     sequence
> >   mmc: Add support for UHS modes
> >   mmc: disable UHS modes if Vcc cannot be switched on and off
> >   mmc: Change mode when switching to a boot partition
> >   mmc: use the right voltage level for MMC DDR and HS200 modes
> >   mmc: add a library function to send tuning command
> >
> > Kishon Vijay Abraham I (9):
> >   mmc: make mmc_set_ios() return status
> >   mmc: Enable signal voltage to be selected from mmc core
> >   mmc: add power cyle support in mmc core
> >   mmc: add a new mmc parameter to disable mmc clock
> >   mmc: disable the mmc clock during power off
> >   mmc: Add a execute_tuning() callback to the mmc operations.
> >   mmc: add HS200 support in MMC core
> >   mmc: Retry some MMC cmds on failure
> >   dm: mmc: Add a library function to parse generic dt binding
> >
> >  cmd/mmc.c                |    3 +-
> >  drivers/mmc/Kconfig      |   23 +
> >  drivers/mmc/fsl_esdhc.c  |    2 +-
> >  drivers/mmc/mmc-uclass.c |   87 +++
> >  drivers/mmc/mmc.c        | 1511
> ++++++++++++++++++++++++++++++++++------------
> >  include/mmc.h            |  176 +++++-
> >  6 files changed, 1417 insertions(+), 385 deletions(-)
> >
> 
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot

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

* [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes
  2017-11-23  9:46     ` Siva Durga Prasad Paladugu
@ 2017-11-23  9:51       ` Marek Vasut
  2017-11-27 10:13       ` Jaehoon Chung
  1 sibling, 0 replies; 50+ messages in thread
From: Marek Vasut @ 2017-11-23  9:51 UTC (permalink / raw)
  To: u-boot

On 11/23/2017 10:46 AM, Siva Durga Prasad Paladugu wrote:
> Hi Jaehoon,
> 
>> -----Original Message-----
>> From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Jaehoon
>> Chung
>> Sent: Friday, October 20, 2017 5:02 PM
>> To: Jean-Jacques Hiblot <jjhiblot@ti.com>; trini at konsulko.com;
>> kishon at ti.com; sjg at chromium.org
>> Cc: u-boot at lists.denx.de
>> Subject: Re: [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and
>> UHS modes
>>
>> Dear JJ
>>
>> On 09/21/2017 11:29 PM, 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, Atmel SAMA5D3 xplained). 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 5 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:
>>> - send the initialization stream (74 clock cycles)
>>> - wait while the card is busy (used during UHS voltage switching). checking
>> is
>>>   done on dat0.
>>> - 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.
>>> Also in case of a reset (as opposed to a power on), it ensures that
>>> the SDCard is in clean state before re-doing the initialization.
>>>
>>> And finally the last commits add the support for HS200 and UHS.
>>>
>>> With this in place and the required changes in the HSMMC host driver
>>> (including DMA), we observe significant improvements in the
>> performances on a DRA72 evm:
>>> eMMC HS200: 124 MB/s
>>> eMMC DDR52: 78 MB/s
>>> sd   SDR104: 71 MB/s
>>> sd   SDR50: 44 MB/s
>>
>> Applied to u-boot-mmc! Thanks!
>> I will apply the patches relevant to this patchset. Sorry for late applying this.
> 
> I would like to test UHS and HS200 series on ZynqMP platform. 
> Is it the branch " testing-uhs-supporting" that I should be using for testing it?
> Please confirm.

That should do, plus look at the uniphier/renesas SDHI patches posted to
the ML adding UHS200 support, that should get you started with the
arasan IP too.

-- 
Best regards,
Marek Vasut

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

* [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes
  2017-11-23  9:46     ` Siva Durga Prasad Paladugu
  2017-11-23  9:51       ` Marek Vasut
@ 2017-11-27 10:13       ` Jaehoon Chung
  1 sibling, 0 replies; 50+ messages in thread
From: Jaehoon Chung @ 2017-11-27 10:13 UTC (permalink / raw)
  To: u-boot

On 11/23/2017 06:46 PM, Siva Durga Prasad Paladugu wrote:
> Hi Jaehoon,
> 
>> -----Original Message-----
>> From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Jaehoon
>> Chung
>> Sent: Friday, October 20, 2017 5:02 PM
>> To: Jean-Jacques Hiblot <jjhiblot@ti.com>; trini at konsulko.com;
>> kishon at ti.com; sjg at chromium.org
>> Cc: u-boot at lists.denx.de
>> Subject: Re: [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and
>> UHS modes
>>
>> Dear JJ
>>
>> On 09/21/2017 11:29 PM, 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, Atmel SAMA5D3 xplained). 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 5 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:
>>> - send the initialization stream (74 clock cycles)
>>> - wait while the card is busy (used during UHS voltage switching). checking
>> is
>>>   done on dat0.
>>> - 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.
>>> Also in case of a reset (as opposed to a power on), it ensures that
>>> the SDCard is in clean state before re-doing the initialization.
>>>
>>> And finally the last commits add the support for HS200 and UHS.
>>>
>>> With this in place and the required changes in the HSMMC host driver
>>> (including DMA), we observe significant improvements in the
>> performances on a DRA72 evm:
>>> eMMC HS200: 124 MB/s
>>> eMMC DDR52: 78 MB/s
>>> sd   SDR104: 71 MB/s
>>> sd   SDR50: 44 MB/s
>>
>> Applied to u-boot-mmc! Thanks!
>> I will apply the patches relevant to this patchset. Sorry for late applying this.
> 
> I would like to test UHS and HS200 series on ZynqMP platform. 
> Is it the branch " testing-uhs-supporting" that I should be using for testing it?
> Please confirm.

Hi, i applied these patch into u-boot-mmc/master. So if you want to check, just use master branch.
If there are problem, let me know, plz. and send patches, plz.
Then it's useful to me. 

(I will remove the testing-uhs-supporting" branch, because it's already merged into master branch.)

Best Regards,
Jaehoon Chung

> 
> Thanks,
> Siva
> 
>>
>> Best Regards,
>> Jaehoon Chung
>>
>>>
>>> cheers,
>>>
>>> Jean-Jacques
>>>
>>> changes since v1:
>>> Changes take in account all the comment made during the first round of
>> review.
>>> But it also include a rework of the handling of the voltage supplies
>>> and 2 new helper functions that can be used by the host driver during
>>> tuning and dts parsing.
>>>
>>> Here is a detailed list:
>>>  * rebase on u-boot/master.
>>>  * add the description for the new functions/members
>>>  * fix the typos found in the reviews
>>>  * limit the new features to DM_MMC only
>>>  * fix the new checkpatch warnings/errors (is it now more strict ?)
>>>  * get the voltage regulators from dts (main and IO-lines)
>>>  * remove the set_vdd callback and do the job in the mmc core
>>>  * add a send_init_stream callback to perform the 74 clock cycle
>>>    sequence after power up
>>>  * do a full power cycle (if possible) before the initialization. This ensures
>>>    that the sd/MMC is in valid knwon state. Also it allows to check if the
>> power
>>>    cycling works as expected.
>>>  * disable the UHS modes is power cycling is not available/working. This
>> ensures
>>>    that we won't be stuck if the UHS initialization fails.
>>>  * select the appropriate signal voltage when selecting a mode (MMC
>>> only)
>>>  * add a helper function to parse the generic dt bindings
>>>  * add a helper function to send the tuning command
>>>
>>> Jean-Jacques Hiblot (17):
>>>   mmc: dm: get the IO-line and main voltage regulators from the dts
>>>   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: introduce mmc modes
>>>   mmc: Add a function 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: Add a new callback function to perform the 74 clocks cycle
>>>     sequence
>>>   mmc: Add support for UHS modes
>>>   mmc: disable UHS modes if Vcc cannot be switched on and off
>>>   mmc: Change mode when switching to a boot partition
>>>   mmc: use the right voltage level for MMC DDR and HS200 modes
>>>   mmc: add a library function to send tuning command
>>>
>>> Kishon Vijay Abraham I (9):
>>>   mmc: make mmc_set_ios() return status
>>>   mmc: Enable signal voltage to be selected from mmc core
>>>   mmc: add power cyle support in mmc core
>>>   mmc: add a new mmc parameter to disable mmc clock
>>>   mmc: disable the mmc clock during power off
>>>   mmc: Add a execute_tuning() callback to the mmc operations.
>>>   mmc: add HS200 support in MMC core
>>>   mmc: Retry some MMC cmds on failure
>>>   dm: mmc: Add a library function to parse generic dt binding
>>>
>>>  cmd/mmc.c                |    3 +-
>>>  drivers/mmc/Kconfig      |   23 +
>>>  drivers/mmc/fsl_esdhc.c  |    2 +-
>>>  drivers/mmc/mmc-uclass.c |   87 +++
>>>  drivers/mmc/mmc.c        | 1511
>> ++++++++++++++++++++++++++++++++++------------
>>>  include/mmc.h            |  176 +++++-
>>>  6 files changed, 1417 insertions(+), 385 deletions(-)
>>>
>>
>> _______________________________________________
>> U-Boot mailing list
>> U-Boot at lists.denx.de
>> https://lists.denx.de/listinfo/u-boot

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

* [U-Boot] [PATCH v2 10/26] mmc: refactor SD startup to make it easier to support new modes
  2017-09-21 14:29   ` [U-Boot] [PATCH v2 10/26] mmc: refactor SD startup to make it easier to support new modes Jean-Jacques Hiblot
@ 2018-02-09  0:10     ` Jonathan Gray
  0 siblings, 0 replies; 50+ messages in thread
From: Jonathan Gray @ 2018-02-09  0:10 UTC (permalink / raw)
  To: u-boot

On Thu, Sep 21, 2017 at 04:29:57PM +0200, Jean-Jacques Hiblot 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>
> Reviewed-by: Simon Glass <sjg@chromium.org>

This change broke mmc with the vexpress_ca15_tc2 target and
qemu-system-arm -M vexpress-a15.

commit d0c221fe7336fc7d9ada57d96f4a8911a3aac041
Author:     Jean-Jacques Hiblot <jjhiblot@ti.com>
AuthorDate: Thu Sep 21 16:29:57 2017 +0200
Commit:     Jaehoon Chung <jh80.chung@samsung.com>
CommitDate: Fri Jan 12 18:11:04 2018 +0900

    mmc: refactor SD startup to make it easier to support new modes
    
    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>
    Reviewed-by: Simon Glass <sjg@chromium.org>

with a build from master e24bd1e79e223aa89854c0be95a53e2d538144a5

U-Boot 2018.03-rc1-00185-g1e19c70639 (Feb 09 2018 - 11:31:54 +1300)

DRAM:  1 GiB
WARNING: Caches not enabled
Flash: 128 MiB
MMC:   MMC: 0
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   smc911x-0
Hit any key to stop autoboot:  0
=> load mmc 0:1 ${ramdisk_addr} fdt.dtb
unable to select a mode
mmc_init: -524, time 23
unable to select a mode
mmc_init: -524, time 22
** Bad device mmc 0 **
=> load mmc 0:1 ${loadaddr} efi/boot/bootarm.efi
unable to select a mode
mmc_init: -524, time 21
unable to select a mode
mmc_init: -524, time 21
** Bad device mmc 0 **
=> bootefi ${loadaddr} ${ramdisk_addr}
## Starting EFI application at a0008000 ...
WARNING: using memory device/image path, this may confuse some payloads!
Scanning disks on mmc...
unable to select a mode
mmc_init: -524, time 21
MMC Device 1 not found
MMC Device 2 not found
MMC Device 3 not found
Found 0 disks
WARNING: Invalid device tree, expect boot to fail
efi_load_pe: Invalid DOS Signature

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

* [U-Boot] [PATCH v2 22/26] mmc: Change mode when switching to a boot partition
  2017-09-21 14:30   ` [U-Boot] [PATCH v2 22/26] mmc: Change mode when switching to a boot partition Jean-Jacques Hiblot
@ 2018-07-24  8:28     ` Faiz Abbas
  0 siblings, 0 replies; 50+ messages in thread
From: Faiz Abbas @ 2018-07-24  8:28 UTC (permalink / raw)
  To: u-boot

Hi,

On Thursday 21 September 2017 08:00 PM, Jean-Jacques Hiblot wrote:
> Boot partitions do not support HS200. Changing to a lower performance mode
> is required to access them.

I see that the spec says "HS200 and HS400 modes are not supported during
*boot operation*". Can you point out where it says boot partitions are
not accessible in HS200/HS400?

I reverted this patch and was able to access boot0 partition in HS400
mode in U-boot.

Thanks,
Faiz

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

end of thread, other threads:[~2018-07-24  8:28 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20170921143028epcas3p3fce32811279a7e0bf9941e4bbc621ddd@epcas3p3.samsung.com>
2017-09-21 14:29 ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jean-Jacques Hiblot
2017-09-21 14:29   ` [U-Boot] [PATCH v2 01/26] mmc: dm: get the IO-line and main voltage regulators from the dts Jean-Jacques Hiblot
2017-09-21 14:29   ` [U-Boot] [PATCH v2 02/26] mmc: split mmc_startup() Jean-Jacques Hiblot
2017-09-21 14:29   ` [U-Boot] [PATCH v2 03/26] mmc: move the MMC startup for version above v4.0 in a separate function Jean-Jacques Hiblot
2017-09-21 14:29   ` [U-Boot] [PATCH v2 04/26] mmc: make ext_csd part of struct mmc Jean-Jacques Hiblot
2017-09-21 14:29   ` [U-Boot] [PATCH v2 05/26] mmc: add a function to read and test the ext csd (mmc >= 4) Jean-Jacques Hiblot
2017-09-21 14:29   ` [U-Boot] [PATCH v2 06/26] mmc: introduce mmc modes Jean-Jacques Hiblot
2017-09-21 14:29   ` [U-Boot] [PATCH v2 07/26] mmc: Add a function to dump the mmc capabilities Jean-Jacques Hiblot
2017-09-22 13:54     ` Jaehoon Chung
2017-10-02  8:57       ` Jean-Jacques Hiblot
2017-10-09  4:48         ` Simon Glass
2017-09-21 14:29   ` [U-Boot] [PATCH v2 08/26] mmc: use mmc modes to select the correct bus speed Jean-Jacques Hiblot
2017-09-21 14:29   ` [U-Boot] [PATCH v2 09/26] cmd: mmc: display the mode name and current bus speed in the mmc info Jean-Jacques Hiblot
2017-09-21 14:29   ` [U-Boot] [PATCH v2 10/26] mmc: refactor SD startup to make it easier to support new modes Jean-Jacques Hiblot
2018-02-09  0:10     ` Jonathan Gray
2017-09-21 14:29   ` [U-Boot] [PATCH v2 11/26] mmc: refactor MMC " Jean-Jacques Hiblot
2017-09-21 14:29   ` [U-Boot] [PATCH v2 12/26] mmc: make mmc_set_ios() return status Jean-Jacques Hiblot
2017-09-21 14:30   ` [U-Boot] [PATCH v2 13/26] mmc: Enable signal voltage to be selected from mmc core Jean-Jacques Hiblot
2017-09-22 13:54     ` Jaehoon Chung
2017-10-02  9:04       ` Jean-Jacques Hiblot
2017-09-21 14:30   ` [U-Boot] [PATCH v2 14/26] mmc: Add a new callback function to perform the 74 clocks cycle sequence Jean-Jacques Hiblot
2017-09-21 14:30   ` [U-Boot] [PATCH v2 15/26] mmc: add power cyle support in mmc core Jean-Jacques Hiblot
2017-09-21 14:30   ` [U-Boot] [PATCH v2 16/26] mmc: add a new mmc parameter to disable mmc clock Jean-Jacques Hiblot
2017-09-21 14:30   ` [U-Boot] [PATCH v2 17/26] mmc: disable the mmc clock during power off Jean-Jacques Hiblot
2017-09-21 14:30   ` [U-Boot] [PATCH v2 18/26] mmc: Add a execute_tuning() callback to the mmc operations Jean-Jacques Hiblot
2017-09-21 14:30   ` [U-Boot] [PATCH v2 19/26] mmc: add HS200 support in MMC core Jean-Jacques Hiblot
2017-09-21 14:30   ` [U-Boot] [PATCH v2 20/26] mmc: Add support for UHS modes Jean-Jacques Hiblot
2017-09-21 14:30   ` [U-Boot] [PATCH v2 21/26] mmc: disable UHS modes if Vcc cannot be switched on and off Jean-Jacques Hiblot
2017-09-21 14:30   ` [U-Boot] [PATCH v2 22/26] mmc: Change mode when switching to a boot partition Jean-Jacques Hiblot
2018-07-24  8:28     ` Faiz Abbas
2017-09-21 14:30   ` [U-Boot] [PATCH v2 23/26] mmc: Retry some MMC cmds on failure Jean-Jacques Hiblot
2017-09-22 13:54     ` Jaehoon Chung
2017-10-02  9:05       ` Jean-Jacques Hiblot
2017-09-21 14:30   ` [U-Boot] [PATCH v2 24/26] mmc: use the right voltage level for MMC DDR and HS200 modes Jean-Jacques Hiblot
2017-09-22 13:54     ` Jaehoon Chung
2017-09-21 14:30   ` [U-Boot] [PATCH v2 25/26] mmc: add a library function to send tuning command Jean-Jacques Hiblot
2017-09-21 14:30   ` [U-Boot] [PATCH v2 26/26] dm: mmc: Add a library function to parse generic dt binding Jean-Jacques Hiblot
2017-09-22 13:54     ` Jaehoon Chung
2017-10-02  9:08       ` Jean-Jacques Hiblot
2017-09-25  2:14     ` Simon Glass
2017-09-22 14:42   ` [U-Boot] [PATCH v2 00/26] mmc: Add support for HS200 and UHS modes Jaehoon Chung
2017-10-02  9:15     ` Jean-Jacques Hiblot
2017-10-14 14:51       ` Marek Vasut
2017-10-18 13:19         ` Jean-Jacques Hiblot
2017-10-18 13:26           ` Marek Vasut
2017-10-20 10:49         ` Jaehoon Chung
2017-10-20 11:31   ` Jaehoon Chung
2017-11-23  9:46     ` Siva Durga Prasad Paladugu
2017-11-23  9:51       ` Marek Vasut
2017-11-27 10:13       ` Jaehoon Chung

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.