···11+#ifndef __ASM_CPU_SH2A_CACHEFLUSH_H22+#define __ASM_CPU_SH2A_CACHEFLUSH_H33+44+/* 55+ * Cache flushing:66+ *77+ * - flush_cache_all() flushes entire cache88+ * - flush_cache_mm(mm) flushes the specified mm context's cache lines99+ * - flush_cache_dup mm(mm) handles cache flushing when forking1010+ * - flush_cache_page(mm, vmaddr, pfn) flushes a single page1111+ * - flush_cache_range(vma, start, end) flushes a range of pages1212+ *1313+ * - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache1414+ * - flush_icache_range(start, end) flushes(invalidates) a range for icache1515+ * - flush_icache_page(vma, pg) flushes(invalidates) a page for icache1616+ *1717+ * Caches are indexed (effectively) by physical address on SH-2, so1818+ * we don't need them.1919+ */2020+#define flush_cache_all() do { } while (0)2121+#define flush_cache_mm(mm) do { } while (0)2222+#define flush_cache_dup_mm(mm) do { } while (0)2323+#define flush_cache_range(vma, start, end) do { } while (0)2424+#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)2525+#define flush_dcache_page(page) do { } while (0)2626+#define flush_dcache_mmap_lock(mapping) do { } while (0)2727+#define flush_dcache_mmap_unlock(mapping) do { } while (0)2828+void flush_icache_range(unsigned long start, unsigned long end);2929+#define flush_icache_page(vma,pg) do { } while (0)3030+#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)3131+#define flush_cache_sigtramp(vaddr) do { } while (0)3232+3333+#define p3_cache_init() do { } while (0)3434+#endif /* __ASM_CPU_SH2A_CACHEFLUSH_H */
···22 * arch/sh/mm/cache-sh2.c33 *44 * Copyright (C) 2002 Paul Mundt55+ * Copyright (C) 2008 Yoshinori Sato56 *67 * Released under the terms of the GNU GPL v2.0.78 */···2524 end = ((unsigned long)start + size + L1_CACHE_BYTES-1)2625 & ~(L1_CACHE_BYTES-1);2726 for (v = begin; v < end; v+=L1_CACHE_BYTES) {2828- /* FIXME cache purge */2929- ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);2727+ unsigned long addr = CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0);2828+ int way;2929+ for (way = 0; way < 4; way++) {3030+ unsigned long data = ctrl_inl(addr | (way << 12));3131+ if ((data & CACHE_PHYSADDR_MASK) == (v & CACHE_PHYSADDR_MASK)) {3232+ data &= ~SH_CACHE_UPDATED;3333+ ctrl_outl(data, addr | (way << 12));3434+ }3535+ }3036 }3137}3238···4537 begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);4638 end = ((unsigned long)start + size + L1_CACHE_BYTES-1)4739 & ~(L1_CACHE_BYTES-1);4848- for (v = begin; v < end; v+=L1_CACHE_BYTES) {4949- ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);5050- }4040+4141+ for (v = begin; v < end; v+=L1_CACHE_BYTES)4242+ ctrl_outl((v & CACHE_PHYSADDR_MASK),4343+ CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0) | 0x00000008);5144}52455346void __flush_invalidate_region(void *start, int size)5447{4848+#ifdef CONFIG_CACHE_WRITEBACK4949+ /*5050+ * SH-2 does not support individual line invalidation, only a5151+ * global invalidate.5252+ */5353+ unsigned long ccr;5454+ unsigned long flags;5555+ local_irq_save(flags);5656+ jump_to_uncached();5757+5858+ ccr = ctrl_inl(CCR);5959+ ccr |= CCR_CACHE_INVALIDATE;6060+ ctrl_outl(ccr, CCR);6161+6262+ back_to_cached();6363+ local_irq_restore(flags);6464+#else5565 unsigned long v;5666 unsigned long begin, end;57675868 begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);5969 end = ((unsigned long)start + size + L1_CACHE_BYTES-1)6070 & ~(L1_CACHE_BYTES-1);6161- for (v = begin; v < end; v+=L1_CACHE_BYTES) {6262- ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008);6363- }6464-}65717272+ for (v = begin; v < end; v+=L1_CACHE_BYTES)7373+ ctrl_outl((v & CACHE_PHYSADDR_MASK),7474+ CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0) | 0x00000008);7575+#endif7676+}
+129
arch/sh/mm/cache-sh2a.c
···11+/*22+ * arch/sh/mm/cache-sh2a.c33+ *44+ * Copyright (C) 2008 Yoshinori Sato55+ *66+ * Released under the terms of the GNU GPL v2.0.77+ */88+99+#include <linux/init.h>1010+#include <linux/mm.h>1111+1212+#include <asm/cache.h>1313+#include <asm/addrspace.h>1414+#include <asm/processor.h>1515+#include <asm/cacheflush.h>1616+#include <asm/io.h>1717+1818+void __flush_wback_region(void *start, int size)1919+{2020+ unsigned long v;2121+ unsigned long begin, end;2222+ unsigned long flags;2323+2424+ begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);2525+ end = ((unsigned long)start + size + L1_CACHE_BYTES-1)2626+ & ~(L1_CACHE_BYTES-1);2727+2828+ local_irq_save(flags);2929+ jump_to_uncached();3030+3131+ for (v = begin; v < end; v+=L1_CACHE_BYTES) {3232+ unsigned long addr = CACHE_OC_ADDRESS_ARRAY | (v & 0x000007f0);3333+ int way;3434+ for (way = 0; way < 4; way++) {3535+ unsigned long data = ctrl_inl(addr | (way << 11));3636+ if ((data & CACHE_PHYSADDR_MASK) == (v & CACHE_PHYSADDR_MASK)) {3737+ data &= ~SH_CACHE_UPDATED;3838+ ctrl_outl(data, addr | (way << 11));3939+ }4040+ }4141+ }4242+4343+ back_to_cached();4444+ local_irq_restore(flags);4545+}4646+4747+void __flush_purge_region(void *start, int size)4848+{4949+ unsigned long v;5050+ unsigned long begin, end;5151+ unsigned long flags;5252+5353+ begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);5454+ end = ((unsigned long)start + size + L1_CACHE_BYTES-1)5555+ & ~(L1_CACHE_BYTES-1);5656+5757+ local_irq_save(flags);5858+ jump_to_uncached();5959+6060+ for (v = begin; v < end; v+=L1_CACHE_BYTES) {6161+ ctrl_outl((v & CACHE_PHYSADDR_MASK),6262+ CACHE_OC_ADDRESS_ARRAY | (v & 0x000003f0) | 0x00000008);6363+ }6464+ back_to_cached();6565+ local_irq_restore(flags);6666+}6767+6868+void __flush_invalidate_region(void *start, int size)6969+{7070+ unsigned long v;7171+ unsigned long begin, end;7272+ unsigned long flags;7373+7474+ begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);7575+ end = ((unsigned long)start + size + L1_CACHE_BYTES-1)7676+ & ~(L1_CACHE_BYTES-1);7777+ local_irq_save(flags);7878+ jump_to_uncached();7979+8080+#ifdef CONFIG_CACHE_WRITEBACK8181+ ctrl_outl(ctrl_inl(CCR) | CCR_OCACHE_INVALIDATE, CCR);8282+ /* I-cache invalidate */8383+ for (v = begin; v < end; v+=L1_CACHE_BYTES) {8484+ ctrl_outl((v & CACHE_PHYSADDR_MASK),8585+ CACHE_IC_ADDRESS_ARRAY | (v & 0x000003f0) | 0x00000008);8686+ }8787+#else8888+ for (v = begin; v < end; v+=L1_CACHE_BYTES) {8989+ ctrl_outl((v & CACHE_PHYSADDR_MASK),9090+ CACHE_IC_ADDRESS_ARRAY | (v & 0x000003f0) | 0x00000008);9191+ ctrl_outl((v & CACHE_PHYSADDR_MASK),9292+ CACHE_OC_ADDRESS_ARRAY | (v & 0x000003f0) | 0x00000008);9393+ }9494+#endif9595+ back_to_cached();9696+ local_irq_restore(flags);9797+}9898+9999+/* WBack O-Cache and flush I-Cache */100100+void flush_icache_range(unsigned long start, unsigned long end)101101+{102102+ unsigned long v;103103+ unsigned long flags;104104+105105+ start = start & ~(L1_CACHE_BYTES-1);106106+ end = (end + L1_CACHE_BYTES-1) & ~(L1_CACHE_BYTES-1);107107+108108+ local_irq_save(flags);109109+ jump_to_uncached();110110+111111+ for (v = start; v < end; v+=L1_CACHE_BYTES) {112112+ unsigned long addr = (v & 0x000007f0);113113+ int way;114114+ /* O-Cache writeback */115115+ for (way = 0; way < 4; way++) {116116+ unsigned long data = ctrl_inl(CACHE_OC_ADDRESS_ARRAY | addr | (way << 11));117117+ if ((data & CACHE_PHYSADDR_MASK) == (v & CACHE_PHYSADDR_MASK)) {118118+ data &= ~SH_CACHE_UPDATED;119119+ ctrl_outl(data, CACHE_OC_ADDRESS_ARRAY | addr | (way << 11));120120+ }121121+ }122122+ /* I-Cache invalidate */123123+ ctrl_outl(addr,124124+ CACHE_IC_ADDRESS_ARRAY | addr | 0x00000008);125125+ }126126+127127+ back_to_cached();128128+ local_irq_restore(flags);129129+}