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