mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 15:41:40 +00:00
i.MX28: Allow coexistence of PIO and DMA mode for SD/MMC
This SD DMA function of i.MX28 is still apparently too experimental to be enabled by default in 2012.04 release. Enable this feature only if the user plans to tinker with DCache or explicitly enables it. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Stefano Babic <sbabic@denx.de> Cc: Wolfgang Denk <wd@denx.de> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <fabio.estevam@freescale.com>
This commit is contained in:
parent
d0f5600f54
commit
4cc76c609f
1 changed files with 47 additions and 1 deletions
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue