From: James S. <jsi...@us...> - 2001-11-19 17:37:07
|
Update of /cvsroot/linux-mips/linux/arch/mips64/kernel In directory usw-pr-cvs1:/tmp/cvs-serv23927 Modified Files: setup.c Log Message: Use same CPU detection code as 32-bit kernel. Index: setup.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips64/kernel/setup.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- setup.c 2001/10/29 17:42:46 1.4 +++ setup.c 2001/11/19 17:37:04 1.5 @@ -124,38 +124,328 @@ check_wait(); } +/* + * Probe whether cpu has config register by trying to play with + * alternate cache bit and see whether it matters. + * It's used by cpu_probe to distinguish between R3000A and R3081. + */ +static inline int cpu_has_confreg(void) +{ +#ifdef CONFIG_CPU_R3000 + extern unsigned long r3k_cache_size(unsigned long); + unsigned long size1, size2; + unsigned long cfg = read_32bit_cp0_register(CP0_CONF); + + size1 = r3k_cache_size(ST0_ISC); + write_32bit_cp0_register(CP0_CONF, cfg^CONF_AC); + size2 = r3k_cache_size(ST0_ISC); + write_32bit_cp0_register(CP0_CONF, cfg); + return size1 != size2; +#else + return 0; +#endif +} + +/* declaration of the global struct */ +struct mips_cpu mips_cpu = {PRID_IMP_UNKNOWN, CPU_UNKNOWN, 0, 0, 0, + {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}}; + +#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4KTLB \ + | MIPS_CPU_COUNTER | MIPS_CPU_CACHE_CDEX) + static inline void cpu_probe(void) { - unsigned int prid = read_32bit_cp0_register(CP0_PRID); +#ifdef CONFIG_CPU_MIPS32 + unsigned long config1; +#endif - switch(prid & 0xff00) { - case PRID_IMP_R4000: - if((prid & 0xff) == PRID_REV_R4400) - mips_cputype = CPU_R4400SC; - else - mips_cputype = CPU_R4000SC; - break; - case PRID_IMP_R4600: - mips_cputype = CPU_R4600; - break; - case PRID_IMP_R4700: - mips_cputype = CPU_R4700; - break; - case PRID_IMP_R5000: - mips_cputype = CPU_R5000; + mips_cpu.processor_id = read_32bit_cp0_register(CP0_PRID); + switch (mips_cpu.processor_id & 0xff0000) { + case PRID_COMP_LEGACY: + switch (mips_cpu.processor_id & 0xff00) { + case PRID_IMP_R2000: + mips_cpu.cputype = CPU_R2000; + mips_cpu.isa_level = MIPS_CPU_ISA_I; + mips_cpu.options = MIPS_CPU_TLB; + mips_cpu.tlbsize = 64; + break; + case PRID_IMP_R3000: + if ((mips_cpu.processor_id & 0xff) == PRID_REV_R3000A) + if (cpu_has_confreg()) + mips_cpu.cputype = CPU_R3081E; + else + mips_cpu.cputype = CPU_R3000A; + else + mips_cpu.cputype = CPU_R3000; + mips_cpu.isa_level = MIPS_CPU_ISA_I; + mips_cpu.options = MIPS_CPU_TLB; + mips_cpu.tlbsize = 64; + break; + case PRID_IMP_R4000: + if ((mips_cpu.processor_id & 0xff) == PRID_REV_R4400) + mips_cpu.cputype = CPU_R4400SC; + else + mips_cpu.cputype = CPU_R4000SC; + mips_cpu.isa_level = MIPS_CPU_ISA_III; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | + MIPS_CPU_32FPR | MIPS_CPU_WATCH | + MIPS_CPU_VCE; + mips_cpu.tlbsize = 48; + break; + case PRID_IMP_VR41XX: + mips_cpu.cputype = CPU_VR41XX; + mips_cpu.isa_level = MIPS_CPU_ISA_III; + mips_cpu.options = R4K_OPTS; + mips_cpu.tlbsize = 32; + break; + case PRID_IMP_R4300: + mips_cpu.cputype = CPU_R4300; + mips_cpu.isa_level = MIPS_CPU_ISA_III; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR; + mips_cpu.tlbsize = 32; + break; + case PRID_IMP_R4600: + mips_cpu.cputype = CPU_R4600; + mips_cpu.isa_level = MIPS_CPU_ISA_III; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU; + mips_cpu.tlbsize = 48; + break; + #if 0 + case PRID_IMP_R4650: + /* + * This processor doesn't have an MMU, so it's not + * "real easy" to run Linux on it. It is left purely + * for documentation. Commented out because it shares + * it's c0_prid id number with the TX3900. + */ + mips_cpu.cputype = CPU_R4650; + mips_cpu.isa_level = MIPS_CPU_ISA_III; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU; + mips_cpu.tlbsize = 48; + break; + #endif + case PRID_IMP_TX39: + mips_cpu.isa_level = MIPS_CPU_ISA_I; + mips_cpu.options = MIPS_CPU_TLB; + + switch (mips_cpu.processor_id & 0xff) { + case PRID_REV_TX3912: + mips_cpu.cputype = CPU_TX3912; + mips_cpu.tlbsize = 32; + break; + case PRID_REV_TX3922: + mips_cpu.cputype = CPU_TX3922; + mips_cpu.tlbsize = 64; + break; + case PRID_REV_TX3927: + case PRID_REV_TX3927B: + /* check core-mode */ + if ((*(volatile u32 *)0xfffee004 >> 16) == 0x3927) + mips_cpu.cputype = CPU_TX3927; + else + mips_cpu.cputype = CPU_TX39XX; + mips_cpu.tlbsize = 64; + mips_cpu.icache.ways = 2; + mips_cpu.dcache.ways = 2; + break; + case PRID_REV_TX39H3TEG: + /* support core-mode only */ + mips_cpu.cputype = CPU_TX39XX; + mips_cpu.tlbsize = 32; + mips_cpu.icache.ways = 2; + mips_cpu.dcache.ways = 2; + break; + default: + mips_cpu.cputype = CPU_UNKNOWN; + break; + } + break; + case PRID_IMP_R4700: + mips_cpu.cputype = CPU_R4700; + mips_cpu.isa_level = MIPS_CPU_ISA_III; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | + MIPS_CPU_32FPR; + mips_cpu.tlbsize = 48; + break; + case PRID_IMP_TX49: + mips_cpu.cputype = CPU_TX49XX; + mips_cpu.isa_level = MIPS_CPU_ISA_III; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | + MIPS_CPU_32FPR; + mips_cpu.tlbsize = 48; + mips_cpu.icache.ways = 4; + mips_cpu.dcache.ways = 4; + break; + case PRID_IMP_R5000: + mips_cpu.cputype = CPU_R5000; + mips_cpu.isa_level = MIPS_CPU_ISA_IV; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | + MIPS_CPU_32FPR; + mips_cpu.tlbsize = 48; + break; + case PRID_IMP_R5432: + mips_cpu.cputype = CPU_R5432; + mips_cpu.isa_level = MIPS_CPU_ISA_IV; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | + MIPS_CPU_32FPR; + mips_cpu.tlbsize = 48; + break; + case PRID_IMP_R5500: + mips_cpu.cputype = CPU_R5500; + mips_cpu.isa_level = MIPS_CPU_ISA_IV; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | + MIPS_CPU_32FPR; + mips_cpu.tlbsize = 48; + break; + case PRID_IMP_NEVADA: + mips_cpu.cputype = CPU_NEVADA; + mips_cpu.isa_level = MIPS_CPU_ISA_IV; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | + MIPS_CPU_32FPR | MIPS_CPU_DIVEC; + mips_cpu.tlbsize = 48; + mips_cpu.icache.ways = 2; + mips_cpu.dcache.ways = 2; + break; + case PRID_IMP_R6000: + mips_cpu.cputype = CPU_R6000; + mips_cpu.isa_level = MIPS_CPU_ISA_II; + mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU; + mips_cpu.tlbsize = 32; + break; + case PRID_IMP_R6000A: + mips_cpu.cputype = CPU_R6000A; + mips_cpu.isa_level = MIPS_CPU_ISA_II; + mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU; + mips_cpu.tlbsize = 32; + break; + case PRID_IMP_RM7000: + mips_cpu.cputype = CPU_RM7000; + mips_cpu.isa_level = MIPS_CPU_ISA_IV; + mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | + MIPS_CPU_32FPR; + /* + * Undocumented RM7000: Bit 29 in the info register of + * the RM7000 v2.0 indicates if the TLB has 48 or 64 + * entries. + * + * 29 1 => 64 entry JTLB + * 0 => 48 entry JTLB + */ + mips_cpu.tlbsize = (get_info() & (1 << 29)) ? 64 : 48; + break; + case PRID_IMP_R8000: + mips_cpu.cputype = CPU_R8000; + mips_cpu.isa_level = MIPS_CPU_ISA_IV; + mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_FPU | MIPS_CPU_32FPR; + mips_cpu.tlbsize = 384; /* has wierd TLB: 3-way x 128 */ + break; + case PRID_IMP_R10000: + mips_cpu.cputype = CPU_R10000; + mips_cpu.isa_level = MIPS_CPU_ISA_IV; + mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_COUNTER | MIPS_CPU_WATCH; + mips_cpu.tlbsize = 64; + break; + default: + mips_cpu.cputype = CPU_UNKNOWN; + break; + } break; - case PRID_IMP_NEVADA: - mips_cputype = CPU_NEVADA; +#ifdef CONFIG_CPU_MIPS32 + case PRID_COMP_MIPS: + switch (mips_cpu.processor_id & 0xff00) { + case PRID_IMP_4KC: + mips_cpu.cputype = CPU_4KC; + goto cpu_4kc; + case PRID_IMP_4KEC: + mips_cpu.cputype = CPU_4KEC; + goto cpu_4kc; + case PRID_IMP_4KSC: + mips_cpu.cputype = CPU_4KSC; +cpu_4kc: + /* + * Why do we set all these options by default, THEN + * query them?? + */ + mips_cpu.isa_level = MIPS_CPU_ISA_M32; + mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | + MIPS_CPU_DIVEC | MIPS_CPU_WATCH; + config1 = read_mips32_cp0_config1(); + if (config1 & (1 << 3)) + mips_cpu.options |= MIPS_CPU_WATCH; + if (config1 & (1 << 2)) + mips_cpu.options |= MIPS_CPU_MIPS16; + if (config1 & 1) + mips_cpu.options |= MIPS_CPU_FPU; + mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT; + break; + case PRID_IMP_5KC: + mips_cpu.cputype = CPU_5KC; + mips_cpu.isa_level = MIPS_CPU_ISA_M64; + /* See comment above about querying options */ + mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | + MIPS_CPU_DIVEC | MIPS_CPU_WATCH; + config1 = read_mips32_cp0_config1(); + if (config1 & (1 << 3)) + mips_cpu.options |= MIPS_CPU_WATCH; + if (config1 & (1 << 2)) + mips_cpu.options |= MIPS_CPU_MIPS16; + if (config1 & 1) + mips_cpu.options |= MIPS_CPU_FPU; + break; + mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT; + default: + mips_cpu.cputype = CPU_UNKNOWN; + break; + } break; - case PRID_IMP_R8000: - mips_cputype = CPU_R8000; + case PRID_COMP_ALCHEMY: + switch (mips_cpu.processor_id & 0xff00) { + case PRID_IMP_AU1_REV1: + case PRID_IMP_AU1_REV2: + mips_cpu.cputype = CPU_AU1000; + mips_cpu.isa_level = MIPS_CPU_ISA_M32; + mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | + MIPS_CPU_DIVEC | MIPS_CPU_WATCH; + config1 = read_mips32_cp0_config1(); + if (config1 & (1 << 3)) + mips_cpu.options |= MIPS_CPU_WATCH; + if (config1 & (1 << 2)) + mips_cpu.options |= MIPS_CPU_MIPS16; + if (config1 & 1) + mips_cpu.options |= MIPS_CPU_FPU; + mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT; + break; + default: + mips_cpu.cputype = CPU_UNKNOWN; + break; + } break; - case PRID_IMP_R10000: - case PRID_IMP_R12000: - mips_cputype = CPU_R10000; +#endif /* CONFIG_CPU_MIPS32 */ + case PRID_COMP_SIBYTE: + switch (mips_cpu.processor_id & 0xff00) { + case PRID_IMP_SB1: + mips_cpu.cputype = CPU_SB1; + mips_cpu.isa_level = MIPS_CPU_ISA_M64; + mips_cpu.options = (MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_COUNTER | MIPS_CPU_DIVEC); +#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS + /* FPU in pass1 is known to have issues. */ + mips_cpu.options |= MIPS_CPU_FPU; +#endif + break; + default: + mips_cpu.cputype = CPU_UNKNOWN; + break; + } break; default: - mips_cputype = CPU_UNKNOWN; + mips_cpu.cputype = CPU_UNKNOWN; } } |