1*30374f98SPaul Burton /* 2*30374f98SPaul Burton * (C) Copyright 2003 3*30374f98SPaul Burton * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> 4*30374f98SPaul Burton * 5*30374f98SPaul Burton * SPDX-License-Identifier: GPL-2.0+ 6*30374f98SPaul Burton */ 7*30374f98SPaul Burton 8*30374f98SPaul Burton #include <common.h> 9*30374f98SPaul Burton #include <asm/cacheops.h> 10*30374f98SPaul Burton #include <asm/mipsregs.h> 11*30374f98SPaul Burton 12*30374f98SPaul Burton #ifdef CONFIG_SYS_CACHELINE_SIZE 13*30374f98SPaul Burton 14*30374f98SPaul Burton static inline unsigned long icache_line_size(void) 15*30374f98SPaul Burton { 16*30374f98SPaul Burton return CONFIG_SYS_CACHELINE_SIZE; 17*30374f98SPaul Burton } 18*30374f98SPaul Burton 19*30374f98SPaul Burton static inline unsigned long dcache_line_size(void) 20*30374f98SPaul Burton { 21*30374f98SPaul Burton return CONFIG_SYS_CACHELINE_SIZE; 22*30374f98SPaul Burton } 23*30374f98SPaul Burton 24*30374f98SPaul Burton #else /* !CONFIG_SYS_CACHELINE_SIZE */ 25*30374f98SPaul Burton 26*30374f98SPaul Burton static inline unsigned long icache_line_size(void) 27*30374f98SPaul Burton { 28*30374f98SPaul Burton unsigned long conf1, il; 29*30374f98SPaul Burton conf1 = read_c0_config1(); 30*30374f98SPaul Burton il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHIFT; 31*30374f98SPaul Burton if (!il) 32*30374f98SPaul Burton return 0; 33*30374f98SPaul Burton return 2 << il; 34*30374f98SPaul Burton } 35*30374f98SPaul Burton 36*30374f98SPaul Burton static inline unsigned long dcache_line_size(void) 37*30374f98SPaul Burton { 38*30374f98SPaul Burton unsigned long conf1, dl; 39*30374f98SPaul Burton conf1 = read_c0_config1(); 40*30374f98SPaul Burton dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHIFT; 41*30374f98SPaul Burton if (!dl) 42*30374f98SPaul Burton return 0; 43*30374f98SPaul Burton return 2 << dl; 44*30374f98SPaul Burton } 45*30374f98SPaul Burton 46*30374f98SPaul Burton #endif /* !CONFIG_SYS_CACHELINE_SIZE */ 47*30374f98SPaul Burton 48*30374f98SPaul Burton void flush_cache(ulong start_addr, ulong size) 49*30374f98SPaul Burton { 50*30374f98SPaul Burton unsigned long ilsize = icache_line_size(); 51*30374f98SPaul Burton unsigned long dlsize = dcache_line_size(); 52*30374f98SPaul Burton const void *addr, *aend; 53*30374f98SPaul Burton 54*30374f98SPaul Burton /* aend will be miscalculated when size is zero, so we return here */ 55*30374f98SPaul Burton if (size == 0) 56*30374f98SPaul Burton return; 57*30374f98SPaul Burton 58*30374f98SPaul Burton addr = (const void *)(start_addr & ~(dlsize - 1)); 59*30374f98SPaul Burton aend = (const void *)((start_addr + size - 1) & ~(dlsize - 1)); 60*30374f98SPaul Burton 61*30374f98SPaul Burton if (ilsize == dlsize) { 62*30374f98SPaul Burton /* flush I-cache & D-cache simultaneously */ 63*30374f98SPaul Burton while (1) { 64*30374f98SPaul Burton mips_cache(HIT_WRITEBACK_INV_D, addr); 65*30374f98SPaul Burton mips_cache(HIT_INVALIDATE_I, addr); 66*30374f98SPaul Burton if (addr == aend) 67*30374f98SPaul Burton break; 68*30374f98SPaul Burton addr += dlsize; 69*30374f98SPaul Burton } 70*30374f98SPaul Burton return; 71*30374f98SPaul Burton } 72*30374f98SPaul Burton 73*30374f98SPaul Burton /* flush D-cache */ 74*30374f98SPaul Burton while (1) { 75*30374f98SPaul Burton mips_cache(HIT_WRITEBACK_INV_D, addr); 76*30374f98SPaul Burton if (addr == aend) 77*30374f98SPaul Burton break; 78*30374f98SPaul Burton addr += dlsize; 79*30374f98SPaul Burton } 80*30374f98SPaul Burton 81*30374f98SPaul Burton /* flush I-cache */ 82*30374f98SPaul Burton addr = (const void *)(start_addr & ~(ilsize - 1)); 83*30374f98SPaul Burton aend = (const void *)((start_addr + size - 1) & ~(ilsize - 1)); 84*30374f98SPaul Burton while (1) { 85*30374f98SPaul Burton mips_cache(HIT_INVALIDATE_I, addr); 86*30374f98SPaul Burton if (addr == aend) 87*30374f98SPaul Burton break; 88*30374f98SPaul Burton addr += ilsize; 89*30374f98SPaul Burton } 90*30374f98SPaul Burton } 91*30374f98SPaul Burton 92*30374f98SPaul Burton void flush_dcache_range(ulong start_addr, ulong stop) 93*30374f98SPaul Burton { 94*30374f98SPaul Burton unsigned long lsize = dcache_line_size(); 95*30374f98SPaul Burton const void *addr = (const void *)(start_addr & ~(lsize - 1)); 96*30374f98SPaul Burton const void *aend = (const void *)((stop - 1) & ~(lsize - 1)); 97*30374f98SPaul Burton 98*30374f98SPaul Burton while (1) { 99*30374f98SPaul Burton mips_cache(HIT_WRITEBACK_INV_D, addr); 100*30374f98SPaul Burton if (addr == aend) 101*30374f98SPaul Burton break; 102*30374f98SPaul Burton addr += lsize; 103*30374f98SPaul Burton } 104*30374f98SPaul Burton } 105*30374f98SPaul Burton 106*30374f98SPaul Burton void invalidate_dcache_range(ulong start_addr, ulong stop) 107*30374f98SPaul Burton { 108*30374f98SPaul Burton unsigned long lsize = dcache_line_size(); 109*30374f98SPaul Burton const void *addr = (const void *)(start_addr & ~(lsize - 1)); 110*30374f98SPaul Burton const void *aend = (const void *)((stop - 1) & ~(lsize - 1)); 111*30374f98SPaul Burton 112*30374f98SPaul Burton while (1) { 113*30374f98SPaul Burton mips_cache(HIT_INVALIDATE_D, addr); 114*30374f98SPaul Burton if (addr == aend) 115*30374f98SPaul Burton break; 116*30374f98SPaul Burton addr += lsize; 117*30374f98SPaul Burton } 118*30374f98SPaul Burton } 119