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