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