1*660d5f0dSAlexey Brodkin /* 2*660d5f0dSAlexey Brodkin * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. 3*660d5f0dSAlexey Brodkin * 4*660d5f0dSAlexey Brodkin * SPDX-License-Identifier: GPL-2.0+ 5*660d5f0dSAlexey Brodkin */ 6*660d5f0dSAlexey Brodkin 7*660d5f0dSAlexey Brodkin #include <config.h> 8*660d5f0dSAlexey Brodkin #include <asm/arcregs.h> 9*660d5f0dSAlexey Brodkin 10*660d5f0dSAlexey Brodkin /* Bit values in IC_CTRL */ 11*660d5f0dSAlexey Brodkin #define IC_CTRL_CACHE_DISABLE (1 << 0) 12*660d5f0dSAlexey Brodkin 13*660d5f0dSAlexey Brodkin /* Bit values in DC_CTRL */ 14*660d5f0dSAlexey Brodkin #define DC_CTRL_CACHE_DISABLE (1 << 0) 15*660d5f0dSAlexey Brodkin #define DC_CTRL_INV_MODE_FLUSH (1 << 6) 16*660d5f0dSAlexey Brodkin #define DC_CTRL_FLUSH_STATUS (1 << 8) 17*660d5f0dSAlexey Brodkin #define CACHE_VER_NUM_MASK 0xF 18*660d5f0dSAlexey Brodkin 19*660d5f0dSAlexey Brodkin int icache_status(void) 20*660d5f0dSAlexey Brodkin { 21*660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 22*660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 23*660d5f0dSAlexey Brodkin return 0; 24*660d5f0dSAlexey Brodkin 25*660d5f0dSAlexey Brodkin return (read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE) != 26*660d5f0dSAlexey Brodkin IC_CTRL_CACHE_DISABLE; 27*660d5f0dSAlexey Brodkin } 28*660d5f0dSAlexey Brodkin 29*660d5f0dSAlexey Brodkin void icache_enable(void) 30*660d5f0dSAlexey Brodkin { 31*660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 32*660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 33*660d5f0dSAlexey Brodkin return; 34*660d5f0dSAlexey Brodkin 35*660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) & 36*660d5f0dSAlexey Brodkin ~IC_CTRL_CACHE_DISABLE); 37*660d5f0dSAlexey Brodkin } 38*660d5f0dSAlexey Brodkin 39*660d5f0dSAlexey Brodkin void icache_disable(void) 40*660d5f0dSAlexey Brodkin { 41*660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 42*660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_IC_BUILD) & CACHE_VER_NUM_MASK)) 43*660d5f0dSAlexey Brodkin return; 44*660d5f0dSAlexey Brodkin 45*660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) | 46*660d5f0dSAlexey Brodkin IC_CTRL_CACHE_DISABLE); 47*660d5f0dSAlexey Brodkin } 48*660d5f0dSAlexey Brodkin 49*660d5f0dSAlexey Brodkin void invalidate_icache_all(void) 50*660d5f0dSAlexey Brodkin { 51*660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_ICACHE_OFF 52*660d5f0dSAlexey Brodkin /* Any write to IC_IVIC register triggers invalidation of entire I$ */ 53*660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_IVIC, 1); 54*660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_ICACHE_OFF */ 55*660d5f0dSAlexey Brodkin } 56*660d5f0dSAlexey Brodkin 57*660d5f0dSAlexey Brodkin int dcache_status(void) 58*660d5f0dSAlexey Brodkin { 59*660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 60*660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 61*660d5f0dSAlexey Brodkin return 0; 62*660d5f0dSAlexey Brodkin 63*660d5f0dSAlexey Brodkin return (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE) != 64*660d5f0dSAlexey Brodkin DC_CTRL_CACHE_DISABLE; 65*660d5f0dSAlexey Brodkin } 66*660d5f0dSAlexey Brodkin 67*660d5f0dSAlexey Brodkin void dcache_enable(void) 68*660d5f0dSAlexey Brodkin { 69*660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 70*660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 71*660d5f0dSAlexey Brodkin return; 72*660d5f0dSAlexey Brodkin 73*660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) & 74*660d5f0dSAlexey Brodkin ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE)); 75*660d5f0dSAlexey Brodkin } 76*660d5f0dSAlexey Brodkin 77*660d5f0dSAlexey Brodkin void dcache_disable(void) 78*660d5f0dSAlexey Brodkin { 79*660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 80*660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 81*660d5f0dSAlexey Brodkin return; 82*660d5f0dSAlexey Brodkin 83*660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) | 84*660d5f0dSAlexey Brodkin DC_CTRL_CACHE_DISABLE); 85*660d5f0dSAlexey Brodkin } 86*660d5f0dSAlexey Brodkin 87*660d5f0dSAlexey Brodkin void flush_dcache_all(void) 88*660d5f0dSAlexey Brodkin { 89*660d5f0dSAlexey Brodkin /* If no cache in CPU exit immediately */ 90*660d5f0dSAlexey Brodkin if (!(read_aux_reg(ARC_BCR_DC_BUILD) & CACHE_VER_NUM_MASK)) 91*660d5f0dSAlexey Brodkin return; 92*660d5f0dSAlexey Brodkin 93*660d5f0dSAlexey Brodkin /* Do flush of entire cache */ 94*660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_FLSH, 1); 95*660d5f0dSAlexey Brodkin 96*660d5f0dSAlexey Brodkin /* Wait flush end */ 97*660d5f0dSAlexey Brodkin while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) 98*660d5f0dSAlexey Brodkin ; 99*660d5f0dSAlexey Brodkin } 100*660d5f0dSAlexey Brodkin 101*660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 102*660d5f0dSAlexey Brodkin static void dcache_flush_line(unsigned addr) 103*660d5f0dSAlexey Brodkin { 104*660d5f0dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER > 2) 105*660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_PTAG, addr); 106*660d5f0dSAlexey Brodkin #endif 107*660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_FLDL, addr); 108*660d5f0dSAlexey Brodkin 109*660d5f0dSAlexey Brodkin /* Wait flush end */ 110*660d5f0dSAlexey Brodkin while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS) 111*660d5f0dSAlexey Brodkin ; 112*660d5f0dSAlexey Brodkin 113*660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_ICACHE_OFF 114*660d5f0dSAlexey Brodkin /* 115*660d5f0dSAlexey Brodkin * Invalidate I$ for addresses range just flushed from D$. 116*660d5f0dSAlexey Brodkin * If we try to execute data flushed above it will be valid/correct 117*660d5f0dSAlexey Brodkin */ 118*660d5f0dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER > 2) 119*660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_PTAG, addr); 120*660d5f0dSAlexey Brodkin #endif 121*660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_IC_IVIL, addr); 122*660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_ICACHE_OFF */ 123*660d5f0dSAlexey Brodkin } 124*660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */ 125*660d5f0dSAlexey Brodkin 126*660d5f0dSAlexey Brodkin void flush_dcache_range(unsigned long start, unsigned long end) 127*660d5f0dSAlexey Brodkin { 128*660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 129*660d5f0dSAlexey Brodkin unsigned int addr; 130*660d5f0dSAlexey Brodkin 131*660d5f0dSAlexey Brodkin start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 132*660d5f0dSAlexey Brodkin end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 133*660d5f0dSAlexey Brodkin 134*660d5f0dSAlexey Brodkin for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) 135*660d5f0dSAlexey Brodkin dcache_flush_line(addr); 136*660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */ 137*660d5f0dSAlexey Brodkin } 138*660d5f0dSAlexey Brodkin 139*660d5f0dSAlexey Brodkin void invalidate_dcache_range(unsigned long start, unsigned long end) 140*660d5f0dSAlexey Brodkin { 141*660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 142*660d5f0dSAlexey Brodkin unsigned int addr; 143*660d5f0dSAlexey Brodkin 144*660d5f0dSAlexey Brodkin start = start & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 145*660d5f0dSAlexey Brodkin end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); 146*660d5f0dSAlexey Brodkin 147*660d5f0dSAlexey Brodkin for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) { 148*660d5f0dSAlexey Brodkin #if (CONFIG_ARC_MMU_VER > 2) 149*660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_PTAG, addr); 150*660d5f0dSAlexey Brodkin #endif 151*660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_IVDL, addr); 152*660d5f0dSAlexey Brodkin } 153*660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */ 154*660d5f0dSAlexey Brodkin } 155*660d5f0dSAlexey Brodkin 156*660d5f0dSAlexey Brodkin void invalidate_dcache_all(void) 157*660d5f0dSAlexey Brodkin { 158*660d5f0dSAlexey Brodkin #ifndef CONFIG_SYS_DCACHE_OFF 159*660d5f0dSAlexey Brodkin /* Write 1 to DC_IVDC register triggers invalidation of entire D$ */ 160*660d5f0dSAlexey Brodkin write_aux_reg(ARC_AUX_DC_IVDC, 1); 161*660d5f0dSAlexey Brodkin #endif /* CONFIG_SYS_DCACHE_OFF */ 162*660d5f0dSAlexey Brodkin } 163*660d5f0dSAlexey Brodkin 164*660d5f0dSAlexey Brodkin void flush_cache(unsigned long start, unsigned long size) 165*660d5f0dSAlexey Brodkin { 166*660d5f0dSAlexey Brodkin flush_dcache_range(start, start + size); 167*660d5f0dSAlexey Brodkin } 168