diff options
Diffstat (limited to 'drivers/mmc/tegra_mmc.c')
| -rw-r--r-- | drivers/mmc/tegra_mmc.c | 64 | 
1 files changed, 41 insertions, 23 deletions
| diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index 1fd5592f2..d749ab095 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -19,6 +19,7 @@   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   */ +#include <bouncebuf.h>  #include <common.h>  #include <asm/gpio.h>  #include <asm/io.h> @@ -66,14 +67,17 @@ static void tegra_get_setup(struct mmc_host *host, int dev_index)  	host->reg = (struct tegra_mmc *)host->base;  } -static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data) +static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data, +				struct bounce_buffer *bbstate)  {  	unsigned char ctrl; -	debug("data->dest: %08X, data->blocks: %u, data->blocksize: %u\n", -	(u32)data->dest, data->blocks, data->blocksize); -	writel((u32)data->dest, &host->reg->sysad); +	debug("buf: %p (%p), data->blocks: %u, data->blocksize: %u\n", +		bbstate->bounce_buffer, bbstate->user_buffer, data->blocks, +		data->blocksize); + +	writel((u32)bbstate->bounce_buffer, &host->reg->sysad);  	/*  	 * DMASEL[4:3]  	 * 00 = Selects SDMA @@ -114,14 +118,6 @@ static void mmc_set_transfer_mode(struct mmc_host *host, struct mmc_data *data)  	if (data->flags & MMC_DATA_READ)  		mode |= TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ; -	if (data->flags & MMC_DATA_WRITE) { -		if ((uintptr_t)data->src & (ARCH_DMA_MINALIGN - 1)) -			printf("Warning: unaligned write to %p may fail\n", -			       data->src); -		flush_dcache_range((ulong)data->src, (ulong)data->src + -			data->blocks * data->blocksize); -	} -  	writew(mode, &host->reg->trnmod);  } @@ -156,8 +152,8 @@ static int mmc_wait_inhibit(struct mmc_host *host,  	return 0;  } -static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, -			struct mmc_data *data) +static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd, +			struct mmc_data *data, struct bounce_buffer *bbstate)  {  	struct mmc_host *host = (struct mmc_host *)mmc->priv;  	int flags, i; @@ -172,7 +168,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,  		return result;  	if (data) -		mmc_prepare_data(host, data); +		mmc_prepare_data(host, data, bbstate);  	debug("cmd->arg: %08x\n", cmd->cmdarg);  	writel(cmd->cmdarg, &host->reg->argument); @@ -322,20 +318,42 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,  			}  		}  		writel(mask, &host->reg->norintsts); -		if (data->flags & MMC_DATA_READ) { -			if ((uintptr_t)data->dest & (ARCH_DMA_MINALIGN - 1)) -				printf("Warning: unaligned read from %p " -					"may fail\n", data->dest); -			invalidate_dcache_range((ulong)data->dest, -				(ulong)data->dest + -					data->blocks * data->blocksize); -		}  	}  	udelay(1000);  	return 0;  } +static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, +			struct mmc_data *data) +{ +	void *buf; +	unsigned int bbflags; +	size_t len; +	struct bounce_buffer bbstate; +	int ret; + +	if (data) { +		if (data->flags & MMC_DATA_READ) { +			buf = data->dest; +			bbflags = GEN_BB_WRITE; +		} else { +			buf = (void *)data->src; +			bbflags = GEN_BB_READ; +		} +		len = data->blocks * data->blocksize; + +		bounce_buffer_start(&bbstate, buf, len, bbflags); +	} + +	ret = mmc_send_cmd_bounced(mmc, cmd, data, &bbstate); + +	if (data) +		bounce_buffer_stop(&bbstate); + +	return ret; +} +  static void mmc_change_clock(struct mmc_host *host, uint clock)  {  	int div; |