All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [RFC 0/3][v4] mmc inizialization steps enhanced
@ 2011-03-11 12:01 Raffaele Recalcati
  2011-03-11 12:01 ` [U-Boot] [RFC 1/3][v4] mmc: checking status after commands with R1b response Raffaele Recalcati
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Raffaele Recalcati @ 2011-03-11 12:01 UTC (permalink / raw)
  To: u-boot

I have added some better inizializations and status check.
I have created following patchset for Davinci dm365 against
git://arago-project.org/git/projects/u-boot-davinci.git git tree.
There are two commits more in that tree, but they are not
in conflict with my work.
I have finally tested this series on basi board, based on 
Davinci dm365, that contains an eMMC device. 

Raffaele Recalcati (3):
  mmc: checking status after commands with R1b response
  mmc: SEND_OP_COND considers card capabilities (voltage)
  mmc: trace added

 drivers/mmc/mmc.c |  136 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 include/mmc.h     |    6 ++
 2 files changed, 137 insertions(+), 5 deletions(-)

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

* [U-Boot] [RFC 1/3][v4] mmc: checking status after commands with R1b response
  2011-03-11 12:01 [U-Boot] [RFC 0/3][v4] mmc inizialization steps enhanced Raffaele Recalcati
@ 2011-03-11 12:01 ` Raffaele Recalcati
  2011-03-11 12:18   ` Lei Wen
  2011-03-11 12:01 ` [U-Boot] [RFC 2/3][v4] mmc: SEND_OP_COND considers card capabilities (voltage) Raffaele Recalcati
  2011-03-11 12:01 ` [U-Boot] [RFC 3/3][v4] mmc: trace added Raffaele Recalcati
  2 siblings, 1 reply; 12+ messages in thread
From: Raffaele Recalcati @ 2011-03-11 12:01 UTC (permalink / raw)
  To: u-boot

From: Raffaele Recalcati <raffaele.recalcati@bticino.it>

It is recommended to check card status after these kind of commands.
This is done using CMD13 (SEND_STATUS) JEDEC command until
the card is ready.
In case of error the card status field is displayed.

Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
---
 drivers/mmc/mmc.c |   60 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 include/mmc.h     |    4 +++
 2 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 6805b33..fc1792a 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -48,6 +48,40 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 	return mmc->send_cmd(mmc, cmd, data);
 }
 
+int mmc_send_status(struct mmc *mmc, int timeout)
+{
+	struct mmc_cmd cmd;
+	int err;
+	int status;
+
+	cmd.cmdidx = MMC_CMD_SEND_STATUS;
+	cmd.resp_type = MMC_RSP_R1;
+	cmd.cmdarg = 0;
+	cmd.flags = 0;
+
+	do {
+		err = mmc_send_cmd(mmc, &cmd, NULL);
+		if (err)
+			return err;
+		else if (cmd.response[0] & MMC_STATUS_RDY_FOR_DATA)
+			break;
+
+		udelay(1000);
+
+		if (cmd.response[0] & MMC_STATUS_MASK) {
+			printf("Status Error: 0x%08X\n", cmd.response[0]);
+			return COMM_ERR;
+		}
+	} while (timeout--);
+
+	if (!timeout) {
+		printf("Timeout waiting card ready\n");
+		return TIMEOUT;
+	}
+
+	return 0;
+}
+
 int mmc_set_blocklen(struct mmc *mmc, int len)
 {
 	struct mmc_cmd cmd;
@@ -82,6 +116,7 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
 {
 	struct mmc_cmd cmd;
 	struct mmc_data data;
+	int timeout = 1000;
 
 	if ((start + blkcnt) > mmc->block_dev.lba) {
 		printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
@@ -121,6 +156,9 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
 			printf("mmc fail to send stop cmd\n");
 			return 0;
 		}
+
+		/* Waiting for the ready status */
+		mmc_send_status(mmc, 1000);
 	}
 
 	return blkcnt;
@@ -158,6 +196,7 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)
 {
 	struct mmc_cmd cmd;
 	struct mmc_data data;
+	int timeout = 1000;
 
 	if (blkcnt > 1)
 		cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
@@ -189,6 +228,9 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)
 			printf("mmc fail to send stop cmd\n");
 			return 0;
 		}
+
+		/* Waiting for the ready status */
+		mmc_send_status(mmc, 1000);
 	}
 
 	return blkcnt;
@@ -369,15 +411,23 @@ int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd)
 int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
 {
 	struct mmc_cmd cmd;
+	int timeout = 1000;
+	int ret;
 
 	cmd.cmdidx = MMC_CMD_SWITCH;
 	cmd.resp_type = MMC_RSP_R1b;
 	cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
-		(index << 16) |
-		(value << 8);
+				 (index << 16) |
+				 (value << 8);
 	cmd.flags = 0;
 
-	return mmc_send_cmd(mmc, &cmd, NULL);
+	ret = mmc_send_cmd(mmc, &cmd, NULL);
+
+	/* Waiting for the ready status */
+	mmc_send_status(mmc, 1000);
+
+	return ret;
+
 }
 
 int mmc_change_freq(struct mmc *mmc)
@@ -610,6 +660,7 @@ int mmc_startup(struct mmc *mmc)
 	u64 cmult, csize;
 	struct mmc_cmd cmd;
 	char ext_csd[512];
+	int timeout = 1000;
 
 	/* Put the Card in Identify Mode */
 	cmd.cmdidx = MMC_CMD_ALL_SEND_CID;
@@ -722,6 +773,9 @@ int mmc_startup(struct mmc *mmc)
 	cmd.flags = 0;
 	err = mmc_send_cmd(mmc, &cmd, NULL);
 
+	/* Waiting for the ready status */
+	mmc_send_status(mmc, 1000);
+
 	if (err)
 		return err;
 
diff --git a/include/mmc.h b/include/mmc.h
index fcd0fd1..4ee8e1c 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -94,6 +94,10 @@
 #define OCR_BUSY	0x80000000
 #define OCR_HCS		0x40000000
 
+#define MMC_STATUS_MASK		(~0x0206BF7F)
+#define MMC_STATUS_RDY_FOR_DATA (1<<8)
+#define MMC_STATUS_CURR_STATE	(0xf<<9)
+
 #define MMC_VDD_165_195		0x00000080	/* VDD voltage 1.65 - 1.95 */
 #define MMC_VDD_20_21		0x00000100	/* VDD voltage 2.0 ~ 2.1 */
 #define MMC_VDD_21_22		0x00000200	/* VDD voltage 2.1 ~ 2.2 */
-- 
1.7.0.4

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

* [U-Boot] [RFC 2/3][v4] mmc: SEND_OP_COND considers card capabilities (voltage)
  2011-03-11 12:01 [U-Boot] [RFC 0/3][v4] mmc inizialization steps enhanced Raffaele Recalcati
  2011-03-11 12:01 ` [U-Boot] [RFC 1/3][v4] mmc: checking status after commands with R1b response Raffaele Recalcati
@ 2011-03-11 12:01 ` Raffaele Recalcati
  2011-03-11 12:18   ` Lei Wen
  2011-04-13 11:24   ` Andy Fleming
  2011-03-11 12:01 ` [U-Boot] [RFC 3/3][v4] mmc: trace added Raffaele Recalcati
  2 siblings, 2 replies; 12+ messages in thread
From: Raffaele Recalcati @ 2011-03-11 12:01 UTC (permalink / raw)
  To: u-boot

From: Raffaele Recalcati <raffaele.recalcati@bticino.it>

The first SEND_OP_COND (CMD1) command added is used to ask card capabilities.
After it an AND operation is done between card capabilities and host
capabilities (at the moment only for the voltage field).
Finally the correct value is sent to the MMC, waiting that the card
exits from busy state.

Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
---
 drivers/mmc/mmc.c |   19 +++++++++++++++++--
 include/mmc.h     |    2 ++
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index fc1792a..5bea476 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -351,17 +351,32 @@ sd_send_op_cond(struct mmc *mmc)
 
 int mmc_send_op_cond(struct mmc *mmc)
 {
-	int timeout = 1000;
+	int timeout = 10000;
 	struct mmc_cmd cmd;
 	int err;
 
 	/* Some cards seem to need this */
 	mmc_go_idle(mmc);
 
+	/* Asking to the card its capabilities */
+	cmd.cmdidx = MMC_CMD_SEND_OP_COND;
+	cmd.resp_type = MMC_RSP_R3;
+	cmd.cmdarg = 0;
+	cmd.flags = 0;
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+
+	if (err)
+		return err;
+
+	udelay(1000);
+
 	do {
 		cmd.cmdidx = MMC_CMD_SEND_OP_COND;
 		cmd.resp_type = MMC_RSP_R3;
-		cmd.cmdarg = OCR_HCS | mmc->voltages;
+		cmd.cmdarg = ((mmc->voltages &
+			      (cmd.response[0] & OCR_VOLTAGE_MASK)) |
+			      (cmd.response[0] & OCR_ACCESS_MODE));
 		cmd.flags = 0;
 
 		err = mmc_send_cmd(mmc, &cmd, NULL);
diff --git a/include/mmc.h b/include/mmc.h
index 4ee8e1c..d18526d 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -93,6 +93,8 @@
 
 #define OCR_BUSY	0x80000000
 #define OCR_HCS		0x40000000
+#define OCR_VOLTAGE_MASK	0x007FFF80
+#define OCR_ACCESS_MODE		0x60000000
 
 #define MMC_STATUS_MASK		(~0x0206BF7F)
 #define MMC_STATUS_RDY_FOR_DATA (1<<8)
-- 
1.7.0.4

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

* [U-Boot] [RFC 3/3][v4] mmc: trace added
  2011-03-11 12:01 [U-Boot] [RFC 0/3][v4] mmc inizialization steps enhanced Raffaele Recalcati
  2011-03-11 12:01 ` [U-Boot] [RFC 1/3][v4] mmc: checking status after commands with R1b response Raffaele Recalcati
  2011-03-11 12:01 ` [U-Boot] [RFC 2/3][v4] mmc: SEND_OP_COND considers card capabilities (voltage) Raffaele Recalcati
@ 2011-03-11 12:01 ` Raffaele Recalcati
  2 siblings, 0 replies; 12+ messages in thread
From: Raffaele Recalcati @ 2011-03-11 12:01 UTC (permalink / raw)
  To: u-boot

From: Raffaele Recalcati <raffaele.recalcati@bticino.it>

Defining CONFIG_MMC_TRACE in the include board file it is possible to activate
a tracing support.
This code helps in case of eMMC hw failure or to investigate possible eMMC
initialization issues.

Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
---
 drivers/mmc/mmc.c |   57 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 57 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 5bea476..3395d7c 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -45,7 +45,60 @@ int board_mmc_getcd(u8 *cd, struct mmc *mmc)__attribute__((weak,
 
 int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 {
+#ifdef CONFIG_MMC_TRACE
+	int ret;
+	int i;
+	u8 *ptr;
+
+	printf("CMD_SEND:%d\n", cmd->cmdidx);
+	printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
+	printf("\t\tFLAG\t\t\t %d\n", cmd->flags);
+	ret = mmc->send_cmd(mmc, cmd, data);
+	switch (cmd->resp_type) {
+		case MMC_RSP_NONE:
+			printf("\t\tMMC_RSP_NONE\n");
+			break;
+		case MMC_RSP_R1:
+			printf("\t\tMMC_RSP_R1,5,6,7 \t 0x%08X \n",
+				cmd->response[0]);
+			break;
+		case MMC_RSP_R1b:
+			printf("\t\tMMC_RSP_R1b\t\t 0x%08X \n",
+				cmd->response[0]);
+			break;
+		case MMC_RSP_R2:
+			printf("\t\tMMC_RSP_R2\t\t 0x%08X \n",
+				cmd->response[0]);
+			printf("\t\t          \t\t 0x%08X \n",
+				cmd->response[1]);
+			printf("\t\t          \t\t 0x%08X \n",
+				cmd->response[2]);
+			printf("\t\t          \t\t 0x%08X \n",
+				cmd->response[3]);
+			printf("\n");
+			printf("\t\t\t\t\tDUMPING DATA\n");
+			for (i = 0; i < 4; i++) {
+				int j;
+				printf("\t\t\t\t\t%03d - ", i*4);
+				ptr = &cmd->response[i];
+				ptr += 3;
+				for (j = 0; j < 4; j++)
+					printf("%02X ", *ptr--);
+				printf("\n");
+			}
+			break;
+		case MMC_RSP_R3:
+			printf("\t\tMMC_RSP_R3,4\t\t 0x%08X \n",
+				cmd->response[0]);
+			break;
+		default:
+			printf("\t\tERROR MMC rsp not supported\n");
+			break;
+	}
+	return ret;
+#else
 	return mmc->send_cmd(mmc, cmd, data);
+#endif
 }
 
 int mmc_send_status(struct mmc *mmc, int timeout)
@@ -74,6 +127,10 @@ int mmc_send_status(struct mmc *mmc, int timeout)
 		}
 	} while (timeout--);
 
+#ifdef CONFIG_MMC_TRACE
+	status = (cmd.response[0] & MMC_STATUS_CURR_STATE) >> 9;
+	printf("CURR STATE:%d\n", status);
+#endif
 	if (!timeout) {
 		printf("Timeout waiting card ready\n");
 		return TIMEOUT;
-- 
1.7.0.4

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

* [U-Boot] [RFC 1/3][v4] mmc: checking status after commands with R1b response
  2011-03-11 12:01 ` [U-Boot] [RFC 1/3][v4] mmc: checking status after commands with R1b response Raffaele Recalcati
@ 2011-03-11 12:18   ` Lei Wen
  2011-08-06 12:07     ` Marek Vasut
  0 siblings, 1 reply; 12+ messages in thread
From: Lei Wen @ 2011-03-11 12:18 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 11, 2011 at 8:01 PM, Raffaele Recalcati
<lamiaposta71@gmail.com> wrote:
> From: Raffaele Recalcati <raffaele.recalcati@bticino.it>
>
> It is recommended to check card status after these kind of commands.
> This is done using CMD13 (SEND_STATUS) JEDEC command until
> the card is ready.
> In case of error the card status field is displayed.
>
> Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
> ---
> ?drivers/mmc/mmc.c | ? 60 ++++++++++++++++++++++++++++++++++++++++++++++++++--
> ?include/mmc.h ? ? | ? ?4 +++
> ?2 files changed, 61 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 6805b33..fc1792a 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -48,6 +48,40 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
> ? ? ? ?return mmc->send_cmd(mmc, cmd, data);
> ?}
>
> +int mmc_send_status(struct mmc *mmc, int timeout)
> +{
> + ? ? ? struct mmc_cmd cmd;
> + ? ? ? int err;
> + ? ? ? int status;
> +
> + ? ? ? cmd.cmdidx = MMC_CMD_SEND_STATUS;
> + ? ? ? cmd.resp_type = MMC_RSP_R1;
> + ? ? ? cmd.cmdarg = 0;
> + ? ? ? cmd.flags = 0;
> +
> + ? ? ? do {
> + ? ? ? ? ? ? ? err = mmc_send_cmd(mmc, &cmd, NULL);
> + ? ? ? ? ? ? ? if (err)
> + ? ? ? ? ? ? ? ? ? ? ? return err;
> + ? ? ? ? ? ? ? else if (cmd.response[0] & MMC_STATUS_RDY_FOR_DATA)
> + ? ? ? ? ? ? ? ? ? ? ? break;
> +
> + ? ? ? ? ? ? ? udelay(1000);
> +
> + ? ? ? ? ? ? ? if (cmd.response[0] & MMC_STATUS_MASK) {
> + ? ? ? ? ? ? ? ? ? ? ? printf("Status Error: 0x%08X\n", cmd.response[0]);
> + ? ? ? ? ? ? ? ? ? ? ? return COMM_ERR;
> + ? ? ? ? ? ? ? }
> + ? ? ? } while (timeout--);
> +
> + ? ? ? if (!timeout) {
> + ? ? ? ? ? ? ? printf("Timeout waiting card ready\n");
> + ? ? ? ? ? ? ? return TIMEOUT;
> + ? ? ? }
> +
> + ? ? ? return 0;
> +}
> +
> ?int mmc_set_blocklen(struct mmc *mmc, int len)
> ?{
> ? ? ? ?struct mmc_cmd cmd;
> @@ -82,6 +116,7 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
> ?{
> ? ? ? ?struct mmc_cmd cmd;
> ? ? ? ?struct mmc_data data;
> + ? ? ? int timeout = 1000;
>
> ? ? ? ?if ((start + blkcnt) > mmc->block_dev.lba) {
> ? ? ? ? ? ? ? ?printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
> @@ -121,6 +156,9 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
> ? ? ? ? ? ? ? ? ? ? ? ?printf("mmc fail to send stop cmd\n");
> ? ? ? ? ? ? ? ? ? ? ? ?return 0;
> ? ? ? ? ? ? ? ?}
> +
> + ? ? ? ? ? ? ? /* Waiting for the ready status */
> + ? ? ? ? ? ? ? mmc_send_status(mmc, 1000);
> ? ? ? ?}
>
> ? ? ? ?return blkcnt;
> @@ -158,6 +196,7 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)
> ?{
> ? ? ? ?struct mmc_cmd cmd;
> ? ? ? ?struct mmc_data data;
> + ? ? ? int timeout = 1000;
>
> ? ? ? ?if (blkcnt > 1)
> ? ? ? ? ? ? ? ?cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
> @@ -189,6 +228,9 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)
> ? ? ? ? ? ? ? ? ? ? ? ?printf("mmc fail to send stop cmd\n");
> ? ? ? ? ? ? ? ? ? ? ? ?return 0;
> ? ? ? ? ? ? ? ?}
> +
> + ? ? ? ? ? ? ? /* Waiting for the ready status */
> + ? ? ? ? ? ? ? mmc_send_status(mmc, 1000);
> ? ? ? ?}
>
> ? ? ? ?return blkcnt;
> @@ -369,15 +411,23 @@ int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd)
> ?int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
> ?{
> ? ? ? ?struct mmc_cmd cmd;
> + ? ? ? int timeout = 1000;
> + ? ? ? int ret;
>
> ? ? ? ?cmd.cmdidx = MMC_CMD_SWITCH;
> ? ? ? ?cmd.resp_type = MMC_RSP_R1b;
> ? ? ? ?cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
> - ? ? ? ? ? ? ? (index << 16) |
> - ? ? ? ? ? ? ? (value << 8);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(index << 16) |
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(value << 8);
> ? ? ? ?cmd.flags = 0;
>
> - ? ? ? return mmc_send_cmd(mmc, &cmd, NULL);
> + ? ? ? ret = mmc_send_cmd(mmc, &cmd, NULL);
> +
> + ? ? ? /* Waiting for the ready status */
> + ? ? ? mmc_send_status(mmc, 1000);
> +
> + ? ? ? return ret;
> +
> ?}
>
> ?int mmc_change_freq(struct mmc *mmc)
> @@ -610,6 +660,7 @@ int mmc_startup(struct mmc *mmc)
> ? ? ? ?u64 cmult, csize;
> ? ? ? ?struct mmc_cmd cmd;
> ? ? ? ?char ext_csd[512];
> + ? ? ? int timeout = 1000;
>
> ? ? ? ?/* Put the Card in Identify Mode */
> ? ? ? ?cmd.cmdidx = MMC_CMD_ALL_SEND_CID;
> @@ -722,6 +773,9 @@ int mmc_startup(struct mmc *mmc)
> ? ? ? ?cmd.flags = 0;
> ? ? ? ?err = mmc_send_cmd(mmc, &cmd, NULL);
>
> + ? ? ? /* Waiting for the ready status */
> + ? ? ? mmc_send_status(mmc, 1000);
> +
> ? ? ? ?if (err)
> ? ? ? ? ? ? ? ?return err;
>
> diff --git a/include/mmc.h b/include/mmc.h
> index fcd0fd1..4ee8e1c 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -94,6 +94,10 @@
> ?#define OCR_BUSY ? ? ? 0x80000000
> ?#define OCR_HCS ? ? ? ? ? ? ? ?0x40000000
>
> +#define MMC_STATUS_MASK ? ? ? ? ? ? ? ?(~0x0206BF7F)
> +#define MMC_STATUS_RDY_FOR_DATA (1<<8)
> +#define MMC_STATUS_CURR_STATE ?(0xf<<9)
> +
> ?#define MMC_VDD_165_195 ? ? ? ? ? ? ? ?0x00000080 ? ? ?/* VDD voltage 1.65 - 1.95 */
> ?#define MMC_VDD_20_21 ? ? ? ? ?0x00000100 ? ? ?/* VDD voltage 2.0 ~ 2.1 */
> ?#define MMC_VDD_21_22 ? ? ? ? ?0x00000200 ? ? ?/* VDD voltage 2.1 ~ 2.2 */
> --
> 1.7.0.4
>

Works fine on Pantheon board. (armv5)
Tested-by:Lei Wen <leiwen@marvell.com>

Best regards,
Lei

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

* [U-Boot] [RFC 2/3][v4] mmc: SEND_OP_COND considers card capabilities (voltage)
  2011-03-11 12:01 ` [U-Boot] [RFC 2/3][v4] mmc: SEND_OP_COND considers card capabilities (voltage) Raffaele Recalcati
@ 2011-03-11 12:18   ` Lei Wen
  2011-04-13 11:24   ` Andy Fleming
  1 sibling, 0 replies; 12+ messages in thread
From: Lei Wen @ 2011-03-11 12:18 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 11, 2011 at 8:01 PM, Raffaele Recalcati
<lamiaposta71@gmail.com> wrote:
> From: Raffaele Recalcati <raffaele.recalcati@bticino.it>
>
> The first SEND_OP_COND (CMD1) command added is used to ask card capabilities.
> After it an AND operation is done between card capabilities and host
> capabilities (at the moment only for the voltage field).
> Finally the correct value is sent to the MMC, waiting that the card
> exits from busy state.
>
> Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
> ---
> ?drivers/mmc/mmc.c | ? 19 +++++++++++++++++--
> ?include/mmc.h ? ? | ? ?2 ++
> ?2 files changed, 19 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index fc1792a..5bea476 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -351,17 +351,32 @@ sd_send_op_cond(struct mmc *mmc)
>
> ?int mmc_send_op_cond(struct mmc *mmc)
> ?{
> - ? ? ? int timeout = 1000;
> + ? ? ? int timeout = 10000;
> ? ? ? ?struct mmc_cmd cmd;
> ? ? ? ?int err;
>
> ? ? ? ?/* Some cards seem to need this */
> ? ? ? ?mmc_go_idle(mmc);
>
> + ? ? ? /* Asking to the card its capabilities */
> + ? ? ? cmd.cmdidx = MMC_CMD_SEND_OP_COND;
> + ? ? ? cmd.resp_type = MMC_RSP_R3;
> + ? ? ? cmd.cmdarg = 0;
> + ? ? ? cmd.flags = 0;
> +
> + ? ? ? err = mmc_send_cmd(mmc, &cmd, NULL);
> +
> + ? ? ? if (err)
> + ? ? ? ? ? ? ? return err;
> +
> + ? ? ? udelay(1000);
> +
> ? ? ? ?do {
> ? ? ? ? ? ? ? ?cmd.cmdidx = MMC_CMD_SEND_OP_COND;
> ? ? ? ? ? ? ? ?cmd.resp_type = MMC_RSP_R3;
> - ? ? ? ? ? ? ? cmd.cmdarg = OCR_HCS | mmc->voltages;
> + ? ? ? ? ? ? ? cmd.cmdarg = ((mmc->voltages &
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? (cmd.response[0] & OCR_VOLTAGE_MASK)) |
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? (cmd.response[0] & OCR_ACCESS_MODE));
> ? ? ? ? ? ? ? ?cmd.flags = 0;
>
> ? ? ? ? ? ? ? ?err = mmc_send_cmd(mmc, &cmd, NULL);
> diff --git a/include/mmc.h b/include/mmc.h
> index 4ee8e1c..d18526d 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -93,6 +93,8 @@
>
> ?#define OCR_BUSY ? ? ? 0x80000000
> ?#define OCR_HCS ? ? ? ? ? ? ? ?0x40000000
> +#define OCR_VOLTAGE_MASK ? ? ? 0x007FFF80
> +#define OCR_ACCESS_MODE ? ? ? ? ? ? ? ?0x60000000
>
> ?#define MMC_STATUS_MASK ? ? ? ? ? ? ? ?(~0x0206BF7F)
> ?#define MMC_STATUS_RDY_FOR_DATA (1<<8)
> --
> 1.7.0.4
>

Works fine on Pantheon board. (armv5)
Tested-by:Lei Wen <leiwen@marvell.com>

Best regards,
Lei

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

* [U-Boot] [RFC 2/3][v4] mmc: SEND_OP_COND considers card capabilities (voltage)
  2011-03-11 12:01 ` [U-Boot] [RFC 2/3][v4] mmc: SEND_OP_COND considers card capabilities (voltage) Raffaele Recalcati
  2011-03-11 12:18   ` Lei Wen
@ 2011-04-13 11:24   ` Andy Fleming
  2011-04-14  7:48     ` Raffaele Recalcati
  2011-07-28 19:25     ` Gary Thomas
  1 sibling, 2 replies; 12+ messages in thread
From: Andy Fleming @ 2011-04-13 11:24 UTC (permalink / raw)
  To: u-boot

On Fri, Mar 11, 2011 at 6:01 AM, Raffaele Recalcati
<lamiaposta71@gmail.com> wrote:
> From: Raffaele Recalcati <raffaele.recalcati@bticino.it>
>
> The first SEND_OP_COND (CMD1) command added is used to ask card capabilities.
> After it an AND operation is done between card capabilities and host
> capabilities (at the moment only for the voltage field).
> Finally the correct value is sent to the MMC, waiting that the card
> exits from busy state.
>
> Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
> ---
> ?drivers/mmc/mmc.c | ? 19 +++++++++++++++++--
> ?include/mmc.h ? ? | ? ?2 ++
> ?2 files changed, 19 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index fc1792a..5bea476 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -351,17 +351,32 @@ sd_send_op_cond(struct mmc *mmc)
>
> ?int mmc_send_op_cond(struct mmc *mmc)
> ?{
> - ? ? ? int timeout = 1000;
> + ? ? ? int timeout = 10000;
> ? ? ? ?struct mmc_cmd cmd;
> ? ? ? ?int err;
>
> ? ? ? ?/* Some cards seem to need this */
> ? ? ? ?mmc_go_idle(mmc);
>
> + ? ? ? /* Asking to the card its capabilities */
> + ? ? ? cmd.cmdidx = MMC_CMD_SEND_OP_COND;
> + ? ? ? cmd.resp_type = MMC_RSP_R3;
> + ? ? ? cmd.cmdarg = 0;
> + ? ? ? cmd.flags = 0;
> +
> + ? ? ? err = mmc_send_cmd(mmc, &cmd, NULL);
> +
> + ? ? ? if (err)
> + ? ? ? ? ? ? ? return err;
> +
> + ? ? ? udelay(1000);
> +
> ? ? ? ?do {
> ? ? ? ? ? ? ? ?cmd.cmdidx = MMC_CMD_SEND_OP_COND;
> ? ? ? ? ? ? ? ?cmd.resp_type = MMC_RSP_R3;
> - ? ? ? ? ? ? ? cmd.cmdarg = OCR_HCS | mmc->voltages;
> + ? ? ? ? ? ? ? cmd.cmdarg = ((mmc->voltages &
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? (cmd.response[0] & OCR_VOLTAGE_MASK)) |
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? (cmd.response[0] & OCR_ACCESS_MODE));


My concern here is that OCR_HCS has been dropped. I thought it was
necessary to query the HCS abilities.

I'm guessing I'm missing something, or that it's not needed, so I will
apply this patch, and we'll see if anyone has issues.

Andy

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

* [U-Boot] [RFC 2/3][v4] mmc: SEND_OP_COND considers card capabilities (voltage)
  2011-04-13 11:24   ` Andy Fleming
@ 2011-04-14  7:48     ` Raffaele Recalcati
  2011-07-28 19:25     ` Gary Thomas
  1 sibling, 0 replies; 12+ messages in thread
From: Raffaele Recalcati @ 2011-04-14  7:48 UTC (permalink / raw)
  To: u-boot

Hi Andy,

On Wed, Apr 13, 2011 at 1:24 PM, Andy Fleming <afleming@gmail.com> wrote:
> On Fri, Mar 11, 2011 at 6:01 AM, Raffaele Recalcati
> <lamiaposta71@gmail.com> wrote:
>> From: Raffaele Recalcati <raffaele.recalcati@bticino.it>
>>
>> The first SEND_OP_COND (CMD1) command added is used to ask card capabilities.
>> After it an AND operation is done between card capabilities and host
>> capabilities (at the moment only for the voltage field).
>> Finally the correct value is sent to the MMC, waiting that the card
>> exits from busy state.
>>
>> Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
>> ---
>> ?drivers/mmc/mmc.c | ? 19 +++++++++++++++++--
>> ?include/mmc.h ? ? | ? ?2 ++
>> ?2 files changed, 19 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>> index fc1792a..5bea476 100644
>> --- a/drivers/mmc/mmc.c
>> +++ b/drivers/mmc/mmc.c
>> @@ -351,17 +351,32 @@ sd_send_op_cond(struct mmc *mmc)
>>
>> ?int mmc_send_op_cond(struct mmc *mmc)
>> ?{
>> - ? ? ? int timeout = 1000;
>> + ? ? ? int timeout = 10000;
>> ? ? ? ?struct mmc_cmd cmd;
>> ? ? ? ?int err;
>>
>> ? ? ? ?/* Some cards seem to need this */
>> ? ? ? ?mmc_go_idle(mmc);
>>
>> + ? ? ? /* Asking to the card its capabilities */
>> + ? ? ? cmd.cmdidx = MMC_CMD_SEND_OP_COND;
>> + ? ? ? cmd.resp_type = MMC_RSP_R3;
>> + ? ? ? cmd.cmdarg = 0;
>> + ? ? ? cmd.flags = 0;
>> +
>> + ? ? ? err = mmc_send_cmd(mmc, &cmd, NULL);
>> +
>> + ? ? ? if (err)
>> + ? ? ? ? ? ? ? return err;
>> +
>> + ? ? ? udelay(1000);
>> +
>> ? ? ? ?do {
>> ? ? ? ? ? ? ? ?cmd.cmdidx = MMC_CMD_SEND_OP_COND;
>> ? ? ? ? ? ? ? ?cmd.resp_type = MMC_RSP_R3;
>> - ? ? ? ? ? ? ? cmd.cmdarg = OCR_HCS | mmc->voltages;
>> + ? ? ? ? ? ? ? cmd.cmdarg = ((mmc->voltages &
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? (cmd.response[0] & OCR_VOLTAGE_MASK)) |
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? (cmd.response[0] & OCR_ACCESS_MODE));
>
>
> My concern here is that OCR_HCS has been dropped. I thought it was
> necessary to query the HCS abilities.
>
> I'm guessing I'm missing something, or that it's not needed, so I will
> apply this patch, and we'll see if anyone has issues.
>
> Andy
>

Thx,
Raffaele

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

* [U-Boot] [RFC 2/3][v4] mmc: SEND_OP_COND considers card capabilities (voltage)
  2011-04-13 11:24   ` Andy Fleming
  2011-04-14  7:48     ` Raffaele Recalcati
@ 2011-07-28 19:25     ` Gary Thomas
  2011-08-17  2:51       ` Andy Fleming
  1 sibling, 1 reply; 12+ messages in thread
From: Gary Thomas @ 2011-07-28 19:25 UTC (permalink / raw)
  To: u-boot

On 2011-04-13 05:24, Andy Fleming wrote:
> On Fri, Mar 11, 2011 at 6:01 AM, Raffaele Recalcati
> <lamiaposta71@gmail.com>  wrote:
>> From: Raffaele Recalcati<raffaele.recalcati@bticino.it>
>>
>> The first SEND_OP_COND (CMD1) command added is used to ask card capabilities.
>> After it an AND operation is done between card capabilities and host
>> capabilities (at the moment only for the voltage field).
>> Finally the correct value is sent to the MMC, waiting that the card
>> exits from busy state.
>>
>> Signed-off-by: Raffaele Recalcati<raffaele.recalcati@bticino.it>
>> ---
>>   drivers/mmc/mmc.c |   19 +++++++++++++++++--
>>   include/mmc.h     |    2 ++
>>   2 files changed, 19 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>> index fc1792a..5bea476 100644
>> --- a/drivers/mmc/mmc.c
>> +++ b/drivers/mmc/mmc.c
>> @@ -351,17 +351,32 @@ sd_send_op_cond(struct mmc *mmc)
>>
>>   int mmc_send_op_cond(struct mmc *mmc)
>>   {
>> -       int timeout = 1000;
>> +       int timeout = 10000;
>>         struct mmc_cmd cmd;
>>         int err;
>>
>>         /* Some cards seem to need this */
>>         mmc_go_idle(mmc);
>>
>> +       /* Asking to the card its capabilities */
>> +       cmd.cmdidx = MMC_CMD_SEND_OP_COND;
>> +       cmd.resp_type = MMC_RSP_R3;
>> +       cmd.cmdarg = 0;
>> +       cmd.flags = 0;
>> +
>> +       err = mmc_send_cmd(mmc,&cmd, NULL);
>> +
>> +       if (err)
>> +               return err;
>> +
>> +       udelay(1000);
>> +
>>         do {
>>                 cmd.cmdidx = MMC_CMD_SEND_OP_COND;
>>                 cmd.resp_type = MMC_RSP_R3;
>> -               cmd.cmdarg = OCR_HCS | mmc->voltages;
>> +               cmd.cmdarg = ((mmc->voltages&
>> +                             (cmd.response[0]&  OCR_VOLTAGE_MASK)) |
>> +                             (cmd.response[0]&  OCR_ACCESS_MODE));
>
>
> My concern here is that OCR_HCS has been dropped. I thought it was
> necessary to query the HCS abilities.
>
> I'm guessing I'm missing something, or that it's not needed, so I will
> apply this patch, and we'll see if anyone has issues.

I just tried this on my eMMC chip (THGBM1G5D2EBAI7) and without the OCR_HCS bit set, the
device gets totally hosed.  Only a power cycle will fix it.

Adding it back like this fixes the problem:
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 21aedba..76117da 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -446,7 +446,7 @@ int mmc_send_op_cond(struct mmc *mmc)
                 cmd.cmdidx = MMC_CMD_SEND_OP_COND;
                 cmd.resp_type = MMC_RSP_R3;
                 cmd.cmdarg = (mmc_host_is_spi(mmc) ? 0 :
-                               (mmc->voltages &
+                               OCR_HCS | (mmc->voltages &
                                 (cmd.response[0] & OCR_VOLTAGE_MASK)) |
                                 (cmd.response[0] & OCR_ACCESS_MODE));
                 cmd.flags = 0;

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

* [U-Boot] [RFC 1/3][v4] mmc: checking status after commands with R1b response
  2011-03-11 12:18   ` Lei Wen
@ 2011-08-06 12:07     ` Marek Vasut
  2011-08-06 12:18       ` Lei Wen
  0 siblings, 1 reply; 12+ messages in thread
From: Marek Vasut @ 2011-08-06 12:07 UTC (permalink / raw)
  To: u-boot

On Friday, March 11, 2011 01:18:15 PM Lei Wen wrote:
> On Fri, Mar 11, 2011 at 8:01 PM, Raffaele Recalcati
> 
> <lamiaposta71@gmail.com> wrote:
> > From: Raffaele Recalcati <raffaele.recalcati@bticino.it>
> > 
> > It is recommended to check card status after these kind of commands.
> > This is done using CMD13 (SEND_STATUS) JEDEC command until
> > the card is ready.
> > In case of error the card status field is displayed.
> > 
> > Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
> > ---
> >  drivers/mmc/mmc.c |   60
> > ++++++++++++++++++++++++++++++++++++++++++++++++++-- include/mmc.h     |
> >    4 +++
> >  2 files changed, 61 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> > index 6805b33..fc1792a 100644
> > --- a/drivers/mmc/mmc.c
> > +++ b/drivers/mmc/mmc.c
> > @@ -48,6 +48,40 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
> > struct mmc_data *data) return mmc->send_cmd(mmc, cmd, data);
> >  }
> > 
> > +int mmc_send_status(struct mmc *mmc, int timeout)
> > +{
> > +       struct mmc_cmd cmd;
> > +       int err;
> > +       int status;
> > +
> > +       cmd.cmdidx = MMC_CMD_SEND_STATUS;
> > +       cmd.resp_type = MMC_RSP_R1;
> > +       cmd.cmdarg = 0;
> > +       cmd.flags = 0;
> > +
> > +       do {
> > +               err = mmc_send_cmd(mmc, &cmd, NULL);
> > +               if (err)
> > +                       return err;
> > +               else if (cmd.response[0] & MMC_STATUS_RDY_FOR_DATA)
> > +                       break;
> > +
> > +               udelay(1000);
> > +
> > +               if (cmd.response[0] & MMC_STATUS_MASK) {
> > +                       printf("Status Error: 0x%08X\n",
> > cmd.response[0]); +                       return COMM_ERR;
> > +               }
> > +       } while (timeout--);
> > +
> > +       if (!timeout) {
> > +               printf("Timeout waiting card ready\n");
> > +               return TIMEOUT;
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> >  int mmc_set_blocklen(struct mmc *mmc, int len)
> >  {
> >        struct mmc_cmd cmd;
> > @@ -82,6 +116,7 @@ mmc_write_blocks(struct mmc *mmc, ulong start,
> > lbaint_t blkcnt, const void*src) {
> >        struct mmc_cmd cmd;
> >        struct mmc_data data;
> > +       int timeout = 1000;
> > 
> >        if ((start + blkcnt) > mmc->block_dev.lba) {
> >                printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
> > @@ -121,6 +156,9 @@ mmc_write_blocks(struct mmc *mmc, ulong start,
> > lbaint_t blkcnt, const void*src) printf("mmc fail to send stop cmd\n");
> >                        return 0;
> >                }
> > +
> > +               /* Waiting for the ready status */
> > +               mmc_send_status(mmc, 1000);
> >        }
> > 
> >        return blkcnt;
> > @@ -158,6 +196,7 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong
> > start, lbaint_t blkcnt) {
> >        struct mmc_cmd cmd;
> >        struct mmc_data data;
> > +       int timeout = 1000;
> > 
> >        if (blkcnt > 1)
> >                cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
> > @@ -189,6 +228,9 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong
> > start, lbaint_t blkcnt) printf("mmc fail to send stop cmd\n");
> >                        return 0;
> >                }
> > +
> > +               /* Waiting for the ready status */
> > +               mmc_send_status(mmc, 1000);
> >        }
> > 
> >        return blkcnt;
> > @@ -369,15 +411,23 @@ int mmc_send_ext_csd(struct mmc *mmc, char
> > *ext_csd) int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
> >  {
> >        struct mmc_cmd cmd;
> > +       int timeout = 1000;
> > +       int ret;
> > 
> >        cmd.cmdidx = MMC_CMD_SWITCH;
> >        cmd.resp_type = MMC_RSP_R1b;
> >        cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
> > -               (index << 16) |
> > -               (value << 8);
> > +                                (index << 16) |
> > +                                (value << 8);
> >        cmd.flags = 0;
> > 
> > -       return mmc_send_cmd(mmc, &cmd, NULL);
> > +       ret = mmc_send_cmd(mmc, &cmd, NULL);
> > +
> > +       /* Waiting for the ready status */
> > +       mmc_send_status(mmc, 1000);
> > +
> > +       return ret;
> > +
> >  }
> > 
> >  int mmc_change_freq(struct mmc *mmc)
> > @@ -610,6 +660,7 @@ int mmc_startup(struct mmc *mmc)
> >        u64 cmult, csize;
> >        struct mmc_cmd cmd;
> >        char ext_csd[512];
> > +       int timeout = 1000;
> > 
> >        /* Put the Card in Identify Mode */
> >        cmd.cmdidx = MMC_CMD_ALL_SEND_CID;
> > @@ -722,6 +773,9 @@ int mmc_startup(struct mmc *mmc)
> >        cmd.flags = 0;
> >        err = mmc_send_cmd(mmc, &cmd, NULL);
> > 
> > +       /* Waiting for the ready status */
> > +       mmc_send_status(mmc, 1000);
> > +
> >        if (err)
> >                return err;
> > 
> > diff --git a/include/mmc.h b/include/mmc.h
> > index fcd0fd1..4ee8e1c 100644
> > --- a/include/mmc.h
> > +++ b/include/mmc.h
> > @@ -94,6 +94,10 @@
> >  #define OCR_BUSY       0x80000000
> >  #define OCR_HCS                0x40000000
> > 
> > +#define MMC_STATUS_MASK                (~0x0206BF7F)
> > +#define MMC_STATUS_RDY_FOR_DATA (1<<8)
> > +#define MMC_STATUS_CURR_STATE  (0xf<<9)
> > +
> >  #define MMC_VDD_165_195                0x00000080      /* VDD voltage
> > 1.65 - 1.95 */ #define MMC_VDD_20_21          0x00000100      /* VDD
> > voltage 2.0 ~ 2.1 */ #define MMC_VDD_21_22          0x00000200      /*
> > VDD voltage 2.1 ~ 2.2 */ --
> > 1.7.0.4
> 
> Works fine on Pantheon board. (armv5)
> Tested-by:Lei Wen <leiwen@marvell.com>

Hi,

have you tested this with cards operating in SPI mode ?

> 
> Best regards,
> Lei
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

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

* [U-Boot] [RFC 1/3][v4] mmc: checking status after commands with R1b response
  2011-08-06 12:07     ` Marek Vasut
@ 2011-08-06 12:18       ` Lei Wen
  0 siblings, 0 replies; 12+ messages in thread
From: Lei Wen @ 2011-08-06 12:18 UTC (permalink / raw)
  To: u-boot

On Sat, Aug 6, 2011 at 8:07 PM, Marek Vasut <marek.vasut@gmail.com> wrote:
> On Friday, March 11, 2011 01:18:15 PM Lei Wen wrote:
>> On Fri, Mar 11, 2011 at 8:01 PM, Raffaele Recalcati
>>
>> <lamiaposta71@gmail.com> wrote:
>> > From: Raffaele Recalcati <raffaele.recalcati@bticino.it>
>> >
>> > It is recommended to check card status after these kind of commands.
>> > This is done using CMD13 (SEND_STATUS) JEDEC command until
>> > the card is ready.
>> > In case of error the card status field is displayed.
>> >
>> > Signed-off-by: Raffaele Recalcati <raffaele.recalcati@bticino.it>
>> > ---
>> > ?drivers/mmc/mmc.c | ? 60
>> > ++++++++++++++++++++++++++++++++++++++++++++++++++-- include/mmc.h ? ? |
>> > ? ?4 +++
>> > ?2 files changed, 61 insertions(+), 3 deletions(-)
>> >
>> > diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>> > index 6805b33..fc1792a 100644
>> > --- a/drivers/mmc/mmc.c
>> > +++ b/drivers/mmc/mmc.c
>> > @@ -48,6 +48,40 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
>> > struct mmc_data *data) return mmc->send_cmd(mmc, cmd, data);
>> > ?}
>> >
>> > +int mmc_send_status(struct mmc *mmc, int timeout)
>> > +{
>> > + ? ? ? struct mmc_cmd cmd;
>> > + ? ? ? int err;
>> > + ? ? ? int status;
>> > +
>> > + ? ? ? cmd.cmdidx = MMC_CMD_SEND_STATUS;
>> > + ? ? ? cmd.resp_type = MMC_RSP_R1;
>> > + ? ? ? cmd.cmdarg = 0;
>> > + ? ? ? cmd.flags = 0;
>> > +
>> > + ? ? ? do {
>> > + ? ? ? ? ? ? ? err = mmc_send_cmd(mmc, &cmd, NULL);
>> > + ? ? ? ? ? ? ? if (err)
>> > + ? ? ? ? ? ? ? ? ? ? ? return err;
>> > + ? ? ? ? ? ? ? else if (cmd.response[0] & MMC_STATUS_RDY_FOR_DATA)
>> > + ? ? ? ? ? ? ? ? ? ? ? break;
>> > +
>> > + ? ? ? ? ? ? ? udelay(1000);
>> > +
>> > + ? ? ? ? ? ? ? if (cmd.response[0] & MMC_STATUS_MASK) {
>> > + ? ? ? ? ? ? ? ? ? ? ? printf("Status Error: 0x%08X\n",
>> > cmd.response[0]); + ? ? ? ? ? ? ? ? ? ? ? return COMM_ERR;
>> > + ? ? ? ? ? ? ? }
>> > + ? ? ? } while (timeout--);
>> > +
>> > + ? ? ? if (!timeout) {
>> > + ? ? ? ? ? ? ? printf("Timeout waiting card ready\n");
>> > + ? ? ? ? ? ? ? return TIMEOUT;
>> > + ? ? ? }
>> > +
>> > + ? ? ? return 0;
>> > +}
>> > +
>> > ?int mmc_set_blocklen(struct mmc *mmc, int len)
>> > ?{
>> > ? ? ? ?struct mmc_cmd cmd;
>> > @@ -82,6 +116,7 @@ mmc_write_blocks(struct mmc *mmc, ulong start,
>> > lbaint_t blkcnt, const void*src) {
>> > ? ? ? ?struct mmc_cmd cmd;
>> > ? ? ? ?struct mmc_data data;
>> > + ? ? ? int timeout = 1000;
>> >
>> > ? ? ? ?if ((start + blkcnt) > mmc->block_dev.lba) {
>> > ? ? ? ? ? ? ? ?printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
>> > @@ -121,6 +156,9 @@ mmc_write_blocks(struct mmc *mmc, ulong start,
>> > lbaint_t blkcnt, const void*src) printf("mmc fail to send stop cmd\n");
>> > ? ? ? ? ? ? ? ? ? ? ? ?return 0;
>> > ? ? ? ? ? ? ? ?}
>> > +
>> > + ? ? ? ? ? ? ? /* Waiting for the ready status */
>> > + ? ? ? ? ? ? ? mmc_send_status(mmc, 1000);
>> > ? ? ? ?}
>> >
>> > ? ? ? ?return blkcnt;
>> > @@ -158,6 +196,7 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong
>> > start, lbaint_t blkcnt) {
>> > ? ? ? ?struct mmc_cmd cmd;
>> > ? ? ? ?struct mmc_data data;
>> > + ? ? ? int timeout = 1000;
>> >
>> > ? ? ? ?if (blkcnt > 1)
>> > ? ? ? ? ? ? ? ?cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
>> > @@ -189,6 +228,9 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong
>> > start, lbaint_t blkcnt) printf("mmc fail to send stop cmd\n");
>> > ? ? ? ? ? ? ? ? ? ? ? ?return 0;
>> > ? ? ? ? ? ? ? ?}
>> > +
>> > + ? ? ? ? ? ? ? /* Waiting for the ready status */
>> > + ? ? ? ? ? ? ? mmc_send_status(mmc, 1000);
>> > ? ? ? ?}
>> >
>> > ? ? ? ?return blkcnt;
>> > @@ -369,15 +411,23 @@ int mmc_send_ext_csd(struct mmc *mmc, char
>> > *ext_csd) int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
>> > ?{
>> > ? ? ? ?struct mmc_cmd cmd;
>> > + ? ? ? int timeout = 1000;
>> > + ? ? ? int ret;
>> >
>> > ? ? ? ?cmd.cmdidx = MMC_CMD_SWITCH;
>> > ? ? ? ?cmd.resp_type = MMC_RSP_R1b;
>> > ? ? ? ?cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
>> > - ? ? ? ? ? ? ? (index << 16) |
>> > - ? ? ? ? ? ? ? (value << 8);
>> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(index << 16) |
>> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(value << 8);
>> > ? ? ? ?cmd.flags = 0;
>> >
>> > - ? ? ? return mmc_send_cmd(mmc, &cmd, NULL);
>> > + ? ? ? ret = mmc_send_cmd(mmc, &cmd, NULL);
>> > +
>> > + ? ? ? /* Waiting for the ready status */
>> > + ? ? ? mmc_send_status(mmc, 1000);
>> > +
>> > + ? ? ? return ret;
>> > +
>> > ?}
>> >
>> > ?int mmc_change_freq(struct mmc *mmc)
>> > @@ -610,6 +660,7 @@ int mmc_startup(struct mmc *mmc)
>> > ? ? ? ?u64 cmult, csize;
>> > ? ? ? ?struct mmc_cmd cmd;
>> > ? ? ? ?char ext_csd[512];
>> > + ? ? ? int timeout = 1000;
>> >
>> > ? ? ? ?/* Put the Card in Identify Mode */
>> > ? ? ? ?cmd.cmdidx = MMC_CMD_ALL_SEND_CID;
>> > @@ -722,6 +773,9 @@ int mmc_startup(struct mmc *mmc)
>> > ? ? ? ?cmd.flags = 0;
>> > ? ? ? ?err = mmc_send_cmd(mmc, &cmd, NULL);
>> >
>> > + ? ? ? /* Waiting for the ready status */
>> > + ? ? ? mmc_send_status(mmc, 1000);
>> > +
>> > ? ? ? ?if (err)
>> > ? ? ? ? ? ? ? ?return err;
>> >
>> > diff --git a/include/mmc.h b/include/mmc.h
>> > index fcd0fd1..4ee8e1c 100644
>> > --- a/include/mmc.h
>> > +++ b/include/mmc.h
>> > @@ -94,6 +94,10 @@
>> > ?#define OCR_BUSY ? ? ? 0x80000000
>> > ?#define OCR_HCS ? ? ? ? ? ? ? ?0x40000000
>> >
>> > +#define MMC_STATUS_MASK ? ? ? ? ? ? ? ?(~0x0206BF7F)
>> > +#define MMC_STATUS_RDY_FOR_DATA (1<<8)
>> > +#define MMC_STATUS_CURR_STATE ?(0xf<<9)
>> > +
>> > ?#define MMC_VDD_165_195 ? ? ? ? ? ? ? ?0x00000080 ? ? ?/* VDD voltage
>> > 1.65 - 1.95 */ #define MMC_VDD_20_21 ? ? ? ? ?0x00000100 ? ? ?/* VDD
>> > voltage 2.0 ~ 2.1 */ #define MMC_VDD_21_22 ? ? ? ? ?0x00000200 ? ? ?/*
>> > VDD voltage 2.1 ~ 2.2 */ --
>> > 1.7.0.4
>>
>> Works fine on Pantheon board. (armv5)
>> Tested-by:Lei Wen <leiwen@marvell.com>
>
> Hi,
>
> have you tested this with cards operating in SPI mode ?
>

no... I just test with normal sd and emmc card...

Best regards,
Lei

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

* [U-Boot] [RFC 2/3][v4] mmc: SEND_OP_COND considers card capabilities (voltage)
  2011-07-28 19:25     ` Gary Thomas
@ 2011-08-17  2:51       ` Andy Fleming
  0 siblings, 0 replies; 12+ messages in thread
From: Andy Fleming @ 2011-08-17  2:51 UTC (permalink / raw)
  To: u-boot

Please see:

commit b1f1e821d335de58d362bf3013c93cef86cdb356
Author: ?ukasz Majewski <l.majewski@samsung.com>
Date:   Tue Jul 5 02:19:44 2011 +0000

    mmc: Access mode validation for eMMC cards > 2 GiB

It adds support for setting the HCS bit. It will only be done if your
driver has set  mmc->host_caps & MMC_MODE_HC.

Let me know if that patch didn't solve your problem.

Andy

On Thu, Jul 28, 2011 at 2:25 PM, Gary Thomas <samoht.yrag@gmail.com> wrote:
> On 2011-04-13 05:24, Andy Fleming wrote:
>>
>> On Fri, Mar 11, 2011 at 6:01 AM, Raffaele Recalcati
>> <lamiaposta71@gmail.com> ?wrote:
>>>
>>> From: Raffaele Recalcati<raffaele.recalcati@bticino.it>
>>>
>>> The first SEND_OP_COND (CMD1) command added is used to ask card
>>> capabilities.
>>> After it an AND operation is done between card capabilities and host
>>> capabilities (at the moment only for the voltage field).
>>> Finally the correct value is sent to the MMC, waiting that the card
>>> exits from busy state.
>>>
>>> Signed-off-by: Raffaele Recalcati<raffaele.recalcati@bticino.it>
>>> ---
>>> ?drivers/mmc/mmc.c | ? 19 +++++++++++++++++--
>>> ?include/mmc.h ? ? | ? ?2 ++
>>> ?2 files changed, 19 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
>>> index fc1792a..5bea476 100644
>>> --- a/drivers/mmc/mmc.c
>>> +++ b/drivers/mmc/mmc.c
>>> @@ -351,17 +351,32 @@ sd_send_op_cond(struct mmc *mmc)
>>>
>>> ?int mmc_send_op_cond(struct mmc *mmc)
>>> ?{
>>> - ? ? ? int timeout = 1000;
>>> + ? ? ? int timeout = 10000;
>>> ? ? ? ?struct mmc_cmd cmd;
>>> ? ? ? ?int err;
>>>
>>> ? ? ? ?/* Some cards seem to need this */
>>> ? ? ? ?mmc_go_idle(mmc);
>>>
>>> + ? ? ? /* Asking to the card its capabilities */
>>> + ? ? ? cmd.cmdidx = MMC_CMD_SEND_OP_COND;
>>> + ? ? ? cmd.resp_type = MMC_RSP_R3;
>>> + ? ? ? cmd.cmdarg = 0;
>>> + ? ? ? cmd.flags = 0;
>>> +
>>> + ? ? ? err = mmc_send_cmd(mmc,&cmd, NULL);
>>> +
>>> + ? ? ? if (err)
>>> + ? ? ? ? ? ? ? return err;
>>> +
>>> + ? ? ? udelay(1000);
>>> +
>>> ? ? ? ?do {
>>> ? ? ? ? ? ? ? ?cmd.cmdidx = MMC_CMD_SEND_OP_COND;
>>> ? ? ? ? ? ? ? ?cmd.resp_type = MMC_RSP_R3;
>>> - ? ? ? ? ? ? ? cmd.cmdarg = OCR_HCS | mmc->voltages;
>>> + ? ? ? ? ? ? ? cmd.cmdarg = ((mmc->voltages&
>>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? (cmd.response[0]& ?OCR_VOLTAGE_MASK)) |
>>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? (cmd.response[0]& ?OCR_ACCESS_MODE));
>>
>>
>> My concern here is that OCR_HCS has been dropped. I thought it was
>> necessary to query the HCS abilities.
>>
>> I'm guessing I'm missing something, or that it's not needed, so I will
>> apply this patch, and we'll see if anyone has issues.
>
> I just tried this on my eMMC chip (THGBM1G5D2EBAI7) and without the OCR_HCS
> bit set, the
> device gets totally hosed. ?Only a power cycle will fix it.
>
> Adding it back like this fixes the problem:
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 21aedba..76117da 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -446,7 +446,7 @@ int mmc_send_op_cond(struct mmc *mmc)
> ? ? ? ? ? ? ? ?cmd.cmdidx = MMC_CMD_SEND_OP_COND;
> ? ? ? ? ? ? ? ?cmd.resp_type = MMC_RSP_R3;
> ? ? ? ? ? ? ? ?cmd.cmdarg = (mmc_host_is_spi(mmc) ? 0 :
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (mmc->voltages &
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OCR_HCS | (mmc->voltages &
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(cmd.response[0] & OCR_VOLTAGE_MASK)) |
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(cmd.response[0] & OCR_ACCESS_MODE));
> ? ? ? ? ? ? ? ?cmd.flags = 0;
>

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

end of thread, other threads:[~2011-08-17  2:51 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-03-11 12:01 [U-Boot] [RFC 0/3][v4] mmc inizialization steps enhanced Raffaele Recalcati
2011-03-11 12:01 ` [U-Boot] [RFC 1/3][v4] mmc: checking status after commands with R1b response Raffaele Recalcati
2011-03-11 12:18   ` Lei Wen
2011-08-06 12:07     ` Marek Vasut
2011-08-06 12:18       ` Lei Wen
2011-03-11 12:01 ` [U-Boot] [RFC 2/3][v4] mmc: SEND_OP_COND considers card capabilities (voltage) Raffaele Recalcati
2011-03-11 12:18   ` Lei Wen
2011-04-13 11:24   ` Andy Fleming
2011-04-14  7:48     ` Raffaele Recalcati
2011-07-28 19:25     ` Gary Thomas
2011-08-17  2:51       ` Andy Fleming
2011-03-11 12:01 ` [U-Boot] [RFC 3/3][v4] mmc: trace added Raffaele Recalcati

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.