1/* 2 * Cache-handling routined for MIPS CPUs 3 * 4 * Copyright (c) 2003 Wolfgang Denk <wd@denx.de> 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9#include <asm-offsets.h> 10#include <config.h> 11#include <asm/asm.h> 12#include <asm/regdef.h> 13#include <asm/mipsregs.h> 14#include <asm/addrspace.h> 15#include <asm/cacheops.h> 16 17#ifndef CONFIG_SYS_MIPS_CACHE_MODE 18#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT 19#endif 20 21#ifdef CONFIG_64BIT 22# define RA ta3 23#else 24# define RA t7 25#endif 26 27#define INDEX_BASE CKSEG0 28 29 .macro f_fill64 dst, offset, val 30 LONG_S \val, (\offset + 0 * LONGSIZE)(\dst) 31 LONG_S \val, (\offset + 1 * LONGSIZE)(\dst) 32 LONG_S \val, (\offset + 2 * LONGSIZE)(\dst) 33 LONG_S \val, (\offset + 3 * LONGSIZE)(\dst) 34 LONG_S \val, (\offset + 4 * LONGSIZE)(\dst) 35 LONG_S \val, (\offset + 5 * LONGSIZE)(\dst) 36 LONG_S \val, (\offset + 6 * LONGSIZE)(\dst) 37 LONG_S \val, (\offset + 7 * LONGSIZE)(\dst) 38#if LONGSIZE == 4 39 LONG_S \val, (\offset + 8 * LONGSIZE)(\dst) 40 LONG_S \val, (\offset + 9 * LONGSIZE)(\dst) 41 LONG_S \val, (\offset + 10 * LONGSIZE)(\dst) 42 LONG_S \val, (\offset + 11 * LONGSIZE)(\dst) 43 LONG_S \val, (\offset + 12 * LONGSIZE)(\dst) 44 LONG_S \val, (\offset + 13 * LONGSIZE)(\dst) 45 LONG_S \val, (\offset + 14 * LONGSIZE)(\dst) 46 LONG_S \val, (\offset + 15 * LONGSIZE)(\dst) 47#endif 48 .endm 49 50/* 51 * mips_init_icache(uint PRId, ulong icache_size, unchar icache_linesz) 52 */ 53LEAF(mips_init_icache) 54 blez a1, 9f 55 mtc0 zero, CP0_TAGLO 56 /* clear tag to invalidate */ 57 PTR_LI t0, INDEX_BASE 58 PTR_ADDU t1, t0, a1 591: cache INDEX_STORE_TAG_I, 0(t0) 60 PTR_ADDU t0, a2 61 bne t0, t1, 1b 62 /* fill once, so data field parity is correct */ 63 PTR_LI t0, INDEX_BASE 642: cache FILL, 0(t0) 65 PTR_ADDU t0, a2 66 bne t0, t1, 2b 67 /* invalidate again - prudent but not strictly neccessary */ 68 PTR_LI t0, INDEX_BASE 691: cache INDEX_STORE_TAG_I, 0(t0) 70 PTR_ADDU t0, a2 71 bne t0, t1, 1b 729: jr ra 73 END(mips_init_icache) 74 75/* 76 * mips_init_dcache(uint PRId, ulong dcache_size, unchar dcache_linesz) 77 */ 78LEAF(mips_init_dcache) 79 blez a1, 9f 80 mtc0 zero, CP0_TAGLO 81 /* clear all tags */ 82 PTR_LI t0, INDEX_BASE 83 PTR_ADDU t1, t0, a1 841: cache INDEX_STORE_TAG_D, 0(t0) 85 PTR_ADDU t0, a2 86 bne t0, t1, 1b 87 /* load from each line (in cached space) */ 88 PTR_LI t0, INDEX_BASE 892: LONG_L zero, 0(t0) 90 PTR_ADDU t0, a2 91 bne t0, t1, 2b 92 /* clear all tags */ 93 PTR_LI t0, INDEX_BASE 941: cache INDEX_STORE_TAG_D, 0(t0) 95 PTR_ADDU t0, a2 96 bne t0, t1, 1b 979: jr ra 98 END(mips_init_dcache) 99 100/* 101 * mips_cache_reset - low level initialisation of the primary caches 102 * 103 * This routine initialises the primary caches to ensure that they have good 104 * parity. It must be called by the ROM before any cached locations are used 105 * to prevent the possibility of data with bad parity being written to memory. 106 * 107 * To initialise the instruction cache it is essential that a source of data 108 * with good parity is available. This routine will initialise an area of 109 * memory starting at location zero to be used as a source of parity. 110 * 111 * RETURNS: N/A 112 * 113 */ 114NESTED(mips_cache_reset, 0, ra) 115 move RA, ra 116 117#if !defined(CONFIG_SYS_ICACHE_SIZE) || !defined(CONFIG_SYS_DCACHE_SIZE) || \ 118 !defined(CONFIG_SYS_CACHELINE_SIZE) 119 /* read Config1 for use below */ 120 mfc0 t5, CP0_CONFIG, 1 121#endif 122 123#ifdef CONFIG_SYS_CACHELINE_SIZE 124 li t9, CONFIG_SYS_CACHELINE_SIZE 125 li t8, CONFIG_SYS_CACHELINE_SIZE 126#else 127 /* Detect I-cache line size. */ 128 srl t8, t5, MIPS_CONF1_IL_SHIFT 129 andi t8, t8, (MIPS_CONF1_IL >> MIPS_CONF1_IL_SHIFT) 130 beqz t8, 1f 131 li t6, 2 132 sllv t8, t6, t8 133 1341: /* Detect D-cache line size. */ 135 srl t9, t5, MIPS_CONF1_DL_SHIFT 136 andi t9, t9, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHIFT) 137 beqz t9, 1f 138 li t6, 2 139 sllv t9, t6, t9 1401: 141#endif 142 143#ifdef CONFIG_SYS_ICACHE_SIZE 144 li t2, CONFIG_SYS_ICACHE_SIZE 145#else 146 /* Detect I-cache size. */ 147 srl t6, t5, MIPS_CONF1_IS_SHIFT 148 andi t6, t6, (MIPS_CONF1_IS >> MIPS_CONF1_IS_SHIFT) 149 li t4, 32 150 xori t2, t6, 0x7 151 beqz t2, 1f 152 addi t6, t6, 1 153 sllv t4, t4, t6 1541: /* At this point t4 == I-cache sets. */ 155 mul t2, t4, t8 156 srl t6, t5, MIPS_CONF1_IA_SHIFT 157 andi t6, t6, (MIPS_CONF1_IA >> MIPS_CONF1_IA_SHIFT) 158 addi t6, t6, 1 159 /* At this point t6 == I-cache ways. */ 160 mul t2, t2, t6 161#endif 162 163#ifdef CONFIG_SYS_DCACHE_SIZE 164 li t3, CONFIG_SYS_DCACHE_SIZE 165#else 166 /* Detect D-cache size. */ 167 srl t6, t5, MIPS_CONF1_DS_SHIFT 168 andi t6, t6, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHIFT) 169 li t4, 32 170 xori t3, t6, 0x7 171 beqz t3, 1f 172 addi t6, t6, 1 173 sllv t4, t4, t6 1741: /* At this point t4 == I-cache sets. */ 175 mul t3, t4, t9 176 srl t6, t5, MIPS_CONF1_DA_SHIFT 177 andi t6, t6, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHIFT) 178 addi t6, t6, 1 179 /* At this point t6 == I-cache ways. */ 180 mul t3, t3, t6 181#endif 182 183 /* Determine the largest L1 cache size */ 184#if defined(CONFIG_SYS_ICACHE_SIZE) && defined(CONFIG_SYS_DCACHE_SIZE) 185#if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE 186 li v0, CONFIG_SYS_ICACHE_SIZE 187#else 188 li v0, CONFIG_SYS_DCACHE_SIZE 189#endif 190#else 191 move v0, t2 192 sltu t1, t2, t3 193 movn v0, t3, t1 194#endif 195 /* 196 * Now clear that much memory starting from zero. 197 */ 198 PTR_LI a0, CKSEG1 199 PTR_ADDU a1, a0, v0 2002: PTR_ADDIU a0, 64 201 f_fill64 a0, -64, zero 202 bne a0, a1, 2b 203 204 /* 205 * The caches are probably in an indeterminate state, 206 * so we force good parity into them by doing an 207 * invalidate, load/fill, invalidate for each line. 208 */ 209 210 /* 211 * Assume bottom of RAM will generate good parity for the cache. 212 */ 213 214 /* 215 * Initialize the I-cache first, 216 */ 217 move a1, t2 218 move a2, t8 219 PTR_LA v1, mips_init_icache 220 jalr v1 221 222 /* 223 * then initialize D-cache. 224 */ 225 move a1, t3 226 move a2, t9 227 PTR_LA v1, mips_init_dcache 228 jalr v1 229 230 jr RA 231 END(mips_cache_reset) 232 233/* 234 * dcache_status - get cache status 235 * 236 * RETURNS: 0 - cache disabled; 1 - cache enabled 237 * 238 */ 239LEAF(dcache_status) 240 mfc0 t0, CP0_CONFIG 241 li t1, CONF_CM_UNCACHED 242 andi t0, t0, CONF_CM_CMASK 243 move v0, zero 244 beq t0, t1, 2f 245 li v0, 1 2462: jr ra 247 END(dcache_status) 248 249/* 250 * dcache_disable - disable cache 251 * 252 * RETURNS: N/A 253 * 254 */ 255LEAF(dcache_disable) 256 mfc0 t0, CP0_CONFIG 257 li t1, -8 258 and t0, t0, t1 259 ori t0, t0, CONF_CM_UNCACHED 260 mtc0 t0, CP0_CONFIG 261 jr ra 262 END(dcache_disable) 263 264/* 265 * dcache_enable - enable cache 266 * 267 * RETURNS: N/A 268 * 269 */ 270LEAF(dcache_enable) 271 mfc0 t0, CP0_CONFIG 272 ori t0, CONF_CM_CMASK 273 xori t0, CONF_CM_CMASK 274 ori t0, CONFIG_SYS_MIPS_CACHE_MODE 275 mtc0 t0, CP0_CONFIG 276 jr ra 277 END(dcache_enable) 278