[MIPS] cpu/mips/cache.S: Introduce NESTED/LEAF/END macros
[oweals/u-boot.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 #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 /*******************************************************************************
108 *
109 * mips_cache_reset - low level initialisation of the primary caches
110 *
111 * This routine initialises the primary caches to ensure that they
112 * have good parity.  It must be called by the ROM before any cached locations
113 * are used to prevent the possibility of data with bad parity being written to
114 * memory.
115 * To initialise the instruction cache it is essential that a source of data
116 * with good parity is available. This routine
117 * will initialise an area of memory starting at location zero to be used as
118 * a source of parity.
119 *
120 * RETURNS: N/A
121 *
122 */
123 NESTED(mips_cache_reset, 0, ra)
124         li      t2, CFG_ICACHE_SIZE
125         li      t3, CFG_DCACHE_SIZE
126         li      t4, CFG_CACHELINE_SIZE
127         move    t5, t4
128
129         li      v0, MIPS_MAX_CACHE_SIZE
130
131         /* Now clear that much memory starting from zero.
132          */
133
134         li      a0, KSEG1
135         addu    a1, a0, v0
136 2:
137         sw      zero, 0(a0)
138         sw      zero, 4(a0)
139         sw      zero, 8(a0)
140         sw      zero, 12(a0)
141         sw      zero, 16(a0)
142         sw      zero, 20(a0)
143         sw      zero, 24(a0)
144         sw      zero, 28(a0)
145         addu    a0, 32
146         bltu    a0, a1, 2b
147
148         /* Set invalid tag.
149          */
150
151         mtc0    zero, CP0_TAGLO
152
153         /*
154          * The caches are probably in an indeterminate state,
155          * so we force good parity into them by doing an
156          * invalidate, load/fill, invalidate for each line.
157          */
158
159         /* Assume bottom of RAM will generate good parity for the cache.
160          */
161
162         li      a0, K0BASE
163         move    a2, t2          # icacheSize
164         move    a3, t4          # icacheLineSize
165         move    a1, a2
166         icacheopn(a0,a1,a2,a3,121,(Index_Store_Tag_I,Fill))
167
168         /* To support Orion/R4600, we initialise the data cache in 3 passes.
169          */
170
171         /* 1: initialise dcache tags.
172          */
173
174         li      a0, K0BASE
175         move    a2, t3          # dcacheSize
176         move    a3, t5          # dcacheLineSize
177         move    a1, a2
178         icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
179
180         /* 2: fill dcache.
181          */
182
183         li      a0, K0BASE
184         move    a2, t3          # dcacheSize
185         move    a3, t5          # dcacheLineSize
186         move    a1, a2
187         icacheopn(a0,a1,a2,a3,1lw,(dummy))
188
189         /* 3: clear dcache tags.
190          */
191
192         li      a0, K0BASE
193         move    a2, t3          # dcacheSize
194         move    a3, t5          # dcacheLineSize
195         move    a1, a2
196         icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
197
198         j       ra
199         END(mips_cache_reset)
200
201 /*******************************************************************************
202 *
203 * dcache_status - get cache status
204 *
205 * RETURNS: 0 - cache disabled; 1 - cache enabled
206 *
207 */
208 LEAF(dcache_status)
209         mfc0    v0, CP0_CONFIG
210         andi    v0, v0, 1
211         j       ra
212         END(dcache_status)
213
214 /*******************************************************************************
215 *
216 * dcache_disable - disable cache
217 *
218 * RETURNS: N/A
219 *
220 */
221 LEAF(dcache_disable)
222         mfc0    t0, CP0_CONFIG
223         li      t1, -8
224         and     t0, t0, t1
225         ori     t0, t0, CONF_CM_UNCACHED
226         mtc0    t0, CP0_CONFIG
227         j       ra
228         END(dcache_disable)
229
230 #ifdef CFG_INIT_RAM_LOCK_MIPS
231 /*******************************************************************************
232 *
233 * mips_cache_lock - lock RAM area pointed to by a0 in cache.
234 *
235 * RETURNS: N/A
236 *
237 */
238 #if defined(CONFIG_PURPLE)
239 # define        CACHE_LOCK_SIZE (CFG_DCACHE_SIZE/2)
240 #else
241 # define        CACHE_LOCK_SIZE (CFG_DCACHE_SIZE)
242 #endif
243         .globl  mips_cache_lock
244         .ent    mips_cache_lock
245 mips_cache_lock:
246         li      a1, K0BASE - CACHE_LOCK_SIZE
247         addu    a0, a1
248         li      a2, CACHE_LOCK_SIZE
249         li      a3, CFG_CACHELINE_SIZE
250         move    a1, a2
251         icacheop(a0,a1,a2,a3,0x1d)
252
253         j       ra
254
255         .end    mips_cache_lock
256 #endif /* CFG_INIT_RAM_LOCK_MIPS */