diff options
| author | Wolfgang Denk <wd@denx.de> | 2012-04-16 23:01:12 +0200 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2012-04-16 23:01:12 +0200 | 
| commit | db39f24151627733d6166c5e9a875fe8b356fa72 (patch) | |
| tree | d091e23af47b9ae848c6f69144f941d9f072aae6 /drivers/mmc/mxsmmc.c | |
| parent | b64c2420e02a7d068aae6e0d069f270feb3cdc9a (diff) | |
| parent | 2694bb9bcc8ca9636faf38c866dda7bf0529e35f (diff) | |
| download | olio-uboot-2014.01-db39f24151627733d6166c5e9a875fe8b356fa72.tar.xz olio-uboot-2014.01-db39f24151627733d6166c5e9a875fe8b356fa72.zip | |
Merge branch 'master' of git://git.denx.de/u-boot-arm
* 'master' of git://git.denx.de/u-boot-arm:
  ARM926EJS: Fix cache.c to comply with checkpatch.pl
  ARM926EJS: Make asm routines volatile in cache ops
  MX35: mx35pdk: wrong board revision
  ARM1136: MX35: Make asm routines volatile in cache ops
  ARM: add u-boot.imx as target for i.MX SOCs
  M28: Pull out CONFIG_APBH_DMA so it's always enabled
  DMA: Split the APBH DMA init into block and channel init
  imx: Return gpio_set_value in gpio_direction_output
  imx: Use GPIO_TO_PORT macro in the gpio driver instead of (gpio >> 5)
  imx: Add GPIO_TO_PORT macro in the mxc_gpio driver
  imx: Remove unneeded/repititive definitions from imx headers
  i.MX28: Allow coexistence of PIO and DMA mode for SD/MMC
  MX31: mx31pdk: drop enable_caches from board file
  i.MX28: Fix initial stack pointer position
  mx35: mx35pdk: fix when cache functions are linked
  mx35: flea3: fix when cache functions are linked
  ARM: 926ejs: use debug() for misaligned addresses
  ARM1136: add cache flush and invalidate operations
  mx6qsabrelite: Fix the serial console port
  mx6qsabrelite: Add boot switch setting information into the README
  i.MX6: mx6qsabrelite: add cache commands if cache is enabled
  i.MX6: implement enable_caches()
  i.MX6: define CACHELINE_SIZE
  MX53: DDR: Fix ZQHWCTRL field TZQ_CS
  mx28evk: Add a README file
  mx28: Split the README into a common part and a m28 specific part
  tricorder: Load kernel from ubifs
  tricorder: Add UBIFS
  cm-t35: fix Ethernet reset timing
  hawkboard: Add CONFIG_SPL_LIBGENERIC_SUPPORT
  BeagleBoard: Remove userbutton command and use gpio command instead
  OMAP: Move omap1510inn to Unmaintained / Orphaned
Diffstat (limited to 'drivers/mmc/mxsmmc.c')
| -rw-r--r-- | drivers/mmc/mxsmmc.c | 53 | 
1 files changed, 52 insertions, 1 deletions
| diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c index e8bad9dc7..35c6bdabb 100644 --- a/drivers/mmc/mxsmmc.c +++ b/drivers/mmc/mxsmmc.c @@ -43,6 +43,13 @@  #include <asm/arch/sys_proto.h>  #include <asm/arch/dma.h> +/* + * CONFIG_MXS_MMC_DMA: This feature is highly experimental and has no + *                     performance benefit unless you operate the platform with + *                     data cache enabled. This is disabled by default, enable + *                     only if you know what you're doing. + */ +  struct mxsmmc_priv {  	int			id;  	struct mx28_ssp_regs	*regs; @@ -66,8 +73,13 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)  	struct mx28_ssp_regs *ssp_regs = priv->regs;  	uint32_t reg;  	int timeout; -	uint32_t data_count, cache_data_count; +	uint32_t data_count;  	uint32_t ctrl0; +#ifndef CONFIG_MXS_MMC_DMA +	uint32_t *data_ptr; +#else +	uint32_t cache_data_count; +#endif  	debug("MMC%d: CMD%d\n", mmc->block_dev.dev, cmd->cmdidx); @@ -185,7 +197,9 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)  		return 0;  	data_count = data->blocksize * data->blocks; +	timeout = MXSMMC_MAX_TIMEOUT; +#ifdef CONFIG_MXS_MMC_DMA  	if (data_count % ARCH_DMA_MINALIGN)  		cache_data_count = roundup(data_count, ARCH_DMA_MINALIGN);  	else @@ -218,6 +232,38 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)  		invalidate_dcache_range((uint32_t)priv->desc->cmd.address,  			(uint32_t)(priv->desc->cmd.address + cache_data_count));  	} +#else +	if (data->flags & MMC_DATA_READ) { +		data_ptr = (uint32_t *)data->dest; +		while (data_count && --timeout) { +			reg = readl(&ssp_regs->hw_ssp_status); +			if (!(reg & SSP_STATUS_FIFO_EMPTY)) { +				*data_ptr++ = readl(&ssp_regs->hw_ssp_data); +				data_count -= 4; +				timeout = MXSMMC_MAX_TIMEOUT; +			} else +				udelay(1000); +		} +	} else { +		data_ptr = (uint32_t *)data->src; +		timeout *= 100; +		while (data_count && --timeout) { +			reg = readl(&ssp_regs->hw_ssp_status); +			if (!(reg & SSP_STATUS_FIFO_FULL)) { +				writel(*data_ptr++, &ssp_regs->hw_ssp_data); +				data_count -= 4; +				timeout = MXSMMC_MAX_TIMEOUT; +			} else +				udelay(1000); +		} +	} + +	if (!timeout) { +		printf("MMC%d: Data timeout with command %d (status 0x%08x)!\n", +			mmc->block_dev.dev, cmd->cmdidx, reg); +		return COMM_ERR; +	} +#endif  	/* Check data errors */  	reg = readl(&ssp_regs->hw_ssp_status); @@ -292,6 +338,7 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int))  		(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;  	struct mmc *mmc = NULL;  	struct mxsmmc_priv *priv = NULL; +	int ret;  	mmc = malloc(sizeof(struct mmc));  	if (!mmc) @@ -310,6 +357,10 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int))  		return -ENOMEM;  	} +	ret = mxs_dma_init_channel(id); +	if (ret) +		return ret; +  	priv->mmc_is_wp = wp;  	priv->id = id;  	switch (id) { |