Re: [U-Boot] [PATCH 3/4] MMC Multi-block Support
On Sat, Oct 23, 2010 at 8:14 AM, Ghorai, Sukumar s-gho...@ti.com wrote: -Original Message- From: u-boot-boun...@lists.denx.de [mailto:u-boot-boun...@lists.denx.de] On Behalf Of Steve Sakoman Sent: Friday, October 15, 2010 3:14 AM To: John Rigby Cc: u-boot@lists.denx.de; Alagu Sankar; Andy Fleming Subject: Re: [U-Boot] [PATCH 3/4] MMC Multi-block Support On Mon, Oct 4, 2010 at 1:32 PM, John Rigby jcri...@gmail.com wrote: Alagu, This never made it into Andy's tree nor upstream. Could you submit a new patch to current upstream with the config option removed as Andy said he did back in May? Maybe we can get it commited via some other maintainer. Steve Sakoman seems to have done some MMC work lately. I've done some testing with this patch on OMAP3 and OMAP4, in the always enabled version. I compared the old legacy mmc driver vs the new generic mmc driver vs new generic mmc driver with multiblock read support added. The good news is that the generic mmc driver for OMAP is almost twice as fast as the old legacy driver. These patches should be in the next u-boot-ti pull request and so will be in mainline shortly. The bad news is that multiblock reads seem to make no difference :-( For reading a 45MB file from an ext3 partition using ext2load I get: legacy: 62 seconds generic: 35 seconds generic w/ multi: 35 seconds I'm happy to resubmit the multi-block read patch because it does seem to work properly and may even yield improvements on other architectures. Would you like me to do that? [Ghorai] would you please try with additional change? Yes! That is much better! Now multiblock reads are faster :-) The results (including the old legacy mmc driver for reference): legacy: 62 seconds generic: 35 seconds generic w/ multi: 9 seconds I will add my Acked-by and Tested-by and submit the final patch to the list later today. Steve $git diff drivers/mmc/omap_hsmmc.c diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index f8b9840..7f3f968 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -401,6 +401,7 @@ int omap_mmc_init(int dev_index) mmc-f_min = 40; mmc-f_max = 5200; + mmc-b_max = 0x; mmc_register(mmc); Steve ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [PATCH 3/4] MMC Multi-block Support
-Original Message- From: Steve Sakoman [mailto:sako...@gmail.com] Sent: Monday, October 25, 2010 11:00 PM To: Ghorai, Sukumar Cc: John Rigby; u-boot@lists.denx.de; Alagu Sankar; Andy Fleming Subject: Re: [U-Boot] [PATCH 3/4] MMC Multi-block Support On Sat, Oct 23, 2010 at 8:14 AM, Ghorai, Sukumar s-gho...@ti.com wrote: -Original Message- From: u-boot-boun...@lists.denx.de [mailto:u-boot- boun...@lists.denx.de] On Behalf Of Steve Sakoman Sent: Friday, October 15, 2010 3:14 AM To: John Rigby Cc: u-boot@lists.denx.de; Alagu Sankar; Andy Fleming Subject: Re: [U-Boot] [PATCH 3/4] MMC Multi-block Support On Mon, Oct 4, 2010 at 1:32 PM, John Rigby jcri...@gmail.com wrote: Alagu, This never made it into Andy's tree nor upstream. Could you submit a new patch to current upstream with the config option removed as Andy said he did back in May? Maybe we can get it commited via some other maintainer. Steve Sakoman seems to have done some MMC work lately. I've done some testing with this patch on OMAP3 and OMAP4, in the always enabled version. I compared the old legacy mmc driver vs the new generic mmc driver vs new generic mmc driver with multiblock read support added. The good news is that the generic mmc driver for OMAP is almost twice as fast as the old legacy driver. These patches should be in the next u-boot-ti pull request and so will be in mainline shortly. The bad news is that multiblock reads seem to make no difference :-( For reading a 45MB file from an ext3 partition using ext2load I get: legacy: 62 seconds generic: 35 seconds generic w/ multi: 35 seconds I'm happy to resubmit the multi-block read patch because it does seem to work properly and may even yield improvements on other architectures. Would you like me to do that? [Ghorai] would you please try with additional change? Yes! That is much better! Now multiblock reads are faster :-) The results (including the old legacy mmc driver for reference): legacy: 62 seconds generic: 35 seconds generic w/ multi: 9 seconds I will add my Acked-by and Tested-by and submit the final patch to the list later today. [Ghorai] please add Tested-by: Sukumar Ghorai s-gho...@ti.com And will submit a separate patch as mentioned below. Steve $git diff drivers/mmc/omap_hsmmc.c diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index f8b9840..7f3f968 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -401,6 +401,7 @@ int omap_mmc_init(int dev_index) mmc-f_min = 40; mmc-f_max = 5200; + mmc-b_max = 0x; mmc_register(mmc); Steve ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [PATCH 3/4] MMC Multi-block Support
-Original Message- From: u-boot-boun...@lists.denx.de [mailto:u-boot-boun...@lists.denx.de] On Behalf Of Steve Sakoman Sent: Friday, October 15, 2010 3:14 AM To: John Rigby Cc: u-boot@lists.denx.de; Alagu Sankar; Andy Fleming Subject: Re: [U-Boot] [PATCH 3/4] MMC Multi-block Support On Mon, Oct 4, 2010 at 1:32 PM, John Rigby jcri...@gmail.com wrote: Alagu, This never made it into Andy's tree nor upstream. Could you submit a new patch to current upstream with the config option removed as Andy said he did back in May? Maybe we can get it commited via some other maintainer. Steve Sakoman seems to have done some MMC work lately. I've done some testing with this patch on OMAP3 and OMAP4, in the always enabled version. I compared the old legacy mmc driver vs the new generic mmc driver vs new generic mmc driver with multiblock read support added. The good news is that the generic mmc driver for OMAP is almost twice as fast as the old legacy driver. These patches should be in the next u-boot-ti pull request and so will be in mainline shortly. The bad news is that multiblock reads seem to make no difference :-( For reading a 45MB file from an ext3 partition using ext2load I get: legacy: 62 seconds generic: 35 seconds generic w/ multi: 35 seconds I'm happy to resubmit the multi-block read patch because it does seem to work properly and may even yield improvements on other architectures. Would you like me to do that? [Ghorai] would you please try with additional change? $git diff drivers/mmc/omap_hsmmc.c diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index f8b9840..7f3f968 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -401,6 +401,7 @@ int omap_mmc_init(int dev_index) mmc-f_min = 40; mmc-f_max = 5200; + mmc-b_max = 0x; mmc_register(mmc); Steve ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [PATCH 3/4] MMC Multi-block Support
On Mon, Oct 4, 2010 at 1:32 PM, John Rigby jcri...@gmail.com wrote: Alagu, This never made it into Andy's tree nor upstream. Could you submit a new patch to current upstream with the config option removed as Andy said he did back in May? Maybe we can get it commited via some other maintainer. Steve Sakoman seems to have done some MMC work lately. I've done some testing with this patch on OMAP3 and OMAP4, in the always enabled version. I compared the old legacy mmc driver vs the new generic mmc driver vs new generic mmc driver with multiblock read support added. The good news is that the generic mmc driver for OMAP is almost twice as fast as the old legacy driver. These patches should be in the next u-boot-ti pull request and so will be in mainline shortly. The bad news is that multiblock reads seem to make no difference :-( For reading a 45MB file from an ext3 partition using ext2load I get: legacy: 62 seconds generic: 35 seconds generic w/ multi: 35 seconds I'm happy to resubmit the multi-block read patch because it does seem to work properly and may even yield improvements on other architectures. Would you like me to do that? Steve ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [PATCH 3/4] MMC Multi-block Support
On Mon, Oct 4, 2010 at 1:32 PM, John Rigby jcri...@gmail.com wrote: Alagu, This never made it into Andy's tree nor upstream. Could you submit a new patch to current upstream with the config option removed as Andy said he did back in May? Maybe we can get it commited via some other maintainer. Steve Sakoman seems to have done some MMC work lately. I've done some testing with this patch on OMAP3 and OMAP4, in the always enabled version. I compared the old legacy mmc driver vs the new generic mmc driver vs new generic mmc driver with multiblock read support added. The good news is that the generic mmc driver for OMAP is almost twice as fast as the old legacy driver. These patches should be in the next u-boot-ti pull request and so will be in mainline shortly. The bad news is that multiblock reads seem to make no difference :-( For reading a 45MB file from an ext3 partition using ext2load I get: legacy: 62 seconds generic: 35 seconds generic w/ multi: 35 seconds I'm happy to resubmit the multi-block read patch because it does seem to work properly and may even yield improvements on other architectures. Would you like me to do that? Steve Yes please submit updated patches if you have them in your tree. Others might want to participate in a new round of review. Sandeep ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [PATCH 3/4] MMC Multi-block Support
Alagu, This never made it into Andy's tree nor upstream. Could you submit a new patch to current upstream with the config option removed as Andy said he did back in May? Maybe we can get it commited via some other maintainer. Steve Sakoman seems to have done some MMC work lately. Thanks, John On Fri, May 14, 2010 at 11:37 AM, Andy Fleming aflem...@gmail.com wrote: On Wed, May 12, 2010 at 4:38 AM, Alagu Sankar alagusan...@embwise.com wrote: Added Multi-Block Read support for Generic MMC. Modified existing multi-block write to limit the maximum number of blocks per transfer. This feature is enabled with CONFIG_MMC_MBLOCK option. A new member is added in the mmc structure for the host controller to specify the maximum number of blocks it supports. Signed-off-by: Alagu Sankar alagusan...@embwise.com I removed the config option, and just made this always how it works. Applied. Thanks! ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [PATCH 3/4] MMC Multi-block Support
Hi, Has this changed been merged into uboot mainline? Current mmc framework read is rather slow comparing with the write... If we could get the multiply-read behavior, that would be nice. :-) Thanks, Lei On Sat, May 15, 2010 at 1:37 AM, Andy Fleming aflem...@gmail.com wrote: On Wed, May 12, 2010 at 4:38 AM, Alagu Sankar alagusan...@embwise.com wrote: Added Multi-Block Read support for Generic MMC. Modified existing multi-block write to limit the maximum number of blocks per transfer. This feature is enabled with CONFIG_MMC_MBLOCK option. A new member is added in the mmc structure for the host controller to specify the maximum number of blocks it supports. Signed-off-by: Alagu Sankar alagusan...@embwise.com I removed the config option, and just made this always how it works. Applied. Thanks! ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [PATCH 3/4] MMC Multi-block Support
On Wed, May 12, 2010 at 4:38 AM, Alagu Sankar alagusan...@embwise.com wrote: Added Multi-Block Read support for Generic MMC. Modified existing multi-block write to limit the maximum number of blocks per transfer. This feature is enabled with CONFIG_MMC_MBLOCK option. A new member is added in the mmc structure for the host controller to specify the maximum number of blocks it supports. Signed-off-by: Alagu Sankar alagusan...@embwise.com I removed the config option, and just made this always how it works. Applied. Thanks! ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [PATCH 3/4] MMC Multi-block Support
Hi, Personally I think this patch can be used as common. CONFIG_MMC_MBLOCK is not needed. It can improve performance a lot for generic mmc. Thanks~~ Yours Terry -Original Message- From: u-boot-boun...@lists.denx.de [mailto:u-boot-boun...@lists.denx.de] On Behalf Of Alagu Sankar Sent: 2010年5月12日 17:43 To: u-boot@lists.denx.de Subject: [U-Boot] [PATCH 3/4] MMC Multi-block Support Added Multi-Block Read support for Generic MMC. Modified existing multi-block write to limit the maximum number of blocks per transfer. This feature is enabled with CONFIG_MMC_MBLOCK option. A new member is added in the mmc structure for the host controller to specify the maximum number of blocks it supports. Signed-off-by: Alagu Sankar alagusan...@embwise.com --- drivers/mmc/mmc.c | 156 + include/mmc.h |3 + 2 files changed, 159 insertions(+), 0 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index e7abf94..3f5a200 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -77,6 +77,7 @@ struct mmc *find_mmc_device(int dev_num) return NULL; } +#ifndef CONFIG_MMC_MBLOCK static ulong mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src) { @@ -238,6 +239,156 @@ static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst) return blkcnt; } +#else + +static int mmc_write_blocks(struct mmc *mmc, const char *src, uint start, + uint blkcnt) +{ + struct mmc_cmd cmd; + struct mmc_data data; + int err; + int blklen; + + blklen = mmc-write_bl_len; + + err = mmc_set_blocklen(mmc, mmc-write_bl_len); + + if (err) { + printf(set write bl len failed\n\r); + return err; + } + + if (blkcnt 1) + cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK; + else + cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK; + + if (mmc-high_capacity) + cmd.cmdarg = start; + else + cmd.cmdarg = start * blklen; + + cmd.resp_type = MMC_RSP_R1; + cmd.flags = 0; + + data.src = src; + data.blocks = blkcnt; + data.blocksize = blklen; + data.flags = MMC_DATA_WRITE; + + err = mmc_send_cmd(mmc, cmd, data); + + if (err) { + printf(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; + err = mmc_send_cmd(mmc, cmd, NULL); + } + + return err; +} + +static ulong +mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void *src) +{ + int err; + int i; + struct mmc *mmc = find_mmc_device(dev_num); + uint b_max = mmc-b_max; + + if (!mmc) + return 0; + + for (i = blkcnt; i 0; i -= b_max) { + uint blocks = (i b_max) ? b_max : i; + + err = mmc_write_blocks(mmc, src, start, blocks); + if (err) + return blkcnt - i; + start += blocks; + src += (mmc-write_bl_len * blocks); + } + + return blkcnt; +} + +int mmc_read_blocks(struct mmc *mmc, void *dst, uint blocknum, uint +blkcnt) { + int err; + struct mmc_cmd cmd; + struct mmc_data data; + + 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; + else + cmd.cmdarg = blocknum * mmc-read_bl_len; + + cmd.resp_type = MMC_RSP_R1; + cmd.flags = 0; + + data.dest = dst; + data.blocks = blkcnt; + data.blocksize = mmc-read_bl_len; + data.flags = MMC_DATA_READ; + + err = mmc_send_cmd(mmc, cmd, data); + if (err) + return err; + + if (blkcnt 1) { + cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; + cmd.cmdarg = 0; + cmd.resp_type = MMC_RSP_R1b; + cmd.flags = 0; + err = mmc_send_cmd(mmc, cmd, NULL); + } + + return err; +} + +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); + uint b_max = mmc-b_max; + + if (!mmc) + return 0; + + /* We always do full block reads from the card */ + err = mmc_set_blocklen(mmc, mmc-read_bl_len); + if (err) + return 0; + + for (i = blkcnt; i 0; i -= b_max) { + uint blocks = (i b_max) ? b_max : i; + + err = mmc_read_blocks(mmc, dst, start, blocks); + if (err) { + printf(block read failed: %d\n
[U-Boot] [PATCH 3/4] MMC Multi-block Support
Added Multi-Block Read support for Generic MMC. Modified existing multi-block write to limit the maximum number of blocks per transfer. This feature is enabled with CONFIG_MMC_MBLOCK option. A new member is added in the mmc structure for the host controller to specify the maximum number of blocks it supports. Signed-off-by: Alagu Sankar alagusan...@embwise.com --- drivers/mmc/mmc.c | 156 + include/mmc.h |3 + 2 files changed, 159 insertions(+), 0 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index e7abf94..3f5a200 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -77,6 +77,7 @@ struct mmc *find_mmc_device(int dev_num) return NULL; } +#ifndef CONFIG_MMC_MBLOCK static ulong mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src) { @@ -238,6 +239,156 @@ static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst) return blkcnt; } +#else + +static int mmc_write_blocks(struct mmc *mmc, const char *src, uint start, + uint blkcnt) +{ + struct mmc_cmd cmd; + struct mmc_data data; + int err; + int blklen; + + blklen = mmc-write_bl_len; + + err = mmc_set_blocklen(mmc, mmc-write_bl_len); + + if (err) { + printf(set write bl len failed\n\r); + return err; + } + + if (blkcnt 1) + cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK; + else + cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK; + + if (mmc-high_capacity) + cmd.cmdarg = start; + else + cmd.cmdarg = start * blklen; + + cmd.resp_type = MMC_RSP_R1; + cmd.flags = 0; + + data.src = src; + data.blocks = blkcnt; + data.blocksize = blklen; + data.flags = MMC_DATA_WRITE; + + err = mmc_send_cmd(mmc, cmd, data); + + if (err) { + printf(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; + err = mmc_send_cmd(mmc, cmd, NULL); + } + + return err; +} + +static ulong +mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void *src) +{ + int err; + int i; + struct mmc *mmc = find_mmc_device(dev_num); + uint b_max = mmc-b_max; + + if (!mmc) + return 0; + + for (i = blkcnt; i 0; i -= b_max) { + uint blocks = (i b_max) ? b_max : i; + + err = mmc_write_blocks(mmc, src, start, blocks); + if (err) + return blkcnt - i; + start += blocks; + src += (mmc-write_bl_len * blocks); + } + + return blkcnt; +} + +int mmc_read_blocks(struct mmc *mmc, void *dst, uint blocknum, uint blkcnt) +{ + int err; + struct mmc_cmd cmd; + struct mmc_data data; + + 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; + else + cmd.cmdarg = blocknum * mmc-read_bl_len; + + cmd.resp_type = MMC_RSP_R1; + cmd.flags = 0; + + data.dest = dst; + data.blocks = blkcnt; + data.blocksize = mmc-read_bl_len; + data.flags = MMC_DATA_READ; + + err = mmc_send_cmd(mmc, cmd, data); + if (err) + return err; + + if (blkcnt 1) { + cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; + cmd.cmdarg = 0; + cmd.resp_type = MMC_RSP_R1b; + cmd.flags = 0; + err = mmc_send_cmd(mmc, cmd, NULL); + } + + return err; +} + +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); + uint b_max = mmc-b_max; + + if (!mmc) + return 0; + + /* We always do full block reads from the card */ + err = mmc_set_blocklen(mmc, mmc-read_bl_len); + if (err) + return 0; + + for (i = blkcnt; i 0; i -= b_max) { + uint blocks = (i b_max) ? b_max : i; + + err = mmc_read_blocks(mmc, dst, start, blocks); + if (err) { + printf(block read failed: %d\n, err); + return blkcnt - i; + } + start += blocks; + dst += (mmc-read_bl_len * blocks); + } + + return blkcnt; +} + +#endif + int mmc_go_idle(struct mmc* mmc) { struct mmc_cmd cmd; @@ -858,6 +1009,11 @@ int mmc_register(struct mmc *mmc) mmc-block_dev.block_read = mmc_bread; mmc-block_dev.block_write = mmc_bwrite;
[U-Boot] [PATCH 3/4] MMC Multi-block Support
Added Multi-Block Read support for Generic MMC. Modified existing multi-block write to limit the maximum number of blocks per transfer. This feature is enabled with CONFIG_MMC_MBLOCK option. A new member is added in the mmc structure for the host controller to specify the maximum number of blocks it supports. Signed-off-by: Alagu Sankar alagusan...@embwise.com --- drivers/mmc/mmc.c | 156 + include/mmc.h |3 + 2 files changed, 159 insertions(+), 0 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index e7abf94..3f5a200 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -77,6 +77,7 @@ struct mmc *find_mmc_device(int dev_num) return NULL; } +#ifndef CONFIG_MMC_MBLOCK static ulong mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src) { @@ -238,6 +239,156 @@ static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst) return blkcnt; } +#else + +static int mmc_write_blocks(struct mmc *mmc, const char *src, uint start, + uint blkcnt) +{ + struct mmc_cmd cmd; + struct mmc_data data; + int err; + int blklen; + + blklen = mmc-write_bl_len; + + err = mmc_set_blocklen(mmc, mmc-write_bl_len); + + if (err) { + printf(set write bl len failed\n\r); + return err; + } + + if (blkcnt 1) + cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK; + else + cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK; + + if (mmc-high_capacity) + cmd.cmdarg = start; + else + cmd.cmdarg = start * blklen; + + cmd.resp_type = MMC_RSP_R1; + cmd.flags = 0; + + data.src = src; + data.blocks = blkcnt; + data.blocksize = blklen; + data.flags = MMC_DATA_WRITE; + + err = mmc_send_cmd(mmc, cmd, data); + + if (err) { + printf(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; + err = mmc_send_cmd(mmc, cmd, NULL); + } + + return err; +} + +static ulong +mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void *src) +{ + int err; + int i; + struct mmc *mmc = find_mmc_device(dev_num); + uint b_max = mmc-b_max; + + if (!mmc) + return 0; + + for (i = blkcnt; i 0; i -= b_max) { + uint blocks = (i b_max) ? b_max : i; + + err = mmc_write_blocks(mmc, src, start, blocks); + if (err) + return blkcnt - i; + start += blocks; + src += (mmc-write_bl_len * blocks); + } + + return blkcnt; +} + +int mmc_read_blocks(struct mmc *mmc, void *dst, uint blocknum, uint blkcnt) +{ + int err; + struct mmc_cmd cmd; + struct mmc_data data; + + 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; + else + cmd.cmdarg = blocknum * mmc-read_bl_len; + + cmd.resp_type = MMC_RSP_R1; + cmd.flags = 0; + + data.dest = dst; + data.blocks = blkcnt; + data.blocksize = mmc-read_bl_len; + data.flags = MMC_DATA_READ; + + err = mmc_send_cmd(mmc, cmd, data); + if (err) + return err; + + if (blkcnt 1) { + cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; + cmd.cmdarg = 0; + cmd.resp_type = MMC_RSP_R1b; + cmd.flags = 0; + err = mmc_send_cmd(mmc, cmd, NULL); + } + + return err; +} + +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); + uint b_max = mmc-b_max; + + if (!mmc) + return 0; + + /* We always do full block reads from the card */ + err = mmc_set_blocklen(mmc, mmc-read_bl_len); + if (err) + return 0; + + for (i = blkcnt; i 0; i -= b_max) { + uint blocks = (i b_max) ? b_max : i; + + err = mmc_read_blocks(mmc, dst, start, blocks); + if (err) { + printf(block read failed: %d\n, err); + return blkcnt - i; + } + start += blocks; + dst += (mmc-read_bl_len * blocks); + } + + return blkcnt; +} + +#endif + int mmc_go_idle(struct mmc* mmc) { struct mmc_cmd cmd; @@ -858,6 +1009,11 @@ int mmc_register(struct mmc *mmc) mmc-block_dev.block_read = mmc_bread; mmc-block_dev.block_write = mmc_bwrite;