aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/cpu-probe.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/cpu-probe.c')
-rw-r--r--arch/mips/kernel/cpu-probe.c200
1 files changed, 152 insertions, 48 deletions
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 48dfb9de853d..e36515dcd3b2 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -20,6 +20,7 @@
20 20
21#include <asm/bugs.h> 21#include <asm/bugs.h>
22#include <asm/cpu.h> 22#include <asm/cpu.h>
23#include <asm/cpu-features.h>
23#include <asm/cpu-type.h> 24#include <asm/cpu-type.h>
24#include <asm/fpu.h> 25#include <asm/fpu.h>
25#include <asm/mipsregs.h> 26#include <asm/mipsregs.h>
@@ -31,11 +32,127 @@
31#include <asm/spram.h> 32#include <asm/spram.h>
32#include <asm/uaccess.h> 33#include <asm/uaccess.h>
33 34
35/*
36 * Get the FPU Implementation/Revision.
37 */
38static inline unsigned long cpu_get_fpu_id(void)
39{
40 unsigned long tmp, fpu_id;
41
42 tmp = read_c0_status();
43 __enable_fpu(FPU_AS_IS);
44 fpu_id = read_32bit_cp1_register(CP1_REVISION);
45 write_c0_status(tmp);
46 return fpu_id;
47}
48
49/*
50 * Check if the CPU has an external FPU.
51 */
52static inline int __cpu_has_fpu(void)
53{
54 return (cpu_get_fpu_id() & FPIR_IMP_MASK) != FPIR_IMP_NONE;
55}
56
57static inline unsigned long cpu_get_msa_id(void)
58{
59 unsigned long status, msa_id;
60
61 status = read_c0_status();
62 __enable_fpu(FPU_64BIT);
63 enable_msa();
64 msa_id = read_msa_ir();
65 disable_msa();
66 write_c0_status(status);
67 return msa_id;
68}
69
70/*
71 * Determine the FCSR mask for FPU hardware.
72 */
73static inline void cpu_set_fpu_fcsr_mask(struct cpuinfo_mips *c)
74{
75 unsigned long sr, mask, fcsr, fcsr0, fcsr1;
76
77 mask = FPU_CSR_ALL_X | FPU_CSR_ALL_E | FPU_CSR_ALL_S | FPU_CSR_RM;
78
79 sr = read_c0_status();
80 __enable_fpu(FPU_AS_IS);
81
82 fcsr = read_32bit_cp1_register(CP1_STATUS);
83
84 fcsr0 = fcsr & mask;
85 write_32bit_cp1_register(CP1_STATUS, fcsr0);
86 fcsr0 = read_32bit_cp1_register(CP1_STATUS);
87
88 fcsr1 = fcsr | ~mask;
89 write_32bit_cp1_register(CP1_STATUS, fcsr1);
90 fcsr1 = read_32bit_cp1_register(CP1_STATUS);
91
92 write_32bit_cp1_register(CP1_STATUS, fcsr);
93
94 write_c0_status(sr);
95
96 c->fpu_msk31 = ~(fcsr0 ^ fcsr1) & ~mask;
97}
98
99/*
100 * Set the FIR feature flags for the FPU emulator.
101 */
102static void cpu_set_nofpu_id(struct cpuinfo_mips *c)
103{
104 u32 value;
105
106 value = 0;
107 if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
108 MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
109 MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6))
110 value |= MIPS_FPIR_D | MIPS_FPIR_S;
111 if (c->isa_level & (MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
112 MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6))
113 value |= MIPS_FPIR_F64 | MIPS_FPIR_L | MIPS_FPIR_W;
114 c->fpu_id = value;
115}
116
117/* Determined FPU emulator mask to use for the boot CPU with "nofpu". */
118static unsigned int mips_nofpu_msk31;
119
120/*
121 * Set options for FPU hardware.
122 */
123static void cpu_set_fpu_opts(struct cpuinfo_mips *c)
124{
125 c->fpu_id = cpu_get_fpu_id();
126 mips_nofpu_msk31 = c->fpu_msk31;
127
128 if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
129 MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
130 MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) {
131 if (c->fpu_id & MIPS_FPIR_3D)
132 c->ases |= MIPS_ASE_MIPS3D;
133 if (c->fpu_id & MIPS_FPIR_FREP)
134 c->options |= MIPS_CPU_FRE;
135 }
136
137 cpu_set_fpu_fcsr_mask(c);
138}
139
140/*
141 * Set options for the FPU emulator.
142 */
143static void cpu_set_nofpu_opts(struct cpuinfo_mips *c)
144{
145 c->options &= ~MIPS_CPU_FPU;
146 c->fpu_msk31 = mips_nofpu_msk31;
147
148 cpu_set_nofpu_id(c);
149}
150
34static int mips_fpu_disabled; 151static int mips_fpu_disabled;
35 152
36static int __init fpu_disable(char *s) 153static int __init fpu_disable(char *s)
37{ 154{
38 cpu_data[0].options &= ~MIPS_CPU_FPU; 155 cpu_set_nofpu_opts(&boot_cpu_data);
39 mips_fpu_disabled = 1; 156 mips_fpu_disabled = 1;
40 157
41 return 1; 158 return 1;
@@ -178,41 +295,6 @@ static inline void set_elf_platform(int cpu, const char *plat)
178 __elf_platform = plat; 295 __elf_platform = plat;
179} 296}
180 297
181/*
182 * Get the FPU Implementation/Revision.
183 */
184static inline unsigned long cpu_get_fpu_id(void)
185{
186 unsigned long tmp, fpu_id;
187
188 tmp = read_c0_status();
189 __enable_fpu(FPU_AS_IS);
190 fpu_id = read_32bit_cp1_register(CP1_REVISION);
191 write_c0_status(tmp);
192 return fpu_id;
193}
194
195/*
196 * Check the CPU has an FPU the official way.
197 */
198static inline int __cpu_has_fpu(void)
199{
200 return (cpu_get_fpu_id() & FPIR_IMP_MASK) != FPIR_IMP_NONE;
201}
202
203static inline unsigned long cpu_get_msa_id(void)
204{
205 unsigned long status, msa_id;
206
207 status = read_c0_status();
208 __enable_fpu(FPU_64BIT);
209 enable_msa();
210 msa_id = read_msa_ir();
211 disable_msa();
212 write_c0_status(status);
213 return msa_id;
214}
215
216static inline void cpu_probe_vmbits(struct cpuinfo_mips *c) 298static inline void cpu_probe_vmbits(struct cpuinfo_mips *c)
217{ 299{
218#ifdef __NEED_VMBITS_PROBE 300#ifdef __NEED_VMBITS_PROBE
@@ -441,6 +523,8 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
441 c->htw_seq = 0; 523 c->htw_seq = 0;
442 c->options |= MIPS_CPU_HTW; 524 c->options |= MIPS_CPU_HTW;
443 } 525 }
526 if (config3 & MIPS_CONF3_CDMM)
527 c->options |= MIPS_CPU_CDMM;
444 528
445 return config3 & MIPS_CONF_M; 529 return config3 & MIPS_CONF_M;
446} 530}
@@ -516,6 +600,10 @@ static inline unsigned int decode_config5(struct cpuinfo_mips *c)
516 c->options |= MIPS_CPU_MAAR; 600 c->options |= MIPS_CPU_MAAR;
517 if (config5 & MIPS_CONF5_LLB) 601 if (config5 & MIPS_CONF5_LLB)
518 c->options |= MIPS_CPU_RW_LLB; 602 c->options |= MIPS_CPU_RW_LLB;
603#ifdef CONFIG_XPA
604 if (config5 & MIPS_CONF5_MVH)
605 c->options |= MIPS_CPU_XPA;
606#endif
519 607
520 return config5 & MIPS_CONF_M; 608 return config5 & MIPS_CONF_M;
521} 609}
@@ -575,6 +663,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
575 case PRID_IMP_R2000: 663 case PRID_IMP_R2000:
576 c->cputype = CPU_R2000; 664 c->cputype = CPU_R2000;
577 __cpu_name[cpu] = "R2000"; 665 __cpu_name[cpu] = "R2000";
666 c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
578 c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE | 667 c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
579 MIPS_CPU_NOFPUEX; 668 MIPS_CPU_NOFPUEX;
580 if (__cpu_has_fpu()) 669 if (__cpu_has_fpu())
@@ -594,6 +683,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
594 c->cputype = CPU_R3000; 683 c->cputype = CPU_R3000;
595 __cpu_name[cpu] = "R3000"; 684 __cpu_name[cpu] = "R3000";
596 } 685 }
686 c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
597 c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE | 687 c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
598 MIPS_CPU_NOFPUEX; 688 MIPS_CPU_NOFPUEX;
599 if (__cpu_has_fpu()) 689 if (__cpu_has_fpu())
@@ -642,6 +732,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
642 } 732 }
643 733
644 set_isa(c, MIPS_CPU_ISA_III); 734 set_isa(c, MIPS_CPU_ISA_III);
735 c->fpu_msk31 |= FPU_CSR_CONDX;
645 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | 736 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
646 MIPS_CPU_WATCH | MIPS_CPU_VCE | 737 MIPS_CPU_WATCH | MIPS_CPU_VCE |
647 MIPS_CPU_LLSC; 738 MIPS_CPU_LLSC;
@@ -649,6 +740,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
649 break; 740 break;
650 case PRID_IMP_VR41XX: 741 case PRID_IMP_VR41XX:
651 set_isa(c, MIPS_CPU_ISA_III); 742 set_isa(c, MIPS_CPU_ISA_III);
743 c->fpu_msk31 |= FPU_CSR_CONDX;
652 c->options = R4K_OPTS; 744 c->options = R4K_OPTS;
653 c->tlbsize = 32; 745 c->tlbsize = 32;
654 switch (c->processor_id & 0xf0) { 746 switch (c->processor_id & 0xf0) {
@@ -690,6 +782,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
690 c->cputype = CPU_R4300; 782 c->cputype = CPU_R4300;
691 __cpu_name[cpu] = "R4300"; 783 __cpu_name[cpu] = "R4300";
692 set_isa(c, MIPS_CPU_ISA_III); 784 set_isa(c, MIPS_CPU_ISA_III);
785 c->fpu_msk31 |= FPU_CSR_CONDX;
693 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | 786 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
694 MIPS_CPU_LLSC; 787 MIPS_CPU_LLSC;
695 c->tlbsize = 32; 788 c->tlbsize = 32;
@@ -698,6 +791,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
698 c->cputype = CPU_R4600; 791 c->cputype = CPU_R4600;
699 __cpu_name[cpu] = "R4600"; 792 __cpu_name[cpu] = "R4600";
700 set_isa(c, MIPS_CPU_ISA_III); 793 set_isa(c, MIPS_CPU_ISA_III);
794 c->fpu_msk31 |= FPU_CSR_CONDX;
701 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | 795 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
702 MIPS_CPU_LLSC; 796 MIPS_CPU_LLSC;
703 c->tlbsize = 48; 797 c->tlbsize = 48;
@@ -713,11 +807,13 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
713 c->cputype = CPU_R4650; 807 c->cputype = CPU_R4650;
714 __cpu_name[cpu] = "R4650"; 808 __cpu_name[cpu] = "R4650";
715 set_isa(c, MIPS_CPU_ISA_III); 809 set_isa(c, MIPS_CPU_ISA_III);
810 c->fpu_msk31 |= FPU_CSR_CONDX;
716 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC; 811 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC;
717 c->tlbsize = 48; 812 c->tlbsize = 48;
718 break; 813 break;
719 #endif 814 #endif
720 case PRID_IMP_TX39: 815 case PRID_IMP_TX39:
816 c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
721 c->options = MIPS_CPU_TLB | MIPS_CPU_TX39_CACHE; 817 c->options = MIPS_CPU_TLB | MIPS_CPU_TX39_CACHE;
722 818
723 if ((c->processor_id & 0xf0) == (PRID_REV_TX3927 & 0xf0)) { 819 if ((c->processor_id & 0xf0) == (PRID_REV_TX3927 & 0xf0)) {
@@ -743,6 +839,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
743 c->cputype = CPU_R4700; 839 c->cputype = CPU_R4700;
744 __cpu_name[cpu] = "R4700"; 840 __cpu_name[cpu] = "R4700";
745 set_isa(c, MIPS_CPU_ISA_III); 841 set_isa(c, MIPS_CPU_ISA_III);
842 c->fpu_msk31 |= FPU_CSR_CONDX;
746 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | 843 c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
747 MIPS_CPU_LLSC; 844 MIPS_CPU_LLSC;
748 c->tlbsize = 48; 845 c->tlbsize = 48;
@@ -751,6 +848,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
751 c->cputype = CPU_TX49XX; 848 c->cputype = CPU_TX49XX;
752 __cpu_name[cpu] = "R49XX"; 849 __cpu_name[cpu] = "R49XX";
753 set_isa(c, MIPS_CPU_ISA_III); 850 set_isa(c, MIPS_CPU_ISA_III);
851 c->fpu_msk31 |= FPU_CSR_CONDX;
754 c->options = R4K_OPTS | MIPS_CPU_LLSC; 852 c->options = R4K_OPTS | MIPS_CPU_LLSC;
755 if (!(c->processor_id & 0x08)) 853 if (!(c->processor_id & 0x08))
756 c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR; 854 c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR;
@@ -792,6 +890,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
792 c->cputype = CPU_R6000; 890 c->cputype = CPU_R6000;
793 __cpu_name[cpu] = "R6000"; 891 __cpu_name[cpu] = "R6000";
794 set_isa(c, MIPS_CPU_ISA_II); 892 set_isa(c, MIPS_CPU_ISA_II);
893 c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
795 c->options = MIPS_CPU_TLB | MIPS_CPU_FPU | 894 c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
796 MIPS_CPU_LLSC; 895 MIPS_CPU_LLSC;
797 c->tlbsize = 32; 896 c->tlbsize = 32;
@@ -800,6 +899,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
800 c->cputype = CPU_R6000A; 899 c->cputype = CPU_R6000A;
801 __cpu_name[cpu] = "R6000A"; 900 __cpu_name[cpu] = "R6000A";
802 set_isa(c, MIPS_CPU_ISA_II); 901 set_isa(c, MIPS_CPU_ISA_II);
902 c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
803 c->options = MIPS_CPU_TLB | MIPS_CPU_FPU | 903 c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
804 MIPS_CPU_LLSC; 904 MIPS_CPU_LLSC;
805 c->tlbsize = 32; 905 c->tlbsize = 32;
@@ -850,8 +950,13 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
850 c->tlbsize = 64; 950 c->tlbsize = 64;
851 break; 951 break;
852 case PRID_IMP_R14000: 952 case PRID_IMP_R14000:
853 c->cputype = CPU_R14000; 953 if (((c->processor_id >> 4) & 0x0f) > 2) {
854 __cpu_name[cpu] = "R14000"; 954 c->cputype = CPU_R16000;
955 __cpu_name[cpu] = "R16000";
956 } else {
957 c->cputype = CPU_R14000;
958 __cpu_name[cpu] = "R14000";
959 }
855 set_isa(c, MIPS_CPU_ISA_IV); 960 set_isa(c, MIPS_CPU_ISA_IV);
856 c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX | 961 c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
857 MIPS_CPU_FPU | MIPS_CPU_32FPR | 962 MIPS_CPU_FPU | MIPS_CPU_32FPR |
@@ -866,12 +971,14 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
866 __cpu_name[cpu] = "ICT Loongson-2"; 971 __cpu_name[cpu] = "ICT Loongson-2";
867 set_elf_platform(cpu, "loongson2e"); 972 set_elf_platform(cpu, "loongson2e");
868 set_isa(c, MIPS_CPU_ISA_III); 973 set_isa(c, MIPS_CPU_ISA_III);
974 c->fpu_msk31 |= FPU_CSR_CONDX;
869 break; 975 break;
870 case PRID_REV_LOONGSON2F: 976 case PRID_REV_LOONGSON2F:
871 c->cputype = CPU_LOONGSON2; 977 c->cputype = CPU_LOONGSON2;
872 __cpu_name[cpu] = "ICT Loongson-2"; 978 __cpu_name[cpu] = "ICT Loongson-2";
873 set_elf_platform(cpu, "loongson2f"); 979 set_elf_platform(cpu, "loongson2f");
874 set_isa(c, MIPS_CPU_ISA_III); 980 set_isa(c, MIPS_CPU_ISA_III);
981 c->fpu_msk31 |= FPU_CSR_CONDX;
875 break; 982 break;
876 case PRID_REV_LOONGSON3A: 983 case PRID_REV_LOONGSON3A:
877 c->cputype = CPU_LOONGSON3; 984 c->cputype = CPU_LOONGSON3;
@@ -1308,6 +1415,9 @@ void cpu_probe(void)
1308 c->cputype = CPU_UNKNOWN; 1415 c->cputype = CPU_UNKNOWN;
1309 c->writecombine = _CACHE_UNCACHED; 1416 c->writecombine = _CACHE_UNCACHED;
1310 1417
1418 c->fpu_csr31 = FPU_CSR_RN;
1419 c->fpu_msk31 = FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
1420
1311 c->processor_id = read_c0_prid(); 1421 c->processor_id = read_c0_prid();
1312 switch (c->processor_id & PRID_COMP_MASK) { 1422 switch (c->processor_id & PRID_COMP_MASK) {
1313 case PRID_COMP_LEGACY: 1423 case PRID_COMP_LEGACY:
@@ -1364,16 +1474,10 @@ void cpu_probe(void)
1364 ~(1 << MIPS_PWCTL_PWEN_SHIFT)); 1474 ~(1 << MIPS_PWCTL_PWEN_SHIFT));
1365 } 1475 }
1366 1476
1367 if (c->options & MIPS_CPU_FPU) { 1477 if (c->options & MIPS_CPU_FPU)
1368 c->fpu_id = cpu_get_fpu_id(); 1478 cpu_set_fpu_opts(c);
1369 1479 else
1370 if (c->isa_level & cpu_has_mips_r) { 1480 cpu_set_nofpu_opts(c);
1371 if (c->fpu_id & MIPS_FPIR_3D)
1372 c->ases |= MIPS_ASE_MIPS3D;
1373 if (c->fpu_id & MIPS_FPIR_FREP)
1374 c->options |= MIPS_CPU_FRE;
1375 }
1376 }
1377 1481
1378 if (cpu_has_mips_r2_r6) { 1482 if (cpu_has_mips_r2_r6) {
1379 c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1; 1483 c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1;