1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include <linux/config.h>
22#include <linux/init.h>
23#include <asm/mmu_context.h>
24#include <asm/bootinfo.h>
25#include <asm/cacheops.h>
26#include <asm/cpu.h>
27#include <asm/uaccess.h>
28
29extern void sb1_dma_init(void);
30
31
32static unsigned long icache_size;
33static unsigned long dcache_size;
34
35static unsigned short icache_line_size;
36static unsigned short dcache_line_size;
37
38static unsigned int icache_index_mask;
39static unsigned int dcache_index_mask;
40
41static unsigned short icache_assoc;
42static unsigned short dcache_assoc;
43
44static unsigned short icache_sets;
45static unsigned short dcache_sets;
46
47static unsigned int icache_range_cutoff;
48static unsigned int dcache_range_cutoff;
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66static inline void __sb1_writeback_inv_dcache_all(void)
67{
68 __asm__ __volatile__ (
69 ".set push \n"
70 ".set noreorder \n"
71 ".set noat \n"
72 ".set mips4 \n"
73 " move $1, $0 \n"
74 "1: cache %2, 0($1) \n"
75 " cache %2, (1<<13)($1)\n"
76 " cache %2, (2<<13)($1)\n"
77 " cache %2, (3<<13)($1)\n"
78 " addiu %1, %1, -1 \n"
79 " bnez %1, 1b \n"
80 " addu $1, $1, %0 \n"
81 ".set pop \n"
82 :
83 : "r" (dcache_line_size), "r" (dcache_sets),
84 "i" (Index_Writeback_Inv_D));
85}
86
87
88
89
90
91
92
93static inline void __sb1_writeback_inv_dcache_range(unsigned long start,
94 unsigned long end)
95{
96 __asm__ __volatile__ (
97 " .set push \n"
98 " .set noreorder \n"
99 " .set noat \n"
100 " .set mips4 \n"
101 " and $1, %0, %3 \n"
102 "1: cache %4, (0<<13)($1) \n"
103 " cache %4, (1<<13)($1) \n"
104 " cache %4, (2<<13)($1) \n"
105 " cache %4, (3<<13)($1) \n"
106 " xori $1, $1, 1<<12 \n"
107 " cache %4, (0<<13)($1) \n"
108 " cache %4, (1<<13)($1) \n"
109 " cache %4, (2<<13)($1) \n"
110 " cache %4, (3<<13)($1) \n"
111 " addu %0, %0, %2 \n"
112 " bne %0, %1, 1b \n"
113 " and $1, %0, %3 \n"
114 " sync \n"
115 " .set pop \n"
116 :
117 : "r" (start & ~(dcache_line_size - 1)),
118 "r" ((end + dcache_line_size - 1) & ~(dcache_line_size - 1)),
119 "r" (dcache_line_size),
120 "r" (dcache_index_mask),
121 "i" (Index_Writeback_Inv_D));
122}
123
124
125
126
127
128
129static inline void __sb1_writeback_inv_dcache_phys_range(unsigned long start,
130 unsigned long end)
131{
132 __asm__ __volatile__ (
133 " .set push \n"
134 " .set noreorder \n"
135 " .set noat \n"
136 " .set mips4 \n"
137 " and $1, %0, %3 \n"
138 "1: cache %4, (0<<13)($1) \n"
139 " cache %4, (1<<13)($1) \n"
140 " cache %4, (2<<13)($1) \n"
141 " cache %4, (3<<13)($1) \n"
142 " addu %0, %0, %2 \n"
143 " bne %0, %1, 1b \n"
144 " and $1, %0, %3 \n"
145 " sync \n"
146 " .set pop \n"
147 :
148 : "r" (start & ~(dcache_line_size - 1)),
149 "r" ((end + dcache_line_size - 1) & ~(dcache_line_size - 1)),
150 "r" (dcache_line_size),
151 "r" (dcache_index_mask),
152 "i" (Index_Writeback_Inv_D));
153}
154
155
156
157
158
159static inline void __sb1_flush_icache_all(void)
160{
161 __asm__ __volatile__ (
162 ".set push \n"
163 ".set noreorder \n"
164 ".set noat \n"
165 ".set mips4 \n"
166 " move $1, $0 \n"
167 "1: cache %2, 0($1) \n"
168 " cache %2, (1<<13)($1)\n"
169 " cache %2, (2<<13)($1)\n"
170 " cache %2, (3<<13)($1)\n"
171 " addiu %1, %1, -1 \n"
172 " bnez %1, 1b \n"
173 " addu $1, $1, %0 \n"
174 " bnezl $0, 2f \n"
175 " nop \n"
176 "2: sync \n"
177 ".set pop \n"
178 :
179 : "r" (icache_line_size), "r" (icache_sets),
180 "i" (Index_Invalidate_I));
181}
182
183
184
185
186
187
188static void local_sb1_flush_cache_page(struct vm_area_struct *vma,
189 unsigned long addr)
190{
191 int cpu = smp_processor_id();
192
193#ifndef CONFIG_SMP
194 if (!(vma->vm_flags & VM_EXEC))
195 return;
196#endif
197
198 __sb1_writeback_inv_dcache_range(addr, addr + PAGE_SIZE);
199
200
201
202
203 if (cpu_context(cpu, vma->vm_mm) != 0)
204 drop_mmu_context(vma->vm_mm, cpu);
205}
206
207#ifdef CONFIG_SMP
208struct flush_cache_page_args {
209 struct vm_area_struct *vma;
210 unsigned long addr;
211};
212
213static void sb1_flush_cache_page_ipi(void *info)
214{
215 struct flush_cache_page_args *args = info;
216
217 local_sb1_flush_cache_page(args->vma, args->addr);
218}
219
220
221static void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr)
222{
223 struct flush_cache_page_args args;
224
225 if (!(vma->vm_flags & VM_EXEC))
226 return;
227
228 addr &= PAGE_MASK;
229 args.vma = vma;
230 args.addr = addr;
231 smp_call_function(sb1_flush_cache_page_ipi, (void *) &args, 1, 1);
232 local_sb1_flush_cache_page(vma, addr);
233}
234#else
235void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr)
236 __attribute__((alias("local_sb1_flush_cache_page")));
237#endif
238
239
240
241
242
243
244
245static inline void __sb1_flush_icache_range(unsigned long start,
246 unsigned long end)
247{
248 __asm__ __volatile__ (
249 ".set push \n"
250 ".set noreorder \n"
251 ".set noat \n"
252 ".set mips4 \n"
253 " and $1, %0, %3 \n"
254 "1: cache %4, (0<<13)($1) \n"
255 " cache %4, (1<<13)($1) \n"
256 " cache %4, (2<<13)($1) \n"
257 " cache %4, (3<<13)($1) \n"
258 " addu %0, %0, %2 \n"
259 " bne %0, %1, 1b \n"
260 " and $1, %0, %3 \n"
261 " bnezl $0, 2f \n"
262 " nop \n"
263 "2: sync \n"
264 ".set pop \n"
265 :
266 : "r" (start & ~(icache_line_size - 1)),
267 "r" ((end + icache_line_size - 1) & ~(icache_line_size - 1)),
268 "r" (icache_line_size),
269 "r" (icache_index_mask),
270 "i" (Index_Invalidate_I));
271}
272
273
274
275
276
277static void local_sb1___flush_cache_all(void)
278{
279 __sb1_writeback_inv_dcache_all();
280 __sb1_flush_icache_all();
281}
282
283#ifdef CONFIG_SMP
284void sb1___flush_cache_all_ipi(void *ignored)
285 __attribute__((alias("local_sb1___flush_cache_all")));
286
287static void sb1___flush_cache_all(void)
288{
289 smp_call_function(sb1___flush_cache_all_ipi, 0, 1, 1);
290 local_sb1___flush_cache_all();
291}
292#else
293void sb1___flush_cache_all(void)
294 __attribute__((alias("local_sb1___flush_cache_all")));
295#endif
296
297
298
299
300
301
302
303
304
305static void local_sb1_flush_icache_range(unsigned long start,
306 unsigned long end)
307{
308
309 if ((end - start) > dcache_range_cutoff)
310 __sb1_writeback_inv_dcache_all();
311 else
312 __sb1_writeback_inv_dcache_range(start, end);
313
314
315 if ((end - start) > icache_range_cutoff)
316 __sb1_flush_icache_all();
317 else
318 __sb1_flush_icache_range(start, end);
319}
320
321#ifdef CONFIG_SMP
322struct flush_icache_range_args {
323 unsigned long start;
324 unsigned long end;
325};
326
327static void sb1_flush_icache_range_ipi(void *info)
328{
329 struct flush_icache_range_args *args = info;
330
331 local_sb1_flush_icache_range(args->start, args->end);
332}
333
334void sb1_flush_icache_range(unsigned long start, unsigned long end)
335{
336 struct flush_icache_range_args args;
337
338 args.start = start;
339 args.end = end;
340 smp_call_function(sb1_flush_icache_range_ipi, &args, 1, 1);
341 local_sb1_flush_icache_range(start, end);
342}
343#else
344void sb1_flush_icache_range(unsigned long start, unsigned long end)
345 __attribute__((alias("local_sb1_flush_icache_range")));
346#endif
347
348
349
350
351
352
353static void local_sb1_flush_icache_page(struct vm_area_struct *vma,
354 struct page *page)
355{
356 unsigned long start;
357 int cpu = smp_processor_id();
358
359#ifndef CONFIG_SMP
360 if (!(vma->vm_flags & VM_EXEC))
361 return;
362#endif
363
364
365 start = (unsigned long)(page-mem_map) << PAGE_SHIFT;
366 __sb1_writeback_inv_dcache_phys_range(start, start + PAGE_SIZE);
367
368
369
370
371 if (cpu_context(cpu, vma->vm_mm) != 0) {
372 drop_mmu_context(vma->vm_mm, cpu);
373 }
374}
375
376#ifdef CONFIG_SMP
377struct flush_icache_page_args {
378 struct vm_area_struct *vma;
379 struct page *page;
380};
381
382static void sb1_flush_icache_page_ipi(void *info)
383{
384 struct flush_icache_page_args *args = info;
385 local_sb1_flush_icache_page(args->vma, args->page);
386}
387
388
389static void sb1_flush_icache_page(struct vm_area_struct *vma,
390 struct page *page)
391{
392 struct flush_icache_page_args args;
393
394 if (!(vma->vm_flags & VM_EXEC))
395 return;
396 args.vma = vma;
397 args.page = page;
398 smp_call_function(sb1_flush_icache_page_ipi, (void *) &args, 1, 1);
399 local_sb1_flush_icache_page(vma, page);
400}
401#else
402void sb1_flush_icache_page(struct vm_area_struct *vma, struct page *page)
403 __attribute__((alias("local_sb1_flush_icache_page")));
404#endif
405
406
407
408
409static void local_sb1_flush_cache_sigtramp(unsigned long addr)
410{
411 __asm__ __volatile__ (
412 " .set push \n"
413 " .set noreorder \n"
414 " .set noat \n"
415 " .set mips4 \n"
416 " cache %2, (0<<13)(%0) \n"
417 " cache %2, (1<<13)(%0) \n"
418 " cache %2, (2<<13)(%0) \n"
419 " cache %2, (3<<13)(%0) \n"
420 " xori $1, %0, 1<<12 \n"
421 " cache %2, (0<<13)($1) \n"
422 " cache %2, (1<<13)($1) \n"
423 " cache %2, (2<<13)($1) \n"
424 " cache %2, (3<<13)($1) \n"
425 " cache %3, (0<<13)(%1) \n"
426 " cache %3, (1<<13)(%1) \n"
427 " cache %3, (2<<13)(%1) \n"
428 " cache %3, (3<<13)(%1) \n"
429 " bnezl $0, 1f \n"
430 " nop \n"
431 "1: \n"
432 " .set pop \n"
433 :
434 : "r" (addr & dcache_index_mask), "r" (addr & icache_index_mask),
435 "i" (Index_Writeback_Inv_D), "i" (Index_Invalidate_I));
436}
437
438#ifdef CONFIG_SMP
439static void sb1_flush_cache_sigtramp_ipi(void *info)
440{
441 unsigned long iaddr = (unsigned long) info;
442 local_sb1_flush_cache_sigtramp(iaddr);
443}
444
445static void sb1_flush_cache_sigtramp(unsigned long addr)
446{
447 local_sb1_flush_cache_sigtramp(addr);
448 smp_call_function(sb1_flush_cache_sigtramp_ipi, (void *) addr, 1, 1);
449}
450#else
451void sb1_flush_cache_sigtramp(unsigned long addr)
452 __attribute__((alias("local_sb1_flush_cache_sigtramp")));
453#endif
454
455
456
457
458
459
460
461static void sb1_nop(void)
462{
463}
464
465
466
467
468
469
470
471
472
473
474
475
476
477static unsigned int decode_cache_sets(unsigned int config_field)
478{
479 if (config_field == 7) {
480
481 return 0;
482 }
483 return (1<<(config_field + 6));
484}
485
486
487
488
489
490
491
492
493
494
495
496
497
498static unsigned int decode_cache_line_size(unsigned int config_field)
499{
500 if (config_field == 0) {
501 return 0;
502 } else if (config_field == 7) {
503
504 return 0;
505 }
506 return (1<<(config_field + 1));
507}
508
509
510
511
512
513
514
515
516
517
518
519
520static char *way_string[] = {
521 "direct mapped", "2-way", "3-way", "4-way",
522 "5-way", "6-way", "7-way", "8-way",
523};
524
525static __init void probe_cache_sizes(void)
526{
527 u32 config1;
528
529 config1 = read_c0_config1();
530 icache_line_size = decode_cache_line_size((config1 >> 19) & 0x7);
531 dcache_line_size = decode_cache_line_size((config1 >> 10) & 0x7);
532 icache_sets = decode_cache_sets((config1 >> 22) & 0x7);
533 dcache_sets = decode_cache_sets((config1 >> 13) & 0x7);
534 icache_assoc = ((config1 >> 16) & 0x7) + 1;
535 dcache_assoc = ((config1 >> 7) & 0x7) + 1;
536 icache_size = icache_line_size * icache_sets * icache_assoc;
537 dcache_size = dcache_line_size * dcache_sets * dcache_assoc;
538
539 icache_index_mask = (icache_sets - 1) * icache_line_size;
540 dcache_index_mask = (dcache_sets - 1) * dcache_line_size;
541
542
543
544
545
546
547 icache_range_cutoff = icache_sets * icache_line_size;
548 dcache_range_cutoff = (dcache_sets / 2) * icache_line_size;
549
550 printk("Primary instruction cache %ldkB, %s, linesize %d bytes.\n",
551 icache_size >> 10, way_string[icache_assoc - 1],
552 icache_line_size);
553 printk("Primary data cache %ldkB, %s, linesize %d bytes.\n",
554 dcache_size >> 10, way_string[dcache_assoc - 1],
555 dcache_line_size);
556}
557
558
559
560
561
562
563void ld_mmu_sb1(void)
564{
565 extern char except_vec2_sb1;
566 extern char handle_vec2_sb1;
567 unsigned long temp;
568
569
570 memcpy((void *)(KSEG0 + 0x100), &except_vec2_sb1, 0x80);
571 memcpy((void *)(KSEG1 + 0x100), &except_vec2_sb1, 0x80);
572 memcpy((void *)KSEG1ADDR(&handle_vec2_sb1), &handle_vec2_sb1, 0x80);
573
574 probe_cache_sizes();
575
576#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
577 sb1_dma_init();
578#endif
579
580
581
582
583
584
585 _flush_cache_range = (void *) sb1_nop;
586 _flush_cache_mm = (void (*)(struct mm_struct *))sb1_nop;
587 _flush_cache_all = sb1_nop;
588
589
590 _flush_icache_range = sb1_flush_icache_range;
591 _flush_icache_page = sb1_flush_icache_page;
592 _flush_icache_all = __sb1_flush_icache_all;
593
594
595 _flush_cache_page = sb1_flush_cache_page;
596
597 _flush_cache_sigtramp = sb1_flush_cache_sigtramp;
598 _flush_data_cache_page = (void *) sb1_nop;
599
600
601 ___flush_cache_all = sb1___flush_cache_all;
602
603 change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
604
605
606
607
608 __asm__ __volatile__ (
609 " .set push \n"
610 " .set mips4 \n"
611 " la %0, 1f \n"
612 " mtc0 %0, $14 \n"
613 " eret \n"
614 "1: .set pop \n"
615 : "=r" (temp));
616 flush_cache_all();
617}
618