1 /* 2 * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw> 3 * Copyright (C) 2009, Wind River Systems Inc 4 * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <common.h> 10 #include <asm/cache.h> 11 12 DECLARE_GLOBAL_DATA_PTR; 13 14 static void __flush_dcache(unsigned long start, unsigned long end) 15 { 16 unsigned long addr; 17 18 start &= ~(gd->arch.dcache_line_size - 1); 19 end += (gd->arch.dcache_line_size - 1); 20 end &= ~(gd->arch.dcache_line_size - 1); 21 22 for (addr = start; addr < end; addr += gd->arch.dcache_line_size) { 23 __asm__ __volatile__ (" flushda 0(%0)\n" 24 : /* Outputs */ 25 : /* Inputs */ "r"(addr) 26 /* : No clobber */); 27 } 28 } 29 30 static void __flush_dcache_all(unsigned long start, unsigned long end) 31 { 32 unsigned long addr; 33 34 start &= ~(gd->arch.dcache_line_size - 1); 35 end += (gd->arch.dcache_line_size - 1); 36 end &= ~(gd->arch.dcache_line_size - 1); 37 38 if (end > start + gd->arch.dcache_size) 39 end = start + gd->arch.dcache_size; 40 41 for (addr = start; addr < end; addr += gd->arch.dcache_line_size) { 42 __asm__ __volatile__ (" flushd 0(%0)\n" 43 : /* Outputs */ 44 : /* Inputs */ "r"(addr) 45 /* : No clobber */); 46 } 47 } 48 49 static void __invalidate_dcache(unsigned long start, unsigned long end) 50 { 51 unsigned long addr; 52 53 start &= ~(gd->arch.dcache_line_size - 1); 54 end += (gd->arch.dcache_line_size - 1); 55 end &= ~(gd->arch.dcache_line_size - 1); 56 57 for (addr = start; addr < end; addr += gd->arch.dcache_line_size) { 58 __asm__ __volatile__ (" initda 0(%0)\n" 59 : /* Outputs */ 60 : /* Inputs */ "r"(addr) 61 /* : No clobber */); 62 } 63 } 64 65 static void __flush_icache(unsigned long start, unsigned long end) 66 { 67 unsigned long addr; 68 69 start &= ~(gd->arch.icache_line_size - 1); 70 end += (gd->arch.icache_line_size - 1); 71 end &= ~(gd->arch.icache_line_size - 1); 72 73 if (end > start + gd->arch.icache_size) 74 end = start + gd->arch.icache_size; 75 76 for (addr = start; addr < end; addr += gd->arch.icache_line_size) { 77 __asm__ __volatile__ (" flushi %0\n" 78 : /* Outputs */ 79 : /* Inputs */ "r"(addr) 80 /* : No clobber */); 81 } 82 __asm__ __volatile(" flushp\n"); 83 } 84 85 void flush_dcache_all(void) 86 { 87 __flush_dcache_all(0, gd->arch.dcache_size); 88 __flush_icache(0, gd->arch.icache_size); 89 } 90 91 void flush_dcache_range(unsigned long start, unsigned long end) 92 { 93 if (gd->arch.has_initda) 94 __flush_dcache(start, end); 95 else 96 __flush_dcache_all(start, end); 97 } 98 99 void flush_cache(unsigned long start, unsigned long size) 100 { 101 if (gd->arch.has_initda) 102 __flush_dcache(start, start + size); 103 else 104 __flush_dcache_all(start, start + size); 105 __flush_icache(start, start + size); 106 } 107 108 void invalidate_dcache_range(unsigned long start, unsigned long end) 109 { 110 if (gd->arch.has_initda) 111 __invalidate_dcache(start, end); 112 else 113 __flush_dcache_all(start, end); 114 } 115 116 int dcache_status(void) 117 { 118 return 1; 119 } 120 121 void dcache_enable(void) 122 { 123 flush_dcache_all(); 124 } 125 126 void dcache_disable(void) 127 { 128 flush_dcache_all(); 129 } 130