^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Processor capabilities determination functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) xxxx the Anonymous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 1994 - 2006 Ralf Baechle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2003, 2004 Maciej W. Rozycki
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2001, 2004, 2011, 2012 MIPS Technologies, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/stddef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/bugs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/cpu-features.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/cpu-type.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/fpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/mipsregs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/elf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "fpu-probe.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /* Hardware capabilities */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned int elf_hwcap __read_mostly;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) EXPORT_SYMBOL_GPL(elf_hwcap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) void __init check_bugs32(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * Probe whether cpu has config register by trying to play with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * alternate cache bit and see whether it matters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * It's used by cpu_probe to distinguish between R3000A and R3081.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static inline int cpu_has_confreg(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #ifdef CONFIG_CPU_R3000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) extern unsigned long r3k_cache_size(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) unsigned long size1, size2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) unsigned long cfg = read_c0_conf();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) size1 = r3k_cache_size(ST0_ISC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) write_c0_conf(cfg ^ R30XX_CONF_AC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) size2 = r3k_cache_size(ST0_ISC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) write_c0_conf(cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return size1 != size2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static inline void set_elf_platform(int cpu, const char *plat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (cpu == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) __elf_platform = plat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) const char *__cpu_name[NR_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) const char *__elf_platform;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) const char *__elf_base_platform;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) void cpu_probe(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct cpuinfo_mips *c = ¤t_cpu_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) unsigned int cpu = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * Set a default elf platform, cpu probe may later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * overwrite it with a more precise value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) set_elf_platform(cpu, "mips");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) c->processor_id = PRID_IMP_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) c->fpu_id = FPIR_IMP_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) c->cputype = CPU_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) c->writecombine = _CACHE_UNCACHED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) c->fpu_csr31 = FPU_CSR_RN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) c->fpu_msk31 = FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) FPU_CSR_CONDX | FPU_CSR_FS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) c->srsets = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) c->processor_id = read_c0_prid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) switch (c->processor_id & (PRID_COMP_MASK | PRID_IMP_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) case PRID_COMP_LEGACY | PRID_IMP_R2000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) c->cputype = CPU_R2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) __cpu_name[cpu] = "R2000";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) MIPS_CPU_NOFPUEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (__cpu_has_fpu())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) c->options |= MIPS_CPU_FPU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) c->tlbsize = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) case PRID_COMP_LEGACY | PRID_IMP_R3000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if ((c->processor_id & PRID_REV_MASK) == PRID_REV_R3000A) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (cpu_has_confreg()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) c->cputype = CPU_R3081E;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) __cpu_name[cpu] = "R3081";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) c->cputype = CPU_R3000A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) __cpu_name[cpu] = "R3000A";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) c->cputype = CPU_R3000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) __cpu_name[cpu] = "R3000";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) MIPS_CPU_NOFPUEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (__cpu_has_fpu())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) c->options |= MIPS_CPU_FPU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) c->tlbsize = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) case PRID_COMP_LEGACY | PRID_IMP_TX39:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) c->options = MIPS_CPU_TLB | MIPS_CPU_TX39_CACHE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if ((c->processor_id & 0xf0) == (PRID_REV_TX3927 & 0xf0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) c->cputype = CPU_TX3927;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) __cpu_name[cpu] = "TX3927";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) c->tlbsize = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) switch (c->processor_id & PRID_REV_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) case PRID_REV_TX3912:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) c->cputype = CPU_TX3912;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) __cpu_name[cpu] = "TX3912";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) c->tlbsize = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) case PRID_REV_TX3922:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) c->cputype = CPU_TX3922;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) __cpu_name[cpu] = "TX3922";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) c->tlbsize = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) BUG_ON(!__cpu_name[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) BUG_ON(c->cputype == CPU_UNKNOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * Platform code can force the cpu type to optimize code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * generation. In that case be sure the cpu type is correctly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * manually setup otherwise it could trigger some nasty bugs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) BUG_ON(current_cpu_type() != c->cputype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (mips_fpu_disabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) c->options &= ~MIPS_CPU_FPU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (c->options & MIPS_CPU_FPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) cpu_set_fpu_opts(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) cpu_set_nofpu_opts(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) void cpu_report(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct cpuinfo_mips *c = ¤t_cpu_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) pr_info("CPU%d revision is: %08x (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) smp_processor_id(), c->processor_id, cpu_name_string());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (c->options & MIPS_CPU_FPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) pr_info("FPU revision is: %08x\n", c->fpu_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }