Blame view

arch/mips/mm/c-tx39.c 10.1 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
  /*
   * r2300.c: R2000 and R3000 specific mmu/cache code.
   *
79add6277   Justin P. Mattock   update David Mill...
5
   * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
10
11
12
13
14
   *
   * with a lot of changes to make this thing work for R3000s
   * Tx39XX R4k style caches added. HK
   * Copyright (C) 1998, 1999, 2000 Harald Koerfgen
   * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
   */
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/sched.h>
631330f58   Ralf Baechle   MIPS: Build fix -...
15
  #include <linux/smp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
19
20
21
  #include <linux/mm.h>
  
  #include <asm/cacheops.h>
  #include <asm/page.h>
  #include <asm/pgtable.h>
  #include <asm/mmu_context.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
25
26
27
28
29
30
  #include <asm/isadep.h>
  #include <asm/io.h>
  #include <asm/bootinfo.h>
  #include <asm/cpu.h>
  
  /* For R3000 cores with R4000 style caches */
  static unsigned long icache_size, dcache_size;		/* Size in bytes */
  
  #include <asm/r4kcache.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
33
  /* This sequence is required to ensure icache is disabled immediately */
  #define TX39_STOP_STREAMING() \
  __asm__ __volatile__( \
703422879   Ralf Baechle   MIPS: Whitespace ...
34
35
36
37
38
39
  	".set	 push
  \t" \
  	".set	 noreorder
  \t" \
  	"b	 1f
  \t" \
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
43
44
45
46
47
48
49
  	"nop
  \t" \
  	"1:
  \t" \
  	".set pop" \
  	)
  
  /* TX39H-style cache flush routines. */
  static void tx39h_flush_icache_all(void)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
54
55
56
  	unsigned long flags, config;
  
  	/* disable icache (set ICE#) */
  	local_irq_save(flags);
  	config = read_c0_conf();
  	write_c0_conf(config & ~TX39_CONF_ICE);
  	TX39_STOP_STREAMING();
41700e739   Atsushi Nemoto   [MIPS] Add protec...
57
  	blast_icache16();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
61
62
63
  	write_c0_conf(config);
  	local_irq_restore(flags);
  }
  
  static void tx39h_dma_cache_wback_inv(unsigned long addr, unsigned long size)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
  	/* Catch bad driver code */
  	BUG_ON(size == 0);
  
  	iob();
41700e739   Atsushi Nemoto   [MIPS] Add protec...
68
  	blast_inv_dcache_range(addr, addr + size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
71
72
73
74
  }
  
  
  /* TX39H2,TX39H3 */
  static inline void tx39_blast_dcache_page(unsigned long addr)
  {
10cc35290   Ralf Baechle   [MIPS] Allow hard...
75
  	if (current_cpu_type() != CPU_TX3912)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  		blast_dcache16_page(addr);
  }
  
  static inline void tx39_blast_dcache_page_indexed(unsigned long addr)
  {
  	blast_dcache16_page_indexed(addr);
  }
  
  static inline void tx39_blast_dcache(void)
  {
  	blast_dcache16();
  }
  
  static inline void tx39_blast_icache_page(unsigned long addr)
  {
  	unsigned long flags, config;
  	/* disable icache (set ICE#) */
  	local_irq_save(flags);
  	config = read_c0_conf();
  	write_c0_conf(config & ~TX39_CONF_ICE);
  	TX39_STOP_STREAMING();
  	blast_icache16_page(addr);
  	write_c0_conf(config);
  	local_irq_restore(flags);
  }
  
  static inline void tx39_blast_icache_page_indexed(unsigned long addr)
  {
  	unsigned long flags, config;
  	/* disable icache (set ICE#) */
  	local_irq_save(flags);
  	config = read_c0_conf();
  	write_c0_conf(config & ~TX39_CONF_ICE);
  	TX39_STOP_STREAMING();
  	blast_icache16_page_indexed(addr);
  	write_c0_conf(config);
  	local_irq_restore(flags);
  }
  
  static inline void tx39_blast_icache(void)
  {
  	unsigned long flags, config;
  	/* disable icache (set ICE#) */
  	local_irq_save(flags);
  	config = read_c0_conf();
  	write_c0_conf(config & ~TX39_CONF_ICE);
  	TX39_STOP_STREAMING();
  	blast_icache16();
  	write_c0_conf(config);
  	local_irq_restore(flags);
  }
9c5a3d729   Ralf Baechle   [MIPS] Handle ali...
127
128
129
130
131
132
133
134
135
  static void tx39__flush_cache_vmap(void)
  {
  	tx39_blast_dcache();
  }
  
  static void tx39__flush_cache_vunmap(void)
  {
  	tx39_blast_dcache();
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
138
139
140
141
  static inline void tx39_flush_cache_all(void)
  {
  	if (!cpu_has_dc_aliases)
  		return;
  
  	tx39_blast_dcache();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
143
144
145
146
147
148
149
150
151
152
153
  }
  
  static inline void tx39___flush_cache_all(void)
  {
  	tx39_blast_dcache();
  	tx39_blast_icache();
  }
  
  static void tx39_flush_cache_mm(struct mm_struct *mm)
  {
  	if (!cpu_has_dc_aliases)
  		return;
a5664c407   Atsushi Nemoto   [MIPS] TX39: Remo...
154
155
  	if (cpu_context(smp_processor_id(), mm) != 0)
  		tx39_blast_dcache();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
157
158
159
160
  }
  
  static void tx39_flush_cache_range(struct vm_area_struct *vma,
  	unsigned long start, unsigned long end)
  {
a5664c407   Atsushi Nemoto   [MIPS] TX39: Remo...
161
162
  	if (!cpu_has_dc_aliases)
  		return;
9043f7e95   Atsushi Nemoto   Sync c-tx39.c wit...
163
  	if (!(cpu_context(smp_processor_id(), vma->vm_mm)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
  		return;
a5664c407   Atsushi Nemoto   [MIPS] TX39: Remo...
165
  	tx39_blast_dcache();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
167
168
169
170
171
172
  }
  
  static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn)
  {
  	int exec = vma->vm_flags & VM_EXEC;
  	struct mm_struct *mm = vma->vm_mm;
  	pgd_t *pgdp;
2bee1b584   Mike Rapoport   mips: add support...
173
  	p4d_t *p4dp;
c6e8b5877   Ralf Baechle   Update MIPS to us...
174
  	pud_t *pudp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
177
178
179
180
181
182
183
184
185
186
  	pmd_t *pmdp;
  	pte_t *ptep;
  
  	/*
  	 * If ownes no valid ASID yet, cannot possibly have gotten
  	 * this page into the cache.
  	 */
  	if (cpu_context(smp_processor_id(), mm) == 0)
  		return;
  
  	page &= PAGE_MASK;
  	pgdp = pgd_offset(mm, page);
2bee1b584   Mike Rapoport   mips: add support...
187
188
  	p4dp = p4d_offset(pgdp, page);
  	pudp = pud_offset(p4dp, page);
c6e8b5877   Ralf Baechle   Update MIPS to us...
189
  	pmdp = pmd_offset(pudp, page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
  	ptep = pte_offset(pmdp, page);
  
  	/*
  	 * If the page isn't marked valid, the page cannot possibly be
  	 * in the cache.
  	 */
  	if (!(pte_val(*ptep) & _PAGE_PRESENT))
  		return;
  
  	/*
  	 * Doing flushes for another ASID than the current one is
  	 * too difficult since stupid R4k caches do a TLB translation
  	 * for every cache flush operation.  So we do indexed flushes
  	 * in that case, which doesn't overly flush the cache too much.
  	 */
  	if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) {
  		if (cpu_has_dc_aliases || exec)
  			tx39_blast_dcache_page(page);
  		if (exec)
  			tx39_blast_icache_page(page);
  
  		return;
  	}
  
  	/*
  	 * Do indexed flush, too much work to get the (possible) TLB refills
  	 * to work correctly.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
219
220
221
222
  	if (cpu_has_dc_aliases || exec)
  		tx39_blast_dcache_page_indexed(page);
  	if (exec)
  		tx39_blast_icache_page_indexed(page);
  }
7e3bfc7cf   Ralf Baechle   [MIPS] Handle IDE...
223
224
  static void local_tx39_flush_data_cache_page(void * addr)
  {
a5664c407   Atsushi Nemoto   [MIPS] TX39: Remo...
225
  	tx39_blast_dcache_page((unsigned long)addr);
7e3bfc7cf   Ralf Baechle   [MIPS] Handle IDE...
226
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
229
230
231
232
233
  static void tx39_flush_data_cache_page(unsigned long addr)
  {
  	tx39_blast_dcache_page(addr);
  }
  
  static void tx39_flush_icache_range(unsigned long start, unsigned long end)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
235
  	if (end - start > dcache_size)
  		tx39_blast_dcache();
41700e739   Atsushi Nemoto   [MIPS] Add protec...
236
237
  	else
  		protected_blast_dcache_range(start, end);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
240
241
242
  
  	if (end - start > icache_size)
  		tx39_blast_icache();
  	else {
  		unsigned long flags, config;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
246
247
  		/* disable icache (set ICE#) */
  		local_irq_save(flags);
  		config = read_c0_conf();
  		write_c0_conf(config & ~TX39_CONF_ICE);
  		TX39_STOP_STREAMING();
41700e739   Atsushi Nemoto   [MIPS] Add protec...
248
  		protected_blast_icache_range(start, end);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
252
  		write_c0_conf(config);
  		local_irq_restore(flags);
  	}
  }
d9cdc901a   Ralf Baechle   MIPS: cache: Prov...
253
254
255
256
  static void tx39_flush_kernel_vmap_range(unsigned long vaddr, int size)
  {
  	BUG();
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
258
  static void tx39_dma_cache_wback_inv(unsigned long addr, unsigned long size)
  {
41700e739   Atsushi Nemoto   [MIPS] Add protec...
259
  	unsigned long end;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
261
262
263
264
265
266
267
268
269
  
  	if (((size | addr) & (PAGE_SIZE - 1)) == 0) {
  		end = addr + size;
  		do {
  			tx39_blast_dcache_page(addr);
  			addr += PAGE_SIZE;
  		} while(addr != end);
  	} else if (size > dcache_size) {
  		tx39_blast_dcache();
  	} else {
41700e739   Atsushi Nemoto   [MIPS] Add protec...
270
  		blast_dcache_range(addr, addr + size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
273
274
275
  	}
  }
  
  static void tx39_dma_cache_inv(unsigned long addr, unsigned long size)
  {
41700e739   Atsushi Nemoto   [MIPS] Add protec...
276
  	unsigned long end;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
278
279
280
281
282
283
284
285
286
  
  	if (((size | addr) & (PAGE_SIZE - 1)) == 0) {
  		end = addr + size;
  		do {
  			tx39_blast_dcache_page(addr);
  			addr += PAGE_SIZE;
  		} while(addr != end);
  	} else if (size > dcache_size) {
  		tx39_blast_dcache();
  	} else {
41700e739   Atsushi Nemoto   [MIPS] Add protec...
287
  		blast_inv_dcache_range(addr, addr + size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
291
292
293
294
295
296
297
298
299
300
301
  static __init void tx39_probe_cache(void)
  {
  	unsigned long config;
  
  	config = read_c0_conf();
  
  	icache_size = 1 << (10 + ((config & TX39_CONF_ICS_MASK) >>
  				  TX39_CONF_ICS_SHIFT));
  	dcache_size = 1 << (10 + ((config & TX39_CONF_DCS_MASK) >>
  				  TX39_CONF_DCS_SHIFT));
  
  	current_cpu_data.icache.linesz = 16;
10cc35290   Ralf Baechle   [MIPS] Allow hard...
302
  	switch (current_cpu_type()) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
  	case CPU_TX3912:
  		current_cpu_data.icache.ways = 1;
  		current_cpu_data.dcache.ways = 1;
  		current_cpu_data.dcache.linesz = 4;
  		break;
  
  	case CPU_TX3927:
  		current_cpu_data.icache.ways = 2;
  		current_cpu_data.dcache.ways = 2;
  		current_cpu_data.dcache.linesz = 16;
  		break;
  
  	case CPU_TX3922:
  	default:
  		current_cpu_data.icache.ways = 1;
  		current_cpu_data.dcache.ways = 1;
  		current_cpu_data.dcache.linesz = 16;
  		break;
  	}
  }
078a55fc8   Paul Gortmaker   MIPS: Delete __cp...
323
  void tx39_cache_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
325
326
327
328
329
330
331
332
333
  {
  	extern void build_clear_page(void);
  	extern void build_copy_page(void);
  	unsigned long config;
  
  	config = read_c0_conf();
  	config &= ~TX39_CONF_WBON;
  	write_c0_conf(config);
  
  	tx39_probe_cache();
10cc35290   Ralf Baechle   [MIPS] Allow hard...
334
  	switch (current_cpu_type()) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
  	case CPU_TX3912:
  		/* TX39/H core (writethru direct-map cache) */
9c5a3d729   Ralf Baechle   [MIPS] Handle ali...
337
338
  		__flush_cache_vmap	= tx39__flush_cache_vmap;
  		__flush_cache_vunmap	= tx39__flush_cache_vunmap;
703422879   Ralf Baechle   MIPS: Whitespace ...
339
  		flush_cache_all = tx39h_flush_icache_all;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
341
342
343
  		__flush_cache_all	= tx39h_flush_icache_all;
  		flush_cache_mm		= (void *) tx39h_flush_icache_all;
  		flush_cache_range	= (void *) tx39h_flush_icache_all;
  		flush_cache_page	= (void *) tx39h_flush_icache_all;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
  		flush_icache_range	= (void *) tx39h_flush_icache_all;
e0cee3eea   Thomas Bogendoerfer   [MIPS] Fix WARNIN...
345
  		local_flush_icache_range = (void *) tx39h_flush_icache_all;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346

7e3bfc7cf   Ralf Baechle   [MIPS] Handle IDE...
347
  		local_flush_data_cache_page	= (void *) tx39h_flush_icache_all;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
349
350
351
352
353
354
355
356
357
358
359
  		flush_data_cache_page	= (void *) tx39h_flush_icache_all;
  
  		_dma_cache_wback_inv	= tx39h_dma_cache_wback_inv;
  
  		shm_align_mask		= PAGE_SIZE - 1;
  
  		break;
  
  	case CPU_TX3922:
  	case CPU_TX3927:
  	default:
  		/* TX39/H2,H3 core (writeback 2way-set-associative cache) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360
  		/* board-dependent init code may set WBON */
9c5a3d729   Ralf Baechle   [MIPS] Handle ali...
361
362
  		__flush_cache_vmap	= tx39__flush_cache_vmap;
  		__flush_cache_vunmap	= tx39__flush_cache_vunmap;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
365
366
367
  		flush_cache_all = tx39_flush_cache_all;
  		__flush_cache_all = tx39___flush_cache_all;
  		flush_cache_mm = tx39_flush_cache_mm;
  		flush_cache_range = tx39_flush_cache_range;
  		flush_cache_page = tx39_flush_cache_page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
  		flush_icache_range = tx39_flush_icache_range;
3885ec8ca   Atsushi Nemoto   [MIPS] TX39xx: Ad...
369
  		local_flush_icache_range = tx39_flush_icache_range;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370

d9cdc901a   Ralf Baechle   MIPS: cache: Prov...
371
  		__flush_kernel_vmap_range = tx39_flush_kernel_vmap_range;
7e3bfc7cf   Ralf Baechle   [MIPS] Handle IDE...
372
  		local_flush_data_cache_page = local_tx39_flush_data_cache_page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
374
375
376
377
378
379
  		flush_data_cache_page = tx39_flush_data_cache_page;
  
  		_dma_cache_wback_inv = tx39_dma_cache_wback_inv;
  		_dma_cache_wback = tx39_dma_cache_wback_inv;
  		_dma_cache_inv = tx39_dma_cache_inv;
  
  		shm_align_mask = max_t(unsigned long,
703422879   Ralf Baechle   MIPS: Whitespace ...
380
381
  				       (dcache_size / current_cpu_data.dcache.ways) - 1,
  				       PAGE_SIZE - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
383
384
  
  		break;
  	}
01882b4d5   James Hogan   MIPS: c-r4k: Spli...
385
386
  	__flush_icache_user_range = flush_icache_range;
  	__local_flush_icache_user_range = local_flush_icache_range;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
  	current_cpu_data.icache.waysize = icache_size / current_cpu_data.icache.ways;
  	current_cpu_data.dcache.waysize = dcache_size / current_cpu_data.dcache.ways;
  
  	current_cpu_data.icache.sets =
  		current_cpu_data.icache.waysize / current_cpu_data.icache.linesz;
  	current_cpu_data.dcache.sets =
  		current_cpu_data.dcache.waysize / current_cpu_data.dcache.linesz;
  
  	if (current_cpu_data.dcache.waysize > PAGE_SIZE)
  		current_cpu_data.dcache.flags |= MIPS_CACHE_ALIASES;
  
  	current_cpu_data.icache.waybit = 0;
  	current_cpu_data.dcache.waybit = 0;
  
  	printk("Primary instruction cache %ldkB, linesize %d bytes
  ",
  		icache_size >> 10, current_cpu_data.icache.linesz);
  	printk("Primary data cache %ldkB, linesize %d bytes
  ",
  		dcache_size >> 10, current_cpu_data.dcache.linesz);
  
  	build_clear_page();
  	build_copy_page();
1d40cfcd3   Ralf Baechle   Avoid SMP cachefl...
410
  	tx39h_flush_icache_all();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
  }