summaryrefslogtreecommitdiff
path: root/drivers/mmc/mmc.c
diff options
context:
space:
mode:
authorTerry Lv <r65388@freescale.com>2010-03-25 18:34:40 +0800
committerTerry Lv <r65388@freescale.com>2010-03-26 17:48:54 +0800
commit76ca5d255b4920986c66c1a66e826420719f433c (patch)
tree2d580d9010e02d240e725c44950a80e6fc0ce421 /drivers/mmc/mmc.c
parentc86131164139fcb0ce1b448856ef452bdf6a346c (diff)
downloadu-boot-imx-76ca5d255b4920986c66c1a66e826420719f433c.zip
u-boot-imx-76ca5d255b4920986c66c1a66e826420719f433c.tar.gz
u-boot-imx-76ca5d255b4920986c66c1a66e826420719f433c.tar.bz2
ENGR00122050: mmc can't read data whose size exceeds 32M
mmc can't read data whose size exceeds 32M. Signed-off-by: Terry Lv <r65388@freescale.com>
Diffstat (limited to 'drivers/mmc/mmc.c')
-rw-r--r--drivers/mmc/mmc.c126
1 files changed, 71 insertions, 55 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 422c6ed..01d3210 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -35,6 +35,7 @@
#include <linux/list.h>
#include <mmc.h>
#include <div64.h>
+#include <fsl_esdhc.h>
static struct list_head mmc_devices;
static int cur_dev_num = -1;
@@ -82,6 +83,7 @@ mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
int stoperr = 0;
struct mmc *mmc = find_mmc_device(dev_num);
int blklen;
+ lbaint_t blk_offset = 0, blk_left = blkcnt;
if (!mmc)
return -1;
@@ -95,38 +97,45 @@ mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
return err;
}
- if (blkcnt > 1)
- cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
- else
- cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK;
+ do {
+ cmd.cmdidx = (blk_left > 1) \
+ ? MMC_CMD_WRITE_MULTIPLE_BLOCK \
+ : MMC_CMD_WRITE_SINGLE_BLOCK;
- if (mmc->high_capacity)
- cmd.cmdarg = start;
- else
- cmd.cmdarg = start * blklen;
+ cmd.cmdarg = (mmc->high_capacity) \
+ ? (start + blk_offset) \
+ : ((start + blk_offset) * blklen);
- cmd.resp_type = MMC_RSP_R1;
- cmd.flags = 0;
+ cmd.resp_type = MMC_RSP_R1;
+ cmd.flags = 0;
- data.src = src;
- data.blocks = blkcnt;
- data.blocksize = blklen;
- data.flags = MMC_DATA_WRITE;
+ data.src = src + blk_offset * blklen;
+ data.blocks = (blk_left > MAX_BLK_CNT) \
+ ? MAX_BLK_CNT : blk_left;
+ data.blocksize = blklen;
+ data.flags = MMC_DATA_WRITE;
- err = mmc_send_cmd(mmc, &cmd, &data);
+ err = mmc_send_cmd(mmc, &cmd, &data);
- if (err) {
- puts("mmc write failed\n\r");
- return err;
- }
+ if (err) {
+ puts("mmc write failed\n\r");
+ return err;
+ }
- if (blkcnt > 1) {
- cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
- cmd.cmdarg = 0;
- cmd.resp_type = MMC_RSP_R1b;
- cmd.flags = 0;
- stoperr = mmc_send_cmd(mmc, &cmd, NULL);
- }
+ if (blk_left > 1) {
+ cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
+ cmd.cmdarg = 0;
+ cmd.resp_type = MMC_RSP_R1b;
+ cmd.flags = 0;
+ stoperr = mmc_send_cmd(mmc, &cmd, NULL);
+ }
+
+ if (blk_left > MAX_BLK_CNT) {
+ blk_left -= MAX_BLK_CNT;
+ blk_offset += MAX_BLK_CNT;
+ } else
+ break;
+ } while (blk_left > 0);
return blkcnt;
}
@@ -214,6 +223,7 @@ static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
int stoperr = 0;
struct mmc *mmc = find_mmc_device(dev_num);
int blklen;
+ lbaint_t blk_offset = 0, blk_left = blkcnt;
if (!mmc)
return -1;
@@ -227,38 +237,44 @@ static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
return err;
}
- if (blkcnt > 1)
- cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
- else
- cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK;
+ do {
+ cmd.cmdidx = (blk_left > 1) \
+ ? MMC_CMD_READ_MULTIPLE_BLOCK \
+ : MMC_CMD_READ_SINGLE_BLOCK;
- if (mmc->high_capacity)
- cmd.cmdarg = start;
- else
- cmd.cmdarg = start * blklen;
+ cmd.cmdarg = (mmc->high_capacity) \
+ ? (start + blk_offset) \
+ : ((start + blk_offset) * blklen);
- cmd.resp_type = MMC_RSP_R1;
- cmd.flags = 0;
+ cmd.resp_type = MMC_RSP_R1;
+ cmd.flags = 0;
- data.dest = dst;
- data.blocks = blkcnt;
- data.blocksize = blklen;
- data.flags = MMC_DATA_READ;
+ data.dest = dst + blk_offset * blklen;
+ data.blocks = (blk_left > MAX_BLK_CNT) ? MAX_BLK_CNT : blk_left;
+ data.blocksize = blklen;
+ data.flags = MMC_DATA_READ;
- err = mmc_send_cmd(mmc, &cmd, &data);
+ err = mmc_send_cmd(mmc, &cmd, &data);
- if (err) {
- puts("mmc read failed\n\r");
- return err;
- }
+ if (err) {
+ puts("mmc read failed\n\r");
+ return err;
+ }
- if (blkcnt > 1) {
- cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
- cmd.cmdarg = 0;
- cmd.resp_type = MMC_RSP_R1b;
- cmd.flags = 0;
- stoperr = mmc_send_cmd(mmc, &cmd, NULL);
- }
+ if (blk_left > 1) {
+ cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
+ cmd.cmdarg = 0;
+ cmd.resp_type = MMC_RSP_R1b;
+ cmd.flags = 0;
+ stoperr = mmc_send_cmd(mmc, &cmd, NULL);
+ }
+
+ if (blk_left > MAX_BLK_CNT) {
+ blk_left -= MAX_BLK_CNT;
+ blk_offset += MAX_BLK_CNT;
+ } else
+ break;
+ } while (blk_left > 0);
return blkcnt;
}
@@ -901,9 +917,9 @@ int mmc_startup(struct mmc *mmc)
break;
}
} else {
- csize = (mmc->csd[1] & 0x3f) << 16
- | (mmc->csd[2] & 0xffff0000) >> 16;
- cmult = 8;
+ csize = (mmc->csd[1] & 0x3ff) << 2
+ | (mmc->csd[2] & 0xc0000000) >> 30;
+ cmult = (mmc->csd[2] & 0x00038000) >> 15;
}
mmc->capacity = (csize + 1) << (cmult + 2);