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