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 */ 57a3ab2ae7SDaniel Schwierzeck srl \line_sz, $1, \off + MIPS_CONF1_DL_SHF - MIPS_CONF1_DA_SHF 58a3ab2ae7SDaniel Schwierzeck andi \line_sz, \line_sz, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHF) 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 */ 65a3ab2ae7SDaniel Schwierzeck srl \sz, $1, \off + MIPS_CONF1_DA_SHF - MIPS_CONF1_DA_SHF 66a3ab2ae7SDaniel Schwierzeck andi \sz, \sz, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHF) 679f8ac824SPaul Burton addiu \sz, \sz, 1 68536cb7ceSPaul Burton 69536cb7ceSPaul Burton /* sz *= line_sz */ 70536cb7ceSPaul Burton mul \sz, \sz, \line_sz 71536cb7ceSPaul Burton 72536cb7ceSPaul Burton /* detect log32(sets) */ 73a3ab2ae7SDaniel Schwierzeck srl $1, $1, \off + MIPS_CONF1_DS_SHF - MIPS_CONF1_DA_SHF 74a3ab2ae7SDaniel Schwierzeck andi $1, $1, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHF) 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) 102*ace3be4fSPaul Burton#ifndef CONFIG_SYS_CACHE_SIZE_AUTO 1034a5d8898SPaul Burton li t2, CONFIG_SYS_ICACHE_SIZE 104536cb7ceSPaul Burton li t8, CONFIG_SYS_CACHELINE_SIZE 1054a5d8898SPaul Burton#else 106a3ab2ae7SDaniel Schwierzeck l1_info t2, t8, MIPS_CONF1_IA_SHF 1074a5d8898SPaul Burton#endif 1084a5d8898SPaul Burton 109*ace3be4fSPaul Burton#ifndef CONFIG_SYS_CACHE_SIZE_AUTO 1104a5d8898SPaul Burton li t3, CONFIG_SYS_DCACHE_SIZE 111536cb7ceSPaul Burton li t9, CONFIG_SYS_CACHELINE_SIZE 1124a5d8898SPaul Burton#else 113a3ab2ae7SDaniel Schwierzeck l1_info t3, t9, MIPS_CONF1_DA_SHF 1144a5d8898SPaul Burton#endif 1154a5d8898SPaul Burton 116dd7c7200SPaul Burton#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD 117dd7c7200SPaul Burton 1184a5d8898SPaul Burton /* Determine the largest L1 cache size */ 119*ace3be4fSPaul Burton#ifndef CONFIG_SYS_CACHE_SIZE_AUTO 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 139dd7c7200SPaul Burton#endif /* CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD */ 1404a5d8898SPaul Burton 1414a5d8898SPaul Burton /* 1428755d507SPaul Burton * The TagLo registers used depend upon the CPU implementation, but the 1438755d507SPaul Burton * architecture requires that it is safe for software to write to both 1448755d507SPaul Burton * TagLo selects 0 & 2 covering supported cases. 1458755d507SPaul Burton */ 1468755d507SPaul Burton mtc0 zero, CP0_TAGLO 1478755d507SPaul Burton mtc0 zero, CP0_TAGLO, 2 1488755d507SPaul Burton 1498755d507SPaul Burton /* 150dd7c7200SPaul Burton * The caches are probably in an indeterminate state, so we force good 151dd7c7200SPaul Burton * parity into them by doing an invalidate for each line. If 152dd7c7200SPaul Burton * CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD is set then we'll proceed to 153dd7c7200SPaul Burton * perform a load/fill & a further invalidate for each line, assuming 154dd7c7200SPaul Burton * that the bottom of RAM (having just been cleared) will generate good 155dd7c7200SPaul Burton * parity for the cache. 1564a5d8898SPaul Burton */ 1574a5d8898SPaul Burton 1584a5d8898SPaul Burton /* 1594a5d8898SPaul Burton * Initialize the I-cache first, 1604a5d8898SPaul Burton */ 161ca4e833cSPaul Burton blez t2, 1f 162ca4e833cSPaul Burton PTR_LI t0, INDEX_BASE 163ca4e833cSPaul Burton PTR_ADDU t1, t0, t2 164ca4e833cSPaul Burton /* clear tag to invalidate */ 165ca4e833cSPaul Burton cache_loop t0, t1, t8, INDEX_STORE_TAG_I 166dd7c7200SPaul Burton#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD 167ca4e833cSPaul Burton /* fill once, so data field parity is correct */ 168ca4e833cSPaul Burton PTR_LI t0, INDEX_BASE 169ca4e833cSPaul Burton cache_loop t0, t1, t8, FILL 170ca4e833cSPaul Burton /* invalidate again - prudent but not strictly neccessary */ 171ca4e833cSPaul Burton PTR_LI t0, INDEX_BASE 172ca4e833cSPaul Burton cache_loop t0, t1, t8, INDEX_STORE_TAG_I 173dd7c7200SPaul Burton#endif 1744a5d8898SPaul Burton 1754a5d8898SPaul Burton /* 1764a5d8898SPaul Burton * then initialize D-cache. 1774a5d8898SPaul Burton */ 178ca4e833cSPaul Burton1: blez t3, 3f 179ca4e833cSPaul Burton PTR_LI t0, INDEX_BASE 180ca4e833cSPaul Burton PTR_ADDU t1, t0, t3 181ca4e833cSPaul Burton /* clear all tags */ 182ca4e833cSPaul Burton cache_loop t0, t1, t9, INDEX_STORE_TAG_D 183dd7c7200SPaul Burton#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD 184ca4e833cSPaul Burton /* load from each line (in cached space) */ 185ca4e833cSPaul Burton PTR_LI t0, INDEX_BASE 186ca4e833cSPaul Burton2: LONG_L zero, 0(t0) 187ca4e833cSPaul Burton PTR_ADDU t0, t9 188ca4e833cSPaul Burton bne t0, t1, 2b 189ca4e833cSPaul Burton /* clear all tags */ 190ca4e833cSPaul Burton PTR_LI t0, INDEX_BASE 191ca4e833cSPaul Burton cache_loop t0, t1, t9, INDEX_STORE_TAG_D 192dd7c7200SPaul Burton#endif 1934a5d8898SPaul Burton 194ca4e833cSPaul Burton3: jr ra 1954a5d8898SPaul Burton END(mips_cache_reset) 1964a5d8898SPaul Burton 1974a5d8898SPaul Burton/* 1984a5d8898SPaul Burton * dcache_status - get cache status 1994a5d8898SPaul Burton * 2004a5d8898SPaul Burton * RETURNS: 0 - cache disabled; 1 - cache enabled 2014a5d8898SPaul Burton * 2024a5d8898SPaul Burton */ 2034a5d8898SPaul BurtonLEAF(dcache_status) 2044a5d8898SPaul Burton mfc0 t0, CP0_CONFIG 2054a5d8898SPaul Burton li t1, CONF_CM_UNCACHED 2064a5d8898SPaul Burton andi t0, t0, CONF_CM_CMASK 2074a5d8898SPaul Burton move v0, zero 2084a5d8898SPaul Burton beq t0, t1, 2f 2094a5d8898SPaul Burton li v0, 1 2104a5d8898SPaul Burton2: jr ra 2114a5d8898SPaul Burton END(dcache_status) 2124a5d8898SPaul Burton 2134a5d8898SPaul Burton/* 2144a5d8898SPaul Burton * dcache_disable - disable cache 2154a5d8898SPaul Burton * 2164a5d8898SPaul Burton * RETURNS: N/A 2174a5d8898SPaul Burton * 2184a5d8898SPaul Burton */ 2194a5d8898SPaul BurtonLEAF(dcache_disable) 2204a5d8898SPaul Burton mfc0 t0, CP0_CONFIG 2214a5d8898SPaul Burton li t1, -8 2224a5d8898SPaul Burton and t0, t0, t1 2234a5d8898SPaul Burton ori t0, t0, CONF_CM_UNCACHED 2244a5d8898SPaul Burton mtc0 t0, CP0_CONFIG 2254a5d8898SPaul Burton jr ra 2264a5d8898SPaul Burton END(dcache_disable) 2274a5d8898SPaul Burton 2284a5d8898SPaul Burton/* 2294a5d8898SPaul Burton * dcache_enable - enable cache 2304a5d8898SPaul Burton * 2314a5d8898SPaul Burton * RETURNS: N/A 2324a5d8898SPaul Burton * 2334a5d8898SPaul Burton */ 2344a5d8898SPaul BurtonLEAF(dcache_enable) 2354a5d8898SPaul Burton mfc0 t0, CP0_CONFIG 2364a5d8898SPaul Burton ori t0, CONF_CM_CMASK 2374a5d8898SPaul Burton xori t0, CONF_CM_CMASK 2384a5d8898SPaul Burton ori t0, CONFIG_SYS_MIPS_CACHE_MODE 2394a5d8898SPaul Burton mtc0 t0, CP0_CONFIG 2404a5d8898SPaul Burton jr ra 2414a5d8898SPaul Burton END(dcache_enable) 242