[U-Boot] [PATCH] tegra: mmc: Support operation with dcache enabled

When the data cache is enabled we must flush on write and invalidate on read. We also check that buffers are aligned to data cache lines boundaries. With recent work in U-Boot this should generally be the case but the warnings will catch problems.
Signed-off-by: Simon Glass sjg@chromium.org --- drivers/mmc/tegra2_mmc.c | 15 +++++++++++++++ 1 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/drivers/mmc/tegra2_mmc.c b/drivers/mmc/tegra2_mmc.c index 035a868..bcf476f 100644 --- a/drivers/mmc/tegra2_mmc.c +++ b/drivers/mmc/tegra2_mmc.c @@ -114,6 +114,14 @@ 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(data->src, data->src + + data->blocks * data->blocksize); + } + writew(mode, &host->reg->trnmod); }
@@ -310,6 +318,13 @@ 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(data->dest, data->dest + + data->blocks * data->blocksize); + } }
udelay(1000);

Simon Glass wrote at Wednesday, December 21, 2011 1:03 PM:
When the data cache is enabled we must flush on write and invalidate on read. We also check that buffers are aligned to data cache lines boundaries. With recent work in U-Boot this should generally be the case but the warnings will catch problems.
Signed-off-by: Simon Glass sjg@chromium.org
Conceptually this seems fine, but shouldn't the MMC driver core be doing the cache management, so all platforms without cache coherency can benefit from it?

On Wednesday 21 December 2011 16:10:16 Stephen Warren wrote:
Simon Glass wrote at Wednesday, December 21, 2011 1:03 PM:
When the data cache is enabled we must flush on write and invalidate on read. We also check that buffers are aligned to data cache lines boundaries. With recent work in U-Boot this should generally be the case but the warnings will catch problems.
Conceptually this seems fine, but shouldn't the MMC driver core be doing the cache management, so all platforms without cache coherency can benefit from it?
if the driver bitbangs things out (like SPI/MMC), then the core doing it would be a waste wouldn't it ?
a better question might be how does Linux handle it ? does it force the drivers to do it, or does the core take care of things ? -mike

On Sun, Jan 8, 2012 at 2:42 AM, Mike Frysinger vapier@gentoo.org wrote:
On Wednesday 21 December 2011 16:10:16 Stephen Warren wrote:
Simon Glass wrote at Wednesday, December 21, 2011 1:03 PM:
When the data cache is enabled we must flush on write and invalidate on read. We also check that buffers are aligned to data cache lines boundaries. With recent work in U-Boot this should generally be the case but the warnings will catch problems.
Conceptually this seems fine, but shouldn't the MMC driver core be doing the cache management, so all platforms without cache coherency can benefit from it?
if the driver bitbangs things out (like SPI/MMC), then the core doing it would be a waste wouldn't it ?
a better question might be how does Linux handle it ? does it force the drivers to do it, or does the core take care of things ?
As I understand it, drivers are responsible for handling this on their own. However, they use an intermediate DMA API to map a buffer into DMA-capable memory space, and then to unmap it when it's done. There's also a "flush" function. We could theoretically provide a similar capability.
I think, for now, doing this by hand in each driver is fine. A full DMA layer would require some design, and would, I think, devolve into essentially just cache-flushing. I'm not aware of any U-Boot drivers which would require actual mapping calls to deal with things like using 36-bits of physical memory. Yet.
Andy

On Wed, Dec 21, 2011 at 2:02 PM, Simon Glass sjg@chromium.org wrote:
When the data cache is enabled we must flush on write and invalidate on read. We also check that buffers are aligned to data cache lines boundaries. With recent work in U-Boot this should generally be the case but the warnings will catch problems.
Signed-off-by: Simon Glass sjg@chromium.org
With this patch applied, I see these warnings:
tegra2_mmc.c: In function 'mmc_set_transfer_mode': tegra2_mmc.c:122:4: warning: passing argument 1 of 'flush_dcache_range' makes integer from pointer without a cast /local/afleming/u-boot/include/common.h:695:6: note: expected 'long unsigned int' but argument is of type 'const char *' tegra2_mmc.c:122:4: warning: passing argument 2 of 'flush_dcache_range' makes integer from pointer without a cast /local/afleming/u-boot/include/common.h:695:6: note: expected 'long unsigned int' but argument is of type 'const char *' tegra2_mmc.c: In function 'mmc_send_cmd': tegra2_mmc.c:326:5: warning: passing argument 1 of 'invalidate_dcache_range' makes integer from pointer without a cast /local/afleming/u-boot/include/common.h:696:6: note: expected 'long unsigned int' but argument is of type 'char *' tegra2_mmc.c:326:5: warning: passing argument 2 of 'invalidate_dcache_range' makes integer from pointer without a cast /local/afleming/u-boot/include/common.h:696:6: note: expected 'long unsigned int' but argument is of type 'char *'
Andy

Hi Andy,
On Sun, Jan 8, 2012 at 7:36 PM, Andy Fleming afleming@gmail.com wrote:
On Wed, Dec 21, 2011 at 2:02 PM, Simon Glass sjg@chromium.org wrote:
When the data cache is enabled we must flush on write and invalidate on read. We also check that buffers are aligned to data cache lines boundaries. With recent work in U-Boot this should generally be the case but the warnings will catch problems.
Signed-off-by: Simon Glass sjg@chromium.org
H With this patch applied, I see these warnings:
Yes Tom mentioned this also. Since it seems this is the way we are going (rather than a fix at the generic MMC level) I will tidy this up and resubmit.
tegra2_mmc.c: In function 'mmc_set_transfer_mode': tegra2_mmc.c:122:4: warning: passing argument 1 of 'flush_dcache_range' makes integer from pointer without a cast /local/afleming/u-boot/include/common.h:695:6: note: expected 'long unsigned int' but argument is of type 'const char *' tegra2_mmc.c:122:4: warning: passing argument 2 of 'flush_dcache_range' makes integer from pointer without a cast /local/afleming/u-boot/include/common.h:695:6: note: expected 'long unsigned int' but argument is of type 'const char *' tegra2_mmc.c: In function 'mmc_send_cmd': tegra2_mmc.c:326:5: warning: passing argument 1 of 'invalidate_dcache_range' makes integer from pointer without a cast /local/afleming/u-boot/include/common.h:696:6: note: expected 'long unsigned int' but argument is of type 'char *' tegra2_mmc.c:326:5: warning: passing argument 2 of 'invalidate_dcache_range' makes integer from pointer without a cast /local/afleming/u-boot/include/common.h:696:6: note: expected 'long unsigned int' but argument is of type 'char *'
Andy
Regards, Simon
participants (4)
-
Andy Fleming
-
Mike Frysinger
-
Simon Glass
-
Stephen Warren