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