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 12*8cb4817dSPaul Burton DECLARE_GLOBAL_DATA_PTR; 1337228621SPaul Burton 14*8cb4817dSPaul Burton void mips_cache_probe(void) 15*8cb4817dSPaul Burton { 16*8cb4817dSPaul Burton #ifdef CONFIG_SYS_CACHE_SIZE_AUTO 17*8cb4817dSPaul Burton unsigned long conf1, il, dl; 1837228621SPaul Burton 1930374f98SPaul Burton conf1 = read_c0_config1(); 20*8cb4817dSPaul Burton 21a3ab2ae7SDaniel Schwierzeck il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHF; 22*8cb4817dSPaul Burton dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHF; 23*8cb4817dSPaul Burton 24*8cb4817dSPaul Burton gd->arch.l1i_line_size = il ? (2 << il) : 0; 25*8cb4817dSPaul Burton gd->arch.l1d_line_size = dl ? (2 << dl) : 0; 26*8cb4817dSPaul Burton #endif 27*8cb4817dSPaul Burton } 28*8cb4817dSPaul Burton 29*8cb4817dSPaul Burton static inline unsigned long icache_line_size(void) 30*8cb4817dSPaul Burton { 31*8cb4817dSPaul Burton #ifdef CONFIG_SYS_CACHE_SIZE_AUTO 32*8cb4817dSPaul Burton return gd->arch.l1i_line_size; 33*8cb4817dSPaul Burton #else 34*8cb4817dSPaul Burton return CONFIG_SYS_ICACHE_LINE_SIZE; 35*8cb4817dSPaul Burton #endif 3630374f98SPaul Burton } 3730374f98SPaul Burton 3830374f98SPaul Burton static inline unsigned long dcache_line_size(void) 3930374f98SPaul Burton { 40*8cb4817dSPaul Burton #ifdef CONFIG_SYS_CACHE_SIZE_AUTO 41*8cb4817dSPaul Burton return gd->arch.l1d_line_size; 42*8cb4817dSPaul Burton #else 4337228621SPaul Burton return CONFIG_SYS_DCACHE_LINE_SIZE; 44*8cb4817dSPaul Burton #endif 4530374f98SPaul Burton } 4630374f98SPaul Burton 47fb64cda5SPaul Burton #define cache_loop(start, end, lsize, ops...) do { \ 48fb64cda5SPaul Burton const void *addr = (const void *)(start & ~(lsize - 1)); \ 49fb64cda5SPaul Burton const void *aend = (const void *)((end - 1) & ~(lsize - 1)); \ 50fb64cda5SPaul Burton const unsigned int cache_ops[] = { ops }; \ 51fb64cda5SPaul Burton unsigned int i; \ 52fb64cda5SPaul Burton \ 53fb64cda5SPaul Burton for (; addr <= aend; addr += lsize) { \ 54fb64cda5SPaul Burton for (i = 0; i < ARRAY_SIZE(cache_ops); i++) \ 55fb64cda5SPaul Burton mips_cache(cache_ops[i], addr); \ 56fb64cda5SPaul Burton } \ 57fb64cda5SPaul Burton } while (0) 58fb64cda5SPaul Burton 5930374f98SPaul Burton void flush_cache(ulong start_addr, ulong size) 6030374f98SPaul Burton { 6130374f98SPaul Burton unsigned long ilsize = icache_line_size(); 6230374f98SPaul Burton unsigned long dlsize = dcache_line_size(); 6330374f98SPaul Burton 6430374f98SPaul Burton /* aend will be miscalculated when size is zero, so we return here */ 6530374f98SPaul Burton if (size == 0) 6630374f98SPaul Burton return; 6730374f98SPaul Burton 6830374f98SPaul Burton if (ilsize == dlsize) { 6930374f98SPaul Burton /* flush I-cache & D-cache simultaneously */ 70fb64cda5SPaul Burton cache_loop(start_addr, start_addr + size, ilsize, 71fb64cda5SPaul Burton HIT_WRITEBACK_INV_D, HIT_INVALIDATE_I); 7230374f98SPaul Burton return; 7330374f98SPaul Burton } 7430374f98SPaul Burton 7530374f98SPaul Burton /* flush D-cache */ 76fb64cda5SPaul Burton cache_loop(start_addr, start_addr + size, dlsize, HIT_WRITEBACK_INV_D); 7730374f98SPaul Burton 7830374f98SPaul Burton /* flush I-cache */ 79fb64cda5SPaul Burton cache_loop(start_addr, start_addr + size, ilsize, HIT_INVALIDATE_I); 8030374f98SPaul Burton } 8130374f98SPaul Burton 8230374f98SPaul Burton void flush_dcache_range(ulong start_addr, ulong stop) 8330374f98SPaul Burton { 8430374f98SPaul Burton unsigned long lsize = dcache_line_size(); 8530374f98SPaul Burton 86fbb0de08SMarek Vasut /* aend will be miscalculated when size is zero, so we return here */ 87fbb0de08SMarek Vasut if (start_addr == stop) 88fbb0de08SMarek Vasut return; 89fbb0de08SMarek Vasut 90fb64cda5SPaul Burton cache_loop(start_addr, stop, lsize, HIT_WRITEBACK_INV_D); 9130374f98SPaul Burton } 9230374f98SPaul Burton 9330374f98SPaul Burton void invalidate_dcache_range(ulong start_addr, ulong stop) 9430374f98SPaul Burton { 9530374f98SPaul Burton unsigned long lsize = dcache_line_size(); 9630374f98SPaul Burton 97fbb0de08SMarek Vasut /* aend will be miscalculated when size is zero, so we return here */ 98fbb0de08SMarek Vasut if (start_addr == stop) 99fbb0de08SMarek Vasut return; 100fbb0de08SMarek Vasut 101a95800e8SPaul Burton cache_loop(start_addr, stop, lsize, HIT_INVALIDATE_D); 10230374f98SPaul Burton } 103