Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/mips/kernel/cpu-r3k-probe.c
26424 views
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 */
29
unsigned int elf_hwcap __read_mostly;
30
EXPORT_SYMBOL_GPL(elf_hwcap);
31
32
void __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
*/
42
static inline int cpu_has_confreg(void)
43
{
44
#ifdef CONFIG_CPU_R3000
45
unsigned long size1, size2;
46
unsigned long cfg = read_c0_conf();
47
48
size1 = r3k_cache_size(ST0_ISC);
49
write_c0_conf(cfg ^ R30XX_CONF_AC);
50
size2 = r3k_cache_size(ST0_ISC);
51
write_c0_conf(cfg);
52
return size1 != size2;
53
#else
54
return 0;
55
#endif
56
}
57
58
static inline void set_elf_platform(int cpu, const char *plat)
59
{
60
if (cpu == 0)
61
__elf_platform = plat;
62
}
63
64
const char *__cpu_name[NR_CPUS];
65
const char *__elf_platform;
66
const char *__elf_base_platform;
67
68
void cpu_probe(void)
69
{
70
struct cpuinfo_mips *c = &current_cpu_data;
71
unsigned int cpu = smp_processor_id();
72
73
/*
74
* Set a default elf platform, cpu probe may later
75
* overwrite it with a more precise value
76
*/
77
set_elf_platform(cpu, "mips");
78
79
c->processor_id = PRID_IMP_UNKNOWN;
80
c->fpu_id = FPIR_IMP_NONE;
81
c->cputype = CPU_UNKNOWN;
82
c->writecombine = _CACHE_UNCACHED;
83
84
c->fpu_csr31 = FPU_CSR_RN;
85
c->fpu_msk31 = FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008 |
86
FPU_CSR_CONDX | FPU_CSR_FS;
87
88
c->srsets = 1;
89
90
c->processor_id = read_c0_prid();
91
switch (c->processor_id & (PRID_COMP_MASK | PRID_IMP_MASK)) {
92
case PRID_COMP_LEGACY | PRID_IMP_R2000:
93
c->cputype = CPU_R2000;
94
__cpu_name[cpu] = "R2000";
95
c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
96
MIPS_CPU_NOFPUEX;
97
if (__cpu_has_fpu())
98
c->options |= MIPS_CPU_FPU;
99
c->tlbsize = 64;
100
break;
101
case PRID_COMP_LEGACY | PRID_IMP_R3000:
102
if ((c->processor_id & PRID_REV_MASK) == PRID_REV_R3000A) {
103
if (cpu_has_confreg()) {
104
c->cputype = CPU_R3081E;
105
__cpu_name[cpu] = "R3081";
106
} else {
107
c->cputype = CPU_R3000A;
108
__cpu_name[cpu] = "R3000A";
109
}
110
} else {
111
c->cputype = CPU_R3000;
112
__cpu_name[cpu] = "R3000";
113
}
114
c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
115
MIPS_CPU_NOFPUEX;
116
if (__cpu_has_fpu())
117
c->options |= MIPS_CPU_FPU;
118
c->tlbsize = 64;
119
break;
120
}
121
122
BUG_ON(!__cpu_name[cpu]);
123
BUG_ON(c->cputype == CPU_UNKNOWN);
124
125
/*
126
* Platform code can force the cpu type to optimize code
127
* generation. In that case be sure the cpu type is correctly
128
* manually setup otherwise it could trigger some nasty bugs.
129
*/
130
BUG_ON(current_cpu_type() != c->cputype);
131
132
if (mips_fpu_disabled)
133
c->options &= ~MIPS_CPU_FPU;
134
135
if (c->options & MIPS_CPU_FPU)
136
cpu_set_fpu_opts(c);
137
else
138
cpu_set_nofpu_opts(c);
139
140
reserve_exception_space(0, 0x400);
141
}
142
143
void cpu_report(void)
144
{
145
struct cpuinfo_mips *c = &current_cpu_data;
146
147
pr_info("CPU%d revision is: %08x (%s)\n",
148
smp_processor_id(), c->processor_id, cpu_name_string());
149
if (c->options & MIPS_CPU_FPU)
150
pr_info("FPU revision is: %08x\n", c->fpu_id);
151
}
152
153