diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/mips/mm/sc-ip22.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/mips/mm/sc-ip22.c')
-rw-r--r-- | arch/mips/mm/sc-ip22.c | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/arch/mips/mm/sc-ip22.c b/arch/mips/mm/sc-ip22.c new file mode 100644 index 000000000000..d236cf8b7374 --- /dev/null +++ b/arch/mips/mm/sc-ip22.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * sc-ip22.c: Indy cache management functions. | ||
3 | * | ||
4 | * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org), | ||
5 | * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com). | ||
6 | */ | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/sched.h> | ||
10 | #include <linux/mm.h> | ||
11 | |||
12 | #include <asm/bcache.h> | ||
13 | #include <asm/page.h> | ||
14 | #include <asm/pgtable.h> | ||
15 | #include <asm/system.h> | ||
16 | #include <asm/bootinfo.h> | ||
17 | #include <asm/sgi/ip22.h> | ||
18 | #include <asm/sgi/mc.h> | ||
19 | |||
20 | /* Secondary cache size in bytes, if present. */ | ||
21 | static unsigned long scache_size; | ||
22 | |||
23 | #undef DEBUG_CACHE | ||
24 | |||
25 | #define SC_SIZE 0x00080000 | ||
26 | #define SC_LINE 32 | ||
27 | #define CI_MASK (SC_SIZE - SC_LINE) | ||
28 | #define SC_INDEX(n) ((n) & CI_MASK) | ||
29 | |||
30 | static inline void indy_sc_wipe(unsigned long first, unsigned long last) | ||
31 | { | ||
32 | unsigned long tmp; | ||
33 | |||
34 | __asm__ __volatile__( | ||
35 | ".set\tpush\t\t\t# indy_sc_wipe\n\t" | ||
36 | ".set\tnoreorder\n\t" | ||
37 | ".set\tmips3\n\t" | ||
38 | ".set\tnoat\n\t" | ||
39 | "mfc0\t%2, $12\n\t" | ||
40 | "li\t$1, 0x80\t\t\t# Go 64 bit\n\t" | ||
41 | "mtc0\t$1, $12\n\t" | ||
42 | |||
43 | "dli\t$1, 0x9000000080000000\n\t" | ||
44 | "or\t%0, $1\t\t\t# first line to flush\n\t" | ||
45 | "or\t%1, $1\t\t\t# last line to flush\n\t" | ||
46 | ".set\tat\n\t" | ||
47 | |||
48 | "1:\tsw\t$0, 0(%0)\n\t" | ||
49 | "bne\t%0, %1, 1b\n\t" | ||
50 | " daddu\t%0, 32\n\t" | ||
51 | |||
52 | "mtc0\t%2, $12\t\t\t# Back to 32 bit\n\t" | ||
53 | "nop; nop; nop; nop;\n\t" | ||
54 | ".set\tpop" | ||
55 | : "=r" (first), "=r" (last), "=&r" (tmp) | ||
56 | : "0" (first), "1" (last)); | ||
57 | } | ||
58 | |||
59 | static void indy_sc_wback_invalidate(unsigned long addr, unsigned long size) | ||
60 | { | ||
61 | unsigned long first_line, last_line; | ||
62 | unsigned long flags; | ||
63 | |||
64 | #ifdef DEBUG_CACHE | ||
65 | printk("indy_sc_wback_invalidate[%08lx,%08lx]", addr, size); | ||
66 | #endif | ||
67 | |||
68 | /* Catch bad driver code */ | ||
69 | BUG_ON(size == 0); | ||
70 | |||
71 | /* Which lines to flush? */ | ||
72 | first_line = SC_INDEX(addr); | ||
73 | last_line = SC_INDEX(addr + size - 1); | ||
74 | |||
75 | local_irq_save(flags); | ||
76 | if (first_line <= last_line) { | ||
77 | indy_sc_wipe(first_line, last_line); | ||
78 | goto out; | ||
79 | } | ||
80 | |||
81 | indy_sc_wipe(first_line, SC_SIZE - SC_LINE); | ||
82 | indy_sc_wipe(0, last_line); | ||
83 | out: | ||
84 | local_irq_restore(flags); | ||
85 | } | ||
86 | |||
87 | static void indy_sc_enable(void) | ||
88 | { | ||
89 | unsigned long addr, tmp1, tmp2; | ||
90 | |||
91 | /* This is really cool... */ | ||
92 | #ifdef DEBUG_CACHE | ||
93 | printk("Enabling R4600 SCACHE\n"); | ||
94 | #endif | ||
95 | __asm__ __volatile__( | ||
96 | ".set\tpush\n\t" | ||
97 | ".set\tnoreorder\n\t" | ||
98 | ".set\tmips3\n\t" | ||
99 | "mfc0\t%2, $12\n\t" | ||
100 | "nop; nop; nop; nop;\n\t" | ||
101 | "li\t%1, 0x80\n\t" | ||
102 | "mtc0\t%1, $12\n\t" | ||
103 | "nop; nop; nop; nop;\n\t" | ||
104 | "li\t%0, 0x1\n\t" | ||
105 | "dsll\t%0, 31\n\t" | ||
106 | "lui\t%1, 0x9000\n\t" | ||
107 | "dsll32\t%1, 0\n\t" | ||
108 | "or\t%0, %1, %0\n\t" | ||
109 | "sb\t$0, 0(%0)\n\t" | ||
110 | "mtc0\t$0, $12\n\t" | ||
111 | "nop; nop; nop; nop;\n\t" | ||
112 | "mtc0\t%2, $12\n\t" | ||
113 | "nop; nop; nop; nop;\n\t" | ||
114 | ".set\tpop" | ||
115 | : "=r" (tmp1), "=r" (tmp2), "=r" (addr)); | ||
116 | } | ||
117 | |||
118 | static void indy_sc_disable(void) | ||
119 | { | ||
120 | unsigned long tmp1, tmp2, tmp3; | ||
121 | |||
122 | #ifdef DEBUG_CACHE | ||
123 | printk("Disabling R4600 SCACHE\n"); | ||
124 | #endif | ||
125 | __asm__ __volatile__( | ||
126 | ".set\tpush\n\t" | ||
127 | ".set\tnoreorder\n\t" | ||
128 | ".set\tmips3\n\t" | ||
129 | "li\t%0, 0x1\n\t" | ||
130 | "dsll\t%0, 31\n\t" | ||
131 | "lui\t%1, 0x9000\n\t" | ||
132 | "dsll32\t%1, 0\n\t" | ||
133 | "or\t%0, %1, %0\n\t" | ||
134 | "mfc0\t%2, $12\n\t" | ||
135 | "nop; nop; nop; nop\n\t" | ||
136 | "li\t%1, 0x80\n\t" | ||
137 | "mtc0\t%1, $12\n\t" | ||
138 | "nop; nop; nop; nop\n\t" | ||
139 | "sh\t$0, 0(%0)\n\t" | ||
140 | "mtc0\t$0, $12\n\t" | ||
141 | "nop; nop; nop; nop\n\t" | ||
142 | "mtc0\t%2, $12\n\t" | ||
143 | "nop; nop; nop; nop\n\t" | ||
144 | ".set\tpop" | ||
145 | : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)); | ||
146 | } | ||
147 | |||
148 | static inline int __init indy_sc_probe(void) | ||
149 | { | ||
150 | unsigned int size = ip22_eeprom_read(&sgimc->eeprom, 17); | ||
151 | if (size == 0) | ||
152 | return 0; | ||
153 | |||
154 | size <<= PAGE_SHIFT; | ||
155 | printk(KERN_INFO "R4600/R5000 SCACHE size %dK, linesize 32 bytes.\n", | ||
156 | size >> 10); | ||
157 | scache_size = size; | ||
158 | |||
159 | return 1; | ||
160 | } | ||
161 | |||
162 | /* XXX Check with wje if the Indy caches can differenciate between | ||
163 | writeback + invalidate and just invalidate. */ | ||
164 | struct bcache_ops indy_sc_ops = { | ||
165 | .bc_enable = indy_sc_enable, | ||
166 | .bc_disable = indy_sc_disable, | ||
167 | .bc_wback_inv = indy_sc_wback_invalidate, | ||
168 | .bc_inv = indy_sc_wback_invalidate | ||
169 | }; | ||
170 | |||
171 | void __init indy_sc_init(void) | ||
172 | { | ||
173 | if (indy_sc_probe()) { | ||
174 | indy_sc_enable(); | ||
175 | bcops = &indy_sc_ops; | ||
176 | } | ||
177 | } | ||