[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