1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <linux/init.h>
16#include <linux/kernel.h>
17#include <linux/ptrace.h>
18#include <linux/stddef.h>
19
20#include <asm/bugs.h>
21#include <asm/cpu.h>
22#include <asm/fpu.h>
23#include <asm/mipsregs.h>
24#include <asm/system.h>
25
26
27
28
29
30
31
32
33void (*cpu_wait)(void) = NULL;
34
35static void r3081_wait(void)
36{
37 unsigned long cfg = read_c0_conf();
38 write_c0_conf(cfg | R30XX_CONF_HALT);
39}
40
41static void r39xx_wait(void)
42{
43 unsigned long cfg = read_c0_conf();
44 write_c0_conf(cfg | TX39_CONF_HALT);
45}
46
47static void r4k_wait(void)
48{
49 __asm__(".set\tmips3\n\t"
50 "wait\n\t"
51 ".set\tmips0");
52}
53
54void au1k_wait(void)
55{
56#ifdef CONFIG_PM
57
58 __asm__(".set\tmips3\n\t"
59 "wait\n\t"
60 "nop\n\t"
61 "nop\n\t"
62 "nop\n\t"
63 "nop\n\t"
64 ".set\tmips0");
65#else
66 __asm__("nop\n\t"
67 "nop");
68#endif
69}
70
71static inline void check_wait(void)
72{
73 struct cpuinfo_mips *c = ¤t_cpu_data;
74
75 printk("Checking for 'wait' instruction... ");
76 switch (c->cputype) {
77 case CPU_R3081:
78 case CPU_R3081E:
79 cpu_wait = r3081_wait;
80 printk(" available.\n");
81 break;
82 case CPU_TX3927:
83 cpu_wait = r39xx_wait;
84 printk(" available.\n");
85 break;
86 case CPU_R4200:
87
88 case CPU_R4600:
89 case CPU_R4640:
90 case CPU_R4650:
91 case CPU_R4700:
92 case CPU_R5000:
93 case CPU_NEVADA:
94 case CPU_RM7000:
95 case CPU_TX49XX:
96 case CPU_4KC:
97 case CPU_4KEC:
98 case CPU_4KSC:
99 case CPU_5KC:
100
101 case CPU_24K:
102 case CPU_25KF:
103 cpu_wait = r4k_wait;
104 printk(" available.\n");
105 break;
106 case CPU_AU1000:
107 case CPU_AU1100:
108 case CPU_AU1500:
109 cpu_wait = au1k_wait;
110 printk(" available.\n");
111 break;
112 default:
113 printk(" unavailable.\n");
114 break;
115 }
116}
117
118static inline void align_mod(const int align, const int mod)
119{
120 asm volatile(
121 ".set push\n\t"
122 ".set noreorder\n\t"
123 ".balign %0\n\t"
124 ".rept %1\n\t"
125 "nop\n\t"
126 ".endr\n\t"
127 ".set pop"
128 :
129 : "n" (align), "n" (mod));
130}
131
132static inline void mult_sh_align_mod(long *v1, long *v2, long *w,
133 const int align, const int mod)
134{
135 unsigned long flags;
136 int m1, m2;
137 long p, s, lv1, lv2, lw;
138
139
140
141
142
143
144
145
146
147 local_irq_save(flags);
148
149
150
151
152
153
154
155
156
157
158 asm volatile(
159 ""
160 : "=r" (m1), "=r" (m2), "=r" (s)
161 : "0" (5), "1" (8), "2" (5));
162 align_mod(align, mod);
163
164
165
166
167
168
169 asm volatile(
170 ".set push\n\t"
171 ".set noat\n\t"
172 ".set noreorder\n\t"
173 ".set nomacro\n\t"
174 "mult %2, %3\n\t"
175 "dsll32 %0, %4, %5\n\t"
176 "mflo $0\n\t"
177 "dsll32 %1, %4, %5\n\t"
178 "nop\n\t"
179 ".set pop"
180 : "=&r" (lv1), "=r" (lw)
181 : "r" (m1), "r" (m2), "r" (s), "I" (0)
182 : "hi", "lo", "accum");
183
184
185
186
187
188
189 asm volatile(
190 ""
191 : "=r" (m1), "=r" (m2), "=r" (s)
192 : "0" (m1), "1" (m2), "2" (s));
193 align_mod(align, mod);
194 p = m1 * m2;
195 lv2 = s << 32;
196 asm volatile(
197 ""
198 : "=r" (lv2)
199 : "0" (lv2), "r" (p));
200 local_irq_restore(flags);
201
202 *v1 = lv1;
203 *v2 = lv2;
204 *w = lw;
205}
206
207static inline void check_mult_sh(void)
208{
209 long v1[8], v2[8], w[8];
210 int bug, fix, i;
211
212 printk("Checking for the multiply/shift bug... ");
213
214
215
216
217
218
219
220
221
222
223 mult_sh_align_mod(&v1[0], &v2[0], &w[0], 32, 0);
224 mult_sh_align_mod(&v1[1], &v2[1], &w[1], 32, 1);
225 mult_sh_align_mod(&v1[2], &v2[2], &w[2], 32, 2);
226 mult_sh_align_mod(&v1[3], &v2[3], &w[3], 32, 3);
227 mult_sh_align_mod(&v1[4], &v2[4], &w[4], 32, 4);
228 mult_sh_align_mod(&v1[5], &v2[5], &w[5], 32, 5);
229 mult_sh_align_mod(&v1[6], &v2[6], &w[6], 32, 6);
230 mult_sh_align_mod(&v1[7], &v2[7], &w[7], 32, 7);
231
232 bug = 0;
233 for (i = 0; i < 8; i++)
234 if (v1[i] != w[i])
235 bug = 1;
236
237 if (bug == 0) {
238 printk("no.\n");
239 return;
240 }
241
242 printk("yes, workaround... ");
243
244 fix = 1;
245 for (i = 0; i < 8; i++)
246 if (v2[i] != w[i])
247 fix = 0;
248
249 if (fix == 1) {
250 printk("yes.\n");
251 return;
252 }
253
254 printk("no.\n");
255 panic("Reliable operation impossible!\n"
256#ifndef CONFIG_CPU_R4000
257 "Configure for R4000 to enable the workaround."
258#else
259 "Please report to <linux-mips@linux-mips.org>."
260#endif
261 );
262}
263
264static volatile int daddi_ov __initdata = 0;
265
266asmlinkage void __init do_daddi_ov(struct pt_regs *regs)
267{
268 daddi_ov = 1;
269 regs->cp0_epc += 4;
270}
271
272static inline void check_daddi(void)
273{
274 extern asmlinkage void handle_daddi_ov(void);
275 unsigned long flags;
276 void *handler;
277 long v;
278
279 printk("Checking for the daddi bug... ");
280
281 local_irq_save(flags);
282 handler = set_except_vector(12, handle_daddi_ov);
283
284
285
286
287
288
289
290
291
292 asm volatile(
293 ".set push\n\t"
294 ".set noat\n\t"
295 ".set noreorder\n\t"
296 ".set nomacro\n\t"
297#ifdef HAVE_AS_SET_DADDI
298 ".set daddi\n\t"
299#endif
300 "daddi %0, %1, %2\n\t"
301 ".set pop"
302 : "=r" (v)
303 : "r" (0x7fffffffffffedcd), "I" (0x1234));
304 set_except_vector(12, handler);
305 local_irq_restore(flags);
306
307 if (daddi_ov) {
308 printk("no.\n");
309 return;
310 }
311
312 printk("yes, workaround... ");
313
314 local_irq_save(flags);
315 handler = set_except_vector(12, handle_daddi_ov);
316 asm volatile(
317 "daddi %0, %1, %2"
318 : "=r" (v)
319 : "r" (0x7fffffffffffedcd), "I" (0x1234));
320 set_except_vector(12, handler);
321 local_irq_restore(flags);
322
323 if (daddi_ov) {
324 printk("yes.\n");
325 return;
326 }
327
328 printk("no.\n");
329 panic("Reliable operation impossible!\n"
330#if !defined(CONFIG_CPU_R4000) && !defined(CONFIG_CPU_R4400)
331 "Configure for R4000 or R4400 to enable the workaround."
332#else
333 "Please report to <linux-mips@linux-mips.org>."
334#endif
335 );
336}
337
338static inline void check_daddiu(void)
339{
340 long v, w;
341
342 printk("Checking for the daddiu bug... ");
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360 asm volatile(
361 ".set push\n\t"
362 ".set noat\n\t"
363 ".set noreorder\n\t"
364 ".set nomacro\n\t"
365#ifdef HAVE_AS_SET_DADDI
366 ".set daddi\n\t"
367#endif
368 "daddiu %0, %2, %3\n\t"
369 "addiu %1, $0, %3\n\t"
370 "daddu %1, %2\n\t"
371 ".set pop"
372 : "=&r" (v), "=&r" (w)
373 : "r" (0x7fffffffffffedcd), "I" (0x1234));
374
375 if (v == w) {
376 printk("no.\n");
377 return;
378 }
379
380 printk("yes, workaround... ");
381
382 asm volatile(
383 "daddiu %0, %2, %3\n\t"
384 "addiu %1, $0, %3\n\t"
385 "daddu %1, %2"
386 : "=&r" (v), "=&r" (w)
387 : "r" (0x7fffffffffffedcd), "I" (0x1234));
388
389 if (v == w) {
390 printk("yes.\n");
391 return;
392 }
393
394 printk("no.\n");
395 panic("Reliable operation impossible!\n"
396#if !defined(CONFIG_CPU_R4000) && !defined(CONFIG_CPU_R4400)
397 "Configure for R4000 or R4400 to enable the workaround."
398#else
399 "Please report to <linux-mips@linux-mips.org>."
400#endif
401 );
402}
403
404void __init check_bugs(void)
405{
406 check_wait();
407 check_mult_sh();
408 check_daddi();
409 check_daddiu();
410}
411
412
413
414
415
416
417static inline int cpu_has_confreg(void)
418{
419#ifdef CONFIG_CPU_R3000
420 extern unsigned long r3k_cache_size(unsigned long);
421 unsigned long size1, size2;
422 unsigned long cfg = read_c0_conf();
423
424 size1 = r3k_cache_size(ST0_ISC);
425 write_c0_conf(cfg ^ R30XX_CONF_AC);
426 size2 = r3k_cache_size(ST0_ISC);
427 write_c0_conf(cfg);
428 return size1 != size2;
429#else
430 return 0;
431#endif
432}
433
434
435
436
437static inline unsigned long cpu_get_fpu_id(void)
438{
439 unsigned long tmp, fpu_id;
440
441 tmp = read_c0_status();
442 __enable_fpu();
443 fpu_id = read_32bit_cp1_register(CP1_REVISION);
444 write_c0_status(tmp);
445 return fpu_id;
446}
447
448
449
450
451static inline int __cpu_has_fpu(void)
452{
453 return ((cpu_get_fpu_id() & 0xff00) != FPIR_IMP_NONE);
454}
455
456#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4KTLB \
457 | MIPS_CPU_COUNTER)
458
459static inline void cpu_probe_legacy(struct cpuinfo_mips *c)
460{
461 switch (c->processor_id & 0xff00) {
462 case PRID_IMP_R2000:
463 c->cputype = CPU_R2000;
464 c->isa_level = MIPS_CPU_ISA_I;
465 c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX |
466 MIPS_CPU_LLSC;
467 if (__cpu_has_fpu())
468 c->options |= MIPS_CPU_FPU;
469 c->tlbsize = 64;
470 break;
471 case PRID_IMP_R3000:
472 if ((c->processor_id & 0xff) == PRID_REV_R3000A)
473 if (cpu_has_confreg())
474 c->cputype = CPU_R3081E;
475 else
476 c->cputype = CPU_R3000A;
477 else
478 c->cputype = CPU_R3000;
479 c->isa_level = MIPS_CPU_ISA_I;
480 c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX |
481 MIPS_CPU_LLSC;
482 if (__cpu_has_fpu())
483 c->options |= MIPS_CPU_FPU;
484 c->tlbsize = 64;
485 break;
486 case PRID_IMP_R4000:
487 if ((c->processor_id & 0xff) >= PRID_REV_R4400)
488 c->cputype = CPU_R4400SC;
489 else
490 c->cputype = CPU_R4000SC;
491 c->isa_level = MIPS_CPU_ISA_III;
492 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
493 MIPS_CPU_WATCH | MIPS_CPU_VCE |
494 MIPS_CPU_LLSC;
495 c->tlbsize = 48;
496 break;
497 case PRID_IMP_VR41XX:
498 switch (c->processor_id & 0xf0) {
499#ifndef CONFIG_VR4181
500 case PRID_REV_VR4111:
501 c->cputype = CPU_VR4111;
502 break;
503#else
504 case PRID_REV_VR4181:
505 c->cputype = CPU_VR4181;
506 break;
507#endif
508 case PRID_REV_VR4121:
509 c->cputype = CPU_VR4121;
510 break;
511 case PRID_REV_VR4122:
512 if ((c->processor_id & 0xf) < 0x3)
513 c->cputype = CPU_VR4122;
514 else
515 c->cputype = CPU_VR4181A;
516 break;
517 case PRID_REV_VR4130:
518 if ((c->processor_id & 0xf) < 0x4)
519 c->cputype = CPU_VR4131;
520 else
521 c->cputype = CPU_VR4133;
522 break;
523 default:
524 printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
525 c->cputype = CPU_VR41XX;
526 break;
527 }
528 c->isa_level = MIPS_CPU_ISA_III;
529 c->options = R4K_OPTS;
530 c->tlbsize = 32;
531 break;
532 case PRID_IMP_R4300:
533 c->cputype = CPU_R4300;
534 c->isa_level = MIPS_CPU_ISA_III;
535 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
536 MIPS_CPU_LLSC;
537 c->tlbsize = 32;
538 break;
539 case PRID_IMP_R4600:
540 c->cputype = CPU_R4600;
541 c->isa_level = MIPS_CPU_ISA_III;
542 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC;
543 c->tlbsize = 48;
544 break;
545 #if 0
546 case PRID_IMP_R4650:
547
548
549
550
551
552
553 c->cputype = CPU_R4650;
554 c->isa_level = MIPS_CPU_ISA_III;
555 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC;
556 c->tlbsize = 48;
557 break;
558 #endif
559 case PRID_IMP_TX39:
560 c->isa_level = MIPS_CPU_ISA_I;
561 c->options = MIPS_CPU_TLB;
562
563 if ((c->processor_id & 0xf0) == (PRID_REV_TX3927 & 0xf0)) {
564 c->cputype = CPU_TX3927;
565 c->tlbsize = 64;
566 } else {
567 switch (c->processor_id & 0xff) {
568 case PRID_REV_TX3912:
569 c->cputype = CPU_TX3912;
570 c->tlbsize = 32;
571 break;
572 case PRID_REV_TX3922:
573 c->cputype = CPU_TX3922;
574 c->tlbsize = 64;
575 break;
576 default:
577 c->cputype = CPU_UNKNOWN;
578 break;
579 }
580 }
581 break;
582 case PRID_IMP_R4700:
583 c->cputype = CPU_R4700;
584 c->isa_level = MIPS_CPU_ISA_III;
585 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
586 MIPS_CPU_LLSC;
587 c->tlbsize = 48;
588 break;
589 case PRID_IMP_TX49:
590 c->cputype = CPU_TX49XX;
591 c->isa_level = MIPS_CPU_ISA_III;
592 c->options = R4K_OPTS | MIPS_CPU_LLSC;
593 if (!(c->processor_id & 0x08))
594 c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR;
595 c->tlbsize = 48;
596 break;
597 case PRID_IMP_R5000:
598 c->cputype = CPU_R5000;
599 c->isa_level = MIPS_CPU_ISA_IV;
600 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
601 MIPS_CPU_LLSC;
602 c->tlbsize = 48;
603 break;
604 case PRID_IMP_R5432:
605 c->cputype = CPU_R5432;
606 c->isa_level = MIPS_CPU_ISA_IV;
607 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
608 MIPS_CPU_WATCH | MIPS_CPU_LLSC;
609 c->tlbsize = 48;
610 break;
611 case PRID_IMP_R5500:
612 c->cputype = CPU_R5500;
613 c->isa_level = MIPS_CPU_ISA_IV;
614 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
615 MIPS_CPU_WATCH | MIPS_CPU_LLSC;
616 c->tlbsize = 48;
617 break;
618 case PRID_IMP_NEVADA:
619 c->cputype = CPU_NEVADA;
620 c->isa_level = MIPS_CPU_ISA_IV;
621 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
622 MIPS_CPU_DIVEC | MIPS_CPU_LLSC;
623 c->tlbsize = 48;
624 break;
625 case PRID_IMP_R6000:
626 c->cputype = CPU_R6000;
627 c->isa_level = MIPS_CPU_ISA_II;
628 c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
629 MIPS_CPU_LLSC;
630 c->tlbsize = 32;
631 break;
632 case PRID_IMP_R6000A:
633 c->cputype = CPU_R6000A;
634 c->isa_level = MIPS_CPU_ISA_II;
635 c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
636 MIPS_CPU_LLSC;
637 c->tlbsize = 32;
638 break;
639 case PRID_IMP_RM7000:
640 c->cputype = CPU_RM7000;
641 c->isa_level = MIPS_CPU_ISA_IV;
642 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
643 MIPS_CPU_LLSC;
644
645
646
647
648
649
650
651
652 c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48;
653 break;
654 case PRID_IMP_RM9000:
655 c->cputype = CPU_RM9000;
656 c->isa_level = MIPS_CPU_ISA_IV;
657 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
658 MIPS_CPU_LLSC;
659
660
661
662
663
664
665
666 c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48;
667 break;
668 case PRID_IMP_R8000:
669 c->cputype = CPU_R8000;
670 c->isa_level = MIPS_CPU_ISA_IV;
671 c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
672 MIPS_CPU_FPU | MIPS_CPU_32FPR |
673 MIPS_CPU_LLSC;
674 c->tlbsize = 384;
675 break;
676 case PRID_IMP_R10000:
677 c->cputype = CPU_R10000;
678 c->isa_level = MIPS_CPU_ISA_IV;
679 c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
680 MIPS_CPU_FPU | MIPS_CPU_32FPR |
681 MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
682 MIPS_CPU_LLSC;
683 c->tlbsize = 64;
684 break;
685 case PRID_IMP_R12000:
686 c->cputype = CPU_R12000;
687 c->isa_level = MIPS_CPU_ISA_IV;
688 c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
689 MIPS_CPU_FPU | MIPS_CPU_32FPR |
690 MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
691 MIPS_CPU_LLSC;
692 c->tlbsize = 64;
693 break;
694 default:
695 c->cputype = CPU_UNKNOWN;
696 break;
697 }
698}
699
700static inline void decode_config1(struct cpuinfo_mips *c)
701{
702 unsigned long config0 = read_c0_config();
703 unsigned long config1;
704
705 if ((config0 & (1 << 31)) == 0)
706 return;
707
708
709 c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
710 MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | MIPS_CPU_DIVEC |
711 MIPS_CPU_LLSC;
712 config1 = read_c0_config1();
713 if (config1 & (1 << 3))
714 c->options |= MIPS_CPU_WATCH;
715 if (config1 & (1 << 2))
716 c->options |= MIPS_CPU_MIPS16;
717 if (config1 & (1 << 1))
718 c->options |= MIPS_CPU_EJTAG;
719 if (config1 & 1) {
720 c->options |= MIPS_CPU_FPU;
721 c->options |= MIPS_CPU_32FPR;
722 }
723 c->scache.flags = MIPS_CACHE_NOT_PRESENT;
724
725 c->tlbsize = ((config1 >> 25) & 0x3f) + 1;
726}
727
728static inline void cpu_probe_mips(struct cpuinfo_mips *c)
729{
730 decode_config1(c);
731 switch (c->processor_id & 0xff00) {
732 case PRID_IMP_4KC:
733 c->cputype = CPU_4KC;
734 c->isa_level = MIPS_CPU_ISA_M32;
735 break;
736 case PRID_IMP_4KEC:
737 c->cputype = CPU_4KEC;
738 c->isa_level = MIPS_CPU_ISA_M32;
739 break;
740 case PRID_IMP_4KSC:
741 c->cputype = CPU_4KSC;
742 c->isa_level = MIPS_CPU_ISA_M32;
743 break;
744 case PRID_IMP_5KC:
745 c->cputype = CPU_5KC;
746 c->isa_level = MIPS_CPU_ISA_M64;
747 break;
748 case PRID_IMP_20KC:
749 c->cputype = CPU_20KC;
750 c->isa_level = MIPS_CPU_ISA_M64;
751 break;
752 case PRID_IMP_24K:
753 c->cputype = CPU_24K;
754 c->isa_level = MIPS_CPU_ISA_M32;
755 break;
756 case PRID_IMP_25KF:
757 c->cputype = CPU_25KF;
758 c->isa_level = MIPS_CPU_ISA_M64;
759
760 c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
761 break;
762 default:
763 c->cputype = CPU_UNKNOWN;
764 break;
765 }
766}
767
768static inline void cpu_probe_alchemy(struct cpuinfo_mips *c)
769{
770 decode_config1(c);
771 switch (c->processor_id & 0xff00) {
772 case PRID_IMP_AU1_REV1:
773 case PRID_IMP_AU1_REV2:
774 switch ((c->processor_id >> 24) & 0xff) {
775 case 0:
776 c->cputype = CPU_AU1000;
777 break;
778 case 1:
779 c->cputype = CPU_AU1500;
780 break;
781 case 2:
782 c->cputype = CPU_AU1100;
783 break;
784 default:
785 panic("Unknown Au Core!");
786 break;
787 }
788 c->isa_level = MIPS_CPU_ISA_M32;
789 break;
790 }
791}
792
793static inline void cpu_probe_sibyte(struct cpuinfo_mips *c)
794{
795 decode_config1(c);
796 switch (c->processor_id & 0xff00) {
797 case PRID_IMP_SB1:
798 c->cputype = CPU_SB1;
799 c->isa_level = MIPS_CPU_ISA_M64;
800 c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
801 MIPS_CPU_COUNTER | MIPS_CPU_DIVEC |
802 MIPS_CPU_MCHECK | MIPS_CPU_EJTAG |
803 MIPS_CPU_WATCH | MIPS_CPU_LLSC;
804#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS
805
806 c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR;
807#endif
808 break;
809 default:
810 c->cputype = CPU_UNKNOWN;
811 break;
812 }
813}
814
815static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c)
816{
817 decode_config1(c);
818 switch (c->processor_id & 0xff00) {
819 case PRID_IMP_SR71000:
820 c->cputype = CPU_SR71000;
821 c->isa_level = MIPS_CPU_ISA_M64;
822 c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
823 MIPS_CPU_4KTLB | MIPS_CPU_FPU |
824 MIPS_CPU_COUNTER | MIPS_CPU_MCHECK;
825 c->scache.ways = 8;
826 c->tlbsize = 64;
827 break;
828 default:
829 c->cputype = CPU_UNKNOWN;
830 break;
831 }
832}
833
834__init void cpu_probe(void)
835{
836 struct cpuinfo_mips *c = ¤t_cpu_data;
837
838 c->processor_id = PRID_IMP_UNKNOWN;
839 c->fpu_id = FPIR_IMP_NONE;
840 c->cputype = CPU_UNKNOWN;
841
842 c->processor_id = read_c0_prid();
843 switch (c->processor_id & 0xff0000) {
844 case PRID_COMP_LEGACY:
845 cpu_probe_legacy(c);
846 break;
847 case PRID_COMP_MIPS:
848 cpu_probe_mips(c);
849 break;
850 case PRID_COMP_ALCHEMY:
851 cpu_probe_alchemy(c);
852 break;
853 case PRID_COMP_SIBYTE:
854 cpu_probe_sibyte(c);
855 break;
856
857 case PRID_COMP_SANDCRAFT:
858 cpu_probe_sandcraft(c);
859 break;
860 default:
861 c->cputype = CPU_UNKNOWN;
862 }
863 if (c->options & MIPS_CPU_FPU)
864 c->fpu_id = cpu_get_fpu_id();
865}
866
867__init void cpu_report(void)
868{
869 struct cpuinfo_mips *c = ¤t_cpu_data;
870
871 printk("CPU revision is: %08x\n", c->processor_id);
872 if (c->options & MIPS_CPU_FPU)
873 printk("FPU revision is: %08x\n", c->fpu_id);
874}
875