1660d5f0dSAlexey Brodkin /* 2660d5f0dSAlexey Brodkin * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. 3660d5f0dSAlexey Brodkin * 4660d5f0dSAlexey Brodkin * SPDX-License-Identifier: GPL-2.0+ 5660d5f0dSAlexey Brodkin */ 6660d5f0dSAlexey Brodkin 7660d5f0dSAlexey Brodkin #include <config.h> 8660d5f0dSAlexey Brodkin #include <asm/arcregs.h> 9205e7a7bSAlexey Brodkin #include <asm/cache.h> 10660d5f0dSAlexey Brodkin 11660d5f0dSAlexey Brodkin /* Bit values in IC_CTRL */ 12660d5f0dSAlexey Brodkin #define IC_CTRL_CACHE_DISABLE (1 << 0) 13660d5f0dSAlexey Brodkin 14660d5f0dSAlexey Brodkin /* Bit values in DC_CTRL */ 15660d5f0dSAlexey Brodkin #define DC_CTRL_CACHE_DISABLE (1 << 0) 16660d5f0dSAlexey Brodkin #define DC_CTRL_INV_MODE_FLUSH (1 << 6) 17660d5f0dSAlexey Brodkin #define DC_CTRL_FLUSH_STATUS (1 << 8) 18660d5f0dSAlexey Brodkin #define CACHE_VER_NUM_MASK 0xF 19*6eb15e50SAlexey Brodkin #define SLC_CTRL_SB (1 << 2) 20660d5f0dSAlexey Brodkin 21660d5f0dSAlexey Brodkin int icache_status(void) 22660d5f0dSAlexey Brodkin { 23660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 24660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 25660d5f0dSAlexey Brodkin return 0; 26660d5f0dSAlexey Brodkin 27660d5f0dSAlexey Brodkin return (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) != 28660d5f0dSAlexey Brodkin IC_CTRL_CACHE_DISABLE; 29660d5f0dSAlexey Brodkin } 30660d5f0dSAlexey Brodkin 31660d5f0dSAlexey Brodkin void icache_enable(void) 32660d5f0dSAlexey Brodkin { 33660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 34660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 35660d5f0dSAlexey Brodkin return; 36660d5f0dSAlexey Brodkin 37660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) & 38660d5f0dSAlexey Brodkin ~IC_CTRL_CACHE_DISABLE); 39660d5f0dSAlexey Brodkin } 40660d5f0dSAlexey Brodkin 41660d5f0dSAlexey Brodkin void icache_disable(void) 42660d5f0dSAlexey Brodkin { 43660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 44660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 45660d5f0dSAlexey Brodkin return; 46660d5f0dSAlexey Brodkin 47660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) | 48660d5f0dSAlexey Brodkin IC_CTRL_CACHE_DISABLE); 49660d5f0dSAlexey Brodkin } 50660d5f0dSAlexey Brodkin 51660d5f0dSAlexey Brodkin void invalidate_icache_all(void) 52660d5f0dSAlexey Brodkin { 53ae4a351aSAlexey Brodkin /* If no cache in CPU exit immediately */ 54ae4a351aSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 55ae4a351aSAlexey Brodkin return; 56ae4a351aSAlexey Brodkin 57660d5f0dSAlexey Brodkin /* Any write to IC_IVIC register triggers invalidation of entire I$ */ 58660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_IVIC, 1); 59660d5f0dSAlexey Brodkin } 60660d5f0dSAlexey Brodkin 61660d5f0dSAlexey Brodkin int dcache_status(void) 62660d5f0dSAlexey Brodkin { 63660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 64660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 65660d5f0dSAlexey Brodkin return 0; 66660d5f0dSAlexey Brodkin 67660d5f0dSAlexey Brodkin return (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) != 68660d5f0dSAlexey Brodkin DC_CTRL_CACHE_DISABLE; 69660d5f0dSAlexey Brodkin } 70660d5f0dSAlexey Brodkin 71660d5f0dSAlexey Brodkin void dcache_enable(void) 72660d5f0dSAlexey Brodkin { 73660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 74660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 75660d5f0dSAlexey Brodkin return; 76660d5f0dSAlexey Brodkin 77660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) & 78660d5f0dSAlexey Brodkin ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE)); 79660d5f0dSAlexey Brodkin } 80660d5f0dSAlexey Brodkin 81660d5f0dSAlexey Brodkin void dcache_disable(void) 82660d5f0dSAlexey Brodkin { 83660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 84660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 85660d5f0dSAlexey Brodkin return; 86660d5f0dSAlexey Brodkin 87660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) | 88660d5f0dSAlexey Brodkin DC_CTRL_CACHE_DISABLE); 89660d5f0dSAlexey Brodkin } 90660d5f0dSAlexey Brodkin 91660d5f0dSAlexey Brodkin void flush_dcache_all(void) 92660d5f0dSAlexey Brodkin { 93660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 94660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 95660d5f0dSAlexey Brodkin return; 96660d5f0dSAlexey Brodkin 97660d5f0dSAlexey Brodkin /* Do flush of entire cache */ 98660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_FLSH, 1); 99660d5f0dSAlexey Brodkin 100660d5f0dSAlexey Brodkin /* Wait flush end */ 101660d5f0dSAlexey Brodkin while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) 102660d5f0dSAlexey Brodkin ; 103660d5f0dSAlexey Brodkin } 104660d5f0dSAlexey Brodkin 105660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 106660d5f0dSAlexey Brodkin static void dcache_flush_line(unsigned addr) 107660d5f0dSAlexey Brodkin { 1085ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 109660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_PTAG, addr); 110660d5f0dSAlexey Brodkin #endif 111660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_FLDL, addr); 112660d5f0dSAlexey Brodkin 113660d5f0dSAlexey Brodkin /* Wait flush end */ 114660d5f0dSAlexey Brodkin while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) 115660d5f0dSAlexey Brodkin ; 116660d5f0dSAlexey Brodkin 117660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_ICACHE_OFF 118660d5f0dSAlexey Brodkin /* 119660d5f0dSAlexey Brodkin * Invalidate I$ for addresses range just flushed from D$. 120660d5f0dSAlexey Brodkin * If we try to execute data flushed above it will be valid/correct 121660d5f0dSAlexey Brodkin */ 1225ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 123660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_PTAG, addr); 124660d5f0dSAlexey Brodkin #endif 125660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_IVIL, addr); 126660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_ICACHE_OFF */ 127660d5f0dSAlexey Brodkin } 128660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */ 129660d5f0dSAlexey Brodkin 130660d5f0dSAlexey Brodkin void flush_dcache_range(unsigned long start, unsigned long end) 131660d5f0dSAlexey Brodkin { 132660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 133660d5f0dSAlexey Brodkin unsigned int addr; 134660d5f0dSAlexey Brodkin 135660d5f0dSAlexey Brodkin start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 136660d5f0dSAlexey Brodkin end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 137660d5f0dSAlexey Brodkin 138660d5f0dSAlexey Brodkin for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) 139660d5f0dSAlexey Brodkin dcache_flush_line(addr); 140660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */ 141660d5f0dSAlexey Brodkin } 142660d5f0dSAlexey Brodkin 143660d5f0dSAlexey Brodkin void invalidate_dcache_range(unsigned long start, unsigned long end) 144660d5f0dSAlexey Brodkin { 145660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 146660d5f0dSAlexey Brodkin unsigned int addr; 147660d5f0dSAlexey Brodkin 148660d5f0dSAlexey Brodkin start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 149660d5f0dSAlexey Brodkin end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 150660d5f0dSAlexey Brodkin 151660d5f0dSAlexey Brodkin for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) { 1525ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 153660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_PTAG, addr); 154660d5f0dSAlexey Brodkin #endif 155660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_IVDL, addr); 156660d5f0dSAlexey Brodkin } 157660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */ 158660d5f0dSAlexey Brodkin } 159660d5f0dSAlexey Brodkin 160660d5f0dSAlexey Brodkin void invalidate_dcache_all(void) 161660d5f0dSAlexey Brodkin { 162ae4a351aSAlexey Brodkin /* If no cache in CPU exit immediately */ 163ae4a351aSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 164ae4a351aSAlexey Brodkin return; 165ae4a351aSAlexey Brodkin 166660d5f0dSAlexey Brodkin /* Write 1 to DC_IVDC register triggers invalidation of entire D$ */ 167660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_IVDC, 1); 168660d5f0dSAlexey Brodkin } 169660d5f0dSAlexey Brodkin 170660d5f0dSAlexey Brodkin void flush_cache(unsigned long start, unsigned long size) 171660d5f0dSAlexey Brodkin { 172660d5f0dSAlexey Brodkin flush_dcache_range(start, start + size); 173660d5f0dSAlexey Brodkin } 174*6eb15e50SAlexey Brodkin 175*6eb15e50SAlexey Brodkin #ifdef CONFIG_ISA_ARCV2 176*6eb15e50SAlexey Brodkin void slc_enable(void) 177*6eb15e50SAlexey Brodkin { 178*6eb15e50SAlexey Brodkin /* If SLC ver = 0, no SLC present in CPU */ 179*6eb15e50SAlexey Brodkin if (!(read_aux_reg(ARC_BCR_SLC) & 0xff)) 180*6eb15e50SAlexey Brodkin return; 181*6eb15e50SAlexey Brodkin 182*6eb15e50SAlexey Brodkin write_aux_reg(ARC_AUX_SLC_CONTROL, 183*6eb15e50SAlexey Brodkin read_aux_reg(ARC_AUX_SLC_CONTROL) & ~1); 184*6eb15e50SAlexey Brodkin } 185*6eb15e50SAlexey Brodkin 186*6eb15e50SAlexey Brodkin void slc_disable(void) 187*6eb15e50SAlexey Brodkin { 188*6eb15e50SAlexey Brodkin /* If SLC ver = 0, no SLC present in CPU */ 189*6eb15e50SAlexey Brodkin if (!(read_aux_reg(ARC_BCR_SLC) & 0xff)) 190*6eb15e50SAlexey Brodkin return; 191*6eb15e50SAlexey Brodkin 192*6eb15e50SAlexey Brodkin write_aux_reg(ARC_AUX_SLC_CONTROL, 193*6eb15e50SAlexey Brodkin read_aux_reg(ARC_AUX_SLC_CONTROL) | 1); 194*6eb15e50SAlexey Brodkin } 195*6eb15e50SAlexey Brodkin 196*6eb15e50SAlexey Brodkin void slc_flush(void) 197*6eb15e50SAlexey Brodkin { 198*6eb15e50SAlexey Brodkin /* If SLC ver = 0, no SLC present in CPU */ 199*6eb15e50SAlexey Brodkin if (!(read_aux_reg(ARC_BCR_SLC) & 0xff)) 200*6eb15e50SAlexey Brodkin return; 201*6eb15e50SAlexey Brodkin 202*6eb15e50SAlexey Brodkin write_aux_reg(ARC_AUX_SLC_FLUSH, 1); 203*6eb15e50SAlexey Brodkin 204*6eb15e50SAlexey Brodkin /* Wait flush end */ 205*6eb15e50SAlexey Brodkin while (read_aux_reg(ARC_AUX_SLC_CONTROL) & SLC_CTRL_SB) 206*6eb15e50SAlexey Brodkin ; 207*6eb15e50SAlexey Brodkin } 208*6eb15e50SAlexey Brodkin 209*6eb15e50SAlexey Brodkin void slc_invalidate(void) 210*6eb15e50SAlexey Brodkin { 211*6eb15e50SAlexey Brodkin /* If SLC ver = 0, no SLC present in CPU */ 212*6eb15e50SAlexey Brodkin if (!(read_aux_reg(ARC_BCR_SLC) & 0xff)) 213*6eb15e50SAlexey Brodkin return; 214*6eb15e50SAlexey Brodkin 215*6eb15e50SAlexey Brodkin write_aux_reg(ARC_AUX_SLC_INVALIDATE, 1); 216*6eb15e50SAlexey Brodkin } 217*6eb15e50SAlexey Brodkin 218*6eb15e50SAlexey Brodkin #endif /* CONFIG_ISA_ARCV2 */ 219