Blame view
common/bouncebuf.c
1.91 KB
83d290c56
|
1 |
// SPDX-License-Identifier: GPL-2.0+ |
b660df3c9
|
2 3 4 5 |
/* * Generic bounce buffer implementation * * Copyright (C) 2012 Marek Vasut <marex@denx.de> |
b660df3c9
|
6 7 8 |
*/ #include <common.h> |
1eb69ae49
|
9 |
#include <cpu_func.h> |
b660df3c9
|
10 11 12 |
#include <malloc.h> #include <errno.h> #include <bouncebuf.h> |
84d35b286
|
13 |
static int addr_aligned(struct bounce_buffer *state) |
b660df3c9
|
14 15 16 17 |
{ const ulong align_mask = ARCH_DMA_MINALIGN - 1; /* Check if start is aligned */ |
84d35b286
|
18 19 20 |
if ((ulong)state->user_buffer & align_mask) { debug("Unaligned buffer address %p ", state->user_buffer); |
b660df3c9
|
21 22 |
return 0; } |
84d35b286
|
23 24 |
/* Check if length is aligned */ if (state->len != state->len_aligned) { |
5d69a5d17
|
25 26 |
debug("Unaligned buffer length %zu ", state->len); |
b660df3c9
|
27 28 29 30 31 32 |
return 0; } /* Aligned */ return 1; } |
84d35b286
|
33 34 |
int bounce_buffer_start(struct bounce_buffer *state, void *data, size_t len, unsigned int flags) |
b660df3c9
|
35 |
{ |
84d35b286
|
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
|
51 |
} |
84d35b286
|
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
|
59 60 61 |
return 0; } |
84d35b286
|
62 |
int bounce_buffer_stop(struct bounce_buffer *state) |
b660df3c9
|
63 |
{ |
84d35b286
|
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
|
70 |
|
84d35b286
|
71 |
if (state->bounce_buffer == state->user_buffer) |
b660df3c9
|
72 |
return 0; |
84d35b286
|
73 74 |
if (state->flags & GEN_BB_WRITE) memcpy(state->user_buffer, state->bounce_buffer, state->len); |
b660df3c9
|
75 |
|
84d35b286
|
76 |
free(state->bounce_buffer); |
b660df3c9
|
77 78 79 |
return 0; } |