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 1fd5592..d749ab0 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; |