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