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 19static 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 40static 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 54static 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(SH_CCR); 67 ccr |= CCR_CACHE_INVALIDATE; 68 __raw_writel(ccr, SH_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 86void __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