1*c456cfc2SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * arch/sh/mm/cache-sh2.c
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright (C) 2002 Paul Mundt
6cce2d453SYoshinori Sato * Copyright (C) 2008 Yoshinori Sato
71da177e4SLinus Torvalds */
89d4436a6SYoshinori Sato
91da177e4SLinus Torvalds #include <linux/init.h>
101da177e4SLinus Torvalds #include <linux/mm.h>
111da177e4SLinus Torvalds
121da177e4SLinus Torvalds #include <asm/cache.h>
131da177e4SLinus Torvalds #include <asm/addrspace.h>
141da177e4SLinus Torvalds #include <asm/processor.h>
151da177e4SLinus Torvalds #include <asm/cacheflush.h>
161da177e4SLinus Torvalds #include <asm/io.h>
171da177e4SLinus Torvalds
sh2__flush_wback_region(void * start,int size)18109b44a8SPaul Mundt static void sh2__flush_wback_region(void *start, int size)
191da177e4SLinus Torvalds {
209d4436a6SYoshinori Sato unsigned long v;
219d4436a6SYoshinori Sato unsigned long begin, end;
221da177e4SLinus Torvalds
239d4436a6SYoshinori Sato begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
249d4436a6SYoshinori Sato end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
259d4436a6SYoshinori Sato & ~(L1_CACHE_BYTES-1);
269d4436a6SYoshinori Sato for (v = begin; v < end; v+=L1_CACHE_BYTES) {
27cce2d453SYoshinori Sato unsigned long addr = CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0);
28cce2d453SYoshinori Sato int way;
29cce2d453SYoshinori Sato for (way = 0; way < 4; way++) {
309d56dd3bSPaul Mundt unsigned long data = __raw_readl(addr | (way << 12));
31cce2d453SYoshinori Sato if ((data & CACHE_PHYSADDR_MASK) == (v & CACHE_PHYSADDR_MASK)) {
32cce2d453SYoshinori Sato data &= ~SH_CACHE_UPDATED;
339d56dd3bSPaul Mundt __raw_writel(data, addr | (way << 12));
34cce2d453SYoshinori Sato }
35cce2d453SYoshinori Sato }
369d4436a6SYoshinori Sato }
379d4436a6SYoshinori Sato }
381da177e4SLinus Torvalds
sh2__flush_purge_region(void * start,int size)39109b44a8SPaul Mundt static void sh2__flush_purge_region(void *start, int size)
409d4436a6SYoshinori Sato {
419d4436a6SYoshinori Sato unsigned long v;
429d4436a6SYoshinori Sato unsigned long begin, end;
431da177e4SLinus Torvalds
449d4436a6SYoshinori Sato begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
459d4436a6SYoshinori Sato end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
469d4436a6SYoshinori Sato & ~(L1_CACHE_BYTES-1);
47cce2d453SYoshinori Sato
48cce2d453SYoshinori Sato for (v = begin; v < end; v+=L1_CACHE_BYTES)
499d56dd3bSPaul Mundt __raw_writel((v & CACHE_PHYSADDR_MASK),
50cce2d453SYoshinori Sato CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0) | 0x00000008);
519d4436a6SYoshinori Sato }
521da177e4SLinus Torvalds
sh2__flush_invalidate_region(void * start,int size)53109b44a8SPaul Mundt static void sh2__flush_invalidate_region(void *start, int size)
549d4436a6SYoshinori Sato {
55cce2d453SYoshinori Sato #ifdef CONFIG_CACHE_WRITEBACK
56cce2d453SYoshinori Sato /*
57cce2d453SYoshinori Sato * SH-2 does not support individual line invalidation, only a
58cce2d453SYoshinori Sato * global invalidate.
59cce2d453SYoshinori Sato */
60cce2d453SYoshinori Sato unsigned long ccr;
61cce2d453SYoshinori Sato unsigned long flags;
62cce2d453SYoshinori Sato local_irq_save(flags);
63cce2d453SYoshinori Sato jump_to_uncached();
64cce2d453SYoshinori Sato
65a5f6ea29SGeert Uytterhoeven ccr = __raw_readl(SH_CCR);
66cce2d453SYoshinori Sato ccr |= CCR_CACHE_INVALIDATE;
67a5f6ea29SGeert Uytterhoeven __raw_writel(ccr, SH_CCR);
68cce2d453SYoshinori Sato
69cce2d453SYoshinori Sato back_to_cached();
70cce2d453SYoshinori Sato local_irq_restore(flags);
71cce2d453SYoshinori Sato #else
729d4436a6SYoshinori Sato unsigned long v;
739d4436a6SYoshinori Sato unsigned long begin, end;
749d4436a6SYoshinori Sato
759d4436a6SYoshinori Sato begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
769d4436a6SYoshinori Sato end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
779d4436a6SYoshinori Sato & ~(L1_CACHE_BYTES-1);
781da177e4SLinus Torvalds
79cce2d453SYoshinori Sato for (v = begin; v < end; v+=L1_CACHE_BYTES)
809d56dd3bSPaul Mundt __raw_writel((v & CACHE_PHYSADDR_MASK),
81cce2d453SYoshinori Sato CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0) | 0x00000008);
82cce2d453SYoshinori Sato #endif
83cce2d453SYoshinori Sato }
84109b44a8SPaul Mundt
sh2_cache_init(void)85109b44a8SPaul Mundt void __init sh2_cache_init(void)
86109b44a8SPaul Mundt {
87109b44a8SPaul Mundt __flush_wback_region = sh2__flush_wback_region;
88109b44a8SPaul Mundt __flush_purge_region = sh2__flush_purge_region;
89109b44a8SPaul Mundt __flush_invalidate_region = sh2__flush_invalidate_region;
90109b44a8SPaul Mundt }
91