This patch should allow a CPU to register it's own cache ops. This shall allow multiple CPUs with different cache handlings to be supported.
Signed-off-by: Marek Vasut <marek.va...@gmail.com> Cc: Albert ARIBAUD <albert.u.b...@aribaud.net> Cc: Wolfgang Denk <w...@denx.de> --- arch/arm/include/asm/cache.h | 22 ++++++++ arch/arm/include/asm/global_data.h | 1 + arch/arm/lib/cache.c | 99 ++++++++++++++++++++++++++--------- 3 files changed, 96 insertions(+), 26 deletions(-) diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h index eef6a5a..8e1fa6c 100644 --- a/arch/arm/include/asm/cache.h +++ b/arch/arm/include/asm/cache.h @@ -53,4 +53,26 @@ void l2_cache_disable(void); #define ARCH_DMA_MINALIGN 64 #endif +enum cache_data_op { + CACHE_FLUSH, + CACHE_INVAL +}; + +enum cache_mgmt_op { + CACHE_ENABLE, + CACHE_DISABLE +}; + +struct cache_ops { + uint32_t cache_line_size; + void (*dcache_range_op)(enum cache_data_op op, u32 start, u32 end); + void (*dcache_whole_op)(enum cache_data_op op); + void (*icache_range_op)(enum cache_data_op op, u32 start, u32 end); + void (*icache_whole_op)(enum cache_data_op op); + void (*icache_ops)(enum cache_mgmt_op op); + void (*dcache_ops)(enum cache_mgmt_op op); +}; + +void cpu_register_cache_ops(struct cache_ops *ops); + #endif /* _ASM_CACHE_H */ diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index c3ff789..e50f58f 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -38,6 +38,7 @@ typedef struct global_data { unsigned long flags; unsigned long baudrate; unsigned long have_console; /* serial_init() was called */ + struct cache_ops *cache_ops; /* cache operations */ #ifdef CONFIG_PRE_CONSOLE_BUFFER unsigned long precon_buf_idx; /* Pre-Console buffer index */ #endif diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c index b545fb7..e8d5884 100644 --- a/arch/arm/lib/cache.c +++ b/arch/arm/lib/cache.c @@ -25,43 +25,90 @@ #include <common.h> -void __flush_cache(unsigned long start, unsigned long size) -{ -#if defined(CONFIG_OMAP2420) || defined(CONFIG_ARM1136) - void arm1136_cache_flush(void); +DECLARE_GLOBAL_DATA_PTR; - arm1136_cache_flush(); -#endif -#ifdef CONFIG_ARM926EJS - /* test and clean, page 2-23 of arm926ejs manual */ - asm("0: mrc p15, 0, r15, c7, c10, 3\n\t" "bne 0b\n" : : : "memory"); - /* disable write buffer as well (page 2-22) */ - asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); +/* Some broken stuff which will need sorting later. */ +#if defined(CONFIG_OMAP2420) || defined(CONFIG_ARM1136) || \ + defined(CONFIG_ARM926EJS) +#define CONFIG_CACHE_COMPAT #endif - return; + +/* + * Generic implementation of "enable_caches()" API call. + * + * This call enable both I-cache and D-cache. + */ +void enable_caches(void) +{ + struct cache_ops *ops = gd->cache_ops; + + if (!ops) { + puts("WARNING: Caches not enabled\n"); + return; + } + + ops->icache_ops(CACHE_ENABLE); + ops->dcache_ops(CACHE_ENABLE); } -void flush_cache(unsigned long start, unsigned long size) - __attribute__((weak, alias("__flush_cache"))); /* - * Default implementation: - * do a range flush for the entire range + * Generic implementation of "flush_dcache_all" API call. + * + * This flushes whole D-cache. */ -void __flush_dcache_all(void) +void flush_dcache_all(void) { - flush_cache(0, ~0); + struct cache_ops *ops = gd->cache_ops; + +#ifdef CONFIG_CACHE_COMPAT + cache_flush_compat(); +#endif + + if (!ops) + return; + + ops->dcache_whole_op(CACHE_FLUSH); } -void flush_dcache_all(void) - __attribute__((weak, alias("__flush_dcache_all"))); +/* + * Generic implementation of "flush_dcache_range" API call. + * + * This flushes line in D-cache. + */ +void flush_dcache_range(unsigned long start, unsigned long stop) +{ + struct cache_ops *ops = gd->cache_ops; + uint32_t cache_line_mask; + +#ifdef CONFIG_CACHE_COMPAT + cache_flush_compat(); +#endif + + if (!ops) + return; + + cache_line_mask = ops->cache_line_size - 1; + + if (start & cache_line_mask) + debug("CACHE: Unaligned start of flushed area\n"); + + if (stop & cache_line_mask) + debug("CACHE: Unaligned end of flushed area\n"); + + ops->dcache_range_op(CACHE_FLUSH, start, stop); +} /* - * Default implementation of enable_caches() - * Real implementation should be in platform code + * Generic implementation of "flush_cache" API call. + * + * This flushes line in D-cache. */ -void __enable_caches(void) +void flush_cache(unsigned long start, unsigned long stop) { - puts("WARNING: Caches not enabled\n"); + flush_dcache_range(start, stop); +} + +void cpu_register_cache_ops(struct cache_ops *ops) +{ + gd->cache_ops = ops; } -void enable_caches(void) - __attribute__((weak, alias("__enable_caches"))); -- 1.7.6.3 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot