[U-Boot] [PATCH 3/4] MMC Multi-block Support
Lv Terry-R65388
r65388 at freescale.com
Thu May 13 09:19:31 CEST 2010
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-bounces at lists.denx.de
> [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Alagu Sankar
> Sent: 2010年5月12日 17:43
> To: u-boot at 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 <alagusankar at 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 at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
>
>
More information about the U-Boot
mailing list