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 .macro l1_info sz, line_sz, off 101 .set push 102 .set noat 103 104 mfc0 $1, CP0_CONFIG, 1 105 106 /* detect line size */ 107 srl \line_sz, $1, \off + MIPS_CONF1_DL_SHIFT - MIPS_CONF1_DA_SHIFT 108 andi \line_sz, \line_sz, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHIFT) 109 move \sz, zero 110 beqz \line_sz, 10f 111 li \sz, 2 112 sllv \line_sz, \sz, \line_sz 113 114 /* detect associativity */ 115 srl \sz, $1, \off + MIPS_CONF1_DA_SHIFT - MIPS_CONF1_DA_SHIFT 116 andi \sz, \sz, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHIFT) 117 addi \sz, \sz, 1 118 119 /* sz *= line_sz */ 120 mul \sz, \sz, \line_sz 121 122 /* detect log32(sets) */ 123 srl $1, $1, \off + MIPS_CONF1_DS_SHIFT - MIPS_CONF1_DA_SHIFT 124 andi $1, $1, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHIFT) 125 addiu $1, $1, 1 126 andi $1, $1, 0x7 127 128 /* sz <<= log32(sets) */ 129 sllv \sz, \sz, $1 130 131 /* sz *= 32 */ 132 li $1, 32 133 mul \sz, \sz, $1 13410: 135 .set pop 136 .endm 137/* 138 * mips_cache_reset - low level initialisation of the primary caches 139 * 140 * This routine initialises the primary caches to ensure that they have good 141 * parity. It must be called by the ROM before any cached locations are used 142 * to prevent the possibility of data with bad parity being written to memory. 143 * 144 * To initialise the instruction cache it is essential that a source of data 145 * with good parity is available. This routine will initialise an area of 146 * memory starting at location zero to be used as a source of parity. 147 * 148 * RETURNS: N/A 149 * 150 */ 151NESTED(mips_cache_reset, 0, ra) 152 move RA, ra 153 154#ifdef CONFIG_SYS_ICACHE_SIZE 155 li t2, CONFIG_SYS_ICACHE_SIZE 156 li t8, CONFIG_SYS_CACHELINE_SIZE 157#else 158 l1_info t2, t8, MIPS_CONF1_IA_SHIFT 159#endif 160 161#ifdef CONFIG_SYS_DCACHE_SIZE 162 li t3, CONFIG_SYS_DCACHE_SIZE 163 li t9, CONFIG_SYS_CACHELINE_SIZE 164#else 165 l1_info t3, t9, MIPS_CONF1_DA_SHIFT 166#endif 167 168 /* Determine the largest L1 cache size */ 169#if defined(CONFIG_SYS_ICACHE_SIZE) && defined(CONFIG_SYS_DCACHE_SIZE) 170#if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE 171 li v0, CONFIG_SYS_ICACHE_SIZE 172#else 173 li v0, CONFIG_SYS_DCACHE_SIZE 174#endif 175#else 176 move v0, t2 177 sltu t1, t2, t3 178 movn v0, t3, t1 179#endif 180 /* 181 * Now clear that much memory starting from zero. 182 */ 183 PTR_LI a0, CKSEG1 184 PTR_ADDU a1, a0, v0 1852: PTR_ADDIU a0, 64 186 f_fill64 a0, -64, zero 187 bne a0, a1, 2b 188 189 /* 190 * The caches are probably in an indeterminate state, 191 * so we force good parity into them by doing an 192 * invalidate, load/fill, invalidate for each line. 193 */ 194 195 /* 196 * Assume bottom of RAM will generate good parity for the cache. 197 */ 198 199 /* 200 * Initialize the I-cache first, 201 */ 202 move a1, t2 203 move a2, t8 204 PTR_LA v1, mips_init_icache 205 jalr v1 206 207 /* 208 * then initialize D-cache. 209 */ 210 move a1, t3 211 move a2, t9 212 PTR_LA v1, mips_init_dcache 213 jalr v1 214 215 jr RA 216 END(mips_cache_reset) 217 218/* 219 * dcache_status - get cache status 220 * 221 * RETURNS: 0 - cache disabled; 1 - cache enabled 222 * 223 */ 224LEAF(dcache_status) 225 mfc0 t0, CP0_CONFIG 226 li t1, CONF_CM_UNCACHED 227 andi t0, t0, CONF_CM_CMASK 228 move v0, zero 229 beq t0, t1, 2f 230 li v0, 1 2312: jr ra 232 END(dcache_status) 233 234/* 235 * dcache_disable - disable cache 236 * 237 * RETURNS: N/A 238 * 239 */ 240LEAF(dcache_disable) 241 mfc0 t0, CP0_CONFIG 242 li t1, -8 243 and t0, t0, t1 244 ori t0, t0, CONF_CM_UNCACHED 245 mtc0 t0, CP0_CONFIG 246 jr ra 247 END(dcache_disable) 248 249/* 250 * dcache_enable - enable cache 251 * 252 * RETURNS: N/A 253 * 254 */ 255LEAF(dcache_enable) 256 mfc0 t0, CP0_CONFIG 257 ori t0, CONF_CM_CMASK 258 xori t0, CONF_CM_CMASK 259 ori t0, CONFIG_SYS_MIPS_CACHE_MODE 260 mtc0 t0, CP0_CONFIG 261 jr ra 262 END(dcache_enable) 263