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