Blame view
common/bouncebuf.c
1.89 KB
b660df3c9 COMMON: Implement... |
1 2 3 4 5 |
/* * Generic bounce buffer implementation * * Copyright (C) 2012 Marek Vasut <marex@denx.de> * |
1a4596601 Add GPL-2.0+ SPDX... |
6 |
* SPDX-License-Identifier: GPL-2.0+ |
b660df3c9 COMMON: Implement... |
7 8 9 10 11 12 |
*/ #include <common.h> #include <malloc.h> #include <errno.h> #include <bouncebuf.h> |
84d35b286 common: rework bo... |
13 |
static int addr_aligned(struct bounce_buffer *state) |
b660df3c9 COMMON: Implement... |
14 15 16 17 |
{ const ulong align_mask = ARCH_DMA_MINALIGN - 1; /* Check if start is aligned */ |
84d35b286 common: rework bo... |
18 19 20 |
if ((ulong)state->user_buffer & align_mask) { debug("Unaligned buffer address %p ", state->user_buffer); |
b660df3c9 COMMON: Implement... |
21 22 |
return 0; } |
84d35b286 common: rework bo... |
23 24 |
/* Check if length is aligned */ if (state->len != state->len_aligned) { |
5d69a5d17 Fix a few printf ... |
25 26 |
debug("Unaligned buffer length %zu ", state->len); |
b660df3c9 COMMON: Implement... |
27 28 29 30 31 32 |
return 0; } /* Aligned */ return 1; } |
84d35b286 common: rework bo... |
33 34 |
int bounce_buffer_start(struct bounce_buffer *state, void *data, size_t len, unsigned int flags) |
b660df3c9 COMMON: Implement... |
35 |
{ |
84d35b286 common: rework bo... |
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
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); |
b660df3c9 COMMON: Implement... |
51 |
} |
84d35b286 common: rework bo... |
52 53 54 55 56 57 58 |
/* * 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); |
b660df3c9 COMMON: Implement... |
59 60 61 |
return 0; } |
84d35b286 common: rework bo... |
62 |
int bounce_buffer_stop(struct bounce_buffer *state) |
b660df3c9 COMMON: Implement... |
63 |
{ |
84d35b286 common: rework bo... |
64 65 66 67 68 69 |
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); } |
b660df3c9 COMMON: Implement... |
70 |
|
84d35b286 common: rework bo... |
71 |
if (state->bounce_buffer == state->user_buffer) |
b660df3c9 COMMON: Implement... |
72 |
return 0; |
84d35b286 common: rework bo... |
73 74 |
if (state->flags & GEN_BB_WRITE) memcpy(state->user_buffer, state->bounce_buffer, state->len); |
b660df3c9 COMMON: Implement... |
75 |
|
84d35b286 common: rework bo... |
76 |
free(state->bounce_buffer); |
b660df3c9 COMMON: Implement... |
77 78 79 |
return 0; } |