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", 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; > > +#ifdef CONFIG_MMC_MBLOCK > + if (mmc->b_max == 0) > + mmc->b_max = 1; > +#endif > + > INIT_LIST_HEAD (&mmc->link); > > list_add_tail (&mmc->link, &mmc_devices); diff --git > a/include/mmc.h b/include/mmc.h index 8973bc7..04c7eaf 100644 > --- a/include/mmc.h > +++ b/include/mmc.h > @@ -264,6 +264,9 @@ struct mmc { > struct mmc_cmd *cmd, struct mmc_data *data); > void (*set_ios)(struct mmc *mmc); > int (*init)(struct mmc *mmc); > +#ifdef CONFIG_MMC_MBLOCK > + uint b_max; > +#endif > }; > > int mmc_register(struct mmc *mmc); > -- > 1.6.0.6 > > _______________________________________________ > 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