From ac0865ff33870cdf2cd480165045e1bc311e9fa2 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Sun, 5 Apr 2009 13:30:52 +0530 Subject: mmc: clean up help texts Remove some repeated words and superfluous newlines in the mmc command help entries. Signed-off-by: Rabin Vincent --- common/cmd_mmc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c index f1fa32f..bd55ff1 100644 --- a/common/cmd_mmc.c +++ b/common/cmd_mmc.c @@ -135,8 +135,9 @@ int do_mmcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return 0; } -U_BOOT_CMD(mmcinfo, 2, 0, do_mmcinfo, "mmcinfo -- display MMC info\n", - NULL); +U_BOOT_CMD(mmcinfo, 2, 0, do_mmcinfo, + "print MMC information", + "\n"); int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { @@ -218,8 +219,8 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) U_BOOT_CMD( mmc, 6, 1, do_mmcops, "MMC sub system", - "mmc read addr blk# cnt\n" + "read addr blk# cnt\n" "mmc write addr blk# cnt\n" "mmc rescan \n" - "mmc list - lists available devices\n"); + "mmc list - list available devices\n"); #endif -- cgit v1.1 From e85649c7e683faea1ccfddc9fa9abc62f38e4201 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Sun, 5 Apr 2009 13:30:53 +0530 Subject: mmc: check find_mmc_device return value find_mmc_device returns NULL if an invalid device number is specified. Check for this to avoid dereferencing NULL pointers. Signed-off-by: Rabin Vincent --- common/cmd_mmc.c | 9 +++++++++ drivers/mmc/mmc.c | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c index bd55ff1..039fe59 100644 --- a/common/cmd_mmc.c +++ b/common/cmd_mmc.c @@ -149,6 +149,9 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) int dev = simple_strtoul(argv[2], NULL, 10); struct mmc *mmc = find_mmc_device(dev); + if (!mmc) + return 1; + mmc_init(mmc); return 0; @@ -175,6 +178,9 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) u32 blk = simple_strtoul(argv[4], NULL, 16); struct mmc *mmc = find_mmc_device(dev); + if (!mmc) + return 1; + printf("\nMMC read: dev # %d, block # %d, count %d ... ", dev, blk, cnt); @@ -197,6 +203,9 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) int blk = simple_strtoul(argv[4], NULL, 16); + if (!mmc) + return 1; + printf("\nMMC write: dev # %d, block # %d, count %d ... ", dev, blk, cnt); diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 7791c38..70b4130 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -846,7 +846,7 @@ block_dev_desc_t *mmc_get_dev(int dev) { struct mmc *mmc = find_mmc_device(dev); - return &mmc->block_dev; + return mmc ? &mmc->block_dev : NULL; } int mmc_init(struct mmc *mmc) -- cgit v1.1 From 9b1f942c09dd942e6de3185caa81c111b14de567 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Sun, 5 Apr 2009 13:30:54 +0530 Subject: mmc: use lldiv to fix arm eabi build The generic MMC core uses direct long long divisions, which do not build with ARM EABI toolchains. Use lldiv() instead, which works everywhere. Signed-off-by: Rabin Vincent --- drivers/mmc/mmc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 70b4130..95ed21e 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -31,6 +31,7 @@ #include #include #include +#include static struct list_head mmc_devices; static int cur_dev_num = -1; @@ -155,8 +156,8 @@ int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size) char *buffer; int i; int blklen = mmc->read_bl_len; - int startblock = src / blklen; - int endblock = (src + size - 1) / blklen; + int startblock = lldiv(src, mmc->read_bl_len); + int endblock = lldiv(src + size - 1, mmc->read_bl_len); int err = 0; /* Make a buffer big enough to hold all the blocks we might read */ @@ -789,7 +790,7 @@ int mmc_startup(struct mmc *mmc) mmc->block_dev.lun = 0; mmc->block_dev.type = 0; mmc->block_dev.blksz = mmc->read_bl_len; - mmc->block_dev.lba = mmc->capacity/mmc->read_bl_len; + mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len); sprintf(mmc->block_dev.vendor,"Man %02x%02x%02x Snr %02x%02x%02x%02x", mmc->cid[0], mmc->cid[1], mmc->cid[2], mmc->cid[9], mmc->cid[10], mmc->cid[11], mmc->cid[12]); -- cgit v1.1 From 0b453ffe28bb9227d86ddbe0893bd19c93f04ed7 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Sun, 5 Apr 2009 13:30:55 +0530 Subject: mmc: fix response decoding on little endian The mmc code defines the response as an array of chars. However, it access the response bytes both as (i) an array of four uints (with casts) and (ii) as individual chars. The former case is used more often, including by the driver when it assigns the response. The char-wise accesses are broken on little endian systems because they assume that the bytes in the uints are in big endian byte order. This patch fixes this by changing the response to be an array of four uints and replacing the char-wise accesses with equivalent uint-wise accesses. Signed-off-by: Rabin Vincent --- drivers/mmc/mmc.c | 20 ++++++++++---------- include/mmc.h | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 95ed21e..1c89e31 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -651,7 +651,7 @@ int mmc_startup(struct mmc *mmc) mmc->csd[3] = ((uint *)(cmd.response))[3]; if (mmc->version == MMC_VERSION_UNKNOWN) { - int version = (cmd.response[0] >> 2) & 0xf; + int version = (cmd.response[0] >> 26) & 0xf; switch (version) { case 0: @@ -676,8 +676,8 @@ int mmc_startup(struct mmc *mmc) } /* divide frequency by 10, since the mults are 10x bigger */ - freq = fbase[(cmd.response[3] & 0x7)]; - mult = multipliers[((cmd.response[3] >> 3) & 0xf)]; + freq = fbase[(cmd.response[0] & 0x7)]; + mult = multipliers[((cmd.response[0] >> 3) & 0xf)]; mmc->tran_speed = freq * mult; @@ -791,13 +791,13 @@ int mmc_startup(struct mmc *mmc) mmc->block_dev.type = 0; mmc->block_dev.blksz = mmc->read_bl_len; mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len); - sprintf(mmc->block_dev.vendor,"Man %02x%02x%02x Snr %02x%02x%02x%02x", - mmc->cid[0], mmc->cid[1], mmc->cid[2], - mmc->cid[9], mmc->cid[10], mmc->cid[11], mmc->cid[12]); - sprintf(mmc->block_dev.product,"%c%c%c%c%c", mmc->cid[3], - mmc->cid[4], mmc->cid[5], mmc->cid[6], mmc->cid[7]); - sprintf(mmc->block_dev.revision,"%d.%d", mmc->cid[8] >> 4, - mmc->cid[8] & 0xf); + sprintf(mmc->block_dev.vendor, "Man %06x Snr %08x", mmc->cid[0] >> 8, + (mmc->cid[2] << 8) | (mmc->cid[3] >> 24)); + sprintf(mmc->block_dev.product, "%c%c%c%c%c", mmc->cid[0] & 0xff, + (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff, + (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff); + sprintf(mmc->block_dev.revision, "%d.%d", mmc->cid[2] >> 28, + (mmc->cid[2] >> 24) & 0xf); init_part(&mmc->block_dev); return 0; diff --git a/include/mmc.h b/include/mmc.h index b9b27ba..229d494 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -91,7 +91,7 @@ #define MMC_HS_TIMING 0x00000100 #define MMC_HS_52MHZ 0x2 -#define OCR_BUSY 0x80 +#define OCR_BUSY 0x80000000 #define OCR_HCS 0x40000000 #define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */ @@ -223,7 +223,7 @@ struct mmc_cmd { ushort cmdidx; uint resp_type; uint cmdarg; - char response[18]; + uint response[4]; uint flags; }; @@ -253,7 +253,7 @@ struct mmc { uint ocr; uint scr[2]; uint csd[4]; - char cid[16]; + uint cid[4]; ushort rca; uint tran_speed; uint read_bl_len; -- cgit v1.1 From 998be3dd59ed0af4bec38324047fecfa88ac45db Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Sun, 5 Apr 2009 13:30:56 +0530 Subject: mmc: drop unnecessary casts Now that response is a uint, we can drop all the casts. Signed-off-by: Rabin Vincent --- drivers/mmc/fsl_esdhc.c | 10 +++++----- drivers/mmc/mmc.c | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 0ba45cd..8274af5 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -206,12 +206,12 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) cmdrsp2 = in_be32(®s->cmdrsp2); cmdrsp1 = in_be32(®s->cmdrsp1); cmdrsp0 = in_be32(®s->cmdrsp0); - ((uint *)(cmd->response))[0] = (cmdrsp3 << 8) | (cmdrsp2 >> 24); - ((uint *)(cmd->response))[1] = (cmdrsp2 << 8) | (cmdrsp1 >> 24); - ((uint *)(cmd->response))[2] = (cmdrsp1 << 8) | (cmdrsp0 >> 24); - ((uint *)(cmd->response))[3] = (cmdrsp0 << 8); + cmd->response[0] = (cmdrsp3 << 8) | (cmdrsp2 >> 24); + cmd->response[1] = (cmdrsp2 << 8) | (cmdrsp1 >> 24); + cmd->response[2] = (cmdrsp1 << 8) | (cmdrsp0 >> 24); + cmd->response[3] = (cmdrsp0 << 8); } else - ((uint *)(cmd->response))[0] = in_be32(®s->cmdrsp0); + cmd->response[0] = in_be32(®s->cmdrsp0); /* Wait until all of the blocks are transferred */ if (data) { diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 1c89e31..925f863 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -292,7 +292,7 @@ sd_send_op_cond(struct mmc *mmc) if (mmc->version != SD_VERSION_2) mmc->version = SD_VERSION_1_0; - mmc->ocr = ((uint *)(cmd.response))[0]; + mmc->ocr = cmd.response[0]; mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS); mmc->rca = 0; @@ -327,7 +327,7 @@ int mmc_send_op_cond(struct mmc *mmc) return UNUSABLE_ERR; mmc->version = MMC_VERSION_UNKNOWN; - mmc->ocr = ((uint *)(cmd.response))[0]; + mmc->ocr = cmd.response[0]; mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS); mmc->rca = 0; @@ -632,7 +632,7 @@ int mmc_startup(struct mmc *mmc) return err; if (IS_SD(mmc)) - mmc->rca = (((uint *)(cmd.response))[0] >> 16) & 0xffff; + mmc->rca = (cmd.response[0] >> 16) & 0xffff; /* Get the Card-Specific Data */ cmd.cmdidx = MMC_CMD_SEND_CSD; @@ -645,10 +645,10 @@ int mmc_startup(struct mmc *mmc) if (err) return err; - mmc->csd[0] = ((uint *)(cmd.response))[0]; - mmc->csd[1] = ((uint *)(cmd.response))[1]; - mmc->csd[2] = ((uint *)(cmd.response))[2]; - mmc->csd[3] = ((uint *)(cmd.response))[3]; + mmc->csd[0] = cmd.response[0]; + mmc->csd[1] = cmd.response[1]; + mmc->csd[2] = cmd.response[2]; + mmc->csd[3] = cmd.response[3]; if (mmc->version == MMC_VERSION_UNKNOWN) { int version = (cmd.response[0] >> 26) & 0xf; @@ -681,12 +681,12 @@ int mmc_startup(struct mmc *mmc) mmc->tran_speed = freq * mult; - mmc->read_bl_len = 1 << ((((uint *)(cmd.response))[1] >> 16) & 0xf); + mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf); if (IS_SD(mmc)) mmc->write_bl_len = mmc->read_bl_len; else - mmc->write_bl_len = 1 << ((((uint *)(cmd.response))[3] >> 22) & 0xf); + mmc->write_bl_len = 1 << ((cmd.response[3] >> 22) & 0xf); if (mmc->high_capacity) { csize = (mmc->csd[1] & 0x3f) << 16 @@ -819,7 +819,7 @@ int mmc_send_if_cond(struct mmc *mmc) if (err) return err; - if ((((uint *)(cmd.response))[0] & 0xff) != 0xaa) + if ((cmd.response[0] & 0xff) != 0xaa) return UNUSABLE_ERR; else mmc->version = SD_VERSION_2; -- cgit v1.1 From f33cb34b3971dabe3720d577b0e1b8601c09fe17 Mon Sep 17 00:00:00 2001 From: Yauhen Kharuzhy Date: Thu, 7 May 2009 13:08:53 +0300 Subject: mmc: Remove return from mmc_init for non SD 2.0 compatible cards. Cards which are not compatible with SD 2.0 standard, may return response for CMD8 command, but it will be invalid in terms of SD 2.0. We should accept this case as admissible, just like Linux does. Signed-off-by: Yauhen Kharuzhy Signed-off-by: Andy Fleming --- drivers/mmc/mmc.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 925f863..64a311d 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -868,10 +868,6 @@ int mmc_init(struct mmc *mmc) /* Test for SD version 2 */ err = mmc_send_if_cond(mmc); - /* If we got an error other than timeout, we bail */ - if (err && err != TIMEOUT) - return err; - /* Now try to get the SD card's operating condition */ err = sd_send_op_cond(mmc); -- cgit v1.1 From 4e3d89ba948eef801ffd46ef862cdede5b3f8320 Mon Sep 17 00:00:00 2001 From: Yauhen Kharuzhy Date: Thu, 7 May 2009 00:43:30 +0300 Subject: mmc: Fix decoding of SCR & function switch data on little-endian machines SCR & switch data are read from card as big-endian words and should be converted to CPU byte order. Signed-off-by: Yauhen Kharuzhy Signed-off-by: Andy Fleming --- drivers/mmc/mmc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 64a311d..8c736ce 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -487,8 +487,8 @@ retry_scr: return err; } - mmc->scr[0] = scr[0]; - mmc->scr[1] = scr[1]; + mmc->scr[0] = __be32_to_cpu(scr[0]); + mmc->scr[1] = __be32_to_cpu(scr[1]); switch ((mmc->scr[0] >> 24) & 0xf) { case 0: @@ -518,7 +518,7 @@ retry_scr: return err; /* The high-speed function is busy. Try again */ - if (!switch_status[7] & SD_HIGHSPEED_BUSY) + if (!(__be32_to_cpu(switch_status[7]) & SD_HIGHSPEED_BUSY)) break; } @@ -526,7 +526,7 @@ retry_scr: mmc->card_caps |= MMC_MODE_4BIT; /* If high-speed isn't supported, we return */ - if (!(switch_status[3] & SD_HIGHSPEED_SUPPORTED)) + if (!(__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED)) return 0; err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)&switch_status); @@ -534,7 +534,7 @@ retry_scr: if (err) return err; - if ((switch_status[4] & 0x0f000000) == 0x01000000) + if ((__be32_to_cpu(switch_status[4]) & 0x0f000000) == 0x01000000) mmc->card_caps |= MMC_MODE_HS; return 0; -- cgit v1.1