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 19660d5f0dSAlexey Brodkin 20660d5f0dSAlexey Brodkin int icache_status(void) 21660d5f0dSAlexey Brodkin { 22660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 23660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 24660d5f0dSAlexey Brodkin return 0; 25660d5f0dSAlexey Brodkin 26660d5f0dSAlexey Brodkin return (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) != 27660d5f0dSAlexey Brodkin IC_CTRL_CACHE_DISABLE; 28660d5f0dSAlexey Brodkin } 29660d5f0dSAlexey Brodkin 30660d5f0dSAlexey Brodkin void icache_enable(void) 31660d5f0dSAlexey Brodkin { 32660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 33660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 34660d5f0dSAlexey Brodkin return; 35660d5f0dSAlexey Brodkin 36660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) & 37660d5f0dSAlexey Brodkin ~IC_CTRL_CACHE_DISABLE); 38660d5f0dSAlexey Brodkin } 39660d5f0dSAlexey Brodkin 40660d5f0dSAlexey Brodkin void icache_disable(void) 41660d5f0dSAlexey Brodkin { 42660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 43660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 44660d5f0dSAlexey Brodkin return; 45660d5f0dSAlexey Brodkin 46660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) | 47660d5f0dSAlexey Brodkin IC_CTRL_CACHE_DISABLE); 48660d5f0dSAlexey Brodkin } 49660d5f0dSAlexey Brodkin 50660d5f0dSAlexey Brodkin void invalidate_icache_all(void) 51660d5f0dSAlexey Brodkin { 52*ae4a351aSAlexey Brodkin /* If no cache in CPU exit immediately */ 53*ae4a351aSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 54*ae4a351aSAlexey Brodkin return; 55*ae4a351aSAlexey Brodkin 56660d5f0dSAlexey Brodkin /* Any write to IC_IVIC register triggers invalidation of entire I$ */ 57660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_IVIC, 1); 58660d5f0dSAlexey Brodkin } 59660d5f0dSAlexey Brodkin 60660d5f0dSAlexey Brodkin int dcache_status(void) 61660d5f0dSAlexey Brodkin { 62660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 63660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 64660d5f0dSAlexey Brodkin return 0; 65660d5f0dSAlexey Brodkin 66660d5f0dSAlexey Brodkin return (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) != 67660d5f0dSAlexey Brodkin DC_CTRL_CACHE_DISABLE; 68660d5f0dSAlexey Brodkin } 69660d5f0dSAlexey Brodkin 70660d5f0dSAlexey Brodkin void dcache_enable(void) 71660d5f0dSAlexey Brodkin { 72660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 73660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 74660d5f0dSAlexey Brodkin return; 75660d5f0dSAlexey Brodkin 76660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) & 77660d5f0dSAlexey Brodkin ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE)); 78660d5f0dSAlexey Brodkin } 79660d5f0dSAlexey Brodkin 80660d5f0dSAlexey Brodkin void dcache_disable(void) 81660d5f0dSAlexey Brodkin { 82660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 83660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 84660d5f0dSAlexey Brodkin return; 85660d5f0dSAlexey Brodkin 86660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) | 87660d5f0dSAlexey Brodkin DC_CTRL_CACHE_DISABLE); 88660d5f0dSAlexey Brodkin } 89660d5f0dSAlexey Brodkin 90660d5f0dSAlexey Brodkin void flush_dcache_all(void) 91660d5f0dSAlexey Brodkin { 92660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 93660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 94660d5f0dSAlexey Brodkin return; 95660d5f0dSAlexey Brodkin 96660d5f0dSAlexey Brodkin /* Do flush of entire cache */ 97660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_FLSH, 1); 98660d5f0dSAlexey Brodkin 99660d5f0dSAlexey Brodkin /* Wait flush end */ 100660d5f0dSAlexey Brodkin while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) 101660d5f0dSAlexey Brodkin ; 102660d5f0dSAlexey Brodkin } 103660d5f0dSAlexey Brodkin 104660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 105660d5f0dSAlexey Brodkin static void dcache_flush_line(unsigned addr) 106660d5f0dSAlexey Brodkin { 1075ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 108660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_PTAG, addr); 109660d5f0dSAlexey Brodkin #endif 110660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_FLDL, addr); 111660d5f0dSAlexey Brodkin 112660d5f0dSAlexey Brodkin /* Wait flush end */ 113660d5f0dSAlexey Brodkin while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) 114660d5f0dSAlexey Brodkin ; 115660d5f0dSAlexey Brodkin 116660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_ICACHE_OFF 117660d5f0dSAlexey Brodkin /* 118660d5f0dSAlexey Brodkin * Invalidate I$ for addresses range just flushed from D$. 119660d5f0dSAlexey Brodkin * If we try to execute data flushed above it will be valid/correct 120660d5f0dSAlexey Brodkin */ 1215ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 122660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_PTAG, addr); 123660d5f0dSAlexey Brodkin #endif 124660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_IVIL, addr); 125660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_ICACHE_OFF */ 126660d5f0dSAlexey Brodkin } 127660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */ 128660d5f0dSAlexey Brodkin 129660d5f0dSAlexey Brodkin void flush_dcache_range(unsigned long start, unsigned long end) 130660d5f0dSAlexey Brodkin { 131660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 132660d5f0dSAlexey Brodkin unsigned int addr; 133660d5f0dSAlexey Brodkin 134660d5f0dSAlexey Brodkin start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 135660d5f0dSAlexey Brodkin end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 136660d5f0dSAlexey Brodkin 137660d5f0dSAlexey Brodkin for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) 138660d5f0dSAlexey Brodkin dcache_flush_line(addr); 139660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */ 140660d5f0dSAlexey Brodkin } 141660d5f0dSAlexey Brodkin 142660d5f0dSAlexey Brodkin void invalidate_dcache_range(unsigned long start, unsigned long end) 143660d5f0dSAlexey Brodkin { 144660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 145660d5f0dSAlexey Brodkin unsigned int addr; 146660d5f0dSAlexey Brodkin 147660d5f0dSAlexey Brodkin start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 148660d5f0dSAlexey Brodkin end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 149660d5f0dSAlexey Brodkin 150660d5f0dSAlexey Brodkin for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) { 1515ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 152660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_PTAG, addr); 153660d5f0dSAlexey Brodkin #endif 154660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_IVDL, addr); 155660d5f0dSAlexey Brodkin } 156660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */ 157660d5f0dSAlexey Brodkin } 158660d5f0dSAlexey Brodkin 159660d5f0dSAlexey Brodkin void invalidate_dcache_all(void) 160660d5f0dSAlexey Brodkin { 161*ae4a351aSAlexey Brodkin /* If no cache in CPU exit immediately */ 162*ae4a351aSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 163*ae4a351aSAlexey Brodkin return; 164*ae4a351aSAlexey Brodkin 165660d5f0dSAlexey Brodkin /* Write 1 to DC_IVDC register triggers invalidation of entire D$ */ 166660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_IVDC, 1); 167660d5f0dSAlexey Brodkin } 168660d5f0dSAlexey Brodkin 169660d5f0dSAlexey Brodkin void flush_cache(unsigned long start, unsigned long size) 170660d5f0dSAlexey Brodkin { 171660d5f0dSAlexey Brodkin flush_dcache_range(start, start + size); 172660d5f0dSAlexey Brodkin } 173