summaryrefslogtreecommitdiff
path: root/common/bouncebuf.c
diff options
context:
space:
mode:
authorStefano Babic <sbabic@denx.de>2012-12-08 12:02:45 +0100
committerStefano Babic <sbabic@denx.de>2012-12-08 12:02:45 +0100
commit05a860c228fe6c8f2e7aced8cc8ef88bc1038363 (patch)
tree764536da9202b9de387a0d957829f64dfba818b7 /common/bouncebuf.c
parent393ff47ba3123208f7c4f08d63f114300a41d0c4 (diff)
parentfd4d564b3c80b111f18c93adb14233a6a7ddb0e9 (diff)
downloadu-boot-imx-05a860c228fe6c8f2e7aced8cc8ef88bc1038363.zip
u-boot-imx-05a860c228fe6c8f2e7aced8cc8ef88bc1038363.tar.gz
u-boot-imx-05a860c228fe6c8f2e7aced8cc8ef88bc1038363.tar.bz2
Merge branch 'master' of git://git.denx.de/u-boot into master
Conflicts: drivers/power/power_fsl.c include/configs/mx35pdk.h include/configs/mx53loco.h include/configs/woodburn_common.h board/woodburn/woodburn.c These boards still use the old old PMIC framework, so they do not merge properly after the power framework was merged into mainline. Fix all conflicts and update woodburn to use Power Framework. Signed-off-by: Stefano Babic <sbabic@denx.de>
Diffstat (limited to 'common/bouncebuf.c')
-rw-r--r--common/bouncebuf.c75
1 files changed, 41 insertions, 34 deletions
diff --git a/common/bouncebuf.c b/common/bouncebuf.c
index 4f827f8..1df12cd 100644
--- a/common/bouncebuf.c
+++ b/common/bouncebuf.c
@@ -27,21 +27,19 @@
#include <errno.h>
#include <bouncebuf.h>
-static int addr_aligned(void *data, size_t len)
+static int addr_aligned(struct bounce_buffer *state)
{
const ulong align_mask = ARCH_DMA_MINALIGN - 1;
/* Check if start is aligned */
- if ((ulong)data & align_mask) {
- debug("Unaligned start address %p\n", data);
+ if ((ulong)state->user_buffer & align_mask) {
+ debug("Unaligned buffer address %p\n", state->user_buffer);
return 0;
}
- data += len;
-
- /* Check if end is aligned */
- if ((ulong)data & align_mask) {
- debug("Unaligned end address %p\n", data);
+ /* Check if length is aligned */
+ if (state->len != state->len_aligned) {
+ debug("Unaligned buffer length %d\n", state->len);
return 0;
}
@@ -49,44 +47,53 @@ static int addr_aligned(void *data, size_t len)
return 1;
}
-int bounce_buffer_start(void **data, size_t len, void **backup, uint8_t flags)
+int bounce_buffer_start(struct bounce_buffer *state, void *data,
+ size_t len, unsigned int flags)
{
- void *tmp;
- size_t alen;
-
- if (addr_aligned(*data, len)) {
- *backup = NULL;
- return 0;
+ state->user_buffer = data;
+ state->bounce_buffer = data;
+ state->len = len;
+ state->len_aligned = roundup(len, ARCH_DMA_MINALIGN);
+ state->flags = flags;
+
+ if (!addr_aligned(state)) {
+ state->bounce_buffer = memalign(ARCH_DMA_MINALIGN,
+ state->len_aligned);
+ if (!state->bounce_buffer)
+ return -ENOMEM;
+
+ if (state->flags & GEN_BB_READ)
+ memcpy(state->bounce_buffer, state->user_buffer,
+ state->len);
}
- alen = roundup(len, ARCH_DMA_MINALIGN);
- tmp = memalign(ARCH_DMA_MINALIGN, alen);
-
- if (!tmp)
- return -ENOMEM;
-
- if (flags & GEN_BB_READ)
- memcpy(tmp, *data, len);
-
- *backup = *data;
- *data = tmp;
+ /*
+ * 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);
return 0;
}
-int bounce_buffer_stop(void **data, size_t len, void **backup, uint8_t flags)
+int bounce_buffer_stop(struct bounce_buffer *state)
{
- void *tmp = *data;
+ if (state->flags & 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) +
+ state->len_aligned);
+ }
- /* The buffer was already aligned, since "backup" is NULL. */
- if (!*backup)
+ if (state->bounce_buffer == state->user_buffer)
return 0;
- if (flags & GEN_BB_WRITE)
- memcpy(*backup, *data, len);
+ if (state->flags & GEN_BB_WRITE)
+ memcpy(state->user_buffer, state->bounce_buffer, state->len);
- *data = *backup;
- free(tmp);
+ free(state->bounce_buffer);
return 0;
}