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