3232#include <asm/spram.h>
3333#include <asm/uaccess.h>
3434
35+ /*
36+ * Determine the FCSR mask for FPU hardware.
37+ */
38+ static inline void cpu_set_fpu_fcsr_mask (struct cpuinfo_mips * c )
39+ {
40+ unsigned long sr , mask , fcsr , fcsr0 , fcsr1 ;
41+
42+ mask = FPU_CSR_ALL_X | FPU_CSR_ALL_E | FPU_CSR_ALL_S | FPU_CSR_RM ;
43+
44+ sr = read_c0_status ();
45+ __enable_fpu (FPU_AS_IS );
46+
47+ fcsr = read_32bit_cp1_register (CP1_STATUS );
48+
49+ fcsr0 = fcsr & mask ;
50+ write_32bit_cp1_register (CP1_STATUS , fcsr0 );
51+ fcsr0 = read_32bit_cp1_register (CP1_STATUS );
52+
53+ fcsr1 = fcsr | ~mask ;
54+ write_32bit_cp1_register (CP1_STATUS , fcsr1 );
55+ fcsr1 = read_32bit_cp1_register (CP1_STATUS );
56+
57+ write_32bit_cp1_register (CP1_STATUS , fcsr );
58+
59+ write_c0_status (sr );
60+
61+ c -> fpu_msk31 = ~(fcsr0 ^ fcsr1 ) & ~mask ;
62+ }
63+
3564/*
3665 * Set the FIR feature flags for the FPU emulator.
3766 */
@@ -50,11 +79,15 @@ static void cpu_set_nofpu_id(struct cpuinfo_mips *c)
5079 c -> fpu_id = value ;
5180}
5281
82+ /* Determined FPU emulator mask to use for the boot CPU with "nofpu". */
83+ static unsigned int mips_nofpu_msk31 ;
84+
5385static int mips_fpu_disabled ;
5486
5587static int __init fpu_disable (char * s )
5688{
5789 boot_cpu_data .options &= ~MIPS_CPU_FPU ;
90+ boot_cpu_data .fpu_msk31 = mips_nofpu_msk31 ;
5891 cpu_set_nofpu_id (& boot_cpu_data );
5992 mips_fpu_disabled = 1 ;
6093
@@ -597,6 +630,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
597630 case PRID_IMP_R2000 :
598631 c -> cputype = CPU_R2000 ;
599632 __cpu_name [cpu ] = "R2000" ;
633+ c -> fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS ;
600634 c -> options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
601635 MIPS_CPU_NOFPUEX ;
602636 if (__cpu_has_fpu ())
@@ -616,6 +650,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
616650 c -> cputype = CPU_R3000 ;
617651 __cpu_name [cpu ] = "R3000" ;
618652 }
653+ c -> fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS ;
619654 c -> options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
620655 MIPS_CPU_NOFPUEX ;
621656 if (__cpu_has_fpu ())
@@ -664,13 +699,15 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
664699 }
665700
666701 set_isa (c , MIPS_CPU_ISA_III );
702+ c -> fpu_msk31 |= FPU_CSR_CONDX ;
667703 c -> options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
668704 MIPS_CPU_WATCH | MIPS_CPU_VCE |
669705 MIPS_CPU_LLSC ;
670706 c -> tlbsize = 48 ;
671707 break ;
672708 case PRID_IMP_VR41XX :
673709 set_isa (c , MIPS_CPU_ISA_III );
710+ c -> fpu_msk31 |= FPU_CSR_CONDX ;
674711 c -> options = R4K_OPTS ;
675712 c -> tlbsize = 32 ;
676713 switch (c -> processor_id & 0xf0 ) {
@@ -712,6 +749,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
712749 c -> cputype = CPU_R4300 ;
713750 __cpu_name [cpu ] = "R4300" ;
714751 set_isa (c , MIPS_CPU_ISA_III );
752+ c -> fpu_msk31 |= FPU_CSR_CONDX ;
715753 c -> options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
716754 MIPS_CPU_LLSC ;
717755 c -> tlbsize = 32 ;
@@ -720,6 +758,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
720758 c -> cputype = CPU_R4600 ;
721759 __cpu_name [cpu ] = "R4600" ;
722760 set_isa (c , MIPS_CPU_ISA_III );
761+ c -> fpu_msk31 |= FPU_CSR_CONDX ;
723762 c -> options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
724763 MIPS_CPU_LLSC ;
725764 c -> tlbsize = 48 ;
@@ -735,11 +774,13 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
735774 c -> cputype = CPU_R4650 ;
736775 __cpu_name [cpu ] = "R4650" ;
737776 set_isa (c , MIPS_CPU_ISA_III );
777+ c -> fpu_msk31 |= FPU_CSR_CONDX ;
738778 c -> options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC ;
739779 c -> tlbsize = 48 ;
740780 break ;
741781 #endif
742782 case PRID_IMP_TX39 :
783+ c -> fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS ;
743784 c -> options = MIPS_CPU_TLB | MIPS_CPU_TX39_CACHE ;
744785
745786 if ((c -> processor_id & 0xf0 ) == (PRID_REV_TX3927 & 0xf0 )) {
@@ -765,6 +806,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
765806 c -> cputype = CPU_R4700 ;
766807 __cpu_name [cpu ] = "R4700" ;
767808 set_isa (c , MIPS_CPU_ISA_III );
809+ c -> fpu_msk31 |= FPU_CSR_CONDX ;
768810 c -> options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
769811 MIPS_CPU_LLSC ;
770812 c -> tlbsize = 48 ;
@@ -773,6 +815,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
773815 c -> cputype = CPU_TX49XX ;
774816 __cpu_name [cpu ] = "R49XX" ;
775817 set_isa (c , MIPS_CPU_ISA_III );
818+ c -> fpu_msk31 |= FPU_CSR_CONDX ;
776819 c -> options = R4K_OPTS | MIPS_CPU_LLSC ;
777820 if (!(c -> processor_id & 0x08 ))
778821 c -> options |= MIPS_CPU_FPU | MIPS_CPU_32FPR ;
@@ -814,6 +857,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
814857 c -> cputype = CPU_R6000 ;
815858 __cpu_name [cpu ] = "R6000" ;
816859 set_isa (c , MIPS_CPU_ISA_II );
860+ c -> fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS ;
817861 c -> options = MIPS_CPU_TLB | MIPS_CPU_FPU |
818862 MIPS_CPU_LLSC ;
819863 c -> tlbsize = 32 ;
@@ -822,6 +866,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
822866 c -> cputype = CPU_R6000A ;
823867 __cpu_name [cpu ] = "R6000A" ;
824868 set_isa (c , MIPS_CPU_ISA_II );
869+ c -> fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS ;
825870 c -> options = MIPS_CPU_TLB | MIPS_CPU_FPU |
826871 MIPS_CPU_LLSC ;
827872 c -> tlbsize = 32 ;
@@ -893,12 +938,14 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
893938 __cpu_name [cpu ] = "ICT Loongson-2" ;
894939 set_elf_platform (cpu , "loongson2e" );
895940 set_isa (c , MIPS_CPU_ISA_III );
941+ c -> fpu_msk31 |= FPU_CSR_CONDX ;
896942 break ;
897943 case PRID_REV_LOONGSON2F :
898944 c -> cputype = CPU_LOONGSON2 ;
899945 __cpu_name [cpu ] = "ICT Loongson-2" ;
900946 set_elf_platform (cpu , "loongson2f" );
901947 set_isa (c , MIPS_CPU_ISA_III );
948+ c -> fpu_msk31 |= FPU_CSR_CONDX ;
902949 break ;
903950 case PRID_REV_LOONGSON3A :
904951 c -> cputype = CPU_LOONGSON3 ;
@@ -1335,6 +1382,9 @@ void cpu_probe(void)
13351382 c -> cputype = CPU_UNKNOWN ;
13361383 c -> writecombine = _CACHE_UNCACHED ;
13371384
1385+ c -> fpu_csr31 = FPU_CSR_RN ;
1386+ c -> fpu_msk31 = FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008 ;
1387+
13381388 c -> processor_id = read_c0_prid ();
13391389 switch (c -> processor_id & PRID_COMP_MASK ) {
13401390 case PRID_COMP_LEGACY :
@@ -1393,6 +1443,7 @@ void cpu_probe(void)
13931443
13941444 if (c -> options & MIPS_CPU_FPU ) {
13951445 c -> fpu_id = cpu_get_fpu_id ();
1446+ mips_nofpu_msk31 = c -> fpu_msk31 ;
13961447
13971448 if (c -> isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
13981449 MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
@@ -1402,6 +1453,8 @@ void cpu_probe(void)
14021453 if (c -> fpu_id & MIPS_FPIR_FREP )
14031454 c -> options |= MIPS_CPU_FRE ;
14041455 }
1456+
1457+ cpu_set_fpu_fcsr_mask (c );
14051458 } else
14061459 cpu_set_nofpu_id (c );
14071460
0 commit comments