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