1*4a5d8898SPaul Burton/* 2*4a5d8898SPaul Burton * Cache-handling routined for MIPS CPUs 3*4a5d8898SPaul Burton * 4*4a5d8898SPaul Burton * Copyright (c) 2003 Wolfgang Denk <wd@denx.de> 5*4a5d8898SPaul Burton * 6*4a5d8898SPaul Burton * SPDX-License-Identifier: GPL-2.0+ 7*4a5d8898SPaul Burton */ 8*4a5d8898SPaul Burton 9*4a5d8898SPaul Burton#include <asm-offsets.h> 10*4a5d8898SPaul Burton#include <config.h> 11*4a5d8898SPaul Burton#include <asm/asm.h> 12*4a5d8898SPaul Burton#include <asm/regdef.h> 13*4a5d8898SPaul Burton#include <asm/mipsregs.h> 14*4a5d8898SPaul Burton#include <asm/addrspace.h> 15*4a5d8898SPaul Burton#include <asm/cacheops.h> 16*4a5d8898SPaul Burton 17*4a5d8898SPaul Burton#ifndef CONFIG_SYS_MIPS_CACHE_MODE 18*4a5d8898SPaul Burton#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT 19*4a5d8898SPaul Burton#endif 20*4a5d8898SPaul Burton 21*4a5d8898SPaul Burton#ifdef CONFIG_64BIT 22*4a5d8898SPaul Burton# define RA ta3 23*4a5d8898SPaul Burton#else 24*4a5d8898SPaul Burton# define RA t7 25*4a5d8898SPaul Burton#endif 26*4a5d8898SPaul Burton 27*4a5d8898SPaul Burton#define INDEX_BASE CKSEG0 28*4a5d8898SPaul Burton 29*4a5d8898SPaul Burton .macro f_fill64 dst, offset, val 30*4a5d8898SPaul Burton LONG_S \val, (\offset + 0 * LONGSIZE)(\dst) 31*4a5d8898SPaul Burton LONG_S \val, (\offset + 1 * LONGSIZE)(\dst) 32*4a5d8898SPaul Burton LONG_S \val, (\offset + 2 * LONGSIZE)(\dst) 33*4a5d8898SPaul Burton LONG_S \val, (\offset + 3 * LONGSIZE)(\dst) 34*4a5d8898SPaul Burton LONG_S \val, (\offset + 4 * LONGSIZE)(\dst) 35*4a5d8898SPaul Burton LONG_S \val, (\offset + 5 * LONGSIZE)(\dst) 36*4a5d8898SPaul Burton LONG_S \val, (\offset + 6 * LONGSIZE)(\dst) 37*4a5d8898SPaul Burton LONG_S \val, (\offset + 7 * LONGSIZE)(\dst) 38*4a5d8898SPaul Burton#if LONGSIZE == 4 39*4a5d8898SPaul Burton LONG_S \val, (\offset + 8 * LONGSIZE)(\dst) 40*4a5d8898SPaul Burton LONG_S \val, (\offset + 9 * LONGSIZE)(\dst) 41*4a5d8898SPaul Burton LONG_S \val, (\offset + 10 * LONGSIZE)(\dst) 42*4a5d8898SPaul Burton LONG_S \val, (\offset + 11 * LONGSIZE)(\dst) 43*4a5d8898SPaul Burton LONG_S \val, (\offset + 12 * LONGSIZE)(\dst) 44*4a5d8898SPaul Burton LONG_S \val, (\offset + 13 * LONGSIZE)(\dst) 45*4a5d8898SPaul Burton LONG_S \val, (\offset + 14 * LONGSIZE)(\dst) 46*4a5d8898SPaul Burton LONG_S \val, (\offset + 15 * LONGSIZE)(\dst) 47*4a5d8898SPaul Burton#endif 48*4a5d8898SPaul Burton .endm 49*4a5d8898SPaul Burton 50*4a5d8898SPaul Burton/* 51*4a5d8898SPaul Burton * mips_init_icache(uint PRId, ulong icache_size, unchar icache_linesz) 52*4a5d8898SPaul Burton */ 53*4a5d8898SPaul BurtonLEAF(mips_init_icache) 54*4a5d8898SPaul Burton blez a1, 9f 55*4a5d8898SPaul Burton mtc0 zero, CP0_TAGLO 56*4a5d8898SPaul Burton /* clear tag to invalidate */ 57*4a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 58*4a5d8898SPaul Burton PTR_ADDU t1, t0, a1 59*4a5d8898SPaul Burton1: cache INDEX_STORE_TAG_I, 0(t0) 60*4a5d8898SPaul Burton PTR_ADDU t0, a2 61*4a5d8898SPaul Burton bne t0, t1, 1b 62*4a5d8898SPaul Burton /* fill once, so data field parity is correct */ 63*4a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 64*4a5d8898SPaul Burton2: cache FILL, 0(t0) 65*4a5d8898SPaul Burton PTR_ADDU t0, a2 66*4a5d8898SPaul Burton bne t0, t1, 2b 67*4a5d8898SPaul Burton /* invalidate again - prudent but not strictly neccessary */ 68*4a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 69*4a5d8898SPaul Burton1: cache INDEX_STORE_TAG_I, 0(t0) 70*4a5d8898SPaul Burton PTR_ADDU t0, a2 71*4a5d8898SPaul Burton bne t0, t1, 1b 72*4a5d8898SPaul Burton9: jr ra 73*4a5d8898SPaul Burton END(mips_init_icache) 74*4a5d8898SPaul Burton 75*4a5d8898SPaul Burton/* 76*4a5d8898SPaul Burton * mips_init_dcache(uint PRId, ulong dcache_size, unchar dcache_linesz) 77*4a5d8898SPaul Burton */ 78*4a5d8898SPaul BurtonLEAF(mips_init_dcache) 79*4a5d8898SPaul Burton blez a1, 9f 80*4a5d8898SPaul Burton mtc0 zero, CP0_TAGLO 81*4a5d8898SPaul Burton /* clear all tags */ 82*4a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 83*4a5d8898SPaul Burton PTR_ADDU t1, t0, a1 84*4a5d8898SPaul Burton1: cache INDEX_STORE_TAG_D, 0(t0) 85*4a5d8898SPaul Burton PTR_ADDU t0, a2 86*4a5d8898SPaul Burton bne t0, t1, 1b 87*4a5d8898SPaul Burton /* load from each line (in cached space) */ 88*4a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 89*4a5d8898SPaul Burton2: LONG_L zero, 0(t0) 90*4a5d8898SPaul Burton PTR_ADDU t0, a2 91*4a5d8898SPaul Burton bne t0, t1, 2b 92*4a5d8898SPaul Burton /* clear all tags */ 93*4a5d8898SPaul Burton PTR_LI t0, INDEX_BASE 94*4a5d8898SPaul Burton1: cache INDEX_STORE_TAG_D, 0(t0) 95*4a5d8898SPaul Burton PTR_ADDU t0, a2 96*4a5d8898SPaul Burton bne t0, t1, 1b 97*4a5d8898SPaul Burton9: jr ra 98*4a5d8898SPaul Burton END(mips_init_dcache) 99*4a5d8898SPaul Burton 100*4a5d8898SPaul Burton/* 101*4a5d8898SPaul Burton * mips_cache_reset - low level initialisation of the primary caches 102*4a5d8898SPaul Burton * 103*4a5d8898SPaul Burton * This routine initialises the primary caches to ensure that they have good 104*4a5d8898SPaul Burton * parity. It must be called by the ROM before any cached locations are used 105*4a5d8898SPaul Burton * to prevent the possibility of data with bad parity being written to memory. 106*4a5d8898SPaul Burton * 107*4a5d8898SPaul Burton * To initialise the instruction cache it is essential that a source of data 108*4a5d8898SPaul Burton * with good parity is available. This routine will initialise an area of 109*4a5d8898SPaul Burton * memory starting at location zero to be used as a source of parity. 110*4a5d8898SPaul Burton * 111*4a5d8898SPaul Burton * RETURNS: N/A 112*4a5d8898SPaul Burton * 113*4a5d8898SPaul Burton */ 114*4a5d8898SPaul BurtonNESTED(mips_cache_reset, 0, ra) 115*4a5d8898SPaul Burton move RA, ra 116*4a5d8898SPaul Burton 117*4a5d8898SPaul Burton#if !defined(CONFIG_SYS_ICACHE_SIZE) || !defined(CONFIG_SYS_DCACHE_SIZE) || \ 118*4a5d8898SPaul Burton !defined(CONFIG_SYS_CACHELINE_SIZE) 119*4a5d8898SPaul Burton /* read Config1 for use below */ 120*4a5d8898SPaul Burton mfc0 t5, CP0_CONFIG, 1 121*4a5d8898SPaul Burton#endif 122*4a5d8898SPaul Burton 123*4a5d8898SPaul Burton#ifdef CONFIG_SYS_CACHELINE_SIZE 124*4a5d8898SPaul Burton li t9, CONFIG_SYS_CACHELINE_SIZE 125*4a5d8898SPaul Burton li t8, CONFIG_SYS_CACHELINE_SIZE 126*4a5d8898SPaul Burton#else 127*4a5d8898SPaul Burton /* Detect I-cache line size. */ 128*4a5d8898SPaul Burton srl t8, t5, MIPS_CONF1_IL_SHIFT 129*4a5d8898SPaul Burton andi t8, t8, (MIPS_CONF1_IL >> MIPS_CONF1_IL_SHIFT) 130*4a5d8898SPaul Burton beqz t8, 1f 131*4a5d8898SPaul Burton li t6, 2 132*4a5d8898SPaul Burton sllv t8, t6, t8 133*4a5d8898SPaul Burton 134*4a5d8898SPaul Burton1: /* Detect D-cache line size. */ 135*4a5d8898SPaul Burton srl t9, t5, MIPS_CONF1_DL_SHIFT 136*4a5d8898SPaul Burton andi t9, t9, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHIFT) 137*4a5d8898SPaul Burton beqz t9, 1f 138*4a5d8898SPaul Burton li t6, 2 139*4a5d8898SPaul Burton sllv t9, t6, t9 140*4a5d8898SPaul Burton1: 141*4a5d8898SPaul Burton#endif 142*4a5d8898SPaul Burton 143*4a5d8898SPaul Burton#ifdef CONFIG_SYS_ICACHE_SIZE 144*4a5d8898SPaul Burton li t2, CONFIG_SYS_ICACHE_SIZE 145*4a5d8898SPaul Burton#else 146*4a5d8898SPaul Burton /* Detect I-cache size. */ 147*4a5d8898SPaul Burton srl t6, t5, MIPS_CONF1_IS_SHIFT 148*4a5d8898SPaul Burton andi t6, t6, (MIPS_CONF1_IS >> MIPS_CONF1_IS_SHIFT) 149*4a5d8898SPaul Burton li t4, 32 150*4a5d8898SPaul Burton xori t2, t6, 0x7 151*4a5d8898SPaul Burton beqz t2, 1f 152*4a5d8898SPaul Burton addi t6, t6, 1 153*4a5d8898SPaul Burton sllv t4, t4, t6 154*4a5d8898SPaul Burton1: /* At this point t4 == I-cache sets. */ 155*4a5d8898SPaul Burton mul t2, t4, t8 156*4a5d8898SPaul Burton srl t6, t5, MIPS_CONF1_IA_SHIFT 157*4a5d8898SPaul Burton andi t6, t6, (MIPS_CONF1_IA >> MIPS_CONF1_IA_SHIFT) 158*4a5d8898SPaul Burton addi t6, t6, 1 159*4a5d8898SPaul Burton /* At this point t6 == I-cache ways. */ 160*4a5d8898SPaul Burton mul t2, t2, t6 161*4a5d8898SPaul Burton#endif 162*4a5d8898SPaul Burton 163*4a5d8898SPaul Burton#ifdef CONFIG_SYS_DCACHE_SIZE 164*4a5d8898SPaul Burton li t3, CONFIG_SYS_DCACHE_SIZE 165*4a5d8898SPaul Burton#else 166*4a5d8898SPaul Burton /* Detect D-cache size. */ 167*4a5d8898SPaul Burton srl t6, t5, MIPS_CONF1_DS_SHIFT 168*4a5d8898SPaul Burton andi t6, t6, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHIFT) 169*4a5d8898SPaul Burton li t4, 32 170*4a5d8898SPaul Burton xori t3, t6, 0x7 171*4a5d8898SPaul Burton beqz t3, 1f 172*4a5d8898SPaul Burton addi t6, t6, 1 173*4a5d8898SPaul Burton sllv t4, t4, t6 174*4a5d8898SPaul Burton1: /* At this point t4 == I-cache sets. */ 175*4a5d8898SPaul Burton mul t3, t4, t9 176*4a5d8898SPaul Burton srl t6, t5, MIPS_CONF1_DA_SHIFT 177*4a5d8898SPaul Burton andi t6, t6, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHIFT) 178*4a5d8898SPaul Burton addi t6, t6, 1 179*4a5d8898SPaul Burton /* At this point t6 == I-cache ways. */ 180*4a5d8898SPaul Burton mul t3, t3, t6 181*4a5d8898SPaul Burton#endif 182*4a5d8898SPaul Burton 183*4a5d8898SPaul Burton /* Determine the largest L1 cache size */ 184*4a5d8898SPaul Burton#if defined(CONFIG_SYS_ICACHE_SIZE) && defined(CONFIG_SYS_DCACHE_SIZE) 185*4a5d8898SPaul Burton#if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE 186*4a5d8898SPaul Burton li v0, CONFIG_SYS_ICACHE_SIZE 187*4a5d8898SPaul Burton#else 188*4a5d8898SPaul Burton li v0, CONFIG_SYS_DCACHE_SIZE 189*4a5d8898SPaul Burton#endif 190*4a5d8898SPaul Burton#else 191*4a5d8898SPaul Burton move v0, t2 192*4a5d8898SPaul Burton sltu t1, t2, t3 193*4a5d8898SPaul Burton movn v0, t3, t1 194*4a5d8898SPaul Burton#endif 195*4a5d8898SPaul Burton /* 196*4a5d8898SPaul Burton * Now clear that much memory starting from zero. 197*4a5d8898SPaul Burton */ 198*4a5d8898SPaul Burton PTR_LI a0, CKSEG1 199*4a5d8898SPaul Burton PTR_ADDU a1, a0, v0 200*4a5d8898SPaul Burton2: PTR_ADDIU a0, 64 201*4a5d8898SPaul Burton f_fill64 a0, -64, zero 202*4a5d8898SPaul Burton bne a0, a1, 2b 203*4a5d8898SPaul Burton 204*4a5d8898SPaul Burton /* 205*4a5d8898SPaul Burton * The caches are probably in an indeterminate state, 206*4a5d8898SPaul Burton * so we force good parity into them by doing an 207*4a5d8898SPaul Burton * invalidate, load/fill, invalidate for each line. 208*4a5d8898SPaul Burton */ 209*4a5d8898SPaul Burton 210*4a5d8898SPaul Burton /* 211*4a5d8898SPaul Burton * Assume bottom of RAM will generate good parity for the cache. 212*4a5d8898SPaul Burton */ 213*4a5d8898SPaul Burton 214*4a5d8898SPaul Burton /* 215*4a5d8898SPaul Burton * Initialize the I-cache first, 216*4a5d8898SPaul Burton */ 217*4a5d8898SPaul Burton move a1, t2 218*4a5d8898SPaul Burton move a2, t8 219*4a5d8898SPaul Burton PTR_LA v1, mips_init_icache 220*4a5d8898SPaul Burton jalr v1 221*4a5d8898SPaul Burton 222*4a5d8898SPaul Burton /* 223*4a5d8898SPaul Burton * then initialize D-cache. 224*4a5d8898SPaul Burton */ 225*4a5d8898SPaul Burton move a1, t3 226*4a5d8898SPaul Burton move a2, t9 227*4a5d8898SPaul Burton PTR_LA v1, mips_init_dcache 228*4a5d8898SPaul Burton jalr v1 229*4a5d8898SPaul Burton 230*4a5d8898SPaul Burton jr RA 231*4a5d8898SPaul Burton END(mips_cache_reset) 232*4a5d8898SPaul Burton 233*4a5d8898SPaul Burton/* 234*4a5d8898SPaul Burton * dcache_status - get cache status 235*4a5d8898SPaul Burton * 236*4a5d8898SPaul Burton * RETURNS: 0 - cache disabled; 1 - cache enabled 237*4a5d8898SPaul Burton * 238*4a5d8898SPaul Burton */ 239*4a5d8898SPaul BurtonLEAF(dcache_status) 240*4a5d8898SPaul Burton mfc0 t0, CP0_CONFIG 241*4a5d8898SPaul Burton li t1, CONF_CM_UNCACHED 242*4a5d8898SPaul Burton andi t0, t0, CONF_CM_CMASK 243*4a5d8898SPaul Burton move v0, zero 244*4a5d8898SPaul Burton beq t0, t1, 2f 245*4a5d8898SPaul Burton li v0, 1 246*4a5d8898SPaul Burton2: jr ra 247*4a5d8898SPaul Burton END(dcache_status) 248*4a5d8898SPaul Burton 249*4a5d8898SPaul Burton/* 250*4a5d8898SPaul Burton * dcache_disable - disable cache 251*4a5d8898SPaul Burton * 252*4a5d8898SPaul Burton * RETURNS: N/A 253*4a5d8898SPaul Burton * 254*4a5d8898SPaul Burton */ 255*4a5d8898SPaul BurtonLEAF(dcache_disable) 256*4a5d8898SPaul Burton mfc0 t0, CP0_CONFIG 257*4a5d8898SPaul Burton li t1, -8 258*4a5d8898SPaul Burton and t0, t0, t1 259*4a5d8898SPaul Burton ori t0, t0, CONF_CM_UNCACHED 260*4a5d8898SPaul Burton mtc0 t0, CP0_CONFIG 261*4a5d8898SPaul Burton jr ra 262*4a5d8898SPaul Burton END(dcache_disable) 263*4a5d8898SPaul Burton 264*4a5d8898SPaul Burton/* 265*4a5d8898SPaul Burton * dcache_enable - enable cache 266*4a5d8898SPaul Burton * 267*4a5d8898SPaul Burton * RETURNS: N/A 268*4a5d8898SPaul Burton * 269*4a5d8898SPaul Burton */ 270*4a5d8898SPaul BurtonLEAF(dcache_enable) 271*4a5d8898SPaul Burton mfc0 t0, CP0_CONFIG 272*4a5d8898SPaul Burton ori t0, CONF_CM_CMASK 273*4a5d8898SPaul Burton xori t0, CONF_CM_CMASK 274*4a5d8898SPaul Burton ori t0, CONFIG_SYS_MIPS_CACHE_MODE 275*4a5d8898SPaul Burton mtc0 t0, CP0_CONFIG 276*4a5d8898SPaul Burton jr ra 277*4a5d8898SPaul Burton END(dcache_enable) 278