wdenk | bb1b826 | 2003-03-27 12:09:35 +0000 | [diff] [blame] | 1 | /* |
Shinya Kuribayashi | 396aa80 | 2008-03-25 21:30:07 +0900 | [diff] [blame] | 2 | * Cache-handling routined for MIPS CPUs |
wdenk | bb1b826 | 2003-03-27 12:09:35 +0000 | [diff] [blame] | 3 | * |
| 4 | * Copyright (c) 2003 Wolfgang Denk <wd@denx.de> |
| 5 | * |
Wolfgang Denk | d79de1d | 2013-07-08 09:37:19 +0200 | [diff] [blame] | 6 | * SPDX-License-Identifier: GPL-2.0+ |
wdenk | bb1b826 | 2003-03-27 12:09:35 +0000 | [diff] [blame] | 7 | */ |
| 8 | |
Wolfgang Denk | 0191e47 | 2010-10-26 14:34:52 +0200 | [diff] [blame] | 9 | #include <asm-offsets.h> |
wdenk | bb1b826 | 2003-03-27 12:09:35 +0000 | [diff] [blame] | 10 | #include <config.h> |
Shinya Kuribayashi | 0622212 | 2008-03-25 21:30:06 +0900 | [diff] [blame] | 11 | #include <asm/asm.h> |
wdenk | bb1b826 | 2003-03-27 12:09:35 +0000 | [diff] [blame] | 12 | #include <asm/regdef.h> |
| 13 | #include <asm/mipsregs.h> |
| 14 | #include <asm/addrspace.h> |
| 15 | #include <asm/cacheops.h> |
Paul Burton | 8156078 | 2016-09-21 11:18:54 +0100 | [diff] [blame] | 16 | #include <asm/cm.h> |
wdenk | bb1b826 | 2003-03-27 12:09:35 +0000 | [diff] [blame] | 17 | |
Daniel Schwierzeck | 9adc190 | 2012-04-02 02:57:55 +0000 | [diff] [blame] | 18 | #ifndef CONFIG_SYS_MIPS_CACHE_MODE |
| 19 | #define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT |
| 20 | #endif |
| 21 | |
Shinya Kuribayashi | 6c6b261 | 2008-06-05 22:29:00 +0900 | [diff] [blame] | 22 | #define INDEX_BASE CKSEG0 |
Shinya Kuribayashi | 5bb51af | 2008-03-25 21:30:06 +0900 | [diff] [blame] | 23 | |
Shinya Kuribayashi | 52c27e6 | 2008-03-25 21:30:06 +0900 | [diff] [blame] | 24 | .macro f_fill64 dst, offset, val |
| 25 | LONG_S \val, (\offset + 0 * LONGSIZE)(\dst) |
| 26 | LONG_S \val, (\offset + 1 * LONGSIZE)(\dst) |
| 27 | LONG_S \val, (\offset + 2 * LONGSIZE)(\dst) |
| 28 | LONG_S \val, (\offset + 3 * LONGSIZE)(\dst) |
| 29 | LONG_S \val, (\offset + 4 * LONGSIZE)(\dst) |
| 30 | LONG_S \val, (\offset + 5 * LONGSIZE)(\dst) |
| 31 | LONG_S \val, (\offset + 6 * LONGSIZE)(\dst) |
| 32 | LONG_S \val, (\offset + 7 * LONGSIZE)(\dst) |
| 33 | #if LONGSIZE == 4 |
| 34 | LONG_S \val, (\offset + 8 * LONGSIZE)(\dst) |
| 35 | LONG_S \val, (\offset + 9 * LONGSIZE)(\dst) |
| 36 | LONG_S \val, (\offset + 10 * LONGSIZE)(\dst) |
| 37 | LONG_S \val, (\offset + 11 * LONGSIZE)(\dst) |
| 38 | LONG_S \val, (\offset + 12 * LONGSIZE)(\dst) |
| 39 | LONG_S \val, (\offset + 13 * LONGSIZE)(\dst) |
| 40 | LONG_S \val, (\offset + 14 * LONGSIZE)(\dst) |
| 41 | LONG_S \val, (\offset + 15 * LONGSIZE)(\dst) |
| 42 | #endif |
| 43 | .endm |
| 44 | |
Paul Burton | d878cc2 | 2015-01-29 01:28:00 +0000 | [diff] [blame] | 45 | .macro cache_loop curr, end, line_sz, op |
| 46 | 10: cache \op, 0(\curr) |
| 47 | PTR_ADDU \curr, \curr, \line_sz |
| 48 | bne \curr, \end, 10b |
| 49 | .endm |
| 50 | |
Paul Burton | edf1f85 | 2015-01-29 01:27:59 +0000 | [diff] [blame] | 51 | .macro l1_info sz, line_sz, off |
| 52 | .set push |
| 53 | .set noat |
| 54 | |
| 55 | mfc0 $1, CP0_CONFIG, 1 |
| 56 | |
| 57 | /* detect line size */ |
Daniel Schwierzeck | a6dae71 | 2016-01-12 21:48:26 +0100 | [diff] [blame] | 58 | srl \line_sz, $1, \off + MIPS_CONF1_DL_SHF - MIPS_CONF1_DA_SHF |
| 59 | andi \line_sz, \line_sz, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHF) |
Paul Burton | edf1f85 | 2015-01-29 01:27:59 +0000 | [diff] [blame] | 60 | move \sz, zero |
| 61 | beqz \line_sz, 10f |
| 62 | li \sz, 2 |
| 63 | sllv \line_sz, \sz, \line_sz |
| 64 | |
| 65 | /* detect associativity */ |
Daniel Schwierzeck | a6dae71 | 2016-01-12 21:48:26 +0100 | [diff] [blame] | 66 | srl \sz, $1, \off + MIPS_CONF1_DA_SHF - MIPS_CONF1_DA_SHF |
| 67 | andi \sz, \sz, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHF) |
Paul Burton | 53c9826 | 2016-05-16 10:52:10 +0100 | [diff] [blame] | 68 | addiu \sz, \sz, 1 |
Paul Burton | edf1f85 | 2015-01-29 01:27:59 +0000 | [diff] [blame] | 69 | |
| 70 | /* sz *= line_sz */ |
| 71 | mul \sz, \sz, \line_sz |
| 72 | |
| 73 | /* detect log32(sets) */ |
Daniel Schwierzeck | a6dae71 | 2016-01-12 21:48:26 +0100 | [diff] [blame] | 74 | srl $1, $1, \off + MIPS_CONF1_DS_SHF - MIPS_CONF1_DA_SHF |
| 75 | andi $1, $1, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHF) |
Paul Burton | edf1f85 | 2015-01-29 01:27:59 +0000 | [diff] [blame] | 76 | addiu $1, $1, 1 |
| 77 | andi $1, $1, 0x7 |
| 78 | |
| 79 | /* sz <<= log32(sets) */ |
| 80 | sllv \sz, \sz, $1 |
| 81 | |
| 82 | /* sz *= 32 */ |
| 83 | li $1, 32 |
| 84 | mul \sz, \sz, $1 |
| 85 | 10: |
| 86 | .set pop |
| 87 | .endm |
Shinya Kuribayashi | 6911d0a | 2011-05-07 00:18:13 +0900 | [diff] [blame] | 88 | /* |
| 89 | * mips_cache_reset - low level initialisation of the primary caches |
| 90 | * |
| 91 | * This routine initialises the primary caches to ensure that they have good |
| 92 | * parity. It must be called by the ROM before any cached locations are used |
| 93 | * to prevent the possibility of data with bad parity being written to memory. |
| 94 | * |
| 95 | * To initialise the instruction cache it is essential that a source of data |
| 96 | * with good parity is available. This routine will initialise an area of |
| 97 | * memory starting at location zero to be used as a source of parity. |
| 98 | * |
Paul Burton | 8156078 | 2016-09-21 11:18:54 +0100 | [diff] [blame] | 99 | * Note that this function does not follow the standard calling convention & |
| 100 | * may clobber typically callee-saved registers. |
| 101 | * |
Shinya Kuribayashi | 6911d0a | 2011-05-07 00:18:13 +0900 | [diff] [blame] | 102 | * RETURNS: N/A |
| 103 | * |
| 104 | */ |
Paul Burton | 8156078 | 2016-09-21 11:18:54 +0100 | [diff] [blame] | 105 | #define R_RETURN s0 |
| 106 | #define R_IC_SIZE s1 |
| 107 | #define R_IC_LINE s2 |
| 108 | #define R_DC_SIZE s3 |
| 109 | #define R_DC_LINE s4 |
| 110 | #define R_L2_SIZE s5 |
| 111 | #define R_L2_LINE s6 |
| 112 | #define R_L2_BYPASSED s7 |
| 113 | #define R_L2_L2C t8 |
Paul Burton | ca41a03 | 2015-01-29 01:28:01 +0000 | [diff] [blame] | 114 | LEAF(mips_cache_reset) |
Paul Burton | 8156078 | 2016-09-21 11:18:54 +0100 | [diff] [blame] | 115 | move R_RETURN, ra |
| 116 | |
| 117 | #ifdef CONFIG_MIPS_L2_CACHE |
| 118 | /* |
| 119 | * For there to be an L2 present, Config2 must be present. If it isn't |
| 120 | * then we proceed knowing there's no L2 cache. |
| 121 | */ |
| 122 | move R_L2_SIZE, zero |
| 123 | move R_L2_LINE, zero |
| 124 | move R_L2_BYPASSED, zero |
| 125 | move R_L2_L2C, zero |
| 126 | mfc0 t0, CP0_CONFIG, 1 |
| 127 | bgez t0, l2_probe_done |
| 128 | |
| 129 | /* |
| 130 | * From MIPSr6 onwards the L2 cache configuration might not be reported |
| 131 | * by Config2. The Config5.L2C bit indicates whether this is the case, |
| 132 | * and if it is then we need knowledge of where else to look. For cores |
| 133 | * from Imagination Technologies this is a CM GCR. |
| 134 | */ |
| 135 | # if __mips_isa_rev >= 6 |
| 136 | /* Check that Config5 exists */ |
| 137 | mfc0 t0, CP0_CONFIG, 2 |
| 138 | bgez t0, l2_probe_cop0 |
| 139 | mfc0 t0, CP0_CONFIG, 3 |
| 140 | bgez t0, l2_probe_cop0 |
| 141 | mfc0 t0, CP0_CONFIG, 4 |
| 142 | bgez t0, l2_probe_cop0 |
| 143 | |
| 144 | /* Check Config5.L2C is set */ |
| 145 | mfc0 t0, CP0_CONFIG, 5 |
| 146 | and R_L2_L2C, t0, MIPS_CONF5_L2C |
| 147 | beqz R_L2_L2C, l2_probe_cop0 |
| 148 | |
| 149 | /* Config5.L2C is set */ |
| 150 | # ifdef CONFIG_MIPS_CM |
| 151 | /* The CM will provide L2 configuration */ |
| 152 | PTR_LI t0, CKSEG1ADDR(CONFIG_MIPS_CM_BASE) |
| 153 | lw t1, GCR_L2_CONFIG(t0) |
| 154 | bgez t1, l2_probe_done |
| 155 | |
| 156 | ext R_L2_LINE, t1, \ |
| 157 | GCR_L2_CONFIG_LINESZ_SHIFT, GCR_L2_CONFIG_LINESZ_BITS |
| 158 | beqz R_L2_LINE, l2_probe_done |
| 159 | li t2, 2 |
| 160 | sllv R_L2_LINE, t2, R_L2_LINE |
| 161 | |
| 162 | ext t2, t1, GCR_L2_CONFIG_ASSOC_SHIFT, GCR_L2_CONFIG_ASSOC_BITS |
| 163 | addiu t2, t2, 1 |
| 164 | mul R_L2_SIZE, R_L2_LINE, t2 |
| 165 | |
| 166 | ext t2, t1, GCR_L2_CONFIG_SETSZ_SHIFT, GCR_L2_CONFIG_SETSZ_BITS |
| 167 | sllv R_L2_SIZE, R_L2_SIZE, t2 |
| 168 | li t2, 64 |
| 169 | mul R_L2_SIZE, R_L2_SIZE, t2 |
| 170 | |
| 171 | /* Bypass the L2 cache so that we can init the L1s early */ |
| 172 | or t1, t1, GCR_L2_CONFIG_BYPASS |
| 173 | sw t1, GCR_L2_CONFIG(t0) |
| 174 | sync |
| 175 | li R_L2_BYPASSED, 1 |
| 176 | |
| 177 | /* Zero the L2 tag registers */ |
| 178 | sw zero, GCR_L2_TAG_ADDR(t0) |
| 179 | sw zero, GCR_L2_TAG_ADDR_UPPER(t0) |
| 180 | sw zero, GCR_L2_TAG_STATE(t0) |
| 181 | sw zero, GCR_L2_TAG_STATE_UPPER(t0) |
| 182 | sw zero, GCR_L2_DATA(t0) |
| 183 | sw zero, GCR_L2_DATA_UPPER(t0) |
| 184 | sync |
| 185 | # else |
| 186 | /* We don't know how to retrieve L2 configuration on this system */ |
| 187 | # endif |
| 188 | b l2_probe_done |
| 189 | # endif |
| 190 | |
| 191 | /* |
| 192 | * For pre-r6 systems, or r6 systems with Config5.L2C==0, probe the L2 |
| 193 | * cache configuration from the cop0 Config2 register. |
| 194 | */ |
| 195 | l2_probe_cop0: |
| 196 | mfc0 t0, CP0_CONFIG, 2 |
| 197 | |
| 198 | srl R_L2_LINE, t0, MIPS_CONF2_SL_SHF |
| 199 | andi R_L2_LINE, R_L2_LINE, MIPS_CONF2_SL >> MIPS_CONF2_SL_SHF |
| 200 | beqz R_L2_LINE, l2_probe_done |
| 201 | li t1, 2 |
| 202 | sllv R_L2_LINE, t1, R_L2_LINE |
| 203 | |
| 204 | srl t1, t0, MIPS_CONF2_SA_SHF |
| 205 | andi t1, t1, MIPS_CONF2_SA >> MIPS_CONF2_SA_SHF |
| 206 | addiu t1, t1, 1 |
| 207 | mul R_L2_SIZE, R_L2_LINE, t1 |
| 208 | |
| 209 | srl t1, t0, MIPS_CONF2_SS_SHF |
| 210 | andi t1, t1, MIPS_CONF2_SS >> MIPS_CONF2_SS_SHF |
| 211 | sllv R_L2_SIZE, R_L2_SIZE, t1 |
| 212 | li t1, 64 |
| 213 | mul R_L2_SIZE, R_L2_SIZE, t1 |
| 214 | |
| 215 | /* Attempt to bypass the L2 so that we can init the L1s early */ |
| 216 | or t0, t0, MIPS_CONF2_L2B |
| 217 | mtc0 t0, CP0_CONFIG, 2 |
| 218 | ehb |
| 219 | mfc0 t0, CP0_CONFIG, 2 |
| 220 | and R_L2_BYPASSED, t0, MIPS_CONF2_L2B |
| 221 | |
| 222 | /* Zero the L2 tag registers */ |
| 223 | mtc0 zero, CP0_TAGLO, 4 |
| 224 | ehb |
| 225 | l2_probe_done: |
| 226 | #endif |
| 227 | |
Paul Burton | 5e51142 | 2016-05-27 14:28:04 +0100 | [diff] [blame] | 228 | #ifndef CONFIG_SYS_CACHE_SIZE_AUTO |
Paul Burton | f868be5 | 2016-09-21 11:18:52 +0100 | [diff] [blame] | 229 | li R_IC_SIZE, CONFIG_SYS_ICACHE_SIZE |
| 230 | li R_IC_LINE, CONFIG_SYS_ICACHE_LINE_SIZE |
Paul Burton | f122b5a | 2013-11-08 11:18:42 +0000 | [diff] [blame] | 231 | #else |
Paul Burton | f868be5 | 2016-09-21 11:18:52 +0100 | [diff] [blame] | 232 | l1_info R_IC_SIZE, R_IC_LINE, MIPS_CONF1_IA_SHF |
Paul Burton | f122b5a | 2013-11-08 11:18:42 +0000 | [diff] [blame] | 233 | #endif |
| 234 | |
Paul Burton | 5e51142 | 2016-05-27 14:28:04 +0100 | [diff] [blame] | 235 | #ifndef CONFIG_SYS_CACHE_SIZE_AUTO |
Paul Burton | f868be5 | 2016-09-21 11:18:52 +0100 | [diff] [blame] | 236 | li R_DC_SIZE, CONFIG_SYS_DCACHE_SIZE |
| 237 | li R_DC_LINE, CONFIG_SYS_DCACHE_LINE_SIZE |
Paul Burton | f122b5a | 2013-11-08 11:18:42 +0000 | [diff] [blame] | 238 | #else |
Paul Burton | f868be5 | 2016-09-21 11:18:52 +0100 | [diff] [blame] | 239 | l1_info R_DC_SIZE, R_DC_LINE, MIPS_CONF1_DA_SHF |
Paul Burton | f122b5a | 2013-11-08 11:18:42 +0000 | [diff] [blame] | 240 | #endif |
| 241 | |
Paul Burton | 6832bdc | 2015-01-29 01:28:02 +0000 | [diff] [blame] | 242 | #ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD |
| 243 | |
Paul Burton | f122b5a | 2013-11-08 11:18:42 +0000 | [diff] [blame] | 244 | /* Determine the largest L1 cache size */ |
Paul Burton | 5e51142 | 2016-05-27 14:28:04 +0100 | [diff] [blame] | 245 | #ifndef CONFIG_SYS_CACHE_SIZE_AUTO |
Paul Burton | f122b5a | 2013-11-08 11:18:42 +0000 | [diff] [blame] | 246 | #if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE |
| 247 | li v0, CONFIG_SYS_ICACHE_SIZE |
| 248 | #else |
| 249 | li v0, CONFIG_SYS_DCACHE_SIZE |
| 250 | #endif |
| 251 | #else |
Paul Burton | f868be5 | 2016-09-21 11:18:52 +0100 | [diff] [blame] | 252 | move v0, R_IC_SIZE |
| 253 | sltu t1, R_IC_SIZE, R_DC_SIZE |
| 254 | movn v0, R_DC_SIZE, t1 |
Paul Burton | f122b5a | 2013-11-08 11:18:42 +0000 | [diff] [blame] | 255 | #endif |
Shinya Kuribayashi | 52c27e6 | 2008-03-25 21:30:06 +0900 | [diff] [blame] | 256 | /* |
| 257 | * Now clear that much memory starting from zero. |
wdenk | bb1b826 | 2003-03-27 12:09:35 +0000 | [diff] [blame] | 258 | */ |
Shinya Kuribayashi | 6c6b261 | 2008-06-05 22:29:00 +0900 | [diff] [blame] | 259 | PTR_LI a0, CKSEG1 |
Shinya Kuribayashi | 52c27e6 | 2008-03-25 21:30:06 +0900 | [diff] [blame] | 260 | PTR_ADDU a1, a0, v0 |
| 261 | 2: PTR_ADDIU a0, 64 |
| 262 | f_fill64 a0, -64, zero |
| 263 | bne a0, a1, 2b |
wdenk | 57b2d80 | 2003-06-27 21:31:46 +0000 | [diff] [blame] | 264 | |
Paul Burton | 6832bdc | 2015-01-29 01:28:02 +0000 | [diff] [blame] | 265 | #endif /* CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD */ |
wdenk | bb1b826 | 2003-03-27 12:09:35 +0000 | [diff] [blame] | 266 | |
Paul Burton | 8156078 | 2016-09-21 11:18:54 +0100 | [diff] [blame] | 267 | #ifdef CONFIG_MIPS_L2_CACHE |
| 268 | /* |
| 269 | * If the L2 is bypassed, init the L1 first so that we can execute the |
| 270 | * rest of the cache initialisation using the L1 instruction cache. |
| 271 | */ |
| 272 | bnez R_L2_BYPASSED, l1_init |
| 273 | |
| 274 | l2_init: |
| 275 | PTR_LI t0, INDEX_BASE |
| 276 | PTR_ADDU t1, t0, R_L2_SIZE |
| 277 | 1: cache INDEX_STORE_TAG_SD, 0(t0) |
| 278 | PTR_ADDU t0, t0, R_L2_LINE |
| 279 | bne t0, t1, 1b |
| 280 | |
| 281 | /* |
| 282 | * If the L2 was bypassed then we already initialised the L1s before |
| 283 | * the L2, so we are now done. |
| 284 | */ |
| 285 | bnez R_L2_BYPASSED, l2_unbypass |
| 286 | #endif |
| 287 | |
Shinya Kuribayashi | 5bb51af | 2008-03-25 21:30:06 +0900 | [diff] [blame] | 288 | /* |
Paul Burton | 69acad0 | 2015-01-29 01:28:03 +0000 | [diff] [blame] | 289 | * The TagLo registers used depend upon the CPU implementation, but the |
| 290 | * architecture requires that it is safe for software to write to both |
| 291 | * TagLo selects 0 & 2 covering supported cases. |
| 292 | */ |
Paul Burton | 8156078 | 2016-09-21 11:18:54 +0100 | [diff] [blame] | 293 | l1_init: |
Paul Burton | 69acad0 | 2015-01-29 01:28:03 +0000 | [diff] [blame] | 294 | mtc0 zero, CP0_TAGLO |
| 295 | mtc0 zero, CP0_TAGLO, 2 |
Paul Burton | ac8668a | 2016-09-21 11:18:58 +0100 | [diff] [blame] | 296 | ehb |
Paul Burton | 69acad0 | 2015-01-29 01:28:03 +0000 | [diff] [blame] | 297 | |
| 298 | /* |
Paul Burton | 6832bdc | 2015-01-29 01:28:02 +0000 | [diff] [blame] | 299 | * The caches are probably in an indeterminate state, so we force good |
| 300 | * parity into them by doing an invalidate for each line. If |
| 301 | * CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD is set then we'll proceed to |
| 302 | * perform a load/fill & a further invalidate for each line, assuming |
| 303 | * that the bottom of RAM (having just been cleared) will generate good |
| 304 | * parity for the cache. |
wdenk | bb1b826 | 2003-03-27 12:09:35 +0000 | [diff] [blame] | 305 | */ |
| 306 | |
Shinya Kuribayashi | 5bb51af | 2008-03-25 21:30:06 +0900 | [diff] [blame] | 307 | /* |
| 308 | * Initialize the I-cache first, |
wdenk | bb1b826 | 2003-03-27 12:09:35 +0000 | [diff] [blame] | 309 | */ |
Paul Burton | f868be5 | 2016-09-21 11:18:52 +0100 | [diff] [blame] | 310 | blez R_IC_SIZE, 1f |
Paul Burton | ca41a03 | 2015-01-29 01:28:01 +0000 | [diff] [blame] | 311 | PTR_LI t0, INDEX_BASE |
Paul Burton | f868be5 | 2016-09-21 11:18:52 +0100 | [diff] [blame] | 312 | PTR_ADDU t1, t0, R_IC_SIZE |
Paul Burton | ca41a03 | 2015-01-29 01:28:01 +0000 | [diff] [blame] | 313 | /* clear tag to invalidate */ |
Paul Burton | f868be5 | 2016-09-21 11:18:52 +0100 | [diff] [blame] | 314 | cache_loop t0, t1, R_IC_LINE, INDEX_STORE_TAG_I |
Paul Burton | 6832bdc | 2015-01-29 01:28:02 +0000 | [diff] [blame] | 315 | #ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD |
Paul Burton | ca41a03 | 2015-01-29 01:28:01 +0000 | [diff] [blame] | 316 | /* fill once, so data field parity is correct */ |
| 317 | PTR_LI t0, INDEX_BASE |
Paul Burton | f868be5 | 2016-09-21 11:18:52 +0100 | [diff] [blame] | 318 | cache_loop t0, t1, R_IC_LINE, FILL |
Paul Burton | ca41a03 | 2015-01-29 01:28:01 +0000 | [diff] [blame] | 319 | /* invalidate again - prudent but not strictly neccessary */ |
| 320 | PTR_LI t0, INDEX_BASE |
Paul Burton | f868be5 | 2016-09-21 11:18:52 +0100 | [diff] [blame] | 321 | cache_loop t0, t1, R_IC_LINE, INDEX_STORE_TAG_I |
Paul Burton | 6832bdc | 2015-01-29 01:28:02 +0000 | [diff] [blame] | 322 | #endif |
wdenk | bb1b826 | 2003-03-27 12:09:35 +0000 | [diff] [blame] | 323 | |
Paul Burton | 8c57b04 | 2016-09-21 11:18:49 +0100 | [diff] [blame] | 324 | /* Enable use of the I-cache by setting Config.K0 */ |
| 325 | sync |
| 326 | mfc0 t0, CP0_CONFIG |
| 327 | li t1, CONFIG_SYS_MIPS_CACHE_MODE |
| 328 | #if __mips_isa_rev >= 2 |
| 329 | ins t0, t1, 0, 3 |
| 330 | #else |
| 331 | ori t0, t0, CONF_CM_CMASK |
| 332 | xori t0, t0, CONF_CM_CMASK |
| 333 | or t0, t0, t1 |
| 334 | #endif |
| 335 | mtc0 t0, CP0_CONFIG |
| 336 | |
Shinya Kuribayashi | 5bb51af | 2008-03-25 21:30:06 +0900 | [diff] [blame] | 337 | /* |
| 338 | * then initialize D-cache. |
wdenk | bb1b826 | 2003-03-27 12:09:35 +0000 | [diff] [blame] | 339 | */ |
Paul Burton | f868be5 | 2016-09-21 11:18:52 +0100 | [diff] [blame] | 340 | 1: blez R_DC_SIZE, 3f |
Paul Burton | ca41a03 | 2015-01-29 01:28:01 +0000 | [diff] [blame] | 341 | PTR_LI t0, INDEX_BASE |
Paul Burton | f868be5 | 2016-09-21 11:18:52 +0100 | [diff] [blame] | 342 | PTR_ADDU t1, t0, R_DC_SIZE |
Paul Burton | ca41a03 | 2015-01-29 01:28:01 +0000 | [diff] [blame] | 343 | /* clear all tags */ |
Paul Burton | f868be5 | 2016-09-21 11:18:52 +0100 | [diff] [blame] | 344 | cache_loop t0, t1, R_DC_LINE, INDEX_STORE_TAG_D |
Paul Burton | 6832bdc | 2015-01-29 01:28:02 +0000 | [diff] [blame] | 345 | #ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD |
Paul Burton | ca41a03 | 2015-01-29 01:28:01 +0000 | [diff] [blame] | 346 | /* load from each line (in cached space) */ |
| 347 | PTR_LI t0, INDEX_BASE |
| 348 | 2: LONG_L zero, 0(t0) |
Paul Burton | f868be5 | 2016-09-21 11:18:52 +0100 | [diff] [blame] | 349 | PTR_ADDU t0, R_DC_LINE |
Paul Burton | ca41a03 | 2015-01-29 01:28:01 +0000 | [diff] [blame] | 350 | bne t0, t1, 2b |
| 351 | /* clear all tags */ |
| 352 | PTR_LI t0, INDEX_BASE |
Paul Burton | f868be5 | 2016-09-21 11:18:52 +0100 | [diff] [blame] | 353 | cache_loop t0, t1, R_DC_LINE, INDEX_STORE_TAG_D |
Paul Burton | 6832bdc | 2015-01-29 01:28:02 +0000 | [diff] [blame] | 354 | #endif |
Paul Burton | 8156078 | 2016-09-21 11:18:54 +0100 | [diff] [blame] | 355 | 3: |
| 356 | |
| 357 | #ifdef CONFIG_MIPS_L2_CACHE |
| 358 | /* If the L2 isn't bypassed then we're done */ |
| 359 | beqz R_L2_BYPASSED, return |
| 360 | |
| 361 | /* The L2 is bypassed - go initialise it */ |
| 362 | b l2_init |
| 363 | |
| 364 | l2_unbypass: |
| 365 | # if __mips_isa_rev >= 6 |
| 366 | beqz R_L2_L2C, 1f |
| 367 | |
| 368 | li t0, CKSEG1ADDR(CONFIG_MIPS_CM_BASE) |
| 369 | lw t1, GCR_L2_CONFIG(t0) |
| 370 | xor t1, t1, GCR_L2_CONFIG_BYPASS |
| 371 | sw t1, GCR_L2_CONFIG(t0) |
| 372 | sync |
| 373 | ehb |
| 374 | b 2f |
| 375 | # endif |
| 376 | 1: mfc0 t0, CP0_CONFIG, 2 |
| 377 | xor t0, t0, MIPS_CONF2_L2B |
| 378 | mtc0 t0, CP0_CONFIG, 2 |
| 379 | ehb |
| 380 | |
| 381 | 2: |
Paul Burton | a8b8bd2 | 2016-09-21 11:18:55 +0100 | [diff] [blame] | 382 | # ifdef CONFIG_MIPS_CM |
| 383 | /* Config3 must exist for a CM to be present */ |
| 384 | mfc0 t0, CP0_CONFIG, 1 |
| 385 | bgez t0, 2f |
| 386 | mfc0 t0, CP0_CONFIG, 2 |
| 387 | bgez t0, 2f |
| 388 | |
| 389 | /* Check Config3.CMGCR to determine CM presence */ |
| 390 | mfc0 t0, CP0_CONFIG, 3 |
| 391 | and t0, t0, MIPS_CONF3_CMGCR |
| 392 | beqz t0, 2f |
| 393 | |
| 394 | /* Change Config.K0 to a coherent CCA */ |
| 395 | mfc0 t0, CP0_CONFIG |
| 396 | li t1, CONF_CM_CACHABLE_COW |
| 397 | #if __mips_isa_rev >= 2 |
| 398 | ins t0, t1, 0, 3 |
| 399 | #else |
| 400 | ori t0, t0, CONF_CM_CMASK |
| 401 | xori t0, t0, CONF_CM_CMASK |
| 402 | or t0, t0, t1 |
| 403 | #endif |
| 404 | mtc0 t0, CP0_CONFIG |
| 405 | |
| 406 | /* |
| 407 | * Join the coherent domain such that the caches of this core are kept |
| 408 | * coherent with those of other cores. |
| 409 | */ |
| 410 | PTR_LI t0, CKSEG1ADDR(CONFIG_MIPS_CM_BASE) |
| 411 | lw t1, GCR_REV(t0) |
| 412 | li t2, GCR_REV_CM3 |
| 413 | li t3, GCR_Cx_COHERENCE_EN |
| 414 | bge t1, t2, 1f |
| 415 | li t3, GCR_Cx_COHERENCE_DOM_EN |
| 416 | 1: sw t3, GCR_Cx_COHERENCE(t0) |
| 417 | ehb |
| 418 | 2: |
| 419 | # endif |
Paul Burton | 8156078 | 2016-09-21 11:18:54 +0100 | [diff] [blame] | 420 | #endif |
wdenk | bb1b826 | 2003-03-27 12:09:35 +0000 | [diff] [blame] | 421 | |
Paul Burton | 8156078 | 2016-09-21 11:18:54 +0100 | [diff] [blame] | 422 | return: |
Paul Burton | 0286885 | 2016-09-21 11:18:59 +0100 | [diff] [blame] | 423 | /* Ensure all cache operations complete before returning */ |
| 424 | sync |
Paul Burton | 8156078 | 2016-09-21 11:18:54 +0100 | [diff] [blame] | 425 | jr ra |
Shinya Kuribayashi | 0622212 | 2008-03-25 21:30:06 +0900 | [diff] [blame] | 426 | END(mips_cache_reset) |
wdenk | bb1b826 | 2003-03-27 12:09:35 +0000 | [diff] [blame] | 427 | |
Shinya Kuribayashi | 6911d0a | 2011-05-07 00:18:13 +0900 | [diff] [blame] | 428 | /* |
| 429 | * dcache_status - get cache status |
| 430 | * |
| 431 | * RETURNS: 0 - cache disabled; 1 - cache enabled |
| 432 | * |
| 433 | */ |
Shinya Kuribayashi | 0622212 | 2008-03-25 21:30:06 +0900 | [diff] [blame] | 434 | LEAF(dcache_status) |
Shinya Kuribayashi | 3bdce4f | 2008-03-25 21:30:07 +0900 | [diff] [blame] | 435 | mfc0 t0, CP0_CONFIG |
| 436 | li t1, CONF_CM_UNCACHED |
| 437 | andi t0, t0, CONF_CM_CMASK |
| 438 | move v0, zero |
| 439 | beq t0, t1, 2f |
| 440 | li v0, 1 |
| 441 | 2: jr ra |
Shinya Kuribayashi | 0622212 | 2008-03-25 21:30:06 +0900 | [diff] [blame] | 442 | END(dcache_status) |
wdenk | bb1b826 | 2003-03-27 12:09:35 +0000 | [diff] [blame] | 443 | |
Shinya Kuribayashi | 6911d0a | 2011-05-07 00:18:13 +0900 | [diff] [blame] | 444 | /* |
| 445 | * dcache_disable - disable cache |
| 446 | * |
| 447 | * RETURNS: N/A |
| 448 | * |
| 449 | */ |
Shinya Kuribayashi | 0622212 | 2008-03-25 21:30:06 +0900 | [diff] [blame] | 450 | LEAF(dcache_disable) |
wdenk | bb1b826 | 2003-03-27 12:09:35 +0000 | [diff] [blame] | 451 | mfc0 t0, CP0_CONFIG |
| 452 | li t1, -8 |
| 453 | and t0, t0, t1 |
| 454 | ori t0, t0, CONF_CM_UNCACHED |
Shinya Kuribayashi | c7faac5 | 2007-10-27 15:27:06 +0900 | [diff] [blame] | 455 | mtc0 t0, CP0_CONFIG |
Shinya Kuribayashi | 9dabea1 | 2008-04-17 23:35:13 +0900 | [diff] [blame] | 456 | jr ra |
Shinya Kuribayashi | 0622212 | 2008-03-25 21:30:06 +0900 | [diff] [blame] | 457 | END(dcache_disable) |
wdenk | bb1b826 | 2003-03-27 12:09:35 +0000 | [diff] [blame] | 458 | |
Shinya Kuribayashi | 6911d0a | 2011-05-07 00:18:13 +0900 | [diff] [blame] | 459 | /* |
| 460 | * dcache_enable - enable cache |
| 461 | * |
| 462 | * RETURNS: N/A |
| 463 | * |
| 464 | */ |
Shinya Kuribayashi | 4d0e2c9 | 2008-05-03 13:51:28 +0900 | [diff] [blame] | 465 | LEAF(dcache_enable) |
| 466 | mfc0 t0, CP0_CONFIG |
| 467 | ori t0, CONF_CM_CMASK |
| 468 | xori t0, CONF_CM_CMASK |
Daniel Schwierzeck | 9adc190 | 2012-04-02 02:57:55 +0000 | [diff] [blame] | 469 | ori t0, CONFIG_SYS_MIPS_CACHE_MODE |
Shinya Kuribayashi | 4d0e2c9 | 2008-05-03 13:51:28 +0900 | [diff] [blame] | 470 | mtc0 t0, CP0_CONFIG |
| 471 | jr ra |
| 472 | END(dcache_enable) |