]> git.sur5r.net Git - u-boot/blob - cpu/mips/cache.S
[MIPS] Fix I-/D-cache initialization loops
[u-boot] / cpu / mips / 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 #include <config.h>
26 #include <version.h>
27 #include <asm/asm.h>
28 #include <asm/regdef.h>
29 #include <asm/mipsregs.h>
30 #include <asm/addrspace.h>
31 #include <asm/cacheops.h>
32
33 #define RA              t8
34
35         /* 16KB is the maximum size of instruction and data caches on
36          * MIPS 4K.
37          */
38 #define MIPS_MAX_CACHE_SIZE     0x4000
39
40 #define INDEX_BASE      KSEG0
41
42         .macro  cache_op op addr
43         .set    push
44         .set    noreorder
45         .set    mips3
46         cache   \op, 0(\addr)
47         .set    pop
48         .endm
49
50 /*
51  * cacheop macro to automate cache operations
52  * first some helpers...
53  */
54 #define _mincache(size, maxsize) \
55    bltu  size,maxsize,9f ; \
56    move  size,maxsize ;    \
57 9:
58
59 #define _align(minaddr, maxaddr, linesize) \
60    .set noat ; \
61    subu  AT,linesize,1 ;   \
62    not   AT ;        \
63    and   minaddr,AT ;      \
64    addu  maxaddr,-1 ;      \
65    and   maxaddr,AT ;      \
66    .set at
67
68 /* general operations */
69 #define doop1(op1) \
70    cache op1,0(a0)
71 #define doop2(op1, op2) \
72    cache op1,0(a0) ;    \
73    nop ;          \
74    cache op2,0(a0)
75
76 /* specials for cache initialisation */
77 #define doop1lw(op1) \
78    lw zero,0(a0)
79 #define doop1lw1(op1) \
80    cache op1,0(a0) ;    \
81    lw zero,0(a0) ;      \
82    cache op1,0(a0)
83 #define doop121(op1,op2) \
84    cache op1,0(a0) ;    \
85    nop;           \
86    cache op2,0(a0) ;    \
87    nop;           \
88    cache op1,0(a0)
89
90 #define _oploopn(minaddr, maxaddr, linesize, tag, ops) \
91    .set  noreorder ;    \
92 10:   doop##tag##ops ;  \
93    bne     minaddr,maxaddr,10b ; \
94    add      minaddr,linesize ;   \
95    .set  reorder
96
97 /* finally the cache operation macros */
98 #define vcacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \
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 icacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \
106    _mincache(n, cacheSize);   \
107    blez  n,11f ;        \
108    addu  n,kva ;        \
109    _align(kva, n, cacheLineSize) ; \
110    _oploopn(kva, n, cacheLineSize, tag, ops) ; \
111 11:
112
113 #define vcacheop(kva, n, cacheSize, cacheLineSize, op) \
114    vcacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
115
116 #define icacheop(kva, n, cacheSize, cacheLineSize, op) \
117    icacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
118
119         .macro  f_fill64 dst, offset, val
120         LONG_S  \val, (\offset +  0 * LONGSIZE)(\dst)
121         LONG_S  \val, (\offset +  1 * LONGSIZE)(\dst)
122         LONG_S  \val, (\offset +  2 * LONGSIZE)(\dst)
123         LONG_S  \val, (\offset +  3 * LONGSIZE)(\dst)
124         LONG_S  \val, (\offset +  4 * LONGSIZE)(\dst)
125         LONG_S  \val, (\offset +  5 * LONGSIZE)(\dst)
126         LONG_S  \val, (\offset +  6 * LONGSIZE)(\dst)
127         LONG_S  \val, (\offset +  7 * LONGSIZE)(\dst)
128 #if LONGSIZE == 4
129         LONG_S  \val, (\offset +  8 * LONGSIZE)(\dst)
130         LONG_S  \val, (\offset +  9 * LONGSIZE)(\dst)
131         LONG_S  \val, (\offset + 10 * LONGSIZE)(\dst)
132         LONG_S  \val, (\offset + 11 * LONGSIZE)(\dst)
133         LONG_S  \val, (\offset + 12 * LONGSIZE)(\dst)
134         LONG_S  \val, (\offset + 13 * LONGSIZE)(\dst)
135         LONG_S  \val, (\offset + 14 * LONGSIZE)(\dst)
136         LONG_S  \val, (\offset + 15 * LONGSIZE)(\dst)
137 #endif
138         .endm
139
140 /*
141  * mips_init_icache(uint PRId, ulong icache_size, unchar icache_linesz)
142  */
143 LEAF(mips_init_icache)
144         blez    a1, 9f
145         mtc0    zero, CP0_TAGLO
146         /* clear tag to invalidate */
147         PTR_LI          t0, INDEX_BASE
148         PTR_ADDU        t1, t0, a1
149 1:      cache_op        Index_Store_Tag_I t0
150         PTR_ADDU        t0, a2
151         bne             t0, t1, 1b
152         /* fill once, so data field parity is correct */
153         PTR_LI          t0, INDEX_BASE
154 2:      cache_op        Fill t0
155         PTR_ADDU        t0, a2
156         bne             t0, t1, 2b
157         /* invalidate again - prudent but not strictly neccessary */
158         PTR_LI          t0, INDEX_BASE
159 1:      cache_op        Index_Store_Tag_I t0
160         PTR_ADDU        t0, a2
161         bne             t0, t1, 1b
162 9:      jr      ra
163         END(mips_init_icache)
164
165 /*
166  * mips_init_dcache(uint PRId, ulong dcache_size, unchar dcache_linesz)
167  */
168 LEAF(mips_init_dcache)
169         blez    a1, 9f
170         mtc0    zero, CP0_TAGLO
171         /* clear all tags */
172         PTR_LI          t0, INDEX_BASE
173         PTR_ADDU        t1, t0, a1
174 1:      cache_op        Index_Store_Tag_D t0
175         PTR_ADDU        t0, a2
176         bne             t0, t1, 1b
177         /* load from each line (in cached space) */
178         PTR_LI          t0, INDEX_BASE
179 2:      LONG_L          zero, 0(t0)
180         PTR_ADDU        t0, a2
181         bne             t0, t1, 2b
182         /* clear all tags */
183         PTR_LI          t0, INDEX_BASE
184 1:      cache_op        Index_Store_Tag_D t0
185         PTR_ADDU        t0, a2
186         bne             t0, t1, 1b
187 9:      jr      ra
188         END(mips_init_dcache)
189
190 /*******************************************************************************
191 *
192 * mips_cache_reset - low level initialisation of the primary caches
193 *
194 * This routine initialises the primary caches to ensure that they
195 * have good parity.  It must be called by the ROM before any cached locations
196 * are used to prevent the possibility of data with bad parity being written to
197 * memory.
198 * To initialise the instruction cache it is essential that a source of data
199 * with good parity is available. This routine
200 * will initialise an area of memory starting at location zero to be used as
201 * a source of parity.
202 *
203 * RETURNS: N/A
204 *
205 */
206 NESTED(mips_cache_reset, 0, ra)
207         move    RA, ra
208         li      t2, CFG_ICACHE_SIZE
209         li      t3, CFG_DCACHE_SIZE
210         li      t4, CFG_CACHELINE_SIZE
211         move    t5, t4
212
213         li      v0, MIPS_MAX_CACHE_SIZE
214
215         /*
216          * Now clear that much memory starting from zero.
217          */
218         PTR_LI          a0, KSEG1
219         PTR_ADDU        a1, a0, v0
220 2:      PTR_ADDIU       a0, 64
221         f_fill64        a0, -64, zero
222         bne             a0, a1, 2b
223
224         /*
225          * The caches are probably in an indeterminate state,
226          * so we force good parity into them by doing an
227          * invalidate, load/fill, invalidate for each line.
228          */
229
230         /*
231          * Assume bottom of RAM will generate good parity for the cache.
232          */
233
234         /*
235          * Initialize the I-cache first,
236          */
237         move    a1, t2
238         move    a2, t4
239         bal     mips_init_icache
240
241         /*
242          * then initialize D-cache.
243          */
244         move    a1, t3
245         move    a2, t5
246         bal     mips_init_dcache
247
248         jr      RA
249         END(mips_cache_reset)
250
251 /*******************************************************************************
252 *
253 * dcache_status - get cache status
254 *
255 * RETURNS: 0 - cache disabled; 1 - cache enabled
256 *
257 */
258 LEAF(dcache_status)
259         mfc0    v0, CP0_CONFIG
260         andi    v0, v0, 1
261         j       ra
262         END(dcache_status)
263
264 /*******************************************************************************
265 *
266 * dcache_disable - disable cache
267 *
268 * RETURNS: N/A
269 *
270 */
271 LEAF(dcache_disable)
272         mfc0    t0, CP0_CONFIG
273         li      t1, -8
274         and     t0, t0, t1
275         ori     t0, t0, CONF_CM_UNCACHED
276         mtc0    t0, CP0_CONFIG
277         j       ra
278         END(dcache_disable)
279
280 #ifdef CFG_INIT_RAM_LOCK_MIPS
281 /*******************************************************************************
282 *
283 * mips_cache_lock - lock RAM area pointed to by a0 in cache.
284 *
285 * RETURNS: N/A
286 *
287 */
288 #if defined(CONFIG_PURPLE)
289 # define        CACHE_LOCK_SIZE (CFG_DCACHE_SIZE/2)
290 #else
291 # define        CACHE_LOCK_SIZE (CFG_DCACHE_SIZE)
292 #endif
293         .globl  mips_cache_lock
294         .ent    mips_cache_lock
295 mips_cache_lock:
296         li      a1, K0BASE - CACHE_LOCK_SIZE
297         addu    a0, a1
298         li      a2, CACHE_LOCK_SIZE
299         li      a3, CFG_CACHELINE_SIZE
300         move    a1, a2
301         icacheop(a0,a1,a2,a3,0x1d)
302
303         j       ra
304
305         .end    mips_cache_lock
306 #endif /* CFG_INIT_RAM_LOCK_MIPS */