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#ifdef CONFIG_64BIT 224a5d8898SPaul Burton# define RA ta3 234a5d8898SPaul Burton#else 244a5d8898SPaul Burton# define RA t7 254a5d8898SPaul Burton#endif 264a5d8898SPaul Burton 274a5d8898SPaul Burton#define INDEX_BASE CKSEG0 284a5d8898SPaul Burton 294a5d8898SPaul Burton .macro f_fill64 dst, offset, val 304a5d8898SPaul Burton LONG_S \val, (\offset + 0 * LONGSIZE)(\dst) 314a5d8898SPaul Burton LONG_S \val, (\offset + 1 * LONGSIZE)(\dst) 324a5d8898SPaul Burton LONG_S \val, (\offset + 2 * LONGSIZE)(\dst) 334a5d8898SPaul Burton LONG_S \val, (\offset + 3 * LONGSIZE)(\dst) 344a5d8898SPaul Burton LONG_S \val, (\offset + 4 * LONGSIZE)(\dst) 354a5d8898SPaul Burton LONG_S \val, (\offset + 5 * LONGSIZE)(\dst) 364a5d8898SPaul Burton LONG_S \val, (\offset + 6 * LONGSIZE)(\dst) 374a5d8898SPaul Burton LONG_S \val, (\offset + 7 * LONGSIZE)(\dst) 384a5d8898SPaul Burton#if LONGSIZE == 4 394a5d8898SPaul Burton LONG_S \val, (\offset + 8 * LONGSIZE)(\dst) 404a5d8898SPaul Burton LONG_S \val, (\offset + 9 * LONGSIZE)(\dst) 414a5d8898SPaul Burton LONG_S \val, (\offset + 10 * LONGSIZE)(\dst) 424a5d8898SPaul Burton LONG_S \val, (\offset + 11 * LONGSIZE)(\dst) 434a5d8898SPaul Burton LONG_S \val, (\offset + 12 * LONGSIZE)(\dst) 444a5d8898SPaul Burton LONG_S \val, (\offset + 13 * LONGSIZE)(\dst) 454a5d8898SPaul Burton LONG_S \val, (\offset + 14 * LONGSIZE)(\dst) 464a5d8898SPaul Burton LONG_S \val, (\offset + 15 * LONGSIZE)(\dst) 474a5d8898SPaul Burton#endif 484a5d8898SPaul Burton .endm 494a5d8898SPaul Burton 50*ac22fecaSPaul Burton .macro cache_loop curr, end, line_sz, op 51*ac22fecaSPaul Burton10: cache \op, 0(\curr) 52*ac22fecaSPaul Burton PTR_ADDU \curr, \curr, \line_sz 53*ac22fecaSPaul Burton bne \curr, \end, 10b 54*ac22fecaSPaul Burton .endm 55*ac22fecaSPaul Burton 564a5d8898SPaul Burton/* 574a5d8898SPaul Burton * mips_init_icache(uint PRId, ulong icache_size, unchar icache_linesz) 584a5d8898SPaul Burton */ 594a5d8898SPaul BurtonLEAF(mips_init_icache) 604a5d8898SPaul Burton blez a1, 9f 614a5d8898SPaul Burton mtc0 zero, CP0_TAGLO 624a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 634a5d8898SPaul Burton PTR_ADDU t1, t0, a1 64*ac22fecaSPaul Burton /* clear tag to invalidate */ 65*ac22fecaSPaul Burton cache_loop t0, t1, a2, INDEX_STORE_TAG_I 664a5d8898SPaul Burton /* fill once, so data field parity is correct */ 674a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 68*ac22fecaSPaul Burton cache_loop t0, t1, a2, FILL 694a5d8898SPaul Burton /* invalidate again - prudent but not strictly neccessary */ 704a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 71*ac22fecaSPaul Burton cache_loop t0, t1, a2, INDEX_STORE_TAG_I 724a5d8898SPaul Burton9: jr ra 734a5d8898SPaul Burton END(mips_init_icache) 744a5d8898SPaul Burton 754a5d8898SPaul Burton/* 764a5d8898SPaul Burton * mips_init_dcache(uint PRId, ulong dcache_size, unchar dcache_linesz) 774a5d8898SPaul Burton */ 784a5d8898SPaul BurtonLEAF(mips_init_dcache) 794a5d8898SPaul Burton blez a1, 9f 804a5d8898SPaul Burton mtc0 zero, CP0_TAGLO 814a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 824a5d8898SPaul Burton PTR_ADDU t1, t0, a1 83*ac22fecaSPaul Burton /* clear all tags */ 84*ac22fecaSPaul Burton cache_loop t0, t1, a2, INDEX_STORE_TAG_D 854a5d8898SPaul Burton /* load from each line (in cached space) */ 864a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 874a5d8898SPaul Burton2: LONG_L zero, 0(t0) 884a5d8898SPaul Burton PTR_ADDU t0, a2 894a5d8898SPaul Burton bne t0, t1, 2b 904a5d8898SPaul Burton /* clear all tags */ 914a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 92*ac22fecaSPaul Burton cache_loop t0, t1, a2, INDEX_STORE_TAG_D 934a5d8898SPaul Burton9: jr ra 944a5d8898SPaul Burton END(mips_init_dcache) 954a5d8898SPaul Burton 96536cb7ceSPaul Burton .macro l1_info sz, line_sz, off 97536cb7ceSPaul Burton .set push 98536cb7ceSPaul Burton .set noat 99536cb7ceSPaul Burton 100536cb7ceSPaul Burton mfc0 $1, CP0_CONFIG, 1 101536cb7ceSPaul Burton 102536cb7ceSPaul Burton /* detect line size */ 103536cb7ceSPaul Burton srl \line_sz, $1, \off + MIPS_CONF1_DL_SHIFT - MIPS_CONF1_DA_SHIFT 104536cb7ceSPaul Burton andi \line_sz, \line_sz, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHIFT) 105536cb7ceSPaul Burton move \sz, zero 106536cb7ceSPaul Burton beqz \line_sz, 10f 107536cb7ceSPaul Burton li \sz, 2 108536cb7ceSPaul Burton sllv \line_sz, \sz, \line_sz 109536cb7ceSPaul Burton 110536cb7ceSPaul Burton /* detect associativity */ 111536cb7ceSPaul Burton srl \sz, $1, \off + MIPS_CONF1_DA_SHIFT - MIPS_CONF1_DA_SHIFT 112536cb7ceSPaul Burton andi \sz, \sz, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHIFT) 113536cb7ceSPaul Burton addi \sz, \sz, 1 114536cb7ceSPaul Burton 115536cb7ceSPaul Burton /* sz *= line_sz */ 116536cb7ceSPaul Burton mul \sz, \sz, \line_sz 117536cb7ceSPaul Burton 118536cb7ceSPaul Burton /* detect log32(sets) */ 119536cb7ceSPaul Burton srl $1, $1, \off + MIPS_CONF1_DS_SHIFT - MIPS_CONF1_DA_SHIFT 120536cb7ceSPaul Burton andi $1, $1, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHIFT) 121536cb7ceSPaul Burton addiu $1, $1, 1 122536cb7ceSPaul Burton andi $1, $1, 0x7 123536cb7ceSPaul Burton 124536cb7ceSPaul Burton /* sz <<= log32(sets) */ 125536cb7ceSPaul Burton sllv \sz, \sz, $1 126536cb7ceSPaul Burton 127536cb7ceSPaul Burton /* sz *= 32 */ 128536cb7ceSPaul Burton li $1, 32 129536cb7ceSPaul Burton mul \sz, \sz, $1 130536cb7ceSPaul Burton10: 131536cb7ceSPaul Burton .set pop 132536cb7ceSPaul Burton .endm 1334a5d8898SPaul Burton/* 1344a5d8898SPaul Burton * mips_cache_reset - low level initialisation of the primary caches 1354a5d8898SPaul Burton * 1364a5d8898SPaul Burton * This routine initialises the primary caches to ensure that they have good 1374a5d8898SPaul Burton * parity. It must be called by the ROM before any cached locations are used 1384a5d8898SPaul Burton * to prevent the possibility of data with bad parity being written to memory. 1394a5d8898SPaul Burton * 1404a5d8898SPaul Burton * To initialise the instruction cache it is essential that a source of data 1414a5d8898SPaul Burton * with good parity is available. This routine will initialise an area of 1424a5d8898SPaul Burton * memory starting at location zero to be used as a source of parity. 1434a5d8898SPaul Burton * 1444a5d8898SPaul Burton * RETURNS: N/A 1454a5d8898SPaul Burton * 1464a5d8898SPaul Burton */ 1474a5d8898SPaul BurtonNESTED(mips_cache_reset, 0, ra) 1484a5d8898SPaul Burton move RA, ra 1494a5d8898SPaul Burton 1504a5d8898SPaul Burton#ifdef CONFIG_SYS_ICACHE_SIZE 1514a5d8898SPaul Burton li t2, CONFIG_SYS_ICACHE_SIZE 152536cb7ceSPaul Burton li t8, CONFIG_SYS_CACHELINE_SIZE 1534a5d8898SPaul Burton#else 154536cb7ceSPaul Burton l1_info t2, t8, MIPS_CONF1_IA_SHIFT 1554a5d8898SPaul Burton#endif 1564a5d8898SPaul Burton 1574a5d8898SPaul Burton#ifdef CONFIG_SYS_DCACHE_SIZE 1584a5d8898SPaul Burton li t3, CONFIG_SYS_DCACHE_SIZE 159536cb7ceSPaul Burton li t9, CONFIG_SYS_CACHELINE_SIZE 1604a5d8898SPaul Burton#else 161536cb7ceSPaul Burton l1_info t3, t9, MIPS_CONF1_DA_SHIFT 1624a5d8898SPaul Burton#endif 1634a5d8898SPaul Burton 1644a5d8898SPaul Burton /* Determine the largest L1 cache size */ 1654a5d8898SPaul Burton#if defined(CONFIG_SYS_ICACHE_SIZE) && defined(CONFIG_SYS_DCACHE_SIZE) 1664a5d8898SPaul Burton#if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE 1674a5d8898SPaul Burton li v0, CONFIG_SYS_ICACHE_SIZE 1684a5d8898SPaul Burton#else 1694a5d8898SPaul Burton li v0, CONFIG_SYS_DCACHE_SIZE 1704a5d8898SPaul Burton#endif 1714a5d8898SPaul Burton#else 1724a5d8898SPaul Burton move v0, t2 1734a5d8898SPaul Burton sltu t1, t2, t3 1744a5d8898SPaul Burton movn v0, t3, t1 1754a5d8898SPaul Burton#endif 1764a5d8898SPaul Burton /* 1774a5d8898SPaul Burton * Now clear that much memory starting from zero. 1784a5d8898SPaul Burton */ 1794a5d8898SPaul Burton PTR_LI a0, CKSEG1 1804a5d8898SPaul Burton PTR_ADDU a1, a0, v0 1814a5d8898SPaul Burton2: PTR_ADDIU a0, 64 1824a5d8898SPaul Burton f_fill64 a0, -64, zero 1834a5d8898SPaul Burton bne a0, a1, 2b 1844a5d8898SPaul Burton 1854a5d8898SPaul Burton /* 1864a5d8898SPaul Burton * The caches are probably in an indeterminate state, 1874a5d8898SPaul Burton * so we force good parity into them by doing an 1884a5d8898SPaul Burton * invalidate, load/fill, invalidate for each line. 1894a5d8898SPaul Burton */ 1904a5d8898SPaul Burton 1914a5d8898SPaul Burton /* 1924a5d8898SPaul Burton * Assume bottom of RAM will generate good parity for the cache. 1934a5d8898SPaul Burton */ 1944a5d8898SPaul Burton 1954a5d8898SPaul Burton /* 1964a5d8898SPaul Burton * Initialize the I-cache first, 1974a5d8898SPaul Burton */ 1984a5d8898SPaul Burton move a1, t2 1994a5d8898SPaul Burton move a2, t8 2004a5d8898SPaul Burton PTR_LA v1, mips_init_icache 2014a5d8898SPaul Burton jalr v1 2024a5d8898SPaul Burton 2034a5d8898SPaul Burton /* 2044a5d8898SPaul Burton * then initialize D-cache. 2054a5d8898SPaul Burton */ 2064a5d8898SPaul Burton move a1, t3 2074a5d8898SPaul Burton move a2, t9 2084a5d8898SPaul Burton PTR_LA v1, mips_init_dcache 2094a5d8898SPaul Burton jalr v1 2104a5d8898SPaul Burton 2114a5d8898SPaul Burton jr RA 2124a5d8898SPaul Burton END(mips_cache_reset) 2134a5d8898SPaul Burton 2144a5d8898SPaul Burton/* 2154a5d8898SPaul Burton * dcache_status - get cache status 2164a5d8898SPaul Burton * 2174a5d8898SPaul Burton * RETURNS: 0 - cache disabled; 1 - cache enabled 2184a5d8898SPaul Burton * 2194a5d8898SPaul Burton */ 2204a5d8898SPaul BurtonLEAF(dcache_status) 2214a5d8898SPaul Burton mfc0 t0, CP0_CONFIG 2224a5d8898SPaul Burton li t1, CONF_CM_UNCACHED 2234a5d8898SPaul Burton andi t0, t0, CONF_CM_CMASK 2244a5d8898SPaul Burton move v0, zero 2254a5d8898SPaul Burton beq t0, t1, 2f 2264a5d8898SPaul Burton li v0, 1 2274a5d8898SPaul Burton2: jr ra 2284a5d8898SPaul Burton END(dcache_status) 2294a5d8898SPaul Burton 2304a5d8898SPaul Burton/* 2314a5d8898SPaul Burton * dcache_disable - disable cache 2324a5d8898SPaul Burton * 2334a5d8898SPaul Burton * RETURNS: N/A 2344a5d8898SPaul Burton * 2354a5d8898SPaul Burton */ 2364a5d8898SPaul BurtonLEAF(dcache_disable) 2374a5d8898SPaul Burton mfc0 t0, CP0_CONFIG 2384a5d8898SPaul Burton li t1, -8 2394a5d8898SPaul Burton and t0, t0, t1 2404a5d8898SPaul Burton ori t0, t0, CONF_CM_UNCACHED 2414a5d8898SPaul Burton mtc0 t0, CP0_CONFIG 2424a5d8898SPaul Burton jr ra 2434a5d8898SPaul Burton END(dcache_disable) 2444a5d8898SPaul Burton 2454a5d8898SPaul Burton/* 2464a5d8898SPaul Burton * dcache_enable - enable cache 2474a5d8898SPaul Burton * 2484a5d8898SPaul Burton * RETURNS: N/A 2494a5d8898SPaul Burton * 2504a5d8898SPaul Burton */ 2514a5d8898SPaul BurtonLEAF(dcache_enable) 2524a5d8898SPaul Burton mfc0 t0, CP0_CONFIG 2534a5d8898SPaul Burton ori t0, CONF_CM_CMASK 2544a5d8898SPaul Burton xori t0, CONF_CM_CMASK 2554a5d8898SPaul Burton ori t0, CONFIG_SYS_MIPS_CACHE_MODE 2564a5d8898SPaul Burton mtc0 t0, CP0_CONFIG 2574a5d8898SPaul Burton jr ra 2584a5d8898SPaul Burton END(dcache_enable) 259