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 static inline unsigned long icache_line_size(void) 1330374f98SPaul Burton { 1430374f98SPaul Burton unsigned long conf1, il; 1537228621SPaul Burton 1637228621SPaul Burton if (!config_enabled(CONFIG_SYS_CACHE_SIZE_AUTO)) 1737228621SPaul Burton return CONFIG_SYS_ICACHE_LINE_SIZE; 1837228621SPaul Burton 1930374f98SPaul Burton conf1 = read_c0_config1(); 20a3ab2ae7SDaniel Schwierzeck il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHF; 2130374f98SPaul Burton if (!il) 2230374f98SPaul Burton return 0; 2330374f98SPaul Burton return 2 << il; 2430374f98SPaul Burton } 2530374f98SPaul Burton 2630374f98SPaul Burton static inline unsigned long dcache_line_size(void) 2730374f98SPaul Burton { 2830374f98SPaul Burton unsigned long conf1, dl; 2937228621SPaul Burton 3037228621SPaul Burton if (!config_enabled(CONFIG_SYS_CACHE_SIZE_AUTO)) 3137228621SPaul Burton return CONFIG_SYS_DCACHE_LINE_SIZE; 3237228621SPaul Burton 3330374f98SPaul Burton conf1 = read_c0_config1(); 34a3ab2ae7SDaniel Schwierzeck dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHF; 3530374f98SPaul Burton if (!dl) 3630374f98SPaul Burton return 0; 3730374f98SPaul Burton return 2 << dl; 3830374f98SPaul Burton } 3930374f98SPaul Burton 40fb64cda5SPaul Burton #define cache_loop(start, end, lsize, ops...) do { \ 41fb64cda5SPaul Burton const void *addr = (const void *)(start & ~(lsize - 1)); \ 42fb64cda5SPaul Burton const void *aend = (const void *)((end - 1) & ~(lsize - 1)); \ 43fb64cda5SPaul Burton const unsigned int cache_ops[] = { ops }; \ 44fb64cda5SPaul Burton unsigned int i; \ 45fb64cda5SPaul Burton \ 46fb64cda5SPaul Burton for (; addr <= aend; addr += lsize) { \ 47fb64cda5SPaul Burton for (i = 0; i < ARRAY_SIZE(cache_ops); i++) \ 48fb64cda5SPaul Burton mips_cache(cache_ops[i], addr); \ 49fb64cda5SPaul Burton } \ 50fb64cda5SPaul Burton } while (0) 51fb64cda5SPaul Burton 5230374f98SPaul Burton void flush_cache(ulong start_addr, ulong size) 5330374f98SPaul Burton { 5430374f98SPaul Burton unsigned long ilsize = icache_line_size(); 5530374f98SPaul Burton unsigned long dlsize = dcache_line_size(); 5630374f98SPaul Burton 5730374f98SPaul Burton /* aend will be miscalculated when size is zero, so we return here */ 5830374f98SPaul Burton if (size == 0) 5930374f98SPaul Burton return; 6030374f98SPaul Burton 6130374f98SPaul Burton if (ilsize == dlsize) { 6230374f98SPaul Burton /* flush I-cache & D-cache simultaneously */ 63fb64cda5SPaul Burton cache_loop(start_addr, start_addr + size, ilsize, 64fb64cda5SPaul Burton HIT_WRITEBACK_INV_D, HIT_INVALIDATE_I); 6530374f98SPaul Burton return; 6630374f98SPaul Burton } 6730374f98SPaul Burton 6830374f98SPaul Burton /* flush D-cache */ 69fb64cda5SPaul Burton cache_loop(start_addr, start_addr + size, dlsize, HIT_WRITEBACK_INV_D); 7030374f98SPaul Burton 7130374f98SPaul Burton /* flush I-cache */ 72fb64cda5SPaul Burton cache_loop(start_addr, start_addr + size, ilsize, HIT_INVALIDATE_I); 7330374f98SPaul Burton } 7430374f98SPaul Burton 7530374f98SPaul Burton void flush_dcache_range(ulong start_addr, ulong stop) 7630374f98SPaul Burton { 7730374f98SPaul Burton unsigned long lsize = dcache_line_size(); 7830374f98SPaul Burton 79fbb0de08SMarek Vasut /* aend will be miscalculated when size is zero, so we return here */ 80fbb0de08SMarek Vasut if (start_addr == stop) 81fbb0de08SMarek Vasut return; 82fbb0de08SMarek Vasut 83fb64cda5SPaul Burton cache_loop(start_addr, stop, lsize, HIT_WRITEBACK_INV_D); 8430374f98SPaul Burton } 8530374f98SPaul Burton 8630374f98SPaul Burton void invalidate_dcache_range(ulong start_addr, ulong stop) 8730374f98SPaul Burton { 8830374f98SPaul Burton unsigned long lsize = dcache_line_size(); 8930374f98SPaul Burton 90fbb0de08SMarek Vasut /* aend will be miscalculated when size is zero, so we return here */ 91fbb0de08SMarek Vasut if (start_addr == stop) 92fbb0de08SMarek Vasut return; 93fbb0de08SMarek Vasut 94*a95800e8SPaul Burton cache_loop(start_addr, stop, lsize, HIT_INVALIDATE_D); 9530374f98SPaul Burton } 96