]> git.sur5r.net Git - u-boot/blob - cpu/mips/cache.S
67ee19fba8ea819d2ee162697e8232fb0d96e87a
[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/regdef.h>
28 #include <asm/mipsregs.h>
29 #include <asm/addrspace.h>
30 #include <asm/cacheops.h>
31
32         /* 16KB is the maximum size of instruction and data caches on
33          * MIPS 4K.
34          */
35 #define MIPS_MAX_CACHE_SIZE     0x4000
36
37 /*
38  * cacheop macro to automate cache operations
39  * first some helpers...
40  */
41 #define _mincache(size, maxsize) \
42    bltu  size,maxsize,9f ; \
43    move  size,maxsize ;    \
44 9:
45
46 #define _align(minaddr, maxaddr, linesize) \
47    .set noat ; \
48    subu  AT,linesize,1 ;   \
49    not   AT ;        \
50    and   minaddr,AT ;      \
51    addu  maxaddr,-1 ;      \
52    and   maxaddr,AT ;      \
53    .set at
54
55 /* general operations */
56 #define doop1(op1) \
57    cache op1,0(a0)
58 #define doop2(op1, op2) \
59    cache op1,0(a0) ;    \
60    nop ;          \
61    cache op2,0(a0)
62
63 /* specials for cache initialisation */
64 #define doop1lw(op1) \
65    lw zero,0(a0)
66 #define doop1lw1(op1) \
67    cache op1,0(a0) ;    \
68    lw zero,0(a0) ;      \
69    cache op1,0(a0)
70 #define doop121(op1,op2) \
71    cache op1,0(a0) ;    \
72    nop;           \
73    cache op2,0(a0) ;    \
74    nop;           \
75    cache op1,0(a0)
76
77 #define _oploopn(minaddr, maxaddr, linesize, tag, ops) \
78    .set  noreorder ;    \
79 10:   doop##tag##ops ;  \
80    bne     minaddr,maxaddr,10b ; \
81    add      minaddr,linesize ;   \
82    .set  reorder
83
84 /* finally the cache operation macros */
85 #define vcacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \
86    blez  n,11f ;        \
87    addu  n,kva ;        \
88    _align(kva, n, cacheLineSize) ; \
89    _oploopn(kva, n, cacheLineSize, tag, ops) ; \
90 11:
91
92 #define icacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \
93    _mincache(n, cacheSize);   \
94    blez  n,11f ;        \
95    addu  n,kva ;        \
96    _align(kva, n, cacheLineSize) ; \
97    _oploopn(kva, n, cacheLineSize, tag, ops) ; \
98 11:
99
100 #define vcacheop(kva, n, cacheSize, cacheLineSize, op) \
101    vcacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
102
103 #define icacheop(kva, n, cacheSize, cacheLineSize, op) \
104    icacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
105
106 /*******************************************************************************
107 *
108 * mips_cache_reset - low level initialisation of the primary caches
109 *
110 * This routine initialises the primary caches to ensure that they
111 * have good parity.  It must be called by the ROM before any cached locations
112 * are used to prevent the possibility of data with bad parity being written to
113 * memory.
114 * To initialise the instruction cache it is essential that a source of data
115 * with good parity is available. This routine
116 * will initialise an area of memory starting at location zero to be used as
117 * a source of parity.
118 *
119 * RETURNS: N/A
120 *
121 */
122         .globl  mips_cache_reset
123         .ent    mips_cache_reset
124 mips_cache_reset:
125
126         li      t2, CFG_ICACHE_SIZE
127         li      t3, CFG_DCACHE_SIZE
128         li      t4, CFG_CACHELINE_SIZE
129         move    t5, t4
130
131         li      v0, MIPS_MAX_CACHE_SIZE
132
133         /* Now clear that much memory starting from zero.
134          */
135
136         li      a0, KSEG1
137         addu    a1, a0, v0
138 2:
139         sw      zero, 0(a0)
140         sw      zero, 4(a0)
141         sw      zero, 8(a0)
142         sw      zero, 12(a0)
143         sw      zero, 16(a0)
144         sw      zero, 20(a0)
145         sw      zero, 24(a0)
146         sw      zero, 28(a0)
147         addu    a0, 32
148         bltu    a0, a1, 2b
149
150         /* Set invalid tag.
151          */
152
153         mtc0    zero, CP0_TAGLO
154
155         /*
156          * The caches are probably in an indeterminate state,
157          * so we force good parity into them by doing an
158          * invalidate, load/fill, invalidate for each line.
159          */
160
161         /* Assume bottom of RAM will generate good parity for the cache.
162          */
163
164         li      a0, K0BASE
165         move    a2, t2          # icacheSize
166         move    a3, t4          # icacheLineSize
167         move    a1, a2
168         icacheopn(a0,a1,a2,a3,121,(Index_Store_Tag_I,Fill))
169
170         /* To support Orion/R4600, we initialise the data cache in 3 passes.
171          */
172
173         /* 1: initialise dcache tags.
174          */
175
176         li      a0, K0BASE
177         move    a2, t3          # dcacheSize
178         move    a3, t5          # dcacheLineSize
179         move    a1, a2
180         icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
181
182         /* 2: fill dcache.
183          */
184
185         li      a0, K0BASE
186         move    a2, t3          # dcacheSize
187         move    a3, t5          # dcacheLineSize
188         move    a1, a2
189         icacheopn(a0,a1,a2,a3,1lw,(dummy))
190
191         /* 3: clear dcache tags.
192          */
193
194         li      a0, K0BASE
195         move    a2, t3          # dcacheSize
196         move    a3, t5          # dcacheLineSize
197         move    a1, a2
198         icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
199
200         j       ra
201
202         .end    mips_cache_reset
203
204 /*******************************************************************************
205 *
206 * dcache_status - get cache status
207 *
208 * RETURNS: 0 - cache disabled; 1 - cache enabled
209 *
210 */
211         .globl  dcache_status
212         .ent    dcache_status
213 dcache_status:
214
215         mfc0    v0, CP0_CONFIG
216         andi    v0, v0, 1
217         j       ra
218
219         .end    dcache_status
220
221 /*******************************************************************************
222 *
223 * dcache_disable - disable cache
224 *
225 * RETURNS: N/A
226 *
227 */
228         .globl  dcache_disable
229         .ent    dcache_disable
230 dcache_disable:
231
232         mfc0    t0, CP0_CONFIG
233         li      t1, -8
234         and     t0, t0, t1
235         ori     t0, t0, CONF_CM_UNCACHED
236         mtc0    t0, CP0_CONFIG
237         j       ra
238
239         .end    dcache_disable
240
241 #ifdef CFG_INIT_RAM_LOCK_MIPS
242 /*******************************************************************************
243 *
244 * mips_cache_lock - lock RAM area pointed to by a0 in cache.
245 *
246 * RETURNS: N/A
247 *
248 */
249 #if defined(CONFIG_PURPLE)
250 # define        CACHE_LOCK_SIZE (CFG_DCACHE_SIZE/2)
251 #else
252 # define        CACHE_LOCK_SIZE (CFG_DCACHE_SIZE)
253 #endif
254         .globl  mips_cache_lock
255         .ent    mips_cache_lock
256 mips_cache_lock:
257         li      a1, K0BASE - CACHE_LOCK_SIZE
258         addu    a0, a1
259         li      a2, CACHE_LOCK_SIZE
260         li      a3, CFG_CACHELINE_SIZE
261         move    a1, a2
262         icacheop(a0,a1,a2,a3,0x1d)
263
264         j       ra
265
266         .end    mips_cache_lock
267 #endif /* CFG_INIT_RAM_LOCK_MIPS */