ipq807x: dcache support for mmc driver

This patch makes mmc driver dcache aware to keep
the mmc functionality intact, with or without dcache
is enabled.

flush_cache used here does both clean and invalidate
cache thus preventing data loss during unaligned access,
if any.

Change-Id: I0910bd17678d3855bba27e9f8f7c08606774b28d
Signed-off-by: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
This commit is contained in:
Gokul Sriram Palanisamy 2018-01-22 11:27:06 +05:30 committed by Gerrit - the friendly Code Review server
parent a9998014f9
commit 4a788032d8
3 changed files with 21 additions and 9 deletions

View file

@ -257,7 +257,9 @@ static ulong mmc_bread(int dev_num, lbaint_t start, lbaint_t blkcnt, void *dst)
debug("%s: Failed to set blocklen\n", __func__);
return 0;
}
#if !defined(CONFIG_SYS_DCACHE_OFF)
flush_cache((unsigned long)dst, blkcnt * mmc->read_bl_len);
#endif
do {
cur = (blocks_todo > mmc->cfg->b_max) ?
mmc->cfg->b_max : blocks_todo;
@ -269,6 +271,9 @@ static ulong mmc_bread(int dev_num, lbaint_t start, lbaint_t blkcnt, void *dst)
start += cur;
dst += cur * mmc->read_bl_len;
} while (blocks_todo > 0);
#if !defined(CONFIG_SYS_DCACHE_OFF)
flush_cache((unsigned long)dst, blkcnt * mmc->read_bl_len);
#endif
return blkcnt;
}

View file

@ -233,6 +233,10 @@ ulong mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void *src)
if (mmc_set_blocklen(mmc, mmc->write_bl_len))
return 0;
#if !defined(CONFIG_SYS_DCACHE_OFF)
flush_cache((unsigned long)src,
(unsigned long)blkcnt * mmc->write_bl_len);
#endif
do {
cur = (blocks_todo > mmc->cfg->b_max) ?
mmc->cfg->b_max : blocks_todo;

View file

@ -91,9 +91,9 @@ static struct adma_desc *sdhci_prepare_descriptors(void *data, uint32_t len)
list[0].tran_att = SDHCI_ADMA_TRANS_VALID | SDHCI_ADMA_TRANS_DATA
| SDHCI_ADMA_TRANS_END;
invalidate_dcache_range((uint32_t)list & ~(CACHE_LINE_SIZE - 1),
ALIGN((uint32_t)list + sizeof(struct adma_desc),CACHE_LINE_SIZE));
#if !defined(CONFIG_SYS_DCACHE_OFF)
flush_cache((unsigned long)list, sizeof(struct adma_desc));
#endif
} else {
list_len = len / SDHCI_ADMA_DESC_LINE_SZ;
remain = len - (list_len * SDHCI_ADMA_DESC_LINE_SZ);
@ -124,10 +124,12 @@ static struct adma_desc *sdhci_prepare_descriptors(void *data, uint32_t len)
list[list_len - 1].len = (len < SDHCI_ADMA_DESC_LINE_SZ) ? len : (SDHCI_ADMA_DESC_LINE_SZ & 0xffff);
list[list_len - 1].tran_att = SDHCI_ADMA_TRANS_VALID | SDHCI_ADMA_TRANS_DATA |
SDHCI_ADMA_TRANS_END;
}
invalidate_dcache_range((uint32_t)list & ~(CACHE_LINE_SIZE - 1),
ALIGN((uint32_t)list + table_len,CACHE_LINE_SIZE));
#if !defined(CONFIG_SYS_DCACHE_OFF)
flush_cache((unsigned long)list, table_len);
#endif
}
return list;
}
@ -295,11 +297,11 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
if (data->flags == MMC_DATA_READ)
mode |= SDHCI_TRNS_READ;
#ifdef CONFIG_MMC_SDMA
if (data->flags == MMC_DATA_READ)
start_addr = (unsigned long)data->dest;
else
start_addr = (unsigned long)data->src;
#ifdef CONFIG_MMC_SDMA
if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) &&
(start_addr & 0x7) != 0x0) {
is_aligned = 0;
@ -337,7 +339,8 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
}
sdhci_writel(host, cmd->cmdarg, SDHCI_ARGUMENT);
#ifdef CONFIG_MMC_SDMA
#if defined(CONFIG_MMC_SDMA) || (defined(CONFIG_MMC_ADMA) && \
!defined(CONFIG_SYS_DCACHE_OFF))
flush_cache(start_addr, trans_bytes);
#endif
udelay(5);