]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/arm926ejs/cache.c
Implement cache functions for ARM-926ejs
[karo-tx-uboot.git] / arch / arm / cpu / arm926ejs / cache.c
1 /*
2  * (C) Copyright 2011
3  * Ilya Yanok, EmCraft Systems
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc.
21  */
22 #include <linux/types.h>
23 #include <common.h>
24
25 #define DCACHE_SIZE                     0x4000    // 16KB Size of data cache in bytes
26 #define DCACHE_LINE_SIZE                32    // Size of a data cache line
27 #define DCACHE_WAYS                     64    // Associativity of the cache
28 /*
29  * This is the maximum size of an area which will be invalidated
30  * using the single invalidate entry instructions.  Anything larger
31  * than this, and we go for the whole cache.
32  *
33  * This value should be chosen such that we choose the cheapest
34  * alternative.
35  */
36 #define CACHE_DLIMIT                    16384
37
38 #ifndef CONFIG_SYS_DCACHE_OFF
39 void invalidate_dcache_all(void)
40 {
41         asm volatile (
42                 "mcr    p15, 0, %0, c7, c6, 0\n" /* invalidate d-cache */
43                 "mcr    p15, 0, %0, c7, c5, 0\n" /* invalidate I cache */
44                 "mcr    p15, 0, %0, c7, c10, 4\n" /* data write back */
45                 :
46                 : "r"(0)
47                 : "memory");
48 }
49
50 void invalidate_dcache_range(unsigned long start, unsigned long end)
51 {
52         asm volatile (
53 #ifndef CONFIG_SYS_ARM_CACHE_WRITETHROUGH
54                 "tst    %1, %4\n"
55                 "mcrne  p15, 0, %1, c7, c10, 1\n" /* clean D entry */
56                 "tst    %2, %4\n"
57                 "mcrne  p15, 0, %2, c7, c10, 1\n" /* clean D entry */
58 #endif
59                 "bic    %1, %1, %4\n"
60                 "add    %2, %2, %4\n"
61                 "bic    %2, %2, %4\n"
62                 "1:\n"
63                 "mcr    p15, 0, %1, c7, c6, 1\n" /* invalidate D cache entry */
64                 "add    %1, %1, %3\n"
65                 "cmp    %1, %2\n"
66                 "blo    1b\n"
67                 "mcr    p15, 0, %0, c7, c5, 0\n" /* invalidate I cache */
68                 "mcr    p15, 0, %0, c7, c10, 4\n" /* data write back */
69                 :
70                 : "r"(0), "r"(start), "r"(end),
71                   "I"(DCACHE_LINE_SIZE),
72                   "I"(DCACHE_LINE_SIZE - 1)
73                 : "memory"
74                 );
75
76 }
77
78 #ifndef CONFIG_SYS_ARM_CACHE_WRITETHROUGH
79 void flush_dcache_range(unsigned long start, unsigned long end)
80 {
81         if (end - start > CACHE_DLIMIT)
82                 flush_dcache_all();
83         else
84                 flush_cache(start & ~(SZ_4K - 1), ALIGN(end, SZ_4K));
85 }
86
87 void flush_cache(unsigned long start, unsigned long end)
88 {
89         asm volatile (
90                 "1:\n"
91                 "mcr    p15, 0, %1, c7, c14, 1\n" /* clean and invalidate D entry */
92                 "add    %1, %1, %3\n"
93                 "cmp    %1, %2\n"
94                 "blo    1b\n"
95                 "mcr    p15, 0, %0, c7, c5, 0\n" /* invalidate I cache */
96                 "mcr    p15, 0, %0, c7, c10, 4\n" /* data write back */
97                 :
98                 : "r"(0), "r"(start), "r"(end), "I"(DCACHE_LINE_SIZE)
99                 : "memory"
100                 );
101 }
102
103 void flush_dcache_all(void)
104 {
105         asm volatile (
106                 "1:\n"
107                 "mrc    p15, 0, r15, c7, c14, 3\n" /* test,clean,invalidate */
108                 "bne    1b\n"
109                 "mcr    p15, 0, %0, c7, c5, 0\n" /* invalidate I cache */
110                 "mcr    p15, 0, %0, c7, c10, 4\n" /* data write back */
111                 :
112                 : "r"(0)
113                 : "memory"
114                 );
115 }
116 #else
117 void flush_dcache_range(unsigned long start, unsigned long end)
118 {
119         invalidate_dcache_range(start, end);
120 }
121
122 void flush_cache(unsigned long start, unsigned long end)
123 {
124         invalidate_dcache_range(start, end);
125 }
126
127 void flush_dcache_all(void)
128 {
129         invalidate_dcache_all();
130 }
131 #endif /* CONFIG_SYS_ARM_CACHE_WRITETHROUGH */
132
133 #else /* #ifndef CONFIG_SYS_DCACHE_OFF */
134 void invalidate_dcache_all(void)
135 {
136 }
137
138 void flush_dcache_all(void)
139 {
140 }
141
142 void invalidate_dcache_range(unsigned long start, unsigned long stop)
143 {
144 }
145
146 void flush_dcache_range(unsigned long start, unsigned long stop)
147 {
148 }
149
150 void  flush_cache(unsigned long start, unsigned long size)
151 {
152 }
153 #endif /* #ifndef CONFIG_SYS_DCACHE_OFF */
154
155 /*
156  * Stub implementations for l2 cache operations
157  */
158 void __l2_cache_disable(void)
159 {
160 }
161 void l2_cache_disable(void)
162         __attribute__((weak, alias("__l2_cache_disable")));