130374f98SPaul Burton /* 230374f98SPaul Burton * (C) Copyright 2003 330374f98SPaul Burton * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> 430374f98SPaul Burton * 530374f98SPaul Burton * SPDX-License-Identifier: GPL-2.0+ 630374f98SPaul Burton */ 730374f98SPaul Burton 830374f98SPaul Burton #include <common.h> 930374f98SPaul Burton #include <asm/cacheops.h> 1030374f98SPaul Burton #include <asm/mipsregs.h> 1130374f98SPaul Burton 1230374f98SPaul Burton #ifdef CONFIG_SYS_CACHELINE_SIZE 1330374f98SPaul Burton 1430374f98SPaul Burton static inline unsigned long icache_line_size(void) 1530374f98SPaul Burton { 1630374f98SPaul Burton return CONFIG_SYS_CACHELINE_SIZE; 1730374f98SPaul Burton } 1830374f98SPaul Burton 1930374f98SPaul Burton static inline unsigned long dcache_line_size(void) 2030374f98SPaul Burton { 2130374f98SPaul Burton return CONFIG_SYS_CACHELINE_SIZE; 2230374f98SPaul Burton } 2330374f98SPaul Burton 2430374f98SPaul Burton #else /* !CONFIG_SYS_CACHELINE_SIZE */ 2530374f98SPaul Burton 2630374f98SPaul Burton static inline unsigned long icache_line_size(void) 2730374f98SPaul Burton { 2830374f98SPaul Burton unsigned long conf1, il; 2930374f98SPaul Burton conf1 = read_c0_config1(); 30a3ab2ae7SDaniel Schwierzeck il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHF; 3130374f98SPaul Burton if (!il) 3230374f98SPaul Burton return 0; 3330374f98SPaul Burton return 2 << il; 3430374f98SPaul Burton } 3530374f98SPaul Burton 3630374f98SPaul Burton static inline unsigned long dcache_line_size(void) 3730374f98SPaul Burton { 3830374f98SPaul Burton unsigned long conf1, dl; 3930374f98SPaul Burton conf1 = read_c0_config1(); 40a3ab2ae7SDaniel Schwierzeck dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHF; 4130374f98SPaul Burton if (!dl) 4230374f98SPaul Burton return 0; 4330374f98SPaul Burton return 2 << dl; 4430374f98SPaul Burton } 4530374f98SPaul Burton 4630374f98SPaul Burton #endif /* !CONFIG_SYS_CACHELINE_SIZE */ 4730374f98SPaul Burton 4830374f98SPaul Burton void flush_cache(ulong start_addr, ulong size) 4930374f98SPaul Burton { 5030374f98SPaul Burton unsigned long ilsize = icache_line_size(); 5130374f98SPaul Burton unsigned long dlsize = dcache_line_size(); 5230374f98SPaul Burton const void *addr, *aend; 5330374f98SPaul Burton 5430374f98SPaul Burton /* aend will be miscalculated when size is zero, so we return here */ 5530374f98SPaul Burton if (size == 0) 5630374f98SPaul Burton return; 5730374f98SPaul Burton 5830374f98SPaul Burton addr = (const void *)(start_addr & ~(dlsize - 1)); 5930374f98SPaul Burton aend = (const void *)((start_addr + size - 1) & ~(dlsize - 1)); 6030374f98SPaul Burton 6130374f98SPaul Burton if (ilsize == dlsize) { 6230374f98SPaul Burton /* flush I-cache & D-cache simultaneously */ 6330374f98SPaul Burton while (1) { 6430374f98SPaul Burton mips_cache(HIT_WRITEBACK_INV_D, addr); 6530374f98SPaul Burton mips_cache(HIT_INVALIDATE_I, addr); 6630374f98SPaul Burton if (addr == aend) 6730374f98SPaul Burton break; 6830374f98SPaul Burton addr += dlsize; 6930374f98SPaul Burton } 7030374f98SPaul Burton return; 7130374f98SPaul Burton } 7230374f98SPaul Burton 7330374f98SPaul Burton /* flush D-cache */ 7430374f98SPaul Burton while (1) { 7530374f98SPaul Burton mips_cache(HIT_WRITEBACK_INV_D, addr); 7630374f98SPaul Burton if (addr == aend) 7730374f98SPaul Burton break; 7830374f98SPaul Burton addr += dlsize; 7930374f98SPaul Burton } 8030374f98SPaul Burton 8130374f98SPaul Burton /* flush I-cache */ 8230374f98SPaul Burton addr = (const void *)(start_addr & ~(ilsize - 1)); 8330374f98SPaul Burton aend = (const void *)((start_addr + size - 1) & ~(ilsize - 1)); 8430374f98SPaul Burton while (1) { 8530374f98SPaul Burton mips_cache(HIT_INVALIDATE_I, addr); 8630374f98SPaul Burton if (addr == aend) 8730374f98SPaul Burton break; 8830374f98SPaul Burton addr += ilsize; 8930374f98SPaul Burton } 9030374f98SPaul Burton } 9130374f98SPaul Burton 9230374f98SPaul Burton void flush_dcache_range(ulong start_addr, ulong stop) 9330374f98SPaul Burton { 9430374f98SPaul Burton unsigned long lsize = dcache_line_size(); 9530374f98SPaul Burton const void *addr = (const void *)(start_addr & ~(lsize - 1)); 9630374f98SPaul Burton const void *aend = (const void *)((stop - 1) & ~(lsize - 1)); 9730374f98SPaul Burton 98*fbb0de08SMarek Vasut /* aend will be miscalculated when size is zero, so we return here */ 99*fbb0de08SMarek Vasut if (start_addr == stop) 100*fbb0de08SMarek Vasut return; 101*fbb0de08SMarek Vasut 10230374f98SPaul Burton while (1) { 10330374f98SPaul Burton mips_cache(HIT_WRITEBACK_INV_D, addr); 10430374f98SPaul Burton if (addr == aend) 10530374f98SPaul Burton break; 10630374f98SPaul Burton addr += lsize; 10730374f98SPaul Burton } 10830374f98SPaul Burton } 10930374f98SPaul Burton 11030374f98SPaul Burton void invalidate_dcache_range(ulong start_addr, ulong stop) 11130374f98SPaul Burton { 11230374f98SPaul Burton unsigned long lsize = dcache_line_size(); 11330374f98SPaul Burton const void *addr = (const void *)(start_addr & ~(lsize - 1)); 11430374f98SPaul Burton const void *aend = (const void *)((stop - 1) & ~(lsize - 1)); 11530374f98SPaul Burton 116*fbb0de08SMarek Vasut /* aend will be miscalculated when size is zero, so we return here */ 117*fbb0de08SMarek Vasut if (start_addr == stop) 118*fbb0de08SMarek Vasut return; 119*fbb0de08SMarek Vasut 12030374f98SPaul Burton while (1) { 12130374f98SPaul Burton mips_cache(HIT_INVALIDATE_D, addr); 12230374f98SPaul Burton if (addr == aend) 12330374f98SPaul Burton break; 12430374f98SPaul Burton addr += lsize; 12530374f98SPaul Burton } 12630374f98SPaul Burton } 127