mmc inizialization steps enhanced
v4 cover mmc inizialization steps enhanced
I have added some better inizializations and status check. I have created following patchset for Davinci dm365 againstgit://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(-)
RFC v4 1/3 mmc: checking status after commands with R1b response
From: Raffaele Recalcati <[email protected]>
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.
--- drivers/mmc/mmc.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++-- include/mmc.h | 4 +++ 2 files changed, 61 insertions(+), 3 deletions(-)
drivers/mmc/mmc.c +57 -3
@@ -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;
include/mmc.h +4 -0
@@ -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 */
Signature · 1 line
1.7.0.4
RFC v4 1/3 mmc: checking status after commands with R1b response
Quoted 151 lines · Raffaele Recalcati
From: Raffaele Recalcati <[email protected]>
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 <[email protected]>---
?drivers/mmc/mmc.c | ? 60 ++++++++++++++++++++++++++++++++++++++++++++++++++-- ?include/mmc.h ? ? | ? ?4 +++
?2 files changed, 61 insertions(+), 3 deletions(-)drivers/mmc/mmc.c +44
-0@@ -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);drivers/mmc/mmc.c +6
-0+ + ? ? ? /* Waiting for the ready status */ + ? ? ? mmc_send_status(mmc, 1000); + + ? ? ? return ret; +?}
?int
mmc_change_freq(struct mmc *mmc)drivers/mmc/mmc.c +1
-0@@ -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;drivers/mmc/mmc.c +3
-0@@ -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;include/mmc.h +0
-0@@ -94,6 +94,10 @@?#define
OCR_BUSY? ? ?0x80000000
?#defineOCR_HCS? ? ? ? ? ? ? ?0x40000000include/mmc.h +4
-0+#define MMC_STATUS_MASK ? ? ? ? ? ? ? ?(~0x0206BF7F) +#define MMC_STATUS_RDY_FOR_DATA (1<<8) +#define MMC_STATUS_CURR_STATE ?(0xf<<9) +
Quoted 6 lines
?#define
MMC_VDD_165_195? ? ? ? ? ? ? ?0x00000080 ? ? ?/* VDD voltage 1.65 - 1.95 */ ?#defineMMC_VDD_20_21? ? ? ? ?0x00000100 ? ? ?/* VDD voltage 2.0 ~ 2.1 */ ?#defineMMC_VDD_21_22? ? ? ? ?0x00000200 ? ? ?/* VDD voltage 2.1 ~ 2.2 */ --
1.7.0.4
Works fine on Pantheon board. (armv5)
Best regards,
Lei
RFC v4 1/3 mmc: checking status after commands with R1b response
Quoted 162 lines · Lei Wen
On Fri, Mar 11, 2011 at 8:01 PM, Raffaele Recalcati
Quoted 153 lines · <[email protected]> wrote:
From: Raffaele Recalcati <[email protected]>
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 <[email protected]>--- drivers/mmc/mmc.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++-- include/mmc.h | 4 +++ 2 files changed, 61 insertions(+), 3 deletions(-)drivers/mmc/mmc.c +56
-3@@ -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;include/mmc.h +4
-0@@ -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 Quoted 4 lines
1.65 - 1.95 */ #define
MMC_VDD_20_210x00000100/* VDD
voltage 2.0 ~ 2.1 */ #defineMMC_VDD_21_220x00000200/*
VDD voltage 2.1 ~ 2.2 */ --
1.7.0.4Works fine on Pantheon board. (armv5)
Quoted 1 line
Tested-by Lei Wen <[email protected]>
Hi,
have you tested this with cards operating in SPI mode ?
Quoted 7 lines
Best regards,
Lei
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot
RFC v4 1/3 mmc: checking status after commands with R1b response
Quoted 165 lines · Marek Vasut
Quoted 162 lines · Lei Wen
On Fri, Mar 11, 2011 at 8:01 PM, Raffaele Recalcati
Quoted 152 lines · <[email protected]> wrote:
From: Raffaele Recalcati <[email protected]>
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 <[email protected]>---
?drivers/mmc/mmc.c | ? 60 ++++++++++++++++++++++++++++++++++++++++++++++++++--include/mmc.h? ? | ? ?4 +++
?2 files changed, 61 insertions(+), 3 deletions(-)drivers/mmc/mmc.c +33
-0@@ -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_cmdcmd;drivers/mmc/mmc.c +10
-0@@ -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);drivers/mmc/mmc.c +6
-0+ + ? ? ? /* Waiting for the ready status */ + ? ? ? mmc_send_status(mmc, 1000); + + ? ? ? return ret; +?}
?int
mmc_change_freq(struct mmc *mmc)drivers/mmc/mmc.c +1
-0@@ -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;drivers/mmc/mmc.c +3
-0@@ -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;include/mmc.h +0
-0@@ -94,6 +94,10 @@?#define
OCR_BUSY? ? ?0x80000000
?#defineOCR_HCS? ? ? ? ? ? ? ?0x40000000include/mmc.h +4
-0+#define MMC_STATUS_MASK ? ? ? ? ? ? ? ?(~0x0206BF7F) +#define MMC_STATUS_RDY_FOR_DATA (1<<8) +#define MMC_STATUS_CURR_STATE ?(0xf<<9) +Quoted 5 lines
?#define
MMC_VDD_165_195? ? ? ? ? ? ? ?0x00000080 ? ? ?/* VDD voltage 1.65 - 1.95 */ #defineMMC_VDD_20_21? ? ? ? ?0x00000100 ? ? ?/* VDD voltage 2.0 ~ 2.1 */ #defineMMC_VDD_21_22? ? ? ? ?0x00000200 ? ? ?/* VDD voltage 2.1 ~ 2.2 */ --
1.7.0.4Works fine on Pantheon board. (armv5)
Quoted 1 line
Tested-by Lei Wen <[email protected]>
Quoted 4 lines
Hi,
have you tested this with cards operating in SPI mode ?
no... I just test with normal sd and emmc card...
Best regards,
Lei
RFC v4 2/3 mmc: SEND_OP_COND considers card capabilities (voltage)
In reply to Raffaele RecalcatiFrom: Raffaele Recalcati <[email protected]>
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.
--- drivers/mmc/mmc.c | 19 +++++++++++++++++-- include/mmc.h | 2 ++ 2 files changed, 19 insertions(+), 2 deletions(-)
drivers/mmc/mmc.c +17 -2
@@ -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);
include/mmc.h +2 -0
@@ -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)
Signature · 1 line
1.7.0.4
RFC v4 2/3 mmc: SEND_OP_COND considers card capabilities (voltage)
Quoted 64 lines · Raffaele Recalcati
From: Raffaele Recalcati <[email protected]>
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 <[email protected]>---
?drivers/mmc/mmc.c | ? 19 +++++++++++++++++-- ?include/mmc.h ? ? | ? ?2 ++
?2 files changed, 19 insertions(+), 2 deletions(-)drivers/mmc/mmc.c +1
-1@@ -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;drivers/mmc/mmc.c +8
-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);include/mmc.h +0
-0@@ -93,6 +93,8 @@?#define
OCR_BUSY? ? ?0x80000000
?#defineOCR_HCS? ? ? ? ? ? ? ?0x40000000include/mmc.h +2
-0+#define OCR_VOLTAGE_MASK ? ? ? 0x007FFF80 +#define OCR_ACCESS_MODE ? ? ? ? ? ? ? ?0x60000000
Quoted 5 lines
?#define
MMC_STATUS_MASK? ? ? ? ? ? ? ?(~0x0206BF7F) ?#defineMMC_STATUS_RDY_FOR_DATA(1<<8)
--
1.7.0.4
Works fine on Pantheon board. (armv5)
Best regards,
Lei
RFC v4 2/3 mmc: SEND_OP_COND considers card capabilities (voltage)
In reply to Raffaele RecalcatiQuoted 43 lines · Raffaele Recalcati
From: Raffaele Recalcati <[email protected]>
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 <[email protected]>---
?drivers/mmc/mmc.c | ? 19 +++++++++++++++++-- ?include/mmc.h ? ? | ? ?2 ++
?2 files changed, 19 insertions(+), 2 deletions(-)drivers/mmc/mmc.c +1
-1@@ -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;drivers/mmc/mmc.c +8
-0+ + ? ? ? err = mmc_send_cmd(mmc, &cmd, NULL); + + ? ? ? if (err) + ? ? ? ? ? ? ? return err; + + ? ? ? udelay(1000); +
Quoted 7 lines
? ? ? ?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
RFC v4 2/3 mmc: SEND_OP_COND considers card capabilities (voltage)
Hi Andy,
Quoted 57 lines · Andy Fleming
Quoted 43 lines · Raffaele Recalcati
From: Raffaele Recalcati <[email protected]>
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 <[email protected]>---
?drivers/mmc/mmc.c | ? 19 +++++++++++++++++-- ?include/mmc.h ? ? | ? ?2 ++
?2 files changed, 19 insertions(+), 2 deletions(-)drivers/mmc/mmc.c +1
-1@@ -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;drivers/mmc/mmc.c +8
-0+ + ? ? ? err = mmc_send_cmd(mmc, &cmd, NULL); + + ? ? ? if (err) + ? ? ? ? ? ? ? return err; + + ? ? ? udelay(1000); +Quoted 7 lines
? ? ? ?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_HCShas been dropped. I thought it was necessary to query the HCS abilities.
Quoted 5 lines
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
RFC v4 2/3 mmc: SEND_OP_COND considers card capabilities (voltage)
In reply to Andy FlemingQuoted 57 lines · Andy Fleming
Quoted 40 lines · Raffaele Recalcati
From: Raffaele Recalcati<[email protected]>
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<[email protected]>--- drivers/mmc/mmc.c | 19 +++++++++++++++++-- include/mmc.h | 2 ++ 2 files changed, 19 insertions(+), 2 deletions(-)drivers/mmc/mmc.c +11
-1@@ -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;drivers/mmc/mmc.c sd_send_op_cond(struct mmc *mmc) · line 379
Quoted 10 lines
drivers/mmc/mmc.c +6
-1+ +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_HCShas been dropped. I thought it was necessary to query the HCS abilities.
Quoted 2 lines
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:
drivers/mmc/mmc.c +1 -1
@@ -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 ;
RFC v4 2/3 mmc: SEND_OP_COND considers card capabilities (voltage)
Please see:
commit b1f1e821d335de58d362bf3013c93cef86cdb356
Author: ?ukasz Majewski <[email protected]> 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
Quoted 83 lines · Gary Thomas
Quoted 60 lines · Andy Fleming
Quoted 45 lines · On Fri, Mar 11, 2011 at 6:01 AM, Raffaele Recalcati <[email protected]>…
From: Raffaele Recalcati<[email protected]>
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<[email protected]>---
?drivers/mmc/mmc.c | ? 19 +++++++++++++++++-- ?include/mmc.h ? ? | ? ?2 ++
?2 files changed, 19 insertions(+), 2 deletions(-)drivers/mmc/mmc.c +1
-1@@ -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;drivers/mmc/mmc.c +8
-0+ + ? ? ? err = mmc_send_cmd(mmc,&cmd, NULL); + + ? ? ? if (err) + ? ? ? ? ? ? ? return err; + + ? ? ? udelay(1000); +Quoted 7 lines
? ? ? ?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_HCShas been dropped. I thought it was necessary to query the HCS abilities.Quoted 2 lines
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_HCSbit set, the
device gets totally hosed. ?Only a power cycle will fix it.Adding it back like this fixes the problem:
drivers/mmc/mmc.c +0
-0@@ -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;
RFC v4 3/3 mmc: trace added
In reply to Raffaele RecalcatiFrom: Raffaele Recalcati <[email protected]>
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.
--- drivers/mmc/mmc.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 57 insertions(+), 0 deletions(-)
drivers/mmc/mmc.c +57 -0
@@ -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 ;
Signature · 1 line
1.7.0.4