blob: 443240e540b897937eb165c83fa945bee593f971 [file] [log] [blame]
wdenkbb1b8262003-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
wdenkbb1b8262003-03-27 12:09:35 +000025#include <config.h>
26#include <version.h>
27#include <asm/regdef.h>
28#include <asm/mipsregs.h>
29#include <asm/addrspace.h>
30#include <asm/cacheops.h>
31
wdenkbb1b8262003-03-27 12:09:35 +000032 /* 16KB is the maximum size of instruction and data caches on
33 * MIPS 4K.
34 */
35#define MIPS_MAX_CACHE_SIZE 0x4000
36
wdenkbb1b8262003-03-27 12:09:35 +000037/*
38 * cacheop macro to automate cache operations
39 * first some helpers...
40 */
41#define _mincache(size, maxsize) \
42 bltu size,maxsize,9f ; \
43 move size,maxsize ; \
449:
45
46#define _align(minaddr, maxaddr, linesize) \
47 .set noat ; \
48 subu AT,linesize,1 ; \
49 not AT ; \
50 and minaddr,AT ; \
51 addu maxaddr,-1 ; \
52 and maxaddr,AT ; \
53 .set at
54
55/* general operations */
56#define doop1(op1) \
57 cache op1,0(a0)
58#define doop2(op1, op2) \
59 cache op1,0(a0) ; \
60 nop ; \
61 cache op2,0(a0)
62
63/* specials for cache initialisation */
64#define doop1lw(op1) \
65 lw zero,0(a0)
66#define doop1lw1(op1) \
67 cache op1,0(a0) ; \
68 lw zero,0(a0) ; \
69 cache op1,0(a0)
70#define doop121(op1,op2) \
71 cache op1,0(a0) ; \
72 nop; \
73 cache op2,0(a0) ; \
74 nop; \
75 cache op1,0(a0)
76
77#define _oploopn(minaddr, maxaddr, linesize, tag, ops) \
78 .set noreorder ; \
7910: doop##tag##ops ; \
80 bne minaddr,maxaddr,10b ; \
81 add minaddr,linesize ; \
82 .set reorder
83
84/* finally the cache operation macros */
85#define vcacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \
86 blez n,11f ; \
87 addu n,kva ; \
88 _align(kva, n, cacheLineSize) ; \
89 _oploopn(kva, n, cacheLineSize, tag, ops) ; \
9011:
91
92#define icacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \
93 _mincache(n, cacheSize); \
94 blez n,11f ; \
95 addu n,kva ; \
96 _align(kva, n, cacheLineSize) ; \
97 _oploopn(kva, n, cacheLineSize, tag, ops) ; \
9811:
99
100#define vcacheop(kva, n, cacheSize, cacheLineSize, op) \
101 vcacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
102
103#define icacheop(kva, n, cacheSize, cacheLineSize, op) \
104 icacheopn(kva, n, cacheSize, cacheLineSize, 1, (op))
105
106/*******************************************************************************
107*
108* mips_cache_reset - low level initialisation of the primary caches
109*
110* This routine initialises the primary caches to ensure that they
111* have good parity. It must be called by the ROM before any cached locations
112* are used to prevent the possibility of data with bad parity being written to
113* memory.
114* To initialise the instruction cache it is essential that a source of data
115* with good parity is available. This routine
116* will initialise an area of memory starting at location zero to be used as
117* a source of parity.
118*
119* RETURNS: N/A
120*
121*/
122 .globl mips_cache_reset
123 .ent mips_cache_reset
124mips_cache_reset:
125
126 li t2, CFG_ICACHE_SIZE
127 li t3, CFG_DCACHE_SIZE
128 li t4, CFG_CACHELINE_SIZE
129 move t5, t4
130
wdenkbb1b8262003-03-27 12:09:35 +0000131 li v0, MIPS_MAX_CACHE_SIZE
132
133 /* Now clear that much memory starting from zero.
134 */
135
136 li a0, KSEG1
137 addu a1, a0, v0
Shinya Kuribayashic7faac52007-10-27 15:27:06 +09001382:
139 sw zero, 0(a0)
wdenkbb1b8262003-03-27 12:09:35 +0000140 sw zero, 4(a0)
141 sw zero, 8(a0)
142 sw zero, 12(a0)
143 sw zero, 16(a0)
144 sw zero, 20(a0)
145 sw zero, 24(a0)
146 sw zero, 28(a0)
147 addu a0, 32
148 bltu a0, a1, 2b
wdenk57b2d802003-06-27 21:31:46 +0000149
wdenkbb1b8262003-03-27 12:09:35 +0000150 /* Set invalid tag.
151 */
152
153 mtc0 zero, CP0_TAGLO
154
Shinya Kuribayashic7faac52007-10-27 15:27:06 +0900155 /*
156 * The caches are probably in an indeterminate state,
157 * so we force good parity into them by doing an
158 * invalidate, load/fill, invalidate for each line.
159 */
wdenkbb1b8262003-03-27 12:09:35 +0000160
161 /* Assume bottom of RAM will generate good parity for the cache.
162 */
163
164 li a0, K0BASE
165 move a2, t2 # icacheSize
166 move a3, t4 # icacheLineSize
167 move a1, a2
168 icacheopn(a0,a1,a2,a3,121,(Index_Store_Tag_I,Fill))
169
170 /* To support Orion/R4600, we initialise the data cache in 3 passes.
171 */
172
173 /* 1: initialise dcache tags.
174 */
175
176 li a0, K0BASE
177 move a2, t3 # dcacheSize
178 move a3, t5 # dcacheLineSize
179 move a1, a2
180 icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
181
182 /* 2: fill dcache.
183 */
184
185 li a0, K0BASE
186 move a2, t3 # dcacheSize
187 move a3, t5 # dcacheLineSize
188 move a1, a2
189 icacheopn(a0,a1,a2,a3,1lw,(dummy))
190
191 /* 3: clear dcache tags.
192 */
193
194 li a0, K0BASE
195 move a2, t3 # dcacheSize
196 move a3, t5 # dcacheLineSize
197 move a1, a2
198 icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
199
Shinya Kuribayashic7faac52007-10-27 15:27:06 +0900200 j ra
wdenkbb1b8262003-03-27 12:09:35 +0000201
Shinya Kuribayashic7faac52007-10-27 15:27:06 +0900202 .end mips_cache_reset
wdenkbb1b8262003-03-27 12:09:35 +0000203
204/*******************************************************************************
205*
206* dcache_status - get cache status
207*
208* RETURNS: 0 - cache disabled; 1 - cache enabled
209*
210*/
211 .globl dcache_status
212 .ent dcache_status
213dcache_status:
214
215 mfc0 v0, CP0_CONFIG
216 andi v0, v0, 1
217 j ra
218
Shinya Kuribayashic7faac52007-10-27 15:27:06 +0900219 .end dcache_status
wdenkbb1b8262003-03-27 12:09:35 +0000220
221/*******************************************************************************
222*
223* dcache_disable - disable cache
224*
225* RETURNS: N/A
226*
227*/
228 .globl dcache_disable
229 .ent dcache_disable
230dcache_disable:
231
232 mfc0 t0, CP0_CONFIG
233 li t1, -8
234 and t0, t0, t1
235 ori t0, t0, CONF_CM_UNCACHED
Shinya Kuribayashic7faac52007-10-27 15:27:06 +0900236 mtc0 t0, CP0_CONFIG
wdenkbb1b8262003-03-27 12:09:35 +0000237 j ra
238
Shinya Kuribayashic7faac52007-10-27 15:27:06 +0900239 .end dcache_disable
wdenkbb1b8262003-03-27 12:09:35 +0000240
241/*******************************************************************************
242*
243* mips_cache_lock - lock RAM area pointed to by a0 in cache.
244*
245* RETURNS: N/A
246*
247*/
wdenk9b7f3842003-10-09 20:09:04 +0000248#if defined(CONFIG_PURPLE)
wdenka6db71d2003-04-08 23:25:21 +0000249# define CACHE_LOCK_SIZE (CFG_DCACHE_SIZE/2)
wdenk9b7f3842003-10-09 20:09:04 +0000250#else
251# define CACHE_LOCK_SIZE (CFG_DCACHE_SIZE)
wdenka6db71d2003-04-08 23:25:21 +0000252#endif
wdenkbb1b8262003-03-27 12:09:35 +0000253 .globl mips_cache_lock
254 .ent mips_cache_lock
255mips_cache_lock:
wdenka6db71d2003-04-08 23:25:21 +0000256 li a1, K0BASE - CACHE_LOCK_SIZE
wdenkbb1b8262003-03-27 12:09:35 +0000257 addu a0, a1
wdenka6db71d2003-04-08 23:25:21 +0000258 li a2, CACHE_LOCK_SIZE
wdenkbb1b8262003-03-27 12:09:35 +0000259 li a3, CFG_CACHELINE_SIZE
260 move a1, a2
261 icacheop(a0,a1,a2,a3,0x1d)
262
263 j ra
Shinya Kuribayashic7faac52007-10-27 15:27:06 +0900264
wdenkbb1b8262003-03-27 12:09:35 +0000265 .end mips_cache_lock