diff options
Diffstat (limited to 'arch/arm/cpu/arm926ejs/cache.c')
| -rw-r--r-- | arch/arm/cpu/arm926ejs/cache.c | 66 | 
1 files changed, 54 insertions, 12 deletions
| diff --git a/arch/arm/cpu/arm926ejs/cache.c b/arch/arm/cpu/arm926ejs/cache.c index 504f60468..5b23e3a71 100644 --- a/arch/arm/cpu/arm926ejs/cache.c +++ b/arch/arm/cpu/arm926ejs/cache.c @@ -23,29 +23,71 @@  #include <common.h>  #ifndef CONFIG_SYS_DCACHE_OFF -static inline void dcache_noop(void) + +#ifndef CONFIG_SYS_CACHELINE_SIZE +#define CONFIG_SYS_CACHELINE_SIZE	32 +#endif + +void invalidate_dcache_all(void)  { -	if (dcache_status()) { -		puts("WARNING: cache operations are not implemented!\n" -		     "WARNING: disabling D-Cache now, you can re-enable it" -		     "later with 'dcache on' command\n"); -		dcache_disable(); -	} +	asm volatile("mcr p15, 0, %0, c7, c6, 0\n"::"r"(0));  } -void invalidate_dcache_all(void) +void flush_dcache_all(void)  { -	dcache_noop(); +	asm volatile( +		"0:" +		"mrc p15, 0, r15, c7, c14, 3\n" +		"bne 0b\n" +		"mcr p15, 0, %0, c7, c10, 4\n" +		::"r"(0):"memory" +	); +} + +static int check_cache_range(unsigned long start, unsigned long stop) +{ +	int ok = 1; + +	if (start & (CONFIG_SYS_CACHELINE_SIZE - 1)) +		ok = 0; + +	if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1)) +		ok = 0; + +	if (!ok) +		printf("CACHE: Misaligned operation at range [%08lx, %08lx]\n", +			start, stop); + +	return ok;  }  void invalidate_dcache_range(unsigned long start, unsigned long stop)  { -	dcache_noop(); +	if (!check_cache_range(start, stop)) +		return; + +	while (start < stop) { +		asm volatile("mcr p15, 0, %0, c7, c6, 1\n"::"r"(start)); +		start += CONFIG_SYS_CACHELINE_SIZE; +	}  }  void flush_dcache_range(unsigned long start, unsigned long stop)  { -	dcache_noop(); +	if (!check_cache_range(start, stop)) +		return; + +	while (start < stop) { +		asm volatile("mcr p15, 0, %0, c7, c14, 1\n"::"r"(start)); +		start += CONFIG_SYS_CACHELINE_SIZE; +	} + +	asm("mcr p15, 0, %0, c7, c10, 4\n"::"r"(0)); +} + +void flush_cache(unsigned long start, unsigned long size) +{ +	flush_dcache_range(start, start + size);  }  #else /* #ifndef CONFIG_SYS_DCACHE_OFF */  void invalidate_dcache_all(void) @@ -64,7 +106,7 @@ void flush_dcache_range(unsigned long start, unsigned long stop)  {  } -void  flush_cache(unsigned long start, unsigned long size) +void flush_cache(unsigned long start, unsigned long size)  {  }  #endif /* #ifndef CONFIG_SYS_DCACHE_OFF */ |