Blame view

arch/mips/mm/c-r4k.c 37.7 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
  /*
   * This file is subject to the terms and conditions of the GNU General Public
   * License.  See the file "COPYING" in the main directory of this archive
   * for more details.
   *
79add6277   Justin P. Mattock   update David Mill...
6
   * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
   * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Ralf Baechle (ralf@gnu.org)
   * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
   */
a754f7088   Ralf Baechle   [MIPS] Sibyte: re...
10
  #include <linux/hardirq.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
  #include <linux/init.h>
db813fe5a   Ralf Baechle   [MIPS] Avoid inde...
12
  #include <linux/highmem.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
  #include <linux/kernel.h>
641e97f31   Ralf Baechle   [MIPS] Sibyte: Re...
14
  #include <linux/linkage.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
  #include <linux/sched.h>
631330f58   Ralf Baechle   MIPS: Build fix -...
16
  #include <linux/smp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
  #include <linux/mm.h>
351336929   Chris Dearman   [MIPS] Allow sett...
18
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
22
  #include <linux/bitops.h>
  
  #include <asm/bcache.h>
  #include <asm/bootinfo.h>
ec74e361f   Ralf Baechle   Mark a few variab...
23
  #include <asm/cache.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
27
28
29
30
  #include <asm/cacheops.h>
  #include <asm/cpu.h>
  #include <asm/cpu-features.h>
  #include <asm/io.h>
  #include <asm/page.h>
  #include <asm/pgtable.h>
  #include <asm/r4kcache.h>
e001e5280   Ralf Baechle   [MIPS] Replace us...
31
  #include <asm/sections.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
  #include <asm/system.h>
  #include <asm/mmu_context.h>
  #include <asm/war.h>
ba5187dbb   Thiemo Seufer   Better interface ...
35
  #include <asm/cacheflush.h> /* for run_uncached() */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36

7f3f1d01a   Ralf Baechle   [MIPS] Fix deadlo...
37
38
39
40
41
42
43
44
  
  /*
   * Special Variant of smp_call_function for use by cache functions:
   *
   *  o No return value
   *  o collapses to normal function call on UP kernels
   *  o collapses to normal function call on systems with a single shared
   *    primary cache.
c8c5f3fd9   Ralf Baechle   MIPS: More detail...
45
   *  o doesn't disable interrupts on the local CPU
7f3f1d01a   Ralf Baechle   [MIPS] Fix deadlo...
46
   */
48a26e60c   Ralf Baechle   MIPS: Remove wait...
47
  static inline void r4k_on_each_cpu(void (*func) (void *info), void *info)
7f3f1d01a   Ralf Baechle   [MIPS] Fix deadlo...
48
49
50
51
  {
  	preempt_disable();
  
  #if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC)
48a26e60c   Ralf Baechle   MIPS: Remove wait...
52
  	smp_call_function(func, info, 1);
7f3f1d01a   Ralf Baechle   [MIPS] Fix deadlo...
53
54
55
56
  #endif
  	func(info);
  	preempt_enable();
  }
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
57
58
59
60
61
  #if defined(CONFIG_MIPS_CMP)
  #define cpu_has_safe_index_cacheops 0
  #else
  #define cpu_has_safe_index_cacheops 1
  #endif
ec74e361f   Ralf Baechle   Mark a few variab...
62
63
64
65
66
67
  /*
   * Must die.
   */
  static unsigned long icache_size __read_mostly;
  static unsigned long dcache_size __read_mostly;
  static unsigned long scache_size __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
70
71
  
  /*
   * Dummy cache handling routines for machines without boardcaches
   */
73f403527   Chris Dearman   [MIPS] Fix handli...
72
  static void cache_noop(void) {}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
  
  static struct bcache_ops no_sc_ops = {
73f403527   Chris Dearman   [MIPS] Fix handli...
75
76
77
78
  	.bc_enable = (void *)cache_noop,
  	.bc_disable = (void *)cache_noop,
  	.bc_wback_inv = (void *)cache_noop,
  	.bc_inv = (void *)cache_noop
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
81
  };
  
  struct bcache_ops *bcops = &no_sc_ops;
330cfe016   Thiemo Seufer   Let r4600 PRID de...
82
83
  #define cpu_is_r4600_v1_x()	((read_c0_prid() & 0xfffffff0) == 0x00002010)
  #define cpu_is_r4600_v2_x()	((read_c0_prid() & 0xfffffff0) == 0x00002020)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  
  #define R4600_HIT_CACHEOP_WAR_IMPL					\
  do {									\
  	if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())		\
  		*(volatile unsigned long *)CKSEG1;			\
  	if (R4600_V1_HIT_CACHEOP_WAR)					\
  		__asm__ __volatile__("nop;nop;nop;nop");		\
  } while (0)
  
  static void (*r4k_blast_dcache_page)(unsigned long addr);
  
  static inline void r4k_blast_dcache_page_dc32(unsigned long addr)
  {
  	R4600_HIT_CACHEOP_WAR_IMPL;
  	blast_dcache32_page(addr);
  }
605b7ef7b   Kevin Cernekee   MIPS: Support 64-...
100
101
102
103
104
  static inline void r4k_blast_dcache_page_dc64(unsigned long addr)
  {
  	R4600_HIT_CACHEOP_WAR_IMPL;
  	blast_dcache64_page(addr);
  }
234fcd148   Ralf Baechle   [MIPS] Fix loads ...
105
  static void __cpuinit r4k_blast_dcache_page_setup(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
  {
  	unsigned long  dc_lsize = cpu_dcache_line_size();
73f403527   Chris Dearman   [MIPS] Fix handli...
108
109
110
  	if (dc_lsize == 0)
  		r4k_blast_dcache_page = (void *)cache_noop;
  	else if (dc_lsize == 16)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
113
  		r4k_blast_dcache_page = blast_dcache16_page;
  	else if (dc_lsize == 32)
  		r4k_blast_dcache_page = r4k_blast_dcache_page_dc32;
605b7ef7b   Kevin Cernekee   MIPS: Support 64-...
114
115
  	else if (dc_lsize == 64)
  		r4k_blast_dcache_page = r4k_blast_dcache_page_dc64;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
118
  }
  
  static void (* r4k_blast_dcache_page_indexed)(unsigned long addr);
234fcd148   Ralf Baechle   [MIPS] Fix loads ...
119
  static void __cpuinit r4k_blast_dcache_page_indexed_setup(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
  {
  	unsigned long dc_lsize = cpu_dcache_line_size();
73f403527   Chris Dearman   [MIPS] Fix handli...
122
123
124
  	if (dc_lsize == 0)
  		r4k_blast_dcache_page_indexed = (void *)cache_noop;
  	else if (dc_lsize == 16)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
127
  		r4k_blast_dcache_page_indexed = blast_dcache16_page_indexed;
  	else if (dc_lsize == 32)
  		r4k_blast_dcache_page_indexed = blast_dcache32_page_indexed;
605b7ef7b   Kevin Cernekee   MIPS: Support 64-...
128
129
  	else if (dc_lsize == 64)
  		r4k_blast_dcache_page_indexed = blast_dcache64_page_indexed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
131
132
  }
  
  static void (* r4k_blast_dcache)(void);
234fcd148   Ralf Baechle   [MIPS] Fix loads ...
133
  static void __cpuinit r4k_blast_dcache_setup(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
  {
  	unsigned long dc_lsize = cpu_dcache_line_size();
73f403527   Chris Dearman   [MIPS] Fix handli...
136
137
138
  	if (dc_lsize == 0)
  		r4k_blast_dcache = (void *)cache_noop;
  	else if (dc_lsize == 16)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
  		r4k_blast_dcache = blast_dcache16;
  	else if (dc_lsize == 32)
  		r4k_blast_dcache = blast_dcache32;
605b7ef7b   Kevin Cernekee   MIPS: Support 64-...
142
143
  	else if (dc_lsize == 64)
  		r4k_blast_dcache = blast_dcache64;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
  }
  
  /* force code alignment (used for TX49XX_ICACHE_INDEX_INV_WAR) */
  #define JUMP_TO_ALIGN(order) \
  	__asm__ __volatile__( \
  		"b\t1f
  \t" \
  		".align\t" #order "
  \t" \
  		"1:
  \t" \
  		)
  #define CACHE32_UNROLL32_ALIGN	JUMP_TO_ALIGN(10) /* 32 * 32 = 1024 */
  #define CACHE32_UNROLL32_ALIGN2	JUMP_TO_ALIGN(11)
  
  static inline void blast_r4600_v1_icache32(void)
  {
  	unsigned long flags;
  
  	local_irq_save(flags);
  	blast_icache32();
  	local_irq_restore(flags);
  }
  
  static inline void tx49_blast_icache32(void)
  {
  	unsigned long start = INDEX_BASE;
  	unsigned long end = start + current_cpu_data.icache.waysize;
  	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
  	unsigned long ws_end = current_cpu_data.icache.ways <<
  	                       current_cpu_data.icache.waybit;
  	unsigned long ws, addr;
  
  	CACHE32_UNROLL32_ALIGN2;
  	/* I'm in even chunk.  blast odd chunks */
42a3b4f25   Ralf Baechle   [PATCH] mips: nuk...
179
180
  	for (ws = 0; ws < ws_end; ws += ws_inc)
  		for (addr = start + 0x400; addr < end; addr += 0x400 * 2)
21a151d8c   Ralf Baechle   [MIPS] checkfiles...
181
  			cache32_unroll32(addr|ws, Index_Invalidate_I);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
183
  	CACHE32_UNROLL32_ALIGN;
  	/* I'm in odd chunk.  blast even chunks */
42a3b4f25   Ralf Baechle   [PATCH] mips: nuk...
184
185
  	for (ws = 0; ws < ws_end; ws += ws_inc)
  		for (addr = start; addr < end; addr += 0x400 * 2)
21a151d8c   Ralf Baechle   [MIPS] checkfiles...
186
  			cache32_unroll32(addr|ws, Index_Invalidate_I);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
189
190
191
192
193
194
195
196
197
198
199
  }
  
  static inline void blast_icache32_r4600_v1_page_indexed(unsigned long page)
  {
  	unsigned long flags;
  
  	local_irq_save(flags);
  	blast_icache32_page_indexed(page);
  	local_irq_restore(flags);
  }
  
  static inline void tx49_blast_icache32_page_indexed(unsigned long page)
  {
67a3f6de9   Atsushi Nemoto   [MIPS] Fix tx49_b...
200
201
  	unsigned long indexmask = current_cpu_data.icache.waysize - 1;
  	unsigned long start = INDEX_BASE + (page & indexmask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
204
205
206
207
208
209
  	unsigned long end = start + PAGE_SIZE;
  	unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
  	unsigned long ws_end = current_cpu_data.icache.ways <<
  	                       current_cpu_data.icache.waybit;
  	unsigned long ws, addr;
  
  	CACHE32_UNROLL32_ALIGN2;
  	/* I'm in even chunk.  blast odd chunks */
42a3b4f25   Ralf Baechle   [PATCH] mips: nuk...
210
211
  	for (ws = 0; ws < ws_end; ws += ws_inc)
  		for (addr = start + 0x400; addr < end; addr += 0x400 * 2)
21a151d8c   Ralf Baechle   [MIPS] checkfiles...
212
  			cache32_unroll32(addr|ws, Index_Invalidate_I);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
  	CACHE32_UNROLL32_ALIGN;
  	/* I'm in odd chunk.  blast even chunks */
42a3b4f25   Ralf Baechle   [PATCH] mips: nuk...
215
216
  	for (ws = 0; ws < ws_end; ws += ws_inc)
  		for (addr = start; addr < end; addr += 0x400 * 2)
21a151d8c   Ralf Baechle   [MIPS] checkfiles...
217
  			cache32_unroll32(addr|ws, Index_Invalidate_I);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
219
220
  }
  
  static void (* r4k_blast_icache_page)(unsigned long addr);
234fcd148   Ralf Baechle   [MIPS] Fix loads ...
221
  static void __cpuinit r4k_blast_icache_page_setup(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
223
  {
  	unsigned long ic_lsize = cpu_icache_line_size();
73f403527   Chris Dearman   [MIPS] Fix handli...
224
225
226
  	if (ic_lsize == 0)
  		r4k_blast_icache_page = (void *)cache_noop;
  	else if (ic_lsize == 16)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
229
230
231
232
233
234
235
  		r4k_blast_icache_page = blast_icache16_page;
  	else if (ic_lsize == 32)
  		r4k_blast_icache_page = blast_icache32_page;
  	else if (ic_lsize == 64)
  		r4k_blast_icache_page = blast_icache64_page;
  }
  
  
  static void (* r4k_blast_icache_page_indexed)(unsigned long addr);
234fcd148   Ralf Baechle   [MIPS] Fix loads ...
236
  static void __cpuinit r4k_blast_icache_page_indexed_setup(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
  {
  	unsigned long ic_lsize = cpu_icache_line_size();
73f403527   Chris Dearman   [MIPS] Fix handli...
239
240
241
  	if (ic_lsize == 0)
  		r4k_blast_icache_page_indexed = (void *)cache_noop;
  	else if (ic_lsize == 16)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
  		r4k_blast_icache_page_indexed = blast_icache16_page_indexed;
  	else if (ic_lsize == 32) {
02fe2c9ce   Thiemo Seufer   Minor code cleanup.
244
  		if (R4600_V1_INDEX_ICACHEOP_WAR && cpu_is_r4600_v1_x())
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
  			r4k_blast_icache_page_indexed =
  				blast_icache32_r4600_v1_page_indexed;
02fe2c9ce   Thiemo Seufer   Minor code cleanup.
247
248
249
  		else if (TX49XX_ICACHE_INDEX_INV_WAR)
  			r4k_blast_icache_page_indexed =
  				tx49_blast_icache32_page_indexed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
251
252
253
254
255
256
257
  		else
  			r4k_blast_icache_page_indexed =
  				blast_icache32_page_indexed;
  	} else if (ic_lsize == 64)
  		r4k_blast_icache_page_indexed = blast_icache64_page_indexed;
  }
  
  static void (* r4k_blast_icache)(void);
234fcd148   Ralf Baechle   [MIPS] Fix loads ...
258
  static void __cpuinit r4k_blast_icache_setup(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
260
  {
  	unsigned long ic_lsize = cpu_icache_line_size();
73f403527   Chris Dearman   [MIPS] Fix handli...
261
262
263
  	if (ic_lsize == 0)
  		r4k_blast_icache = (void *)cache_noop;
  	else if (ic_lsize == 16)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264
265
266
267
268
269
270
271
272
273
274
275
276
  		r4k_blast_icache = blast_icache16;
  	else if (ic_lsize == 32) {
  		if (R4600_V1_INDEX_ICACHEOP_WAR && cpu_is_r4600_v1_x())
  			r4k_blast_icache = blast_r4600_v1_icache32;
  		else if (TX49XX_ICACHE_INDEX_INV_WAR)
  			r4k_blast_icache = tx49_blast_icache32;
  		else
  			r4k_blast_icache = blast_icache32;
  	} else if (ic_lsize == 64)
  		r4k_blast_icache = blast_icache64;
  }
  
  static void (* r4k_blast_scache_page)(unsigned long addr);
234fcd148   Ralf Baechle   [MIPS] Fix loads ...
277
  static void __cpuinit r4k_blast_scache_page_setup(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
279
  {
  	unsigned long sc_lsize = cpu_scache_line_size();
4debe4f96   Ralf Baechle   [MIPS] Initialize...
280
  	if (scache_size == 0)
73f403527   Chris Dearman   [MIPS] Fix handli...
281
  		r4k_blast_scache_page = (void *)cache_noop;
4debe4f96   Ralf Baechle   [MIPS] Initialize...
282
  	else if (sc_lsize == 16)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
284
285
286
287
288
289
290
291
292
  		r4k_blast_scache_page = blast_scache16_page;
  	else if (sc_lsize == 32)
  		r4k_blast_scache_page = blast_scache32_page;
  	else if (sc_lsize == 64)
  		r4k_blast_scache_page = blast_scache64_page;
  	else if (sc_lsize == 128)
  		r4k_blast_scache_page = blast_scache128_page;
  }
  
  static void (* r4k_blast_scache_page_indexed)(unsigned long addr);
234fcd148   Ralf Baechle   [MIPS] Fix loads ...
293
  static void __cpuinit r4k_blast_scache_page_indexed_setup(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294
295
  {
  	unsigned long sc_lsize = cpu_scache_line_size();
4debe4f96   Ralf Baechle   [MIPS] Initialize...
296
  	if (scache_size == 0)
73f403527   Chris Dearman   [MIPS] Fix handli...
297
  		r4k_blast_scache_page_indexed = (void *)cache_noop;
4debe4f96   Ralf Baechle   [MIPS] Initialize...
298
  	else if (sc_lsize == 16)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
301
302
303
304
305
306
307
308
  		r4k_blast_scache_page_indexed = blast_scache16_page_indexed;
  	else if (sc_lsize == 32)
  		r4k_blast_scache_page_indexed = blast_scache32_page_indexed;
  	else if (sc_lsize == 64)
  		r4k_blast_scache_page_indexed = blast_scache64_page_indexed;
  	else if (sc_lsize == 128)
  		r4k_blast_scache_page_indexed = blast_scache128_page_indexed;
  }
  
  static void (* r4k_blast_scache)(void);
234fcd148   Ralf Baechle   [MIPS] Fix loads ...
309
  static void __cpuinit r4k_blast_scache_setup(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
311
  {
  	unsigned long sc_lsize = cpu_scache_line_size();
4debe4f96   Ralf Baechle   [MIPS] Initialize...
312
  	if (scache_size == 0)
73f403527   Chris Dearman   [MIPS] Fix handli...
313
  		r4k_blast_scache = (void *)cache_noop;
4debe4f96   Ralf Baechle   [MIPS] Initialize...
314
  	else if (sc_lsize == 16)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
316
317
318
319
320
321
322
  		r4k_blast_scache = blast_scache16;
  	else if (sc_lsize == 32)
  		r4k_blast_scache = blast_scache32;
  	else if (sc_lsize == 64)
  		r4k_blast_scache = blast_scache64;
  	else if (sc_lsize == 128)
  		r4k_blast_scache = blast_scache128;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
  static inline void local_r4k___flush_cache_all(void * args)
  {
2a21c7300   Fuxin Zhang   [MIPS] define Hit...
325
326
327
328
  #if defined(CONFIG_CPU_LOONGSON2)
  	r4k_blast_scache();
  	return;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
330
  	r4k_blast_dcache();
  	r4k_blast_icache();
10cc35290   Ralf Baechle   [MIPS] Allow hard...
331
  	switch (current_cpu_type()) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
333
334
335
336
337
  	case CPU_R4000SC:
  	case CPU_R4000MC:
  	case CPU_R4400SC:
  	case CPU_R4400MC:
  	case CPU_R10000:
  	case CPU_R12000:
44d921b24   Kumba   [MIPS] Treat R140...
338
  	case CPU_R14000:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
341
342
343
344
  		r4k_blast_scache();
  	}
  }
  
  static void r4k___flush_cache_all(void)
  {
48a26e60c   Ralf Baechle   MIPS: Remove wait...
345
  	r4k_on_each_cpu(local_r4k___flush_cache_all, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
  }
a76ab5c10   Ralf Baechle   [MIPS] MT: Fix bu...
347
348
349
350
351
352
353
354
355
356
357
358
359
360
  static inline int has_valid_asid(const struct mm_struct *mm)
  {
  #if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
  	int i;
  
  	for_each_online_cpu(i)
  		if (cpu_context(i, mm))
  			return 1;
  
  	return 0;
  #else
  	return cpu_context(smp_processor_id(), mm);
  #endif
  }
9c5a3d729   Ralf Baechle   [MIPS] Handle ali...
361
362
363
364
365
366
367
368
369
  static void r4k__flush_cache_vmap(void)
  {
  	r4k_blast_dcache();
  }
  
  static void r4k__flush_cache_vunmap(void)
  {
  	r4k_blast_dcache();
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
372
  static inline void local_r4k_flush_cache_range(void * args)
  {
  	struct vm_area_struct *vma = args;
2eaa7ec28   Ralf Baechle   [MIPS] Handle I-c...
373
  	int exec = vma->vm_flags & VM_EXEC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374

a76ab5c10   Ralf Baechle   [MIPS] MT: Fix bu...
375
  	if (!(has_valid_asid(vma->vm_mm)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
  		return;
0550d9d13   Atsushi Nemoto   [MIPS] Remove red...
377
  	r4k_blast_dcache();
2eaa7ec28   Ralf Baechle   [MIPS] Handle I-c...
378
379
  	if (exec)
  		r4k_blast_icache();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
380
381
382
383
384
  }
  
  static void r4k_flush_cache_range(struct vm_area_struct *vma,
  	unsigned long start, unsigned long end)
  {
2eaa7ec28   Ralf Baechle   [MIPS] Handle I-c...
385
  	int exec = vma->vm_flags & VM_EXEC;
0550d9d13   Atsushi Nemoto   [MIPS] Remove red...
386

2eaa7ec28   Ralf Baechle   [MIPS] Handle I-c...
387
  	if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc))
48a26e60c   Ralf Baechle   MIPS: Remove wait...
388
  		r4k_on_each_cpu(local_r4k_flush_cache_range, vma);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
390
391
392
393
  }
  
  static inline void local_r4k_flush_cache_mm(void * args)
  {
  	struct mm_struct *mm = args;
a76ab5c10   Ralf Baechle   [MIPS] MT: Fix bu...
394
  	if (!has_valid_asid(mm))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
397
398
  	/*
  	 * Kludge alert.  For obscure reasons R4000SC and R4400SC go nuts if we
  	 * only flush the primary caches but R10000 and R12000 behave sane ...
617667ba7   Ralf Baechle   [MIPS] Avoid dupl...
399
400
  	 * R4000SC and R4400SC indexed S-cache ops also invalidate primary
  	 * caches, so we can bail out early.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
401
  	 */
10cc35290   Ralf Baechle   [MIPS] Allow hard...
402
403
404
405
  	if (current_cpu_type() == CPU_R4000SC ||
  	    current_cpu_type() == CPU_R4000MC ||
  	    current_cpu_type() == CPU_R4400SC ||
  	    current_cpu_type() == CPU_R4400MC) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
  		r4k_blast_scache();
617667ba7   Ralf Baechle   [MIPS] Avoid dupl...
407
408
409
410
  		return;
  	}
  
  	r4k_blast_dcache();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
412
413
414
415
416
  }
  
  static void r4k_flush_cache_mm(struct mm_struct *mm)
  {
  	if (!cpu_has_dc_aliases)
  		return;
48a26e60c   Ralf Baechle   MIPS: Remove wait...
417
  	r4k_on_each_cpu(local_r4k_flush_cache_mm, mm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
419
420
421
  }
  
  struct flush_cache_page_args {
  	struct vm_area_struct *vma;
6ec25809c   Ralf Baechle   Rename page argum...
422
  	unsigned long addr;
de62893bc   Atsushi Nemoto   [MIPS] local_r4k_...
423
  	unsigned long pfn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
425
426
427
428
429
  };
  
  static inline void local_r4k_flush_cache_page(void *args)
  {
  	struct flush_cache_page_args *fcp_args = args;
  	struct vm_area_struct *vma = fcp_args->vma;
6ec25809c   Ralf Baechle   Rename page argum...
430
  	unsigned long addr = fcp_args->addr;
db813fe5a   Ralf Baechle   [MIPS] Avoid inde...
431
  	struct page *page = pfn_to_page(fcp_args->pfn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
433
  	int exec = vma->vm_flags & VM_EXEC;
  	struct mm_struct *mm = vma->vm_mm;
c9c5023d8   Ralf Baechle   [MIPS] Fix buggy ...
434
  	int map_coherent = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
  	pgd_t *pgdp;
c6e8b5877   Ralf Baechle   Update MIPS to us...
436
  	pud_t *pudp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
438
  	pmd_t *pmdp;
  	pte_t *ptep;
db813fe5a   Ralf Baechle   [MIPS] Avoid inde...
439
  	void *vaddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440

79acf83e5   Ralf Baechle   Moves a test whic...
441
442
443
444
  	/*
  	 * If ownes no valid ASID yet, cannot possibly have gotten
  	 * this page into the cache.
  	 */
a76ab5c10   Ralf Baechle   [MIPS] MT: Fix bu...
445
  	if (!has_valid_asid(mm))
79acf83e5   Ralf Baechle   Moves a test whic...
446
  		return;
6ec25809c   Ralf Baechle   Rename page argum...
447
448
449
450
451
  	addr &= PAGE_MASK;
  	pgdp = pgd_offset(mm, addr);
  	pudp = pud_offset(pgdp, addr);
  	pmdp = pmd_offset(pudp, addr);
  	ptep = pte_offset(pmdp, addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
452
453
454
455
456
  
  	/*
  	 * If the page isn't marked valid, the page cannot possibly be
  	 * in the cache.
  	 */
526af35e5   Ralf Baechle   [MIPS] Use pte_pr...
457
  	if (!(pte_present(*ptep)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
  		return;
db813fe5a   Ralf Baechle   [MIPS] Avoid inde...
459
460
461
462
463
464
465
  	if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID))
  		vaddr = NULL;
  	else {
  		/*
  		 * Use kmap_coherent or kmap_atomic to do flushes for
  		 * another ASID than the current one.
  		 */
c9c5023d8   Ralf Baechle   [MIPS] Fix buggy ...
466
467
468
  		map_coherent = (cpu_has_dc_aliases &&
  				page_mapped(page) && !Page_dcache_dirty(page));
  		if (map_coherent)
db813fe5a   Ralf Baechle   [MIPS] Avoid inde...
469
470
471
472
  			vaddr = kmap_coherent(page, addr);
  		else
  			vaddr = kmap_atomic(page, KM_USER0);
  		addr = (unsigned long)vaddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
  	if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
db813fe5a   Ralf Baechle   [MIPS] Avoid inde...
475
  		r4k_blast_dcache_page(addr);
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
476
477
  		if (exec && !cpu_icache_snoops_remote_store)
  			r4k_blast_scache_page(addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
479
  	}
  	if (exec) {
db813fe5a   Ralf Baechle   [MIPS] Avoid inde...
480
  		if (vaddr && cpu_has_vtag_icache && mm == current->active_mm) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
  			int cpu = smp_processor_id();
26a51b270   Thiemo Seufer   Use intermediate ...
482
483
  			if (cpu_context(cpu, mm) != 0)
  				drop_mmu_context(mm, cpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
  		} else
db813fe5a   Ralf Baechle   [MIPS] Avoid inde...
485
486
487
488
  			r4k_blast_icache_page(addr);
  	}
  
  	if (vaddr) {
c9c5023d8   Ralf Baechle   [MIPS] Fix buggy ...
489
  		if (map_coherent)
db813fe5a   Ralf Baechle   [MIPS] Avoid inde...
490
491
492
  			kunmap_coherent();
  		else
  			kunmap_atomic(vaddr, KM_USER0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
494
  	}
  }
6ec25809c   Ralf Baechle   Rename page argum...
495
496
  static void r4k_flush_cache_page(struct vm_area_struct *vma,
  	unsigned long addr, unsigned long pfn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497
498
  {
  	struct flush_cache_page_args args;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
  	args.vma = vma;
6ec25809c   Ralf Baechle   Rename page argum...
500
  	args.addr = addr;
de62893bc   Atsushi Nemoto   [MIPS] local_r4k_...
501
  	args.pfn = pfn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502

48a26e60c   Ralf Baechle   MIPS: Remove wait...
503
  	r4k_on_each_cpu(local_r4k_flush_cache_page, &args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
505
506
507
508
509
510
511
512
  }
  
  static inline void local_r4k_flush_data_cache_page(void * addr)
  {
  	r4k_blast_dcache_page((unsigned long) addr);
  }
  
  static void r4k_flush_data_cache_page(unsigned long addr)
  {
a754f7088   Ralf Baechle   [MIPS] Sibyte: re...
513
514
515
  	if (in_atomic())
  		local_r4k_flush_data_cache_page((void *)addr);
  	else
48a26e60c   Ralf Baechle   MIPS: Remove wait...
516
  		r4k_on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
518
519
  }
  
  struct flush_icache_range_args {
d4264f183   Atsushi Nemoto   [MIPS] Remove wro...
520
521
  	unsigned long start;
  	unsigned long end;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
  };
e0cee3eea   Thomas Bogendoerfer   [MIPS] Fix WARNIN...
523
  static inline void local_r4k_flush_icache_range(unsigned long start, unsigned long end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
524
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
  	if (!cpu_has_ic_fills_f_dc) {
73f403527   Chris Dearman   [MIPS] Fix handli...
526
  		if (end - start >= dcache_size) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
528
  			r4k_blast_dcache();
  		} else {
10a3dabdd   Thiemo Seufer   Add/Fix missing b...
529
  			R4600_HIT_CACHEOP_WAR_IMPL;
41700e739   Atsushi Nemoto   [MIPS] Add protec...
530
  			protected_blast_dcache_range(start, end);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
533
534
535
  	}
  
  	if (end - start > icache_size)
  		r4k_blast_icache();
41700e739   Atsushi Nemoto   [MIPS] Add protec...
536
537
  	else
  		protected_blast_icache_range(start, end);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538
  }
e0cee3eea   Thomas Bogendoerfer   [MIPS] Fix WARNIN...
539
540
541
542
543
544
545
546
  static inline void local_r4k_flush_icache_range_ipi(void *args)
  {
  	struct flush_icache_range_args *fir_args = args;
  	unsigned long start = fir_args->start;
  	unsigned long end = fir_args->end;
  
  	local_r4k_flush_icache_range(start, end);
  }
d4264f183   Atsushi Nemoto   [MIPS] Remove wro...
547
  static void r4k_flush_icache_range(unsigned long start, unsigned long end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
548
549
550
551
552
  {
  	struct flush_icache_range_args args;
  
  	args.start = start;
  	args.end = end;
48a26e60c   Ralf Baechle   MIPS: Remove wait...
553
  	r4k_on_each_cpu(local_r4k_flush_icache_range_ipi, &args);
cc61c1fed   Ralf Baechle   MIPS R2 instructi...
554
  	instruction_hazard();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556
557
558
559
  #ifdef CONFIG_DMA_NONCOHERENT
  
  static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
560
561
  	/* Catch bad driver code */
  	BUG_ON(size == 0);
fc5d2d279   Ralf Baechle   [MIPS] Use the pr...
562
  	if (cpu_has_inclusive_pcaches) {
41700e739   Atsushi Nemoto   [MIPS] Add protec...
563
  		if (size >= scache_size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
  			r4k_blast_scache();
41700e739   Atsushi Nemoto   [MIPS] Add protec...
565
566
  		else
  			blast_scache_range(addr, addr + size);
d0023c4a0   Kevin Cernekee   MIPS: Add SYNC af...
567
  		__sync();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
569
570
571
572
573
574
575
  		return;
  	}
  
  	/*
  	 * Either no secondary cache or the available caches don't have the
  	 * subset property so we have to flush the primary caches
  	 * explicitly
  	 */
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
576
  	if (cpu_has_safe_index_cacheops && size >= dcache_size) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
578
  		r4k_blast_dcache();
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
  		R4600_HIT_CACHEOP_WAR_IMPL;
41700e739   Atsushi Nemoto   [MIPS] Add protec...
580
  		blast_dcache_range(addr, addr + size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
581
582
583
  	}
  
  	bc_wback_inv(addr, size);
d0023c4a0   Kevin Cernekee   MIPS: Add SYNC af...
584
  	__sync();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
586
587
588
  }
  
  static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
590
  	/* Catch bad driver code */
  	BUG_ON(size == 0);
fc5d2d279   Ralf Baechle   [MIPS] Use the pr...
591
  	if (cpu_has_inclusive_pcaches) {
41700e739   Atsushi Nemoto   [MIPS] Add protec...
592
  		if (size >= scache_size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
593
  			r4k_blast_scache();
a8ca8b64e   Ralf Baechle   MIPS: Avoid destr...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
  		else {
  			unsigned long lsize = cpu_scache_line_size();
  			unsigned long almask = ~(lsize - 1);
  
  			/*
  			 * There is no clearly documented alignment requirement
  			 * for the cache instruction on MIPS processors and
  			 * some processors, among them the RM5200 and RM7000
  			 * QED processors will throw an address error for cache
  			 * hit ops with insufficient alignment.  Solved by
  			 * aligning the address to cache line size.
  			 */
  			cache_op(Hit_Writeback_Inv_SD, addr & almask);
  			cache_op(Hit_Writeback_Inv_SD,
  				 (addr + size - 1) & almask);
e9c33572a   Thomas Bogendoerfer   [MIPS] Use real c...
609
  			blast_inv_scache_range(addr, addr + size);
a8ca8b64e   Ralf Baechle   MIPS: Avoid destr...
610
  		}
d0023c4a0   Kevin Cernekee   MIPS: Add SYNC af...
611
  		__sync();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
613
  		return;
  	}
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
614
  	if (cpu_has_safe_index_cacheops && size >= dcache_size) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
616
  		r4k_blast_dcache();
  	} else {
a8ca8b64e   Ralf Baechle   MIPS: Avoid destr...
617
618
  		unsigned long lsize = cpu_dcache_line_size();
  		unsigned long almask = ~(lsize - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
  		R4600_HIT_CACHEOP_WAR_IMPL;
a8ca8b64e   Ralf Baechle   MIPS: Avoid destr...
620
621
  		cache_op(Hit_Writeback_Inv_D, addr & almask);
  		cache_op(Hit_Writeback_Inv_D, (addr + size - 1)  & almask);
e9c33572a   Thomas Bogendoerfer   [MIPS] Use real c...
622
  		blast_inv_dcache_range(addr, addr + size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623
624
625
  	}
  
  	bc_inv(addr, size);
d0023c4a0   Kevin Cernekee   MIPS: Add SYNC af...
626
  	__sync();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
628
629
630
631
632
633
634
635
636
  }
  #endif /* CONFIG_DMA_NONCOHERENT */
  
  /*
   * While we're protected against bad userland addresses we don't care
   * very much about what happens in that case.  Usually a segmentation
   * fault will dump the process later on anyway ...
   */
  static void local_r4k_flush_cache_sigtramp(void * arg)
  {
02fe2c9ce   Thiemo Seufer   Minor code cleanup.
637
638
639
  	unsigned long ic_lsize = cpu_icache_line_size();
  	unsigned long dc_lsize = cpu_dcache_line_size();
  	unsigned long sc_lsize = cpu_scache_line_size();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
640
641
642
  	unsigned long addr = (unsigned long) arg;
  
  	R4600_HIT_CACHEOP_WAR_IMPL;
73f403527   Chris Dearman   [MIPS] Fix handli...
643
644
  	if (dc_lsize)
  		protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
4debe4f96   Ralf Baechle   [MIPS] Initialize...
645
  	if (!cpu_icache_snoops_remote_store && scache_size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646
  		protected_writeback_scache_line(addr & ~(sc_lsize - 1));
73f403527   Chris Dearman   [MIPS] Fix handli...
647
648
  	if (ic_lsize)
  		protected_flush_icache_line(addr & ~(ic_lsize - 1));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
650
651
652
653
654
655
656
  	if (MIPS4K_ICACHE_REFILL_WAR) {
  		__asm__ __volatile__ (
  			".set push
  \t"
  			".set noat
  \t"
  			".set mips3
  \t"
875d43e72   Ralf Baechle   [PATCH] mips: cle...
657
  #ifdef CONFIG_32BIT
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
659
660
  			"la	$at,1f
  \t"
  #endif
875d43e72   Ralf Baechle   [PATCH] mips: cle...
661
  #ifdef CONFIG_64BIT
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
  			"dla	$at,1f
  \t"
  #endif
  			"cache	%0,($at)
  \t"
  			"nop; nop; nop
  "
  			"1:
  \t"
  			".set pop"
  			:
  			: "i" (Hit_Invalidate_I));
  	}
  	if (MIPS_CACHE_SYNC_WAR)
  		__asm__ __volatile__ ("sync");
  }
  
  static void r4k_flush_cache_sigtramp(unsigned long addr)
  {
48a26e60c   Ralf Baechle   MIPS: Remove wait...
681
  	r4k_on_each_cpu(local_r4k_flush_cache_sigtramp, (void *) addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682
683
684
685
686
687
688
  }
  
  static void r4k_flush_icache_all(void)
  {
  	if (cpu_has_vtag_icache)
  		r4k_blast_icache();
  }
d9cdc901a   Ralf Baechle   MIPS: cache: Prov...
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
  struct flush_kernel_vmap_range_args {
  	unsigned long	vaddr;
  	int		size;
  };
  
  static inline void local_r4k_flush_kernel_vmap_range(void *args)
  {
  	struct flush_kernel_vmap_range_args *vmra = args;
  	unsigned long vaddr = vmra->vaddr;
  	int size = vmra->size;
  
  	/*
  	 * Aliases only affect the primary caches so don't bother with
  	 * S-caches or T-caches.
  	 */
  	if (cpu_has_safe_index_cacheops && size >= dcache_size)
  		r4k_blast_dcache();
  	else {
  		R4600_HIT_CACHEOP_WAR_IMPL;
  		blast_dcache_range(vaddr, vaddr + size);
  	}
  }
  
  static void r4k_flush_kernel_vmap_range(unsigned long vaddr, int size)
  {
  	struct flush_kernel_vmap_range_args args;
  
  	args.vaddr = (unsigned long) vaddr;
  	args.size = size;
  
  	r4k_on_each_cpu(local_r4k_flush_kernel_vmap_range, &args);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
721
722
723
724
725
726
727
728
729
730
731
  static inline void rm7k_erratum31(void)
  {
  	const unsigned long ic_lsize = 32;
  	unsigned long addr;
  
  	/* RM7000 erratum #31. The icache is screwed at startup. */
  	write_c0_taglo(0);
  	write_c0_taghi(0);
  
  	for (addr = INDEX_BASE; addr <= INDEX_BASE + 4096; addr += ic_lsize) {
  		__asm__ __volatile__ (
d8748a3ab   Thiemo Seufer   More .set push/pop.
732
733
  			".set push
  \t"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
  			".set noreorder
  \t"
  			".set mips3
  \t"
  			"cache\t%1, 0(%0)
  \t"
  			"cache\t%1, 0x1000(%0)
  \t"
  			"cache\t%1, 0x2000(%0)
  \t"
  			"cache\t%1, 0x3000(%0)
  \t"
  			"cache\t%2, 0(%0)
  \t"
  			"cache\t%2, 0x1000(%0)
  \t"
  			"cache\t%2, 0x2000(%0)
  \t"
  			"cache\t%2, 0x3000(%0)
  \t"
  			"cache\t%1, 0(%0)
  \t"
  			"cache\t%1, 0x1000(%0)
  \t"
  			"cache\t%1, 0x2000(%0)
  \t"
  			"cache\t%1, 0x3000(%0)
  \t"
d8748a3ab   Thiemo Seufer   More .set push/pop.
762
763
  			".set pop
  "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
765
766
767
  			:
  			: "r" (addr), "i" (Index_Store_Tag_I), "i" (Fill));
  	}
  }
234fcd148   Ralf Baechle   [MIPS] Fix loads ...
768
  static char *way_string[] __cpuinitdata = { NULL, "direct mapped", "2-way",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
769
770
  	"3-way", "4-way", "5-way", "6-way", "7-way", "8-way"
  };
234fcd148   Ralf Baechle   [MIPS] Fix loads ...
771
  static void __cpuinit probe_pcache(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
  {
  	struct cpuinfo_mips *c = &current_cpu_data;
  	unsigned int config = read_c0_config();
  	unsigned int prid = read_c0_prid();
  	unsigned long config1;
  	unsigned int lsize;
  
  	switch (c->cputype) {
  	case CPU_R4600:			/* QED style two way caches? */
  	case CPU_R4700:
  	case CPU_R5000:
  	case CPU_NEVADA:
  		icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
  		c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
  		c->icache.ways = 2;
3c68da798   Atsushi Nemoto   [MIPS] Use __ffs(...
787
  		c->icache.waybit = __ffs(icache_size/2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
789
790
791
  
  		dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
  		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
  		c->dcache.ways = 2;
3c68da798   Atsushi Nemoto   [MIPS] Use __ffs(...
792
  		c->dcache.waybit= __ffs(dcache_size/2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
  
  		c->options |= MIPS_CPU_CACHE_CDEX_P;
  		break;
  
  	case CPU_R5432:
  	case CPU_R5500:
  		icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
  		c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
  		c->icache.ways = 2;
  		c->icache.waybit= 0;
  
  		dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
  		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
  		c->dcache.ways = 2;
  		c->dcache.waybit = 0;
5864810bc   Shinya Kuribayashi   MIPS: VR5500: Ena...
808
  		c->options |= MIPS_CPU_CACHE_CDEX_P | MIPS_CPU_PREFETCH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
809
810
811
812
813
814
815
816
817
818
819
820
821
822
  		break;
  
  	case CPU_TX49XX:
  		icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
  		c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
  		c->icache.ways = 4;
  		c->icache.waybit= 0;
  
  		dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
  		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
  		c->dcache.ways = 4;
  		c->dcache.waybit = 0;
  
  		c->options |= MIPS_CPU_CACHE_CDEX_P;
de862b488   Atsushi Nemoto   [MIPS] TX49XX has...
823
  		c->options |= MIPS_CPU_PREFETCH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
  		break;
  
  	case CPU_R4000PC:
  	case CPU_R4000SC:
  	case CPU_R4000MC:
  	case CPU_R4400PC:
  	case CPU_R4400SC:
  	case CPU_R4400MC:
  	case CPU_R4300:
  		icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
  		c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
  		c->icache.ways = 1;
  		c->icache.waybit = 0; 	/* doesn't matter */
  
  		dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
  		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
  		c->dcache.ways = 1;
  		c->dcache.waybit = 0;	/* does not matter */
  
  		c->options |= MIPS_CPU_CACHE_CDEX_P;
  		break;
  
  	case CPU_R10000:
  	case CPU_R12000:
44d921b24   Kumba   [MIPS] Treat R140...
848
  	case CPU_R14000:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
849
850
851
852
853
854
855
856
857
858
859
860
861
862
  		icache_size = 1 << (12 + ((config & R10K_CONF_IC) >> 29));
  		c->icache.linesz = 64;
  		c->icache.ways = 2;
  		c->icache.waybit = 0;
  
  		dcache_size = 1 << (12 + ((config & R10K_CONF_DC) >> 26));
  		c->dcache.linesz = 32;
  		c->dcache.ways = 2;
  		c->dcache.waybit = 0;
  
  		c->options |= MIPS_CPU_PREFETCH;
  		break;
  
  	case CPU_VR4133:
2874fe553   Yoichi Yuasa   [MIPS] vr41xx: Re...
863
  		write_c0_config(config & ~VR41_CONF_P4K);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
864
865
866
867
  	case CPU_VR4131:
  		/* Workaround for cache instruction bug of VR4131 */
  		if (c->processor_id == 0x0c80U || c->processor_id == 0x0c81U ||
  		    c->processor_id == 0x0c82U) {
4e8ab3618   Yoichi Yuasa   [MIPS] VR41xx: Se...
868
869
870
  			config |= 0x00400000U;
  			if (c->processor_id == 0x0c80U)
  				config |= VR41_CONF_BP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
871
  			write_c0_config(config);
1058ecda9   Yoichi Yuasa   [MIPS] vr41xx: Ch...
872
873
  		} else
  			c->options |= MIPS_CPU_CACHE_CDEX_P;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
874
875
876
  		icache_size = 1 << (10 + ((config & CONF_IC) >> 9));
  		c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
  		c->icache.ways = 2;
3c68da798   Atsushi Nemoto   [MIPS] Use __ffs(...
877
  		c->icache.waybit = __ffs(icache_size/2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
878
879
880
881
  
  		dcache_size = 1 << (10 + ((config & CONF_DC) >> 6));
  		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
  		c->dcache.ways = 2;
3c68da798   Atsushi Nemoto   [MIPS] Use __ffs(...
882
  		c->dcache.waybit = __ffs(dcache_size/2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
  		break;
  
  	case CPU_VR41XX:
  	case CPU_VR4111:
  	case CPU_VR4121:
  	case CPU_VR4122:
  	case CPU_VR4181:
  	case CPU_VR4181A:
  		icache_size = 1 << (10 + ((config & CONF_IC) >> 9));
  		c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
  		c->icache.ways = 1;
  		c->icache.waybit = 0; 	/* doesn't matter */
  
  		dcache_size = 1 << (10 + ((config & CONF_DC) >> 6));
  		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
  		c->dcache.ways = 1;
  		c->dcache.waybit = 0;	/* does not matter */
  
  		c->options |= MIPS_CPU_CACHE_CDEX_P;
  		break;
  
  	case CPU_RM7000:
  		rm7k_erratum31();
  
  	case CPU_RM9000:
  		icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
  		c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
  		c->icache.ways = 4;
3c68da798   Atsushi Nemoto   [MIPS] Use __ffs(...
911
  		c->icache.waybit = __ffs(icache_size / c->icache.ways);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912
913
914
915
  
  		dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
  		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
  		c->dcache.ways = 4;
3c68da798   Atsushi Nemoto   [MIPS] Use __ffs(...
916
  		c->dcache.waybit = __ffs(dcache_size / c->dcache.ways);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
917
918
919
920
921
922
  
  #if !defined(CONFIG_SMP) || !defined(RM9000_CDEX_SMP_WAR)
  		c->options |= MIPS_CPU_CACHE_CDEX_P;
  #endif
  		c->options |= MIPS_CPU_PREFETCH;
  		break;
2a21c7300   Fuxin Zhang   [MIPS] define Hit...
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
  	case CPU_LOONGSON2:
  		icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
  		c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
  		if (prid & 0x3)
  			c->icache.ways = 4;
  		else
  			c->icache.ways = 2;
  		c->icache.waybit = 0;
  
  		dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
  		c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
  		if (prid & 0x3)
  			c->dcache.ways = 4;
  		else
  			c->dcache.ways = 2;
  		c->dcache.waybit = 0;
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
  	default:
  		if (!(config & MIPS_CONF_M))
  			panic("Don't know how to probe P-caches on this cpu.");
  
  		/*
  		 * So we seem to be a MIPS32 or MIPS64 CPU
  		 * So let's probe the I-cache ...
  		 */
  		config1 = read_c0_config1();
  
  		if ((lsize = ((config1 >> 19) & 7)))
  			c->icache.linesz = 2 << lsize;
  		else
  			c->icache.linesz = lsize;
  		c->icache.sets = 64 << ((config1 >> 22) & 7);
  		c->icache.ways = 1 + ((config1 >> 16) & 7);
  
  		icache_size = c->icache.sets *
  		              c->icache.ways *
  		              c->icache.linesz;
3c68da798   Atsushi Nemoto   [MIPS] Use __ffs(...
960
  		c->icache.waybit = __ffs(icache_size/c->icache.ways);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
  
  		if (config & 0x8)		/* VI bit */
  			c->icache.flags |= MIPS_CACHE_VTAG;
  
  		/*
  		 * Now probe the MIPS32 / MIPS64 data cache.
  		 */
  		c->dcache.flags = 0;
  
  		if ((lsize = ((config1 >> 10) & 7)))
  			c->dcache.linesz = 2 << lsize;
  		else
  			c->dcache.linesz= lsize;
  		c->dcache.sets = 64 << ((config1 >> 13) & 7);
  		c->dcache.ways = 1 + ((config1 >> 7) & 7);
  
  		dcache_size = c->dcache.sets *
  		              c->dcache.ways *
  		              c->dcache.linesz;
3c68da798   Atsushi Nemoto   [MIPS] Use __ffs(...
980
  		c->dcache.waybit = __ffs(dcache_size/c->dcache.ways);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
  
  		c->options |= MIPS_CPU_PREFETCH;
  		break;
  	}
  
  	/*
  	 * Processor configuration sanity check for the R4000SC erratum
  	 * #5.  With page sizes larger than 32kB there is no possibility
  	 * to get a VCE exception anymore so we don't care about this
  	 * misconfiguration.  The case is rather theoretical anyway;
  	 * presumably no vendor is shipping his hardware in the "bad"
  	 * configuration.
  	 */
  	if ((prid & 0xff00) == PRID_IMP_R4000 && (prid & 0xff) < 0x40 &&
  	    !(config & CONF_SC) && c->icache.linesz != 16 &&
  	    PAGE_SIZE <= 0x8000)
  		panic("Improper R4000SC processor configuration detected");
  
  	/* compute a couple of other cache variables */
  	c->icache.waysize = icache_size / c->icache.ways;
  	c->dcache.waysize = dcache_size / c->dcache.ways;
73f403527   Chris Dearman   [MIPS] Fix handli...
1002
1003
1004
1005
  	c->icache.sets = c->icache.linesz ?
  		icache_size / (c->icache.linesz * c->icache.ways) : 0;
  	c->dcache.sets = c->dcache.linesz ?
  		dcache_size / (c->dcache.linesz * c->dcache.ways) : 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1006
1007
1008
1009
1010
1011
1012
  
  	/*
  	 * R10000 and R12000 P-caches are odd in a positive way.  They're 32kB
  	 * 2-way virtually indexed so normally would suffer from aliases.  So
  	 * normally they'd suffer from aliases but magic in the hardware deals
  	 * with that for us so we don't need to take care ourselves.
  	 */
d1e344e50   Ralf Baechle   Use hardware mech...
1013
  	switch (c->cputype) {
a95970f32   Ralf Baechle   20Kc and SB1 don'...
1014
  	case CPU_20KC:
505403b6a   Ralf Baechle   25Kf is also phys...
1015
  	case CPU_25KF:
641e97f31   Ralf Baechle   [MIPS] Sibyte: Re...
1016
1017
  	case CPU_SB1:
  	case CPU_SB1A:
efa0f81c1   Jayachandran C   MIPS: Netlogic: C...
1018
  	case CPU_XLR:
de62893bc   Atsushi Nemoto   [MIPS] local_r4k_...
1019
  		c->dcache.flags |= MIPS_CACHE_PINDEX;
641e97f31   Ralf Baechle   [MIPS] Sibyte: Re...
1020
  		break;
d1e344e50   Ralf Baechle   Use hardware mech...
1021
1022
  	case CPU_R10000:
  	case CPU_R12000:
44d921b24   Kumba   [MIPS] Treat R140...
1023
  	case CPU_R14000:
d1e344e50   Ralf Baechle   Use hardware mech...
1024
  		break;
641e97f31   Ralf Baechle   [MIPS] Sibyte: Re...
1025

d1e344e50   Ralf Baechle   Use hardware mech...
1026
  	case CPU_24K:
98a41de99   Nigel Stephens   [MIPS] Add missin...
1027
  	case CPU_34K:
2e78ae3f4   Ralf Baechle   [MIPS] 74K: Assum...
1028
  	case CPU_74K:
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
1029
  	case CPU_1004K:
beab375a4   Ralf Baechle   [MIPS] Treat CPUs...
1030
1031
1032
1033
1034
1035
  		if ((read_c0_config7() & (1 << 16))) {
  			/* effectively physically indexed dcache,
  			   thus no virtual aliases. */
  			c->dcache.flags |= MIPS_CACHE_PINDEX;
  			break;
  		}
d1e344e50   Ralf Baechle   Use hardware mech...
1036
  	default:
beab375a4   Ralf Baechle   [MIPS] Treat CPUs...
1037
1038
  		if (c->dcache.waysize > PAGE_SIZE)
  			c->dcache.flags |= MIPS_CACHE_ALIASES;
d1e344e50   Ralf Baechle   Use hardware mech...
1039
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040
1041
1042
1043
1044
1045
1046
1047
1048
  
  	switch (c->cputype) {
  	case CPU_20KC:
  		/*
  		 * Some older 20Kc chips doesn't have the 'VI' bit in
  		 * the config register.
  		 */
  		c->icache.flags |= MIPS_CACHE_VTAG;
  		break;
270717a8a   Manuel Lauss   MIPS: Alchemy: un...
1049
  	case CPU_ALCHEMY:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1050
1051
1052
  		c->icache.flags |= MIPS_CACHE_IC_F_DC;
  		break;
  	}
2a21c7300   Fuxin Zhang   [MIPS] define Hit...
1053
1054
1055
1056
1057
1058
1059
  #ifdef  CONFIG_CPU_LOONGSON2
  	/*
  	 * LOONGSON2 has 4 way icache, but when using indexed cache op,
  	 * one op will act on all 4 ways
  	 */
  	c->icache.ways = 1;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1060
1061
1062
  	printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.
  ",
  	       icache_size >> 10,
7fc7316aa   Ralf Baechle   MIPS: Print the a...
1063
  	       c->icache.flags & MIPS_CACHE_VTAG ? "VIVT" : "VIPT",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1064
  	       way_string[c->icache.ways], c->icache.linesz);
64bfca5cd   Ralf Baechle   [MIPS] Cache: Pro...
1065
1066
1067
1068
1069
1070
1071
  	printk("Primary data cache %ldkB, %s, %s, %s, linesize %d bytes
  ",
  	       dcache_size >> 10, way_string[c->dcache.ways],
  	       (c->dcache.flags & MIPS_CACHE_PINDEX) ? "PIPT" : "VIPT",
  	       (c->dcache.flags & MIPS_CACHE_ALIASES) ?
  			"cache aliases" : "no aliases",
  	       c->dcache.linesz);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1072
1073
1074
1075
1076
1077
1078
1079
  }
  
  /*
   * If you even _breathe_ on this function, look at the gcc output and make sure
   * it does not pop things on and off the stack for the cache sizing loop that
   * executes in KSEG1 space or else you will crash and burn badly.  You have
   * been warned.
   */
234fcd148   Ralf Baechle   [MIPS] Fix loads ...
1080
  static int __cpuinit probe_scache(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1081
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1082
1083
1084
  	unsigned long flags, addr, begin, end, pow2;
  	unsigned int config = read_c0_config();
  	struct cpuinfo_mips *c = &current_cpu_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1085
1086
1087
  
  	if (config & CONF_SC)
  		return 0;
e001e5280   Ralf Baechle   [MIPS] Replace us...
1088
  	begin = (unsigned long) &_stext;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
  	begin &= ~((4 * 1024 * 1024) - 1);
  	end = begin + (4 * 1024 * 1024);
  
  	/*
  	 * This is such a bitch, you'd think they would make it easy to do
  	 * this.  Away you daemons of stupidity!
  	 */
  	local_irq_save(flags);
  
  	/* Fill each size-multiple cache line with a valid tag. */
  	pow2 = (64 * 1024);
  	for (addr = begin; addr < end; addr = (begin + pow2)) {
  		unsigned long *p = (unsigned long *) addr;
  		__asm__ __volatile__("nop" : : "r" (*p)); /* whee... */
  		pow2 <<= 1;
  	}
  
  	/* Load first line with zero (therefore invalid) tag. */
  	write_c0_taglo(0);
  	write_c0_taghi(0);
  	__asm__ __volatile__("nop; nop; nop; nop;"); /* avoid the hazard */
  	cache_op(Index_Store_Tag_I, begin);
  	cache_op(Index_Store_Tag_D, begin);
  	cache_op(Index_Store_Tag_SD, begin);
  
  	/* Now search for the wrap around point. */
  	pow2 = (128 * 1024);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
  	for (addr = begin + (128 * 1024); addr < end; addr = begin + pow2) {
  		cache_op(Index_Load_Tag_SD, addr);
  		__asm__ __volatile__("nop; nop; nop; nop;"); /* hazard... */
  		if (!read_c0_taglo())
  			break;
  		pow2 <<= 1;
  	}
  	local_irq_restore(flags);
  	addr -= begin;
  
  	scache_size = addr;
  	c->scache.linesz = 16 << ((config & R4K_CONF_SB) >> 22);
  	c->scache.ways = 1;
  	c->dcache.waybit = 0;		/* does not matter */
  
  	return 1;
  }
2a21c7300   Fuxin Zhang   [MIPS] define Hit...
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
  #if defined(CONFIG_CPU_LOONGSON2)
  static void __init loongson2_sc_init(void)
  {
  	struct cpuinfo_mips *c = &current_cpu_data;
  
  	scache_size = 512*1024;
  	c->scache.linesz = 32;
  	c->scache.ways = 4;
  	c->scache.waybit = 0;
  	c->scache.waysize = scache_size / (c->scache.ways);
  	c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
  	pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.
  ",
  	       scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
  
  	c->options |= MIPS_CPU_INCLUSIVE_CACHES;
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1151
1152
  extern int r5k_sc_init(void);
  extern int rm7k_sc_init(void);
9318c51ac   Chris Dearman   [MIPS] MIPS32/MIP...
1153
  extern int mips_sc_init(void);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1154

234fcd148   Ralf Baechle   [MIPS] Fix loads ...
1155
  static void __cpuinit setup_scache(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1156
1157
1158
  {
  	struct cpuinfo_mips *c = &current_cpu_data;
  	unsigned int config = read_c0_config();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1159
1160
1161
1162
1163
  	int sc_present = 0;
  
  	/*
  	 * Do the probing thing on R4000SC and R4400SC processors.  Other
  	 * processors don't have a S-cache that would be relevant to the
603e82edf   Joe Perches   arch/mips/: Spell...
1164
  	 * Linux memory management.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1165
1166
1167
1168
1169
1170
  	 */
  	switch (c->cputype) {
  	case CPU_R4000SC:
  	case CPU_R4000MC:
  	case CPU_R4400SC:
  	case CPU_R4400MC:
ba5187dbb   Thiemo Seufer   Better interface ...
1171
  		sc_present = run_uncached(probe_scache);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1172
1173
1174
1175
1176
1177
  		if (sc_present)
  			c->options |= MIPS_CPU_CACHE_CDEX_S;
  		break;
  
  	case CPU_R10000:
  	case CPU_R12000:
44d921b24   Kumba   [MIPS] Treat R140...
1178
  	case CPU_R14000:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
  		scache_size = 0x80000 << ((config & R10K_CONF_SS) >> 16);
  		c->scache.linesz = 64 << ((config >> 13) & 1);
  		c->scache.ways = 2;
  		c->scache.waybit= 0;
  		sc_present = 1;
  		break;
  
  	case CPU_R5000:
  	case CPU_NEVADA:
  #ifdef CONFIG_R5000_CPU_SCACHE
  		r5k_sc_init();
  #endif
                  return;
  
  	case CPU_RM7000:
  	case CPU_RM9000:
  #ifdef CONFIG_RM7000_CPU_SCACHE
  		rm7k_sc_init();
  #endif
  		return;
2a21c7300   Fuxin Zhang   [MIPS] define Hit...
1199
1200
1201
1202
1203
  #if defined(CONFIG_CPU_LOONGSON2)
  	case CPU_LOONGSON2:
  		loongson2_sc_init();
  		return;
  #endif
a3d4fb2d2   Jayachandran C   MIPS: Netlogic: X...
1204
1205
1206
  	case CPU_XLP:
  		/* don't need to worry about L2, fully coherent */
  		return;
2a21c7300   Fuxin Zhang   [MIPS] define Hit...
1207

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1208
  	default:
9318c51ac   Chris Dearman   [MIPS] MIPS32/MIP...
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
  		if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
  		    c->isa_level == MIPS_CPU_ISA_M32R2 ||
  		    c->isa_level == MIPS_CPU_ISA_M64R1 ||
  		    c->isa_level == MIPS_CPU_ISA_M64R2) {
  #ifdef CONFIG_MIPS_CPU_SCACHE
  			if (mips_sc_init ()) {
  				scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;
  				printk("MIPS secondary cache %ldkB, %s, linesize %d bytes.
  ",
  				       scache_size >> 10,
  				       way_string[c->scache.ways], c->scache.linesz);
  			}
  #else
  			if (!(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
  				panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
  #endif
  			return;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1227
1228
1229
1230
1231
  		sc_present = 0;
  	}
  
  	if (!sc_present)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1232
1233
1234
1235
1236
1237
1238
1239
  	/* compute a couple of other cache variables */
  	c->scache.waysize = scache_size / c->scache.ways;
  
  	c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
  
  	printk("Unified secondary cache %ldkB %s, linesize %d bytes.
  ",
  	       scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
fc5d2d279   Ralf Baechle   [MIPS] Use the pr...
1240
  	c->options |= MIPS_CPU_INCLUSIVE_CACHES;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1241
  }
9370b3517   Sergei Shtylyov   [MIPS] Save write...
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
  void au1x00_fixup_config_od(void)
  {
  	/*
  	 * c0_config.od (bit 19) was write only (and read as 0)
  	 * on the early revisions of Alchemy SOCs.  It disables the bus
  	 * transaction overlapping and needs to be set to fix various errata.
  	 */
  	switch (read_c0_prid()) {
  	case 0x00030100: /* Au1000 DA */
  	case 0x00030201: /* Au1000 HA */
  	case 0x00030202: /* Au1000 HB */
  	case 0x01030200: /* Au1500 AB */
  	/*
  	 * Au1100 errata actually keeps silence about this bit, so we set it
  	 * just in case for those revisions that require it to be set according
270717a8a   Manuel Lauss   MIPS: Alchemy: un...
1257
  	 * to the (now gone) cpu table.
9370b3517   Sergei Shtylyov   [MIPS] Save write...
1258
1259
1260
1261
1262
1263
1264
1265
  	 */
  	case 0x02030200: /* Au1100 AB */
  	case 0x02030201: /* Au1100 BA */
  	case 0x02030202: /* Au1100 BC */
  		set_c0_config(1 << 19);
  		break;
  	}
  }
89052bd7b   Ralf Baechle   [MIPS] Fix build ...
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
  /* CP0 hazard avoidance. */
  #define NXP_BARRIER()							\
  	 __asm__ __volatile__(						\
  	".set noreorder
  \t"						\
  	"nop; nop; nop; nop; nop; nop;
  \t"				\
  	".set reorder
  \t")
  
  static void nxp_pr4450_fixup_config(void)
  {
  	unsigned long config0;
  
  	config0 = read_c0_config();
  
  	/* clear all three cache coherency fields */
  	config0 &= ~(0x7 | (7 << 25) | (7 << 28));
  	config0 |= (((_page_cachable_default >> _CACHE_SHIFT) <<  0) |
  		    ((_page_cachable_default >> _CACHE_SHIFT) << 25) |
  		    ((_page_cachable_default >> _CACHE_SHIFT) << 28));
  	write_c0_config(config0);
  	NXP_BARRIER();
  }
351336929   Chris Dearman   [MIPS] Allow sett...
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
  static int __cpuinitdata cca = -1;
  
  static int __init cca_setup(char *str)
  {
  	get_option(&str, &cca);
  
  	return 1;
  }
  
  __setup("cca=", cca_setup);
234fcd148   Ralf Baechle   [MIPS] Fix loads ...
1300
  static void __cpuinit coherency_setup(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1301
  {
351336929   Chris Dearman   [MIPS] Allow sett...
1302
1303
1304
1305
1306
1307
1308
  	if (cca < 0 || cca > 7)
  		cca = read_c0_config() & CONF_CM_CMASK;
  	_page_cachable_default = cca << _CACHE_SHIFT;
  
  	pr_debug("Using cache attribute %d
  ", cca);
  	change_c0_config(CONF_CM_CMASK, cca);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1309
1310
1311
1312
1313
1314
1315
1316
  
  	/*
  	 * c0_status.cu=0 specifies that updates by the sc instruction use
  	 * the coherency mode specified by the TLB; 1 means cachable
  	 * coherent update on write will be used.  Not all processors have
  	 * this bit and; some wire it to zero, others like Toshiba had the
  	 * silly idea of putting something else there ...
  	 */
10cc35290   Ralf Baechle   [MIPS] Allow hard...
1317
  	switch (current_cpu_type()) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1318
1319
1320
1321
1322
1323
1324
1325
  	case CPU_R4000PC:
  	case CPU_R4000SC:
  	case CPU_R4000MC:
  	case CPU_R4400PC:
  	case CPU_R4400SC:
  	case CPU_R4400MC:
  		clear_c0_config(CONF_CU);
  		break;
9370b3517   Sergei Shtylyov   [MIPS] Save write...
1326
  	/*
df586d59a   Ralf Baechle   [MIPS] c-r4k: Typ...
1327
  	 * We need to catch the early Alchemy SOCs with
270717a8a   Manuel Lauss   MIPS: Alchemy: un...
1328
1329
  	 * the write-only co_config.od bit and set it back to one on:
  	 * Au1000 rev DA, HA, HB;  Au1100 AB, BA, BC, Au1500 AB
9370b3517   Sergei Shtylyov   [MIPS] Save write...
1330
  	 */
270717a8a   Manuel Lauss   MIPS: Alchemy: un...
1331
  	case CPU_ALCHEMY:
9370b3517   Sergei Shtylyov   [MIPS] Save write...
1332
1333
  		au1x00_fixup_config_od();
  		break;
89052bd7b   Ralf Baechle   [MIPS] Fix build ...
1334
1335
1336
1337
  
  	case PRID_IMP_PR4450:
  		nxp_pr4450_fixup_config();
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1338
1339
  	}
  }
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
  #if defined(CONFIG_DMA_NONCOHERENT)
  
  static int __cpuinitdata coherentio;
  
  static int __init setcoherentio(char *str)
  {
  	coherentio = 1;
  
  	return 1;
  }
  
  __setup("coherentio", setcoherentio);
  #endif
234fcd148   Ralf Baechle   [MIPS] Fix loads ...
1353
  void __cpuinit r4k_cache_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1354
1355
1356
  {
  	extern void build_clear_page(void);
  	extern void build_copy_page(void);
641e97f31   Ralf Baechle   [MIPS] Sibyte: Re...
1357
1358
  	extern char __weak except_vec2_generic;
  	extern char __weak except_vec2_sb1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1359
  	struct cpuinfo_mips *c = &current_cpu_data;
641e97f31   Ralf Baechle   [MIPS] Sibyte: Re...
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
  	switch (c->cputype) {
  	case CPU_SB1:
  	case CPU_SB1A:
  		set_uncached_handler(0x100, &except_vec2_sb1, 0x80);
  		break;
  
  	default:
  		set_uncached_handler(0x100, &except_vec2_generic, 0x80);
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1370
1371
1372
  
  	probe_pcache();
  	setup_scache();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
  	r4k_blast_dcache_page_setup();
  	r4k_blast_dcache_page_indexed_setup();
  	r4k_blast_dcache_setup();
  	r4k_blast_icache_page_setup();
  	r4k_blast_icache_page_indexed_setup();
  	r4k_blast_icache_setup();
  	r4k_blast_scache_page_setup();
  	r4k_blast_scache_page_indexed_setup();
  	r4k_blast_scache_setup();
  
  	/*
  	 * Some MIPS32 and MIPS64 processors have physically indexed caches.
  	 * This code supports virtually indexed processors and will be
  	 * unnecessarily inefficient on physically indexed processors.
  	 */
73f403527   Chris Dearman   [MIPS] Fix handli...
1388
1389
1390
1391
1392
1393
  	if (c->dcache.linesz)
  		shm_align_mask = max_t( unsigned long,
  					c->dcache.sets * c->dcache.linesz - 1,
  					PAGE_SIZE - 1);
  	else
  		shm_align_mask = PAGE_SIZE-1;
9c5a3d729   Ralf Baechle   [MIPS] Handle ali...
1394
1395
1396
  
  	__flush_cache_vmap	= r4k__flush_cache_vmap;
  	__flush_cache_vunmap	= r4k__flush_cache_vunmap;
db813fe5a   Ralf Baechle   [MIPS] Avoid inde...
1397
  	flush_cache_all		= cache_noop;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1398
1399
1400
  	__flush_cache_all	= r4k___flush_cache_all;
  	flush_cache_mm		= r4k_flush_cache_mm;
  	flush_cache_page	= r4k_flush_cache_page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1401
  	flush_cache_range	= r4k_flush_cache_range;
d9cdc901a   Ralf Baechle   MIPS: cache: Prov...
1402
  	__flush_kernel_vmap_range = r4k_flush_kernel_vmap_range;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1403
1404
  	flush_cache_sigtramp	= r4k_flush_cache_sigtramp;
  	flush_icache_all	= r4k_flush_icache_all;
7e3bfc7cf   Ralf Baechle   [MIPS] Handle IDE...
1405
  	local_flush_data_cache_page	= local_r4k_flush_data_cache_page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1406
1407
  	flush_data_cache_page	= r4k_flush_data_cache_page;
  	flush_icache_range	= r4k_flush_icache_range;
e0cee3eea   Thomas Bogendoerfer   [MIPS] Fix WARNIN...
1408
  	local_flush_icache_range	= local_r4k_flush_icache_range;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1409

39b8d5254   Ralf Baechle   [MIPS] Add suppor...
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
  #if defined(CONFIG_DMA_NONCOHERENT)
  	if (coherentio) {
  		_dma_cache_wback_inv	= (void *)cache_noop;
  		_dma_cache_wback	= (void *)cache_noop;
  		_dma_cache_inv		= (void *)cache_noop;
  	} else {
  		_dma_cache_wback_inv	= r4k_dma_cache_wback_inv;
  		_dma_cache_wback	= r4k_dma_cache_wback_inv;
  		_dma_cache_inv		= r4k_dma_cache_inv;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1420
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1421
1422
  	build_clear_page();
  	build_copy_page();
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
1423
  #if !defined(CONFIG_MIPS_CMP)
1d40cfcd3   Ralf Baechle   Avoid SMP cachefl...
1424
  	local_r4k___flush_cache_all(NULL);
39b8d5254   Ralf Baechle   [MIPS] Add suppor...
1425
  #endif
1d40cfcd3   Ralf Baechle   Avoid SMP cachefl...
1426
  	coherency_setup();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1427
  }