Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Processor capabilities determination functions.
0004  *
0005  * Copyright (C) xxxx  the Anonymous
0006  * Copyright (C) 1994 - 2006 Ralf Baechle
0007  * Copyright (C) 2003, 2004  Maciej W. Rozycki
0008  * Copyright (C) 2001, 2004, 2011, 2012  MIPS Technologies, Inc.
0009  */
0010 #include <linux/init.h>
0011 #include <linux/kernel.h>
0012 #include <linux/ptrace.h>
0013 #include <linux/smp.h>
0014 #include <linux/stddef.h>
0015 #include <linux/export.h>
0016 
0017 #include <asm/bugs.h>
0018 #include <asm/cpu.h>
0019 #include <asm/cpu-features.h>
0020 #include <asm/cpu-type.h>
0021 #include <asm/fpu.h>
0022 #include <asm/mipsregs.h>
0023 #include <asm/elf.h>
0024 #include <asm/traps.h>
0025 
0026 #include "fpu-probe.h"
0027 
0028 /* Hardware capabilities */
0029 unsigned int elf_hwcap __read_mostly;
0030 EXPORT_SYMBOL_GPL(elf_hwcap);
0031 
0032 void __init check_bugs32(void)
0033 {
0034 
0035 }
0036 
0037 /*
0038  * Probe whether cpu has config register by trying to play with
0039  * alternate cache bit and see whether it matters.
0040  * It's used by cpu_probe to distinguish between R3000A and R3081.
0041  */
0042 static inline int cpu_has_confreg(void)
0043 {
0044 #ifdef CONFIG_CPU_R3000
0045     extern unsigned long r3k_cache_size(unsigned long);
0046     unsigned long size1, size2;
0047     unsigned long cfg = read_c0_conf();
0048 
0049     size1 = r3k_cache_size(ST0_ISC);
0050     write_c0_conf(cfg ^ R30XX_CONF_AC);
0051     size2 = r3k_cache_size(ST0_ISC);
0052     write_c0_conf(cfg);
0053     return size1 != size2;
0054 #else
0055     return 0;
0056 #endif
0057 }
0058 
0059 static inline void set_elf_platform(int cpu, const char *plat)
0060 {
0061     if (cpu == 0)
0062         __elf_platform = plat;
0063 }
0064 
0065 const char *__cpu_name[NR_CPUS];
0066 const char *__elf_platform;
0067 const char *__elf_base_platform;
0068 
0069 void cpu_probe(void)
0070 {
0071     struct cpuinfo_mips *c = &current_cpu_data;
0072     unsigned int cpu = smp_processor_id();
0073 
0074     /*
0075      * Set a default elf platform, cpu probe may later
0076      * overwrite it with a more precise value
0077      */
0078     set_elf_platform(cpu, "mips");
0079 
0080     c->processor_id = PRID_IMP_UNKNOWN;
0081     c->fpu_id   = FPIR_IMP_NONE;
0082     c->cputype  = CPU_UNKNOWN;
0083     c->writecombine = _CACHE_UNCACHED;
0084 
0085     c->fpu_csr31    = FPU_CSR_RN;
0086     c->fpu_msk31    = FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008 |
0087               FPU_CSR_CONDX | FPU_CSR_FS;
0088 
0089     c->srsets = 1;
0090 
0091     c->processor_id = read_c0_prid();
0092     switch (c->processor_id & (PRID_COMP_MASK | PRID_IMP_MASK)) {
0093     case PRID_COMP_LEGACY | PRID_IMP_R2000:
0094         c->cputype = CPU_R2000;
0095         __cpu_name[cpu] = "R2000";
0096         c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
0097                  MIPS_CPU_NOFPUEX;
0098         if (__cpu_has_fpu())
0099             c->options |= MIPS_CPU_FPU;
0100         c->tlbsize = 64;
0101         break;
0102     case PRID_COMP_LEGACY | PRID_IMP_R3000:
0103         if ((c->processor_id & PRID_REV_MASK) == PRID_REV_R3000A) {
0104             if (cpu_has_confreg()) {
0105                 c->cputype = CPU_R3081E;
0106                 __cpu_name[cpu] = "R3081";
0107             } else {
0108                 c->cputype = CPU_R3000A;
0109                 __cpu_name[cpu] = "R3000A";
0110             }
0111         } else {
0112             c->cputype = CPU_R3000;
0113             __cpu_name[cpu] = "R3000";
0114         }
0115         c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
0116                  MIPS_CPU_NOFPUEX;
0117         if (__cpu_has_fpu())
0118             c->options |= MIPS_CPU_FPU;
0119         c->tlbsize = 64;
0120         break;
0121     }
0122 
0123     BUG_ON(!__cpu_name[cpu]);
0124     BUG_ON(c->cputype == CPU_UNKNOWN);
0125 
0126     /*
0127      * Platform code can force the cpu type to optimize code
0128      * generation. In that case be sure the cpu type is correctly
0129      * manually setup otherwise it could trigger some nasty bugs.
0130      */
0131     BUG_ON(current_cpu_type() != c->cputype);
0132 
0133     if (mips_fpu_disabled)
0134         c->options &= ~MIPS_CPU_FPU;
0135 
0136     if (c->options & MIPS_CPU_FPU)
0137         cpu_set_fpu_opts(c);
0138     else
0139         cpu_set_nofpu_opts(c);
0140 
0141     reserve_exception_space(0, 0x400);
0142 }
0143 
0144 void cpu_report(void)
0145 {
0146     struct cpuinfo_mips *c = &current_cpu_data;
0147 
0148     pr_info("CPU%d revision is: %08x (%s)\n",
0149         smp_processor_id(), c->processor_id, cpu_name_string());
0150     if (c->options & MIPS_CPU_FPU)
0151         pr_info("FPU revision is: %08x\n", c->fpu_id);
0152 }