diff options
author | Anton staaf <robotboy@chromium.org> | 2011-10-12 13:55:59 +0000 |
---|---|---|
committer | Wolfgang Denk <wd@denx.de> | 2011-10-25 09:23:10 +0200 |
commit | 46a6d51c827a12723e7191128fb7aab42c8f5c09 (patch) | |
tree | dd006809b5a777f6bd463c2d8f3a7bad0426fb68 | |
parent | d47031e6879d6408b08889583600edd6aff378c8 (diff) | |
download | u-boot-imx-46a6d51c827a12723e7191128fb7aab42c8f5c09.zip u-boot-imx-46a6d51c827a12723e7191128fb7aab42c8f5c09.tar.gz u-boot-imx-46a6d51c827a12723e7191128fb7aab42c8f5c09.tar.bz2 |
cache: add ALLOC_CACHE_ALIGN_BUFFER macro
This macro is used to allocate cache line size aligned stack
buffers for use with DMA hardware.
Signed-off-by: Anton Staaf <robotboy@chromium.org>
Cc: Lukasz Majewski <l.majewski@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Aneesh V <aneesh@ti.com>
Cc: Albert ARIBAUD <albert.u.boot@aribaud.net>
Cc: Wolfgang Denk <wd@denx.de>
-rw-r--r-- | doc/README.arm-caches | 2 | ||||
-rw-r--r-- | include/common.h | 58 |
2 files changed, 60 insertions, 0 deletions
diff --git a/doc/README.arm-caches b/doc/README.arm-caches index cd2b458..f6a52e3 100644 --- a/doc/README.arm-caches +++ b/doc/README.arm-caches @@ -40,6 +40,8 @@ Buffer Requirements: - If the buffer is not cache-line aligned invalidation will be restricted to the aligned part. That is, one cache-line at the respective boundary may be left out while doing invalidation. +- A suitable buffer can be alloced on the stack using the + ALLOC_CACHE_ALIGN_BUFFER macro. Cleanup Before Linux: - cleanup_before_linux() should flush the D-cache, invalidate I-cache, and diff --git a/include/common.h b/include/common.h index a1683a2..1357527 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> |