blob: 01fbb2fe3e03d145ff2c83d8f9ee7a8ab5cf12dd [file] [log] [blame]
wdenkc0218802003-03-27 12:09:35 +00001/*
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 ; \
479:
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 ; \
8210: 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) ; \
9311:
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) ; \
10111:
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
127mips_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
1432: 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
wdenk8bde7f72003-06-27 21:31:46 +0000153
wdenkc0218802003-03-27 12:09:35 +0000154 /* 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
217dcache_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
234dcache_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*/
wdenk60fbe252003-04-08 23:25:21 +0000253#if defined(CONFIG_INCA_IP)
254# define CACHE_LOCK_SIZE (CFG_DCACHE_SIZE)
255#elif defined(CONFIG_PURPLE)
256# define CACHE_LOCK_SIZE (CFG_DCACHE_SIZE/2)
257#endif
wdenkc0218802003-03-27 12:09:35 +0000258 .globl mips_cache_lock
259 .ent mips_cache_lock
260mips_cache_lock:
wdenk60fbe252003-04-08 23:25:21 +0000261 li a1, K0BASE - CACHE_LOCK_SIZE
wdenkc0218802003-03-27 12:09:35 +0000262 addu a0, a1
wdenk60fbe252003-04-08 23:25:21 +0000263 li a2, CACHE_LOCK_SIZE
wdenkc0218802003-03-27 12:09:35 +0000264 li a3, CFG_CACHELINE_SIZE
265 move a1, a2
266 icacheop(a0,a1,a2,a3,0x1d)
267
268 j ra
269 .end mips_cache_lock