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