aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k
diff options
context:
space:
mode:
authorGreg Ungerer <gerg@uclinux.org>2011-10-17 00:38:09 -0400
committerGreg Ungerer <gerg@uclinux.org>2011-12-29 19:20:28 -0500
commitae2eca724af2802739efe02b3fc56daa8b674eb9 (patch)
treed95406d3f1eb6c8b1ddd8641d83b86fed10dd422 /arch/m68k
parent78d705e3be4bfbd2e75157d284096d600ea6eda5 (diff)
m68k: add cache support for V4e ColdFire cores running with MMU enabled
Add code to deal with instruction, data and branch caches of the V4e ColdFire cores when they are running with the MMU enabled. This code is loosely based on Freescales changes for the caches of the V4e ColdFire in the 2.6.25 kernel BSP. That code was originally by Kurt Mahan <kmahan@freescale.com> (now <kmahan@xmission.com>). Signed-off-by: Greg Ungerer <gerg@uclinux.org> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> Acked-by: Matt Waddel <mwaddel@yahoo.com> Acked-by: Kurt Mahan <kmahan@xmission.com>
Diffstat (limited to 'arch/m68k')
-rw-r--r--arch/m68k/include/asm/cacheflush_mm.h88
-rw-r--r--arch/m68k/mm/cache.c24
2 files changed, 104 insertions, 8 deletions
diff --git a/arch/m68k/include/asm/cacheflush_mm.h b/arch/m68k/include/asm/cacheflush_mm.h
index 73de7c89d8e..8104bd87464 100644
--- a/arch/m68k/include/asm/cacheflush_mm.h
+++ b/arch/m68k/include/asm/cacheflush_mm.h
@@ -2,23 +2,89 @@
2#define _M68K_CACHEFLUSH_H 2#define _M68K_CACHEFLUSH_H
3 3
4#include <linux/mm.h> 4#include <linux/mm.h>
5#ifdef CONFIG_COLDFIRE
6#include <asm/mcfsim.h>
7#endif
5 8
6/* cache code */ 9/* cache code */
7#define FLUSH_I_AND_D (0x00000808) 10#define FLUSH_I_AND_D (0x00000808)
8#define FLUSH_I (0x00000008) 11#define FLUSH_I (0x00000008)
9 12
13#ifndef ICACHE_MAX_ADDR
14#define ICACHE_MAX_ADDR 0
15#define ICACHE_SET_MASK 0
16#define DCACHE_MAX_ADDR 0
17#define DCACHE_SETMASK 0
18#endif
19
20static inline void flush_cf_icache(unsigned long start, unsigned long end)
21{
22 unsigned long set;
23
24 for (set = start; set <= end; set += (0x10 - 3)) {
25 __asm__ __volatile__ (
26 "cpushl %%ic,(%0)\n\t"
27 "addq%.l #1,%0\n\t"
28 "cpushl %%ic,(%0)\n\t"
29 "addq%.l #1,%0\n\t"
30 "cpushl %%ic,(%0)\n\t"
31 "addq%.l #1,%0\n\t"
32 "cpushl %%ic,(%0)"
33 : "=a" (set)
34 : "a" (set));
35 }
36}
37
38static inline void flush_cf_dcache(unsigned long start, unsigned long end)
39{
40 unsigned long set;
41
42 for (set = start; set <= end; set += (0x10 - 3)) {
43 __asm__ __volatile__ (
44 "cpushl %%dc,(%0)\n\t"
45 "addq%.l #1,%0\n\t"
46 "cpushl %%dc,(%0)\n\t"
47 "addq%.l #1,%0\n\t"
48 "cpushl %%dc,(%0)\n\t"
49 "addq%.l #1,%0\n\t"
50 "cpushl %%dc,(%0)"
51 : "=a" (set)
52 : "a" (set));
53 }
54}
55
56static inline void flush_cf_bcache(unsigned long start, unsigned long end)
57{
58 unsigned long set;
59
60 for (set = start; set <= end; set += (0x10 - 3)) {
61 __asm__ __volatile__ (
62 "cpushl %%bc,(%0)\n\t"
63 "addq%.l #1,%0\n\t"
64 "cpushl %%bc,(%0)\n\t"
65 "addq%.l #1,%0\n\t"
66 "cpushl %%bc,(%0)\n\t"
67 "addq%.l #1,%0\n\t"
68 "cpushl %%bc,(%0)"
69 : "=a" (set)
70 : "a" (set));
71 }
72}
73
10/* 74/*
11 * Cache handling functions 75 * Cache handling functions
12 */ 76 */
13 77
14static inline void flush_icache(void) 78static inline void flush_icache(void)
15{ 79{
16 if (CPU_IS_040_OR_060) 80 if (CPU_IS_COLDFIRE) {
81 flush_cf_icache(0, ICACHE_MAX_ADDR);
82 } else if (CPU_IS_040_OR_060) {
17 asm volatile ( "nop\n" 83 asm volatile ( "nop\n"
18 " .chip 68040\n" 84 " .chip 68040\n"
19 " cpusha %bc\n" 85 " cpusha %bc\n"
20 " .chip 68k"); 86 " .chip 68k");
21 else { 87 } else {
22 unsigned long tmp; 88 unsigned long tmp;
23 asm volatile ( "movec %%cacr,%0\n" 89 asm volatile ( "movec %%cacr,%0\n"
24 " or.w %1,%0\n" 90 " or.w %1,%0\n"
@@ -51,12 +117,14 @@ extern void cache_push_v(unsigned long vaddr, int len);
51 process changes. */ 117 process changes. */
52#define __flush_cache_all() \ 118#define __flush_cache_all() \
53({ \ 119({ \
54 if (CPU_IS_040_OR_060) \ 120 if (CPU_IS_COLDFIRE) { \
121 flush_cf_dcache(0, DCACHE_MAX_ADDR); \
122 } else if (CPU_IS_040_OR_060) { \
55 __asm__ __volatile__("nop\n\t" \ 123 __asm__ __volatile__("nop\n\t" \
56 ".chip 68040\n\t" \ 124 ".chip 68040\n\t" \
57 "cpusha %dc\n\t" \ 125 "cpusha %dc\n\t" \
58 ".chip 68k"); \ 126 ".chip 68k"); \
59 else { \ 127 } else { \
60 unsigned long _tmp; \ 128 unsigned long _tmp; \
61 __asm__ __volatile__("movec %%cacr,%0\n\t" \ 129 __asm__ __volatile__("movec %%cacr,%0\n\t" \
62 "orw %1,%0\n\t" \ 130 "orw %1,%0\n\t" \
@@ -112,7 +180,17 @@ static inline void flush_cache_page(struct vm_area_struct *vma, unsigned long vm
112/* RZ: use cpush %bc instead of cpush %dc, cinv %ic */ 180/* RZ: use cpush %bc instead of cpush %dc, cinv %ic */
113static inline void __flush_page_to_ram(void *vaddr) 181static inline void __flush_page_to_ram(void *vaddr)
114{ 182{
115 if (CPU_IS_040_OR_060) { 183 if (CPU_IS_COLDFIRE) {
184 unsigned long addr, start, end;
185 addr = ((unsigned long) vaddr) & ~(PAGE_SIZE - 1);
186 start = addr & ICACHE_SET_MASK;
187 end = (addr + PAGE_SIZE - 1) & ICACHE_SET_MASK;
188 if (start > end) {
189 flush_cf_bcache(0, end);
190 end = ICACHE_MAX_ADDR;
191 }
192 flush_cf_bcache(start, end);
193 } else if (CPU_IS_040_OR_060) {
116 __asm__ __volatile__("nop\n\t" 194 __asm__ __volatile__("nop\n\t"
117 ".chip 68040\n\t" 195 ".chip 68040\n\t"
118 "cpushp %%bc,(%0)\n\t" 196 "cpushp %%bc,(%0)\n\t"
diff --git a/arch/m68k/mm/cache.c b/arch/m68k/mm/cache.c
index 5437fff5fe0..95d0bf66e2e 100644
--- a/arch/m68k/mm/cache.c
+++ b/arch/m68k/mm/cache.c
@@ -74,8 +74,16 @@ static unsigned long virt_to_phys_slow(unsigned long vaddr)
74/* RZ: use cpush %bc instead of cpush %dc, cinv %ic */ 74/* RZ: use cpush %bc instead of cpush %dc, cinv %ic */
75void flush_icache_range(unsigned long address, unsigned long endaddr) 75void flush_icache_range(unsigned long address, unsigned long endaddr)
76{ 76{
77 77 if (CPU_IS_COLDFIRE) {
78 if (CPU_IS_040_OR_060) { 78 unsigned long start, end;
79 start = address & ICACHE_SET_MASK;
80 end = endaddr & ICACHE_SET_MASK;
81 if (start > end) {
82 flush_cf_icache(0, end);
83 end = ICACHE_MAX_ADDR;
84 }
85 flush_cf_icache(start, end);
86 } else if (CPU_IS_040_OR_060) {
79 address &= PAGE_MASK; 87 address &= PAGE_MASK;
80 88
81 do { 89 do {
@@ -100,7 +108,17 @@ EXPORT_SYMBOL(flush_icache_range);
100void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, 108void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
101 unsigned long addr, int len) 109 unsigned long addr, int len)
102{ 110{
103 if (CPU_IS_040_OR_060) { 111 if (CPU_IS_COLDFIRE) {
112 unsigned long start, end;
113 start = addr & ICACHE_SET_MASK;
114 end = (addr + len) & ICACHE_SET_MASK;
115 if (start > end) {
116 flush_cf_icache(0, end);
117 end = ICACHE_MAX_ADDR;
118 }
119 flush_cf_icache(start, end);
120
121 } else if (CPU_IS_040_OR_060) {
104 asm volatile ("nop\n\t" 122 asm volatile ("nop\n\t"
105 ".chip 68040\n\t" 123 ".chip 68040\n\t"
106 "cpushp %%bc,(%0)\n\t" 124 "cpushp %%bc,(%0)\n\t"