1 /* 2 * (C) Copyright 2011 3 * Ilya Yanok, EmCraft Systems 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc. 21 */ 22 #include <linux/types.h> 23 #include <common.h> 24 25 #ifndef CONFIG_SYS_DCACHE_OFF 26 27 #ifndef CONFIG_SYS_CACHELINE_SIZE 28 #define CONFIG_SYS_CACHELINE_SIZE 32 29 #endif 30 31 void invalidate_dcache_all(void) 32 { 33 asm volatile("mcr p15, 0, %0, c7, c6, 0\n" : : "r"(0)); 34 } 35 36 void flush_dcache_all(void) 37 { 38 asm volatile( 39 "0:" 40 "mrc p15, 0, r15, c7, c14, 3\n" 41 "bne 0b\n" 42 "mcr p15, 0, %0, c7, c10, 4\n" 43 : : "r"(0) : "memory" 44 ); 45 } 46 47 static int check_cache_range(unsigned long start, unsigned long stop) 48 { 49 int ok = 1; 50 51 if (start & (CONFIG_SYS_CACHELINE_SIZE - 1)) 52 ok = 0; 53 54 if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1)) 55 ok = 0; 56 57 if (!ok) 58 debug("CACHE: Misaligned operation at range [%08lx, %08lx]\n", 59 start, stop); 60 61 return ok; 62 } 63 64 void invalidate_dcache_range(unsigned long start, unsigned long stop) 65 { 66 if (!check_cache_range(start, stop)) 67 return; 68 69 while (start < stop) { 70 asm volatile("mcr p15, 0, %0, c7, c6, 1\n" : : "r"(start)); 71 start += CONFIG_SYS_CACHELINE_SIZE; 72 } 73 } 74 75 void flush_dcache_range(unsigned long start, unsigned long stop) 76 { 77 if (!check_cache_range(start, stop)) 78 return; 79 80 while (start < stop) { 81 asm volatile("mcr p15, 0, %0, c7, c14, 1\n" : : "r"(start)); 82 start += CONFIG_SYS_CACHELINE_SIZE; 83 } 84 85 asm volatile("mcr p15, 0, %0, c7, c10, 4\n" : : "r"(0)); 86 } 87 88 void flush_cache(unsigned long start, unsigned long size) 89 { 90 flush_dcache_range(start, start + size); 91 } 92 #else /* #ifndef CONFIG_SYS_DCACHE_OFF */ 93 void invalidate_dcache_all(void) 94 { 95 } 96 97 void flush_dcache_all(void) 98 { 99 } 100 101 void invalidate_dcache_range(unsigned long start, unsigned long stop) 102 { 103 } 104 105 void flush_dcache_range(unsigned long start, unsigned long stop) 106 { 107 } 108 109 void flush_cache(unsigned long start, unsigned long size) 110 { 111 } 112 #endif /* #ifndef CONFIG_SYS_DCACHE_OFF */ 113 114 /* 115 * Stub implementations for l2 cache operations 116 */ 117 void __l2_cache_disable(void) {} 118 119 void l2_cache_disable(void) 120 __attribute__((weak, alias("__l2_cache_disable"))); 121