blob: 9e3ab746b527d08085752a1222998400904a396e [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Patrick Georgiafd4c872020-05-05 23:43:18 +02002/*
Martin Roth0443ac22019-08-30 21:29:41 -06003 * Generic bounce buffer implementation
Lee Leahyeef40eb2017-03-23 10:54:57 -07004 */
5
Lee Leahy48dbc662017-05-08 16:56:03 -07006#ifndef __COMMONLIB_STORAGE_BOUNCEBUF_H__
7#define __COMMONLIB_STORAGE_BOUNCEBUF_H__
Lee Leahyeef40eb2017-03-23 10:54:57 -07008
9#include <stddef.h>
10#include <stdint.h>
11#include <stdlib.h>
12
13/*
14 * GEN_BB_READ -- Data are read from the buffer eg. by DMA hardware.
15 * The source buffer is copied into the bounce buffer (if unaligned, otherwise
16 * the source buffer is used directly) upon start() call, then the operation
17 * requiring the aligned transfer happens, then the bounce buffer is lost upon
18 * stop() call.
19 */
20#define GEN_BB_READ (1 << 0)
21/*
22 * GEN_BB_WRITE -- Data are written into the buffer eg. by DMA hardware.
23 * The source buffer starts in an undefined state upon start() call, then the
24 * operation requiring the aligned transfer happens, then the bounce buffer is
25 * copied into the destination buffer (if unaligned, otherwise destination
26 * buffer is used directly) upon stop() call.
27 */
28#define GEN_BB_WRITE (1 << 1)
29/*
30 * GEN_BB_RW -- Data are read and written into the buffer eg. by DMA hardware.
31 * The source buffer is copied into the bounce buffer (if unaligned, otherwise
32 * the source buffer is used directly) upon start() call, then the operation
33 * requiring the aligned transfer happens, then the bounce buffer is copied
34 * into the destination buffer (if unaligned, otherwise destination buffer is
35 * used directly) upon stop() call.
36 */
37#define GEN_BB_RW (GEN_BB_READ | GEN_BB_WRITE)
38
39struct bounce_buffer {
40 /* Copy of data parameter passed to start() */
41 void *user_buffer;
42 /*
43 * DMA-aligned buffer. This field is always set to the value that
44 * should be used for DMA; either equal to .user_buffer, or to a
45 * freshly allocated aligned buffer.
46 */
47 void *bounce_buffer;
48 /* Copy of len parameter passed to start() */
49 size_t len;
50 /* DMA-aligned buffer length */
51 size_t len_aligned;
52 /* Copy of flags parameter passed to start() */
53 unsigned int flags;
54};
55
56/**
57 * bounce_buffer_start() -- Start the bounce buffer session
58 * state: stores state passed between bounce_buffer_{start,stop}
59 * data: pointer to buffer to be aligned
60 * len: length of the buffer
61 * flags: flags describing the transaction, see above.
62 */
63int bounce_buffer_start(struct bounce_buffer *state, void *data,
64 size_t len, unsigned int flags);
65/**
66 * bounce_buffer_stop() -- Finish the bounce buffer session
67 * state: stores state passed between bounce_buffer_{start,stop}
68 */
69int bounce_buffer_stop(struct bounce_buffer *state);
70
71// TODO(hungte) Eliminate the alignment stuff below and replace them with a
72// better and centralized way to handler non-cache/aligned memory.
73// Helper macros for alignment.
74#define DMA_MINALIGN (64)
75#define ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1))
76#define ALLOC_CACHE_ALIGN_BUFFER(type, name, size) \
77 char __##name[ROUND(size * sizeof(type), DMA_MINALIGN) + \
78 DMA_MINALIGN - 1]; \
Felix Held8d2ec862019-06-20 14:26:09 +020079 type *name = (type *) ALIGN_UP((uintptr_t)__##name, DMA_MINALIGN)
Lee Leahyeef40eb2017-03-23 10:54:57 -070080#ifndef ARCH_DMA_MINALIGN
81#define ARCH_DMA_MINALIGN (DMA_MINALIGN)
82#endif
83
Lee Leahy48dbc662017-05-08 16:56:03 -070084#endif // __COMMONLIB_STORAGE_BOUNCEBUF_H__