14a5d8898SPaul Burton/* 24a5d8898SPaul Burton * Cache-handling routined for MIPS CPUs 34a5d8898SPaul Burton * 44a5d8898SPaul Burton * Copyright (c) 2003 Wolfgang Denk <wd@denx.de> 54a5d8898SPaul Burton * 64a5d8898SPaul Burton * SPDX-License-Identifier: GPL-2.0+ 74a5d8898SPaul Burton */ 84a5d8898SPaul Burton 94a5d8898SPaul Burton#include <asm-offsets.h> 104a5d8898SPaul Burton#include <config.h> 114a5d8898SPaul Burton#include <asm/asm.h> 124a5d8898SPaul Burton#include <asm/regdef.h> 134a5d8898SPaul Burton#include <asm/mipsregs.h> 144a5d8898SPaul Burton#include <asm/addrspace.h> 154a5d8898SPaul Burton#include <asm/cacheops.h> 164a5d8898SPaul Burton 174a5d8898SPaul Burton#ifndef CONFIG_SYS_MIPS_CACHE_MODE 184a5d8898SPaul Burton#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT 194a5d8898SPaul Burton#endif 204a5d8898SPaul Burton 214a5d8898SPaul Burton#define INDEX_BASE CKSEG0 224a5d8898SPaul Burton 234a5d8898SPaul Burton .macro f_fill64 dst, offset, val 244a5d8898SPaul Burton LONG_S \val, (\offset + 0 * LONGSIZE)(\dst) 254a5d8898SPaul Burton LONG_S \val, (\offset + 1 * LONGSIZE)(\dst) 264a5d8898SPaul Burton LONG_S \val, (\offset + 2 * LONGSIZE)(\dst) 274a5d8898SPaul Burton LONG_S \val, (\offset + 3 * LONGSIZE)(\dst) 284a5d8898SPaul Burton LONG_S \val, (\offset + 4 * LONGSIZE)(\dst) 294a5d8898SPaul Burton LONG_S \val, (\offset + 5 * LONGSIZE)(\dst) 304a5d8898SPaul Burton LONG_S \val, (\offset + 6 * LONGSIZE)(\dst) 314a5d8898SPaul Burton LONG_S \val, (\offset + 7 * LONGSIZE)(\dst) 324a5d8898SPaul Burton#if LONGSIZE == 4 334a5d8898SPaul Burton LONG_S \val, (\offset + 8 * LONGSIZE)(\dst) 344a5d8898SPaul Burton LONG_S \val, (\offset + 9 * LONGSIZE)(\dst) 354a5d8898SPaul Burton LONG_S \val, (\offset + 10 * LONGSIZE)(\dst) 364a5d8898SPaul Burton LONG_S \val, (\offset + 11 * LONGSIZE)(\dst) 374a5d8898SPaul Burton LONG_S \val, (\offset + 12 * LONGSIZE)(\dst) 384a5d8898SPaul Burton LONG_S \val, (\offset + 13 * LONGSIZE)(\dst) 394a5d8898SPaul Burton LONG_S \val, (\offset + 14 * LONGSIZE)(\dst) 404a5d8898SPaul Burton LONG_S \val, (\offset + 15 * LONGSIZE)(\dst) 414a5d8898SPaul Burton#endif 424a5d8898SPaul Burton .endm 434a5d8898SPaul Burton 44ac22fecaSPaul Burton .macro cache_loop curr, end, line_sz, op 45ac22fecaSPaul Burton10: cache \op, 0(\curr) 46ac22fecaSPaul Burton PTR_ADDU \curr, \curr, \line_sz 47ac22fecaSPaul Burton bne \curr, \end, 10b 48ac22fecaSPaul Burton .endm 49ac22fecaSPaul Burton 50536cb7ceSPaul Burton .macro l1_info sz, line_sz, off 51536cb7ceSPaul Burton .set push 52536cb7ceSPaul Burton .set noat 53536cb7ceSPaul Burton 54536cb7ceSPaul Burton mfc0 $1, CP0_CONFIG, 1 55536cb7ceSPaul Burton 56536cb7ceSPaul Burton /* detect line size */ 57536cb7ceSPaul Burton srl \line_sz, $1, \off + MIPS_CONF1_DL_SHIFT - MIPS_CONF1_DA_SHIFT 58536cb7ceSPaul Burton andi \line_sz, \line_sz, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHIFT) 59536cb7ceSPaul Burton move \sz, zero 60536cb7ceSPaul Burton beqz \line_sz, 10f 61536cb7ceSPaul Burton li \sz, 2 62536cb7ceSPaul Burton sllv \line_sz, \sz, \line_sz 63536cb7ceSPaul Burton 64536cb7ceSPaul Burton /* detect associativity */ 65536cb7ceSPaul Burton srl \sz, $1, \off + MIPS_CONF1_DA_SHIFT - MIPS_CONF1_DA_SHIFT 66536cb7ceSPaul Burton andi \sz, \sz, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHIFT) 67536cb7ceSPaul Burton addi \sz, \sz, 1 68536cb7ceSPaul Burton 69536cb7ceSPaul Burton /* sz *= line_sz */ 70536cb7ceSPaul Burton mul \sz, \sz, \line_sz 71536cb7ceSPaul Burton 72536cb7ceSPaul Burton /* detect log32(sets) */ 73536cb7ceSPaul Burton srl $1, $1, \off + MIPS_CONF1_DS_SHIFT - MIPS_CONF1_DA_SHIFT 74536cb7ceSPaul Burton andi $1, $1, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHIFT) 75536cb7ceSPaul Burton addiu $1, $1, 1 76536cb7ceSPaul Burton andi $1, $1, 0x7 77536cb7ceSPaul Burton 78536cb7ceSPaul Burton /* sz <<= log32(sets) */ 79536cb7ceSPaul Burton sllv \sz, \sz, $1 80536cb7ceSPaul Burton 81536cb7ceSPaul Burton /* sz *= 32 */ 82536cb7ceSPaul Burton li $1, 32 83536cb7ceSPaul Burton mul \sz, \sz, $1 84536cb7ceSPaul Burton10: 85536cb7ceSPaul Burton .set pop 86536cb7ceSPaul Burton .endm 874a5d8898SPaul Burton/* 884a5d8898SPaul Burton * mips_cache_reset - low level initialisation of the primary caches 894a5d8898SPaul Burton * 904a5d8898SPaul Burton * This routine initialises the primary caches to ensure that they have good 914a5d8898SPaul Burton * parity. It must be called by the ROM before any cached locations are used 924a5d8898SPaul Burton * to prevent the possibility of data with bad parity being written to memory. 934a5d8898SPaul Burton * 944a5d8898SPaul Burton * To initialise the instruction cache it is essential that a source of data 954a5d8898SPaul Burton * with good parity is available. This routine will initialise an area of 964a5d8898SPaul Burton * memory starting at location zero to be used as a source of parity. 974a5d8898SPaul Burton * 984a5d8898SPaul Burton * RETURNS: N/A 994a5d8898SPaul Burton * 1004a5d8898SPaul Burton */ 101ca4e833cSPaul BurtonLEAF(mips_cache_reset) 1024a5d8898SPaul Burton#ifdef CONFIG_SYS_ICACHE_SIZE 1034a5d8898SPaul Burton li t2, CONFIG_SYS_ICACHE_SIZE 104536cb7ceSPaul Burton li t8, CONFIG_SYS_CACHELINE_SIZE 1054a5d8898SPaul Burton#else 106536cb7ceSPaul Burton l1_info t2, t8, MIPS_CONF1_IA_SHIFT 1074a5d8898SPaul Burton#endif 1084a5d8898SPaul Burton 1094a5d8898SPaul Burton#ifdef CONFIG_SYS_DCACHE_SIZE 1104a5d8898SPaul Burton li t3, CONFIG_SYS_DCACHE_SIZE 111536cb7ceSPaul Burton li t9, CONFIG_SYS_CACHELINE_SIZE 1124a5d8898SPaul Burton#else 113536cb7ceSPaul Burton l1_info t3, t9, MIPS_CONF1_DA_SHIFT 1144a5d8898SPaul Burton#endif 1154a5d8898SPaul Burton 116*dd7c7200SPaul Burton#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD 117*dd7c7200SPaul Burton 1184a5d8898SPaul Burton /* Determine the largest L1 cache size */ 1194a5d8898SPaul Burton#if defined(CONFIG_SYS_ICACHE_SIZE) && defined(CONFIG_SYS_DCACHE_SIZE) 1204a5d8898SPaul Burton#if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE 1214a5d8898SPaul Burton li v0, CONFIG_SYS_ICACHE_SIZE 1224a5d8898SPaul Burton#else 1234a5d8898SPaul Burton li v0, CONFIG_SYS_DCACHE_SIZE 1244a5d8898SPaul Burton#endif 1254a5d8898SPaul Burton#else 1264a5d8898SPaul Burton move v0, t2 1274a5d8898SPaul Burton sltu t1, t2, t3 1284a5d8898SPaul Burton movn v0, t3, t1 1294a5d8898SPaul Burton#endif 1304a5d8898SPaul Burton /* 1314a5d8898SPaul Burton * Now clear that much memory starting from zero. 1324a5d8898SPaul Burton */ 1334a5d8898SPaul Burton PTR_LI a0, CKSEG1 1344a5d8898SPaul Burton PTR_ADDU a1, a0, v0 1354a5d8898SPaul Burton2: PTR_ADDIU a0, 64 1364a5d8898SPaul Burton f_fill64 a0, -64, zero 1374a5d8898SPaul Burton bne a0, a1, 2b 1384a5d8898SPaul Burton 139*dd7c7200SPaul Burton#endif /* CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD */ 1404a5d8898SPaul Burton 1414a5d8898SPaul Burton /* 142*dd7c7200SPaul Burton * The caches are probably in an indeterminate state, so we force good 143*dd7c7200SPaul Burton * parity into them by doing an invalidate for each line. If 144*dd7c7200SPaul Burton * CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD is set then we'll proceed to 145*dd7c7200SPaul Burton * perform a load/fill & a further invalidate for each line, assuming 146*dd7c7200SPaul Burton * that the bottom of RAM (having just been cleared) will generate good 147*dd7c7200SPaul Burton * parity for the cache. 1484a5d8898SPaul Burton */ 1494a5d8898SPaul Burton 1504a5d8898SPaul Burton /* 1514a5d8898SPaul Burton * Initialize the I-cache first, 1524a5d8898SPaul Burton */ 153ca4e833cSPaul Burton blez t2, 1f 154ca4e833cSPaul Burton mtc0 zero, CP0_TAGLO 155ca4e833cSPaul Burton PTR_LI t0, INDEX_BASE 156ca4e833cSPaul Burton PTR_ADDU t1, t0, t2 157ca4e833cSPaul Burton /* clear tag to invalidate */ 158ca4e833cSPaul Burton cache_loop t0, t1, t8, INDEX_STORE_TAG_I 159*dd7c7200SPaul Burton#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD 160ca4e833cSPaul Burton /* fill once, so data field parity is correct */ 161ca4e833cSPaul Burton PTR_LI t0, INDEX_BASE 162ca4e833cSPaul Burton cache_loop t0, t1, t8, FILL 163ca4e833cSPaul Burton /* invalidate again - prudent but not strictly neccessary */ 164ca4e833cSPaul Burton PTR_LI t0, INDEX_BASE 165ca4e833cSPaul Burton cache_loop t0, t1, t8, INDEX_STORE_TAG_I 166*dd7c7200SPaul Burton#endif 1674a5d8898SPaul Burton 1684a5d8898SPaul Burton /* 1694a5d8898SPaul Burton * then initialize D-cache. 1704a5d8898SPaul Burton */ 171ca4e833cSPaul Burton1: blez t3, 3f 172ca4e833cSPaul Burton mtc0 zero, CP0_TAGLO 173ca4e833cSPaul Burton PTR_LI t0, INDEX_BASE 174ca4e833cSPaul Burton PTR_ADDU t1, t0, t3 175ca4e833cSPaul Burton /* clear all tags */ 176ca4e833cSPaul Burton cache_loop t0, t1, t9, INDEX_STORE_TAG_D 177*dd7c7200SPaul Burton#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD 178ca4e833cSPaul Burton /* load from each line (in cached space) */ 179ca4e833cSPaul Burton PTR_LI t0, INDEX_BASE 180ca4e833cSPaul Burton2: LONG_L zero, 0(t0) 181ca4e833cSPaul Burton PTR_ADDU t0, t9 182ca4e833cSPaul Burton bne t0, t1, 2b 183ca4e833cSPaul Burton /* clear all tags */ 184ca4e833cSPaul Burton PTR_LI t0, INDEX_BASE 185ca4e833cSPaul Burton cache_loop t0, t1, t9, INDEX_STORE_TAG_D 186*dd7c7200SPaul Burton#endif 1874a5d8898SPaul Burton 188ca4e833cSPaul Burton3: jr ra 1894a5d8898SPaul Burton END(mips_cache_reset) 1904a5d8898SPaul Burton 1914a5d8898SPaul Burton/* 1924a5d8898SPaul Burton * dcache_status - get cache status 1934a5d8898SPaul Burton * 1944a5d8898SPaul Burton * RETURNS: 0 - cache disabled; 1 - cache enabled 1954a5d8898SPaul Burton * 1964a5d8898SPaul Burton */ 1974a5d8898SPaul BurtonLEAF(dcache_status) 1984a5d8898SPaul Burton mfc0 t0, CP0_CONFIG 1994a5d8898SPaul Burton li t1, CONF_CM_UNCACHED 2004a5d8898SPaul Burton andi t0, t0, CONF_CM_CMASK 2014a5d8898SPaul Burton move v0, zero 2024a5d8898SPaul Burton beq t0, t1, 2f 2034a5d8898SPaul Burton li v0, 1 2044a5d8898SPaul Burton2: jr ra 2054a5d8898SPaul Burton END(dcache_status) 2064a5d8898SPaul Burton 2074a5d8898SPaul Burton/* 2084a5d8898SPaul Burton * dcache_disable - disable cache 2094a5d8898SPaul Burton * 2104a5d8898SPaul Burton * RETURNS: N/A 2114a5d8898SPaul Burton * 2124a5d8898SPaul Burton */ 2134a5d8898SPaul BurtonLEAF(dcache_disable) 2144a5d8898SPaul Burton mfc0 t0, CP0_CONFIG 2154a5d8898SPaul Burton li t1, -8 2164a5d8898SPaul Burton and t0, t0, t1 2174a5d8898SPaul Burton ori t0, t0, CONF_CM_UNCACHED 2184a5d8898SPaul Burton mtc0 t0, CP0_CONFIG 2194a5d8898SPaul Burton jr ra 2204a5d8898SPaul Burton END(dcache_disable) 2214a5d8898SPaul Burton 2224a5d8898SPaul Burton/* 2234a5d8898SPaul Burton * dcache_enable - enable cache 2244a5d8898SPaul Burton * 2254a5d8898SPaul Burton * RETURNS: N/A 2264a5d8898SPaul Burton * 2274a5d8898SPaul Burton */ 2284a5d8898SPaul BurtonLEAF(dcache_enable) 2294a5d8898SPaul Burton mfc0 t0, CP0_CONFIG 2304a5d8898SPaul Burton ori t0, CONF_CM_CMASK 2314a5d8898SPaul Burton xori t0, CONF_CM_CMASK 2324a5d8898SPaul Burton ori t0, CONFIG_SYS_MIPS_CACHE_MODE 2334a5d8898SPaul Burton mtc0 t0, CP0_CONFIG 2344a5d8898SPaul Burton jr ra 2354a5d8898SPaul Burton END(dcache_enable) 236