1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * arch/sh/mm/cache-sh2.c 4 * 5 * Copyright (C) 2002 Paul Mundt 6 * Copyright (C) 2008 Yoshinori Sato 7 */ 8 9 #include <linux/init.h> 10 #include <linux/mm.h> 11 12 #include <asm/cache.h> 13 #include <asm/addrspace.h> 14 #include <asm/processor.h> 15 #include <asm/cacheflush.h> 16 #include <asm/io.h> 17 18 static void sh2__flush_wback_region(void *start, int size) 19 { 20 unsigned long v; 21 unsigned long begin, end; 22 23 begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); 24 end = ((unsigned long)start + size + L1_CACHE_BYTES-1) 25 & ~(L1_CACHE_BYTES-1); 26 for (v = begin; v < end; v+=L1_CACHE_BYTES) { 27 unsigned long addr = CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0); 28 int way; 29 for (way = 0; way < 4; way++) { 30 unsigned long data = __raw_readl(addr | (way << 12)); 31 if ((data & CACHE_PHYSADDR_MASK) == (v & CACHE_PHYSADDR_MASK)) { 32 data &= ~SH_CACHE_UPDATED; 33 __raw_writel(data, addr | (way << 12)); 34 } 35 } 36 } 37 } 38 39 static void sh2__flush_purge_region(void *start, int size) 40 { 41 unsigned long v; 42 unsigned long begin, end; 43 44 begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); 45 end = ((unsigned long)start + size + L1_CACHE_BYTES-1) 46 & ~(L1_CACHE_BYTES-1); 47 48 for (v = begin; v < end; v+=L1_CACHE_BYTES) 49 __raw_writel((v & CACHE_PHYSADDR_MASK), 50 CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0) | 0x00000008); 51 } 52 53 static void sh2__flush_invalidate_region(void *start, int size) 54 { 55 #ifdef CONFIG_CACHE_WRITEBACK 56 /* 57 * SH-2 does not support individual line invalidation, only a 58 * global invalidate. 59 */ 60 unsigned long ccr; 61 unsigned long flags; 62 local_irq_save(flags); 63 jump_to_uncached(); 64 65 ccr = __raw_readl(SH_CCR); 66 ccr |= CCR_CACHE_INVALIDATE; 67 __raw_writel(ccr, SH_CCR); 68 69 back_to_cached(); 70 local_irq_restore(flags); 71 #else 72 unsigned long v; 73 unsigned long begin, end; 74 75 begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); 76 end = ((unsigned long)start + size + L1_CACHE_BYTES-1) 77 & ~(L1_CACHE_BYTES-1); 78 79 for (v = begin; v < end; v+=L1_CACHE_BYTES) 80 __raw_writel((v & CACHE_PHYSADDR_MASK), 81 CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0) | 0x00000008); 82 #endif 83 } 84 85 void __init sh2_cache_init(void) 86 { 87 __flush_wback_region = sh2__flush_wback_region; 88 __flush_purge_region = sh2__flush_purge_region; 89 __flush_invalidate_region = sh2__flush_invalidate_region; 90 } 91