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 
__flush_dcache(unsigned long start,unsigned long end)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 
__flush_dcache_all(unsigned long start,unsigned long end)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 
__invalidate_dcache(unsigned long start,unsigned long end)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 
__flush_icache(unsigned long start,unsigned long end)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 
flush_dcache_all(void)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 
flush_dcache_range(unsigned long start,unsigned long end)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 
flush_cache(unsigned long start,unsigned long size)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 
invalidate_dcache_range(unsigned long start,unsigned long end)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 
dcache_status(void)115 int dcache_status(void)
116 {
117 	return 1;
118 }
119 
dcache_enable(void)120 void dcache_enable(void)
121 {
122 	flush_dcache_all();
123 }
124 
dcache_disable(void)125 void dcache_disable(void)
126 {
127 	flush_dcache_all();
128 }
129