adds ifxmips, uboot-ifxmips and removes etrax from 8.09 branch
[openwrt/svn-archive/archive.git] / package / uboot-ifxmips / files / cpu / mips / danube / cache.S
1 /*
2 * Cache-handling routined for MIPS 4K CPUs
3 *
4 * Copyright (c) 2003 Wolfgang Denk <wd@denx.de>
5 *
6 * See file CREDITS for list of people who contributed to this
7 * project.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 */
24
25
26 #include <config.h>
27 #include <version.h>
28 #include <asm/regdef.h>
29 #include <asm/mipsregs.h>
30 #include <asm/addrspace.h>
31 #include <asm/cacheops.h>
32 #if defined(CONFIG_IFX_MIPS)
33 # include "ifx_cache.S"
34 #endif
35
36 /* 16KB is the maximum size of instruction and data caches on
37 * MIPS 4K.
38 */
39 #define MIPS_MAX_CACHE_SIZE 0x4000
40
41
42 /*
43 * cacheop macro to automate cache operations
44 * first some helpers...
45 */
46 #define _mincache(size, maxsize) \
47 bltu size,maxsize,9f ; \
48 move size,maxsize ; \
49 9:
50
51 #define _align(minaddr, maxaddr, linesize) \
52 .set noat ; \
53 subu AT,linesize,1 ; \
54 not AT ; \
55 and minaddr,AT ; \
56 addu maxaddr,-1 ; \
57 and maxaddr,AT ; \
58 .set at
59
60 /* general operations */
61 #define doop1(op1) \
62 cache op1,0(a0)
63 #define doop2(op1, op2) \
64 cache op1,0(a0) ; \
65 nop ; \
66 cache op2,0(a0)
67
68 /* specials for cache initialisation */
69 #define doop1lw(op1) \
70 lw zero,0(a0)
71 #define doop1lw1(op1) \
72 cache op1,0(a0) ; \
73 lw zero,0(a0) ; \
74 cache op1,0(a0)
75 #define doop121(op1,op2) \
76 cache op1,0(a0) ; \
77 nop; \
78 cache op2,0(a0) ; \
79 nop; \
80 cache op1,0(a0)
81
82 #define _oploopn(minaddr, maxaddr, linesize, tag, ops) \
83 .set noreorder ; \
84 10: doop##tag##ops ; \
85 bne minaddr,maxaddr,10b ; \
86 add minaddr,linesize ; \
87 .set reorder
88
89 /* finally the cache operation macros */
90 #define vcacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \
91 blez n,11f ; \
92 addu n,kva ; \
93 _align(kva, n, cacheLineSize) ; \
94 _oploopn(kva, n, cacheLineSize, tag, ops) ; \
95 11:
96
97 #define icacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \
98 _mincache(n, cacheSize); \
99 blez n,11f ; \
100 addu n,kva ; \
101 _align(kva, n, cacheLineSize) ; \
102 _oploopn(kva, n, cacheLineSize, tag, ops) ; \
103 11:
104
105 #define vcacheop(kva, n, cacheSize, cacheLineSize, op) \
106 vcacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
107
108 #define icacheop(kva, n, cacheSize, cacheLineSize, op) \
109 icacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
110
111 /*******************************************************************************
112 *
113 * mips_cache_reset - low level initialisation of the primary caches
114 *
115 * This routine initialises the primary caches to ensure that they
116 * have good parity. It must be called by the ROM before any cached locations
117 * are used to prevent the possibility of data with bad parity being written to
118 * memory.
119 * To initialise the instruction cache it is essential that a source of data
120 * with good parity is available. This routine
121 * will initialise an area of memory starting at location zero to be used as
122 * a source of parity.
123 *
124 * RETURNS: N/A
125 *
126 */
127 .globl mips_cache_reset
128 .ent mips_cache_reset
129 mips_cache_reset:
130
131 li t2, CFG_ICACHE_SIZE
132 li t3, CFG_DCACHE_SIZE
133 li t4, CFG_CACHELINE_SIZE
134 move t5, t4
135
136
137 li v0, MIPS_MAX_CACHE_SIZE
138
139 /* Now clear that much memory starting from zero.
140 */
141
142 li a0, KSEG1
143 addu a1, a0, v0
144
145 2: sw zero, 0(a0)
146 sw zero, 4(a0)
147 sw zero, 8(a0)
148 sw zero, 12(a0)
149 sw zero, 16(a0)
150 sw zero, 20(a0)
151 sw zero, 24(a0)
152 sw zero, 28(a0)
153 addu a0, 32
154 bltu a0, a1, 2b
155
156 /* Set invalid tag.
157 */
158
159 mtc0 zero, CP0_TAGLO
160 #if defined(CONFIG_IFX_MIPS) && defined(IFX_CACHE_EXTRA_INVALID_TAG)
161 IFX_CACHE_EXTRA_INVALID_TAG
162 #endif
163
164 /*
165 * The caches are probably in an indeterminate state,
166 * so we force good parity into them by doing an
167 * invalidate, load/fill, invalidate for each line.
168 */
169
170 /* Assume bottom of RAM will generate good parity for the cache.
171 */
172
173 li a0, K0BASE
174 move a2, t2 # icacheSize
175 move a3, t4 # icacheLineSize
176 move a1, a2
177 icacheopn(a0,a1,a2,a3,121,(Index_Store_Tag_I,Fill))
178
179 #if defined(CONFIG_IFX_MIPS) && defined(IFX_CACHE_EXTRA_OPERATION)
180 IFX_CACHE_EXTRA_OPERATION
181 #else
182 /* To support Orion/R4600, we initialise the data cache in 3 passes.
183 */
184
185 /* 1: initialise dcache tags.
186 */
187
188 li a0, K0BASE
189 move a2, t3 # dcacheSize
190 move a3, t5 # dcacheLineSize
191 move a1, a2
192 icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
193
194 /* 2: fill dcache.
195 */
196
197 li a0, K0BASE
198 move a2, t3 # dcacheSize
199 move a3, t5 # dcacheLineSize
200 move a1, a2
201 icacheopn(a0,a1,a2,a3,1lw,(dummy))
202
203 /* 3: clear dcache tags.
204 */
205
206 li a0, K0BASE
207 move a2, t3 # dcacheSize
208 move a3, t5 # dcacheLineSize
209 move a1, a2
210 icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
211 #endif
212
213 j ra
214 .end mips_cache_reset
215
216
217 /*******************************************************************************
218 *
219 * dcache_status - get cache status
220 *
221 * RETURNS: 0 - cache disabled; 1 - cache enabled
222 *
223 */
224 .globl dcache_status
225 .ent dcache_status
226 dcache_status:
227
228 mfc0 v0, CP0_CONFIG
229 andi v0, v0, 1
230 j ra
231
232 .end dcache_status
233
234 /*******************************************************************************
235 *
236 * dcache_disable - disable cache
237 *
238 * RETURNS: N/A
239 *
240 */
241 .globl dcache_disable
242 .ent dcache_disable
243 dcache_disable:
244
245 mfc0 t0, CP0_CONFIG
246 li t1, -8
247 and t0, t0, t1
248 ori t0, t0, CONF_CM_UNCACHED
249 mtc0 t0, CP0_CONFIG
250 j ra
251
252 .end dcache_disable
253
254
255 /*******************************************************************************
256 *
257 * mips_cache_lock - lock RAM area pointed to by a0 in cache.
258 *
259 * RETURNS: N/A
260 *
261 */
262 #if defined(CONFIG_PURPLE)
263 # define CACHE_LOCK_SIZE (CFG_DCACHE_SIZE/2)
264 #else
265 # define CACHE_LOCK_SIZE (CFG_DCACHE_SIZE)
266 #endif
267 .globl mips_cache_lock
268 .ent mips_cache_lock
269 mips_cache_lock:
270 li a1, K0BASE - CACHE_LOCK_SIZE
271 addu a0, a1
272 li a2, CACHE_LOCK_SIZE
273 li a3, CFG_CACHELINE_SIZE
274 move a1, a2
275 icacheop(a0,a1,a2,a3,0x1d)
276
277 j ra
278 .end mips_cache_lock