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 504a5d8898SPaul Burton/* 514a5d8898SPaul Burton * mips_init_icache(uint PRId, ulong icache_size, unchar icache_linesz) 524a5d8898SPaul Burton */ 534a5d8898SPaul BurtonLEAF(mips_init_icache) 544a5d8898SPaul Burton blez a1, 9f 554a5d8898SPaul Burton mtc0 zero, CP0_TAGLO 564a5d8898SPaul Burton /* clear tag to invalidate */ 574a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 584a5d8898SPaul Burton PTR_ADDU t1, t0, a1 594a5d8898SPaul Burton1: cache INDEX_STORE_TAG_I, 0(t0) 604a5d8898SPaul Burton PTR_ADDU t0, a2 614a5d8898SPaul Burton bne t0, t1, 1b 624a5d8898SPaul Burton /* fill once, so data field parity is correct */ 634a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 644a5d8898SPaul Burton2: cache FILL, 0(t0) 654a5d8898SPaul Burton PTR_ADDU t0, a2 664a5d8898SPaul Burton bne t0, t1, 2b 674a5d8898SPaul Burton /* invalidate again - prudent but not strictly neccessary */ 684a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 694a5d8898SPaul Burton1: cache INDEX_STORE_TAG_I, 0(t0) 704a5d8898SPaul Burton PTR_ADDU t0, a2 714a5d8898SPaul Burton bne t0, t1, 1b 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 /* clear all tags */ 824a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 834a5d8898SPaul Burton PTR_ADDU t1, t0, a1 844a5d8898SPaul Burton1: cache INDEX_STORE_TAG_D, 0(t0) 854a5d8898SPaul Burton PTR_ADDU t0, a2 864a5d8898SPaul Burton bne t0, t1, 1b 874a5d8898SPaul Burton /* load from each line (in cached space) */ 884a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 894a5d8898SPaul Burton2: LONG_L zero, 0(t0) 904a5d8898SPaul Burton PTR_ADDU t0, a2 914a5d8898SPaul Burton bne t0, t1, 2b 924a5d8898SPaul Burton /* clear all tags */ 934a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 944a5d8898SPaul Burton1: cache INDEX_STORE_TAG_D, 0(t0) 954a5d8898SPaul Burton PTR_ADDU t0, a2 964a5d8898SPaul Burton bne t0, t1, 1b 974a5d8898SPaul Burton9: jr ra 984a5d8898SPaul Burton END(mips_init_dcache) 994a5d8898SPaul Burton 100*536cb7ceSPaul Burton .macro l1_info sz, line_sz, off 101*536cb7ceSPaul Burton .set push 102*536cb7ceSPaul Burton .set noat 103*536cb7ceSPaul Burton 104*536cb7ceSPaul Burton mfc0 $1, CP0_CONFIG, 1 105*536cb7ceSPaul Burton 106*536cb7ceSPaul Burton /* detect line size */ 107*536cb7ceSPaul Burton srl \line_sz, $1, \off + MIPS_CONF1_DL_SHIFT - MIPS_CONF1_DA_SHIFT 108*536cb7ceSPaul Burton andi \line_sz, \line_sz, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHIFT) 109*536cb7ceSPaul Burton move \sz, zero 110*536cb7ceSPaul Burton beqz \line_sz, 10f 111*536cb7ceSPaul Burton li \sz, 2 112*536cb7ceSPaul Burton sllv \line_sz, \sz, \line_sz 113*536cb7ceSPaul Burton 114*536cb7ceSPaul Burton /* detect associativity */ 115*536cb7ceSPaul Burton srl \sz, $1, \off + MIPS_CONF1_DA_SHIFT - MIPS_CONF1_DA_SHIFT 116*536cb7ceSPaul Burton andi \sz, \sz, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHIFT) 117*536cb7ceSPaul Burton addi \sz, \sz, 1 118*536cb7ceSPaul Burton 119*536cb7ceSPaul Burton /* sz *= line_sz */ 120*536cb7ceSPaul Burton mul \sz, \sz, \line_sz 121*536cb7ceSPaul Burton 122*536cb7ceSPaul Burton /* detect log32(sets) */ 123*536cb7ceSPaul Burton srl $1, $1, \off + MIPS_CONF1_DS_SHIFT - MIPS_CONF1_DA_SHIFT 124*536cb7ceSPaul Burton andi $1, $1, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHIFT) 125*536cb7ceSPaul Burton addiu $1, $1, 1 126*536cb7ceSPaul Burton andi $1, $1, 0x7 127*536cb7ceSPaul Burton 128*536cb7ceSPaul Burton /* sz <<= log32(sets) */ 129*536cb7ceSPaul Burton sllv \sz, \sz, $1 130*536cb7ceSPaul Burton 131*536cb7ceSPaul Burton /* sz *= 32 */ 132*536cb7ceSPaul Burton li $1, 32 133*536cb7ceSPaul Burton mul \sz, \sz, $1 134*536cb7ceSPaul Burton10: 135*536cb7ceSPaul Burton .set pop 136*536cb7ceSPaul Burton .endm 1374a5d8898SPaul Burton/* 1384a5d8898SPaul Burton * mips_cache_reset - low level initialisation of the primary caches 1394a5d8898SPaul Burton * 1404a5d8898SPaul Burton * This routine initialises the primary caches to ensure that they have good 1414a5d8898SPaul Burton * parity. It must be called by the ROM before any cached locations are used 1424a5d8898SPaul Burton * to prevent the possibility of data with bad parity being written to memory. 1434a5d8898SPaul Burton * 1444a5d8898SPaul Burton * To initialise the instruction cache it is essential that a source of data 1454a5d8898SPaul Burton * with good parity is available. This routine will initialise an area of 1464a5d8898SPaul Burton * memory starting at location zero to be used as a source of parity. 1474a5d8898SPaul Burton * 1484a5d8898SPaul Burton * RETURNS: N/A 1494a5d8898SPaul Burton * 1504a5d8898SPaul Burton */ 1514a5d8898SPaul BurtonNESTED(mips_cache_reset, 0, ra) 1524a5d8898SPaul Burton move RA, ra 1534a5d8898SPaul Burton 1544a5d8898SPaul Burton#ifdef CONFIG_SYS_ICACHE_SIZE 1554a5d8898SPaul Burton li t2, CONFIG_SYS_ICACHE_SIZE 156*536cb7ceSPaul Burton li t8, CONFIG_SYS_CACHELINE_SIZE 1574a5d8898SPaul Burton#else 158*536cb7ceSPaul Burton l1_info t2, t8, MIPS_CONF1_IA_SHIFT 1594a5d8898SPaul Burton#endif 1604a5d8898SPaul Burton 1614a5d8898SPaul Burton#ifdef CONFIG_SYS_DCACHE_SIZE 1624a5d8898SPaul Burton li t3, CONFIG_SYS_DCACHE_SIZE 163*536cb7ceSPaul Burton li t9, CONFIG_SYS_CACHELINE_SIZE 1644a5d8898SPaul Burton#else 165*536cb7ceSPaul Burton l1_info t3, t9, MIPS_CONF1_DA_SHIFT 1664a5d8898SPaul Burton#endif 1674a5d8898SPaul Burton 1684a5d8898SPaul Burton /* Determine the largest L1 cache size */ 1694a5d8898SPaul Burton#if defined(CONFIG_SYS_ICACHE_SIZE) && defined(CONFIG_SYS_DCACHE_SIZE) 1704a5d8898SPaul Burton#if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE 1714a5d8898SPaul Burton li v0, CONFIG_SYS_ICACHE_SIZE 1724a5d8898SPaul Burton#else 1734a5d8898SPaul Burton li v0, CONFIG_SYS_DCACHE_SIZE 1744a5d8898SPaul Burton#endif 1754a5d8898SPaul Burton#else 1764a5d8898SPaul Burton move v0, t2 1774a5d8898SPaul Burton sltu t1, t2, t3 1784a5d8898SPaul Burton movn v0, t3, t1 1794a5d8898SPaul Burton#endif 1804a5d8898SPaul Burton /* 1814a5d8898SPaul Burton * Now clear that much memory starting from zero. 1824a5d8898SPaul Burton */ 1834a5d8898SPaul Burton PTR_LI a0, CKSEG1 1844a5d8898SPaul Burton PTR_ADDU a1, a0, v0 1854a5d8898SPaul Burton2: PTR_ADDIU a0, 64 1864a5d8898SPaul Burton f_fill64 a0, -64, zero 1874a5d8898SPaul Burton bne a0, a1, 2b 1884a5d8898SPaul Burton 1894a5d8898SPaul Burton /* 1904a5d8898SPaul Burton * The caches are probably in an indeterminate state, 1914a5d8898SPaul Burton * so we force good parity into them by doing an 1924a5d8898SPaul Burton * invalidate, load/fill, invalidate for each line. 1934a5d8898SPaul Burton */ 1944a5d8898SPaul Burton 1954a5d8898SPaul Burton /* 1964a5d8898SPaul Burton * Assume bottom of RAM will generate good parity for the cache. 1974a5d8898SPaul Burton */ 1984a5d8898SPaul Burton 1994a5d8898SPaul Burton /* 2004a5d8898SPaul Burton * Initialize the I-cache first, 2014a5d8898SPaul Burton */ 2024a5d8898SPaul Burton move a1, t2 2034a5d8898SPaul Burton move a2, t8 2044a5d8898SPaul Burton PTR_LA v1, mips_init_icache 2054a5d8898SPaul Burton jalr v1 2064a5d8898SPaul Burton 2074a5d8898SPaul Burton /* 2084a5d8898SPaul Burton * then initialize D-cache. 2094a5d8898SPaul Burton */ 2104a5d8898SPaul Burton move a1, t3 2114a5d8898SPaul Burton move a2, t9 2124a5d8898SPaul Burton PTR_LA v1, mips_init_dcache 2134a5d8898SPaul Burton jalr v1 2144a5d8898SPaul Burton 2154a5d8898SPaul Burton jr RA 2164a5d8898SPaul Burton END(mips_cache_reset) 2174a5d8898SPaul Burton 2184a5d8898SPaul Burton/* 2194a5d8898SPaul Burton * dcache_status - get cache status 2204a5d8898SPaul Burton * 2214a5d8898SPaul Burton * RETURNS: 0 - cache disabled; 1 - cache enabled 2224a5d8898SPaul Burton * 2234a5d8898SPaul Burton */ 2244a5d8898SPaul BurtonLEAF(dcache_status) 2254a5d8898SPaul Burton mfc0 t0, CP0_CONFIG 2264a5d8898SPaul Burton li t1, CONF_CM_UNCACHED 2274a5d8898SPaul Burton andi t0, t0, CONF_CM_CMASK 2284a5d8898SPaul Burton move v0, zero 2294a5d8898SPaul Burton beq t0, t1, 2f 2304a5d8898SPaul Burton li v0, 1 2314a5d8898SPaul Burton2: jr ra 2324a5d8898SPaul Burton END(dcache_status) 2334a5d8898SPaul Burton 2344a5d8898SPaul Burton/* 2354a5d8898SPaul Burton * dcache_disable - disable cache 2364a5d8898SPaul Burton * 2374a5d8898SPaul Burton * RETURNS: N/A 2384a5d8898SPaul Burton * 2394a5d8898SPaul Burton */ 2404a5d8898SPaul BurtonLEAF(dcache_disable) 2414a5d8898SPaul Burton mfc0 t0, CP0_CONFIG 2424a5d8898SPaul Burton li t1, -8 2434a5d8898SPaul Burton and t0, t0, t1 2444a5d8898SPaul Burton ori t0, t0, CONF_CM_UNCACHED 2454a5d8898SPaul Burton mtc0 t0, CP0_CONFIG 2464a5d8898SPaul Burton jr ra 2474a5d8898SPaul Burton END(dcache_disable) 2484a5d8898SPaul Burton 2494a5d8898SPaul Burton/* 2504a5d8898SPaul Burton * dcache_enable - enable cache 2514a5d8898SPaul Burton * 2524a5d8898SPaul Burton * RETURNS: N/A 2534a5d8898SPaul Burton * 2544a5d8898SPaul Burton */ 2554a5d8898SPaul BurtonLEAF(dcache_enable) 2564a5d8898SPaul Burton mfc0 t0, CP0_CONFIG 2574a5d8898SPaul Burton ori t0, CONF_CM_CMASK 2584a5d8898SPaul Burton xori t0, CONF_CM_CMASK 2594a5d8898SPaul Burton ori t0, CONFIG_SYS_MIPS_CACHE_MODE 2604a5d8898SPaul Burton mtc0 t0, CP0_CONFIG 2614a5d8898SPaul Burton jr ra 2624a5d8898SPaul Burton END(dcache_enable) 263