From 57d71e4267ecf66c84173f8ff3606091187b93b1 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Thu, 8 Nov 2007 05:17:20 +0000 Subject: Add some CACHEALIGN_* macros and a helper function to assist in aligning data and buffers on PortalPlayer processors to cache line boundaries. They're noops when PROC_NEED_CACHEALIGN isn't defined. Go safe and increase the value to 32 since I'm not sure yet if 16 is sufficient - changing that is a one-liner. Add helper to plugin API which will be needed shortly. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15523 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugin.c | 4 +++ apps/plugin.h | 15 ++++++++++- firmware/drivers/lcd-16bit.c | 3 ++- firmware/export/general.h | 2 ++ firmware/export/system.h | 32 +++++++++++++++++++++++ firmware/general.c | 24 +++++++++++++++++ firmware/target/arm/sandisk/sansa-e200/lcd-e200.c | 4 +-- firmware/target/arm/system-target.h | 8 +++++- 8 files changed, 87 insertions(+), 5 deletions(-) diff --git a/apps/plugin.c b/apps/plugin.c index ff23a55537..a80e9dd86d 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -518,6 +518,10 @@ static const struct plugin_api rockbox_api = { #endif thread_wait, + +#ifdef PROC_NEEDS_CACHEALIGN + align_buffer, +#endif }; int plugin_load(const char* plugin, void* parameter) diff --git a/apps/plugin.h b/apps/plugin.h index 300cad0781..f56590c29e 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -37,6 +37,7 @@ #include "config.h" #include "system.h" #include "dir.h" +#include "general.h" #include "kernel.h" #include "thread.h" #include "button.h" @@ -112,7 +113,7 @@ #define PLUGIN_MAGIC 0x526F634B /* RocK */ /* increase this every time the api struct changes */ -#define PLUGIN_API_VERSION 88 +#define PLUGIN_API_VERSION 89 /* update this to latest version if a change to the api struct breaks backwards compatibility (and please take the opportunity to sort in any @@ -640,6 +641,10 @@ struct plugin_api { #endif void (*thread_wait)(struct thread_entry *thread); + +#ifdef PROC_NEEDS_CACHEALIGN + size_t (*align_buffer)(void **start, size_t size, size_t align); +#endif }; /* plugin header */ @@ -742,4 +747,12 @@ enum plugin_status plugin_start(struct plugin_api* rockbox, void* parameter) #endif /* CACHE_FUNCTION_WRAPPERS */ +#ifndef ALIGN_BUFFER_WRAPPER +#define ALIGN_BUFFER_WRAPPER(api) \ + size_t align_buffer(void **start, size_t size, size_t align) \ + { \ + return (api)->align_buffer(start, size, align); \ + } +#endif /* ALIGN_BUFFER_WRAPPER */ + #endif diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index 2c36ab993a..f16503e0c6 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c @@ -42,7 +42,8 @@ enum fill_opt { }; /*** globals ***/ -fb_data lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] IRAM_LCDFRAMEBUFFER __attribute__ ((aligned (16))); +fb_data lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] + IRAM_LCDFRAMEBUFFER CACHEALIGN_AT_LEAST_ATTR(16); static fb_data* lcd_backdrop = NULL; diff --git a/firmware/export/general.h b/firmware/export/general.h index 427e2773b8..f4ea9e206a 100644 --- a/firmware/export/general.h +++ b/firmware/export/general.h @@ -21,6 +21,7 @@ #define GENERAL_H #include +#include /* round a signed/unsigned 32bit value to the closest of a list of values */ /* returns the index of the closest value */ @@ -34,5 +35,6 @@ int make_list_from_caps32(unsigned long src_mask, unsigned long caps_mask, unsigned long *caps_list); +size_t align_buffer(void **start, size_t size, size_t align); #endif /* GENERAL_H */ diff --git a/firmware/export/system.h b/firmware/export/system.h index dc10c4545f..cba4b81631 100644 --- a/firmware/export/system.h +++ b/firmware/export/system.h @@ -229,4 +229,36 @@ static inline uint32_t swap_odd_even32(uint32_t value) #define flush_icache() #endif +#ifdef PROC_NEEDS_CACHEALIGN +/* Cache alignment attributes and sizes are enabled */ + +/* 2^CACHEALIGN_BITS = the byte size */ +#define CACHEALIGN_SIZE (1u << CACHEALIGN_BITS) + +#define CACHEALIGN_ATTR __attribute__((aligned(CACHEALIGN_SIZE))) +/* Aligns x up to a CACHEALIGN_SIZE boundary */ +#define CACHEALIGN_UP(x) \ + ((typeof (x))ALIGN_UP_P2((uintptr_t)(x), CACHEALIGN_BITS)) +/* Aligns x down to a CACHEALIGN_SIZE boundary */ +#define CACHEALIGN_DOWN(x) \ + ((typeof (x))ALIGN_DOWN_P2((uintptr_t)(x), CACHEALIGN_BITS)) +/* Aligns at least to the greater of size x or CACHEALIGN_SIZE */ +#define CACHEALIGN_AT_LEAST_ATTR(x) __attribute__((aligned(CACHEALIGN_UP(x)))) +/* Aligns a buffer pointer and size to proper boundaries */ +#define CACHEALIGN_BUFFER(start, size) \ + ({ align_buffer((start), (size), CACHEALIGN_SIZE); }) + +#else /* ndef PROC_NEEDS_CACHEALIGN */ + +/* Cache alignment attributes and sizes are not enabled */ +#define CACHEALIGN_ATTR +#define CACHEALIGN_AT_LEAST_ATTR(x) __attribute__((aligned(x))) +#define CACHEALIGN_UP(x) (x) +#define CACHEALIGN_DOWN(x) (x) +/* Make no adjustments */ +#define CACHEALIGN_BUFFER(start, size) \ + ({ (void)(start); (size); }) + +#endif /* PROC_NEEDS_CACHEALIGN */ + #endif /* __SYSTEM_H__ */ diff --git a/firmware/general.c b/firmware/general.c index 7f4348046c..cc3710c8f3 100644 --- a/firmware/general.c +++ b/firmware/general.c @@ -17,6 +17,7 @@ * ****************************************************************************/ #include +#include "system.h" #include "config.h" #include "general.h" @@ -75,3 +76,26 @@ int make_list_from_caps32(unsigned long src_mask, return count; } /* make_list_from_caps32 */ + +/* Only needed for cache aligning atm */ +#ifdef PROC_NEEDS_CACHEALIGN +/* Align a buffer and size to a size boundary while remaining within + * the original boundaries */ +size_t align_buffer(void **start, size_t size, size_t align) +{ + void *newstart = *start; + void *newend = newstart + size; + + /* Align the end down and the start up */ + newend = (void *)ALIGN_DOWN((intptr_t)newend, align); + newstart = (void *)ALIGN_UP((intptr_t)newstart, align); + + /* Hmmm - too small for this */ + if (newend <= newstart) + return 0; + + /* Return adjusted pointer and size */ + *start = newstart; + return newend - newstart; +} +#endif /* PROC_NEEDS_CACHEALIGN */ diff --git a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c index aa969d2bff..e1212c9512 100644 --- a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c +++ b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c @@ -109,9 +109,9 @@ static unsigned short r_drv_output_control = R_DRV_OUTPUT_CONTROL_NORMAL; /* We don't know how to receive a DMA finished signal from the LCD controller * To avoid problems with flickering, we double-buffer the framebuffer and turn * off DMA while updates are taking place - * Same alignment as in lcd-16bit.c and cache interference free */ + * At least the alignment as in lcd-16bit.c and cache interference free */ static fb_data lcd_driver_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] - __attribute__((aligned(16))); + CACHEALIGN_AT_LEAST_ATTR(16); #ifdef BOOTLOADER static void lcd_init_gpio(void) diff --git a/firmware/target/arm/system-target.h b/firmware/target/arm/system-target.h index 6e433be9d5..e9419b3f86 100644 --- a/firmware/target/arm/system-target.h +++ b/firmware/target/arm/system-target.h @@ -94,11 +94,17 @@ static inline unsigned int processor_id(void) #define UNCACHED_ADDR(a) (a) #else #define UNCACHED_ADDR(a) \ - ((typeof (a))((uintptr_t)(a) + 0x10000000)) + ((typeof (a))((uintptr_t)(a) | 0x10000000)) #endif #ifdef CPU_PP502x +/* Certain data needs to be out of the way of cache line interference + * such as data for COP use or for use with UNCACHED_ADDR */ +#define PROC_NEEDS_CACHEALIGN +#define CACHEALIGN_BITS (5) /* 2^5 = 32 bytes */ + +/** cache functions **/ #ifndef BOOTLOADER #define CACHE_FUNCTIONS_AS_CALL -- cgit v1.2.3