diff options
Diffstat (limited to 'include/common.h')
| -rw-r--r-- | include/common.h | 58 | 
1 files changed, 58 insertions, 0 deletions
| diff --git a/include/common.h b/include/common.h index a1683a20a..13575272b 100644 --- a/include/common.h +++ b/include/common.h @@ -843,6 +843,64 @@ int cpu_release(int nr, int argc, char * const argv[]);  #include <asm/cache.h>  #endif +/* + * The ALLOC_CACHE_ALIGN_BUFFER macro is used to allocate a buffer on the + * stack that meets the minimum architecture alignment requirements for DMA. + * Such a buffer is useful for DMA operations where flushing and invalidating + * the cache before and after a read and/or write operation is required for + * correct operations. + * + * When called the macro creates an array on the stack that is sized such + * that: + * + * 1) The beginning of the array can be advanced enough to be aligned. + * + * 2) The size of the aligned portion of the array is a multiple of the minimum + *    architecture alignment required for DMA. + * + * 3) The aligned portion contains enough space for the original number of + *    elements requested. + * + * The macro then creates a pointer to the aligned portion of this array and + * assigns to the pointer the address of the first element in the aligned + * portion of the array. + * + * Calling the macro as: + * + *     ALLOC_CACHE_ALIGN_BUFFER(uint32_t, buffer, 1024); + * + * Will result in something similar to saying: + * + *     uint32_t    buffer[1024]; + * + * The following differences exist: + * + * 1) The resulting buffer is guaranteed to be aligned to the value of + *    ARCH_DMA_MINALIGN. + * + * 2) The buffer variable created by the macro is a pointer to the specified + *    type, and NOT an array of the specified type.  This can be very important + *    if you want the address of the buffer, which you probably do, to pass it + *    to the DMA hardware.  The value of &buffer is different in the two cases. + *    In the macro case it will be the address of the pointer, not the address + *    of the space reserved for the buffer.  However, in the second case it + *    would be the address of the buffer.  So if you are replacing hard coded + *    stack buffers with this macro you need to make sure you remove the & from + *    the locations where you are taking the address of the buffer. + * + * Note that the size parameter is the number of array elements to allocate, + * not the number of bytes. + * + * This macro can not be used outside of function scope, or for the creation + * of a function scoped static buffer.  It can not be used to create a cache + * line aligned global buffer. + */ +#define ALLOC_CACHE_ALIGN_BUFFER(type, name, size)			\ +	char __##name[ROUND(size * sizeof(type), ARCH_DMA_MINALIGN) +	\ +		      ARCH_DMA_MINALIGN - 1];				\ +									\ +	type *name = (type *) ALIGN((uintptr_t)__##name, ARCH_DMA_MINALIGN) +  /* Pull in stuff for the build system */  #ifdef DO_DEPS_ONLY  # include <environment.h> |