From mboxrd@z Thu Jan 1 00:00:00 1970 From: Balaji T K Date: Mon, 12 May 2014 18:51:11 +0530 Subject: [U-Boot] [PATCH] mmc: omap_hsmmc: add adma support In-Reply-To: <1399038920-19023-1-git-send-email-balajitk@ti.com> References: <1399038920-19023-1-git-send-email-balajitk@ti.com> Message-ID: <5370CAC7.80304@ti.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de 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 > --- > 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 > #include > #include > #include > @@ -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 >