]>
Commit | Line | Data |
---|---|---|
c021880a | 1 | /* |
373b16fc | 2 | * Cache-handling routined for MIPS CPUs |
c021880a WD |
3 | * |
4 | * Copyright (c) 2003 Wolfgang Denk <wd@denx.de> | |
5 | * | |
1a459660 | 6 | * SPDX-License-Identifier: GPL-2.0+ |
c021880a WD |
7 | */ |
8 | ||
25ddd1fb | 9 | #include <asm-offsets.h> |
c021880a | 10 | #include <config.h> |
2f5d414c | 11 | #include <asm/asm.h> |
c021880a WD |
12 | #include <asm/regdef.h> |
13 | #include <asm/mipsregs.h> | |
14 | #include <asm/addrspace.h> | |
15 | #include <asm/cacheops.h> | |
16 | ||
979cfeaf DS |
17 | #ifndef CONFIG_SYS_MIPS_CACHE_MODE |
18 | #define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT | |
19 | #endif | |
20 | ||
7daf2ebe | 21 | #define INDEX_BASE CKSEG0 |
2e0e5271 | 22 | |
18988407 SK |
23 | .macro f_fill64 dst, offset, val |
24 | LONG_S \val, (\offset + 0 * LONGSIZE)(\dst) | |
25 | LONG_S \val, (\offset + 1 * LONGSIZE)(\dst) | |
26 | LONG_S \val, (\offset + 2 * LONGSIZE)(\dst) | |
27 | LONG_S \val, (\offset + 3 * LONGSIZE)(\dst) | |
28 | LONG_S \val, (\offset + 4 * LONGSIZE)(\dst) | |
29 | LONG_S \val, (\offset + 5 * LONGSIZE)(\dst) | |
30 | LONG_S \val, (\offset + 6 * LONGSIZE)(\dst) | |
31 | LONG_S \val, (\offset + 7 * LONGSIZE)(\dst) | |
32 | #if LONGSIZE == 4 | |
33 | LONG_S \val, (\offset + 8 * LONGSIZE)(\dst) | |
34 | LONG_S \val, (\offset + 9 * LONGSIZE)(\dst) | |
35 | LONG_S \val, (\offset + 10 * LONGSIZE)(\dst) | |
36 | LONG_S \val, (\offset + 11 * LONGSIZE)(\dst) | |
37 | LONG_S \val, (\offset + 12 * LONGSIZE)(\dst) | |
38 | LONG_S \val, (\offset + 13 * LONGSIZE)(\dst) | |
39 | LONG_S \val, (\offset + 14 * LONGSIZE)(\dst) | |
40 | LONG_S \val, (\offset + 15 * LONGSIZE)(\dst) | |
41 | #endif | |
42 | .endm | |
43 | ||
ac22feca PB |
44 | .macro cache_loop curr, end, line_sz, op |
45 | 10: cache \op, 0(\curr) | |
46 | PTR_ADDU \curr, \curr, \line_sz | |
47 | bne \curr, \end, 10b | |
48 | .endm | |
49 | ||
536cb7ce PB |
50 | .macro l1_info sz, line_sz, off |
51 | .set push | |
52 | .set noat | |
53 | ||
54 | mfc0 $1, CP0_CONFIG, 1 | |
55 | ||
56 | /* detect line size */ | |
a3ab2ae7 DS |
57 | srl \line_sz, $1, \off + MIPS_CONF1_DL_SHF - MIPS_CONF1_DA_SHF |
58 | andi \line_sz, \line_sz, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHF) | |
536cb7ce PB |
59 | move \sz, zero |
60 | beqz \line_sz, 10f | |
61 | li \sz, 2 | |
62 | sllv \line_sz, \sz, \line_sz | |
63 | ||
64 | /* detect associativity */ | |
a3ab2ae7 DS |
65 | srl \sz, $1, \off + MIPS_CONF1_DA_SHF - MIPS_CONF1_DA_SHF |
66 | andi \sz, \sz, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHF) | |
9f8ac824 | 67 | addiu \sz, \sz, 1 |
536cb7ce PB |
68 | |
69 | /* sz *= line_sz */ | |
70 | mul \sz, \sz, \line_sz | |
71 | ||
72 | /* detect log32(sets) */ | |
a3ab2ae7 DS |
73 | srl $1, $1, \off + MIPS_CONF1_DS_SHF - MIPS_CONF1_DA_SHF |
74 | andi $1, $1, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHF) | |
536cb7ce PB |
75 | addiu $1, $1, 1 |
76 | andi $1, $1, 0x7 | |
77 | ||
78 | /* sz <<= log32(sets) */ | |
79 | sllv \sz, \sz, $1 | |
80 | ||
81 | /* sz *= 32 */ | |
82 | li $1, 32 | |
83 | mul \sz, \sz, $1 | |
84 | 10: | |
85 | .set pop | |
86 | .endm | |
7aa1f198 SK |
87 | /* |
88 | * mips_cache_reset - low level initialisation of the primary caches | |
89 | * | |
90 | * This routine initialises the primary caches to ensure that they have good | |
91 | * parity. It must be called by the ROM before any cached locations are used | |
92 | * to prevent the possibility of data with bad parity being written to memory. | |
93 | * | |
94 | * To initialise the instruction cache it is essential that a source of data | |
95 | * with good parity is available. This routine will initialise an area of | |
96 | * memory starting at location zero to be used as a source of parity. | |
97 | * | |
98 | * RETURNS: N/A | |
99 | * | |
100 | */ | |
ca4e833c | 101 | LEAF(mips_cache_reset) |
ace3be4f | 102 | #ifndef CONFIG_SYS_CACHE_SIZE_AUTO |
fa476f75 | 103 | li t2, CONFIG_SYS_ICACHE_SIZE |
37228621 | 104 | li t8, CONFIG_SYS_ICACHE_LINE_SIZE |
fa476f75 | 105 | #else |
a3ab2ae7 | 106 | l1_info t2, t8, MIPS_CONF1_IA_SHF |
fa476f75 PB |
107 | #endif |
108 | ||
ace3be4f | 109 | #ifndef CONFIG_SYS_CACHE_SIZE_AUTO |
fa476f75 | 110 | li t3, CONFIG_SYS_DCACHE_SIZE |
37228621 | 111 | li t9, CONFIG_SYS_DCACHE_LINE_SIZE |
fa476f75 | 112 | #else |
a3ab2ae7 | 113 | l1_info t3, t9, MIPS_CONF1_DA_SHF |
fa476f75 PB |
114 | #endif |
115 | ||
dd7c7200 PB |
116 | #ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD |
117 | ||
fa476f75 | 118 | /* Determine the largest L1 cache size */ |
ace3be4f | 119 | #ifndef CONFIG_SYS_CACHE_SIZE_AUTO |
fa476f75 PB |
120 | #if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE |
121 | li v0, CONFIG_SYS_ICACHE_SIZE | |
122 | #else | |
123 | li v0, CONFIG_SYS_DCACHE_SIZE | |
124 | #endif | |
125 | #else | |
126 | move v0, t2 | |
127 | sltu t1, t2, t3 | |
128 | movn v0, t3, t1 | |
129 | #endif | |
18988407 SK |
130 | /* |
131 | * Now clear that much memory starting from zero. | |
c021880a | 132 | */ |
7daf2ebe | 133 | PTR_LI a0, CKSEG1 |
18988407 SK |
134 | PTR_ADDU a1, a0, v0 |
135 | 2: PTR_ADDIU a0, 64 | |
136 | f_fill64 a0, -64, zero | |
137 | bne a0, a1, 2b | |
8bde7f77 | 138 | |
dd7c7200 | 139 | #endif /* CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD */ |
c021880a | 140 | |
8755d507 PB |
141 | /* |
142 | * The TagLo registers used depend upon the CPU implementation, but the | |
143 | * architecture requires that it is safe for software to write to both | |
144 | * TagLo selects 0 & 2 covering supported cases. | |
145 | */ | |
146 | mtc0 zero, CP0_TAGLO | |
147 | mtc0 zero, CP0_TAGLO, 2 | |
148 | ||
2e0e5271 | 149 | /* |
dd7c7200 PB |
150 | * The caches are probably in an indeterminate state, so we force good |
151 | * parity into them by doing an invalidate for each line. If | |
152 | * CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD is set then we'll proceed to | |
153 | * perform a load/fill & a further invalidate for each line, assuming | |
154 | * that the bottom of RAM (having just been cleared) will generate good | |
155 | * parity for the cache. | |
c021880a WD |
156 | */ |
157 | ||
2e0e5271 SK |
158 | /* |
159 | * Initialize the I-cache first, | |
c021880a | 160 | */ |
ca4e833c | 161 | blez t2, 1f |
ca4e833c PB |
162 | PTR_LI t0, INDEX_BASE |
163 | PTR_ADDU t1, t0, t2 | |
164 | /* clear tag to invalidate */ | |
165 | cache_loop t0, t1, t8, INDEX_STORE_TAG_I | |
dd7c7200 | 166 | #ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD |
ca4e833c PB |
167 | /* fill once, so data field parity is correct */ |
168 | PTR_LI t0, INDEX_BASE | |
169 | cache_loop t0, t1, t8, FILL | |
170 | /* invalidate again - prudent but not strictly neccessary */ | |
171 | PTR_LI t0, INDEX_BASE | |
172 | cache_loop t0, t1, t8, INDEX_STORE_TAG_I | |
dd7c7200 | 173 | #endif |
c021880a | 174 | |
2e0e5271 SK |
175 | /* |
176 | * then initialize D-cache. | |
c021880a | 177 | */ |
ca4e833c | 178 | 1: blez t3, 3f |
ca4e833c PB |
179 | PTR_LI t0, INDEX_BASE |
180 | PTR_ADDU t1, t0, t3 | |
181 | /* clear all tags */ | |
182 | cache_loop t0, t1, t9, INDEX_STORE_TAG_D | |
dd7c7200 | 183 | #ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD |
ca4e833c PB |
184 | /* load from each line (in cached space) */ |
185 | PTR_LI t0, INDEX_BASE | |
186 | 2: LONG_L zero, 0(t0) | |
187 | PTR_ADDU t0, t9 | |
188 | bne t0, t1, 2b | |
189 | /* clear all tags */ | |
190 | PTR_LI t0, INDEX_BASE | |
191 | cache_loop t0, t1, t9, INDEX_STORE_TAG_D | |
dd7c7200 | 192 | #endif |
c021880a | 193 | |
ca4e833c | 194 | 3: jr ra |
2f5d414c | 195 | END(mips_cache_reset) |
c021880a | 196 | |
7aa1f198 SK |
197 | /* |
198 | * dcache_status - get cache status | |
199 | * | |
200 | * RETURNS: 0 - cache disabled; 1 - cache enabled | |
201 | * | |
202 | */ | |
2f5d414c | 203 | LEAF(dcache_status) |
d98e348e SK |
204 | mfc0 t0, CP0_CONFIG |
205 | li t1, CONF_CM_UNCACHED | |
206 | andi t0, t0, CONF_CM_CMASK | |
207 | move v0, zero | |
208 | beq t0, t1, 2f | |
209 | li v0, 1 | |
210 | 2: jr ra | |
2f5d414c | 211 | END(dcache_status) |
c021880a | 212 | |
7aa1f198 SK |
213 | /* |
214 | * dcache_disable - disable cache | |
215 | * | |
216 | * RETURNS: N/A | |
217 | * | |
218 | */ | |
2f5d414c | 219 | LEAF(dcache_disable) |
c021880a WD |
220 | mfc0 t0, CP0_CONFIG |
221 | li t1, -8 | |
222 | and t0, t0, t1 | |
223 | ori t0, t0, CONF_CM_UNCACHED | |
03c031d5 | 224 | mtc0 t0, CP0_CONFIG |
43c50925 | 225 | jr ra |
2f5d414c | 226 | END(dcache_disable) |
c021880a | 227 | |
7aa1f198 SK |
228 | /* |
229 | * dcache_enable - enable cache | |
230 | * | |
231 | * RETURNS: N/A | |
232 | * | |
233 | */ | |
ea638951 SK |
234 | LEAF(dcache_enable) |
235 | mfc0 t0, CP0_CONFIG | |
236 | ori t0, CONF_CM_CMASK | |
237 | xori t0, CONF_CM_CMASK | |
979cfeaf | 238 | ori t0, CONFIG_SYS_MIPS_CACHE_MODE |
ea638951 SK |
239 | mtc0 t0, CP0_CONFIG |
240 | jr ra | |
241 | END(dcache_enable) |