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