[U-Boot] [PATCH][RFC] SD/MMC: multiple block read support
Kumar Gala
galak at kernel.crashing.org
Wed Apr 7 17:31:59 CEST 2010
From: Jerry Huang <Chang-Ming.Huang at freescale.com>
Multiple block read support to improve performance (time it takes) to read
larger amounts of data.
Signed-off-by: Jerry Huang <Chang-Ming.Huang at freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang at freescale.com>
---
drivers/mmc/mmc.c | 71 +++++++++++++++++++++++++---------------------------
1 files changed, 34 insertions(+), 37 deletions(-)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index cf4ea16..bb8b993 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008, Freescale Semiconductor, Inc
+ * Copyright 2008-2010, Freescale Semiconductor, Inc
* Andy Fleming
*
* Based vaguely on the Linux code
@@ -135,33 +135,51 @@ mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
return blkcnt;
}
-int mmc_read_block(struct mmc *mmc, void *dst, uint blocknum)
+int mmc_read_block(struct mmc *mmc, void *dst, uint start, int blkcnt)
{
struct mmc_cmd cmd;
struct mmc_data data;
+ int err, stoperr = 0;
- cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK;
+ if (blkcnt > 1)
+ cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
+ else
+ cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK;
if (mmc->high_capacity)
- cmd.cmdarg = blocknum;
+ cmd.cmdarg = start;
else
- cmd.cmdarg = blocknum * mmc->read_bl_len;
+ cmd.cmdarg = start * mmc->read_bl_len;
cmd.resp_type = MMC_RSP_R1;
cmd.flags = 0;
data.dest = dst;
- data.blocks = 1;
+ data.blocks = blkcnt;
data.blocksize = mmc->read_bl_len;
data.flags = MMC_DATA_READ;
- return mmc_send_cmd(mmc, &cmd, &data);
+ err = mmc_send_cmd(mmc, &cmd, &data);
+
+ 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 (err) {
+ printf("the read data have err %d\n", err);
+ return err;
+ }
+
+ return stoperr;
}
int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size)
{
char *buffer;
- int i;
int blklen = mmc->read_bl_len;
int startblock = lldiv(src, mmc->read_bl_len);
int endblock = lldiv(src + size - 1, mmc->read_bl_len);
@@ -181,28 +199,10 @@ int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size)
if (err)
goto free_buffer;
- for (i = startblock; i <= endblock; i++) {
- int segment_size;
- int offset;
-
- err = mmc_read_block(mmc, buffer, i);
-
- if (err)
- goto free_buffer;
-
- /*
- * The first block may not be aligned, so we
- * copy from the desired point in the block
- */
- offset = (src & (blklen - 1));
- segment_size = MIN(blklen - offset, size);
-
- memcpy(dst, buffer + offset, segment_size);
-
- dst += segment_size;
- src += segment_size;
- size -= segment_size;
- }
+ err = mmc_read_block(mmc, buffer, startblock, endblock - startblock + 1);
+ if (err)
+ goto free_buffer;
+ memcpy(dst, buffer, size);
free_buffer:
free(buffer);
@@ -213,7 +213,6 @@ free_buffer:
static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
{
int err;
- int i;
struct mmc *mmc = find_mmc_device(dev_num);
if (!mmc)
@@ -226,13 +225,11 @@ static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
return 0;
}
- for (i = start; i < start + blkcnt; i++, dst += mmc->read_bl_len) {
- err = mmc_read_block(mmc, dst, i);
+ err = mmc_read_block(mmc, dst, start, blkcnt);
- if (err) {
- printf("block read failed: %d\n", err);
- return i - start;
- }
+ if (err) {
+ printf("block read failed: %d\n", err);
+ return -start;
}
return blkcnt;
--
1.6.0.6
More information about the U-Boot
mailing list