[U-Boot] [PATCH] mmc: omap_hsmmc: add adma support

Balaji T K balajitk at ti.com
Mon May 12 15:21:11 CEST 2014


On Friday 02 May 2014 07:25 PM, Balaji T K wrote:
> MMC instance 1 and 2 is capable of ADMA in omap4, omap5.
> Add support for ADMA and enable ADMA for read/write to
> improve mmc throughput.
Hi,

Realized I need to git format-patch this patch,
Any other comments ?

>
> Signed-off-by: Balaji T K <balajitk at ti.com>
> ---
>   arch/arm/include/asm/omap_mmc.h |   14 +++
>   drivers/mmc/omap_hsmmc.c        |  163 +++++++++++++++++++++++++++++++++++++---
>   include/configs/omap5_uevm.h    |    2
>   3 files changed, 169 insertions(+), 10 deletions(-)
>
> Index: u-boot_denx/arch/arm/include/asm/omap_mmc.h
> ===================================================================
> --- u-boot_denx.orig/arch/arm/include/asm/omap_mmc.h	2014-05-02 19:02:39.042727752 +0530
> +++ u-boot_denx/arch/arm/include/asm/omap_mmc.h	2014-05-02 19:18:00.783780277 +0530
> @@ -47,6 +47,9 @@ struct hsmmc {
>   	unsigned int ie;		/* 0x134 */
>   	unsigned char res4[0x8];
>   	unsigned int capa;		/* 0x140 */
> +	unsigned char res5[0x10];
> +	unsigned int adma_es;		/* 0x154 */
> +	unsigned int adma_sal;		/* 0x158 */
>   };
>
>   /*
> @@ -68,9 +71,11 @@ struct hsmmc {
>   #define WPP_ACTIVEHIGH			(0x0 << 8)
>   #define RESERVED_MASK			(0x3 << 9)
>   #define CTPL_MMC_SD			(0x0 << 11)
> +#define DMA_MNS_ADMA_MODE		(0x1 << 20)
>   #define BLEN_512BYTESLEN		(0x200 << 0)
>   #define NBLK_STPCNT			(0x0 << 16)
>   #define DE_DISABLE			(0x0 << 0)
> +#define DE_ENABLE			(0x1 << 0)
>   #define BCE_DISABLE			(0x0 << 1)
>   #define BCE_ENABLE			(0x1 << 1)
>   #define ACEN_DISABLE			(0x0 << 2)
> @@ -103,6 +108,7 @@ struct hsmmc {
>   #define DTW_1_BITMODE			(0x0 << 1)
>   #define DTW_4_BITMODE			(0x1 << 1)
>   #define DTW_8_BITMODE                   (0x1 << 5) /* CON[DW8]*/
> +#define DMAS				(0x2 << 3)
>   #define SDBP_PWROFF			(0x0 << 8)
>   #define SDBP_PWRON			(0x1 << 8)
>   #define SDVS_1V8			(0x5 << 9)
> @@ -136,12 +142,18 @@ struct hsmmc {
>   #define IE_DTO				(0x01 << 20)
>   #define IE_DCRC				(0x01 << 21)
>   #define IE_DEB				(0x01 << 22)
> +#define IE_ADMAE			(0x01 << 25)
>   #define IE_CERR				(0x01 << 28)
>   #define IE_BADA				(0x01 << 29)
>
> +#define CAPA_ADMA_SUPPORT		(1 << 19)
>   #define VS30_3V0SUP			(1 << 25)
>   #define VS18_1V8SUP			(1 << 26)
>
> +#define ADMA_XFER_VALID			(1 << 0)
> +#define ADMA_XFER_END			(1 << 1)
> +#define ADMA_XFER_DESC			(1 << 5)
> +
>   /* Driver definitions */
>   #define MMCSD_SECTOR_SIZE		512
>   #define MMC_CARD			0
> @@ -151,6 +163,8 @@ struct hsmmc {
>   #define CLK_INITSEQ			0
>   #define CLK_400KHZ			1
>   #define CLK_MISC			2
> +#define DMA_TYPE_SDMA			1
> +#define DMA_TYPE_ADMA			2
>
>   #define RSP_TYPE_NONE	(RSP_TYPE_NORSP   | CCCE_NOCHECK | CICE_NOCHECK)
>   #define MMC_CMD0	(INDEX(0)  | RSP_TYPE_NONE | DP_NO_DATA | DDIR_WRITE)
> Index: u-boot_denx/drivers/mmc/omap_hsmmc.c
> ===================================================================
> --- u-boot_denx.orig/drivers/mmc/omap_hsmmc.c	2014-05-02 19:02:39.066727884 +0530
> +++ u-boot_denx/drivers/mmc/omap_hsmmc.c	2014-05-02 19:17:25.247585485 +0530
> @@ -22,6 +22,7 @@
>    * MA 02111-1307 USA
>    */
>
> +#include <bouncebuf.h>
>   #include <config.h>
>   #include <common.h>
>   #include <malloc.h>
> @@ -44,12 +45,30 @@
>   #undef OMAP_HSMMC_USE_GPIO
>   #endif
>
> +#ifdef CONFIG_SPL_BUILD
> +#undef CONFIG_OMAP_MMC_ADMA
> +#endif
> +
> +#ifdef CONFIG_OMAP_MMC_ADMA
> +struct adma_desc_table {
> +	u16 attr;
> +	u16 length;
> +	u32 addr;
> +};
> +#define ADMA_MAX_BYTES_PER_ROW (127 * 512)
> +#define ADMA_TABLE_NUM_ENTRIES 517
> +#endif
> +
>   /* common definitions for all OMAPs */
>   #define SYSCTL_SRC	(1 << 25)
>   #define SYSCTL_SRD	(1 << 26)
> +#define IE_MASK		(IE_BADA | IE_CERR | IE_DEB | IE_DCRC | IE_DTO |\
> +			 IE_CIE | IE_CEB | IE_CCRC | IE_CTO | IE_BRR |\
> +			 IE_BWR | IE_TC | IE_CC)
>
>   struct omap_hsmmc_data {
>   	struct hsmmc *base_addr;
> +	int cap_dma;
>   	struct mmc_config cfg;
>   #ifdef OMAP_HSMMC_USE_GPIO
>   	int cd_gpio;
> @@ -205,11 +224,13 @@ void mmc_init_stream(struct hsmmc *mmc_b
>   static int omap_hsmmc_init_setup(struct mmc *mmc)
>   {
>   	struct hsmmc *mmc_base;
> +	struct omap_hsmmc_data *hsmmc_data;
>   	unsigned int reg_val;
>   	unsigned int dsor;
>   	ulong start;
>
>   	mmc_base = ((struct omap_hsmmc_data *)mmc->priv)->base_addr;
> +	hsmmc_data = (struct omap_hsmmc_data *)mmc->priv;
>   	mmc_board_init(mmc);
>
>   	writel(readl(&mmc_base->sysconfig) | MMC_SOFTRESET,
> @@ -239,6 +260,16 @@ static int omap_hsmmc_init_setup(struct
>   	writel(CTPL_MMC_SD | reg_val | WPP_ACTIVEHIGH | CDP_ACTIVEHIGH |
>   		MIT_CTO | DW8_1_4BITMODE | MODE_FUNC | STR_BLOCK |
>   		HR_NOHOSTRESP | INIT_NOINIT | NOOPENDRAIN, &mmc_base->con);
> +#ifdef CONFIG_OMAP_MMC_ADMA
> +	if (readl(&mmc_base->capa) & CAPA_ADMA_SUPPORT) {
> +		reg_val = readl(&mmc_base->con);
> +		writel(reg_val | DMA_MNS_ADMA_MODE, &mmc_base->con);
> +		writel(readl(&mmc_base->hctl) | DMAS, &mmc_base->hctl);
> +		hsmmc_data->cap_dma = DMA_TYPE_ADMA;
> +	}
> +#else
> +		hsmmc_data->cap_dma = 0;
> +#endif
>
>   	dsor = 240;
>   	mmc_reg_out(&mmc_base->sysctl, (ICE_MASK | DTO_MASK | CEN_MASK),
> @@ -255,10 +286,7 @@ static int omap_hsmmc_init_setup(struct
>   	writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl);
>
>   	writel(readl(&mmc_base->hctl) | SDBP_PWRON, &mmc_base->hctl);
> -
> -	writel(IE_BADA | IE_CERR | IE_DEB | IE_DCRC | IE_DTO | IE_CIE |
> -		IE_CEB | IE_CCRC | IE_CTO | IE_BRR | IE_BWR | IE_TC | IE_CC,
> -		&mmc_base->ie);
> +	writel(IE_MASK, &mmc_base->ie);
>
>   	mmc_init_stream(mmc_base);
>
> @@ -311,14 +339,93 @@ static void mmc_reset_controller_fsm(str
>   	}
>   }
>
> +#ifdef CONFIG_OMAP_MMC_ADMA
> +static int omap_hsmmc_adma_start(struct hsmmc *mmc_base,
> +	struct adma_desc_table *pdesc, struct mmc_data *data,
> +	void *bounce_buffer)
> +{
> +	int i;
> +	u32 dmaaddr;
> +	ulong blocks;
> +	ulong data_start, data_end;
> +
> +	dmaaddr = (u32) bounce_buffer;
> +	blocks = data->blocks;
> +	writel((u32)pdesc, &mmc_base->adma_sal);
> +	data_start = (ulong) pdesc;
> +
> +	for (i = 0; blocks != 0; i++) {
> +		pdesc->addr = dmaaddr;
> +		pdesc->attr = (ADMA_XFER_DESC | ADMA_XFER_VALID);
> +		if ((blocks * data->blocksize) <= ADMA_MAX_BYTES_PER_ROW) {
> +			pdesc->length = data->blocksize * blocks;
> +			pdesc->attr |= ADMA_XFER_END;
> +			break;
> +		} else {
> +			pdesc->length = ADMA_MAX_BYTES_PER_ROW;
> +			blocks -= (ADMA_MAX_BYTES_PER_ROW / data->blocksize);
> +			dmaaddr += ADMA_MAX_BYTES_PER_ROW;
> +			pdesc++;
> +		}
> +	}
> +	data_end = (ulong) pdesc;
> +	flush_dcache_range(data_start, data_end + ARCH_DMA_MINALIGN);
> +
> +	return 0;
> +}
> +
> +static int omap_hsmmc_adma_wait_for_tc(struct hsmmc *mmc_base)
> +{
> +	unsigned mmc_stat;
> +	ulong start;
> +	int ret = 0;
> +
> +	start = get_timer(0);
> +	while (1) {
> +		mmc_stat = readl(&mmc_base->stat);
> +
> +		if (get_timer(0) - start > 10 * MAX_RETRY_MS) {
> +			printf("%s: timed out waiting for status!\n",
> +			       __func__);
> +			ret = TIMEOUT;
> +			break;
> +		}
> +
> +		if ((mmc_stat & (IE_DTO | IE_DCRC | IE_DEB)) != 0)
> +			mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD);
> +
> +		if (mmc_stat & ERRI_MASK) {
> +			ret = 1;
> +			break;
> +		}
> +
> +		if (mmc_stat & TC_MASK) {
> +			writel(mmc_stat | TC_MASK, &mmc_base->stat);
> +			break;
> +		}
> +	}
> +
> +	return ret;
> +}
> +#endif
> +
>   static int omap_hsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
>   			struct mmc_data *data)
>   {
>   	struct hsmmc *mmc_base;
> +	struct omap_hsmmc_data *hsmmc_data;
>   	unsigned int flags, mmc_stat;
>   	ulong start;
> +	int dma_type = 0;
> +	u32 ie_val;
> +#ifdef CONFIG_OMAP_MMC_ADMA
> +	struct bounce_buffer bb;
> +	ALLOC_CACHE_ALIGN_BUFFER(struct adma_desc_table, adma_desc,
> +				 ADMA_TABLE_NUM_ENTRIES);
> +#endif
>
>   	mmc_base = ((struct omap_hsmmc_data *)mmc->priv)->base_addr;
> +	hsmmc_data = (struct omap_hsmmc_data *)mmc->priv;
>   	start = get_timer(0);
>   	while ((readl(&mmc_base->pstate) & (DATI_MASK | CMDI_MASK)) != 0) {
>   		if (get_timer(0) - start > MAX_RETRY_MS) {
> @@ -373,6 +480,8 @@ static int omap_hsmmc_send_cmd(struct mm
>   		flags |= CICE_CHECK;
>
>   	if (data) {
> +		ie_val = IE_MASK;
> +		writel(ie_val, &mmc_base->ie);
>   		if ((cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK) ||
>   			 (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK)) {
>   			flags |= (MSBS_MULTIBLK | BCE_ENABLE);
> @@ -386,6 +495,29 @@ static int omap_hsmmc_send_cmd(struct mm
>   			flags |= (DP_DATA | DDIR_READ);
>   		else
>   			flags |= (DP_DATA | DDIR_WRITE);
> +
> +		if (!(hsmmc_data->cap_dma & DMA_TYPE_ADMA)) {
> +			dma_type = 0;
> +#ifdef CONFIG_OMAP_MMC_ADMA
> +		} else {
> +			dma_type = DMA_TYPE_ADMA;
> +			flags = flags | DE_ENABLE;
> +			ie_val &= ~(IE_BRR | IE_BWR);
> +			ie_val |= IE_ADMAE;
> +			writel(ie_val, &mmc_base->ie);
> +			if (data->flags == MMC_DATA_READ) {
> +				bounce_buffer_start(&bb, (void *)data->dest,
> +						    data->blocksize *
> +						    data->blocks, GEN_BB_WRITE);
> +			} else {
> +				bounce_buffer_start(&bb, (void *)data->src,
> +						    data->blocksize *
> +						    data->blocks, GEN_BB_READ);
> +			}
> +			omap_hsmmc_adma_start(mmc_base, adma_desc, data,
> +					      bb.bounce_buffer);
> +#endif
> +		}
>   	}
>
>   	writel(cmd->cmdarg, &mmc_base->arg);
> @@ -422,13 +554,24 @@ static int omap_hsmmc_send_cmd(struct mm
>   		}
>   	}
>
> -	if (data && (data->flags & MMC_DATA_READ)) {
> -		mmc_read_data(mmc_base,	data->dest,
> -				data->blocksize * data->blocks);
> -	} else if (data && (data->flags & MMC_DATA_WRITE)) {
> -		mmc_write_data(mmc_base, data->src,
> -				data->blocksize * data->blocks);
> +	if (!dma_type) {
> +		if (data && (data->flags & MMC_DATA_READ)) {
> +			mmc_read_data(mmc_base,	data->dest,
> +				      data->blocksize * data->blocks);
> +		} else if (data && (data->flags & MMC_DATA_WRITE)) {
> +			mmc_write_data(mmc_base, data->src,
> +				       data->blocksize * data->blocks);
> +		}
> +#ifdef CONFIG_OMAP_MMC_ADMA
> +	} else {
> +		omap_hsmmc_adma_wait_for_tc(mmc_base);
> +#endif
>   	}
> +
> +#ifdef CONFIG_OMAP_MMC_ADMA
> +	if (dma_type)
> +		bounce_buffer_stop(&bb);
> +#endif
>   	return 0;
>   }
>
> Index: u-boot_denx/include/configs/omap5_uevm.h
> ===================================================================
> --- u-boot_denx.orig/include/configs/omap5_uevm.h	2014-05-02 19:02:39.094728037 +0530
> +++ u-boot_denx/include/configs/omap5_uevm.h	2014-05-02 19:17:25.247585485 +0530
> @@ -31,6 +31,8 @@
>   #define CONFIG_SYS_REDUNDAND_ENVIRONMENT
>   #define CONFIG_CMD_SAVEENV
>
> +#define CONFIG_BOUNCE_BUFFER
> +#define CONFIG_OMAP_MMC_ADMA
>   /* Enhance our eMMC support / experience. */
>   #define CONFIG_CMD_GPT
>   #define CONFIG_EFI_PARTITION
>



More information about the U-Boot mailing list