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> 9*205e7a7bSAlexey 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 { 52660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_ICACHE_OFF 53660d5f0dSAlexey Brodkin /* Any write to IC_IVIC register triggers invalidation of entire I$ */ 54660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_IVIC, 1); 55660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_ICACHE_OFF */ 56660d5f0dSAlexey Brodkin } 57660d5f0dSAlexey Brodkin 58660d5f0dSAlexey Brodkin int dcache_status(void) 59660d5f0dSAlexey Brodkin { 60660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 61660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 62660d5f0dSAlexey Brodkin return 0; 63660d5f0dSAlexey Brodkin 64660d5f0dSAlexey Brodkin return (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) != 65660d5f0dSAlexey Brodkin DC_CTRL_CACHE_DISABLE; 66660d5f0dSAlexey Brodkin } 67660d5f0dSAlexey Brodkin 68660d5f0dSAlexey Brodkin void dcache_enable(void) 69660d5f0dSAlexey Brodkin { 70660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 71660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 72660d5f0dSAlexey Brodkin return; 73660d5f0dSAlexey Brodkin 74660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) & 75660d5f0dSAlexey Brodkin ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE)); 76660d5f0dSAlexey Brodkin } 77660d5f0dSAlexey Brodkin 78660d5f0dSAlexey Brodkin void dcache_disable(void) 79660d5f0dSAlexey Brodkin { 80660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 81660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 82660d5f0dSAlexey Brodkin return; 83660d5f0dSAlexey Brodkin 84660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) | 85660d5f0dSAlexey Brodkin DC_CTRL_CACHE_DISABLE); 86660d5f0dSAlexey Brodkin } 87660d5f0dSAlexey Brodkin 88660d5f0dSAlexey Brodkin void flush_dcache_all(void) 89660d5f0dSAlexey Brodkin { 90660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 91660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 92660d5f0dSAlexey Brodkin return; 93660d5f0dSAlexey Brodkin 94660d5f0dSAlexey Brodkin /* Do flush of entire cache */ 95660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_FLSH, 1); 96660d5f0dSAlexey Brodkin 97660d5f0dSAlexey Brodkin /* Wait flush end */ 98660d5f0dSAlexey Brodkin while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) 99660d5f0dSAlexey Brodkin ; 100660d5f0dSAlexey Brodkin } 101660d5f0dSAlexey Brodkin 102660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 103660d5f0dSAlexey Brodkin static void dcache_flush_line(unsigned addr) 104660d5f0dSAlexey Brodkin { 1055ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 106660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_PTAG, addr); 107660d5f0dSAlexey Brodkin #endif 108660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_FLDL, addr); 109660d5f0dSAlexey Brodkin 110660d5f0dSAlexey Brodkin /* Wait flush end */ 111660d5f0dSAlexey Brodkin while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) 112660d5f0dSAlexey Brodkin ; 113660d5f0dSAlexey Brodkin 114660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_ICACHE_OFF 115660d5f0dSAlexey Brodkin /* 116660d5f0dSAlexey Brodkin * Invalidate I$ for addresses range just flushed from D$. 117660d5f0dSAlexey Brodkin * If we try to execute data flushed above it will be valid/correct 118660d5f0dSAlexey Brodkin */ 1195ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 120660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_PTAG, addr); 121660d5f0dSAlexey Brodkin #endif 122660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_IVIL, addr); 123660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_ICACHE_OFF */ 124660d5f0dSAlexey Brodkin } 125660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */ 126660d5f0dSAlexey Brodkin 127660d5f0dSAlexey Brodkin void flush_dcache_range(unsigned long start, unsigned long end) 128660d5f0dSAlexey Brodkin { 129660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 130660d5f0dSAlexey Brodkin unsigned int addr; 131660d5f0dSAlexey Brodkin 132660d5f0dSAlexey Brodkin start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 133660d5f0dSAlexey Brodkin end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 134660d5f0dSAlexey Brodkin 135660d5f0dSAlexey Brodkin for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) 136660d5f0dSAlexey Brodkin dcache_flush_line(addr); 137660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */ 138660d5f0dSAlexey Brodkin } 139660d5f0dSAlexey Brodkin 140660d5f0dSAlexey Brodkin void invalidate_dcache_range(unsigned long start, unsigned long end) 141660d5f0dSAlexey Brodkin { 142660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 143660d5f0dSAlexey Brodkin unsigned int addr; 144660d5f0dSAlexey Brodkin 145660d5f0dSAlexey Brodkin start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 146660d5f0dSAlexey Brodkin end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 147660d5f0dSAlexey Brodkin 148660d5f0dSAlexey Brodkin for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) { 1495ff40f3dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER == 3) 150660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_PTAG, addr); 151660d5f0dSAlexey Brodkin #endif 152660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_IVDL, addr); 153660d5f0dSAlexey Brodkin } 154660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */ 155660d5f0dSAlexey Brodkin } 156660d5f0dSAlexey Brodkin 157660d5f0dSAlexey Brodkin void invalidate_dcache_all(void) 158660d5f0dSAlexey Brodkin { 159660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 160660d5f0dSAlexey Brodkin /* Write 1 to DC_IVDC register triggers invalidation of entire D$ */ 161660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_IVDC, 1); 162660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */ 163660d5f0dSAlexey Brodkin } 164660d5f0dSAlexey Brodkin 165660d5f0dSAlexey Brodkin void flush_cache(unsigned long start, unsigned long size) 166660d5f0dSAlexey Brodkin { 167660d5f0dSAlexey Brodkin flush_dcache_range(start, start + size); 168660d5f0dSAlexey Brodkin } 169