blob: c4e80d2b764bee59086679e9f6af7111c3842e98 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * arch/sh/mm/cache-sh2.c
3 *
4 * Copyright (C) 2002 Paul Mundt
Yoshinori Satocce2d452008-08-04 16:33:47 +09005 * Copyright (C) 2008 Yoshinori Sato
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 *
7 * Released under the terms of the GNU GPL v2.0.
8 */
Yoshinori Sato9d4436a2006-11-05 15:40:13 +09009
Linus Torvalds1da177e2005-04-16 15:20:36 -070010#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
Yoshinori Sato9d4436a2006-11-05 15:40:13 +090019void __flush_wback_region(void *start, int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -070020{
Yoshinori Sato9d4436a2006-11-05 15:40:13 +090021 unsigned long v;
22 unsigned long begin, end;
Linus Torvalds1da177e2005-04-16 15:20:36 -070023
Yoshinori Sato9d4436a2006-11-05 15:40:13 +090024 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) {
Yoshinori Satocce2d452008-08-04 16:33:47 +090028 unsigned long addr = CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0);
29 int way;
30 for (way = 0; way < 4; way++) {
31 unsigned long data = ctrl_inl(addr | (way << 12));
32 if ((data & CACHE_PHYSADDR_MASK) == (v & CACHE_PHYSADDR_MASK)) {
33 data &= ~SH_CACHE_UPDATED;
34 ctrl_outl(data, addr | (way << 12));
35 }
36 }
Yoshinori Sato9d4436a2006-11-05 15:40:13 +090037 }
38}
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
Yoshinori Sato9d4436a2006-11-05 15:40:13 +090040void __flush_purge_region(void *start, int size)
41{
42 unsigned long v;
43 unsigned long begin, end;
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
Yoshinori Sato9d4436a2006-11-05 15:40:13 +090045 begin = (unsigned long)start & ~(L1_CACHE_BYTES-1);
46 end = ((unsigned long)start + size + L1_CACHE_BYTES-1)
47 & ~(L1_CACHE_BYTES-1);
Yoshinori Satocce2d452008-08-04 16:33:47 +090048
49 for (v = begin; v < end; v+=L1_CACHE_BYTES)
50 ctrl_outl((v & CACHE_PHYSADDR_MASK),
51 CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0) | 0x00000008);
Yoshinori Sato9d4436a2006-11-05 15:40:13 +090052}
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
Yoshinori Sato9d4436a2006-11-05 15:40:13 +090054void __flush_invalidate_region(void *start, int size)
55{
Yoshinori Satocce2d452008-08-04 16:33:47 +090056#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 = ctrl_inl(CCR);
67 ccr |= CCR_CACHE_INVALIDATE;
68 ctrl_outl(ccr, CCR);
69
70 back_to_cached();
71 local_irq_restore(flags);
72#else
Yoshinori Sato9d4436a2006-11-05 15:40:13 +090073 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
Yoshinori Satocce2d452008-08-04 16:33:47 +090080 for (v = begin; v < end; v+=L1_CACHE_BYTES)
81 ctrl_outl((v & CACHE_PHYSADDR_MASK),
82 CACHE_OC_ADDRESS_ARRAY | (v & 0x00000ff0) | 0x00000008);
83#endif
84}