Bounce buffer may be used for CPU-only transfers (this is currently
the case for cadence_qspi). However, in this case, invalidating the
data cache might throw away copied data that is still in the cache
only.

To make CPU-only transfers work with bouncebuf (but still take
advantage of having aligned buffers), a new flag 'GEN_BB_NODMA' is
introduced. If this flag is set, cache flushing/invalidation is
skipped and only the alignment part of bouncebuf is active.

Signed-off-by: Simon Goldschmidt <sgoldschm...@de.pepperl-fuchs.com>
---
 common/bouncebuf.c  | 9 +++++----
 include/bouncebuf.h | 9 +++++++++
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/common/bouncebuf.c b/common/bouncebuf.c
index 054d9e0302..0d18477f13 100644
--- a/common/bouncebuf.c
+++ b/common/bouncebuf.c
@@ -55,16 +55,17 @@ int bounce_buffer_start(struct bounce_buffer *state, void 
*data,
         * Flush data to RAM so DMA reads can pick it up,
         * and any CPU writebacks don't race with DMA writes
         */
-       flush_dcache_range((unsigned long)state->bounce_buffer,
-                               (unsigned long)(state->bounce_buffer) +
-                                       state->len_aligned);
+       if (!(state->flags & GEN_BB_NODMA))
+               flush_dcache_range((unsigned long)state->bounce_buffer,
+                                       (unsigned long)(state->bounce_buffer) +
+                                               state->len_aligned);
 
        return 0;
 }
 
 int bounce_buffer_stop(struct bounce_buffer *state)
 {
-       if (state->flags & GEN_BB_WRITE) {
+       if ((state->flags & (GEN_BB_WRITE|GEN_BB_NODMA)) == GEN_BB_WRITE) {
                /* Invalidate cache so that CPU can see any newly DMA'd data */
                invalidate_dcache_range((unsigned long)state->bounce_buffer,
                                        (unsigned long)(state->bounce_buffer) +
diff --git a/include/bouncebuf.h b/include/bouncebuf.h
index 5ffa99bc13..c6720b3b2e 100644
--- a/include/bouncebuf.h
+++ b/include/bouncebuf.h
@@ -37,6 +37,15 @@
  */
 #define GEN_BB_RW      (GEN_BB_READ | GEN_BB_WRITE)
 
+/*
+ * GEN_BB_NODMA -- Data is read/written by CPU only (no DMA), so no cache
+ * flushing and invalidating is required. Not passing this for GEN_BB_WRITE
+ * transfers done by the CPU (not DMA) may result in invalid data as the data
+ * written into the cache is lost by invalidating the dcache after the transfer
+ * (unless a writethrough cache is used).
+ */
+#define GEN_BB_NODMA   (1 << 2)
+
 struct bounce_buffer {
        /* Copy of data parameter passed to start() */
        void *user_buffer;
-- 
2.12.2.windows.2

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to