blob: 6d39ba9aac9ef2b23ea694b3dc103fdc435db463 [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
wdenkc0218802003-03-27 12:09:35 +000025#include <config.h>
26#include <version.h>
Shinya Kuribayashi2f5d4142008-03-25 21:30:06 +090027#include <asm/asm.h>
wdenkc0218802003-03-27 12:09:35 +000028#include <asm/regdef.h>
29#include <asm/mipsregs.h>
30#include <asm/addrspace.h>
31#include <asm/cacheops.h>
32
wdenkc0218802003-03-27 12:09:35 +000033 /* 16KB is the maximum size of instruction and data caches on
34 * MIPS 4K.
35 */
36#define MIPS_MAX_CACHE_SIZE 0x4000
37
wdenkc0218802003-03-27 12:09:35 +000038/*
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 ; \
459:
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 ; \
8010: 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) ; \
9111:
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) ; \
9911:
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
Shinya Kuribayashi18988402008-03-25 21:30:06 +0900107 .macro f_fill64 dst, offset, val
108 LONG_S \val, (\offset + 0 * LONGSIZE)(\dst)
109 LONG_S \val, (\offset + 1 * LONGSIZE)(\dst)
110 LONG_S \val, (\offset + 2 * LONGSIZE)(\dst)
111 LONG_S \val, (\offset + 3 * LONGSIZE)(\dst)
112 LONG_S \val, (\offset + 4 * LONGSIZE)(\dst)
113 LONG_S \val, (\offset + 5 * LONGSIZE)(\dst)
114 LONG_S \val, (\offset + 6 * LONGSIZE)(\dst)
115 LONG_S \val, (\offset + 7 * LONGSIZE)(\dst)
116#if LONGSIZE == 4
117 LONG_S \val, (\offset + 8 * LONGSIZE)(\dst)
118 LONG_S \val, (\offset + 9 * LONGSIZE)(\dst)
119 LONG_S \val, (\offset + 10 * LONGSIZE)(\dst)
120 LONG_S \val, (\offset + 11 * LONGSIZE)(\dst)
121 LONG_S \val, (\offset + 12 * LONGSIZE)(\dst)
122 LONG_S \val, (\offset + 13 * LONGSIZE)(\dst)
123 LONG_S \val, (\offset + 14 * LONGSIZE)(\dst)
124 LONG_S \val, (\offset + 15 * LONGSIZE)(\dst)
125#endif
126 .endm
127
wdenkc0218802003-03-27 12:09:35 +0000128/*******************************************************************************
129*
130* mips_cache_reset - low level initialisation of the primary caches
131*
132* This routine initialises the primary caches to ensure that they
133* have good parity. It must be called by the ROM before any cached locations
134* are used to prevent the possibility of data with bad parity being written to
135* memory.
136* To initialise the instruction cache it is essential that a source of data
137* with good parity is available. This routine
138* will initialise an area of memory starting at location zero to be used as
139* a source of parity.
140*
141* RETURNS: N/A
142*
143*/
Shinya Kuribayashi2f5d4142008-03-25 21:30:06 +0900144NESTED(mips_cache_reset, 0, ra)
wdenkc0218802003-03-27 12:09:35 +0000145 li t2, CFG_ICACHE_SIZE
146 li t3, CFG_DCACHE_SIZE
147 li t4, CFG_CACHELINE_SIZE
148 move t5, t4
149
wdenkc0218802003-03-27 12:09:35 +0000150 li v0, MIPS_MAX_CACHE_SIZE
151
Shinya Kuribayashi18988402008-03-25 21:30:06 +0900152 /*
153 * Now clear that much memory starting from zero.
wdenkc0218802003-03-27 12:09:35 +0000154 */
Shinya Kuribayashi18988402008-03-25 21:30:06 +0900155 PTR_LI a0, KSEG1
156 PTR_ADDU a1, a0, v0
1572: PTR_ADDIU a0, 64
158 f_fill64 a0, -64, zero
159 bne a0, a1, 2b
wdenk8bde7f72003-06-27 21:31:46 +0000160
wdenkc0218802003-03-27 12:09:35 +0000161 /* Set invalid tag.
162 */
163
164 mtc0 zero, CP0_TAGLO
165
Shinya Kuribayashi03c031d2007-10-27 15:27:06 +0900166 /*
167 * The caches are probably in an indeterminate state,
168 * so we force good parity into them by doing an
169 * invalidate, load/fill, invalidate for each line.
170 */
wdenkc0218802003-03-27 12:09:35 +0000171
172 /* Assume bottom of RAM will generate good parity for the cache.
173 */
174
175 li a0, K0BASE
176 move a2, t2 # icacheSize
177 move a3, t4 # icacheLineSize
178 move a1, a2
179 icacheopn(a0,a1,a2,a3,121,(Index_Store_Tag_I,Fill))
180
181 /* To support Orion/R4600, we initialise the data cache in 3 passes.
182 */
183
184 /* 1: initialise dcache tags.
185 */
186
187 li a0, K0BASE
188 move a2, t3 # dcacheSize
189 move a3, t5 # dcacheLineSize
190 move a1, a2
191 icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
192
193 /* 2: fill dcache.
194 */
195
196 li a0, K0BASE
197 move a2, t3 # dcacheSize
198 move a3, t5 # dcacheLineSize
199 move a1, a2
200 icacheopn(a0,a1,a2,a3,1lw,(dummy))
201
202 /* 3: clear dcache tags.
203 */
204
205 li a0, K0BASE
206 move a2, t3 # dcacheSize
207 move a3, t5 # dcacheLineSize
208 move a1, a2
209 icacheop(a0,a1,a2,a3,Index_Store_Tag_D)
210
Shinya Kuribayashi03c031d2007-10-27 15:27:06 +0900211 j ra
Shinya Kuribayashi2f5d4142008-03-25 21:30:06 +0900212 END(mips_cache_reset)
wdenkc0218802003-03-27 12:09:35 +0000213
214/*******************************************************************************
215*
216* dcache_status - get cache status
217*
218* RETURNS: 0 - cache disabled; 1 - cache enabled
219*
220*/
Shinya Kuribayashi2f5d4142008-03-25 21:30:06 +0900221LEAF(dcache_status)
wdenkc0218802003-03-27 12:09:35 +0000222 mfc0 v0, CP0_CONFIG
223 andi v0, v0, 1
224 j ra
Shinya Kuribayashi2f5d4142008-03-25 21:30:06 +0900225 END(dcache_status)
wdenkc0218802003-03-27 12:09:35 +0000226
227/*******************************************************************************
228*
229* dcache_disable - disable cache
230*
231* RETURNS: N/A
232*
233*/
Shinya Kuribayashi2f5d4142008-03-25 21:30:06 +0900234LEAF(dcache_disable)
wdenkc0218802003-03-27 12:09:35 +0000235 mfc0 t0, CP0_CONFIG
236 li t1, -8
237 and t0, t0, t1
238 ori t0, t0, CONF_CM_UNCACHED
Shinya Kuribayashi03c031d2007-10-27 15:27:06 +0900239 mtc0 t0, CP0_CONFIG
wdenkc0218802003-03-27 12:09:35 +0000240 j ra
Shinya Kuribayashi2f5d4142008-03-25 21:30:06 +0900241 END(dcache_disable)
wdenkc0218802003-03-27 12:09:35 +0000242
Shinya Kuribayashie1390802008-03-25 11:39:29 +0900243#ifdef CFG_INIT_RAM_LOCK_MIPS
wdenkc0218802003-03-27 12:09:35 +0000244/*******************************************************************************
245*
246* mips_cache_lock - lock RAM area pointed to by a0 in cache.
247*
248* RETURNS: N/A
249*
250*/
wdenk5da627a2003-10-09 20:09:04 +0000251#if defined(CONFIG_PURPLE)
wdenk60fbe252003-04-08 23:25:21 +0000252# define CACHE_LOCK_SIZE (CFG_DCACHE_SIZE/2)
wdenk5da627a2003-10-09 20:09:04 +0000253#else
254# define CACHE_LOCK_SIZE (CFG_DCACHE_SIZE)
wdenk60fbe252003-04-08 23:25:21 +0000255#endif
wdenkc0218802003-03-27 12:09:35 +0000256 .globl mips_cache_lock
257 .ent mips_cache_lock
258mips_cache_lock:
wdenk60fbe252003-04-08 23:25:21 +0000259 li a1, K0BASE - CACHE_LOCK_SIZE
wdenkc0218802003-03-27 12:09:35 +0000260 addu a0, a1
wdenk60fbe252003-04-08 23:25:21 +0000261 li a2, CACHE_LOCK_SIZE
wdenkc0218802003-03-27 12:09:35 +0000262 li a3, CFG_CACHELINE_SIZE
263 move a1, a2
264 icacheop(a0,a1,a2,a3,0x1d)
265
266 j ra
Shinya Kuribayashi03c031d2007-10-27 15:27:06 +0900267
wdenkc0218802003-03-27 12:09:35 +0000268 .end mips_cache_lock
Shinya Kuribayashie1390802008-03-25 11:39:29 +0900269#endif /* CFG_INIT_RAM_LOCK_MIPS */